third_party/heimdal: Import lorikeet-heimdal-202306091507 (commit 7d8afc9d7e3d309ddcc...
authorStefan Metzmacher <metze@samba.org>
Fri, 9 Jun 2023 13:14:50 +0000 (15:14 +0200)
committerAndrew Bartlett <abartlet@samba.org>
Sat, 10 Jun 2023 09:51:38 +0000 (09:51 +0000)
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
41 files changed:
third_party/heimdal/.github/workflows/coverity.yml
third_party/heimdal/.github/workflows/linux-mit-interop.yml
third_party/heimdal/.github/workflows/linux.yml
third_party/heimdal/.github/workflows/osx.yml
third_party/heimdal/.github/workflows/scanbuild.yml
third_party/heimdal/.github/workflows/ubsan.yml
third_party/heimdal/.github/workflows/valgrind.yml
third_party/heimdal/admin/ktutil.1
third_party/heimdal/cf/crypto.m4
third_party/heimdal/doc/setup.texi
third_party/heimdal/kadmin/kadmin-commands.in
third_party/heimdal/kadmin/kadmin.1
third_party/heimdal/kdc/bx509d.c
third_party/heimdal/kdc/ipc_csr_authorizer.c
third_party/heimdal/kdc/kdc-audit.h
third_party/heimdal/kdc/kdc_locl.h
third_party/heimdal/kdc/kerberos5.c
third_party/heimdal/kdc/krb5tgs.c
third_party/heimdal/kdc/mssfu.c
third_party/heimdal/kdc/test_csr_authorizer.c
third_party/heimdal/kuser/kinit.1
third_party/heimdal/kuser/kinit.c
third_party/heimdal/lib/asn1/asn1_print.c
third_party/heimdal/lib/asn1/gen.c
third_party/heimdal/lib/base/config_file.c
third_party/heimdal/lib/base/warn.c
third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c
third_party/heimdal/lib/gssapi/netlogon/import_name.c
third_party/heimdal/lib/hcrypto/test_dh.c
third_party/heimdal/lib/hdb/hdb.c
third_party/heimdal/lib/hx509/file.c
third_party/heimdal/lib/kadm5/ipropd_slave.c
third_party/heimdal/lib/kadm5/marshall.c
third_party/heimdal/lib/krb5/cache.c
third_party/heimdal/lib/krb5/crypto.c
third_party/heimdal/lib/krb5/dcache.c
third_party/heimdal/lib/krb5/principal.c
third_party/heimdal/lib/roken/qsort.c
third_party/heimdal/lib/roken/rtbl.c
third_party/heimdal/lib/roken/snprintf.c
third_party/heimdal/lib/wind/test-normalize.c

index dfea060d04b8dc826bf0ee681ee93bcc43977a14..78ec7e5a56b9b3175610be33988432f980bed9d4 100644 (file)
@@ -16,7 +16,7 @@ jobs:
                 name: [linux-clang]
                 include:
                     - name: linux-clang
-                      os: ubuntu-18.04
+                      os: ubuntu-22.04
                       compiler: clang
         steps:
             - name: Clone repository
@@ -25,7 +25,7 @@ jobs:
               if: startsWith(matrix.os, 'ubuntu')
               run: |
                 sudo apt-get update -qq
-                sudo apt-get install -y bison comerr-dev flex libcap-ng-dev libdb-dev libedit-dev libjson-perl libldap2-dev libncurses5-dev libperl4-corelibs-perl libsqlite3-dev libkeyutils-dev pkg-config python ss-dev texinfo unzip netbase keyutils ldap-utils gdb apport curl libmicrohttpd-dev clang-tools clang-format jq valgrind
+                sudo apt-get install -y bison comerr-dev flex libcap-ng-dev libdb-dev libedit-dev libjson-perl libldap2-dev libncurses5-dev libperl4-corelibs-perl libsqlite3-dev libkeyutils-dev pkg-config python3 ss-dev texinfo unzip netbase keyutils ldap-utils gdb apport curl libmicrohttpd-dev clang-tools clang-format jq valgrind
                 # Temporary workaround for:
                 # https://github.com/actions/virtual-environments/issues/3185
                 sudo hostname localhost
index 72648ee2ce0e4086cf022f22148ff09dd973f3d0..d1837a01d8ca63879b64c5bb0261401c6bf6b612 100644 (file)
@@ -14,7 +14,7 @@ jobs:
                 name: [linux-clang]
                 include:
                     - name: linux-clang
-                      os: ubuntu-18.04
+                      os: ubuntu-22.04
                       compiler: clang
                       cflags: ''
         steps:
@@ -31,7 +31,7 @@ jobs:
                 sudo apt-get install -y bison comerr-dev flex doxygen
                 sudo apt-get install -y libcap-ng-dev libdb-dev libedit-dev libjson-perl
                 sudo apt-get install -y libldap2-dev libncurses5-dev libperl4-corelibs-perl
-                sudo apt-get install -y libsqlite3-dev libkeyutils-dev pkg-config python
+                sudo apt-get install -y libsqlite3-dev libkeyutils-dev pkg-config python3
                 sudo apt-get install -y ss-dev texinfo unzip netbase keyutils ldap-utils
                 sudo apt-get install -y gdb apport curl libmicrohttpd-dev jq valgrind
             - name: Install MIT Kerberos dependencies
index 48e4c80dc3c25c54ae1b9b50f50112f797e1fe46..1bbfbb4ec246c874ea089e446f72f3f1c1e24231 100644 (file)
@@ -57,11 +57,11 @@ jobs:
                 name: [linux-clang, linux-gcc]
                 include:
                     - name: linux-clang
-                      os: ubuntu-18.04
+                      os: ubuntu-22.04
                       compiler: clang
                       cflags: ''
                     - name: linux-gcc
-                      os: ubuntu-18.04
+                      os: ubuntu-22.04
                       compiler: gcc
                       cflags: '-Wnonnull'
         steps:
@@ -74,7 +74,7 @@ jobs:
                 sudo apt-get install -y bison comerr-dev flex doxygen
                 sudo apt-get install -y libcap-ng-dev libdb-dev libedit-dev libjson-perl
                 sudo apt-get install -y libldap2-dev libncurses5-dev libperl4-corelibs-perl
-                sudo apt-get install -y libsqlite3-dev libkeyutils-dev pkg-config python
+                sudo apt-get install -y libsqlite3-dev libkeyutils-dev pkg-config python3
                 sudo apt-get install -y ss-dev texinfo unzip netbase keyutils ldap-utils
                 sudo apt-get install -y gdb apport curl libmicrohttpd-dev jq valgrind
                 # Temporary workaround for:
index 3463e99b6e97cafc2f44ecdcfe840644d0b432df..29aa05fc1f7c5b40ff717f42676519471584c504 100644 (file)
@@ -64,7 +64,7 @@ jobs:
             - name: Install packages
               run: |
                 echo "bison, flex, ncurses, texinfo, and unzip are in the base OS."
-                echo "berkeley-db, perl, python, curl, and jq are installed in the"
+                echo "berkeley-db, perl, python3, curl, and jq are installed in the"
                 echo "base image already."
                 brew install autoconf automake libtool cpanm texinfo texi2html
                 sudo cpanm install JSON
index 678ccfd80462c479e46ce61cd43ac17991b7461b..472b0b7e396a5f7f62540cc0b037fa4ae93fcac5 100644 (file)
@@ -20,7 +20,7 @@ jobs:
                 name: [linux-clang]
                 include:
                     - name: linux-clang
-                      os: ubuntu-18.04
+                      os: ubuntu-22.04
                       compiler: clang
         steps:
             - name: Clone repository
@@ -29,7 +29,7 @@ jobs:
               if: startsWith(matrix.os, 'ubuntu')
               run: |
                 sudo apt-get update -qq
-                sudo apt-get install -y bison comerr-dev flex libcap-ng-dev libdb-dev libedit-dev libjson-perl libldap2-dev libncurses5-dev libperl4-corelibs-perl libsqlite3-dev libkeyutils-dev pkg-config python ss-dev texinfo unzip netbase keyutils ldap-utils gdb apport curl libmicrohttpd-dev clang-tools clang-format jq valgrind
+                sudo apt-get install -y bison comerr-dev flex libcap-ng-dev libdb-dev libedit-dev libjson-perl libldap2-dev libncurses5-dev libperl4-corelibs-perl libsqlite3-dev libkeyutils-dev pkg-config python3 ss-dev texinfo unzip netbase keyutils ldap-utils gdb apport curl libmicrohttpd-dev clang-tools clang-format jq valgrind
                 # Temporary workaround for:
                 # https://github.com/actions/virtual-environments/issues/3185
                 sudo hostname localhost
index d4bb2eda476a508c4c85b07b44c1533e669b4a01..9dec161d430c448f9a65da6f045552c6126303cc 100644 (file)
@@ -57,12 +57,12 @@ jobs:
                 name: [linux-clang, linux-gcc]
                 include:
                     - name: linux-clang
-                      os: ubuntu-18.04
+                      os: ubuntu-22.04
                       compiler: clang
                       cflags: '-fsanitize=undefined'
                       ldflags: ''
                     - name: linux-gcc
-                      os: ubuntu-18.04
+                      os: ubuntu-22.04
                       compiler: gcc
                       cflags: '-Wnonnull -fsanitize=undefined'
                       ldflags: ''
@@ -76,7 +76,7 @@ jobs:
                 sudo apt-get install -y bison comerr-dev flex doxygen
                 sudo apt-get install -y libcap-ng-dev libdb-dev libedit-dev libjson-perl
                 sudo apt-get install -y libldap2-dev libncurses5-dev libperl4-corelibs-perl
-                sudo apt-get install -y libsqlite3-dev libkeyutils-dev pkg-config python
+                sudo apt-get install -y libsqlite3-dev libkeyutils-dev pkg-config python3
                 sudo apt-get install -y ss-dev texinfo unzip netbase keyutils ldap-utils
                 sudo apt-get install -y gdb apport curl libmicrohttpd-dev jq valgrind
                 # Temporary workaround for:
index ab5e909166100021735afc9618557bd44480b87e..8506df999ca2630a0fc675c198e594a65e8426db 100644 (file)
@@ -20,7 +20,7 @@ jobs:
                 name: [linux-clang]
                 include:
                     - name: linux-clang
-                      os: ubuntu-18.04
+                      os: ubuntu-22.04
                       compiler: clang
         steps:
             - name: Clone repository
@@ -29,7 +29,7 @@ jobs:
               if: startsWith(matrix.os, 'ubuntu')
               run: |
                 sudo apt-get update -qq
-                sudo apt-get install -y bison comerr-dev flex libcap-ng-dev lmdb-utils liblmdb-dev libdb-dev libedit-dev libjson-perl libldap2-dev libncurses5-dev libperl4-corelibs-perl libsqlite3-dev libkeyutils-dev pkg-config python ss-dev texinfo unzip netbase keyutils ldap-utils gdb apport curl libmicrohttpd-dev jq valgrind
+                sudo apt-get install -y bison comerr-dev flex libcap-ng-dev lmdb-utils liblmdb-dev libdb-dev libedit-dev libjson-perl libldap2-dev libncurses5-dev libperl4-corelibs-perl libsqlite3-dev libkeyutils-dev pkg-config python3 ss-dev texinfo unzip netbase keyutils ldap-utils gdb apport curl libmicrohttpd-dev jq valgrind
                 # Temporary workaround for:
                 # https://github.com/actions/virtual-environments/issues/3185
                 sudo hostname localhost
index 0036edcbd9be5813ed0dc802d4deeb0d04ef8cb9..fb8bc382b39c7f8a58a89d7a48c6246853def02e 100644 (file)
@@ -174,5 +174,56 @@ command has a
 .Nm prune
 command that can do this on the KDC side.
 .El
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev KRB5_KTNAME
+Specifies the default keytab.
+.It Ev KRB5_CONFIG
+The file name of
+.Pa krb5.conf ,
+the default being
+.Pa /etc/krb5.conf .
+.El
+.Sh KEYTAB NAMING
+The syntax for the value of the
+.Ql KRB5_KTNAME
+environment variable and
+.Oo Fl k Ar keytab \*(Ba Xo
+.Fl Fl keytab= Ns Ar keytab
+.Xc
+.Oc
+options is
+.Ql TYPE:name
+where the TYPE is one of
+.Ql FILE ,
+.Ql HDBGET ,
+.Ql HDB ,
+or
+.Ql ANY ,
+and the name syntax is specific to the keytab type.
+.Pp
+For the FILE keytab type the name is the path to a file whose
+format is the well-known keytab file format used by MIT Kerberos,
+Heimdal, Java, and others.
+.Pp
+For the HDB and HDBGET keytab types the name syntax is
+.Ql [<path>][:mkey=<path>]
+where the first path is the path to the HDB and the second path
+is the path to the master key file.
+Note that to use the HDB and HDBGET keytab types in a program
+linked with Heimdal libraries one first load the
+.Ql libhdb
+library and then register their keytab methods using
+.Xr krb5_kt_register 3 .
+Note also that
+.Nm ktutil
+does not load and register the HDB and HDBGET keytab types at
+this time.
+.Pp
+The ANY keytab type name syntax is a sequence of other keytab
+names (including their TYPE: prefix) separated by commas.
+Note that there is no escape sequence for commas in keytab names.
 .Sh SEE ALSO
 .Xr kadmin 1
+.Xr kinit 1
+.Xr krb5_kt_register 3
index a8ef519841169e483e856f2bb6407a9dcde8d2d0..0f308ced8f959a4c52214f98296c5412d1d95e9c 100644 (file)
@@ -112,6 +112,22 @@ if test "$with_openssl" != "no"; then
         LDFLAGS="${LIB_openssl_crypto} ${LDFLAGS}"
         AC_CHECK_LIB([crypto], [OPENSSL_init],
                      [LIB_openssl_crypto="${LIB_openssl_crypto} -lcrypto"; openssl=yes], [openssl=no], [])
+        if test "$openssl" = "yes"; then
+            AC_CHECK_LIB([crypto],
+                         [OSSL_EC_curve_nid2name],
+                         [AC_DEFINE_UNQUOTED([HAVE_OPENSSL_30], 1,
+                                             [whether OpenSSL is 3.0 or higher])]
+                         )
+            AC_CHECK_HEADERS([openssl/fips.h],
+                             [AC_DEFINE_UNQUOTED([HAVE_OPENSSL_FIPS_H], 1,
+                                                 [whether openssl/fips.h is available])]
+                             )
+            AC_CHECK_LIB([crypto],
+                         [FIPS_mode_set],
+                         [AC_DEFINE_UNQUOTED([HAVE_OPENSSL_FIPS_MODE_SET_API], 1,
+                                             [whether FIPS_mode_set API is available])]
+                         )
+        fi
         # These cases are just for static linking on older OSes,
         # presumably.
         if test "$openssl" = "no"; then
@@ -134,23 +150,6 @@ if test "$with_openssl" != "no"; then
         LDFLAGS="${saved_LDFLAGS}"
 fi
 
-if test "$openssl" = "yes"; then
-    AC_CHECK_LIB([crypto],
-                 [OSSL_EC_curve_nid2name],
-                 [AC_DEFINE_UNQUOTED([HAVE_OPENSSL_30], 1,
-                                     [whether OpenSSL is 3.0 or higher])]
-                 )
-    AC_CHECK_HEADERS([openssl/fips.h],
-                     [AC_DEFINE_UNQUOTED([HAVE_OPENSSL_FIPS_H], 1,
-                                         [whether openssl/fips.h is available])]
-                     )
-    AC_CHECK_LIB([crypto],
-                 [FIPS_mode_set],
-                 [AC_DEFINE_UNQUOTED([HAVE_OPENSSL_FIPS_MODE_SET_API], 1,
-                                     [whether FIPS_mode_set API is available])]
-                 )
-fi
-
 LIB_hcrypto='$(top_builddir)/lib/hcrypto/libhcrypto.la'
 LIB_hcrypto_a='$(top_builddir)/lib/hcrypto/.libs/libhcrypto.a'
 LIB_hcrypto_so='$(top_builddir)/lib/hcrypto/.libs/libhcrypto.so'
index 962541359eecec41e8f160a396f716d4b63da740..1df24d12c651ebc8f41d9e5c0f39011977dffe00 100644 (file)
@@ -127,6 +127,23 @@ alternative configuration.
 env KRB5_CONFIG=$HOME/etc/krb5.conf kinit user@@REALM
 @end example
 
+@cindex KRB5CCNAME
+The Heimdal libraries and commands (and the MIT ones too), support the
+use of the environment variable @samp{KRB5CCNAME} for specifying a
+credentials cache to use.  See the @manpage{kinit,1} for details.
+
+@cindex KRB5_KTNAME
+The Heimdal libraries and commands (and the MIT ones too), support the
+use of the environment variable @samp{KRB5_KTNAME} for specifying a
+keytab file to use for server operations.  See the @manpage{kinit,1} for
+details.
+
+@cindex KRB5_CLIENT_KTNAME
+The Heimdal libraries and commands (and the MIT ones too), support the
+use of the environment variable @samp{KRB5_CLIENT_KTNAME} for specifying
+a keytab file to use for client operations.  See the @manpage{kinit,1}
+for details.
+
 @cindex GSS_MECH_CONFIG
 The GSS-API mechanism configuration file can also be changed from the
 default with the enviornment variable @samp{GSS_MECH_CONFIG}. Note that
index db9c4415e6c5e813d6fc7599ef40fa507a89f188..0872b47a4410ff99eb61b6cc6200f8b64a2c6f70 100644 (file)
@@ -498,7 +498,7 @@ command = {
                long = "krb5-config-file"
                short = "C"
                type = "string"
-               help = "filename to save the principal's krb5.confg in"
+               help = "filename to save the principal's krb5.conf in"
        }
        option = {
                long = "upto"
index ded599794616bde9c579514fad269a18a482426b..42ccad739e8c4f9da30a780351fde13e60617a11 100644 (file)
@@ -114,6 +114,7 @@ Commands include:
 .Op Fl Fl expiration-time= Ns Ar time
 .Op Fl Fl pw-expiration-time= Ns Ar time
 .Op Fl Fl policy= Ns Ar policy-name
+.Op Fl Fl use-defaults
 .Ar principal...
 .Bd -ragged -offset indent
 Adds a new principal to the database. The options not passed on the
@@ -139,6 +140,13 @@ behavior is the default if none of these are given.
 The only policy supported by Heimdal servers is
 .Ql default .
 .Pp
+If some parameters are not given then they will be prompted for
+unless the
+.Fl Fl use-defaults
+option is given, in which case defaults will be taken from the
+principal named
+.Dq default .
+.Pp
 This command has the following aliases:
 .Nm ank ,
 .Nm add_new_key .
@@ -305,10 +313,12 @@ enctypes.
 .Ed
 .Pp
 .Nm prune
-.Ar principal [kvno]
+.Oo Fl Fl kvno= Ns Ar number
+.Oc
+.Ar principal
 .Bd -ragged -offset indent
 Deletes the named principal's keys of the given kvno.  If a kvno is
-not given then this deletes all the named principals keys that are
+not given then this deletes all the named principal's keys that are
 too old to be needed for decrypting tickets issued using those keys
 (i.e., any such tickets are necessarily expired).  The determination
 of "too old" is made using the max-ticket-life attribute of the
@@ -319,6 +329,7 @@ principals, those are not consulted here.
 .Pp
 .Nm ext_keytab
 .Oo Fl k Ar keytab \*(Ba Xo
+.Op Fl Fl random-key
 .Op Fl Fl keepold | Fl Fl keepallold | Fl Fl pruneall
 .Op Fl Fl enctypes= Ns Ar string
 .Fl Fl keytab= Ns Ar string
@@ -329,6 +340,12 @@ principals, those are not consulted here.
 Creates a keytab with the keys of the specified principals.  Requires
 get-keys rights, otherwise the principal's keys are changed and saved in
 the keytab.
+.Pp
+If the
+.Fl Fl random-key
+option is given then new randomly-generated keys will be set on
+the principal.
+.Pp
 If enctypes to use are not given, then the
 .Ar [libdefaults] supported_enctypes
 configuration parameter will be used on the client side to select
@@ -355,11 +372,17 @@ behavior is the default if none of these are given.
 .Op Fl t | Fl Fl terse
 .Op Fl o Ar string | Fl Fl column-info= Ns Ar string
 .Op Fl C Ar path | Fl Fl krb5-config-file= Ns Ar path
+.Op Fl Fl upto= Ns Ar number
 .Ar principal...
 .Bd -ragged -offset indent
 Lists the matching principals, short prints the result as a table,
-while long format produces a more verbose output. Which columns to
-print can be selected with the
+while long format produces a more verbose output.
+If the
+.Fl Fl upto= Ns Ar number
+option is given, then only up to that many principals will be
+listed.
+.Pp
+Which columns to print can be selected with the
 .Fl o
 option. The argument is a comma separated list of column names
 optionally appended with an equal sign
@@ -413,6 +436,9 @@ and
 .Op Fl Fl kvno= Ns Ar number
 .Op Fl Fl policy= Ns Ar policy-name
 .Op Fl Fl alias= Ns Ar alias-name
+.Op Fl Fl constrained-delegation= Ns Ar principal-name
+.Op Fl Fl pkinit-acl= Ns Ar subject-name
+.Op Fl Fl service-enctypes= Ns Ar enctype
 .Op Fl C Ar path | Fl Fl krb5-config-file= Ns Ar path
 .Ar principal...
 .Bd -ragged -offset indent
@@ -471,6 +497,30 @@ Attributes may be negated with a "-", e.g.,
 .Pp
 kadmin -l modify -a -disallow-proxiable user
 .Pp
+The
+.Fl Fl constrained-delegation= Ns Ar principal-name
+option is not currently implemented.
+.Pp
+The
+.Fl Fl pkinit-acl= Ns Ar subject-name
+option authorizes clients with certificates with the given
+subject distinguished name to get tickets for the principal using
+PKINIT.
+This option can be given multiple times.
+The PKINIT ACLs set with this option will replace the existing
+ones.
+.Pp
+The
+.Fl Fl service-enctypes= Ns Ar enctype
+option indicates that the service supports the given enctype
+regardless of whether the service has long-term keys of that
+enctype.
+This option can be given multiple times and will replace the
+existing set of enctypes supported by the service.
+If a service principal does not have any supported enctypes then
+the KDC will assume that it supports only the enctypes of all of
+its long-term keys.
+.Pp
 This command has the following alias:
 .Nm mod .
 .Ed
@@ -588,10 +638,17 @@ Heimdal format.
 .Nm init
 .Op Fl Fl realm-max-ticket-life= Ns Ar string
 .Op Fl Fl realm-max-renewable-life= Ns Ar string
+.Op Fl Fl bare
 .Ar realm
 .Bd -ragged -offset indent
-Initializes the Kerberos database with entries for a new realm. It's
-possible to have more than one realm served by one server.
+Initializes the Kerberos database with entries for a new realm.
+It's possible to have more than one realm served by one server
+with the same database.
+.Pp
+If the
+.Fl Fl bare
+option is given, then only the root krbtgt principal for that
+realm will be created.
 .Ed
 .Pp
 .Nm load
@@ -620,9 +677,21 @@ but just modifies the database with the entries in the dump file.
 .Oc
 .Op Fl Fl convert-file
 .Op Fl Fl master-key-fd= Ns Ar fd
+.Op Fl Fl random-password
 .Bd -ragged -offset indent
 Writes the Kerberos master key to a file used by the KDC.
 .Pp
+If the
+.Fl Fl convert-file
+option is given then convert an existing file to the new format.
+If the
+.Fl Fl master-key-fd= Ns Ar fd
+option is given the the password will be read from the given file
+descriptor.
+If the
+.Fl Fl random-password
+option is given then a password will be generated randomly.
+.Pp
 This command has the following alias:
 .Nm kstash .
 .Ed
index b7e9096f737ca107e4c019675b1e37ba523d70e6..793012baf4a1c5b0aaa9fda1966e8ed8378466b0 100644 (file)
@@ -1169,7 +1169,7 @@ princ_fs_encode(const char *in)
             s[k++] = c;
             break;
         default:
-            if (isalnum(c)) {
+            if (isalnum((unsigned char)c)) {
                 s[k++] = c;
             } else  {
                 s[k++] = '%';
index 86717f6f9e078042fd76382699cdc9a819f8dcaa..f2ce03c879cefec577a41cca05d410b39387094c 100644 (file)
@@ -120,7 +120,7 @@ string_encode_sz(const char *in)
         case '/':
             continue;
         default:
-            if (isalnum(c))
+            if (isalnum((unsigned char)c))
                 continue;
             sz += 2;
         }
index 4b2203f226799e459b049dd23d628043658052d9..df5362031f5ae72128eb35c963e8af2dc1d73821 100644 (file)
@@ -51,6 +51,7 @@
 #define KDC_AUTH_EVENT_CLIENT_NAME_UNAUTHORIZED        7   /* couldn't map GSS/PKINIT name to principal */
 #define KDC_AUTH_EVENT_PREAUTH_FAILED          8   /* generic PA failure */
 #define KDC_AUTH_EVENT_PREAUTH_SUCCEEDED       9   /* generic (non-long term key) PA success */
+#define KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY  10  /* PA failed to validate current long term key, but historic */
 
 /*
  * Audit keys to be queried using kdc_audit_getkv(). There are other keys
 #define KDC_REQUEST_KV_AUTH_EVENT              "#auth_event"           /* heim_number_t */
 #define KDC_REQUEST_KV_PA_NAME                 "pa"                    /* heim_string_t */
 #define KDC_REQUEST_KV_PA_ETYPE                        "pa-etype"              /* heim_number_t */
+#define KDC_REQUEST_KV_PA_SUCCEEDED_KVNO       "pa-succeeded-kvno"     /* heim_number_t */
+#define KDC_REQUEST_KV_PA_FAILED_KVNO          "pa-failed-kvno"        /* heim_number_t */
 #define KDC_REQUEST_KV_GSS_INITIATOR           "gss_initiator"         /* heim_string_t */
 #define KDC_REQUEST_KV_PKINIT_CLIENT_CERT      "pkinit_client_cert"    /* heim_string_t */
+#define KDC_REQUEST_KV_PA_HISTORIC_KVNO                "pa-historic-kvno"      /* heim_number_t */
 
 #endif /* HEIMDAL_KDC_KDC_AUDIT_H */
index 767d04f5c8c9a18f5cabfc6b157572f27b91e710..bf9a0bc55e9c4e050d5d4b47e141f9463bfd06a4 100644 (file)
@@ -168,6 +168,7 @@ struct astgs_request_desc {
     unsigned int rk_is_subkey : 1;
     unsigned int fast_asserted : 1;
     unsigned int explicit_armor_present : 1;
+    krb5_keyblock enc_ad_key;
 
     krb5_crypto armor_crypto;
     hdb_entry *armor_server;
index 1587f7fb2ac47f61cb52b7472e65122bf21d9fe3..26680e0e736454aa19c87a3d9469a0f2eea9f941 100644 (file)
@@ -696,75 +696,51 @@ pa_gss_finalize_pac(astgs_request_t r)
 }
 
 static krb5_error_code
-pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
+pa_enc_chal_decrypt_kvno(astgs_request_t r,
+                        krb5_enctype aenctype,
+                        krb5_data *pepper1client,
+                        krb5_data *pepper1kdc,
+                        krb5_data *pepper2,
+                        krb5_kvno kvno,
+                        EncryptedData *enc_data,
+                        krb5_keyblock *KDCchallengekey,
+                        struct Key **used_key)
 {
-    krb5_data pepper1, pepper2;
-    int invalidPassword = 0;
-    EncryptedData enc_data;
-    krb5_enctype aenctype;
+    unsigned int invalidKeys = 0;
     krb5_error_code ret;
-    struct Key *k;
-    size_t size;
-    int i;
+    const Keys *keys = NULL;
+    unsigned int i;
 
-    heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
-    
-    if (_kdc_is_anon_request(&r->req)) {
-       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-       kdc_log(r->context, r->config, 4, "ENC-CHALL doesn't support anon");
-       return ret;
-    }
-
-    if (r->client->flags.locked_out) {
-       ret = KRB5KDC_ERR_CLIENT_REVOKED;
-       kdc_log(r->context, r->config, 0,
-               "Client (%s) is locked out", r->cname);
-       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
-                             KDC_AUTH_EVENT_CLIENT_LOCKED_OUT);
-       return ret;
-    }
+    if (KDCchallengekey)
+       krb5_keyblock_zero(KDCchallengekey);
+    if (used_key)
+       *used_key = NULL;
 
-    ret = decode_EncryptedData(pa->padata_value.data,
-                              pa->padata_value.length,
-                              &enc_data,
-                              &size);
-    if (ret) {
-       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
-       _kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
-                  r->cname);
-       return ret;
+    keys = hdb_kvno2keys(r->context, r->client, kvno);
+    if (keys == NULL) {
+       return KRB5KDC_ERR_ETYPE_NOSUPP;
     }
 
-    pepper1.data = "clientchallengearmor";
-    pepper1.length = strlen(pepper1.data);
-    pepper2.data = "challengelongterm";
-    pepper2.length = strlen(pepper2.data);
-
-    krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
-
-    kdc_log(r->context, r->config, 5, "FAST armor enctype is: %d", (int)aenctype);
-
-    for (i = 0; i < r->client->keys.len; i++) {
+    for (i = 0; i < keys->len; i++) {
+       struct Key *k = &keys->val[i];
        krb5_crypto challengecrypto, longtermcrypto;
-       krb5_keyblock challengekey;
+       krb5_keyblock client_challengekey;
 
-       k = &r->client->keys.val[i];
-       
        ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
        if (ret)
            continue;
-       
+
        ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
-                                &pepper1, &pepper2, aenctype,
-                                &challengekey);
+                                pepper1client, pepper2, aenctype,
+                                &client_challengekey);
        if (ret) {
            krb5_crypto_destroy(r->context, longtermcrypto);
            continue;
        }
-       
-       ret = krb5_crypto_init(r->context, &challengekey, 0,
+
+       ret = krb5_crypto_init(r->context, &client_challengekey, 0,
                               &challengecrypto);
-       krb5_free_keyblock_contents(r->context, &challengekey);
+       krb5_free_keyblock_contents(r->context, &client_challengekey);
        if (ret) {
            krb5_crypto_destroy(r->context, longtermcrypto);
            continue;
@@ -773,7 +749,7 @@ pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
        ret = _krb5_validate_pa_enc_challenge(r->context,
                                              challengecrypto,
                                              KRB5_KU_ENC_CHALLENGE_CLIENT,
-                                             &enc_data,
+                                             enc_data,
                                              r->cname);
        krb5_crypto_destroy(r->context, challengecrypto);
        if (ret) {
@@ -783,10 +759,14 @@ pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
 
            krb5_crypto_destroy(r->context, longtermcrypto);
 
-           invalidPassword = (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY);
-           if (!invalidPassword) {
-               goto out;
-           }
+           if (ret != KRB5KRB_AP_ERR_BAD_INTEGRITY)
+               return ret;
+
+           invalidKeys += 1;
+
+           if (pepper1kdc == NULL)
+               /* The caller is not interessted in details */
+               continue;
 
            ret2 = krb5_enctype_to_string(r->context, k->key.keytype, &str);
            if (ret2)
@@ -800,78 +780,314 @@ pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
 
            continue;
        }
-    
-       /*
-        * Found a key that the client used, lets pick that as the reply key
-        */
 
-       krb5_free_keyblock_contents(r->context, &r->reply_key);
-       ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
-       if (ret) {
-           krb5_crypto_destroy(r->context, longtermcrypto);
-           goto out;
+       if (pepper1kdc == NULL) {
+           /* The caller is not interessted in details */
+           return 0;
        }
 
-       krb5_free_keyblock_contents(r->context, &challengekey);
+       heim_assert(KDCchallengekey != NULL,
+                   "KDCchallengekey pointer required with pepper1kdc");
+       heim_assert(used_key != NULL,
+                   "used_key pointer required with pepper1kdc");
 
        /*
         * Provide KDC authentication to the client, uses a different
         * challenge key (different pepper).
         */
 
-       pepper1.data = "kdcchallengearmor";
-       pepper1.length = strlen(pepper1.data);
-
        ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
-                                &pepper1, &pepper2, aenctype,
-                                &challengekey);
+                                pepper1kdc, pepper2, aenctype,
+                                KDCchallengekey);
        krb5_crypto_destroy(r->context, longtermcrypto);
        if (ret)
-           goto out;
+           return ret;
+
+       *used_key = k;
+       return 0;
+    }
+
+    if (invalidKeys == 0)
+       return KRB5KDC_ERR_ETYPE_NOSUPP;
+
+    return KRB5KDC_ERR_PREAUTH_FAILED;
+}
+
+static krb5_error_code
+pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
+{
+    krb5_kvno kvno = r->client->kvno;
+    krb5_data pepper1client, pepper1kdc, pepper2;
+    EncryptedData enc_data;
+    krb5_enctype aenctype;
+    krb5_error_code ret;
+    krb5_keyblock KDCchallengekey;
+    struct Key *k = NULL;
+    size_t size;
+
+    heim_assert(r->armor_crypto != NULL, "ENC-CHAL called for non FAST");
+
+    if (_kdc_is_anon_request(&r->req)) {
+       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+       kdc_log(r->context, r->config, 4, "ENC-CHAL doesn't support anon");
+       return ret;
+    }
+
+    if (r->client->flags.locked_out) {
+       ret = KRB5KDC_ERR_CLIENT_REVOKED;
+       kdc_log(r->context, r->config, 0,
+               "Client (%s) is locked out", r->cname);
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                             KDC_AUTH_EVENT_CLIENT_LOCKED_OUT);
+       return ret;
+    }
+
+    ret = decode_EncryptedData(pa->padata_value.data,
+                              pa->padata_value.length,
+                              &enc_data,
+                              &size);
+    if (ret) {
+       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+       _kdc_r_log(r, 4, "Failed to decode PA-DATA -- %s",
+                  r->cname);
+       return ret;
+    }
+
+    pepper1client.data = "clientchallengearmor";
+    pepper1client.length = strlen(pepper1client.data);
+    pepper1kdc.data = "kdcchallengearmor";
+    pepper1kdc.length = strlen(pepper1kdc.data);
+    pepper2.data = "challengelongterm";
+    pepper2.length = strlen(pepper2.data);
+
+    krb5_crypto_getenctype(r->context, r->armor_crypto, &aenctype);
+
+    kdc_log(r->context, r->config, 5, "FAST armor enctype is: %d", (int)aenctype);
+
+    ret = pa_enc_chal_decrypt_kvno(r, aenctype,
+                                  &pepper1client,
+                                  &pepper1kdc,
+                                  &pepper2,
+                                  kvno,
+                                  &enc_data,
+                                  &KDCchallengekey,
+                                  &k);
+    if (ret == KRB5KDC_ERR_ETYPE_NOSUPP) {
+       char *estr;
+       _kdc_set_e_text(r, "No key matching entype");
+       if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
+           estr = NULL;
+       if(estr == NULL)
+           _kdc_r_log(r, 4,
+                      "No client key matching ENC-CHAL (%d) -- %s",
+                      enc_data.etype, r->cname);
+       else
+           _kdc_r_log(r, 4,
+                      "No client key matching ENC-CHAL (%s) -- %s",
+                      estr, r->cname);
+       free(estr);
+       free_EncryptedData(&enc_data);
+       kdc_audit_setkv_number((kdc_request_t)r,
+                              KDC_REQUEST_KV_PA_FAILED_KVNO,
+                              kvno);
+       return ret;
+    }
+    if (ret == KRB5KRB_AP_ERR_SKEW) {
+       /*
+        * Logging happens inside of
+        * _krb5_validate_pa_enc_challenge()
+        * via pa_enc_chal_decrypt_kvno()
+        */
+
+       free_EncryptedData(&enc_data);
+       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                              KDC_AUTH_EVENT_CLIENT_TIME_SKEW);
+
+       /*
+        * The following is needed to make windows clients to
+        * retry using the timestamp in the error message, if
+        * there is a e_text, they become unhappy.
+        */
+       r->e_text = NULL;
+       return ret;
+    }
+    if (ret == KRB5KDC_ERR_PREAUTH_FAILED) {
+       krb5_error_code hret = ret;
+       int hi;
+
+       /*
+        * Logging happens inside of
+        * via pa_enc_chal_decrypt_kvno()
+        */
+
+       kdc_audit_setkv_number((kdc_request_t)r,
+                              KDC_REQUEST_KV_PA_FAILED_KVNO,
+                              kvno);
+
+       /*
+        * Check if old and older keys are
+        * able to decrypt.
+        */
+       for (hi = 1; hi < 3; hi++) {
+           krb5_kvno hkvno;
+
+           if (hi >= kvno) {
+               break;
+           }
+
+           hkvno = kvno - hi;
+           hret = pa_enc_chal_decrypt_kvno(r, aenctype,
+                                           &pepper1client,
+                                           NULL, /* pepper1kdc */
+                                           &pepper2,
+                                           hkvno,
+                                           &enc_data,
+                                           NULL, /* KDCchallengekey */
+                                           NULL); /* used_key */
+           if (hret == 0) {
+               kdc_audit_setkv_number((kdc_request_t)r,
+                                      KDC_REQUEST_KV_PA_HISTORIC_KVNO,
+                                      hkvno);
+               break;
+           }
+           if (hret == KRB5KDC_ERR_ETYPE_NOSUPP) {
+               break;
+           }
+       }
 
-       ret = krb5_crypto_init(r->context, &challengekey, 0, &challengecrypto);
-       krb5_free_keyblock_contents(r->context, &challengekey);
+       free_EncryptedData(&enc_data);
+
+       if (hret == 0)
+           kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                                  KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY);
+       else
+           kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                                  KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
+
+       return ret;
+    }
+    free_EncryptedData(&enc_data);
+    if (ret == 0) {
+       krb5_crypto challengecrypto;
+       char *estr = NULL;
+       char *astr = NULL;
+       char *kstr = NULL;
+
+       ret = krb5_crypto_init(r->context, &KDCchallengekey, 0, &challengecrypto);
+       krb5_free_keyblock_contents(r->context, &KDCchallengekey);
        if (ret)
-           goto out;
+           return ret;
 
        ret = _krb5_make_pa_enc_challenge(r->context, challengecrypto,
                                          KRB5_KU_ENC_CHALLENGE_KDC,
                                          r->rep.padata);
        krb5_crypto_destroy(r->context, challengecrypto);
        if (ret)
-           goto out;
-                                           
-        if (ret == 0)
-            ret = set_salt_padata(r->context, r->config,
-                                 r->rep.padata, k);
+           return ret;
+
+       ret = set_salt_padata(r->context, r->config, r->rep.padata, k);
+       if (ret)
+           return ret;
 
        /*
-        * Success
+        * Found a key that the client used, lets pick that as the reply key
         */
+
+       krb5_free_keyblock_contents(r->context, &r->reply_key);
+       ret = krb5_copy_keyblock_contents(r->context, &k->key, &r->reply_key);
+       if (ret)
+           return ret;
+
+       if (krb5_enctype_to_string(r->context, (int)aenctype, &astr))
+           astr = NULL;
+       if (krb5_enctype_to_string(r->context, enc_data.etype, &estr))
+           estr = NULL;
+       if (krb5_enctype_to_string(r->context, k->key.keytype, &kstr))
+           kstr = NULL;
+       _kdc_r_log(r, 4, "ENC-CHAL Pre-authentication succeeded -- %s "
+                  "using armor=%s enc=%s key=%s",
+                  r->cname,
+                  astr ? astr : "unknown enctype",
+                  estr ? estr : "unknown enctype",
+                  kstr ? kstr : "unknown enctype");
        kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
                               KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
-       goto out;
+       kdc_audit_setkv_number((kdc_request_t)r,
+                              KDC_REQUEST_KV_PA_SUCCEEDED_KVNO,
+                              kvno);
+       return 0;
     }
 
-    if (invalidPassword) {
-       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
-                              KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
-       ret = KRB5KDC_ERR_PREAUTH_FAILED;
-    } else {
-       ret = KRB5KDC_ERR_ETYPE_NOSUPP;
+    return ret;
+}
+
+static krb5_error_code
+pa_enc_ts_decrypt_kvno(astgs_request_t r,
+                      krb5_kvno kvno,
+                      const EncryptedData *enc_data,
+                      krb5_data *ts_data,
+                      Key **_pa_key)
+{
+    krb5_error_code ret;
+    krb5_crypto crypto;
+    Key *pa_key = NULL;
+    const Keys *keys = NULL;
+
+    if (_pa_key)
+       *_pa_key = NULL;
+
+    krb5_data_zero(ts_data);
+
+    keys = hdb_kvno2keys(r->context, r->client, kvno);
+    if (keys == NULL) {
+       return KRB5KDC_ERR_ETYPE_NOSUPP;
+    }
+    ret = hdb_enctype2key(r->context, r->client, keys,
+                         enc_data->etype, &pa_key);
+    if(ret){
+       return KRB5KDC_ERR_ETYPE_NOSUPP;
     }
- out:
-    free_EncryptedData(&enc_data);
 
-    return ret;
+ try_next_key:
+    ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
+    if (ret) {
+       const char *msg = krb5_get_error_message(r->context, ret);
+       _kdc_r_log(r, 4, "krb5_crypto_init failed: %s", msg);
+       krb5_free_error_message(r->context, msg);
+       return ret;
+    }
+
+    ret = krb5_decrypt_EncryptedData(r->context,
+                                    crypto,
+                                    KRB5_KU_PA_ENC_TIMESTAMP,
+                                    enc_data,
+                                    ts_data);
+    krb5_crypto_destroy(r->context, crypto);
+    /*
+     * Since the user might have several keys with the same
+     * enctype but with diffrent salting, we need to try all
+     * the keys with the same enctype.
+     */
+    if (ret) {
+       ret = hdb_next_enctype2key(r->context, r->client, keys,
+                                  enc_data->etype, &pa_key);
+       if (ret == 0)
+           goto try_next_key;
+
+       return KRB5KDC_ERR_PREAUTH_FAILED;
+    }
+
+    if (_pa_key)
+       *_pa_key = pa_key;
+    return 0;
 }
 
 static krb5_error_code
 pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
 {
+    krb5_kvno kvno = r->client->kvno;
     EncryptedData enc_data;
     krb5_error_code ret;
-    krb5_crypto crypto;
     krb5_data ts_data;
     PA_ENC_TS_ENC p;
     size_t len;
@@ -910,12 +1126,10 @@ pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
        goto out;
     }
        
-    ret = hdb_enctype2key(r->context, r->client, NULL,
-                         enc_data.etype, &pa_key);
-    if(ret){
+    ret = pa_enc_ts_decrypt_kvno(r, kvno, &enc_data, &ts_data, &pa_key);
+    if (ret == KRB5KDC_ERR_ETYPE_NOSUPP) {
        char *estr;
        _kdc_set_e_text(r, "No key matching entype");
-       ret = KRB5KDC_ERR_ETYPE_NOSUPP;
        if(krb5_enctype_to_string(r->context, enc_data.etype, &estr))
            estr = NULL;
        if(estr == NULL)
@@ -928,36 +1142,50 @@ pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
                       estr, r->cname);
        free(estr);
        free_EncryptedData(&enc_data);
+       kdc_audit_setkv_number((kdc_request_t)r,
+                              KDC_REQUEST_KV_PA_FAILED_KVNO,
+                              kvno);
        goto out;
     }
-
- try_next_key:
-    ret = krb5_crypto_init(r->context, &pa_key->key, 0, &crypto);
-    if (ret) {
-       const char *msg = krb5_get_error_message(r->context, ret);
-       _kdc_r_log(r, 4, "krb5_crypto_init failed: %s", msg);
-       krb5_free_error_message(r->context, msg);
-       free_EncryptedData(&enc_data);
-       goto out;
-    }
-
-    ret = krb5_decrypt_EncryptedData (r->context,
-                                     crypto,
-                                     KRB5_KU_PA_ENC_TIMESTAMP,
-                                     &enc_data,
-                                     &ts_data);
-    krb5_crypto_destroy(r->context, crypto);
-    /*
-     * Since the user might have several keys with the same
-     * enctype but with diffrent salting, we need to try all
-     * the keys with the same enctype.
-     */
-    if(ret){
+    if (ret == KRB5KDC_ERR_PREAUTH_FAILED) {
        krb5_error_code ret2;
        const char *msg = krb5_get_error_message(r->context, ret);
+       krb5_error_code hret = ret;
+       int hi;
+
+       kdc_audit_setkv_number((kdc_request_t)r,
+                              KDC_REQUEST_KV_PA_FAILED_KVNO,
+                              kvno);
 
-       ret2 = krb5_enctype_to_string(r->context,
-                                     pa_key->key.keytype, &str);
+       /*
+        * Check if old and older keys are
+        * able to decrypt.
+        */
+       for (hi = 1; hi < 3; hi++) {
+           krb5_kvno hkvno;
+
+           if (hi >= kvno) {
+               break;
+           }
+
+           hkvno = kvno - hi;
+           hret = pa_enc_ts_decrypt_kvno(r, hkvno,
+                                         &enc_data,
+                                         &ts_data,
+                                         NULL); /* pa_key */
+           if (hret == 0) {
+               krb5_data_free(&ts_data);
+               kdc_audit_setkv_number((kdc_request_t)r,
+                                      KDC_REQUEST_KV_PA_HISTORIC_KVNO,
+                                      hkvno);
+               break;
+           }
+           if (hret == KRB5KDC_ERR_ETYPE_NOSUPP) {
+               break;
+           }
+       }
+
+       ret2 = krb5_enctype_to_string(r->context, enc_data.etype, &str);
        if (ret2)
            str = NULL;
        _kdc_r_log(r, 2, "Failed to decrypt PA-DATA -- %s "
@@ -966,12 +1194,13 @@ pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
        krb5_xfree(str);
        krb5_free_error_message(r->context, msg);
        kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_PA_ETYPE,
-                              pa_key->key.keytype);
-       kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
-                              KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
-       if(hdb_next_enctype2key(r->context, r->client, NULL,
-                               enc_data.etype, &pa_key) == 0)
-           goto try_next_key;
+                              enc_data.etype);
+       if (hret == 0)
+           kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                                  KDC_AUTH_EVENT_HISTORIC_LONG_TERM_KEY);
+       else
+           kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
+                                  KDC_AUTH_EVENT_WRONG_LONG_TERM_KEY);
 
        free_EncryptedData(&enc_data);
 
@@ -1017,8 +1246,7 @@ pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
     }
     free_PA_ENC_TS_ENC(&p);
 
