From: Stefan Metzmacher Date: Fri, 9 Jun 2023 13:14:50 +0000 (+0200) Subject: third_party/heimdal: Import lorikeet-heimdal-202306091507 (commit 7d8afc9d7e3d309ddcc... X-Git-Tag: talloc-2.4.1~469 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=75ec66c729faad60fa18b9504ba4053b3e2f47bc;p=thirdparty%2Fsamba.git third_party/heimdal: Import lorikeet-heimdal-202306091507 (commit 7d8afc9d7e3d309ddccc2aea6405a8ca6280f6de) Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- diff --git a/third_party/heimdal/.github/workflows/coverity.yml b/third_party/heimdal/.github/workflows/coverity.yml index dfea060d04b..78ec7e5a56b 100644 --- a/third_party/heimdal/.github/workflows/coverity.yml +++ b/third_party/heimdal/.github/workflows/coverity.yml @@ -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 diff --git a/third_party/heimdal/.github/workflows/linux-mit-interop.yml b/third_party/heimdal/.github/workflows/linux-mit-interop.yml index 72648ee2ce0..d1837a01d8c 100644 --- a/third_party/heimdal/.github/workflows/linux-mit-interop.yml +++ b/third_party/heimdal/.github/workflows/linux-mit-interop.yml @@ -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 diff --git a/third_party/heimdal/.github/workflows/linux.yml b/third_party/heimdal/.github/workflows/linux.yml index 48e4c80dc3c..1bbfbb4ec24 100644 --- a/third_party/heimdal/.github/workflows/linux.yml +++ b/third_party/heimdal/.github/workflows/linux.yml @@ -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: diff --git a/third_party/heimdal/.github/workflows/osx.yml b/third_party/heimdal/.github/workflows/osx.yml index 3463e99b6e9..29aa05fc1f7 100644 --- a/third_party/heimdal/.github/workflows/osx.yml +++ b/third_party/heimdal/.github/workflows/osx.yml @@ -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 diff --git a/third_party/heimdal/.github/workflows/scanbuild.yml b/third_party/heimdal/.github/workflows/scanbuild.yml index 678ccfd8046..472b0b7e396 100644 --- a/third_party/heimdal/.github/workflows/scanbuild.yml +++ b/third_party/heimdal/.github/workflows/scanbuild.yml @@ -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 diff --git a/third_party/heimdal/.github/workflows/ubsan.yml b/third_party/heimdal/.github/workflows/ubsan.yml index d4bb2eda476..9dec161d430 100644 --- a/third_party/heimdal/.github/workflows/ubsan.yml +++ b/third_party/heimdal/.github/workflows/ubsan.yml @@ -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: diff --git a/third_party/heimdal/.github/workflows/valgrind.yml b/third_party/heimdal/.github/workflows/valgrind.yml index ab5e9091661..8506df999ca 100644 --- a/third_party/heimdal/.github/workflows/valgrind.yml +++ b/third_party/heimdal/.github/workflows/valgrind.yml @@ -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 diff --git a/third_party/heimdal/admin/ktutil.1 b/third_party/heimdal/admin/ktutil.1 index 0036edcbd9b..fb8bc382b39 100644 --- a/third_party/heimdal/admin/ktutil.1 +++ b/third_party/heimdal/admin/ktutil.1 @@ -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 [][:mkey=] +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 diff --git a/third_party/heimdal/cf/crypto.m4 b/third_party/heimdal/cf/crypto.m4 index a8ef5198411..0f308ced8f9 100644 --- a/third_party/heimdal/cf/crypto.m4 +++ b/third_party/heimdal/cf/crypto.m4 @@ -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' diff --git a/third_party/heimdal/doc/setup.texi b/third_party/heimdal/doc/setup.texi index 962541359ee..1df24d12c65 100644 --- a/third_party/heimdal/doc/setup.texi +++ b/third_party/heimdal/doc/setup.texi @@ -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 diff --git a/third_party/heimdal/kadmin/kadmin-commands.in b/third_party/heimdal/kadmin/kadmin-commands.in index db9c4415e6c..0872b47a441 100644 --- a/third_party/heimdal/kadmin/kadmin-commands.in +++ b/third_party/heimdal/kadmin/kadmin-commands.in @@ -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" diff --git a/third_party/heimdal/kadmin/kadmin.1 b/third_party/heimdal/kadmin/kadmin.1 index ded59979461..42ccad739e8 100644 --- a/third_party/heimdal/kadmin/kadmin.1 +++ b/third_party/heimdal/kadmin/kadmin.1 @@ -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 diff --git a/third_party/heimdal/kdc/bx509d.c b/third_party/heimdal/kdc/bx509d.c index b7e9096f737..793012baf4a 100644 --- a/third_party/heimdal/kdc/bx509d.c +++ b/third_party/heimdal/kdc/bx509d.c @@ -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++] = '%'; diff --git a/third_party/heimdal/kdc/ipc_csr_authorizer.c b/third_party/heimdal/kdc/ipc_csr_authorizer.c index 86717f6f9e0..f2ce03c879c 100644 --- a/third_party/heimdal/kdc/ipc_csr_authorizer.c +++ b/third_party/heimdal/kdc/ipc_csr_authorizer.c @@ -120,7 +120,7 @@ string_encode_sz(const char *in) case '/': continue; default: - if (isalnum(c)) + if (isalnum((unsigned char)c)) continue; sz += 2; } diff --git a/third_party/heimdal/kdc/kdc-audit.h b/third_party/heimdal/kdc/kdc-audit.h index 4b2203f2267..df5362031f5 100644 --- a/third_party/heimdal/kdc/kdc-audit.h +++ b/third_party/heimdal/kdc/kdc-audit.h @@ -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 @@ -61,7 +62,10 @@ #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 */ diff --git a/third_party/heimdal/kdc/kdc_locl.h b/third_party/heimdal/kdc/kdc_locl.h index 767d04f5c8c..bf9a0bc55e9 100644 --- a/third_party/heimdal/kdc/kdc_locl.h +++ b/third_party/heimdal/kdc/kdc_locl.h @@ -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; diff --git a/third_party/heimdal/kdc/kerberos5.c b/third_party/heimdal/kdc/kerberos5.c index 1587f7fb2ac..26680e0e736 100644 --- a/third_party/heimdal/kdc/kerberos5.c +++ b/third_party/heimdal/kdc/kerberos5.c @@ -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); diff --git a/third_party/heimdal/kdc/krb5tgs.c b/third_party/heimdal/kdc/krb5tgs.c index c3b033f58c2..b01aa526283 100644 --- a/third_party/heimdal/kdc/krb5tgs.c +++ b/third_party/heimdal/kdc/krb5tgs.c @@ -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; } diff --git a/third_party/heimdal/kdc/mssfu.c b/third_party/heimdal/kdc/mssfu.c index a88de097a9b..6145fc8e8e1 100644 --- a/third_party/heimdal/kdc/mssfu.c +++ b/third_party/heimdal/kdc/mssfu.c @@ -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); diff --git a/third_party/heimdal/kdc/test_csr_authorizer.c b/third_party/heimdal/kdc/test_csr_authorizer.c index dbf4c421237..200af16c16d 100644 --- a/third_party/heimdal/kdc/test_csr_authorizer.c +++ b/third_party/heimdal/kdc/test_csr_authorizer.c @@ -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; diff --git a/third_party/heimdal/kuser/kinit.1 b/third_party/heimdal/kuser/kinit.1 index b9c77c23505..f374a7c0628 100644 --- a/third_party/heimdal/kuser/kinit.1 +++ b/third_party/heimdal/kuser/kinit.1 @@ -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 +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 diff --git a/third_party/heimdal/kuser/kinit.c b/third_party/heimdal/kuser/kinit.c index a374817a067..7f754c09fd4 100644 --- a/third_party/heimdal/kuser/kinit.c +++ b/third_party/heimdal/kuser/kinit.c @@ -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); diff --git a/third_party/heimdal/lib/asn1/asn1_print.c b/third_party/heimdal/lib/asn1/asn1_print.c index 40c37fbbb94..9ef6ffd23a2 100644 --- a/third_party/heimdal/lib/asn1/asn1_print.c +++ b/third_party/heimdal/lib/asn1/asn1_print.c @@ -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]); diff --git a/third_party/heimdal/lib/asn1/gen.c b/third_party/heimdal/lib/asn1/gen.c index 06dc6bb701b..a660aaed846 100644 --- a/third_party/heimdal/lib/asn1/gen.c +++ b/third_party/heimdal/lib/asn1/gen.c @@ -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, diff --git a/third_party/heimdal/lib/base/config_file.c b/third_party/heimdal/lib/base/config_file.c index 963569ca1eb..b1675ea5f14 100644 --- a/third_party/heimdal/lib/base/config_file.c +++ b/third_party/heimdal/lib/base/config_file.c @@ -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)); diff --git a/third_party/heimdal/lib/base/warn.c b/third_party/heimdal/lib/base/warn.c index 2376a518ee7..3dfed48fdac 100644 --- a/third_party/heimdal/lib/base/warn.c +++ b/third_party/heimdal/lib/base/warn.c @@ -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); diff --git a/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c b/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c index 372e72dd5da..3151efe4289 100644 --- a/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c +++ b/third_party/heimdal/lib/gssapi/mech/gss_mech_switch.c @@ -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(); diff --git a/third_party/heimdal/lib/gssapi/netlogon/import_name.c b/third_party/heimdal/lib/gssapi/netlogon/import_name.c index aa9191f4b4c..8d46486f971 100644 --- a/third_party/heimdal/lib/gssapi/netlogon/import_name.c +++ b/third_party/heimdal/lib/gssapi/netlogon/import_name.c @@ -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') { diff --git a/third_party/heimdal/lib/hcrypto/test_dh.c b/third_party/heimdal/lib/hcrypto/test_dh.c index f49db674652..2ee94772724 100644 --- a/third_party/heimdal/lib/hcrypto/test_dh.c +++ b/third_party/heimdal/lib/hcrypto/test_dh.c @@ -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; diff --git a/third_party/heimdal/lib/hdb/hdb.c b/third_party/heimdal/lib/hdb/hdb.c index c9c6c85bef2..864b4f639da 100644 --- a/third_party/heimdal/lib/hdb/hdb.c +++ b/third_party/heimdal/lib/hdb/hdb.c @@ -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; diff --git a/third_party/heimdal/lib/hx509/file.c b/third_party/heimdal/lib/hx509/file.c index e1fbe7c0688..00f723c38ba 100644 --- a/third_party/heimdal/lib/hx509/file.c +++ b/third_party/heimdal/lib/hx509/file.c @@ -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) diff --git a/third_party/heimdal/lib/kadm5/ipropd_slave.c b/third_party/heimdal/lib/kadm5/ipropd_slave.c index f92b20c8569..e572bffa7de 100644 --- a/third_party/heimdal/lib/kadm5/ipropd_slave.c +++ b/third_party/heimdal/lib/kadm5/ipropd_slave.c @@ -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, diff --git a/third_party/heimdal/lib/kadm5/marshall.c b/third_party/heimdal/lib/kadm5/marshall.c index f979ec0f5c9..849698fbd43 100644 --- a/third_party/heimdal/lib/kadm5/marshall.c +++ b/third_party/heimdal/lib/kadm5/marshall.c @@ -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); diff --git a/third_party/heimdal/lib/krb5/cache.c b/third_party/heimdal/lib/krb5/cache.c index 75083f82840..4afb0ca5c80 100644 --- a/third_party/heimdal/lib/krb5/cache.c +++ b/third_party/heimdal/lib/krb5/cache.c @@ -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 diff --git a/third_party/heimdal/lib/krb5/crypto.c b/third_party/heimdal/lib/krb5/crypto.c index 2fb4f0620f7..699d227d696 100644 --- a/third_party/heimdal/lib/krb5/crypto.c +++ b/third_party/heimdal/lib/krb5/crypto.c @@ -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; } diff --git a/third_party/heimdal/lib/krb5/dcache.c b/third_party/heimdal/lib/krb5/dcache.c index 6a4a226a6c3..77ccda13e72 100644 --- a/third_party/heimdal/lib/krb5/dcache.c +++ b/third_party/heimdal/lib/krb5/dcache.c @@ -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", "")); diff --git a/third_party/heimdal/lib/krb5/principal.c b/third_party/heimdal/lib/krb5/principal.c index ec9649dfed5..4a8e66deb41 100644 --- a/third_party/heimdal/lib/krb5/principal.c +++ b/third_party/heimdal/lib/krb5/principal.c @@ -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); } } diff --git a/third_party/heimdal/lib/roken/qsort.c b/third_party/heimdal/lib/roken/qsort.c index 768981334f2..5849d86a912 100644 --- a/third_party/heimdal/lib/roken/qsort.c +++ b/third_party/heimdal/lib/roken/qsort.c @@ -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) diff --git a/third_party/heimdal/lib/roken/rtbl.c b/third_party/heimdal/lib/roken/rtbl.c index efcf55e5889..1e9e72b6e32 100644 --- a/third_party/heimdal/lib/roken/rtbl.c +++ b/third_party/heimdal/lib/roken/rtbl.c @@ -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, diff --git a/third_party/heimdal/lib/roken/snprintf.c b/third_party/heimdal/lib/roken/snprintf.c index 0b99a4b6f3e..54018bae798 100644 --- a/third_party/heimdal/lib/roken/snprintf.c +++ b/third_party/heimdal/lib/roken/snprintf.c @@ -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, diff --git a/third_party/heimdal/lib/wind/test-normalize.c b/third_party/heimdal/lib/wind/test-normalize.c index 3e13aeec90c..dd38de404a6 100644 --- a/third_party/heimdal/lib/wind/test-normalize.c +++ b/third_party/heimdal/lib/wind/test-normalize.c @@ -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++;