diff --git a/.appveyor.yml b/.appveyor.yml index 28b9106d..cfc759b5 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -19,6 +19,7 @@ build: verbosity: minimal skip_branch_with_pr: true image: Visual Studio 2019 +clone_script: echo Skip AppVeyor Clone environment: global: @@ -32,7 +33,7 @@ environment: PYTHON_DEF: "C:\\Python38-x64" PYTHON_VERSION: "3.8" # Python versions to build wheels for - PYTHONVERS: C:\Python36-x64 C:\Python37-x64 C:\Python38-x64 C:\Python39-x64 C:\Python310-x64 C:\Python311-x64 + PYTHONVERS: C:\Python38-x64 C:\Python39-x64 C:\Python310-x64 C:\Python311-x64 C:\Python312-x64 C:\Python313-x64 PYTHON_ARCH: "64" install: @@ -45,7 +46,18 @@ install: https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | ` Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { ` throw "There are newer queued builds for this pull request, failing early." } - - set OPENSSL_DIR="C:\OpenSSL-v11-Win%PYTHON_ARCH%" + + # Git checkout + - git config --global filter.lfs.smudge "git-lfs smudge --skip -- %f" + - git config --global filter.lfs.process "git-lfs filter-process --skip" + - git init %APPVEYOR_BUILD_FOLDER% + - cd %APPVEYOR_BUILD_FOLDER% + - git remote add origin https://github.com/%APPVEYOR_REPO_NAME%.git + - git fetch -q origin %APPVEYOR_REPO_COMMIT% + - git fetch --tags + - git checkout -qf %APPVEYOR_REPO_COMMIT% + + - set OPENSSL_DIR="C:\OpenSSL-v34-Win64" - set VCLIBDIR=%WINDIR%\System32 - cp %VCLIBDIR%/vcruntime140.dll ssh/ - cp %VCLIBDIR%/msvcr120.dll ssh/ @@ -60,15 +72,13 @@ 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 - # - 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 build_script: + - for %%I in (%PYTHONVERS%) do cp %OPENSSL_DIR%/lib/VC/x64/MD/libcrypto.lib %%I/libs/libcrypto64MD.lib + - for %%I in (%PYTHONVERS%) do cp %OPENSSL_DIR%/lib/VC/x64/MD/libssl.lib %%I/libs/libssl64MD.lib - ci\\appveyor\\build_zlib.bat - for %%I in (%PYTHONVERS%) do cp C:/zlib/lib/zlibstatic.lib %%I/libs/ - for %%I in (%PYTHONVERS%) do ls %%I/libs/ diff --git a/.circleci/config.yml b/.circleci/config.yml index 515f5dbb..9f937255 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -15,46 +15,59 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA version: 2.1 -orbs: - python: circleci/python@2.1.1 jobs: python_test: parameters: python_ver: type: string - default: "3.9" + default: "3.10" docker: - image: cimg/python:<< parameters.python_ver >> steps: - checkout - - python/install-packages: - pip-dependency-file: requirements_dev.txt - pkg-manager: pip - run: name: Deps command: | sudo apt-get update sudo apt-get install cmake openssh-server + pip install -r requirements_dev.txt - run: command: | + pip uninstall -y cython pip install -e . + python -c 'from ssh.session import Session; Session()' eval "$(ssh-agent -s)" name: Build - run: command: | set -x - ls -lhtr ssh/ - pwd - ldd -r ssh/session*.so pytest tests + name: Test + - run: + command: | + pytest ci/integration_tests + name: Integration + max_auto_reruns: 3 + auto_rerun_delay: 10s + - run: + command: | flake8 ssh + name: Flake + - run: + command: | python setup.py sdist - cd dist; pip install *; cd .. + cd dist + pip install * + python -c 'from ssh.session import Session; Session()' + cd .. + name: Sdist Install + - run: + command: | cd doc make html cd .. - name: Test + name: Docs osx: parameters: @@ -70,7 +83,9 @@ 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 which twine - run: @@ -82,37 +97,28 @@ 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: - image: ubuntu-2004:202201-02 + image: ubuntu-2004:current steps: &manylinux-steps - checkout - - run: - name: sdist - command: python setup.py sdist - - python/install-packages: - pip-dependency-file: requirements_dev.txt - pkg-manager: pip - - 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: | sudo apt-get install python3-pip - pip install -U pip + pip install -U pip setuptools pip install twine which twine which python3 - run: name: Build Wheels command: | + export LIBSSH=0.11.1 + export KRB=1.21.3 if [[ -z "${CIRCLE_PR_NUMBER}" ]]; then echo "$DOCKER_PASSWORD" | docker login -u="$DOCKER_USERNAME" --password-stdin; fi @@ -125,11 +131,13 @@ 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: - image: ubuntu-2004:202101-01 + image: ubuntu-2004:current resource_class: arm.medium steps: *manylinux-steps @@ -141,10 +149,10 @@ workflows: matrix: parameters: python_ver: - - "3.6" - "3.8" - - "3.9" - "3.11" + - "3.12" + - "3.13" filters: tags: ignore: /.*/ @@ -161,7 +169,8 @@ workflows: parameters: xcode_ver: - "14.0.0" - - "13.1.0" + - "15.0.0" + - "16.0.0" context: Docker filters: tags: diff --git a/.gitattributes b/.gitattributes index 7b7df679..80254c24 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,2 @@ -*.tar.gz filter=lfs diff=lfs merge=lfs -text -*.rpm filter=lfs diff=lfs merge=lfs -text -*.zip filter=lfs diff=lfs merge=lfs -text -*.xz filter=lfs diff=lfs merge=lfs -text +ci/appveyor/zlib1211.zip export-subst +ssh/_version.py export-subst diff --git a/.gitignore b/.gitignore index 42fda467..ba168aeb 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,7 @@ libssh/compile_commands.json /wheelhouse /.idea -/tests/unit_test_cert_key-cert.pub +/ci/integration_tests/unit_test_cert_key-cert.pub /doc/_build +ci/docker/manylinux/*.tar.gz +ci/appveyor/zlib-1.2.11.zip diff --git a/.readthedocs.yml b/.readthedocs.yml index e5226632..1b49f428 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -1,9 +1,15 @@ version: 2 build: + os: ubuntu-24.04 + tools: + python: "3" apt_packages: - cmake - openssl +sphinx: + configuration: doc/conf.py python: install: + - requirements: doc/requirements.txt - method: pip path: . diff --git a/Changelog.rst b/Changelog.rst index 69cb0acd..d05874f1 100644 --- a/Changelog.rst +++ b/Changelog.rst @@ -1,6 +1,69 @@ Change Log ============= +1.2.0 +++++++ + +Changes +-------- + +* Added private key file formats to `ssh.key` and `ssh.key.Key.export_privkey_file_format` for exporting private key + file with specified format - #96 +* Added `ssh.channel.Channel.get_exit_status` implementation and tests. +* Added key exchange types under `ssh.session`. +* Added `ssh.session.Session.options_set_int_val` for setting an integer value `libssh` option - for example + compression level. + + +Packaging +---------- + +* OSX wheel builds now use embedded `libssh` rather than brew package. +* Dropped Windows Python 3.7 builds. +* Added Python 3.14 manylinux wheels. + + +1.1.1 ++++++ + +Changes +-------- + +No code changes. + + +Packaging +---------- + +* Added Windows Python 3.7 and 3.13 wheel builds. +* Removed manylinux 2010 wheels. +* Wheel builds now use embedded libssh. +* Source distribution now uses embedded libssh. +* Added embedded krb5 for wheel builds. +* Dockerfiles and scripts updates. + + +1.1.0 ++++++ + +Changes +-------- + +* Updated embedded and manylinux libssh to `0.11.1`. +* Support for Python >=3.12. +* Upgraded wheel OpenSSL to 3.4.0. +* Removed testing for Python versions <3.8. + +Packaging +---------- + +* Added binary wheels for Python versions 3.11, 3.12 and 3.13 on support manylinux wheel builds. +* Added OSX 12.0, 13.0 and 14.0 wheels, Apple Silicon. +* Support OSX brew OpenSSL from source builds. +* Top level tests directory is now cross platform and can be run by vendors. +* Moved CI specific integration tests to their own space. + + 1.0.0 ++++++ diff --git a/MANIFEST.in b/MANIFEST.in index 6ff18aa4..3309e662 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,5 @@ recursive-exclude docker * +recursive-exclude ci * include versioneer.py include ssh/_version.py exclude .travis.yml diff --git a/README.rst b/README.rst index ee70a65c..271c0809 100644 --- a/README.rst +++ b/README.rst @@ -25,7 +25,7 @@ Bindings for libssh_ C library. Installation _____________ -Binary wheels are provided for Linux (manylinux 2010), OSX (10.14 and 10.15 for brew Python), and Windows 64-bit (Python 3.6/3.7/3.8). +Binary wheels are provided for Linux (manylinux 2014, x86_64 and aarch64), OSX (12, 13 and 14 for brew Python), and Windows 64-bit (Python 3.8+). Wheels have *no dependencies*. @@ -52,12 +52,12 @@ See `command execution script 0: + all_data += data + try: + size, data = chan.read() + except SSHError: + break + lines = [s.decode('utf-8') for s in all_data.splitlines()] + self.assertEqual(lines[0], self.resp) + sleep(1) + self.assertTrue(chan.is_eof()) + self.assertEqual(chan.close(), 0) + self.assertFalse(chan.is_open()) + self.assertTrue(chan.is_closed()) + + def test_channel_non_blocking_exec(self): + self._auth() + self.session.set_blocking(0) + chan = self.session.channel_new() + while chan == SSH_AGAIN: + wait_socket(self.session, self.sock) + chan = self.session.channel_new() + chan.set_blocking(0) + rc = chan.open_session() + while rc == SSH_AGAIN: + wait_socket(self.session, self.sock) + rc = chan.open_session() + self.assertEqual(rc, 0) + self.assertTrue(chan.is_open()) + self.assertFalse(chan.is_closed()) + rc = chan.request_exec(self.cmd) + while rc == SSH_AGAIN: + wait_socket(self.session, self.sock) + rc = chan.request_exec(self.cmd) + self.assertEqual(rc, 0) + self.assertFalse(chan.is_eof()) + self.assertFalse(chan.is_closed()) + all_data = b"" + while True: + try: + if chan.poll(): + wait_socket(self.session, self.sock) + size, data = chan.read_nonblocking() + if size > 0: + all_data += data + except EOF: + break + lines = [s.decode('utf-8') for s in all_data.splitlines()] + self.assertEqual(lines[0], self.resp) + self.assertRaises(EOF, chan.poll) + self.assertTrue(chan.is_eof()) + rc = chan.close() + while rc == SSH_AGAIN: + wait_socket(self.session, self.sock) + rc = chan.close() + self.assertEqual(rc, 0) + self.assertFalse(chan.is_open()) + self.assertTrue(chan.is_closed()) + + def test_exit_code(self): + self._auth() + chan = self.session.channel_new() + self.assertEqual(chan.open_session(), 0) + self.assertEqual(chan.request_exec('exit 2'), 0) + self.assertEqual(chan.send_eof(), 0) + self.assertEqual(chan.close(), 0) + status = chan.get_exit_status() + self.assertEqual(status, 2) + + def test_exit_state(self): + self._auth() + chan = self.session.channel_new() + self.assertEqual(chan.open_session(), 0) + self.assertEqual(chan.request_exec('exit 2'), 0) + self.assertEqual(chan.send_eof(), 0) + self.assertEqual(chan.close(), 0) + exit_code, signal, pcore_dumped = chan.get_exit_state() + self.assertEqual(exit_code, 2) + + def test_exit_state_w_signal(self): + self._auth() + chan = self.session.channel_new() + my_sig = 'TERM' + chan.open_session() + chan.request_exec('sleep 5 && exit 0') + chan.send_eof() + chan.request_send_signal(my_sig) + chan.close() + exit_code, signal, pcore_dumped = chan.get_exit_state() + self.assertNotEqual(exit_code, 0) + self.assertEqual(signal, bytes(my_sig, 'utf-8')) + + def test_exit_state_w_signal_non_blocking(self): + self._auth() + chan = self.session.channel_new() + my_sig = 'TERM' + chan.open_session() + chan.request_exec('sleep 5 && exit 0') + chan.send_eof() + chan.request_send_signal(my_sig) + chan.close() + self.session.set_blocking(0) + exit_code, signal, pcore_dumped = chan.get_exit_state() + while exit_code == SSH_AGAIN: + self.assertEqual(signal, b"") + self.assertFalse(pcore_dumped) + wait_socket(self.session, self.sock) + exit_code, signal, pcore_dumped = chan.get_exit_state() + self.assertNotEqual(exit_code, 0) + self.assertEqual(signal, bytes(my_sig, 'utf-8')) + + def test_long_running_execute(self): + self._auth() + chan = self.session.channel_new() + self.assertEqual(chan.open_session(), 0) + self.assertEqual(chan.request_exec('sleep 1; exit 3'), 0) + chan.send_eof() + self.assertEqual(chan.close(), 0) + self.assertEqual(chan.get_exit_status(), 3) + + def test_read_stderr(self): + self._auth() + chan = self.session.channel_new() + self.assertEqual(chan.open_session(), 0) + expected = ['stderr output'] + chan.request_exec('echo "stderr output" >&2') + size, data = chan.read(is_stderr=True) + self.assertTrue(size > 0) + lines = [s.decode('utf-8') for s in data.splitlines()] + self.assertListEqual(expected, lines) + + def test_pty(self): + self._auth() + chan = self.session.channel_new() + chan.open_session() + self.assertTrue(chan.request_pty() == 0) + _out = u'stderr output' + expected = [_out] + chan.request_exec(u'echo "%s" >&2' % (_out,)) + # stderr output gets redirected to stdout with a PTY + size, data = chan.read() + self.assertTrue(size > 0) + lines = [s.decode('utf-8') for s in data.splitlines()] + self.assertListEqual(expected, lines) + + def test_write_stdin(self): + self._auth() + _in = u'writing to stdin' + chan = self.session.channel_new() + chan.open_session() + chan.request_exec('cat') + chan.write(_in + '\n') + self.assertEqual(chan.send_eof(), 0) + size, data = chan.read() + self.assertTrue(size > 0) + lines = [line.decode('utf-8') for line in data.splitlines()] + self.assertListEqual([_in], lines) + chan.close() + chan.read() + self.assertTrue(chan.is_eof()) + + def test_write_stderr(self): + self._auth() + chan = self.session.channel_new() + chan.open_session() + chan.request_exec('echo something') + _in = u'stderr' + rc, bytes_written = chan.write_stderr(_in + '\n') + self.assertEqual(rc, 7) + self.assertEqual(bytes_written, 7) + self.assertEqual(chan.close(), 0) diff --git a/ci/integration_tests/test_session.py b/ci/integration_tests/test_session.py new file mode 100644 index 00000000..a4b49d47 --- /dev/null +++ b/ci/integration_tests/test_session.py @@ -0,0 +1,223 @@ +# This file is part of ssh-python. +# Copyright (C) 2018-2025 Panos Kittenis. +# Copyright (C) 2018-2025 ssh-python Contributors. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation, version 2.1. +# +# 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-130 + +import unittest +import socket +import os +import base64 +from select import select + +from ssh.session import Session, SSH_AUTH_AGAIN, SSH_READ_PENDING, SSH_WRITE_PENDING +from ssh.channel import Channel +from ssh.key import SSHKey, import_pubkey_file, import_privkey_file, import_cert_file, \ + import_cert_base64, copy_cert_to_privkey +from ssh.keytypes import RSACert01Key +from ssh import options +from ssh.exceptions import KeyImportError, InvalidAPIUse, \ + AuthenticationDenied +from ssh.scp import SCP, SSH_SCP_READ, SSH_SCP_WRITE, SSH_SCP_RECURSIVE +from ssh.error_codes import SSH_AGAIN +from ssh.utils import wait_socket + +from .base_case import SSHTestCase + + +class SessionTest(SSHTestCase): + + def test_non_blocking_connect(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = Session() + session.options_set(options.USER, self.user) + session.options_set(options.HOST, self.host) + session.options_set_port(self.port) + self.assertEqual(session.set_socket(sock), 0) + session.set_blocking(0) + rc = session.connect() + while rc == SSH_AGAIN: + wait_socket(session, sock) + rc = session.connect() + self.assertEqual(rc, 0) + rc = session.userauth_publickey(self.pkey) + while rc == SSH_AUTH_AGAIN: + wait_socket(session, sock) + rc = session.userauth_publickey(self.pkey) + self.assertEqual(rc, 0) + + def test_should_not_segfault(self): + session = Session() + self.assertEqual(session.get_error(), '') + self.assertRaises(InvalidAPIUse, session.userauth_none) + self.assertRaises(InvalidAPIUse, session.userauth_publickey, self.pkey) + key = import_pubkey_file(self.user_pub_key) + self.assertRaises(InvalidAPIUse, session.userauth_try_publickey, key) + self.assertRaises(InvalidAPIUse, session.userauth_publickey_auto, '') + self.assertRaises(InvalidAPIUse, session.channel_new) + self.assertRaises(InvalidAPIUse, session.get_disconnect_message) + self.assertRaises(InvalidAPIUse, session.get_issue_banner) + self.assertRaises(InvalidAPIUse, session.get_openssh_version) + self.assertIsNone(session.dump_knownhost()) + self.assertIsNone(session.get_clientbanner()) + self.assertIsNone(session.get_serverbanner()) + self.assertIsNone(session.get_kex_algo()) + self.assertIsNone(session.get_cipher_in()) + self.assertIsNone(session.get_cipher_out()) + self.assertIsNone(session.get_hmac_in()) + self.assertIsNone(session.get_hmac_out()) + self.assertIsNotNone(session.get_error_code()) + session.connector_new() + + def test_disconnect(self): + self._auth() + chan = self.session.channel_new() + self.assertEqual(chan.open_session(), 0) + chan.close() + self.session.disconnect() + del chan + + def test_socket_connect(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = Session() + session.options_set(options.USER, self.user) + session.options_set(options.HOST, self.host) + session.options_set_port(self.port) + self.assertEqual(session.set_socket(sock), 0) + self.assertEqual(session.connect(), 0) + self.assertRaises(AuthenticationDenied, session.userauth_none) + self.assertEqual( + session.userauth_publickey(self.pkey), 0) + + def test_connect(self): + self.assertEqual(self.session.connect(), 0) + self.assertRaises(AuthenticationDenied, self.session.userauth_none) + self.assertRaises( + AuthenticationDenied, self.session.userauth_publickey_auto, '') + + def test_key_auth(self): + self.assertEqual(self.session.connect(), 0) + key = import_pubkey_file(self.user_pub_key) + self.assertIsInstance(key, SSHKey) + self.assertEqual( + self.session.userauth_try_publickey(key), 0) + # Private key as public key import error + self.assertRaises(KeyImportError, import_privkey_file, self.user_pub_key) + pkey = import_privkey_file(self.user_key) + self.assertEqual( + self.session.userauth_publickey(pkey), 0) + + def test_cert_auth(self): + self.assertEqual(self.session.connect(), 0) + cert_key = import_cert_file(self.user_cert_file) + self.assertIsInstance(cert_key, SSHKey) + key_type = cert_key.key_type() + self.assertIsInstance(key_type, RSACert01Key) + cert_priv_key = import_privkey_file(self.user_ca_key) + copy_cert_to_privkey(cert_key, cert_priv_key) + self.assertEqual(self.session.userauth_try_publickey(cert_key), 0) + self.assertEqual(self.session.userauth_publickey(cert_priv_key), 0) + chan = self.session.channel_new() + self.assertIsInstance(chan, Channel) + + def test_cert_imports(self): + self.assertRaises(KeyImportError, import_cert_file, self.user_key) + priv_key = SSHKey() + cert_key = import_cert_file(self.user_cert_file) + self.assertRaises(KeyImportError, copy_cert_to_privkey, cert_key, priv_key) + with open(self.user_cert_file, 'rb') as fh: + cert_key_data = base64.b64encode(fh.read()) + # cert_key_data = fh.read() + rsa_cert = RSACert01Key() + self.assertIsNotNone(rsa_cert.value) + # Failing + # cert_key_b64 = import_cert_base64(cert_key_data, rsa_cert) + # self.assertIsInstance(cert_key_b64.key_type(), RSACert01Key) + + def test_open_channel(self): + self._auth() + chan = self.session.channel_new() + self.assertIsInstance(chan, Channel) + + def test_scp_push(self): + self._auth() + scp = self.session.scp_new(SSH_SCP_WRITE, 'test_file') + self.assertIsInstance(scp, SCP) + test_data = b"data\n" + remote_filename = os.sep.join([os.path.dirname(__file__), + "remote_test_file"]) + to_copy = os.sep.join([os.path.dirname(__file__), + "copied"]) + with open(remote_filename, 'wb') as fh: + fh.write(test_data) + try: + fileinfo = os.stat(remote_filename) + scp.push_file64(to_copy, fileinfo.st_size, fileinfo.st_mode & 0o777) + scp.write(test_data) + del scp + finally: + os.unlink(remote_filename) + + def test_gssapi_creds(self): + self.session.connect() + rc = self.session.options_set(options.GSSAPI_SERVER_IDENTITY, 'identity') + self.assertEqual(rc, 0) + rc = self.session.options_set(options.GSSAPI_CLIENT_IDENTITY, 'my_id') + self.assertEqual(rc, 0) + rc = self.session.options_set_gssapi_delegate_credentials(True) + self.assertEqual(rc, 0) + self.assertRaises(AuthenticationDenied, self.session.userauth_gssapi) + rc = self.session.options_set_gssapi_delegate_credentials(False) + self.assertEqual(rc, 0) + self.assertRaises(AuthenticationDenied, self.session.userauth_gssapi) + + def test_agent_auth(self): + self.session.connect() + self.assertRaises( + AuthenticationDenied, self.session.userauth_agent, self.user) + + def test_set_timeout(self): + session = Session() + self.assertEqual(session.options_set(options.TIMEOUT, "1000"), 0) + self.assertEqual(session.options_set(options.TIMEOUT_USEC, "1000"), 0) + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = Session() + session.options_set(options.USER, self.user) + session.options_set(options.HOST, self.host) + session.options_set_port(self.port) + self.assertEqual(session.set_socket(sock), 0) + self.assertEqual(session.options_set(options.TIMEOUT, "1000"), 0) + self.assertEqual(session.options_set(options.TIMEOUT_USEC, "1000"), 0) + + def test_get_server_publickey(self): + self.session.connect() + self.assertIsInstance(self.session.get_server_publickey(), SSHKey) + + def test_compression_connect(self): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((self.host, self.port)) + session = Session() + session.options_set(options.USER, self.user) + session.options_set(options.HOST, self.host) + session.options_set_port(self.port) + # Great API, "yes" "no" as booleans + self.assertEqual(session.options_set(options.COMPRESSION, "yes"), 0) + self.assertEqual(session.options_set_int_val(options.COMPRESSION_LEVEL, 2), 0) + self.assertEqual(session.set_socket(sock), 0) + self.assertEqual(session.connect(), 0) + self.assertEqual( + session.userauth_publickey(self.pkey), 0) diff --git a/ci/integration_tests/test_sftp.py b/ci/integration_tests/test_sftp.py new file mode 100644 index 00000000..ae24308e --- /dev/null +++ b/ci/integration_tests/test_sftp.py @@ -0,0 +1,408 @@ +# This file is part of ssh-python. +# Copyright (C) 2018-2025 Panos Kittenis. +# Copyright (C) 2018-2025 ssh-python Contributors. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation, version 2.1. +# +# 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-130 + +import unittest +import os +import platform +import stat +from sys import version_info +import shutil +import socket +from select import select +import time + +from ssh.session import Session +from ssh import options +from ssh.sftp import SFTP +from ssh.sftp_handles import SFTPDir, SFTPFile +from ssh.sftp_attributes import SFTPAttributes +from ssh.exceptions import InvalidAPIUse, SFTPHandleError, SFTPError +from ssh.error_codes import SSH_AGAIN +from ssh.utils import wait_socket + + +from .base_case import SSHTestCase + + +class SFTPTest(SSHTestCase): + + def test_sftp_init(self): + self._auth() + sftp = self.session.sftp_new() + self.assertIsInstance(sftp, SFTP) + self.assertEqual(sftp.init(), 0) + del sftp + sftp = self.session.sftp_init() + self.assertIsInstance(sftp, SFTP) + + def test_sftp_fail(self): + self.assertRaises(InvalidAPIUse, self.session.sftp_new) + self._auth() + sftp = self.session.sftp_new() + self.assertRaises(SFTPHandleError, sftp.opendir, '.') + + def test_sftp_dir(self): + self._auth() + sftp = self.session.sftp_new() + sftp.init() + _dir = sftp.opendir('.') + self.assertIsInstance(_dir, SFTPDir) + self.assertFalse(_dir.eof()) + self.assertEqual(_dir.closedir(), 0) + # dir handle from context manager + with sftp.opendir('.') as _dir: + for attr in _dir: + self.assertIsInstance(attr, SFTPAttributes) + self.assertIsNotNone(attr.name) + self.assertTrue(_dir.eof()) + + def test_sftp_readdir(self): + self._auth() + sftp = self.session.sftp_new() + sftp.init() + with sftp.opendir('.') as _dir: + attrs = _dir.readdir() + self.assertIsInstance(attrs, SFTPAttributes) + self.assertIsNotNone(attrs.uid) + self.assertIsNotNone(attrs.gid) + self.assertIsNotNone(attrs.owner) + self.assertIsNotNone(attrs.group) + self.assertTrue(attrs.size > 0) + self.assertTrue(isinstance(attrs.name, bytes)) + self.assertTrue(len(attrs.longname) > 1) + self.assertFalse(_dir.closed) + self.assertEqual(_dir.closedir(), 0) + self.assertTrue(_dir.closed) + del _dir + with sftp.opendir('.') as _dir: + pass + self.assertTrue(_dir.closed) + del _dir + + def test_sftp_file_read(self): + self._auth() + sftp = self.session.sftp_new() + sftp.init() + if int(platform.python_version_tuple()[0]) >= 3: + test_file_data = b'test' + bytes(os.linesep, 'utf-8') + else: + test_file_data = b'test' + os.linesep + remote_filename = os.sep.join([os.path.dirname(__file__), + 'remote_test_file']) + with open(remote_filename, 'wb') as test_fh: + test_fh.write(test_file_data) + try: + with sftp.open(remote_filename, os.O_RDONLY, 0) as remote_fh: + self.assertIsInstance(remote_fh, SFTPFile) + remote_data = b"" + for rc, data in remote_fh: + remote_data += data + self.assertFalse(remote_fh.closed) + self.assertEqual(remote_fh.close(), 0) + self.assertTrue(remote_fh.closed) + self.assertEqual(remote_data, test_file_data) + self.assertTrue(remote_fh.closed) + del remote_fh + with sftp.open(remote_filename, os.O_RDONLY, 0) as remote_fh: + pass + self.assertTrue(remote_fh.closed) + finally: + os.unlink(remote_filename) + + def test_sftp_write(self): + self._auth() + sftp = self.session.sftp_new() + sftp.init() + data = b"test file data" + remote_filename = os.sep.join([os.path.dirname(__file__), + "remote_test_file"]) + mode = int("0666") if version_info <= (2,) else 0o666 + with sftp.open(remote_filename, + os.O_CREAT | os.O_WRONLY, + mode) as remote_fh: + remote_fh.write(data) + with open(remote_filename, 'rb') as fh: + written_data = fh.read() + _stat = os.stat(remote_filename) + try: + self.assertEqual(stat.S_IMODE(_stat.st_mode), 420) + self.assertTrue(fh.closed) + self.assertEqual(data, written_data) + except Exception: + raise + finally: + os.unlink(remote_filename) + + def test_sftp_attrs_cls(self): + attrs = SFTPAttributes.new_attrs(None) + self.assertIsInstance(attrs, SFTPAttributes) + self.assertEqual(attrs.uid, 0) + self.assertEqual(attrs.gid, 0) + attrs.flags = 1 + attrs.type = 2 + attrs.size = 3 + attrs.uid = 4 + attrs.gid = 5 + attrs.permissions = 6 + attrs.atime64 = 7 + attrs.atime = 8 + attrs.atime_nseconds = 9 + attrs.createtime = 10 + attrs.createtime_nseconds = 11 + attrs.mtime64 = 12 + attrs.mtime = 13 + attrs.mtime_nseconds = 14 + attrs.extended_count = 15 + self.assertEqual(attrs.flags, 1) + self.assertEqual(attrs.type, 2) + self.assertEqual(attrs.size, 3) + self.assertEqual(attrs.uid, 4) + self.assertEqual(attrs.gid, 5) + self.assertEqual(attrs.permissions, 6) + self.assertEqual(attrs.atime64, 7) + self.assertEqual(attrs.atime, 8) + self.assertEqual(attrs.atime_nseconds, 9) + self.assertEqual(attrs.createtime, 10) + self.assertEqual(attrs.createtime_nseconds, 11) + self.assertEqual(attrs.mtime64, 12) + self.assertEqual(attrs.mtime, 13) + self.assertEqual(attrs.mtime_nseconds, 14) + self.assertEqual(attrs.extended_count, 15) + del attrs + + def test_sftp_stat(self): + self._auth() + sftp = self.session.sftp_init() + self.assertIsInstance(sftp, SFTP) + test_data = b"data" + remote_filename = os.sep.join([os.path.dirname(__file__), + "remote_test_file"]) + with open(remote_filename, 'wb') as fh: + fh.write(test_data) + _mask = int('0644') if version_info <= (2,) else 0o644 + os.chmod(remote_filename, _mask) + _size = os.stat(remote_filename).st_size + try: + attrs = sftp.stat(remote_filename) + self.assertTrue(isinstance(attrs, SFTPAttributes)) + self.assertEqual(attrs.uid, os.getuid()) + self.assertEqual(attrs.gid, os.getgid()) + self.assertEqual(stat.S_IMODE(attrs.permissions), 420) + self.assertTrue(attrs.atime > 0) + self.assertTrue(attrs.mtime > 0) + self.assertTrue(attrs.flags > 0) + self.assertEqual(attrs.size, _size) + except Exception: + raise + finally: + os.unlink(remote_filename) + self.assertRaises(SFTPError, sftp.stat, remote_filename) + self.assertNotEqual(sftp.get_error(), 0) + + def test_sftp_fstat(self): + self._auth() + sftp = self.session.sftp_init() + self.assertTrue(sftp is not None) + test_data = b"data" + remote_filename = os.sep.join([os.path.dirname(__file__), + "remote_test_file"]) + with open(remote_filename, 'wb') as fh: + fh.write(test_data) + try: + with sftp.open(remote_filename, 0, 0) as fh: + attrs = fh.fstat() + self.assertTrue(isinstance(attrs, SFTPAttributes)) + self.assertEqual(attrs.uid, os.getuid()) + self.assertEqual(attrs.gid, os.getgid()) + self.assertTrue(attrs.flags > 0) + except Exception: + raise + finally: + os.unlink(remote_filename) + + def test_sftp_setstat(self): + self._auth() + sftp = self.session.sftp_init() + self.assertTrue(sftp is not None) + test_data = b"data" + remote_filename = os.sep.join([os.path.dirname(__file__), + "remote_test_file"]) + with open(remote_filename, 'wb') as fh: + fh.write(test_data) + _mask = int('0644') if version_info <= (2,) else 0o644 + os.chmod(remote_filename, _mask) + attrs = sftp.stat(remote_filename) + attrs.permissions = int("0400") if version_info <= (2,) else 0o400 + try: + self.assertEqual(sftp.setstat(remote_filename, attrs), 0) + attrs = sftp.stat(remote_filename) + self.assertEqual(attrs.permissions, 33024) + except Exception: + raise + finally: + os.unlink(remote_filename) + + def test_canonicalize_path(self): + self._auth() + sftp = self.session.sftp_init() + self.assertTrue(sftp is not None) + self.assertIsNotNone(sftp.canonicalize_path('.')) + + def test_sftp_symlink_realpath_lstat(self): + self._auth() + sftp = self.session.sftp_init() + self.assertTrue(sftp is not None) + test_data = b"data" + remote_filename = os.sep.join([os.path.dirname(__file__), + "remote_test_file"]) + with open(remote_filename, 'wb') as fh: + fh.write(test_data) + symlink_target = os.sep.join([os.path.dirname(__file__), + 'remote_symlink']) + try: + self.assertEqual(sftp.symlink(remote_filename, symlink_target), 0) + lstat = sftp.lstat(symlink_target) + self.assertTrue(lstat is not None) + self.assertEqual(lstat.size, os.lstat(symlink_target).st_size) + realpath = sftp.canonicalize_path(symlink_target) + self.assertTrue(realpath is not None) + self.assertEqual(realpath, remote_filename) + except Exception: + raise + finally: + os.unlink(symlink_target) + os.unlink(remote_filename) + + def test_readdir(self): + self._auth() + sftp = self.session.sftp_init() + dir_data = [_dir for _dir in sftp.opendir('.')] + self.assertTrue(len(dir_data) > 0) + self.assertTrue(b'.' in (_ls.name for _ls in dir_data)) + self.assertTrue(b'..' in (_ls.name for _ls in dir_data)) + + def test_readdir_failure(self): + self._auth() + sftp = self.session.sftp_init() + self.assertRaises(SFTPError, sftp.opendir, 'fakeyfakey') + + def test_fsync(self): + self._auth() + sftp = self.session.sftp_init() + test_data = b"data" + remote_filename = os.sep.join([os.path.dirname(__file__), + "remote_test_file"]) + with open(remote_filename, 'wb') as fh: + fh.write(test_data) + try: + with sftp.open(remote_filename, 0, 0) as fh: + self.assertEqual(fh.fsync(), 0) + except Exception: + raise + finally: + os.unlink(remote_filename) + + def test_statvfs(self): + self._auth() + sftp = self.session.sftp_init() + vfs = sftp.statvfs('.') + self.assertTrue(vfs is not None) + self.assertTrue(vfs.f_files > 0) + self.assertTrue(vfs.f_bsize > 0) + self.assertTrue(vfs.f_namemax > 0) + + def test_fstatvfs(self): + self._auth() + sftp = self.session.sftp_init() + test_data = b"data" + remote_filename = os.sep.join([os.path.dirname(__file__), + "remote_test_file"]) + with open(remote_filename, 'wb') as fh: + fh.write(test_data) + try: + with sftp.open(remote_filename, 0, 0) as fh: + vfs = fh.fstatvfs() + self.assertTrue(vfs is not None) + self.assertTrue(vfs.f_files > 0) + self.assertTrue(vfs.f_bsize > 0) + self.assertTrue(vfs.f_namemax > 0) + except Exception: + raise + finally: + os.unlink(remote_filename) + + def test_mkdir(self): + mode = int("0644") if version_info <= (2,) else 0o644 + _path = 'tmp' + abspath = os.path.join(os.path.expanduser('~'), _path) + self._auth() + sftp = self.session.sftp_init() + try: + shutil.rmtree(abspath) + except OSError: + pass + sftp.mkdir(_path, mode) + try: + self.assertTrue(os.path.isdir(abspath)) + finally: + shutil.rmtree(abspath) + + # def test_async_read(self): + # sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + # sock.connect((self.host, self.port)) + # self.session = Session() + # self.session.options_set(options.USER, self.user) + # self.session.options_set(options.HOST, self.host) + # self.session.options_set_port(self.port) + # self.assertEqual(self.session.set_socket(sock), 0) + # self.assertEqual(self.session.connect(), 0) + # self.assertEqual(self.session.userauth_publickey(self.pkey), 0) + # sftp = self.session.sftp_new() + # sftp.init() + # if int(platform.python_version_tuple()[0]) >= 3: + # test_file_data = b'test' + bytes(os.linesep, 'utf-8') + # else: + # test_file_data = b'test' + os.linesep + # remote_filename = os.sep.join([os.path.dirname(__file__), + # 'remote_test_file']) + # with open(remote_filename, 'wb') as test_fh: + # test_fh.write(test_file_data) + # # self.session.set_blocking(False) + # try: + # with sftp.open(remote_filename, os.O_RDONLY, 0) as remote_fh: + # self.assertIsInstance(remote_fh, SFTPFile) + # remote_fh.set_nonblocking() + # remote_data = b"" + # async_id = remote_fh.async_read_begin() + # self.assertNotEqual(async_id, 0) + # import ipdb; ipdb.set_trace() + # size, data = remote_fh.async_read(async_id) + # while size > 0 or size == SSH_AGAIN: + # if size == SSH_AGAIN: + # print("Would try again") + # wait_socket(sock, self.session, timeout=1) + # size, data = remote_fh.async_read(async_id) + # continue + # remote_data += data + # size, data = remote_fh.async_read(async_id) + # self.assertFalse(remote_fh.closed) + # self.assertEqual(remote_fh.close(), 0) + # self.assertTrue(remote_fh.closed) + # self.assertEqual(remote_data, test_file_data) + # self.assertTrue(remote_fh.closed) + # finally: + # os.unlink(remote_filename) diff --git a/tests/unit_test_cert_key b/ci/integration_tests/unit_test_cert_key similarity index 100% rename from tests/unit_test_cert_key rename to ci/integration_tests/unit_test_cert_key diff --git a/tests/unit_test_cert_key.pub b/ci/integration_tests/unit_test_cert_key.pub similarity index 100% rename from tests/unit_test_cert_key.pub rename to ci/integration_tests/unit_test_cert_key.pub diff --git a/tests/unit_test_key b/ci/integration_tests/unit_test_key similarity index 100% rename from tests/unit_test_key rename to ci/integration_tests/unit_test_key diff --git a/ci/integration_tests/unit_test_key.pub b/ci/integration_tests/unit_test_key.pub new file mode 100644 index 00000000..4ff0ebc0 --- /dev/null +++ b/ci/integration_tests/unit_test_key.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEsAAs2ew1xYntiiBAb3oqs7UC2Qd2kQ/eF+6WqOjeTFjWGksybnFidV91MwLjHdPmioz/1SleZqSqcD0csBcUs6jqclDlJ2MX8ZjL0e8hFDYpepFPTkwB2D6e55DwK0GJefiHUda5fKaaCzMN69h/RoBYurV/Zxf4+kRUAt+A5RXBGe22BdMtKW30J9endU9qWP4QDWtFXxvOjWHuJc7M/MNP2qww4yBo4xcKTabr8TC9uL7RUh4hMWdiNZnlmwSICT6k9NkkcBbDEIW0SjEcUMRB/V0qQ/J5Jeb8Lea82wDDdcfKaOPmI8ST5WtjfqPkKd9sqVhsq0gcCKtFZv0r zefrer@kirin diff --git a/ci/osx-wheel.sh b/ci/osx-wheel.sh index e525ba0d..e047141c 100755 --- a/ci/osx-wheel.sh +++ b/ci/osx-wheel.sh @@ -1,43 +1,61 @@ #!/bin/bash -xe -# This file is part of ssh-python. -# Copyright (C) 2017-2022 Panos Kittenis and contributors. +# This file is part of ssh-python. +# Copyright (C) 2018-2025 Panos Kittenis. +# Copyright (C) 2018-2025 ssh-python Contributors. # -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation, version 2.1. +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation, version 2.1. # -# 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 -# Lesser General Public License for more details. +# 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 +# Lesser General Public License for more details. # -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-130 +SYSTEM_LIBSSH_DIR="/opt/homebrew/opt/libssh/lib" +MY_LIBSSH_DIR="local/lib" +LIBSSH_INCLUDE_DIR="/opt/homebrew/opt/libssh/include" +set -x + +export CPPFLAGS="-I${LIBSSH_INCLUDE_DIR}" +sudo cp -a libssh/include/* ${LIBSSH_INCLUDE_DIR}/ +set +x pip3 install -U virtualenv python3 -m virtualenv -p "$(which python3)" venv +set -x -set +x source venv/bin/activate -set -x python -V pip3 install -U setuptools pip pip3 install -U delocate wheel -SYSTEM_LIBSSH=1 python3 setup.py bdist_wheel -ls -lhtr /usr/local/lib/ +unset SYSTEM_LIBSSH + +python3 setup.py bdist_wheel + +sudo cp -a ${MY_LIBSSH_DIR}/libssh* ${SYSTEM_LIBSSH_DIR}/ +ls -lhtr ${SYSTEM_LIBSSH_DIR} + delocate-listdeps dist/*.whl delocate-wheel -v -w wheels dist/*.whl delocate-listdeps wheels/*.whl ls -l wheels/*.whl -rm -f /usr/local/lib/libssh* +rm -f ${SYSTEM_LIBSSH_DIR}/libssh* +rm -rf local +ls -lhtr ${SYSTEM_LIBSSH_DIR} + pip3 install -v wheels/*.whl + pwd; mkdir -p temp; cd temp; pwd python3 -c "from ssh.session import Session; Session()" && echo "Import successful" cd ..; pwd + set +x deactivate set -x diff --git a/doc/conf.py b/doc/conf.py index 0746768d..01964c0c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -121,7 +121,7 @@ # Output file base name for HTML help builder. htmlhelp_basename = 'ssh-pythondoc' -intersphinx_mapping = {'https://docs.python.org/': None} +intersphinx_mapping = {'python': ('https://docs.python.org/3', None)} autoclass_content = "both" # A list of files that should not be packed into the epub file. diff --git a/doc/installation.rst b/doc/installation.rst index 2756cf0a..d15b6bef 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -15,6 +15,8 @@ By default, the package will try to build against an embedded version of ``libss To build against a system library, export the ``SYSTEM_LIBSSH=1`` environment variable prior to building. +Note that the library supports its embedded ``libssh`` version and only that version. Use previous ``ssh-python`` versions if wanting to build against older ``libssh`` versions. See `Changelog `_. + The following libraries are required: * OpenSSL 1.0 or 1.1, >=1.1 for Ed25519 support @@ -43,7 +45,7 @@ Building on Windows Requirements: -* Python >= 3.6 +* Python >= 3.8 * Visual Studio 14 or above * OpenSSL 1.1 * Zlib @@ -60,3 +62,5 @@ Steps Note dependencies will need to be built statically to be distributable to other Windows systems. Cygwin/MingW probably do not work. + +No support is offered for building on Windows from source. diff --git a/doc/requirements.txt b/doc/requirements.txt new file mode 100644 index 00000000..82133027 --- /dev/null +++ b/doc/requirements.txt @@ -0,0 +1,2 @@ +sphinx +sphinx_rtd_theme 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/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. Gaßmann 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 00000000..b494fb53 Binary files /dev/null and b/krb5-1.21.3/src/lib/crypto/crypto_tests/test/katmct.pdf differ diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/vb.txt b/krb5-1.21.3/src/lib/crypto/crypto_tests/vb.txt new file mode 100644 index 00000000..dab133c2 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/vb.txt @@ -0,0 +1,87 @@ + +Private Const BlkLenMax = 32 ' maximum block length in bytes +Private Const KeyLenMax = 32 ' maximum block length in bytes +Private Const KeySchLenMax = 128 ' maximum key schedule length in bytes +Private BlkLen As Integer ' actual block length +Private KeyLen As Integer ' actual key length + +Private Type AESctx ' Type to hold the AES context data + Ekey(0 To KeySchLenMax - 1) As Long + Nrnd As Long + Ncol As Long +End Type + +Private Type KeyBlk ' Type to hold user key data + K(0 To KeyLenMax - 1) As Byte +End Type + +Private Type IoBlk ' Type to hold cipher input and output blocks + IO(0 To BlkLenMax - 1) As Byte +End Type + +Rem Change "d:\dll_pth" in the following lines to the directory path where the AES DLL is located +Private Declare Function AesBlkLen Lib "d:\dll_path\aes.dll" Alias "_aes_blk_len@8" (ByVal N As Long, C As AESctx) As Integer +Private Declare Function AesEncKey Lib "d:\dll_path\aes.dll" Alias "_aes_enc_key@12" (K As KeyBlk, ByVal N As Long, C As AESctx) As Integer +Private Declare Function AesDecKey Lib "d:\dll_path\aes.dll" Alias "_aes_dec_key@12" (K As KeyBlk, ByVal N As Long, C As AESctx) As Integer +Private Declare Function AesEncBlk Lib "d:\dll_path\aes.dll" Alias "_aes_enc_blk@12" (Ib As IoBlk, Ob As IoBlk, C As AESctx) As Integer +Private Declare Function AesDecBlk Lib "d:\dll_path\aes.dll" Alias "_aes_dec_blk@12" (Ib As IoBlk, Ob As IoBlk, C As AESctx) As Integer + +Private Sub Hex(X As Byte) ' Output a byte in hexadecimal format +Dim H As Byte +H = Int(X / 16) +If H < 10 Then + Debug.Print Chr(48 + H); +Else + Debug.Print Chr(87 + H); +End If +H = Int(X Mod 16) +If H < 10 Then + Debug.Print Chr(48 + H); +Else + Debug.Print Chr(87 + H); +End If +End Sub + +Private Sub OutKey(S As String, B As KeyBlk) ' Display a key value +Debug.Print: Debug.Print S; +For i = 0 To KeyLen - 1 + Hex B.K(i) +Next i +End Sub + +Private Sub OutBlock(S As String, B As IoBlk) ' Display an input/output block +Debug.Print: Debug.Print S; +For i = 0 To BlkLen - 1 + Hex B.IO(i) +Next i +End Sub + +Rem The following Main routine should output the following in the immediate window: +Rem Key = 00000000000000000000000000000000 +Rem Input = 00000000000000000000000000000000 +Rem Encrypted Text = 66e94bd4ef8a2c3b884cfa59ca342b2e +Rem Decrypted Text = 00000000000000000000000000000000 + +Sub Main() +Dim Key As KeyBlk ' These variables are automatically +Dim Ib As IoBlk, Ob As IoBlk, Rb As IoBlk +Dim Cx As AESctx ' initialised to zero values in VBA +Dim RetVal As Integer + +BlkLen = 16: KeyLen = 16 + +Rem RetVal = AesBlkLen(BlkLen, Cx) ' include if the cipher block size is variable + +OutKey "Key = ", Key +OutBlock "Input = ", Ib + +RetVal = AesEncKey(Key, KeyLen, Cx) ' set an all zero encryption key +RetVal = AesEncBlk(Ib, Ob, Cx) ' encrypt Ib to Ob +OutBlock "Encrypted Text = ", Ob + +RetVal = AesDecKey(Key, KeyLen, Cx) ' set an all zero decryption key +RetVal = AesDecBlk(Ob, Rb, Cx) ' decrypt Ob to Rb +OutBlock "Decrypted Text = ", Rb +Debug.Print + +End Sub diff --git a/krb5-1.21.3/src/lib/crypto/crypto_tests/vectors.c b/krb5-1.21.3/src/lib/crypto/crypto_tests/vectors.c new file mode 100644 index 00000000..bcf5c910 --- /dev/null +++ b/krb5-1.21.3/src/lib/crypto/crypto_tests/vectors.c @@ -0,0 +1,454 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +/* lib/crypto/crypto_tests/vectors.c */ +/* + * 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. + */ + +/* + * 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. Additionally, some ciphers have been + * removed. + */ + +#include +#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 Högskolan + * (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