-    ret = set_salt_padata(r->context, r->config,
-                         r->rep.padata, pa_key);
+    ret = set_salt_padata(r->context, r->config, r->rep.padata, pa_key);
     if (ret == 0)
         ret = krb5_copy_keyblock_contents(r->context, &pa_key->key, &r->reply_key);
     if (ret)
@@ -1034,6 +1262,9 @@ pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
                           pa_key->key.keytype);
     kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
                           KDC_AUTH_EVENT_VALIDATED_LONG_TERM_KEY);
+    kdc_audit_setkv_number((kdc_request_t)r,
+                          KDC_REQUEST_KV_PA_SUCCEEDED_KVNO,
+                          kvno);
 
     ret = 0;
 
@@ -2059,7 +2290,10 @@ add_enc_pa_rep(astgs_request_t r)
                          KRB5_PADATA_REQ_ENC_PA_REP, cdata.data, cdata.length);
     if (ret)
        return ret;
-    
+
+    if (!r->config->enable_fast)
+       return 0;
+
     return krb5_padata_add(r->context, r->ek.encrypted_pa_data,
                           KRB5_PADATA_FX_FAST, NULL, 0);
 }
@@ -2368,12 +2602,18 @@ _kdc_as_rep(astgs_request_t r)
 
            if (!r->armor_crypto && (pat[n].flags & PA_REQ_FAST))
                continue;
