1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

third_party/heimdal: Import lorikeet-heimdal-202306091507 (commit 7d8afc9d7e3d309ddccc2aea6405a8ca6280f6de)

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Stefan Metzmacher 2023-06-09 15:14:50 +02:00 committed by Andrew Bartlett
parent 23ca540abf
commit 75ec66c729
41 changed files with 884 additions and 308 deletions

View 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

View 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

View 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:

View 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

View 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

View 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:

View 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

View 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

View 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'

View 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

View 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"

View 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

View 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++] = '%';

View 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;
}

View 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
@ -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 */

View 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;

View File

@ -695,23 +695,141 @@ pa_gss_finalize_pac(astgs_request_t r)
return _kdc_gss_finalize_pac(r, gcp);
}
static krb5_error_code
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)
{
unsigned int invalidKeys = 0;
krb5_error_code ret;
const Keys *keys = NULL;
unsigned int i;
if (KDCchallengekey)
krb5_keyblock_zero(KDCchallengekey);
if (used_key)
*used_key = NULL;
keys = hdb_kvno2keys(r->context, r->client, kvno);
if (keys == NULL) {
return KRB5KDC_ERR_ETYPE_NOSUPP;
}
for (i = 0; i < keys->len; i++) {
struct Key *k = &keys->val[i];
krb5_crypto challengecrypto, longtermcrypto;
krb5_keyblock client_challengekey;
ret = krb5_crypto_init(r->context, &k->key, 0, &longtermcrypto);
if (ret)
continue;
ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
pepper1client, pepper2, aenctype,
&client_challengekey);
if (ret) {
krb5_crypto_destroy(r->context, longtermcrypto);
continue;
}
ret = krb5_crypto_init(r->context, &client_challengekey, 0,
&challengecrypto);
krb5_free_keyblock_contents(r->context, &client_challengekey);
if (ret) {
krb5_crypto_destroy(r->context, longtermcrypto);
continue;
}
ret = _krb5_validate_pa_enc_challenge(r->context,
challengecrypto,
KRB5_KU_ENC_CHALLENGE_CLIENT,
enc_data,
r->cname);
krb5_crypto_destroy(r->context, challengecrypto);
if (ret) {
const char *msg;
krb5_error_code ret2;
char *str = NULL;
krb5_crypto_destroy(r->context, longtermcrypto);
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)
str = NULL;
msg = krb5_get_error_message(r->context, ret);
_kdc_r_log(r, 2, "Failed to decrypt ENC-CHAL -- %s "
"(enctype %s) error %s",
r->cname, str ? str : "unknown enctype", msg);
krb5_free_error_message(r->context, msg);
free(str);
continue;
}
if (pepper1kdc == NULL) {
/* The caller is not interessted in details */
return 0;
}
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).
*/
ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
pepper1kdc, pepper2, aenctype,
KDCchallengekey);
krb5_crypto_destroy(r->context, longtermcrypto);
if (ret)
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_data pepper1, pepper2;
int invalidPassword = 0;
krb5_kvno kvno = r->client->kvno;
krb5_data pepper1client, pepper1kdc, pepper2;
EncryptedData enc_data;
krb5_enctype aenctype;
krb5_error_code ret;
struct Key *k;
krb5_keyblock KDCchallengekey;
struct Key *k = NULL;
size_t size;
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");
kdc_log(r->context, r->config, 4, "ENC-CHAL doesn't support anon");
return ret;
}
@ -735,8 +853,10 @@ pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
return ret;
}
pepper1.data = "clientchallengearmor";
pepper1.length = strlen(pepper1.data);
pepper1client.data = "clientchallengearmor";
pepper1client.length = strlen(pepper1client.data);
pepper1kdc.data = "kdcchallengearmor";
pepper1kdc.length = strlen(pepper1kdc.data);
pepper2.data = "challengelongterm";
pepper2.length = strlen(pepper2.data);
@ -744,134 +864,230 @@ pa_enc_chal_validate(astgs_request_t r, const PA_DATA *pa)
kdc_log(r->context, r->config, 5, "FAST armor enctype is: %d", (int)aenctype);
for (i = 0; i < r->client->keys.len; i++) {
krb5_crypto challengecrypto, longtermcrypto;
krb5_keyblock challengekey;
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()
*/
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);
if (ret) {
krb5_crypto_destroy(r->context, longtermcrypto);
continue;
}
ret = krb5_crypto_init(r->context, &challengekey, 0,
&challengecrypto);
krb5_free_keyblock_contents(r->context, &challengekey);
if (ret) {
krb5_crypto_destroy(r->context, longtermcrypto);
continue;
}
free_EncryptedData(&enc_data);
kdc_audit_setkv_number((kdc_request_t)r, KDC_REQUEST_KV_AUTH_EVENT,
KDC_AUTH_EVENT_CLIENT_TIME_SKEW);
ret = _krb5_validate_pa_enc_challenge(r->context,
challengecrypto,
KRB5_KU_ENC_CHALLENGE_CLIENT,
&enc_data,
r->cname);
krb5_crypto_destroy(r->context, challengecrypto);
if (ret) {
const char *msg;
krb5_error_code ret2;
char *str = NULL;
/*
* 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;
krb5_crypto_destroy(r->context, longtermcrypto);
/*
* Logging happens inside of
* via pa_enc_chal_decrypt_kvno()
*/
invalidPassword = (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY);
if (!invalidPassword) {
goto out;
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;
}
ret2 = krb5_enctype_to_string(r->context, k->key.keytype, &str);
if (ret2)
str = NULL;
msg = krb5_get_error_message(r->context, ret);
_kdc_r_log(r, 2, "Failed to decrypt ENC-CHAL -- %s "
"(enctype %s) error %s",
r->cname, str ? str : "unknown enctype", msg);
krb5_free_error_message(r->context, msg);
free(str);
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;
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;
}
}
krb5_free_keyblock_contents(r->context, &challengekey);
free_EncryptedData(&enc_data);
/*
* Provide KDC authentication to the client, uses a different
* challenge key (different pepper).
*/
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);
pepper1.data = "kdcchallengearmor";
pepper1.length = strlen(pepper1.data);
return ret;
}
free_EncryptedData(&enc_data);
if (ret == 0) {
krb5_crypto challengecrypto;
char *estr = NULL;
char *astr = NULL;
char *kstr = NULL;
ret = krb5_crypto_fx_cf2(r->context, r->armor_crypto, longtermcrypto,
&pepper1, &pepper2, aenctype,
&challengekey);
krb5_crypto_destroy(r->context, longtermcrypto);
ret = krb5_crypto_init(r->context, &KDCchallengekey, 0, &challengecrypto);
krb5_free_keyblock_contents(r->context, &KDCchallengekey);
if (ret)
goto out;
ret = krb5_crypto_init(r->context, &challengekey, 0, &challengecrypto);
krb5_free_keyblock_contents(r->context, &challengekey);
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;
}
out:
free_EncryptedData(&enc_data);
return ret;
}
static krb5_error_code
pa_enc_ts_validate(astgs_request_t r, const PA_DATA *pa)
pa_enc_ts_decrypt_kvno(astgs_request_t r,
krb5_kvno kvno,
const EncryptedData *enc_data,
krb5_data *ts_data,
Key **_pa_key)
{
EncryptedData enc_data;
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;
}
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_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;
ret2 = krb5_enctype_to_string(r->context,
pa_key->key.keytype, &str);
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_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);

View 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);
ret = krb5_copy_keyblock_contents(r->context,
&r->reply_key,
&r->enc_ad_key);
if (ret)
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; /* ? */
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;
}

View 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);

View 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;

View 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

View 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);

View 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]);

View 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,

View 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));

View 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);

View 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();

View 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') {

View 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;

View 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;

View 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)

View 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,

View 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);

View 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

View 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;
}

View 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", ""));

View 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);
}
}

View 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)

View 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,

View 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,

View 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++;