+           if (pat[n].type == KRB5_PADATA_PKINIT_KX && !r->config->allow_anonymous)
+               continue;
            if (pat[n].type == KRB5_PADATA_ENC_TIMESTAMP) {
                if (r->armor_crypto && !r->config->enable_armored_pa_enc_timestamp)
                    continue;
                if (!r->armor_crypto && !r->config->enable_unarmored_pa_enc_timestamp)
                    continue;
            }
+           if (pat[n].type == KRB5_PADATA_FX_FAST && !r->config->enable_fast)
+               continue;
+           if (pat[n].type == KRB5_PADATA_GSS && !r->config->enable_gss_preauth)
+               continue;
 
            ret = krb5_padata_add(r->context, r->rep.padata,
                                  pat[n].type, NULL, 0);
@@ -2869,6 +3109,7 @@ out:
     if (r->armor_server)
        _kdc_free_ent(r->context, r->armor_serverdb, r->armor_server);
     krb5_free_keyblock_contents(r->context, &r->reply_key);
+    krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
     krb5_free_keyblock_contents(r->context, &r->session_key);
     krb5_free_keyblock_contents(r->context, &r->strengthen_key);
     krb5_pac_free(r->context, r->pac);
index c3b033f58c25663dad1241f43e9a02871b360b13..b01aa52628363f5a0c00ca6a47208f0a335323a7 100644 (file)
@@ -561,7 +561,8 @@ tgs_make_reply(astgs_request_t r,
     rep->pvno = 5;
     rep->msg_type = krb_tgs_rep;
 
-    et->authtime = tgt->authtime;
+    if (et->authtime == 0)
+        et->authtime = tgt->authtime;
     _kdc_fix_time(&b->till);
     et->endtime = min(tgt->endtime, *b->till);
     ALLOC(et->starttime);
@@ -936,8 +937,7 @@ tgs_parse_request(astgs_request_t r,
                  const char *from,
                  const struct sockaddr *from_addr,
                  time_t **csec,
-                 int **cusec,
-                 AuthorizationData **auth_data)
+                 int **cusec)
 {
     krb5_kdc_configuration *config = r->config;
     KDC_REQ_BODY *b = &r->req.req_body;
@@ -948,16 +948,13 @@ tgs_parse_request(astgs_request_t r,
     krb5_auth_context ac = NULL;
     krb5_flags ap_req_options;
     krb5_flags verify_ap_req_flags = 0;
-    krb5_crypto crypto;
     krb5uint32 krbtgt_kvno;     /* kvno used for the PA-TGS-REQ AP-REQ Ticket */
     krb5uint32 krbtgt_kvno_try;
     int kvno_search_tries = 4;  /* number of kvnos to try when tkt_vno == 0 */
     const Keys *krbtgt_keys;/* keyset for TGT tkt_vno */
     Key *tkey;
     krb5_keyblock *subkey = NULL;
-    unsigned usage;
 
-    *auth_data = NULL;
     *csec  = NULL;
     *cusec = NULL;
 
@@ -1140,7 +1137,6 @@ next_kvno:
        goto out;
     }
 
-    usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
     r->rk_is_subkey = 1;
 
     ret = krb5_auth_con_getremotesubkey(r->context, ac, &subkey);
@@ -1152,7 +1148,6 @@ next_kvno:
        goto out;
     }
     if(subkey == NULL){
-       usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
        r->rk_is_subkey = 0;
 
        ret = krb5_auth_con_getkey(r->context, ac, &subkey);
@@ -1178,45 +1173,13 @@ next_kvno:
     if (ret)
        goto out;
 
+    krb5_free_keyblock_contents(r->context,  &r->enc_ad_key);
     if (b->enc_authorization_data) {
-       krb5_data ad;
-
-       ret = krb5_crypto_init(r->context, &r->reply_key, 0, &crypto);
-       if (ret) {
-           const char *msg = krb5_get_error_message(r->context, ret);
-           krb5_auth_con_free(r->context, ac);
-           kdc_log(r->context, config, 4, "krb5_crypto_init failed: %s", msg);
-           krb5_free_error_message(r->context, msg);
-           goto out;
-       }
-       ret = krb5_decrypt_EncryptedData (r->context,
-                                         crypto,
-                                         usage,
-                                         b->enc_authorization_data,
-                                         &ad);
-       krb5_crypto_destroy(r->context, crypto);
-       if(ret){
-           krb5_auth_con_free(r->context, ac);
-           kdc_log(r->context, config, 4,
-                   "Failed to decrypt enc-authorization-data");
-           ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
-           goto out;
-       }
-       ALLOC(*auth_data);
-       if (*auth_data == NULL) {
-           krb5_auth_con_free(r->context, ac);
-           ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
-           goto out;
-       }
-       ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL);
-       if(ret){
-           krb5_auth_con_free(r->context, ac);
-           free(*auth_data);
-           *auth_data = NULL;
-           kdc_log(r->context, config, 4, "Failed to decode authorization data");
-           ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
+       ret = krb5_copy_keyblock_contents(r->context,
+                                         &r->reply_key,
+                                         &r->enc_ad_key);
+       if (ret)
            goto out;
-       }
     }
 
     ret = validate_fast_ad(r, r->ticket->ticket.authorization_data);
@@ -1375,7 +1338,6 @@ _kdc_db_fetch_client(krb5_context context,
 static krb5_error_code
 tgs_build_reply(astgs_request_t priv,
                krb5_enctype krbtgt_etype,
-               AuthorizationData **auth_data,
                const struct sockaddr *from_addr)
 {
     krb5_context context = priv->context;
@@ -1405,6 +1367,7 @@ tgs_build_reply(astgs_request_t priv,
         krb5_principal_get_comp_string(context, priv->krbtgt->principal, 1);
     char **capath = NULL;
     size_t num_capath = 0;
+    AuthorizationData *auth_data = NULL;
 
     HDB *krbtgt_outdb;
     hdb_entry *krbtgt_out = NULL;
@@ -1964,6 +1927,60 @@ server_lookup:
     if (ret)
        goto out;
 
+    if (b->enc_authorization_data) {
+       unsigned auth_data_usage;
+       krb5_crypto crypto;
+       krb5_data ad;
+
+       if (priv->rk_is_subkey != 0) {
+           auth_data_usage = KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY;
+       } else {
+           auth_data_usage = KRB5_KU_TGS_REQ_AUTH_DAT_SESSION;
+       }
+
+       ret = krb5_crypto_init(context, &priv->enc_ad_key, 0, &crypto);
+       if (ret) {
+           const char *msg = krb5_get_error_message(context, ret);
+           kdc_audit_addreason((kdc_request_t)priv,
+                               "krb5_crypto_init() failed for "
+                               "enc_authorization_data");
+           kdc_log(context, config, 4, "krb5_crypto_init failed: %s", msg);
+           krb5_free_error_message(context, msg);
+           goto out;
+       }
+       ret = krb5_decrypt_EncryptedData(context,
+                                        crypto,
+                                        auth_data_usage,
+                                        b->enc_authorization_data,
+                                        &ad);
+       krb5_crypto_destroy(context, crypto);
+       if(ret){
+           kdc_audit_addreason((kdc_request_t)priv,
+                               "Failed to decrypt enc-authorization-data");
+           kdc_log(context, config, 4,
+                   "Failed to decrypt enc-authorization-data");
+           ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
+           goto out;
+       }
+       ALLOC(auth_data);
+       if (auth_data == NULL) {
+           krb5_data_free(&ad);
+           ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
+           goto out;
+       }
+       ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
+       krb5_data_free(&ad);
+       if(ret){
+           free(auth_data);
+           auth_data = NULL;
+           kdc_audit_addreason((kdc_request_t)priv,
+                               "Failed to decode authorization data");
+           kdc_log(context, config, 4, "Failed to decode authorization data");
+           ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
+           goto out;
+       }
+    }
+
     /*
      * Check flags
      */
@@ -2068,7 +2085,7 @@ server_lookup:
                         &tkey_sign->key,
                         &sessionkey,
                         kvno,
-                        *auth_data,
+                        auth_data,
                          tgt_realm,
                         rodc_id,
                         add_ticket_sig);
@@ -2088,6 +2105,11 @@ out:
     krb5_free_principal(context, krbtgt_out_principal);
     free(ref_realm);
 
+    if (auth_data) {
+       free_AuthorizationData(auth_data);
+       free(auth_data);
+    }
+
     free_EncTicketPart(&adtkt);
 
     krb5_pac_free(context, user2user_pac);
@@ -2108,7 +2130,6 @@ _kdc_tgs_rep(astgs_request_t r)
     const char *from = r->from;
     struct sockaddr *from_addr = r->addr;
     int datagram_reply = r->datagram_reply;
-    AuthorizationData *auth_data = NULL;
     krb5_error_code ret;
     int i = 0;
     const PA_DATA *tgs_req, *pa;
@@ -2146,8 +2167,7 @@ _kdc_tgs_rep(astgs_request_t r)
     ret = tgs_parse_request(r, tgs_req,
                            &krbtgt_etype,
                            from, from_addr,
-                           &csec, &cusec,
-                           &auth_data);
+                           &csec, &cusec);
     if (ret == HDB_ERR_NOT_FOUND_HERE) {
        /* kdc_log() is called in tgs_parse_request() */
        goto out;
@@ -2171,7 +2191,6 @@ _kdc_tgs_rep(astgs_request_t r)
 
     ret = tgs_build_reply(r,
                          krbtgt_etype,
-                         &auth_data,
                          from_addr);
     if (ret) {
        kdc_log(r->context, config, 4,
@@ -2248,6 +2267,7 @@ out:
     if (r->explicit_armor_pac)
        krb5_pac_free(r->context, r->explicit_armor_pac);
     krb5_free_keyblock_contents(r->context, &r->reply_key);
+    krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
     krb5_free_keyblock_contents(r->context, &r->strengthen_key);
 
     if (r->ticket)
@@ -2264,10 +2284,5 @@ out:
     _kdc_free_fast_state(&r->fast);
     krb5_pac_free(r->context, r->pac);
 
-    if (auth_data) {
-       free_AuthorizationData(auth_data);
-       free(auth_data);
-    }
-
     return ret;
 }
index a88de097a9b598d3cd88a41f70ab186f47e7e706..6145fc8e8e1da3f4bc0a2377ff073bc0468865c3 100644 (file)
@@ -533,6 +533,15 @@ validate_constrained_delegation(astgs_request_t r)
            goto out;
     }
 
+    if (b->enc_authorization_data && r->rk_is_subkey == 0) {
+       krb5_free_keyblock_contents(r->context, &r->enc_ad_key);
+       ret = krb5_copy_keyblock_contents(r->context,
+                                         &evidence_tkt.key,
+                                         &r->enc_ad_key);
+       if (ret)
+           goto out;
+    }
+
     kdc_log(r->context, r->config, 4, "constrained delegation for %s "
            "from %s (%s) to %s", s4ucname, r->cname, s4usname, r->sname);
 
@@ -555,6 +564,8 @@ validate_constrained_delegation(astgs_request_t r)
 
     r->pac_attributes = s4u_pac_attributes;
 
+    r->et.authtime = evidence_tkt.authtime;
+
 out:
     if (s4u_client)
        _kdc_free_ent(r->context, s4u_clientdb, s4u_client);
index dbf4c4212372bc847d87b8ff6a0270d535d6baca..200af16c16daa03979a23ae8e1c69f6b7bbcd695 100644 (file)
@@ -523,7 +523,7 @@ string_encode_sz(const char *in)
                 sz += 2;
             break;
         default:
-            if (!isalnum(c))
+            if (!isalnum((unsigned char)c))
                 sz += 2;
         }
         first = 0;
index b9c77c235055ca7e8d4fe78ff18e58c95b88381c..f374a7c0628910de16bb6712ee7d6c87e35db963 100644 (file)
@@ -273,6 +273,170 @@ is given,
 will set up new credentials caches, and AFS PAG, and then run the given
 command.
 When it finishes the credentials will be removed.
+.Sh CREDENTIALS CACHE TYPES
+Heimdal supports a number of credentials cache types:
+.Bl -tag -width Ds
+.It FILE
+Uses a file per-cache with a binary format common to other Kerberos
+implementations.
+.It DIR
+Uses a directory with multiple files, one per-cache in a collection.
+.It SCC
+Uses a SQLite3 database with multiple caches in the database.
+.It KEYRING
+Uses a Linux keyring.
+.It KCM
+Uses a inter-process communications (IPC) to talk to a daemon typically named
+.Nm kcm .
+.It API
+Uses KCM or else a shared object that implements the "CCAPI".
+.It MEMORY
+Uses in-process memory (which disappears on process exit, so this if of little
+use in this program,
+.Nm
+).
+.El
+.Sh CREDENTIALS CACHE COLLECTIONS
+Every credentials cache's name consists of its cache type (e.g.,
+FILE), a possibly-optional collection name, and a possibly
+optional "subsidiary" name naming a single cache in the
+collection.
+.Pp
+The convention in Heimdal is that a cache's subsidiary cache name
+is the name of the client principal whose credentials are
+expected to be stored and found in that cache, with the following
+characters replaced with a hyphen: slash, backslash, colon, and
+plus.
+.Pp
+The caches in a credentials cache collection can be listed by the
+.Xr klist 1
+command.
+The
+.Sq FILE
+credentials cache type supports listing of caches in the
+collection only when the
+.Ql enable_file_cache_iteration
+is set to
+.Ql yes
+in the
+.Ql [libdefaults]
+section of
+.Xr krb5.conf 5 .
+.Sh CREDENTIALS CACHE NAMES
+The general syntax for credentials cache names is
+.Dl TYPE:[collection-name][:subsidiary]
+except that for the FILE type it is
+.Dl FILE:collection-name[+subsidiary]
+and for the KEYRING type it is:
+.Dl KEYRING:[anchor:][collection[:subsidiary]]
+where the collection name is free-form and the anchor is one of
+.Sq process ,
+.Sq thread ,
+or
+.Sq legacy .
+.Pp
+The collection name is always absent for the
+.Ql MEMORY
+credentials cache type.
+.Pp
+When the collection name is absent then the default collection
+for the given credentials cache type is used, which are:
+.Bl -tag -compact
+.It Ql /tmp/krb5cc_{UID}
+for FILE caches, where {UID} is a numeric user ID
+.It Ql /tmp/krb5cc_{UID}_dir
+for DIR caches, where {UID} is a numeric user ID
+.It Ql /tmp/krb5scc_{UID}
+for SCC caches, where {UID} is a numeric user ID, and where the
+named file is a SQLite3 database file
+.It Ql {UID}
+for KCM caches, where {UID} is the user's numeric user ID
+.It <implementation-specific>
+for API (CCAPI) credentials caches
+.El
+.Pp
+The collection name is only optional for:
+.Ql DIR ,
+.Ql SCC ,
+.Ql KCM ,
+.Ql KEYRING
+and
+.Ql API
+credentials cache types.
+.Sh EXAMPLE CREDENTIALS CACHE NAMES
+.Bl -tag -width Ds
+.It Ql FILE:/tmp/cc
+this is a FILE cache in a file named
+.Ql /tmp/cc
+(the default would be
+.Ql /tmp/krb5cc_{UID} )
+.It Ql FILE:/tmp/cc+jane@TEST.H5L.SE
+.It Ql DIR:/tmp/ccdir
+this is a FILE cache named by
+.Ql /tmp/krb5cc_{UID}_dir/primary
+which will be of the form
+.Ql /tmp/ccdir/tkt.XXXXXX 
+.It Ql DIR:/tmp/ccdir:jane@TEST.H5L.SE
+this is a FILE ccache named
+.Ql /tmp/ccdir/tkt.jane@TEST.H5L.SE 
+.It Ql DIR::jane@TEST.H5L.SE
+this is a FILE ccache named
+.Ql /tmp/krb5cc_{UID}_dir/tkt.jane@TEST.H5L.SE
+where {UID} is the user's numeric identifier
+.It Ql SCC:
+this is the current primary cache in the SQLite3 database named
+.Ql /tmp/krb5scc_{UID}
+.It Ql SCC:/tmp/ccdb
+this is the current primary cache in the SQLite3 database named
+.Ql /tmp/ccdb
+.It Ql SCC:/tmp/ccdb:jane@TEST.H5L.SE
+this is the cache
+.Dq named jane@TEST.H5L.SE
+in the SQLite3 database
+named
+.Ql /tmp/ccdb
+.It Ql SCC::jane@TEST.H5L.SE
+this is the cache named
+.Dq jane@TEST.H5L.SE
+in the SQLite3 database named
+.Ql /tmp/krb5scc_{UID}
+.It Ql KEYRING:
+this is the primary cache in the default KEYRING collection for
+the running user
+.It Ql KEYRING:foo
+this is the primary cache in the KEYRING collection named
+.Dq foo
+.It Ql KEYRING:foo:jane@TEST.H5L.SE
+this is the cache named
+.Dq jane@TEST.H5L.SE
+in the KEYRING collection named
+.Dq foo
+.It Ql KCM:
+this is the primary cache in the default KCM collection for the
+running user
+.It Ql KCM:12345
+this is the primary cache in the default KCM collection for the
+user whose numeric identifier is 12345
+.It Ql KCM:jane@TEST.H5L.SE
+this is the cache named
+.Dq jane@TEST.H5L.SE
+in the default KCM collection for the running user
+.It Ql KCM:12345:jane@TEST.H5L.SE
+this is the cache named
+.Dq jane@TEST.H5L.SE
+in the default KCM collection for the given user
+.It Ql API:
+this is the primary cache in the default API collection for the
+running user
+.It Ql API:foo
+this is the primary cache in the API collection named
+.Dq foo
+.It Ql API:foo:jane@TEST.H5L.SE
+this is the cache named
+.Dq jane@TEST.H5L.SE
+in the KEYRING collection named
+.Dq foo
+.El
 .Sh ENVIRONMENT
 .Bl -tag -width Ds
 .It Ev KRB5CCNAME
@@ -290,6 +454,7 @@ the default being
 .Xr kdestroy 1 ,
 .Xr klist 1 ,
 .Xr kswitch 1 ,
+.Xr kcm 8 ,
 .Xr krb5_appdefault 3 ,
 .Xr krb5.conf 5
 .\".Sh STANDARDS
index a374817a06771ca8119070e52c80a6093d99736f..7f754c09fd45d0654f4888b38c27ee6827041158 100644 (file)
@@ -1640,9 +1640,13 @@ main(int argc, char **argv)
 
     ret = krb5_init_context(&context);
     if (ret == KRB5_CONFIG_BADFORMAT)
-       errx(1, "krb5_init_context failed to parse configuration file");
+       krb5_err(context, 1, ret, "Failed to parse configuration file");
+    else if (ret == EISDIR)
+        /* We use EISDIR to mean "not a regular file" */
+       krb5_errx(context, 1,
+                  "Failed to read configuration file: not a regular file");
     else if (ret)
-       errx(1, "krb5_init_context failed: %d", ret);
+       krb5_err(context, 1, ret, "Failed to read configuration file");
 
     if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
        usage(1);
index 40c37fbbb9461c040f9cc43d2b17dcb23bb0a86a..9ef6ffd23a2244da31e11e906ab6ee8c538d2b32 100644 (file)
@@ -305,7 +305,7 @@ loop (unsigned char *buf, size_t len, int indent)
                s = str.data;
                printf("\"");
                for (n = 0; n < str.length; n++) {
-                   if (isprint((int)s[n]))
+                   if (isprint(s[n]))
                        printf ("%c", s[n]);
                    else
                        printf ("#%02x", s[n]);
index 06dc6bb701b41bb0a7159452d00a4561d758f5fa..a660aaed846221f459d3725d039085c7e21a3f7d 100644 (file)
@@ -594,7 +594,7 @@ generate_constant (const Symbol *s)
        gen_upper = strdup(s->gen_name);
        len = strlen(gen_upper);
        for (i = 0; i < len; i++)
-           gen_upper[i] = toupper((int)s->gen_name[i]);
+           gen_upper[i] = toupper((unsigned char)s->gen_name[i]);
 
        fprintf (headerfile, "} */\n");
        fprintf (headerfile,
index 963569ca1eb5640d3a482543c4f28dbfb8b2ebd5..b1675ea5f141e1db5399dc6b6683c37cd004ebc6 100644 (file)
@@ -358,7 +358,7 @@ is_absolute_path(const char *path)
 
     /* A drive letter path might be absolute */
     if (len > 3
-         && isalpha(path[0])
+         && isalpha((unsigned char)path[0])
          && path[1] == ':'
          && ISPATHSEP(path[2]))
         return 1;
@@ -414,9 +414,9 @@ heim_config_parse_debug(struct fileptr *f,
             *err_message = "unmatched }";
             return 2048;
         } else if (strncmp(p, "include", sizeof("include") - 1) == 0 &&
-            isspace(p[sizeof("include") - 1])) {
+            isspace((unsigned char)p[sizeof("include") - 1])) {
             p += sizeof("include");
-            while (isspace(*p))
+            while (isspace((unsigned char)*p))
                 p++;
             if (!is_absolute_path(p)) {
                 heim_set_error_message(f->context, HEIM_ERR_CONFIG_BADFORMAT,
@@ -428,9 +428,9 @@ heim_config_parse_debug(struct fileptr *f,
             if (ret)
                 return ret;
         } else if (strncmp(p, "includedir", sizeof("includedir") - 1) == 0 &&
-            isspace(p[sizeof("includedir") - 1])) {
+            isspace((unsigned char)p[sizeof("includedir") - 1])) {
             p += sizeof("includedir");
-            while (isspace(*p))
+            while (isspace((unsigned char)*p))
                 p++;
             if (!is_absolute_path(p)) {
                 heim_set_error_message(f->context, HEIM_ERR_CONFIG_BADFORMAT,
@@ -508,7 +508,7 @@ heim_config_parse_dir_multi(heim_context context,
              * so we're safe.  Anyone changing this if condition here should
              * be aware.
              */
-            if (!isalnum(*p) && *p != '_' && *p != '-' &&
+            if (!isalnum((unsigned char)*p) && *p != '_' && *p != '-' &&
                 strcmp(p, ".conf") != 0) {
                 is_valid = 0;
                 break;
@@ -535,6 +535,22 @@ heim_config_parse_dir_multi(heim_context context,
     return 0;
 }
 
+static int
+is_devnull(struct stat *st)
+{
+#ifdef WIN32
+    return 0;
+#else
+    struct stat devnullst;
+
+    if (stat("/dev/null", &devnullst) == -1)
+        return 0;
+    return st->st_dev == devnullst.st_dev && st->st_ino == devnullst.st_ino;
+#endif
+}
+
+HEIMDAL_THREAD_LOCAL int config_include_depth = 0;
+
 /**
  * Parse a configuration file and add the result into res. This
  * interface can be used to parse several configuration files into one
@@ -548,8 +564,6 @@ heim_config_parse_dir_multi(heim_context context,
  * @ingroup heim_support
  */
 
-HEIMDAL_THREAD_LOCAL int config_include_depth = 0;
-
 heim_error_code
 heim_config_parse_file_multi(heim_context context,
                              const char *fname,
@@ -630,7 +644,7 @@ heim_config_parse_file_multi(heim_context context,
             goto out;
         }
 
-        if (!S_ISREG(st.st_mode)) {
+        if (!S_ISREG(st.st_mode) && !is_devnull(&st)) {
             (void) fclose(f.f);
             heim_set_error_message(context, EISDIR, "not a regular file %s: %s",
                                    fname, strerror(EISDIR));
index 2376a518ee7f287775fd6d7a93ae4457c33288dd..3dfed48fdac8c56ba517a9e342bf07e356cf081e 100644 (file)
@@ -64,7 +64,7 @@ _warnerr(heim_context context, int do_errtext,
            return ENOMEM;
        *arg++ = msg;
     }
-    if (context && do_errtext) {
+    if (do_errtext) {
        strlcat(xfmt, "%s", sizeof(xfmt));
 
        err_str = heim_get_error_message(context, code);
index 372e72dd5da8724a6976374cb5583045941d596e..3151efe4289f35ab41b27857c925f4b9ed768f35 100644 (file)
@@ -542,7 +542,8 @@ gss_name_to_oid(const char *name)
        gss_OID oid = GSS_C_NO_OID;
        size_t namelen = strlen(name);
 
-       if (isdigit(name[0]) && _gss_string_to_oid(name, &oid) == 0)
+       if (isdigit((unsigned char)name[0]) &&
+           _gss_string_to_oid(name, &oid) == 0)
                return oid;
 
        _gss_load_mech();
index aa9191f4b4cdab37792db39687b4e6347adc37e6..8d46486f9713253d2802db0fb92a183896e06043 100644 (file)
@@ -71,8 +71,8 @@ OM_uint32 _netlogon_import_name
 
     /* normalise name to uppercase XXX UTF-8 OK? */
     for (i = 0; i < len; i++) {
-        ((char *)name->NetbiosName.value)[i] =
-            toupper(((char *)name->NetbiosName.value)[i]);
+        ((unsigned char *)name->NetbiosName.value)[i] =
+            toupper(((unsigned char *)name->NetbiosName.value)[i]);
     }
 
     if (dnsName != NULL && dnsName[0] != '\0') {
index f49db674652b5831270c0461d080edc33ec3c3a0..2ee947727246a9b79a38c48e77634bc7e20e65c1 100644 (file)
@@ -260,9 +260,9 @@ str2val(const char *str, int base, size_t *len)
 
     i = 0;
     for (p = str; *p != '\0'; p++) {
-       if (isxdigit((int)*p))
+       if (isxdigit((unsigned char)*p))
            i++;
-       else if (isspace((int)*p))
+       else if (isspace((unsigned char)*p))
            ;
        else
            return NULL;
@@ -277,7 +277,7 @@ str2val(const char *str, int base, size_t *len)
     i = 0;
     f = 0;
     for (rp = dst, p = str; *p != '\0'; p++) {
-       if (isxdigit((int)*p)) {
+       if (isxdigit((unsigned char)*p)) {
            if (!f) {
                b[0] = *p;
                f = 1;
index c9c6c85bef2439e2fba9678f45675a9ee8e98f97..864b4f639da7c45c447d86a96dd45bd387873e9d 100644 (file)
@@ -517,7 +517,7 @@ is_pathish(const char *s)
         strncmp(s, "../", sizeof("../") - 1) == 0)
         return 1;
 #ifdef WIN32
-    if (s[0] == '\\' || (isalpha(s[0]) && s[0] == ':') ||
+    if (s[0] == '\\' || (isalpha((unsigned char)s[0]) && s[0] == ':') ||
         strncmp(s, ".\\", sizeof(".\\") - 1) == 0 ||
         strncmp(s, "\\\\", sizeof("\\\\") - 1) == 0)
         return 1;
index e1fbe7c06886636fcfe70001c587351ebfd47214..00f723c38bad745f40f130eb835a0ce820651b4f 100644 (file)
@@ -239,7 +239,7 @@ hx509_pem_read(hx509_context context,
            p = strchr(buf, ':');
            if (p) {
                *p++ = '\0';
-               while (isspace((int)*p))
+               while (isspace((unsigned char)*p))
                    p++;
                ret = hx509_pem_add_header(&headers, buf, p);
                if (ret)
index f92b20c85690c5fd09a2368d1fc3b0b606417d02..e572bffa7de4ddb2af8ef318e27287419a1c962a 100644 (file)
@@ -948,8 +948,8 @@ main(int argc, char **argv)
        if (auth_context) {
            krb5_auth_con_free(context, auth_context);
            auth_context = NULL;
-           get_creds(context, &ccache, master);
        }
+        get_creds(context, &ccache, master);
         if (verbose)
             krb5_warnx(context, "authenticating to master");
        ret = krb5_sendauth (context, &auth_context, &master_fd,
index f979ec0f5c96c75701fb95ba53cd989690ee8ef3..849698fbd437fc6298e491a30b572b54ef723468 100644 (file)
@@ -572,7 +572,7 @@ eval_recipe1(krb5_storage *sp, const char *typ, const char *val)
             return EINVAL;
         if (consumed < 1)
             return EINVAL;
-        while (isspace(val[consumed]))
+        while (isspace((unsigned char)val[consumed]))
             consumed++;
         if (val[consumed] != '\0')
             return EINVAL;
@@ -592,7 +592,7 @@ eval_recipe1(krb5_storage *sp, const char *typ, const char *val)
         }
         if (consumed < 1)
             return EINVAL;
-        while (isspace(val[consumed]))
+        while (isspace((unsigned char)val[consumed]))
             consumed++;
         if (val[consumed] != '\0')
             return EINVAL;
@@ -697,7 +697,7 @@ eval_recipe(char *r, int spflags)
             }
         } while (nxt);
 
-        while (isspace(*p))
+        while (isspace((unsigned char)*p))
             p++;
         if (*p == '#') {
             p = nxt;
@@ -709,7 +709,7 @@ eval_recipe(char *r, int spflags)
         val = strpbrk(p, " \t");
         if (val) {
             *(val++) = '\0';
-            while (isspace(*val))
+            while (isspace((unsigned char)*val))
                 val++;
         }
         ret = eval_recipe1(sp, typ, val);
index 75083f8284083497d615c150c4f4e3f22b0b503a..4afb0ca5c80dcb39bc917dc0e1f687a1cc44a9b2 100644 (file)
@@ -1418,7 +1418,7 @@ cc_get_prefix_ops(krb5_context context,
 
 #ifdef _WIN32
     /* Is drive letter? */
-    if (isalpha(prefix[0]) && prefix[1] == ':')
+    if (isalpha((unsigned char)prefix[0]) && prefix[1] == ':')
        return &krb5_fcc_ops;
 #endif
 
index 2fb4f0620f763df4d23e9347881481db6c422550..699d227d696d9219f269b63959ece187ca42e65d 100644 (file)
@@ -51,7 +51,7 @@ static void free_key_schedule(krb5_context,
                              struct _krb5_key_data *,
                              struct _krb5_encryption_type *);
 
-/* 
+/*
  * Converts etype to a user readable string and sets as a side effect
  * the krb5_error_message containing this string. Returns
  * KRB5_PROG_ETYPE_NOSUPP in not the conversion of the etype failed in
@@ -859,7 +859,7 @@ krb5_enctype_to_keytype(krb5_context context,
     if(e == NULL) {
         return unsupported_enctype (context, etype);
     }
-    *keytype = e->keytype->type; /* XXX */
+    *keytype = (krb5_keytype)e->keytype->type;
     return 0;
 }
 
@@ -1275,11 +1275,7 @@ decrypt_internal_derived(krb5_context context,
     }
     l = len - et->confoundersize;
     memmove(p, p + et->confoundersize, l);
-    result->data = realloc(p, l);
-    if(result->data == NULL && l != 0) {
-       free(p);
-       return krb5_enomem(context);
-    }
+    result->data = p;
     result->length = l;
     return 0;
 }
@@ -1360,11 +1356,7 @@ decrypt_internal_enc_then_cksum(krb5_context context,
 
     l = len - et->confoundersize;
     memmove(p, p + et->blocksize + et->confoundersize, l);
-    result->data = realloc(p, l);
-    if(result->data == NULL && l != 0) {
-       free(p);
-       return krb5_enomem(context);
-    }
+    result->data = p;
     result->length = l;
     return 0;
 }
@@ -1426,11 +1418,7 @@ decrypt_internal(krb5_context context,
     }
     l = len - et->confoundersize - checksum_sz;
     memmove(p, p + et->confoundersize + checksum_sz, l);
-    result->data = realloc(p, l);
-    if(result->data == NULL && l != 0) {
-       free(p);
-       return krb5_enomem(context);
-    }
+    result->data = p;
     result->length = l;
     return 0;
 }
@@ -1473,11 +1461,7 @@ decrypt_internal_special(krb5_context context,
     }
 
     memmove (p, p + cksum_sz + et->confoundersize, sz);
-    result->data = realloc(p, sz);
-    if(result->data == NULL && sz != 0) {
-       free(p);
-       return krb5_enomem(context);
-    }
+    result->data = p;
     result->length = sz;
     return 0;
 }
index 6a4a226a6c3089fd821066ea3bd583a11b36f597..77ccda13e72ba7ee0491e1490ef452efe34c29b1 100644 (file)
@@ -377,7 +377,7 @@ dcc_resolve_2(krb5_context context,
          *
          */
 
-        if (*res == '\0' || (res[0] == ':' && res[1] == '\0')) {
+        if (res == NULL || *res == '\0' || (res[0] == ':' && res[1] == '\0')) {
             /* XXX Why not? */
             krb5_set_error_message(context, KRB5_CC_FORMAT,
                                    N_("\"DIR:\" is not a valid ccache name", ""));
index ec9649dfed54a8d25788df7108586de0ece42af5..4a8e66deb4162925094b45f4d963e4ee9af98655 100644 (file)
@@ -1463,8 +1463,8 @@ krb5_sname_to_principal(krb5_context context,
 
        /* Lower-case the hostname, because that's the convention */
        for (cp = remote_host; *cp; cp++)
-           if (isupper((int) (*cp)))
-               *cp = tolower((int) (*cp));
+           if (isupper((unsigned char) (*cp)))
+               *cp = tolower((unsigned char) (*cp));
 
         /*
          * If there is only one name canon rule and it says to
@@ -1530,7 +1530,7 @@ static void
 tolower_str(char *s)
 {
     for (; *s != '\0'; s++) {
-        if (isupper(*s))
+        if (isupper((unsigned char)*s))
             *s = tolower_ascii(*s);
     }
 }
index 768981334f251d2ff2a0eaa77e51aa9639462097..5849d86a912dd261a262f8010f9eaf581baa0668 100644 (file)
@@ -69,9 +69,7 @@ static inline void     swapfunc(char *, char *, int, int);
        es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
 
 static inline void
-swapfunc(a, b, n, swaptype)
-       char *a, *b;
-       int n, swaptype;
+swapfunc(char *a, char *b, int n, int swaptype)
 {
        if(swaptype <= 1)
                swapcode(long, a, b, n)
index efcf55e5889829b243e78dd94267c907ed71715f..1e9e72b6e3290e815ef92a96fc35cd6721bca46b 100644 (file)
@@ -473,7 +473,7 @@ rtbl_format_json(rtbl_t table)
 
            if (c->num_rows > j) {
                char *header = c->header;
-               while (isspace((int)header[0])) /* trim off prefixed whitespace */
+               while (isspace((unsigned char)header[0])) /* trim off prefixed whitespace */
                    header++;
                p = rk_strpoolprintf(p, "%s\"%s\" : \"%s\"",
                                     comma ? "," : "", header,
index 0b99a4b6f3e18c9cae4eb34b047021b838f4f7ac..54018bae79823a915d1693f9a14e51341ae4b816 100644 (file)
@@ -309,7 +309,7 @@ append_char(struct snprintf_state *state,
        (*state->append_char) (state, ' ');
        ++len;
     }
-    return 0;
+    return len;
 }
 
 /*
@@ -437,8 +437,7 @@ xyzprintf (struct snprintf_state *state, const char *char_format, va_list ap)
 
            switch (c) {
            case 'c' :
-               append_char(state, va_arg(ap, int), width, flags);
-               ++len;
+               len += append_char(state, va_arg(ap, int), width, flags);
                break;
            case 's' :
                len += append_string(state,
index 3e13aeec90cddbb12578aa6f710eac1769f4c4c7..dd38de404a6974f3fbd41368668a0bc5b3b09fd2 100644 (file)
@@ -142,25 +142,28 @@ main(int argc, char **argv)
 {
     FILE *f;
     char buf[1024];
-    char filename[256] = "NormalizationTest.txt";
+    const char *fn = "NormalizationTest.txt";
     unsigned failures = 0;
     unsigned lineno = 0;
 
     if (argc > 2)
        errx(1, "usage: %s [file]", argv[0]);
     else if (argc == 2)
-       strlcpy(filename, argv[1], sizeof(filename));
+        fn = argv[1];
 
-    f = fopen(filename, "r");
+    f = fopen(fn, "r");
     if (f == NULL) {
        const char *srcdir = getenv("srcdir");
        if (srcdir != NULL) {
-           char longname[256];
-           snprintf(longname, sizeof(longname), "%s/%s", srcdir, filename);
-           f = fopen(longname, "r");
+            char *long_fn = NULL;
+            if (asprintf(&long_fn, "%s/%s", srcdir, fn) == -1 ||
+                long_fn == NULL)
+                errx(1, "Out of memory");
+           f = fopen(long_fn, "r");
+            free(long_fn);
        }
        if (f == NULL)
-           err(1, "open %s", filename);
+           err(1, "open %s", fn);
     }
     while (fgets(buf, sizeof(buf), f) != NULL) {
        lineno++;