summaryrefslogtreecommitdiff
path: root/src/lib/krb5
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/krb5')
-rw-r--r--src/lib/krb5/asn.1/asn1_k_encode.c3
-rw-r--r--src/lib/krb5/ccache/Makefile.in3
-rw-r--r--src/lib/krb5/ccache/cc-int.h4
-rw-r--r--src/lib/krb5/ccache/cc_kcm.c4
-rw-r--r--src/lib/krb5/ccache/cc_keyring.c14
-rw-r--r--src/lib/krb5/ccache/cc_memory.c4
-rw-r--r--src/lib/krb5/ccache/cc_mslsa.c1
-rw-r--r--src/lib/krb5/ccache/cc_retr.c5
-rw-r--r--src/lib/krb5/ccache/ccapi/stdcc_util.c40
-rw-r--r--src/lib/krb5/ccache/cccursor.c49
-rw-r--r--src/lib/krb5/ccache/ccmarshal.c2
-rw-r--r--src/lib/krb5/ccache/ccselect.c52
-rw-r--r--src/lib/krb5/ccache/ccselect_hostname.c146
-rw-r--r--src/lib/krb5/ccache/deps11
-rw-r--r--src/lib/krb5/keytab/kt_file.c8
-rw-r--r--src/lib/krb5/keytab/kt_memory.c2
-rw-r--r--src/lib/krb5/keytab/kt_srvtab.c2
-rw-r--r--src/lib/krb5/krb/Makefile.in14
-rw-r--r--src/lib/krb5/krb/deltat.c75
-rw-r--r--src/lib/krb5/krb/deps38
-rw-r--r--src/lib/krb5/krb/fwd_tgt.c28
-rw-r--r--src/lib/krb5/krb/gc_via_tkt.c11
-rw-r--r--src/lib/krb5/krb/gen_save_subkey.c3
-rw-r--r--src/lib/krb5/krb/get_creds.c15
-rw-r--r--src/lib/krb5/krb/get_in_tkt.c294
-rw-r--r--src/lib/krb5/krb/gic_opt.c2
-rw-r--r--src/lib/krb5/krb/gic_pwd.c4
-rw-r--r--src/lib/krb5/krb/init_creds_ctx.h9
-rw-r--r--src/lib/krb5/krb/init_ctx.c3
-rw-r--r--src/lib/krb5/krb/int-proto.h22
-rw-r--r--src/lib/krb5/krb/mk_req.c5
-rw-r--r--src/lib/krb5/krb/pac.c9
-rw-r--r--src/lib/krb5/krb/pac_sign.c21
-rw-r--r--src/lib/krb5/krb/plugin.c5
-rw-r--r--src/lib/krb5/krb/preauth2.c311
-rw-r--r--src/lib/krb5/krb/preauth_ec.c2
-rw-r--r--src/lib/krb5/krb/send_tgs.c24
-rw-r--r--src/lib/krb5/krb/sendauth.c23
-rw-r--r--src/lib/krb5/krb/str_conv.c4
-rwxr-xr-xsrc/lib/krb5/krb/t_expire_warn.py13
-rw-r--r--src/lib/krb5/krb/t_kerb.c12
-rw-r--r--src/lib/krb5/krb/t_parse_host_string.c5
-rw-r--r--src/lib/krb5/krb/t_valid_times.c109
-rw-r--r--src/lib/krb5/krb/valid_times.c4
-rw-r--r--src/lib/krb5/krb/vfy_increds.c2
-rw-r--r--src/lib/krb5/krb/x-deltat.y1
-rw-r--r--src/lib/krb5/os/Makefile.in2
-rw-r--r--src/lib/krb5/os/accessor.c13
-rw-r--r--src/lib/krb5/os/c_ustime.c15
-rw-r--r--src/lib/krb5/os/dnsglue.c2
-rw-r--r--src/lib/krb5/os/dnsglue.h19
-rw-r--r--src/lib/krb5/os/dnssrv.c18
-rw-r--r--src/lib/krb5/os/expand_path.c2
-rw-r--r--src/lib/krb5/os/genaddrs.c8
-rw-r--r--src/lib/krb5/os/hostaddr.c4
-rw-r--r--src/lib/krb5/os/localaddr.c24
-rw-r--r--src/lib/krb5/os/locate_kdc.c43
-rw-r--r--src/lib/krb5/os/sendto_kdc.c5
-rw-r--r--src/lib/krb5/os/t_locate_kdc.c2
-rw-r--r--src/lib/krb5/os/timeofday.c2
-rw-r--r--src/lib/krb5/os/toffset.c5
-rw-r--r--src/lib/krb5/os/trace.c7
-rw-r--r--src/lib/krb5/os/ustime.c9
-rw-r--r--src/lib/krb5/rcache/rc_dfl.c15
-rw-r--r--src/lib/krb5/rcache/ser_rc.c2
-rw-r--r--src/lib/krb5/rcache/t_replay.c8
-rw-r--r--src/lib/krb5/unicode/ure/ure.c2
67 files changed, 1051 insertions, 574 deletions
diff --git a/src/lib/krb5/asn.1/asn1_k_encode.c b/src/lib/krb5/asn.1/asn1_k_encode.c
index a827ca6083e8..889460989f70 100644
--- a/src/lib/krb5/asn.1/asn1_k_encode.c
+++ b/src/lib/krb5/asn.1/asn1_k_encode.c
@@ -158,8 +158,7 @@ static asn1_error_code
encode_kerberos_time(asn1buf *buf, const void *p, taginfo *rettag,
size_t *len_out)
{
- /* Range checking for time_t vs krb5_timestamp? */
- time_t val = *(krb5_timestamp *)p;
+ time_t val = ts2tt(*(krb5_timestamp *)p);
rettag->asn1class = UNIVERSAL;
rettag->construction = PRIMITIVE;
rettag->tagnum = ASN1_GENERALTIME;
diff --git a/src/lib/krb5/ccache/Makefile.in b/src/lib/krb5/ccache/Makefile.in
index 5ac870728d9d..f84cf793e0db 100644
--- a/src/lib/krb5/ccache/Makefile.in
+++ b/src/lib/krb5/ccache/Makefile.in
@@ -34,6 +34,7 @@ STLIBOBJS= \
ccdefops.o \
ccmarshal.o \
ccselect.o \
+ ccselect_hostname.o \
ccselect_k5identity.o \
ccselect_realm.o \
cc_dir.o \
@@ -52,6 +53,7 @@ OBJS= $(OUTPRE)ccbase.$(OBJEXT) \
$(OUTPRE)ccdefops.$(OBJEXT) \
$(OUTPRE)ccmarshal.$(OBJEXT) \
$(OUTPRE)ccselect.$(OBJEXT) \
+ $(OUTPRE)ccselect_hostname.$(OBJEXT) \
$(OUTPRE)ccselect_k5identity.$(OBJEXT) \
$(OUTPRE)ccselect_realm.$(OBJEXT) \
$(OUTPRE)cc_dir.$(OBJEXT) \
@@ -70,6 +72,7 @@ SRCS= $(srcdir)/ccbase.c \
$(srcdir)/ccdefops.c \
$(srcdir)/ccmarshal.c \
$(srcdir)/ccselect.c \
+ $(srcdir)/ccselect_hostname.c \
$(srcdir)/ccselect_k5identity.c \
$(srcdir)/ccselect_realm.c \
$(srcdir)/cc_dir.c \
diff --git a/src/lib/krb5/ccache/cc-int.h b/src/lib/krb5/ccache/cc-int.h
index ee9b5e0e97a1..d920367cea97 100644
--- a/src/lib/krb5/ccache/cc-int.h
+++ b/src/lib/krb5/ccache/cc-int.h
@@ -124,6 +124,10 @@ krb5_error_code
krb5int_fcc_new_unique(krb5_context context, char *template, krb5_ccache *id);
krb5_error_code
+ccselect_hostname_initvt(krb5_context context, int maj_ver, int min_ver,
+ krb5_plugin_vtable vtable);
+
+krb5_error_code
ccselect_realm_initvt(krb5_context context, int maj_ver, int min_ver,
krb5_plugin_vtable vtable);
diff --git a/src/lib/krb5/ccache/cc_kcm.c b/src/lib/krb5/ccache/cc_kcm.c
index a889e67b4492..b621ed33b3e7 100644
--- a/src/lib/krb5/ccache/cc_kcm.c
+++ b/src/lib/krb5/ccache/cc_kcm.c
@@ -32,7 +32,7 @@
/*
* This cache type contacts a daemon for each cache operation, using Heimdal's
- * KCM protocol. On OS X, the preferred transport is Mach RPC; on other
+ * KCM protocol. On macOS, the preferred transport is Mach RPC; on other
* Unix-like platforms or if the daemon is not available via RPC, Unix domain
* sockets are used instead.
*/
@@ -360,7 +360,7 @@ kcmio_connect(krb5_context context, struct kcmio **io_out)
return ENOMEM;
io->fd = -1;
- /* Try Mach RPC (OS X only), then fall back to Unix domain sockets */
+ /* Try Mach RPC (macOS only), then fall back to Unix domain sockets */
ret = kcmio_mach_connect(context, io);
if (ret)
ret = kcmio_unix_socket_connect(context, io);
diff --git a/src/lib/krb5/ccache/cc_keyring.c b/src/lib/krb5/ccache/cc_keyring.c
index 4fe3f0d6f1f2..fba710b1b651 100644
--- a/src/lib/krb5/ccache/cc_keyring.c
+++ b/src/lib/krb5/ccache/cc_keyring.c
@@ -751,7 +751,7 @@ update_keyring_expiration(krb5_context context, krb5_ccache id)
for (;;) {
if (krcc_next_cred(context, id, &cursor, &creds) != 0)
break;
- if (creds.times.endtime > endtime)
+ if (ts_after(creds.times.endtime, endtime))
endtime = creds.times.endtime;
krb5_free_cred_contents(context, &creds);
}
@@ -765,7 +765,7 @@ update_keyring_expiration(krb5_context context, krb5_ccache id)
/* Setting the timeout to zero would reset the timeout, so we set it to one
* second instead if creds are already expired. */
- timeout = (endtime > now) ? endtime - now : 1;
+ timeout = ts_after(endtime, now) ? ts_delta(endtime, now) : 1;
(void)keyctl_set_timeout(data->cache_id, timeout);
}
@@ -1316,8 +1316,10 @@ krcc_store(krb5_context context, krb5_ccache id, krb5_creds *creds)
if (ret)
goto errout;
- if (creds->times.endtime > now)
- (void)keyctl_set_timeout(cred_key, creds->times.endtime - now);
+ if (ts_after(creds->times.endtime, now)) {
+ (void)keyctl_set_timeout(cred_key,
+ ts_delta(creds->times.endtime, now));
+ }
update_keyring_expiration(context, id);
@@ -1680,8 +1682,8 @@ static void
krcc_update_change_time(krcc_data *data)
{
krb5_timestamp now_time = time(NULL);
- data->changetime = (data->changetime >= now_time) ?
- data->changetime + 1 : now_time;
+ data->changetime = ts_after(now_time, data->changetime) ?
+ now_time : ts_incr(data->changetime, 1);
}
/*
diff --git a/src/lib/krb5/ccache/cc_memory.c b/src/lib/krb5/ccache/cc_memory.c
index 0354575c5c16..c5425eb3ae7a 100644
--- a/src/lib/krb5/ccache/cc_memory.c
+++ b/src/lib/krb5/ccache/cc_memory.c
@@ -720,8 +720,8 @@ static void
update_mcc_change_time(krb5_mcc_data *d)
{
krb5_timestamp now_time = time(NULL);
- d->changetime = (d->changetime >= now_time) ?
- d->changetime + 1 : now_time;
+ d->changetime = ts_after(now_time, d->changetime) ?
+ now_time : ts_incr(d->changetime, 1);
}
static krb5_error_code KRB5_CALLCONV
diff --git a/src/lib/krb5/ccache/cc_mslsa.c b/src/lib/krb5/ccache/cc_mslsa.c
index 7a8047023716..c741a5099ae6 100644
--- a/src/lib/krb5/ccache/cc_mslsa.c
+++ b/src/lib/krb5/ccache/cc_mslsa.c
@@ -1553,6 +1553,7 @@ krb5_lcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
data->LogonHandle = LogonHandle;
data->PackageId = PackageId;
data->princ = NULL;
+ data->flags = 0;
data->cc_name = (char *)malloc(strlen(residual)+1);
if (data->cc_name == NULL) {
diff --git a/src/lib/krb5/ccache/cc_retr.c b/src/lib/krb5/ccache/cc_retr.c
index 1314d24bd68d..e8a20fe36001 100644
--- a/src/lib/krb5/ccache/cc_retr.c
+++ b/src/lib/krb5/ccache/cc_retr.c
@@ -46,11 +46,11 @@ static krb5_boolean
times_match(const krb5_ticket_times *t1, const krb5_ticket_times *t2)
{
if (t1->renew_till) {
- if (t1->renew_till > t2->renew_till)
+ if (ts_after(t1->renew_till, t2->renew_till))
return FALSE; /* this one expires too late */
}
if (t1->endtime) {
- if (t1->endtime > t2->endtime)
+ if (ts_after(t1->endtime, t2->endtime))
return FALSE; /* this one expires too late */
}
/* only care about expiration on a times_match */
@@ -211,7 +211,6 @@ krb5_cc_retrieve_cred_seq (krb5_context context, krb5_ccache id,
int pref;
} fetched, best;
int have_creds = 0;
- krb5_flags oflags = 0;
#define fetchcreds (fetched.creds)
kret = krb5_cc_start_seq_get(context, id, &cursor);
diff --git a/src/lib/krb5/ccache/ccapi/stdcc_util.c b/src/lib/krb5/ccache/ccapi/stdcc_util.c
index 9f44af3d087c..6092ee432222 100644
--- a/src/lib/krb5/ccache/ccapi/stdcc_util.c
+++ b/src/lib/krb5/ccache/ccapi/stdcc_util.c
@@ -16,8 +16,8 @@
#include <malloc.h>
#endif
+#include "k5-int.h"
#include "stdcc_util.h"
-#include "krb5.h"
#ifdef _WIN32 /* it's part of krb5.h everywhere else */
#include "kv5m_err.h"
#endif
@@ -321,10 +321,10 @@ copy_cc_cred_union_to_krb5_creds (krb5_context in_context,
keyblock_contents = NULL;
/* copy times */
- out_creds->times.authtime = cv5->authtime + offset_seconds;
- out_creds->times.starttime = cv5->starttime + offset_seconds;
- out_creds->times.endtime = cv5->endtime + offset_seconds;
- out_creds->times.renew_till = cv5->renew_till + offset_seconds;
+ out_creds->times.authtime = ts_incr(cv5->authtime, offset_seconds);
+ out_creds->times.starttime = ts_incr(cv5->starttime, offset_seconds);
+ out_creds->times.endtime = ts_incr(cv5->endtime, offset_seconds);
+ out_creds->times.renew_till = ts_incr(cv5->renew_till, offset_seconds);
out_creds->is_skey = cv5->is_skey;
out_creds->ticket_flags = cv5->ticket_flags;
@@ -451,11 +451,11 @@ copy_krb5_creds_to_cc_cred_union (krb5_context in_context,
cv5->keyblock.data = keyblock_data;
keyblock_data = NULL;
- cv5->authtime = in_creds->times.authtime - offset_seconds;
- cv5->starttime = in_creds->times.starttime - offset_seconds;
- cv5->endtime = in_creds->times.endtime - offset_seconds;
- cv5->renew_till = in_creds->times.renew_till - offset_seconds;
- cv5->is_skey = in_creds->is_skey;
+ cv5->authtime = ts_incr(in_creds->times.authtime, -offset_seconds);
+ cv5->starttime = ts_incr(in_creds->times.starttime, -offset_seconds);
+ cv5->endtime = ts_incr(in_creds->times.endtime, -offset_seconds);
+ cv5->renew_till = ts_incr(in_creds->times.renew_till, -offset_seconds);
+ cv5->is_skey = in_creds->is_skey;
cv5->ticket_flags = in_creds->ticket_flags;
if (in_creds->ticket.data) {
@@ -732,10 +732,10 @@ void dupCCtoK5(krb5_context context, cc_creds *src, krb5_creds *dest)
err = krb5_get_time_offsets(context, &offset_seconds, &offset_microseconds);
if (err) return;
#endif
- dest->times.authtime = src->authtime + offset_seconds;
- dest->times.starttime = src->starttime + offset_seconds;
- dest->times.endtime = src->endtime + offset_seconds;
- dest->times.renew_till = src->renew_till + offset_seconds;
+ dest->times.authtime = ts_incr(src->authtime, offset_seconds);
+ dest->times.starttime = ts_incr(src->starttime, offset_seconds);
+ dest->times.endtime = ts_incr(src->endtime, offset_seconds);
+ dest->times.renew_till = ts_incr(src->renew_till, offset_seconds);
dest->is_skey = src->is_skey;
dest->ticket_flags = src->ticket_flags;
@@ -804,10 +804,10 @@ void dupK5toCC(krb5_context context, krb5_creds *creds, cred_union **cu)
err = krb5_get_time_offsets(context, &offset_seconds, &offset_microseconds);
if (err) return;
#endif
- c->authtime = creds->times.authtime - offset_seconds;
- c->starttime = creds->times.starttime - offset_seconds;
- c->endtime = creds->times.endtime - offset_seconds;
- c->renew_till = creds->times.renew_till - offset_seconds;
+ c->authtime = ts_incr(creds->times.authtime, -offset_seconds);
+ c->starttime = ts_incr(creds->times.starttime, -offset_seconds);
+ c->endtime = ts_incr(creds->times.endtime, -offset_seconds);
+ c->renew_till = ts_incr(creds->times.renew_till, -offset_seconds);
c->is_skey = creds->is_skey;
c->ticket_flags = creds->ticket_flags;
@@ -925,11 +925,11 @@ times_match(t1, t2)
register const krb5_ticket_times *t2;
{
if (t1->renew_till) {
- if (t1->renew_till > t2->renew_till)
+ if (ts_after(t1->renew_till, t2->renew_till))
return FALSE; /* this one expires too late */
}
if (t1->endtime) {
- if (t1->endtime > t2->endtime)
+ if (ts_after(t1->endtime, t2->endtime))
return FALSE; /* this one expires too late */
}
/* only care about expiration on a times_match */
diff --git a/src/lib/krb5/ccache/cccursor.c b/src/lib/krb5/ccache/cccursor.c
index c31a3f5f0b87..506a27c1b969 100644
--- a/src/lib/krb5/ccache/cccursor.c
+++ b/src/lib/krb5/ccache/cccursor.c
@@ -159,7 +159,7 @@ krb5_cccol_last_change_time(krb5_context context,
ret = krb5_cccol_cursor_next(context, c, &ccache);
if (ccache) {
ret = krb5_cc_last_change_time(context, ccache, &last_time);
- if (!ret && last_time > max_change_time) {
+ if (!ret && ts_after(last_time, max_change_time)) {
max_change_time = last_time;
}
ret = 0;
@@ -230,14 +230,37 @@ save_first_error(krb5_context context, krb5_error_code code,
k5_save_ctx_error(context, code, errsave);
}
+/* Return 0 if cache contains any non-config credentials. Return KRB5_CC_END
+ * if it does not, or another error if we failed to read through it. */
+static krb5_error_code
+has_content(krb5_context context, krb5_ccache cache)
+{
+ krb5_error_code ret;
+ krb5_boolean found = FALSE;
+ krb5_cc_cursor cache_cursor;
+ krb5_creds creds;
+
+ ret = krb5_cc_start_seq_get(context, cache, &cache_cursor);
+ if (ret)
+ return ret;
+ while (!found) {
+ ret = krb5_cc_next_cred(context, cache, &cache_cursor, &creds);
+ if (ret)
+ break;
+ if (!krb5_is_config_principal(context, creds.server))
+ found = TRUE;
+ krb5_free_cred_contents(context, &creds);
+ }
+ krb5_cc_end_seq_get(context, cache, &cache_cursor);
+ return ret;
+}
+
krb5_error_code KRB5_CALLCONV
krb5_cccol_have_content(krb5_context context)
{
krb5_error_code ret;
krb5_cccol_cursor col_cursor;
- krb5_cc_cursor cache_cursor;
krb5_ccache cache;
- krb5_creds creds;
krb5_boolean found = FALSE;
struct errinfo errsave = EMPTY_ERRINFO;
const char *defname;
@@ -252,24 +275,10 @@ krb5_cccol_have_content(krb5_context context)
save_first_error(context, ret, &errsave);
if (ret || cache == NULL)
break;
-
- ret = krb5_cc_start_seq_get(context, cache, &cache_cursor);
+ ret = has_content(context, cache);
save_first_error(context, ret, &errsave);
- if (ret) {
- krb5_cc_close(context, cache);
- continue;
- }
- while (!found) {
- ret = krb5_cc_next_cred(context, cache, &cache_cursor, &creds);
- save_first_error(context, ret, &errsave);
- if (ret)
- break;
-
- if (!krb5_is_config_principal(context, creds.server))
- found = TRUE;
- krb5_free_cred_contents(context, &creds);
- }
- krb5_cc_end_seq_get(context, cache, &cache_cursor);
+ if (!ret)
+ found = TRUE;
krb5_cc_close(context, cache);
}
krb5_cccol_cursor_free(context, &col_cursor);
diff --git a/src/lib/krb5/ccache/ccmarshal.c b/src/lib/krb5/ccache/ccmarshal.c
index bd6d309d1d4e..ae634ccab0d2 100644
--- a/src/lib/krb5/ccache/ccmarshal.c
+++ b/src/lib/krb5/ccache/ccmarshal.c
@@ -100,8 +100,8 @@
* second value when reading it.
*/
-#include "k5-input.h"
#include "cc-int.h"
+#include "k5-input.h"
/* Read a 16-bit integer in host byte order for versions 1 and 2, or in
* big-endian byte order for later versions.*/
diff --git a/src/lib/krb5/ccache/ccselect.c b/src/lib/krb5/ccache/ccselect.c
index 2f3071a272a2..6c360e1002ec 100644
--- a/src/lib/krb5/ccache/ccselect.c
+++ b/src/lib/krb5/ccache/ccselect.c
@@ -71,6 +71,11 @@ load_modules(krb5_context context)
if (ret != 0)
goto cleanup;
+ ret = k5_plugin_register(context, PLUGIN_INTERFACE_CCSELECT, "hostname",
+ ccselect_hostname_initvt);
+ if (ret != 0)
+ goto cleanup;
+
ret = k5_plugin_load_all(context, PLUGIN_INTERFACE_CCSELECT, &modules);
if (ret != 0)
goto cleanup;
@@ -115,14 +120,6 @@ cleanup:
return ret;
}
-static krb5_error_code
-choose(krb5_context context, struct ccselect_module_handle *h,
- krb5_principal server, krb5_ccache *cache_out,
- krb5_principal *princ_out)
-{
- return h->vt.choose(context, h->data, server, cache_out, princ_out);
-}
-
krb5_error_code KRB5_CALLCONV
krb5_cc_select(krb5_context context, krb5_principal server,
krb5_ccache *cache_out, krb5_principal *princ_out)
@@ -132,6 +129,8 @@ krb5_cc_select(krb5_context context, krb5_principal server,
struct ccselect_module_handle **hp, *h;
krb5_ccache cache;
krb5_principal princ;
+ krb5_principal srvcp = NULL;
+ char **fbrealms = NULL;
*cache_out = NULL;
*princ_out = NULL;
@@ -139,7 +138,27 @@ krb5_cc_select(krb5_context context, krb5_principal server,
if (context->ccselect_handles == NULL) {
ret = load_modules(context);
if (ret)
- return ret;
+ goto cleanup;
+ }
+
+ /* Try to use the fallback host realm for the server if there is no
+ * authoritative realm. */
+ if (krb5_is_referral_realm(&server->realm) &&
+ server->type == KRB5_NT_SRV_HST && server->length == 2) {
+ ret = krb5_get_fallback_host_realm(context, &server->data[1],
+ &fbrealms);
+ if (ret)
+ goto cleanup;
+
+ /* Make a copy with the first fallback realm. */
+ ret = krb5_copy_principal(context, server, &srvcp);
+ if (ret)
+ goto cleanup;
+ ret = krb5_set_principal_realm(context, srvcp, fbrealms[0]);
+ if (ret)
+ goto cleanup;
+
+ server = srvcp;
}
/* Consult authoritative modules first, then heuristic ones. */
@@ -149,26 +168,31 @@ krb5_cc_select(krb5_context context, krb5_principal server,
h = *hp;
if (h->priority != priority)
continue;
- ret = choose(context, h, server, &cache, &princ);
+ ret = h->vt.choose(context, h->data, server, &cache, &princ);
if (ret == 0) {
TRACE_CCSELECT_MODCHOICE(context, h->vt.name, server, cache,
princ);
*cache_out = cache;
*princ_out = princ;
- return 0;
+ goto cleanup;
} else if (ret == KRB5_CC_NOTFOUND) {
TRACE_CCSELECT_MODNOTFOUND(context, h->vt.name, server, princ);
*princ_out = princ;
- return ret;
+ goto cleanup;
} else if (ret != KRB5_PLUGIN_NO_HANDLE) {
TRACE_CCSELECT_MODFAIL(context, h->vt.name, ret, server);
- return ret;
+ goto cleanup;
}
}
}
TRACE_CCSELECT_NOTFOUND(context, server);
- return KRB5_CC_NOTFOUND;
+ ret = KRB5_CC_NOTFOUND;
+
+cleanup:
+ krb5_free_principal(context, srvcp);
+ krb5_free_host_realm(context, fbrealms);
+ return ret;
}
void
diff --git a/src/lib/krb5/ccache/ccselect_hostname.c b/src/lib/krb5/ccache/ccselect_hostname.c
new file mode 100644
index 000000000000..475cfabaefd7
--- /dev/null
+++ b/src/lib/krb5/ccache/ccselect_hostname.c
@@ -0,0 +1,146 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/ccache/ccselect_hostname.c - hostname ccselect module */
+/*
+ * Copyright (C) 2017 by Red Hat, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "k5-int.h"
+#include "cc-int.h"
+#include <ctype.h>
+#include <krb5/ccselect_plugin.h>
+
+/* Swap a and b, using tmp as an intermediate. */
+#define SWAP(a, b, tmp) \
+ tmp = a; \
+ a = b; \
+ b = tmp;
+
+static krb5_error_code
+hostname_init(krb5_context context, krb5_ccselect_moddata *data_out,
+ int *priority_out)
+{
+ *data_out = NULL;
+ *priority_out = KRB5_CCSELECT_PRIORITY_HEURISTIC;
+ return 0;
+}
+
+static krb5_error_code
+hostname_choose(krb5_context context, krb5_ccselect_moddata data,
+ krb5_principal server, krb5_ccache *ccache_out,
+ krb5_principal *princ_out)
+{
+ krb5_error_code ret;
+ char *p, *host = NULL;
+ size_t hostlen;
+ krb5_cccol_cursor col_cursor;
+ krb5_ccache ccache, tmp_ccache, best_ccache = NULL;
+ krb5_principal princ, tmp_princ, best_princ = NULL;
+ krb5_data domain;
+
+ *ccache_out = NULL;
+ *princ_out = NULL;
+
+ if (server->type != KRB5_NT_SRV_HST || server->length < 2)
+ return KRB5_PLUGIN_NO_HANDLE;
+
+ /* Compute upper-case hostname. */
+ hostlen = server->data[1].length;
+ host = k5memdup0(server->data[1].data, hostlen, &ret);
+ if (host == NULL)
+ return ret;
+ for (p = host; *p != '\0'; p++) {
+ if (islower(*p))
+ *p = toupper(*p);
+ }
+
+ /* Scan the collection for a cache with a client principal whose realm is
+ * the longest tail of the server hostname. */
+ ret = krb5_cccol_cursor_new(context, &col_cursor);
+ if (ret)
+ goto done;
+
+ for (ret = krb5_cccol_cursor_next(context, col_cursor, &ccache);
+ ret == 0 && ccache != NULL;
+ ret = krb5_cccol_cursor_next(context, col_cursor, &ccache)) {
+ ret = krb5_cc_get_principal(context, ccache, &princ);
+ if (ret) {
+ krb5_cc_close(context, ccache);
+ break;
+ }
+
+ /* Check for a longer match than we have. */
+ domain = make_data(host, hostlen);
+ while (best_princ == NULL ||
+ best_princ->realm.length < domain.length) {
+ if (data_eq(princ->realm, domain)) {
+ SWAP(best_ccache, ccache, tmp_ccache);
+ SWAP(best_princ, princ, tmp_princ);
+ break;
+ }
+
+ /* Try the next parent domain. */
+ p = memchr(domain.data, '.', domain.length);
+ if (p == NULL)
+ break;
+ domain = make_data(p + 1, hostlen - (p + 1 - host));
+ }
+
+ if (ccache != NULL)
+ krb5_cc_close(context, ccache);
+ krb5_free_principal(context, princ);
+ }
+
+ krb5_cccol_cursor_free(context, &col_cursor);
+
+ if (best_ccache != NULL) {
+ *ccache_out = best_ccache;
+ *princ_out = best_princ;
+ } else {
+ ret = KRB5_PLUGIN_NO_HANDLE;
+ }
+
+done:
+ free(host);
+ return ret;
+}
+
+krb5_error_code
+ccselect_hostname_initvt(krb5_context context, int maj_ver, int min_ver,
+ krb5_plugin_vtable vtable)
+{
+ krb5_ccselect_vtable vt;
+
+ if (maj_ver != 1)
+ return KRB5_PLUGIN_VER_NOTSUPP;
+ vt = (krb5_ccselect_vtable)vtable;
+ vt->name = "hostname";
+ vt->init = hostname_init;
+ vt->choose = hostname_choose;
+ return 0;
+}
diff --git a/src/lib/krb5/ccache/deps b/src/lib/krb5/ccache/deps
index 9cd2e00d456c..6732f75548ce 100644
--- a/src/lib/krb5/ccache/deps
+++ b/src/lib/krb5/ccache/deps
@@ -78,6 +78,17 @@ ccselect.so ccselect.po $(OUTPRE)ccselect.$(OBJEXT): \
$(top_srcdir)/include/krb5/ccselect_plugin.h $(top_srcdir)/include/krb5/plugin.h \
$(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
cc-int.h ccselect.c
+ccselect_hostname.so ccselect_hostname.po $(OUTPRE)ccselect_hostname.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/ccselect_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h cc-int.h ccselect_hostname.c
ccselect_k5identity.so ccselect_k5identity.po $(OUTPRE)ccselect_k5identity.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
diff --git a/src/lib/krb5/keytab/kt_file.c b/src/lib/krb5/keytab/kt_file.c
index 6a42f267df7d..091f2c43fa3a 100644
--- a/src/lib/krb5/keytab/kt_file.c
+++ b/src/lib/krb5/keytab/kt_file.c
@@ -264,9 +264,11 @@ more_recent(const krb5_keytab_entry *k1, const krb5_keytab_entry *k2)
* limitations (8-bit kvno storage), pre-1.14 kadmin protocol limitations
* (8-bit kvno marshalling), or KDB limitations (16-bit kvno storage).
*/
- if (k1->timestamp >= k2->timestamp && k1->vno < 128 && k2->vno > 240)
+ if (!ts_after(k2->timestamp, k1->timestamp) &&
+ k1->vno < 128 && k2->vno > 240)
return TRUE;
- if (k1->timestamp <= k2->timestamp && k1->vno > 240 && k2->vno < 128)
+ if (!ts_after(k1->timestamp, k2->timestamp) &&
+ k1->vno > 240 && k2->vno < 128)
return FALSE;
/* Otherwise do a simple version comparison. */
@@ -357,7 +359,7 @@ krb5_ktfile_get_entry(krb5_context context, krb5_keytab id,
}
- if (kvno == IGNORE_VNO) {
+ if (kvno == IGNORE_VNO || new_entry.vno == IGNORE_VNO) {
/* If this entry is more recent (or the first match), free the
* current and keep the new. Otherwise, free the new. */
if (cur_entry.principal == NULL ||
diff --git a/src/lib/krb5/keytab/kt_memory.c b/src/lib/krb5/keytab/kt_memory.c
index e89fdcb4dc99..8824adf50826 100644
--- a/src/lib/krb5/keytab/kt_memory.c
+++ b/src/lib/krb5/keytab/kt_memory.c
@@ -403,7 +403,7 @@ krb5_mkt_get_entry(krb5_context context, krb5_keytab id,
continue;
}
- if (kvno == IGNORE_VNO) {
+ if (kvno == IGNORE_VNO || entry->vno == IGNORE_VNO) {
if (match == NULL)
match = entry;
else if (entry->vno > match->vno)
diff --git a/src/lib/krb5/keytab/kt_srvtab.c b/src/lib/krb5/keytab/kt_srvtab.c
index caa0158ecc2b..bbfaadfc298c 100644
--- a/src/lib/krb5/keytab/kt_srvtab.c
+++ b/src/lib/krb5/keytab/kt_srvtab.c
@@ -205,7 +205,7 @@ krb5_ktsrvtab_get_entry(krb5_context context, krb5_keytab id, krb5_const_princip
while ((kerror = krb5_ktsrvint_read_entry(context, id, &ent)) == 0) {
ent.key.enctype = enctype;
if (krb5_principal_compare(context, principal, ent.principal)) {
- if (kvno == IGNORE_VNO) {
+ if (kvno == IGNORE_VNO || ent.vno == IGNORE_VNO) {
if (!best_entry.principal || (best_entry.vno < ent.vno)) {
krb5_kt_free_entry(context, &best_entry);
best_entry = ent;
diff --git a/src/lib/krb5/krb/Makefile.in b/src/lib/krb5/krb/Makefile.in
index 0fe02a95d09e..55f82b147d8c 100644
--- a/src/lib/krb5/krb/Makefile.in
+++ b/src/lib/krb5/krb/Makefile.in
@@ -364,6 +364,7 @@ SRCS= $(srcdir)/addr_comp.c \
$(srcdir)/t_in_ccache.c \
$(srcdir)/t_response_items.c \
$(srcdir)/t_sname_match.c \
+ $(srcdir)/t_valid_times.c \
$(srcdir)/t_vfy_increds.c
# Someday, when we have a "maintainer mode", do this right:
@@ -457,9 +458,12 @@ t_response_items: t_response_items.o response_items.o $(KRB5_BASE_DEPLIBS)
t_sname_match: t_sname_match.o sname_match.o $(KRB5_BASE_DEPLIBS)
$(CC_LINK) -o $@ t_sname_match.o sname_match.o $(KRB5_BASE_LIBS)
+t_valid_times: t_valid_times.o valid_times.o $(KRB5_BASE_DEPLIBS)
+ $(CC_LINK) -o $@ t_valid_times.o valid_times.o $(KRB5_BASE_LIBS)
+
TEST_PROGS= t_walk_rtree t_kerb t_ser t_deltat t_expand t_authdata t_pac \
- t_in_ccache t_cc_config t_copy_context \
- t_princ t_etypes t_vfy_increds t_response_items t_sname_match
+ t_in_ccache t_cc_config t_copy_context t_princ t_etypes t_vfy_increds \
+ t_response_items t_sname_match t_valid_times
check-unix: $(TEST_PROGS)
$(RUN_TEST_LOCAL_CONF) ./t_kerb \
@@ -496,6 +500,7 @@ check-unix: $(TEST_PROGS)
$(RUN_TEST) ./t_response_items
$(RUN_TEST) ./t_copy_context
$(RUN_TEST) ./t_sname_match
+ $(RUN_TEST) ./t_valid_times
check-pytests: t_expire_warn t_vfy_increds
$(RUNPYTEST) $(srcdir)/t_expire_warn.py $(PYTESTFLAGS)
@@ -522,8 +527,9 @@ clean:
$(OUTPRE)t_ad_fx_armor$(EXEEXT) $(OUTPRE)t_ad_fx_armor.$(OBJEXT) \
$(OUTPRE)t_vfy_increds$(EXEEXT) $(OUTPRE)t_vfy_increds.$(OBJEXT) \
$(OUTPRE)t_response_items$(EXEEXT) \
- $(OUTPRE)t_response_items.$(OBJEXT) $(OUTPRE)t_sname_match$(EXEEXT) \
- $(OUTPRE)t_sname_match.$(OBJEXT) \
+ $(OUTPRE)t_response_items.$(OBJEXT) \
+ $(OUTPRE)t_sname_match$(EXEEXT) $(OUTPRE)t_sname_match.$(OBJEXT) \
+ $(OUTPRE)t_valid_times$(EXEEXT) $(OUTPRE)t_valid_times.$(OBJECT) \
$(OUTPRE)t_parse_host_string$(EXEEXT) \
$(OUTPRE)t_parse_host_string.$(OBJEXT)
diff --git a/src/lib/krb5/krb/deltat.c b/src/lib/krb5/krb/deltat.c
index 2c8b90b54ce3..6e6616e99ff8 100644
--- a/src/lib/krb5/krb/deltat.c
+++ b/src/lib/krb5/krb/deltat.c
@@ -72,7 +72,6 @@
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
#include "k5-int.h"
@@ -153,7 +152,7 @@ static int mylex(int *intp, struct param *tmv);
static int yyparse(struct param *);
-#line 157 "deltat.c" /* yacc.c:339 */
+#line 156 "deltat.c" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
@@ -197,10 +196,10 @@ extern int yydebug;
typedef union YYSTYPE YYSTYPE;
union YYSTYPE
{
-#line 129 "x-deltat.y" /* yacc.c:355 */
+#line 128 "x-deltat.y" /* yacc.c:355 */
int val;
-#line 204 "deltat.c" /* yacc.c:355 */
+#line 203 "deltat.c" /* yacc.c:355 */
};
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
@@ -214,7 +213,7 @@ int yyparse (struct param *tmv);
/* Copy the second part of user declarations. */
-#line 218 "deltat.c" /* yacc.c:358 */
+#line 217 "deltat.c" /* yacc.c:358 */
#ifdef short
# undef short
@@ -512,9 +511,9 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 143, 143, 144, 144, 145, 145, 146, 146, 147,
- 148, 150, 151, 152, 153, 154, 155, 156, 157, 162,
- 163, 166, 167, 170, 171
+ 0, 142, 142, 143, 143, 144, 144, 145, 145, 146,
+ 147, 149, 150, 151, 152, 153, 154, 155, 156, 161,
+ 162, 165, 166, 169, 170
};
#endif
@@ -1310,93 +1309,93 @@ yyreduce:
switch (yyn)
{
case 6:
-#line 145 "x-deltat.y" /* yacc.c:1646 */
+#line 144 "x-deltat.y" /* yacc.c:1646 */
{ (yyval.val) = - (yyvsp[0].val); }
-#line 1316 "deltat.c" /* yacc.c:1646 */
+#line 1315 "deltat.c" /* yacc.c:1646 */
break;
case 9:
-#line 147 "x-deltat.y" /* yacc.c:1646 */
+#line 146 "x-deltat.y" /* yacc.c:1646 */
{ (yyval.val) = (yyvsp[0].val); }
-#line 1322 "deltat.c" /* yacc.c:1646 */
+#line 1321 "deltat.c" /* yacc.c:1646 */
break;
case 10:
-#line 148 "x-deltat.y" /* yacc.c:1646 */
+#line 147 "x-deltat.y" /* yacc.c:1646 */
{ YYERROR; }
-#line 1328 "deltat.c" /* yacc.c:1646 */
+#line 1327 "deltat.c" /* yacc.c:1646 */
break;
case 11:
-#line 150 "x-deltat.y" /* yacc.c:1646 */
+#line 149 "x-deltat.y" /* yacc.c:1646 */
{ DO ((yyvsp[-2].val), 0, 0, (yyvsp[0].val)); }
-#line 1334 "deltat.c" /* yacc.c:1646 */
+#line 1333 "deltat.c" /* yacc.c:1646 */
break;
case 12:
-#line 151 "x-deltat.y" /* yacc.c:1646 */
+#line 150 "x-deltat.y" /* yacc.c:1646 */
{ DO ( 0, (yyvsp[-2].val), 0, (yyvsp[0].val)); }
-#line 1340 "deltat.c" /* yacc.c:1646 */
+#line 1339 "deltat.c" /* yacc.c:1646 */
break;
case 13:
-#line 152 "x-deltat.y" /* yacc.c:1646 */
+#line 151 "x-deltat.y" /* yacc.c:1646 */
{ DO ( 0, 0, (yyvsp[-2].val), (yyvsp[0].val)); }
-#line 1346 "deltat.c" /* yacc.c:1646 */
+#line 1345 "deltat.c" /* yacc.c:1646 */
break;
case 14:
-#line 153 "x-deltat.y" /* yacc.c:1646 */
+#line 152 "x-deltat.y" /* yacc.c:1646 */
{ DO ( 0, 0, 0, (yyvsp[-1].val)); }
-#line 1352 "deltat.c" /* yacc.c:1646 */
+#line 1351 "deltat.c" /* yacc.c:1646 */
break;
case 15:
-#line 154 "x-deltat.y" /* yacc.c:1646 */
+#line 153 "x-deltat.y" /* yacc.c:1646 */
{ DO ((yyvsp[-6].val), (yyvsp[-4].val), (yyvsp[-2].val), (yyvsp[0].val)); }
-#line 1358 "deltat.c" /* yacc.c:1646 */
+#line 1357 "deltat.c" /* yacc.c:1646 */
break;
case 16:
-#line 155 "x-deltat.y" /* yacc.c:1646 */
+#line 154 "x-deltat.y" /* yacc.c:1646 */
{ DO ( 0, (yyvsp[-4].val), (yyvsp[-2].val), (yyvsp[0].val)); }
-#line 1364 "deltat.c" /* yacc.c:1646 */
+#line 1363 "deltat.c" /* yacc.c:1646 */
break;
case 17:
-#line 156 "x-deltat.y" /* yacc.c:1646 */
+#line 155 "x-deltat.y" /* yacc.c:1646 */
{ DO ( 0, (yyvsp[-2].val), (yyvsp[0].val), 0); }
-#line 1370 "deltat.c" /* yacc.c:1646 */
+#line 1369 "deltat.c" /* yacc.c:1646 */
break;
case 18:
-#line 157 "x-deltat.y" /* yacc.c:1646 */
+#line 156 "x-deltat.y" /* yacc.c:1646 */
{ DO ( 0, 0, 0, (yyvsp[0].val)); }
-#line 1376 "deltat.c" /* yacc.c:1646 */
+#line 1375 "deltat.c" /* yacc.c:1646 */
break;
case 20:
-#line 163 "x-deltat.y" /* yacc.c:1646 */
+#line 162 "x-deltat.y" /* yacc.c:1646 */
{ if (HOUR_NOT_OK((yyvsp[-2].val))) YYERROR;
DO_SUM((yyval.val), (yyvsp[-2].val) * 3600, (yyvsp[0].val)); }
-#line 1383 "deltat.c" /* yacc.c:1646 */
+#line 1382 "deltat.c" /* yacc.c:1646 */
break;
case 22:
-#line 167 "x-deltat.y" /* yacc.c:1646 */
+#line 166 "x-deltat.y" /* yacc.c:1646 */
{ if (MIN_NOT_OK((yyvsp[-2].val))) YYERROR;
DO_SUM((yyval.val), (yyvsp[-2].val) * 60, (yyvsp[0].val)); }
-#line 1390 "deltat.c" /* yacc.c:1646 */
+#line 1389 "deltat.c" /* yacc.c:1646 */
break;
case 23:
-#line 170 "x-deltat.y" /* yacc.c:1646 */
+#line 169 "x-deltat.y" /* yacc.c:1646 */
{ (yyval.val) = 0; }
-#line 1396 "deltat.c" /* yacc.c:1646 */
+#line 1395 "deltat.c" /* yacc.c:1646 */
break;
-#line 1400 "deltat.c" /* yacc.c:1646 */
+#line 1399 "deltat.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1624,7 +1623,7 @@ yyreturn:
#endif
return yyresult;
}
-#line 173 "x-deltat.y" /* yacc.c:1906 */
+#line 172 "x-deltat.y" /* yacc.c:1906 */
#ifdef __GNUC__
diff --git a/src/lib/krb5/krb/deps b/src/lib/krb5/krb/deps
index 6919eaf717aa..f78b47e766e1 100644
--- a/src/lib/krb5/krb/deps
+++ b/src/lib/krb5/krb/deps
@@ -1236,8 +1236,15 @@ t_walk_rtree.so t_walk_rtree.po $(OUTPRE)t_walk_rtree.$(OBJEXT): \
$(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
t_walk_rtree.c
t_kerb.so t_kerb.po $(OUTPRE)t_kerb.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
- $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(top_srcdir)/include/krb5.h \
- t_kerb.c
+ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
+ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h t_kerb.c
t_ser.so t_ser.po $(OUTPRE)t_ser.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
$(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
@@ -1283,14 +1290,14 @@ t_pac.so t_pac.po $(OUTPRE)t_pac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
t_parse_host_string.so t_parse_host_string.po $(OUTPRE)t_parse_host_string.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
- $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
- $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
- t_parse_host_string.c
+ $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-cmocka.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
+ $(top_srcdir)/include/socket-utils.h t_parse_host_string.c
t_princ.so t_princ.po $(OUTPRE)t_princ.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
$(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h \
@@ -1389,6 +1396,17 @@ t_sname_match.so t_sname_match.po $(OUTPRE)t_sname_match.$(OBJEXT): \
$(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
$(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
t_sname_match.c
+t_valid_times.so t_valid_times.po $(OUTPRE)t_valid_times.$(OBJEXT): \
+ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
+ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
+ $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
+ $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
+ $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
+ $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
+ $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
+ $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
+ int-proto.h t_valid_times.c
t_vfy_increds.so t_vfy_increds.po $(OUTPRE)t_vfy_increds.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
diff --git a/src/lib/krb5/krb/fwd_tgt.c b/src/lib/krb5/krb/fwd_tgt.c
index a217d4c24001..87f63b6bc4c8 100644
--- a/src/lib/krb5/krb/fwd_tgt.c
+++ b/src/lib/krb5/krb/fwd_tgt.c
@@ -37,8 +37,9 @@
/* Get a TGT for use at the remote host */
krb5_error_code KRB5_CALLCONV
krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context,
- char *rhost, krb5_principal client, krb5_principal server,
- krb5_ccache cc, int forwardable, krb5_data *outbuf)
+ const char *rhost, krb5_principal client,
+ krb5_principal server, krb5_ccache cc, int forwardable,
+ krb5_data *outbuf)
/* Should forwarded TGT also be forwardable? */
{
krb5_replay_data replaydata;
@@ -48,8 +49,8 @@ krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context,
krb5_creds creds, tgt;
krb5_creds *pcreds;
krb5_flags kdcoptions;
- int close_cc = 0;
- int free_rhost = 0;
+ krb5_ccache defcc = NULL;
+ char *def_rhost = NULL;
krb5_enctype enctype = 0;
krb5_keyblock *session_key;
krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes;
@@ -58,9 +59,9 @@ krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context,
memset(&tgt, 0, sizeof(creds));
if (cc == 0) {
- if ((retval = krb5int_cc_default(context, &cc)))
+ if ((retval = krb5int_cc_default(context, &defcc)))
goto errout;
- close_cc = 1;
+ cc = defcc;
}
retval = krb5_auth_con_getkey (context, auth_context, &session_key);
if (retval)
@@ -131,11 +132,11 @@ krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context,
goto errout;
}
- rhost = k5memdup0(server->data[1].data, server->data[1].length,
- &retval);
- if (rhost == NULL)
+ def_rhost = k5memdup0(server->data[1].data, server->data[1].length,
+ &retval);
+ if (def_rhost == NULL)
goto errout;
- free_rhost = 1;
+ rhost = def_rhost;
}
retval = k5_os_hostaddr(context, rhost, &addrs);
@@ -176,10 +177,9 @@ krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context,
errout:
if (addrs)
krb5_free_addresses(context, addrs);
- if (close_cc)
- krb5_cc_close(context, cc);
- if (free_rhost)
- free(rhost);
+ if (defcc)
+ krb5_cc_close(context, defcc);
+ free(def_rhost);
krb5_free_cred_contents(context, &creds);
krb5_free_cred_contents(context, &tgt);
return retval;
diff --git a/src/lib/krb5/krb/gc_via_tkt.c b/src/lib/krb5/krb/gc_via_tkt.c
index 4c0a1a46120a..5b9bb9573e27 100644
--- a/src/lib/krb5/krb/gc_via_tkt.c
+++ b/src/lib/krb5/krb/gc_via_tkt.c
@@ -287,26 +287,27 @@ krb5int_process_tgs_reply(krb5_context context,
retval = KRB5_KDCREP_MODIFIED;
if ((in_cred->times.endtime != 0) &&
- (dec_rep->enc_part2->times.endtime > in_cred->times.endtime))
+ ts_after(dec_rep->enc_part2->times.endtime, in_cred->times.endtime))
retval = KRB5_KDCREP_MODIFIED;
if ((kdcoptions & KDC_OPT_RENEWABLE) &&
(in_cred->times.renew_till != 0) &&
- (dec_rep->enc_part2->times.renew_till > in_cred->times.renew_till))
+ ts_after(dec_rep->enc_part2->times.renew_till,
+ in_cred->times.renew_till))
retval = KRB5_KDCREP_MODIFIED;
if ((kdcoptions & KDC_OPT_RENEWABLE_OK) &&
(dec_rep->enc_part2->flags & KDC_OPT_RENEWABLE) &&
(in_cred->times.endtime != 0) &&
- (dec_rep->enc_part2->times.renew_till > in_cred->times.endtime))
+ ts_after(dec_rep->enc_part2->times.renew_till, in_cred->times.endtime))
retval = KRB5_KDCREP_MODIFIED;
if (retval != 0)
goto cleanup;
if (!in_cred->times.starttime &&
- !in_clock_skew(dec_rep->enc_part2->times.starttime,
- timestamp)) {
+ !ts_within(dec_rep->enc_part2->times.starttime, timestamp,
+ context->clockskew)) {
retval = KRB5_KDCREP_SKEW;
goto cleanup;
}
diff --git a/src/lib/krb5/krb/gen_save_subkey.c b/src/lib/krb5/krb/gen_save_subkey.c
index 61f36aa3665f..bc2c46d30c22 100644
--- a/src/lib/krb5/krb/gen_save_subkey.c
+++ b/src/lib/krb5/krb/gen_save_subkey.c
@@ -38,7 +38,8 @@ k5_generate_and_save_subkey(krb5_context context,
to guarantee randomness, but to make it less likely that multiple
sessions could pick the same subkey. */
struct {
- krb5_int32 sec, usec;
+ krb5_timestamp sec;
+ krb5_int32 usec;
} rnd_data;
krb5_data d;
krb5_error_code retval;
diff --git a/src/lib/krb5/krb/get_creds.c b/src/lib/krb5/krb/get_creds.c
index 110abeb2b1bd..69900adfa046 100644
--- a/src/lib/krb5/krb/get_creds.c
+++ b/src/lib/krb5/krb/get_creds.c
@@ -576,14 +576,6 @@ step_referrals(krb5_context context, krb5_tkt_creds_context ctx)
}
if (ctx->referral_count == 1) {
- /* Cache the referral TGT only if it's from the local realm.
- * Make sure to note the associated authdata, if any. */
- code = krb5_copy_authdata(context, ctx->authdata,
- &ctx->reply_creds->authdata);
- if (code != 0)
- return code;
- (void) krb5_cc_store_cred(context, ctx->ccache, ctx->reply_creds);
-
/* The authdata in this TGT will be copied into subsequent TGTs or the
* final credentials, so we don't need to request it again. */
krb5_free_authdata(context, ctx->in_creds->authdata);
@@ -816,7 +808,7 @@ get_cached_local_tgt(krb5_context context, krb5_tkt_creds_context ctx,
return code;
/* Check if the TGT is expired before bothering the KDC with it. */
- if (now > tgt->times.endtime) {
+ if (ts_after(now, tgt->times.endtime)) {
krb5_free_creds(context, tgt);
return KRB5KRB_AP_ERR_TKT_EXPIRED;
}
@@ -934,8 +926,9 @@ step_get_tgt(krb5_context context, krb5_tkt_creds_context ctx)
/* See where we wound up on the path (or off it). */
path_realm = find_realm_in_path(context, ctx, tgt_realm);
if (path_realm != NULL) {
- /* We got a realm on the expected path, so we can cache it. */
- (void) krb5_cc_store_cred(context, ctx->ccache, ctx->cur_tgt);
+ /* Only cache the TGT if we asked for it, to avoid duplicates. */
+ if (path_realm == ctx->next_realm)
+ (void)krb5_cc_store_cred(context, ctx->ccache, ctx->cur_tgt);
if (path_realm == ctx->last_realm) {
/* We received a TGT for the target realm. */
TRACE_TKT_CREDS_TARGET_TGT(context, ctx->cur_tgt->server);
diff --git a/src/lib/krb5/krb/get_in_tkt.c b/src/lib/krb5/krb/get_in_tkt.c
index 54badbbc32f8..47a00bf2c702 100644
--- a/src/lib/krb5/krb/get_in_tkt.c
+++ b/src/lib/krb5/krb/get_in_tkt.c
@@ -40,24 +40,6 @@ static krb5_error_code sort_krb5_padata_sequence(krb5_context context,
krb5_pa_data **padata);
/*
- * This function performs 32 bit bounded addition so we can generate
- * lifetimes without overflowing krb5_int32
- */
-static krb5_int32
-krb5int_addint32 (krb5_int32 x, krb5_int32 y)
-{
- if ((x > 0) && (y > (KRB5_INT32_MAX - x))) {
- /* sum will be be greater than KRB5_INT32_MAX */
- return KRB5_INT32_MAX;
- } else if ((x < 0) && (y < (KRB5_INT32_MIN - x))) {
- /* sum will be less than KRB5_INT32_MIN */
- return KRB5_INT32_MIN;
- }
-
- return x + y;
-}
-
-/*
* Decrypt the AS reply in ctx, populating ctx->reply->enc_part2. If
* strengthen_key is not null, combine it with the reply key as specified in
* RFC 6113 section 5.4.3. Place the key used in *key_out.
@@ -267,28 +249,28 @@ verify_as_reply(krb5_context context,
(request->from != 0) &&
(request->from != as_reply->enc_part2->times.starttime))
|| ((request->till != 0) &&
- (as_reply->enc_part2->times.endtime > request->till))
+ ts_after(as_reply->enc_part2->times.endtime, request->till))
|| ((request->kdc_options & KDC_OPT_RENEWABLE) &&
(request->rtime != 0) &&
- (as_reply->enc_part2->times.renew_till > request->rtime))
+ ts_after(as_reply->enc_part2->times.renew_till, request->rtime))
|| ((request->kdc_options & KDC_OPT_RENEWABLE_OK) &&
!(request->kdc_options & KDC_OPT_RENEWABLE) &&
(as_reply->enc_part2->flags & KDC_OPT_RENEWABLE) &&
(request->till != 0) &&
- (as_reply->enc_part2->times.renew_till > request->till))
+ ts_after(as_reply->enc_part2->times.renew_till, request->till))
) {
return KRB5_KDCREP_MODIFIED;
}
if (context->library_options & KRB5_LIBOPT_SYNC_KDCTIME) {
- time_offset = as_reply->enc_part2->times.authtime - time_now;
+ time_offset = ts_delta(as_reply->enc_part2->times.authtime, time_now);
retval = krb5_set_time_offsets(context, time_offset, 0);
if (retval)
return retval;
} else {
if ((request->from == 0) &&
- (labs(as_reply->enc_part2->times.starttime - time_now)
- > context->clockskew))
+ !ts_within(as_reply->enc_part2->times.starttime, time_now,
+ context->clockskew))
return (KRB5_KDCREP_SKEW);
}
return 0;
@@ -583,7 +565,7 @@ krb5_init_creds_free(krb5_context context,
k5_response_items_free(ctx->rctx.items);
free(ctx->in_tkt_service);
zapfree(ctx->gakpw.storage.data, ctx->gakpw.storage.length);
- k5_preauth_request_context_fini(context);
+ k5_preauth_request_context_fini(context, ctx);
krb5_free_error(context, ctx->err_reply);
krb5_free_pa_data(context, ctx->err_padata);
krb5_free_cred_contents(context, &ctx->cred);
@@ -593,7 +575,9 @@ krb5_init_creds_free(krb5_context context,
krb5_free_data(context, ctx->inner_request_body);
krb5_free_data(context, ctx->encoded_previous_request);
krb5int_fast_free_state(context, ctx->fast_state);
- krb5_free_pa_data(context, ctx->preauth_to_use);
+ krb5_free_pa_data(context, ctx->optimistic_padata);
+ krb5_free_pa_data(context, ctx->method_padata);
+ krb5_free_pa_data(context, ctx->more_padata);
krb5_free_data_contents(context, &ctx->salt);
krb5_free_data_contents(context, &ctx->s2kparams);
krb5_free_keyblock_contents(context, &ctx->as_key);
@@ -760,23 +744,6 @@ k5_init_creds_current_time(krb5_context context, krb5_init_creds_context ctx,
}
}
-/* Choose a random nonce for ctx->request. */
-static krb5_error_code
-pick_nonce(krb5_context context, krb5_init_creds_context ctx)
-{
- krb5_error_code code = 0;
- unsigned char random_buf[4];
- krb5_data random_data = make_data(random_buf, 4);
-
- /* We incorrectly encode this as signed, so make sure we use an unsigned
- * value to avoid interoperability issues. */
- code = krb5_c_random_make_octets(context, &random_data);
- if (code != 0)
- return code;
- ctx->request->nonce = 0x7fffffff & load_32_n(random_buf);
- return 0;
-}
-
/* Set the timestamps for ctx->request based on the desired lifetimes. */
static krb5_error_code
set_request_times(krb5_context context, krb5_init_creds_context ctx)
@@ -790,16 +757,16 @@ set_request_times(krb5_context context, krb5_init_creds_context ctx)
return code;
/* Omit request start time unless the caller explicitly asked for one. */
- from = krb5int_addint32(now, ctx->start_time);
+ from = ts_incr(now, ctx->start_time);
if (ctx->start_time != 0)
ctx->request->from = from;
- ctx->request->till = krb5int_addint32(from, ctx->tkt_life);
+ ctx->request->till = ts_incr(from, ctx->tkt_life);
if (ctx->renew_life > 0) {
/* Don't ask for a smaller renewable time than the lifetime. */
- ctx->request->rtime = krb5int_addint32(from, ctx->renew_life);
- if (ctx->request->rtime < ctx->request->till)
+ ctx->request->rtime = ts_incr(from, ctx->renew_life);
+ if (ts_after(ctx->request->till, ctx->request->rtime))
ctx->request->rtime = ctx->request->till;
ctx->request->kdc_options &= ~KDC_OPT_RENEWABLE_OK;
} else {
@@ -809,6 +776,31 @@ set_request_times(krb5_context context, krb5_init_creds_context ctx)
return 0;
}
+static void
+read_allowed_preauth_type(krb5_context context, krb5_init_creds_context ctx)
+{
+ krb5_error_code ret;
+ krb5_data config;
+ char *tmp, *p;
+ krb5_ccache in_ccache = k5_gic_opt_get_in_ccache(ctx->opt);
+
+ ctx->allowed_preauth_type = KRB5_PADATA_NONE;
+ if (in_ccache == NULL)
+ return;
+ memset(&config, 0, sizeof(config));
+ if (krb5_cc_get_config(context, in_ccache, ctx->request->server,
+ KRB5_CC_CONF_PA_TYPE, &config) != 0)
+ return;
+ tmp = k5memdup0(config.data, config.length, &ret);
+ krb5_free_data_contents(context, &config);
+ if (tmp == NULL)
+ return;
+ ctx->allowed_preauth_type = strtol(tmp, &p, 10);
+ if (p == NULL || *p != '\0')
+ ctx->allowed_preauth_type = KRB5_PADATA_NONE;
+ free(tmp);
+}
+
/**
* Throw away any pre-authentication realm state and begin with a
* unauthenticated or optimistically authenticated request. If fast_upgrade is
@@ -820,11 +812,15 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
{
krb5_error_code code = 0;
- krb5_free_pa_data(context, ctx->preauth_to_use);
+ krb5_free_pa_data(context, ctx->optimistic_padata);
+ krb5_free_pa_data(context, ctx->method_padata);
+ krb5_free_pa_data(context, ctx->more_padata);
krb5_free_pa_data(context, ctx->err_padata);
krb5_free_error(context, ctx->err_reply);
- ctx->preauth_to_use = ctx->err_padata = NULL;
+ ctx->optimistic_padata = ctx->method_padata = ctx->more_padata = NULL;
+ ctx->err_padata = NULL;
ctx->err_reply = NULL;
+ ctx->selected_preauth_type = KRB5_PADATA_NONE;
krb5int_fast_free_state(context, ctx->fast_state);
ctx->fast_state = NULL;
@@ -834,14 +830,14 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
if (fast_upgrade)
ctx->fast_state->fast_state_flags |= KRB5INT_FAST_DO_FAST;
- k5_preauth_request_context_fini(context);
- k5_preauth_request_context_init(context);
+ k5_preauth_request_context_fini(context, ctx);
+ k5_preauth_request_context_init(context, ctx);
krb5_free_data(context, ctx->outer_request_body);
ctx->outer_request_body = NULL;
if (ctx->opt->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) {
code = make_preauth_list(context, ctx->opt->preauth_list,
ctx->opt->preauth_list_length,
- &ctx->preauth_to_use);
+ &ctx->optimistic_padata);
if (code)
goto cleanup;
}
@@ -867,6 +863,11 @@ restart_init_creds_loop(krb5_context context, krb5_init_creds_context ctx,
&ctx->outer_request_body);
if (code != 0)
goto cleanup;
+
+ /* Read the allowed preauth type for this server principal from the input
+ * ccache, if the application supplied one. */
+ read_allowed_preauth_type(context, ctx);
+
cleanup:
return code;
}
@@ -1172,31 +1173,6 @@ init_creds_validate_reply(krb5_context context,
return 0;
}
-static void
-read_allowed_preauth_type(krb5_context context, krb5_init_creds_context ctx)
-{
- krb5_error_code ret;
- krb5_data config;
- char *tmp, *p;
- krb5_ccache in_ccache = k5_gic_opt_get_in_ccache(ctx->opt);
-
- ctx->allowed_preauth_type = KRB5_PADATA_NONE;
- if (in_ccache == NULL)
- return;
- memset(&config, 0, sizeof(config));
- if (krb5_cc_get_config(context, in_ccache, ctx->request->server,
- KRB5_CC_CONF_PA_TYPE, &config) != 0)
- return;
- tmp = k5memdup0(config.data, config.length, &ret);
- krb5_free_data_contents(context, &config);
- if (tmp == NULL)
- return;
- ctx->allowed_preauth_type = strtol(tmp, &p, 10);
- if (p == NULL || *p != '\0')
- ctx->allowed_preauth_type = KRB5_PADATA_NONE;
- free(tmp);
-}
-
static krb5_error_code
save_selected_preauth_type(krb5_context context, krb5_ccache ccache,
krb5_init_creds_context ctx)
@@ -1313,6 +1289,9 @@ init_creds_step_request(krb5_context context,
krb5_data *out)
{
krb5_error_code code;
+ krb5_preauthtype pa_type;
+ struct errinfo save = EMPTY_ERRINFO;
+ uint32_t rcode = (ctx->err_reply == NULL) ? 0 : ctx->err_reply->error;
if (ctx->loopcount >= MAX_IN_TKT_LOOPS) {
code = KRB5_GET_IN_TKT_LOOP;
@@ -1320,7 +1299,7 @@ init_creds_step_request(krb5_context context,
}
/* RFC 6113 requires a new nonce for the inner request on each try. */
- code = pick_nonce(context, ctx);
+ code = k5_generate_nonce(context, &ctx->request->nonce);
if (code != 0)
goto cleanup;
@@ -1335,11 +1314,6 @@ init_creds_step_request(krb5_context context,
if (code)
goto cleanup;
- /* Read the allowed patype for this server principal from the in_ccache,
- * if the application supplied one. */
- read_allowed_preauth_type(context, ctx);
- ctx->selected_preauth_type = KRB5_PADATA_NONE;
-
/*
* Read cached preauth configuration data for this server principal from
* the in_ccache, if the application supplied one, and delete any that was
@@ -1348,32 +1322,65 @@ init_creds_step_request(krb5_context context,
read_cc_config_in_data(context, ctx);
clear_cc_config_out_data(context, ctx);
- if (ctx->err_reply == NULL) {
- /* Either our first attempt, or retrying after KDC_ERR_PREAUTH_REQUIRED
- * or KDC_ERR_MORE_PREAUTH_DATA_REQUIRED. */
- code = k5_preauth(context, ctx, ctx->preauth_to_use,
- ctx->preauth_required, &ctx->request->padata,
- &ctx->selected_preauth_type);
- if (code != 0)
- goto cleanup;
- } else {
- if (ctx->preauth_to_use != NULL) {
- /*
- * Retry after an error other than PREAUTH_NEEDED,
- * using ctx->err_padata to figure out what to change.
- */
- code = k5_preauth_tryagain(context, ctx, ctx->preauth_to_use,
- &ctx->request->padata);
- } else {
- /* No preauth supplied, so can't query the plugins. */
- code = KRB5KRB_ERR_GENERIC;
+ ctx->request->padata = NULL;
+ if (ctx->optimistic_padata != NULL) {
+ /* Our first attempt, using an optimistic padata list. */
+ TRACE_INIT_CREDS_PREAUTH_OPTIMISTIC(context);
+ code = k5_preauth(context, ctx, ctx->optimistic_padata, TRUE,
+ &ctx->request->padata, &ctx->selected_preauth_type);
+ krb5_free_pa_data(context, ctx->optimistic_padata);
+ ctx->optimistic_padata = NULL;
+ if (code) {
+ /* Make an unauthenticated request, and possibly try again using
+ * the same mechanisms as we tried optimistically. */
+ k5_reset_preauth_types_tried(ctx);
+ krb5_clear_error_message(context);
+ code = 0;
}
- if (code != 0) {
- /* couldn't come up with anything better */
+ } if (ctx->more_padata != NULL) {
+ /* Continuing after KDC_ERR_MORE_PREAUTH_DATA_REQUIRED. */
+ TRACE_INIT_CREDS_PREAUTH_MORE(context, ctx->selected_preauth_type);
+ code = k5_preauth(context, ctx, ctx->more_padata, TRUE,
+ &ctx->request->padata, &pa_type);
+ } else if (rcode == KDC_ERR_PREAUTH_FAILED) {
+ /* Report the KDC-side failure code if we can't try another mech. */
+ code = KRB5KDC_ERR_PREAUTH_FAILED;
+ } else if (rcode && rcode != KDC_ERR_PREAUTH_REQUIRED) {
+ /* Retrying after an error (possibly mechanism-specific), using error
+ * padata to figure out what to change. */
+ TRACE_INIT_CREDS_PREAUTH_TRYAGAIN(context, ctx->err_reply->error,
+ ctx->selected_preauth_type);
+ code = k5_preauth_tryagain(context, ctx, ctx->selected_preauth_type,
+ ctx->err_reply, ctx->err_padata,
+ &ctx->request->padata);
+ if (code) {
+ krb5_clear_error_message(context);
code = ctx->err_reply->error + ERROR_TABLE_BASE_krb5;
+ }
+ }
+ /* Don't continue after a keyboard interrupt. */
+ if (code == KRB5_LIBOS_PWDINTR)
+ goto cleanup;
+ if (code) {
+ /* See if we can try a different preauth mech before giving up. */
+ k5_save_ctx_error(context, code, &save);
+ ctx->selected_preauth_type = KRB5_PADATA_NONE;
+ }
+
+ if (ctx->request->padata == NULL && ctx->method_padata != NULL) {
+ /* Retrying after KDC_ERR_PREAUTH_REQUIRED, or trying again with a
+ * different mechanism after a failure. */
+ TRACE_INIT_CREDS_PREAUTH(context);
+ code = k5_preauth(context, ctx, ctx->method_padata, TRUE,
+ &ctx->request->padata, &ctx->selected_preauth_type);
+ if (code) {
+ if (save.code != 0)
+ code = k5_restore_ctx_error(context, &save);
goto cleanup;
}
}
+ if (ctx->request->padata == NULL)
+ TRACE_INIT_CREDS_PREAUTH_NONE(context);
/* Remember when we sent this request (after any preauth delay). */
ctx->request_time = time(NULL);
@@ -1382,8 +1389,6 @@ init_creds_step_request(krb5_context context,
krb5_free_data(context, ctx->encoded_previous_request);
ctx->encoded_previous_request = NULL;
}
- if (ctx->request->padata)
- ctx->sent_nontrivial_preauth = TRUE;
if (ctx->enc_pa_rep_permitted) {
code = add_padata(&ctx->request->padata, KRB5_ENCPADATA_REQ_ENC_PA_REP,
NULL, 0);
@@ -1411,6 +1416,7 @@ init_creds_step_request(krb5_context context,
cleanup:
krb5_free_pa_data(context, ctx->request->padata);
ctx->request->padata = NULL;
+ k5_clear_error(&save);
return code;
}
@@ -1438,7 +1444,7 @@ note_req_timestamp(krb5_context context, krb5_init_creds_context ctx,
if (k5_time_with_offset(0, 0, &now, &usec) != 0)
return;
- ctx->pa_offset = kdc_time - now;
+ ctx->pa_offset = ts_delta(kdc_time, now);
ctx->pa_offset_usec = kdc_usec - usec;
ctx->pa_offset_state = (ctx->fast_state->armor_key != NULL) ?
AUTH_OFFSET : UNAUTH_OFFSET;
@@ -1463,6 +1469,18 @@ is_referral(krb5_context context, krb5_error *err, krb5_principal client)
return !krb5_realm_compare(context, err->client, client);
}
+/* Transfer error padata to method data in ctx and sort it according to
+ * configuration. */
+static krb5_error_code
+accept_method_data(krb5_context context, krb5_init_creds_context ctx)
+{
+ krb5_free_pa_data(context, ctx->method_padata);
+ ctx->method_padata = ctx->err_padata;
+ ctx->err_padata = NULL;
+ return sort_krb5_padata_sequence(context, &ctx->request->client->realm,
+ ctx->method_padata);
+}
+
static krb5_error_code
init_creds_step_reply(krb5_context context,
krb5_init_creds_context ctx,
@@ -1492,8 +1510,9 @@ init_creds_step_reply(krb5_context context,
ctx->request->client->type == KRB5_NT_ENTERPRISE_PRINCIPAL;
if (ctx->err_reply != NULL) {
+ krb5_free_pa_data(context, ctx->more_padata);
krb5_free_pa_data(context, ctx->err_padata);
- ctx->err_padata = NULL;
+ ctx->more_padata = ctx->err_padata = NULL;
code = krb5int_fast_process_error(context, ctx->fast_state,
&ctx->err_reply, &ctx->err_padata,
&retry);
@@ -1508,7 +1527,7 @@ init_creds_step_reply(krb5_context context,
ctx->restarted = TRUE;
code = restart_init_creds_loop(context, ctx, TRUE);
} else if (!ctx->restarted && reply_code == KDC_ERR_PREAUTH_FAILED &&
- !ctx->sent_nontrivial_preauth) {
+ ctx->selected_preauth_type == KRB5_PADATA_NONE) {
/* The KDC didn't like our informational padata (probably a pre-1.7
* MIT krb5 KDC). Retry without it. */
ctx->enc_pa_rep_permitted = FALSE;
@@ -1519,23 +1538,30 @@ init_creds_step_reply(krb5_context context,
* FAST upgrade. */
ctx->restarted = FALSE;
code = restart_init_creds_loop(context, ctx, FALSE);
- } else if ((reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED ||
- reply_code == KDC_ERR_PREAUTH_REQUIRED) && retry) {
- /* reset the list of preauth types to try */
- k5_reset_preauth_types_tried(context);
- krb5_free_pa_data(context, ctx->preauth_to_use);
- ctx->preauth_to_use = ctx->err_padata;
- ctx->err_padata = NULL;
+ } else if (reply_code == KDC_ERR_PREAUTH_REQUIRED && retry) {
note_req_timestamp(context, ctx, ctx->err_reply->stime,
ctx->err_reply->susec);
- /* This will trigger a new call to k5_preauth(). */
- krb5_free_error(context, ctx->err_reply);
- ctx->err_reply = NULL;
- code = sort_krb5_padata_sequence(context,
- &ctx->request->client->realm,
- ctx->preauth_to_use);
- ctx->preauth_required = TRUE;
-
+ code = accept_method_data(context, ctx);
+ } else if (reply_code == KDC_ERR_PREAUTH_FAILED && retry) {
+ note_req_timestamp(context, ctx, ctx->err_reply->stime,
+ ctx->err_reply->susec);
+ if (ctx->method_padata == NULL) {
+ /* Optimistic preauth failed on the KDC. Allow all mechanisms
+ * to be tried again using method data. */
+ k5_reset_preauth_types_tried(ctx);
+ } else {
+ /* Don't try again with the mechanism that failed. */
+ code = k5_preauth_note_failed(ctx, ctx->selected_preauth_type);
+ if (code)
+ goto cleanup;
+ }
+ ctx->selected_preauth_type = KRB5_PADATA_NONE;
+ /* Accept or update method data if the KDC sent it. */
+ if (ctx->err_padata != NULL)
+ code = accept_method_data(context, ctx);
+ } else if (reply_code == KDC_ERR_MORE_PREAUTH_DATA_REQUIRED && retry) {
+ ctx->more_padata = ctx->err_padata;
+ ctx->err_padata = NULL;
} else if (canon_flag && is_referral(context, ctx->err_reply,
ctx->request->client)) {
TRACE_INIT_CREDS_REFERRAL(context, &ctx->err_reply->client->realm);
@@ -1548,14 +1574,13 @@ init_creds_step_reply(krb5_context context,
goto cleanup;
/* Reset per-realm negotiation state. */
ctx->restarted = FALSE;
- ctx->sent_nontrivial_preauth = FALSE;
ctx->enc_pa_rep_permitted = TRUE;
code = restart_init_creds_loop(context, ctx, FALSE);
} else {
- if (retry) {
+ if (retry && ctx->selected_preauth_type != KRB5_PADATA_NONE) {
code = 0;
} else {
- /* error + no hints = give up */
+ /* error + no hints (or no preauth mech) = give up */
code = (krb5_error_code)reply_code + ERROR_TABLE_BASE_krb5;
}
}
@@ -1573,7 +1598,6 @@ init_creds_step_reply(krb5_context context,
goto cleanup;
/* process any preauth data in the as_reply */
- k5_reset_preauth_types_tried(context);
code = krb5int_fast_process_response(context, ctx->fast_state,
ctx->reply, &strengthen_key);
if (code != 0)
@@ -1658,7 +1682,7 @@ init_creds_step_reply(krb5_context context,
k5_prependmsg(context, code, _("Failed to store credentials"));
}
- k5_preauth_request_context_fini(context);
+ k5_preauth_request_context_fini(context, ctx);
/* success */
ctx->complete = TRUE;
@@ -1685,7 +1709,7 @@ krb5_init_creds_step(krb5_context context,
krb5_data *realm,
unsigned int *flags)
{
- krb5_error_code code = 0, code2;
+ krb5_error_code code, code2;
*flags = 0;
@@ -1698,6 +1722,10 @@ krb5_init_creds_step(krb5_context context,
if (ctx->complete)
return EINVAL;
+ code = k5_preauth_check_context(context, ctx);
+ if (code)
+ return code;
+
if (in->length != 0) {
code = init_creds_step_reply(context, ctx, in);
if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG) {
@@ -1806,7 +1834,8 @@ k5_populate_gic_opt(krb5_context context, krb5_get_init_creds_opt **out,
krb5_creds *creds)
{
int i;
- krb5_int32 starttime;
+ krb5_timestamp starttime;
+ krb5_deltat lifetime;
krb5_get_init_creds_opt *opt;
krb5_error_code retval;
@@ -1838,7 +1867,8 @@ k5_populate_gic_opt(krb5_context context, krb5_get_init_creds_opt **out,
if (retval)
goto cleanup;
if (creds->times.starttime) starttime = creds->times.starttime;
- krb5_get_init_creds_opt_set_tkt_life(opt, creds->times.endtime - starttime);
+ lifetime = ts_delta(creds->times.endtime, starttime);
+ krb5_get_init_creds_opt_set_tkt_life(opt, lifetime);
}
*out = opt;
return 0;
diff --git a/src/lib/krb5/krb/gic_opt.c b/src/lib/krb5/krb/gic_opt.c
index 3be44d5cd756..ccbe1a65fa5a 100644
--- a/src/lib/krb5/krb/gic_opt.c
+++ b/src/lib/krb5/krb/gic_opt.c
@@ -12,7 +12,7 @@
#include <TargetConditionals.h>
#endif
-/* Match struct packing of krb5_get_init_creds_opt on MacOS X. */
+/* Match struct packing of krb5_get_init_creds_opt on macOS. */
#if TARGET_OS_MAC
#pragma pack(push,2)
#endif
diff --git a/src/lib/krb5/krb/gic_pwd.c b/src/lib/krb5/krb/gic_pwd.c
index 6f3a29f2c423..3565a7c4c77a 100644
--- a/src/lib/krb5/krb/gic_pwd.c
+++ b/src/lib/krb5/krb/gic_pwd.c
@@ -211,7 +211,7 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
if (ret != 0)
return;
if (!is_last_req &&
- (pw_exp < now || (pw_exp - now) > 7 * 24 * 60 * 60))
+ (ts_after(now, pw_exp) || ts_delta(pw_exp, now) > 7 * 24 * 60 * 60))
return;
if (!prompter)
@@ -221,7 +221,7 @@ warn_pw_expiry(krb5_context context, krb5_get_init_creds_opt *options,
if (ret != 0)
return;
- delta = pw_exp - now;
+ delta = ts_delta(pw_exp, now);
if (delta < 3600) {
snprintf(banner, sizeof(banner),
_("Warning: Your password will expire in less than one hour "
diff --git a/src/lib/krb5/krb/init_creds_ctx.h b/src/lib/krb5/krb/init_creds_ctx.h
index 38c01c775b6f..fe769685ba09 100644
--- a/src/lib/krb5/krb/init_creds_ctx.h
+++ b/src/lib/krb5/krb/init_creds_ctx.h
@@ -6,6 +6,8 @@
#include "k5-json.h"
#include "int-proto.h"
+typedef struct krb5_preauth_req_context_st *krb5_preauth_req_context;
+
struct krb5_responder_context_st {
k5_response_items *items;
};
@@ -48,7 +50,9 @@ struct _krb5_init_creds_context {
krb5_data *inner_request_body; /**< For preauth */
krb5_data *encoded_previous_request;
struct krb5int_fast_request_state *fast_state;
- krb5_pa_data **preauth_to_use;
+ krb5_pa_data **optimistic_padata; /* from gic options */
+ krb5_pa_data **method_padata; /* from PREAUTH_REQUIRED or PREAUTH_FAILED */
+ krb5_pa_data **more_padata; /* from MORE_PREAUTH_DATA_REQUIRED */
krb5_boolean default_salt;
krb5_data salt;
krb5_data s2kparams;
@@ -56,8 +60,6 @@ struct _krb5_init_creds_context {
krb5_enctype etype;
krb5_boolean enc_pa_rep_permitted;
krb5_boolean restarted;
- krb5_boolean sent_nontrivial_preauth;
- krb5_boolean preauth_required;
struct krb5_responder_context_st rctx;
krb5_preauthtype selected_preauth_type;
krb5_preauthtype allowed_preauth_type;
@@ -67,6 +69,7 @@ struct _krb5_init_creds_context {
krb5_timestamp pa_offset;
krb5_int32 pa_offset_usec;
enum { NO_OFFSET = 0, UNAUTH_OFFSET, AUTH_OFFSET } pa_offset_state;
+ krb5_preauth_req_context preauth_reqctx;
};
krb5_error_code
diff --git a/src/lib/krb5/krb/init_ctx.c b/src/lib/krb5/krb/init_ctx.c
index cf226fdbabc0..4246c5dd274f 100644
--- a/src/lib/krb5/krb/init_ctx.c
+++ b/src/lib/krb5/krb/init_ctx.c
@@ -139,7 +139,8 @@ krb5_init_context_profile(profile_t profile, krb5_flags flags,
krb5_context ctx = 0;
krb5_error_code retval;
struct {
- krb5_int32 now, now_usec;
+ krb5_timestamp now;
+ krb5_int32 now_usec;
long pid;
} seed_data;
krb5_data seed;
diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
index 6da74858e210..cda9010e34a3 100644
--- a/src/lib/krb5/krb/int-proto.h
+++ b/src/lib/krb5/krb/int-proto.h
@@ -83,8 +83,6 @@ krb5int_construct_matching_creds(krb5_context context, krb5_flags options,
krb5_creds *in_creds, krb5_creds *mcreds,
krb5_flags *fields);
-#define in_clock_skew(date, now) (labs((date)-(now)) < context->clockskew)
-
#define IS_TGS_PRINC(p) ((p)->length == 2 && \
data_eq_string((p)->data[0], KRB5_TGS_NAME))
@@ -102,6 +100,9 @@ krb5_get_cred_via_tkt_ext(krb5_context context, krb5_creds *tkt,
krb5_keyblock **out_subkey);
krb5_error_code
+k5_generate_nonce(krb5_context context, int32_t *out);
+
+krb5_error_code
k5_make_tgs_req(krb5_context context, struct krb5int_fast_request_state *,
krb5_creds *tkt, krb5_flags kdcoptions,
krb5_address *const *address, krb5_pa_data **in_padata,
@@ -187,7 +188,8 @@ k5_preauth(krb5_context context, krb5_init_creds_context ctx,
krb5_error_code
k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
- krb5_pa_data **in_padata, krb5_pa_data ***padata_out);
+ krb5_preauthtype pa_type, krb5_error *err,
+ krb5_pa_data **err_padata, krb5_pa_data ***padata_out);
void
k5_init_preauth_context(krb5_context context);
@@ -196,17 +198,25 @@ void
k5_free_preauth_context(krb5_context context);
void
-k5_reset_preauth_types_tried(krb5_context context);
+k5_reset_preauth_types_tried(krb5_init_creds_context ctx);
+
+krb5_error_code
+k5_preauth_note_failed(krb5_init_creds_context ctx, krb5_preauthtype pa_type);
void
k5_preauth_prepare_request(krb5_context context, krb5_get_init_creds_opt *opt,
krb5_kdc_req *request);
void
-k5_preauth_request_context_init(krb5_context context);
+k5_preauth_request_context_init(krb5_context context,
+ krb5_init_creds_context ctx);
void
-k5_preauth_request_context_fini(krb5_context context);
+k5_preauth_request_context_fini(krb5_context context,
+ krb5_init_creds_context ctx);
+
+krb5_error_code
+k5_preauth_check_context(krb5_context context, krb5_init_creds_context ctx);
krb5_error_code
k5_response_items_new(k5_response_items **ri_out);
diff --git a/src/lib/krb5/krb/mk_req.c b/src/lib/krb5/krb/mk_req.c
index 542ef6d4aee5..162c05b5cbd9 100644
--- a/src/lib/krb5/krb/mk_req.c
+++ b/src/lib/krb5/krb/mk_req.c
@@ -48,8 +48,9 @@
krb5_error_code KRB5_CALLCONV
krb5_mk_req(krb5_context context, krb5_auth_context *auth_context,
- krb5_flags ap_req_options, char *service, char *hostname,
- krb5_data *in_data, krb5_ccache ccache, krb5_data *outbuf)
+ krb5_flags ap_req_options, const char *service,
+ const char *hostname, krb5_data *in_data, krb5_ccache ccache,
+ krb5_data *outbuf)
{
krb5_error_code retval;
krb5_principal server;
diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c
index 9098927b5acf..0eb19e6bb464 100644
--- a/src/lib/krb5/krb/pac.c
+++ b/src/lib/krb5/krb/pac.c
@@ -378,7 +378,7 @@ k5_time_to_seconds_since_1970(int64_t ntTime, krb5_timestamp *elapsedSeconds)
abstime = ntTime > 0 ? ntTime - NT_TIME_EPOCH : -ntTime;
- if (abstime > KRB5_INT32_MAX)
+ if (abstime > UINT32_MAX)
return ERANGE;
*elapsedSeconds = abstime;
@@ -436,8 +436,7 @@ k5_pac_validate_client(krb5_context context,
pac_princname_length % 2)
return ERANGE;
- ret = krb5int_ucs2lecs_to_utf8s(p, (size_t)pac_princname_length / 2,
- &pac_princname, NULL);
+ ret = k5_utf16le_to_utf8(p, pac_princname_length, &pac_princname);
if (ret != 0)
return ret;
@@ -792,8 +791,8 @@ mspac_verify(krb5_context kcontext,
* If the above verification failed, don't fail the whole authentication,
* just don't mark the PAC as verified. A checksum mismatch can occur if
* the PAC was copied from a cross-realm TGT by an ignorant KDC, and Apple
- * Mac OS X Server Open Directory (as of 10.6) generates PACs with no
- * server checksum at all.
+ * macOS Server Open Directory (as of 10.6) generates PACs with no server
+ * checksum at all.
*/
return 0;
}
diff --git a/src/lib/krb5/krb/pac_sign.c b/src/lib/krb5/krb/pac_sign.c
index d40df45f99e8..c94899c96a79 100644
--- a/src/lib/krb5/krb/pac_sign.c
+++ b/src/lib/krb5/krb/pac_sign.c
@@ -38,8 +38,8 @@ k5_insert_client_info(krb5_context context,
krb5_error_code ret;
krb5_data client_info;
char *princ_name_utf8 = NULL;
- unsigned char *princ_name_ucs2 = NULL, *p;
- size_t princ_name_ucs2_len = 0;
+ unsigned char *princ_name_utf16 = NULL, *p;
+ size_t princ_name_utf16_len = 0;
uint64_t nt_authtime;
/* If we already have a CLIENT_INFO buffer, then just validate it */
@@ -54,13 +54,12 @@ k5_insert_client_info(krb5_context context,
if (ret != 0)
goto cleanup;
- ret = krb5int_utf8s_to_ucs2les(princ_name_utf8,
- &princ_name_ucs2,
- &princ_name_ucs2_len);
+ ret = k5_utf8_to_utf16le(princ_name_utf8, &princ_name_utf16,
+ &princ_name_utf16_len);
if (ret != 0)
goto cleanup;
- client_info.length = PAC_CLIENT_INFO_LENGTH + princ_name_ucs2_len;
+ client_info.length = PAC_CLIENT_INFO_LENGTH + princ_name_utf16_len;
client_info.data = NULL;
ret = k5_pac_add_buffer(context, pac, KRB5_PAC_CLIENT_INFO,
@@ -75,16 +74,16 @@ k5_insert_client_info(krb5_context context,
store_64_le(nt_authtime, p);
p += 8;
- /* copy in number of UCS-2 characters in principal name */
- store_16_le(princ_name_ucs2_len, p);
+ /* copy in number of UTF-16 bytes in principal name */
+ store_16_le(princ_name_utf16_len, p);
p += 2;
/* copy in principal name */
- memcpy(p, princ_name_ucs2, princ_name_ucs2_len);
+ memcpy(p, princ_name_utf16, princ_name_utf16_len);
cleanup:
- if (princ_name_ucs2 != NULL)
- free(princ_name_ucs2);
+ if (princ_name_utf16 != NULL)
+ free(princ_name_utf16);
krb5_free_unparsed_name(context, princ_name_utf8);
return ret;
diff --git a/src/lib/krb5/krb/plugin.c b/src/lib/krb5/krb/plugin.c
index 7d64b7c7eda9..31aaf661d9af 100644
--- a/src/lib/krb5/krb/plugin.c
+++ b/src/lib/krb5/krb/plugin.c
@@ -57,7 +57,10 @@ const char *interface_names[] = {
"hostrealm",
"audit",
"tls",
- "kdcauthdata"
+ "kdcauthdata",
+ "certauth",
+ "kadm5_auth",
+ "kdcpolicy",
};
/* Return the context's interface structure for id, or NULL if invalid. */
diff --git a/src/lib/krb5/krb/preauth2.c b/src/lib/krb5/krb/preauth2.c
index ca26fb0e3fa5..6b96fa135e1a 100644
--- a/src/lib/krb5/krb/preauth2.c
+++ b/src/lib/krb5/krb/preauth2.c
@@ -46,14 +46,18 @@
typedef struct {
struct krb5_clpreauth_vtable_st vt;
krb5_clpreauth_moddata data;
- krb5_clpreauth_modreq req;
} *clpreauth_handle;
struct krb5_preauth_context_st {
- krb5_preauthtype *tried;
clpreauth_handle *handles;
};
+struct krb5_preauth_req_context_st {
+ krb5_context orig_context;
+ krb5_preauthtype *failed;
+ krb5_clpreauth_modreq *modreqs;
+};
+
/* Release the memory used by a list of handles. */
static void
free_handles(krb5_context context, clpreauth_handle *handles)
@@ -71,21 +75,44 @@ free_handles(krb5_context context, clpreauth_handle *handles)
free(handles);
}
-/* Find the handle in handles which can process pa_type. */
-static clpreauth_handle
-find_module(clpreauth_handle *handles, krb5_preauthtype pa_type)
+/* Return an index into handles which can process pa_type, or -1 if none is
+ * found found. */
+static int
+search_module_list(clpreauth_handle *handles, krb5_preauthtype pa_type)
{
- clpreauth_handle *hp, h;
- krb5_preauthtype *tp;
+ clpreauth_handle h;
+ int i, j;
- for (hp = handles; *hp != NULL; hp++) {
- h = *hp;
- for (tp = h->vt.pa_type_list; *tp != 0; tp++) {
- if (*tp == pa_type)
- return h;
+ for (i = 0; handles[i] != NULL; i++) {
+ h = handles[i];
+ for (j = 0; h->vt.pa_type_list[j] != 0; j++) {
+ if (h->vt.pa_type_list[j] == pa_type)
+ return i;
}
}
- return FALSE;
+ return -1;
+}
+
+/* Find the handle which can process pa_type, or NULL if none is found. On
+ * success, set *modreq_out to the corresponding per-request module data. */
+static clpreauth_handle
+find_module(krb5_context context, krb5_init_creds_context ctx,
+ krb5_preauthtype pa_type, krb5_clpreauth_modreq *modreq_out)
+{
+ krb5_preauth_context pctx = context->preauth_context;
+ krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
+ int i;
+
+ *modreq_out = NULL;
+ if (pctx == NULL || reqctx == NULL)
+ return NULL;
+
+ i = search_module_list(pctx->handles, pa_type);
+ if (i == -1)
+ return NULL;
+
+ *modreq_out = reqctx->modreqs[i];
+ return pctx->handles[i];
}
/* Initialize the preauth state for a krb5 context. */
@@ -93,7 +120,8 @@ void
k5_init_preauth_context(krb5_context context)
{
krb5_plugin_initvt_fn *modules = NULL, *mod;
- clpreauth_handle *list = NULL, h, h2;
+ clpreauth_handle *list = NULL, h;
+ int i;
size_t count;
krb5_preauthtype *tp;
@@ -140,9 +168,10 @@ k5_init_preauth_context(krb5_context context)
/* Check for a preauth type conflict with an existing module. */
for (tp = h->vt.pa_type_list; *tp != 0; tp++) {
- h2 = find_module(list, *tp);
- if (h2 != NULL) {
- TRACE_PREAUTH_CONFLICT(context, h->vt.name, h2->vt.name, *tp);
+ i = search_module_list(list, *tp);
+ if (i != -1) {
+ TRACE_PREAUTH_CONFLICT(context, h->vt.name, list[i]->vt.name,
+ *tp);
break;
}
}
@@ -161,10 +190,9 @@ k5_init_preauth_context(krb5_context context)
list[count] = NULL;
/* Place the constructed preauth context into the krb5 context. */
- context->preauth_context = malloc(sizeof(struct krb5_preauth_context_st));
+ context->preauth_context = malloc(sizeof(*context->preauth_context));
if (context->preauth_context == NULL)
goto cleanup;
- context->preauth_context->tried = NULL;
context->preauth_context->handles = list;
list = NULL;
@@ -173,22 +201,35 @@ cleanup:
free_handles(context, list);
}
-/*
- * Reset the memory of which preauth types we have already tried, because we
- * are entering a new phase of padata processing (such as the padata in an
- * AS-REP).
- */
+/* Reset the memory of which preauth types we have already tried. */
void
-k5_reset_preauth_types_tried(krb5_context context)
+k5_reset_preauth_types_tried(krb5_init_creds_context ctx)
{
- struct krb5_preauth_context_st *pctx = context->preauth_context;
+ krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
- if (pctx == NULL)
+ if (reqctx == NULL)
return;
- free(pctx->tried);
- pctx->tried = NULL;
+ free(reqctx->failed);
+ reqctx->failed = NULL;
}
+/* Add pa_type to the list of types which has previously failed. */
+krb5_error_code
+k5_preauth_note_failed(krb5_init_creds_context ctx, krb5_preauthtype pa_type)
+{
+ krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
+ krb5_preauthtype *newptr;
+ size_t i;
+
+ for (i = 0; reqctx->failed != NULL && reqctx->failed[i] != 0; i++);
+ newptr = realloc(reqctx->failed, (i + 2) * sizeof(*newptr));
+ if (newptr == NULL)
+ return ENOMEM;
+ reqctx->failed = newptr;
+ reqctx->failed[i] = pa_type;
+ reqctx->failed[i + 1] = 0;
+ return 0;
+}
/* Free the per-krb5_context preauth_context. This means clearing any
* plugin-specific context which may have been created, and then
@@ -196,11 +237,10 @@ k5_reset_preauth_types_tried(krb5_context context)
void
k5_free_preauth_context(krb5_context context)
{
- struct krb5_preauth_context_st *pctx = context->preauth_context;
+ krb5_preauth_context pctx = context->preauth_context;
if (pctx == NULL)
return;
- free(pctx->tried);
free_handles(context, pctx->handles);
free(pctx);
context->preauth_context = NULL;
@@ -209,10 +249,13 @@ k5_free_preauth_context(krb5_context context)
/* Initialize the per-AS-REQ context. This means calling the client_req_init
* function to give the plugin a chance to allocate a per-request context. */
void
-k5_preauth_request_context_init(krb5_context context)
+k5_preauth_request_context_init(krb5_context context,
+ krb5_init_creds_context ctx)
{
- struct krb5_preauth_context_st *pctx = context->preauth_context;
- clpreauth_handle *hp, h;
+ krb5_preauth_context pctx = context->preauth_context;
+ clpreauth_handle h;
+ krb5_preauth_req_context reqctx;
+ size_t count, i;
if (pctx == NULL) {
k5_init_preauth_context(context);
@@ -220,30 +263,63 @@ k5_preauth_request_context_init(krb5_context context)
if (pctx == NULL)
return;
}
- k5_reset_preauth_types_tried(context);
- for (hp = pctx->handles; *hp != NULL; hp++) {
- h = *hp;
+
+ reqctx = calloc(1, sizeof(*reqctx));
+ if (reqctx == NULL)
+ return;
+ reqctx->orig_context = context;
+
+ /* Create an array of per-request module data objects corresponding to the
+ * preauth context's array of handles. */
+ for (count = 0; pctx->handles[count] != NULL; count++);
+ reqctx->modreqs = calloc(count, sizeof(*reqctx->modreqs));
+ for (i = 0; i < count; i++) {
+ h = pctx->handles[i];
if (h->vt.request_init != NULL)
- h->vt.request_init(context, h->data, &h->req);
+ h->vt.request_init(context, h->data, &reqctx->modreqs[i]);
}
+ ctx->preauth_reqctx = reqctx;
}
/* Free the per-AS-REQ context. This means clearing any request-specific
* context which the plugin may have created. */
void
-k5_preauth_request_context_fini(krb5_context context)
+k5_preauth_request_context_fini(krb5_context context,
+ krb5_init_creds_context ctx)
{
- struct krb5_preauth_context_st *pctx = context->preauth_context;
- clpreauth_handle *hp, h;
+ krb5_preauth_context pctx = context->preauth_context;
+ krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
+ size_t i;
+ clpreauth_handle h;
- if (pctx == NULL)
+ if (reqctx == NULL)
return;
- for (hp = pctx->handles; *hp != NULL; hp++) {
- h = *hp;
- if (h->req != NULL && h->vt.request_fini != NULL)
- h->vt.request_fini(context, h->data, h->req);
- h->req = NULL;
+ if (reqctx->orig_context == context && pctx != NULL) {
+ for (i = 0; pctx->handles[i] != NULL; i++) {
+ h = pctx->handles[i];
+ if (reqctx->modreqs[i] != NULL && h->vt.request_fini != NULL)
+ h->vt.request_fini(context, h->data, reqctx->modreqs[i]);
+ }
+ } else {
+ TRACE_PREAUTH_WRONG_CONTEXT(context);
+ }
+ free(reqctx->modreqs);
+ free(reqctx->failed);
+ free(reqctx);
+ ctx->preauth_reqctx = NULL;
+}
+
+krb5_error_code
+k5_preauth_check_context(krb5_context context, krb5_init_creds_context ctx)
+{
+ krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
+
+ if (reqctx != NULL && reqctx->orig_context != context) {
+ k5_setmsg(context, EINVAL,
+ _("krb5_init_creds calls must use same library context"));
+ return EINVAL;
}
+ return 0;
}
/* Return 1 if pa_type is a real preauthentication mechanism according to the
@@ -259,6 +335,7 @@ clpreauth_is_real(krb5_context context, clpreauth_handle h,
static krb5_error_code
clpreauth_prep_questions(krb5_context context, clpreauth_handle h,
+ krb5_clpreauth_modreq modreq,
krb5_get_init_creds_opt *opt,
krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
krb5_kdc_req *req, krb5_data *req_body,
@@ -266,35 +343,35 @@ clpreauth_prep_questions(krb5_context context, clpreauth_handle h,
{
if (h->vt.prep_questions == NULL)
return 0;
- return h->vt.prep_questions(context, h->data, h->req, opt, cb, rock, req,
+ return h->vt.prep_questions(context, h->data, modreq, opt, cb, rock, req,
req_body, prev_req, pa_data);
}
static krb5_error_code
clpreauth_process(krb5_context context, clpreauth_handle h,
- krb5_get_init_creds_opt *opt, krb5_clpreauth_callbacks cb,
- krb5_clpreauth_rock rock, krb5_kdc_req *req,
- krb5_data *req_body, krb5_data *prev_req,
+ krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt,
+ krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
+ krb5_kdc_req *req, krb5_data *req_body, krb5_data *prev_req,
krb5_pa_data *pa_data, krb5_prompter_fct prompter,
void *prompter_data, krb5_pa_data ***pa_data_out)
{
- return h->vt.process(context, h->data, h->req, opt, cb, rock, req,
+ return h->vt.process(context, h->data, modreq, opt, cb, rock, req,
req_body, prev_req, pa_data, prompter, prompter_data,
pa_data_out);
}
static krb5_error_code
clpreauth_tryagain(krb5_context context, clpreauth_handle h,
- krb5_get_init_creds_opt *opt, krb5_clpreauth_callbacks cb,
- krb5_clpreauth_rock rock, krb5_kdc_req *req,
- krb5_data *req_body, krb5_data *prev_req,
+ krb5_clpreauth_modreq modreq, krb5_get_init_creds_opt *opt,
+ krb5_clpreauth_callbacks cb, krb5_clpreauth_rock rock,
+ krb5_kdc_req *req, krb5_data *req_body, krb5_data *prev_req,
krb5_preauthtype pa_type, krb5_error *error,
krb5_pa_data **error_padata, krb5_prompter_fct prompter,
void *prompter_data, krb5_pa_data ***pa_data_out)
{
if (h->vt.tryagain == NULL)
return 0;
- return h->vt.tryagain(context, h->data, h->req, opt, cb, rock, req,
+ return h->vt.tryagain(context, h->data, modreq, opt, cb, rock, req,
req_body, prev_req, pa_type, error, error_padata,
prompter, prompter_data, pa_data_out);
}
@@ -420,7 +497,7 @@ responder_get_answer(krb5_context context, krb5_clpreauth_rock rock,
krb5_init_creds_context ctx = (krb5_init_creds_context)rock;
/* Don't let plugins get the raw password. */
- if (question && strcmp(KRB5_RESPONDER_QUESTION_PASSWORD, question) == 0)
+ if (strcmp(KRB5_RESPONDER_QUESTION_PASSWORD, question) == 0)
return NULL;
return k5_response_items_get_answer(ctx->rctx.items, question);
}
@@ -495,7 +572,7 @@ void
k5_preauth_prepare_request(krb5_context context, krb5_get_init_creds_opt *opt,
krb5_kdc_req *req)
{
- struct krb5_preauth_context_st *pctx = context->preauth_context;
+ krb5_preauth_context pctx = context->preauth_context;
clpreauth_handle *hp, h;
krb5_enctype *ep;
@@ -548,28 +625,17 @@ pa_type_allowed(krb5_init_creds_context ctx, krb5_preauthtype pa_type)
pa_type == ctx->allowed_preauth_type;
}
-/*
- * If pa_type has already been tried as a real preauth type for this
- * authentication, return true. Otherwise ass pa_type to the list of tried
- * types and return false.
- */
+/* Return true if pa_type previously failed during this authentication. */
static krb5_boolean
-already_tried(krb5_context context, krb5_preauthtype pa_type)
+previously_failed(krb5_init_creds_context ctx, krb5_preauthtype pa_type)
{
- struct krb5_preauth_context_st *pctx = context->preauth_context;
- size_t count;
- krb5_preauthtype *newptr;
+ krb5_preauth_req_context reqctx = ctx->preauth_reqctx;
+ size_t i;
- for (count = 0; pctx->tried != NULL && pctx->tried[count] != 0; count++) {
- if (pctx->tried[count] == pa_type)
+ for (i = 0; reqctx->failed != NULL && reqctx->failed[i] != 0; i++) {
+ if (reqctx->failed[i] == pa_type)
return TRUE;
}
- newptr = realloc(pctx->tried, (count + 2) * sizeof(*newptr));
- if (newptr == NULL)
- return FALSE;
- pctx->tried = newptr;
- pctx->tried[count] = pa_type;
- pctx->tried[count + 1] = ENCTYPE_NULL;
return FALSE;
}
@@ -580,16 +646,13 @@ process_pa_data(krb5_context context, krb5_init_creds_context ctx,
krb5_pa_data ***out_pa_list, int *out_pa_list_size,
krb5_preauthtype *out_type)
{
- struct krb5_preauth_context_st *pctx = context->preauth_context;
struct errinfo save = EMPTY_ERRINFO;
krb5_pa_data *pa, **pa_ptr, **mod_pa;
krb5_error_code ret = 0;
+ krb5_clpreauth_modreq modreq;
clpreauth_handle h;
int real, i;
- if (pctx == NULL)
- return ENOENT;
-
/* Process all informational padata types, then the first real preauth type
* we succeed on. */
for (real = 0; real <= 1; real++) {
@@ -598,17 +661,17 @@ process_pa_data(krb5_context context, krb5_init_creds_context ctx,
/* Restrict real mechanisms to the chosen one if we have one. */
if (real && !pa_type_allowed(ctx, pa->pa_type))
continue;
- h = find_module(pctx->handles, pa->pa_type);
+ h = find_module(context, ctx, pa->pa_type, &modreq);
if (h == NULL)
continue;
/* Make sure this type is for the current pass. */
if (clpreauth_is_real(context, h, pa->pa_type) != real)
continue;
- /* Only try a real mechanism once per authentication. */
- if (real && already_tried(context, pa->pa_type))
+ /* Don't try a real mechanism again after failure. */
+ if (real && previously_failed(ctx, pa->pa_type))
continue;
mod_pa = NULL;
- ret = clpreauth_process(context, h, ctx->opt, &callbacks,
+ ret = clpreauth_process(context, h, modreq, ctx->opt, &callbacks,
(krb5_clpreauth_rock)ctx, ctx->request,
ctx->inner_request_body,
ctx->encoded_previous_request, pa,
@@ -625,6 +688,9 @@ process_pa_data(krb5_context context, krb5_init_creds_context ctx,
}
free(mod_pa);
}
+ /* Don't continue to try mechanisms after a keyboard interrupt. */
+ if (ret == KRB5_LIBOS_PWDINTR)
+ goto cleanup;
if (ret == 0 && real) {
/* Stop now and record which real padata type we answered. */
*out_type = pa->pa_type;
@@ -633,6 +699,12 @@ process_pa_data(krb5_context context, krb5_init_creds_context ctx,
/* Save the first error we get from a real preauth type. */
k5_save_ctx_error(context, ret, &save);
}
+ if (real && ret) {
+ /* Don't try this mechanism again for this authentication. */
+ ret = k5_preauth_note_failed(ctx, pa->pa_type);
+ if (ret)
+ goto cleanup;
+ }
}
}
@@ -850,45 +922,54 @@ add_s4u_x509_user_padata(krb5_context context, krb5_s4u_userid *userid,
}
/*
- * If one of the modules can adjust its AS_REQ data using the contents of the
- * err_reply, return 0. If it's the sort of correction which requires that we
- * ask the user another question, we let the calling application deal with it.
+ * If the module for pa_type can adjust its AS_REQ data using the contents of
+ * err and err_padata, return 0 with *padata_out set to a padata list for the
+ * next request. If it's the sort of correction which requires that we ask the
+ * user another question, we let the calling application deal with it.
*/
krb5_error_code
k5_preauth_tryagain(krb5_context context, krb5_init_creds_context ctx,
- krb5_pa_data **in_padata, krb5_pa_data ***padata_out)
+ krb5_preauthtype pa_type, krb5_error *err,
+ krb5_pa_data **err_padata, krb5_pa_data ***padata_out)
{
- struct krb5_preauth_context_st *pctx = context->preauth_context;
krb5_error_code ret;
krb5_pa_data **mod_pa;
+ krb5_clpreauth_modreq modreq;
clpreauth_handle h;
- int i;
+ int count;
*padata_out = NULL;
- if (pctx == NULL)
- return KRB5KRB_ERR_GENERIC;
- TRACE_PREAUTH_TRYAGAIN_INPUT(context, in_padata);
+ TRACE_PREAUTH_TRYAGAIN_INPUT(context, pa_type, err_padata);
- for (i = 0; in_padata[i] != NULL; i++) {
- h = find_module(pctx->handles, in_padata[i]->pa_type);
- if (h == NULL)
- continue;
- mod_pa = NULL;
- ret = clpreauth_tryagain(context, h, ctx->opt, &callbacks,
- (krb5_clpreauth_rock)ctx, ctx->request,
- ctx->inner_request_body,
- ctx->encoded_previous_request,
- in_padata[i]->pa_type,
- ctx->err_reply, ctx->err_padata,
- ctx->prompter, ctx->prompter_data, &mod_pa);
- if (ret == 0 && mod_pa != NULL) {
- TRACE_PREAUTH_TRYAGAIN_OUTPUT(context, mod_pa);
- *padata_out = mod_pa;
- return 0;
- }
+ h = find_module(context, ctx, pa_type, &modreq);
+ if (h == NULL)
+ return KRB5KRB_ERR_GENERIC;
+ mod_pa = NULL;
+ ret = clpreauth_tryagain(context, h, modreq, ctx->opt, &callbacks,
+ (krb5_clpreauth_rock)ctx, ctx->request,
+ ctx->inner_request_body,
+ ctx->encoded_previous_request, pa_type, err,
+ err_padata, ctx->prompter, ctx->prompter_data,
+ &mod_pa);
+ TRACE_PREAUTH_TRYAGAIN(context, h->vt.name, pa_type, ret);
+ if (!ret && mod_pa == NULL)
+ ret = KRB5KRB_ERR_GENERIC;
+ if (ret) {
+ k5_preauth_note_failed(ctx, pa_type);
+ return ret;
}
- return KRB5KRB_ERR_GENERIC;
+
+ for (count = 0; mod_pa[count] != NULL; count++);
+ ret = copy_cookie(context, err_padata, &mod_pa, &count);
+ if (ret) {
+ krb5_free_pa_data(context, mod_pa);
+ return ret;
+ }
+
+ TRACE_PREAUTH_TRYAGAIN_OUTPUT(context, mod_pa);
+ *padata_out = mod_pa;
+ return 0;
}
/* Compile the set of response items for in_padata by invoke each module's
@@ -897,9 +978,9 @@ static krb5_error_code
fill_response_items(krb5_context context, krb5_init_creds_context ctx,
krb5_pa_data **in_padata)
{
- struct krb5_preauth_context_st *pctx = context->preauth_context;
krb5_error_code ret;
krb5_pa_data *pa;
+ krb5_clpreauth_modreq modreq;
clpreauth_handle h;
int i;
@@ -908,11 +989,11 @@ fill_response_items(krb5_context context, krb5_init_creds_context ctx,
pa = in_padata[i];
if (!pa_type_allowed(ctx, pa->pa_type))
continue;
- h = find_module(pctx->handles, pa->pa_type);
+ h = find_module(context, ctx, pa->pa_type, &modreq);
if (h == NULL)
continue;
- ret = clpreauth_prep_questions(context, h, ctx->opt, &callbacks,
- (krb5_clpreauth_rock)ctx,
+ ret = clpreauth_prep_questions(context, h, modreq, ctx->opt,
+ &callbacks, (krb5_clpreauth_rock)ctx,
ctx->request, ctx->inner_request_body,
ctx->encoded_previous_request, pa);
if (ret)
@@ -1004,7 +1085,7 @@ krb5_preauth_supply_preauth_data(krb5_context context,
krb5_get_init_creds_opt *opt,
const char *attr, const char *value)
{
- struct krb5_preauth_context_st *pctx = context->preauth_context;
+ krb5_preauth_context pctx = context->preauth_context;
clpreauth_handle *hp, h;
krb5_error_code ret;
diff --git a/src/lib/krb5/krb/preauth_ec.c b/src/lib/krb5/krb/preauth_ec.c
index b1978336a063..c1aa9090fb6c 100644
--- a/src/lib/krb5/krb/preauth_ec.c
+++ b/src/lib/krb5/krb/preauth_ec.c
@@ -58,6 +58,8 @@ ec_process(krb5_context context, krb5_clpreauth_moddata moddata,
krb5_keyblock *challenge_key = NULL, *armor_key, *as_key;
armor_key = cb->fast_armor(context, rock);
+ if (armor_key == NULL)
+ return ENOENT;
retval = cb->get_as_key(context, rock, &as_key);
if (retval == 0 && padata->length) {
krb5_enc_data *enc = NULL;
diff --git a/src/lib/krb5/krb/send_tgs.c b/src/lib/krb5/krb/send_tgs.c
index f6fdf68d4725..e43a5cc5b135 100644
--- a/src/lib/krb5/krb/send_tgs.c
+++ b/src/lib/krb5/krb/send_tgs.c
@@ -28,6 +28,25 @@
#include "int-proto.h"
#include "fast.h"
+/* Choose a random nonce for an AS or TGS request. */
+krb5_error_code
+k5_generate_nonce(krb5_context context, int32_t *out)
+{
+ krb5_error_code ret;
+ unsigned char random_buf[4];
+ krb5_data random_data = make_data(random_buf, 4);
+
+ *out = 0;
+
+ /* We and Heimdal incorrectly encode nonces as signed, so make sure we use
+ * a non-negative value to avoid interoperability issues. */
+ ret = krb5_c_random_make_octets(context, &random_data);
+ if (ret)
+ return ret;
+ *out = 0x7FFFFFFF & load_32_n(random_buf);
+ return 0;
+}
+
/* Construct an AP-REQ message for a TGS request. */
static krb5_error_code
tgs_construct_ap_req(krb5_context context, krb5_data *checksum_data,
@@ -156,10 +175,13 @@ k5_make_tgs_req(krb5_context context,
req.till = desired->times.endtime ? desired->times.endtime :
tgt->times.endtime;
req.rtime = desired->times.renew_till;
+ ret = k5_generate_nonce(context, &req.nonce);
+ if (ret)
+ return ret;
+ *nonce_out = req.nonce;
ret = krb5_timeofday(context, &time_now);
if (ret)
return ret;
- *nonce_out = req.nonce = (krb5_int32)time_now;
*timestamp_out = time_now;
req.addresses = (krb5_address **)addrs;
diff --git a/src/lib/krb5/krb/sendauth.c b/src/lib/krb5/krb/sendauth.c
index f7e6777411aa..149e25dd7362 100644
--- a/src/lib/krb5/krb/sendauth.c
+++ b/src/lib/krb5/krb/sendauth.c
@@ -131,22 +131,21 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context,
This isn't strong cryptographically; the point here is
not to guarantee randomness, but to make it less likely
that multiple sessions could pick the same subkey. */
- char rnd_data[1024];
+ struct sockaddr_storage rnd_data;
GETPEERNAME_ARG3_TYPE len2;
- krb5_data d;
- d.length = sizeof (rnd_data);
- d.data = rnd_data;
- len2 = sizeof (rnd_data);
- if (getpeername (*(int*)fd, (GETPEERNAME_ARG2_TYPE *) rnd_data,
- &len2) == 0) {
+ krb5_data d = make_data(&rnd_data, sizeof(rnd_data));
+
+ len2 = sizeof(rnd_data);
+ if (getpeername(*(int *)fd, ss2sa(&rnd_data), &len2) == 0) {
d.length = len2;
- (void) krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL, &d);
+ (void)krb5_c_random_add_entropy(
+ context, KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL, &d);
}
- len2 = sizeof (rnd_data);
- if (getsockname (*(int*)fd, (GETSOCKNAME_ARG2_TYPE *) rnd_data,
- &len2) == 0) {
+ len2 = sizeof(rnd_data);
+ if (getsockname(*(int *)fd, ss2sa(&rnd_data), &len2) == 0) {
d.length = len2;
- (void) krb5_c_random_add_entropy (context, KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL, &d);
+ (void)krb5_c_random_add_entropy(
+ context, KRB5_C_RANDSOURCE_EXTERNAL_PROTOCOL, &d);
}
}
diff --git a/src/lib/krb5/krb/str_conv.c b/src/lib/krb5/krb/str_conv.c
index 3ab7eacac1c0..f0a2ae20bab5 100644
--- a/src/lib/krb5/krb/str_conv.c
+++ b/src/lib/krb5/krb/str_conv.c
@@ -207,7 +207,7 @@ krb5_error_code KRB5_CALLCONV
krb5_timestamp_to_string(krb5_timestamp timestamp, char *buffer, size_t buflen)
{
size_t ret;
- time_t timestamp2 = timestamp;
+ time_t timestamp2 = ts2tt(timestamp);
struct tm tmbuf;
const char *fmt = "%c"; /* This is to get around gcc -Wall warning that
the year returned might be two digits */
@@ -229,7 +229,7 @@ krb5_timestamp_to_sfstring(krb5_timestamp timestamp, char *buffer, size_t buflen
struct tm *tmp;
size_t i;
size_t ndone;
- time_t timestamp2 = timestamp;
+ time_t timestamp2 = ts2tt(timestamp);
struct tm tmbuf;
static const char * const sftime_format_table[] = {
diff --git a/src/lib/krb5/krb/t_expire_warn.py b/src/lib/krb5/krb/t_expire_warn.py
index e021379ab1cf..aed39e3995ab 100755
--- a/src/lib/krb5/krb/t_expire_warn.py
+++ b/src/lib/krb5/krb/t_expire_warn.py
@@ -39,15 +39,10 @@ realm.run([kadminl, 'addprinc', '-pw', 'pass', '-pwexpire', '3 days', 'days'])
output = realm.run(['./t_expire_warn', 'noexpire', 'pass', '0'])
if output:
fail('Unexpected output for noexpire')
-output = realm.run(['./t_expire_warn', 'minutes', 'pass', '0'])
-if ' less than one hour on ' not in output:
- fail('Expected warning not seen for minutes')
-output = realm.run(['./t_expire_warn', 'hours', 'pass', '0'])
-if ' hours on ' not in output:
- fail('Expected warning not seen for hours')
-output = realm.run(['./t_expire_warn', 'days', 'pass', '0'])
-if ' days on ' not in output:
- fail('Expected warning not seen for days')
+realm.run(['./t_expire_warn', 'minutes', 'pass', '0'],
+ expected_msg=' less than one hour on ')
+realm.run(['./t_expire_warn', 'hours', 'pass', '0'], expected_msg=' hours on ')
+realm.run(['./t_expire_warn', 'days', 'pass', '0'], expected_msg=' days on ')
# Check for expected expire callback behavior. These tests are
# carefully agnostic about whether the KDC supports last_req fields,
diff --git a/src/lib/krb5/krb/t_kerb.c b/src/lib/krb5/krb/t_kerb.c
index 60cfb5b15115..74ac14d9ab64 100644
--- a/src/lib/krb5/krb/t_kerb.c
+++ b/src/lib/krb5/krb/t_kerb.c
@@ -5,16 +5,8 @@
*/
#include "autoconf.h"
-#include "krb5.h"
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
+#include "k5-int.h"
#include <time.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
#include "com_err.h"
@@ -37,7 +29,7 @@ test_string_to_timestamp(krb5_context ctx, char *ktime)
com_err("krb5_string_to_timestamp", retval, 0);
return;
}
- t = (time_t) timestamp;
+ t = ts2tt(timestamp);
printf("Parsed time was %s", ctime(&t));
}
diff --git a/src/lib/krb5/krb/t_parse_host_string.c b/src/lib/krb5/krb/t_parse_host_string.c
index 76dd20f817b0..001b77389555 100644
--- a/src/lib/krb5/krb/t_parse_host_string.c
+++ b/src/lib/krb5/krb/t_parse_host_string.c
@@ -31,10 +31,7 @@
*/
#include "k5-int.h"
-#include <stdarg.h>
-#include <stddef.h>
-#include <setjmp.h>
-#include <cmocka.h>
+#include "k5-cmocka.h"
#include <malloc.h>
/* Call k5_parse_host_string() and check the result against the expected code,
diff --git a/src/lib/krb5/krb/t_valid_times.c b/src/lib/krb5/krb/t_valid_times.c
new file mode 100644
index 000000000000..1b469ffc252f
--- /dev/null
+++ b/src/lib/krb5/krb/t_valid_times.c
@@ -0,0 +1,109 @@
+/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/krb/t_valid_times.c - test program for krb5int_validate_times() */
+/*
+ * Copyright (C) 2017 by the Massachusetts Institute of Technology.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "k5-int.h"
+#include "int-proto.h"
+
+#define BOUNDARY (uint32_t)INT32_MIN
+
+int
+main()
+{
+ krb5_error_code ret;
+ krb5_context context;
+ krb5_ticket_times times = { 0, 0, 0, 0 };
+
+ ret = krb5_init_context(&context);
+ assert(!ret);
+
+ /* Current time is within authtime and end time. */
+ ret = krb5_set_debugging_time(context, 1000, 0);
+ times.authtime = 500;
+ times.endtime = 1500;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is before starttime, but within clock skew. */
+ times.starttime = 1100;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is before starttime by more than clock skew. */
+ times.starttime = 1400;
+ ret = krb5int_validate_times(context, &times);
+ assert(ret == KRB5KRB_AP_ERR_TKT_NYV);
+
+ /* Current time is after end time, but within clock skew. */
+ times.starttime = 500;
+ times.endtime = 800;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is after end time by more than clock skew. */
+ times.endtime = 600;
+ ret = krb5int_validate_times(context, &times);
+ assert(ret == KRB5KRB_AP_ERR_TKT_EXPIRED);
+
+ /* Current time is within starttime and endtime; current time and
+ * endtime are across y2038 boundary. */
+ ret = krb5_set_debugging_time(context, BOUNDARY - 100, 0);
+ assert(!ret);
+ times.starttime = BOUNDARY - 200;
+ times.endtime = BOUNDARY + 500;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is before starttime, but by less than clock skew. */
+ times.starttime = BOUNDARY + 100;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is before starttime by more than clock skew. */
+ times.starttime = BOUNDARY + 250;
+ ret = krb5int_validate_times(context, &times);
+ assert(ret == KRB5KRB_AP_ERR_TKT_NYV);
+
+ /* Current time is after endtime, but by less than clock skew. */
+ ret = krb5_set_debugging_time(context, BOUNDARY + 100, 0);
+ assert(!ret);
+ times.starttime = BOUNDARY - 1000;
+ times.endtime = BOUNDARY - 100;
+ ret = krb5int_validate_times(context, &times);
+ assert(!ret);
+
+ /* Current time is after endtime by more than clock skew. */
+ times.endtime = BOUNDARY - 300;
+ ret = krb5int_validate_times(context, &times);
+ assert(ret == KRB5KRB_AP_ERR_TKT_EXPIRED);
+
+ return 0;
+}
diff --git a/src/lib/krb5/krb/valid_times.c b/src/lib/krb5/krb/valid_times.c
index d63122183eff..294761a882c5 100644
--- a/src/lib/krb5/krb/valid_times.c
+++ b/src/lib/krb5/krb/valid_times.c
@@ -47,10 +47,10 @@ krb5int_validate_times(krb5_context context, krb5_ticket_times *times)
else
starttime = times->authtime;
- if (starttime - currenttime > context->clockskew)
+ if (ts_after(starttime, ts_incr(currenttime, context->clockskew)))
return KRB5KRB_AP_ERR_TKT_NYV; /* ticket not yet valid */
- if ((currenttime - times->endtime) > context->clockskew)
+ if (ts_after(currenttime, ts_incr(times->endtime, context->clockskew)))
return KRB5KRB_AP_ERR_TKT_EXPIRED; /* ticket expired */
return 0;
diff --git a/src/lib/krb5/krb/vfy_increds.c b/src/lib/krb5/krb/vfy_increds.c
index 9786d63b5cb1..b4878ba3852e 100644
--- a/src/lib/krb5/krb/vfy_increds.c
+++ b/src/lib/krb5/krb/vfy_increds.c
@@ -120,7 +120,7 @@ get_vfy_cred(krb5_context context, krb5_creds *creds, krb5_principal server,
ret = krb5_timeofday(context, &in_creds.times.endtime);
if (ret)
goto cleanup;
- in_creds.times.endtime += 5*60;
+ in_creds.times.endtime = ts_incr(in_creds.times.endtime, 5 * 60);
ret = krb5_get_credentials(context, 0, ccache, &in_creds, &out_creds);
if (ret)
goto cleanup;
diff --git a/src/lib/krb5/krb/x-deltat.y b/src/lib/krb5/krb/x-deltat.y
index f9cc2bb46959..da11b88077aa 100644
--- a/src/lib/krb5/krb/x-deltat.y
+++ b/src/lib/krb5/krb/x-deltat.y
@@ -44,7 +44,6 @@
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
-#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
#include "k5-int.h"
diff --git a/src/lib/krb5/os/Makefile.in b/src/lib/krb5/os/Makefile.in
index efa82e22f35e..5d2fcb5be8fa 100644
--- a/src/lib/krb5/os/Makefile.in
+++ b/src/lib/krb5/os/Makefile.in
@@ -225,7 +225,7 @@ check-unix-locate: t_locate_kdc
$(RUN_TEST) ./t_locate_kdc $(LOCREALM); \
else \
echo '*** WARNING: skipped t_locate_kdc test: known DNS name not found'; \
- echo 'Skipped t_locate_kdc test: known DNS name found' >> $(SKIPTESTS); \
+ echo 'Skipped t_locate_kdc test: known DNS name not found' >> $(SKIPTESTS); \
fi; \
else \
echo '*** WARNING: skipped t_locate_kdc test: OFFLINE'; \
diff --git a/src/lib/krb5/os/accessor.c b/src/lib/krb5/os/accessor.c
index df63b14faa56..11552ef42c08 100644
--- a/src/lib/krb5/os/accessor.c
+++ b/src/lib/krb5/os/accessor.c
@@ -30,11 +30,14 @@
/* If this trick gets used elsewhere, move it to k5-platform.h. */
#ifndef DESIGNATED_INITIALIZERS
-#define DESIGNATED_INITIALIZERS \
- /* ANSI/ISO C 1999 supports this... */ \
- (__STDC_VERSION__ >= 199901L \
- /* ...as does GCC, since version 2.something. */ \
- || (!defined __cplusplus && __GNUC__ >= 3))
+/* ANSI/ISO C 1999 supports this... */
+#if __STDC_VERSION__ >= 199901L \
+ /* ...as does GCC, since version 2.something. */ \
+ || (!defined __cplusplus && __GNUC__ >= 3)
+#define DESIGNATED_INITIALIZERS 1
+#else
+#define DESIGNATED_INITIALIZERS 0
+#endif
#endif
krb5_error_code KRB5_CALLCONV
diff --git a/src/lib/krb5/os/c_ustime.c b/src/lib/krb5/os/c_ustime.c
index 871d72183007..f69f2ea4c332 100644
--- a/src/lib/krb5/os/c_ustime.c
+++ b/src/lib/krb5/os/c_ustime.c
@@ -29,7 +29,10 @@
k5_mutex_t krb5int_us_time_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
-struct time_now { krb5_int32 sec, usec; };
+struct time_now {
+ krb5_timestamp sec;
+ krb5_int32 usec;
+};
#if defined(_WIN32)
@@ -73,7 +76,7 @@ get_time_now(struct time_now *n)
static struct time_now last_time;
krb5_error_code
-krb5_crypto_us_timeofday(krb5_int32 *seconds, krb5_int32 *microseconds)
+krb5_crypto_us_timeofday(krb5_timestamp *seconds, krb5_int32 *microseconds)
{
struct time_now now;
krb5_error_code err;
@@ -102,17 +105,17 @@ krb5_crypto_us_timeofday(krb5_int32 *seconds, krb5_int32 *microseconds)
putting now.sec in the past. But don't just use '<' because we
need to properly handle the case where the administrator intentionally
adjusted time backwards. */
- if ((now.sec == last_time.sec-1) ||
- ((now.sec == last_time.sec) && (now.usec <= last_time.usec))) {
+ if (now.sec == ts_incr(last_time.sec, -1) ||
+ (now.sec == last_time.sec && !ts_after(last_time.usec, now.usec))) {
/* Correct 'now' to be exactly one microsecond later than 'last_time'.
Note that _because_ we perform this hack, 'now' may be _earlier_
than 'last_time', even though the system time is monotonically
increasing. */
now.sec = last_time.sec;
- now.usec = ++last_time.usec;
+ now.usec = ts_incr(last_time.usec, 1);
if (now.usec >= 1000000) {
- ++now.sec;
+ now.sec = ts_incr(now.sec, 1);
now.usec = 0;
}
}
diff --git a/src/lib/krb5/os/dnsglue.c b/src/lib/krb5/os/dnsglue.c
index 1a259b399eba..e29066d74bc5 100644
--- a/src/lib/krb5/os/dnsglue.c
+++ b/src/lib/krb5/os/dnsglue.c
@@ -73,7 +73,7 @@ static int initparse(struct krb5int_dns_state *);
#if defined(__APPLE__)
-/* Use the OS X interfaces dns_open, dns_search, and dns_free. */
+/* Use the macOS interfaces dns_open, dns_search, and dns_free. */
#define DECLARE_HANDLE(h) dns_handle_t h
#define INIT_HANDLE(h) ((h = dns_open(NULL)) != NULL)
#define SEARCH(h, n, c, t, a, l) dns_search(h, n, c, t, a, l, NULL, NULL)
diff --git a/src/lib/krb5/os/dnsglue.h b/src/lib/krb5/os/dnsglue.h
index 27147a6cab51..e7844049db72 100644
--- a/src/lib/krb5/os/dnsglue.h
+++ b/src/lib/krb5/os/dnsglue.h
@@ -33,9 +33,9 @@
* BIND 4 doesn't have the ns_initparse() API, so we need to do some
* manual parsing via the HEADER struct. BIND 8 does have
* ns_initparse(), but has enums for the various protocol constants
- * rather than the BIND 4 macros. BIND 9 (at least on Mac OS X
- * Panther) appears to disable res_nsearch() if BIND_8_COMPAT is
- * defined (which is necessary to obtain the HEADER struct).
+ * rather than the BIND 4 macros. BIND 9 (at least on macOS 10.3)
+ * appears to disable res_nsearch() if BIND_8_COMPAT is defined
+ * (which is necessary to obtain the HEADER struct).
*
* We use ns_initparse() if available at all, and never define
* BIND_8_COMPAT. If there is no ns_initparse(), we do manual parsing
@@ -167,15 +167,16 @@ struct srv_dns_entry {
char *host;
};
-krb5_error_code krb5int_make_srv_query_realm(const krb5_data *realm,
- const char *service,
- const char *protocol,
- struct srv_dns_entry **answers);
+krb5_error_code
+krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
+ const char *service, const char *protocol,
+ struct srv_dns_entry **answers);
+
void krb5int_free_srv_dns_data(struct srv_dns_entry *);
krb5_error_code
-k5_make_uri_query(const krb5_data *realm, const char *service,
- struct srv_dns_entry **answers);
+k5_make_uri_query(krb5_context context, const krb5_data *realm,
+ const char *service, struct srv_dns_entry **answers);
#endif /* KRB5_DNS_LOOKUP */
#endif /* !defined(KRB5_DNSGLUE_H) */
diff --git a/src/lib/krb5/os/dnssrv.c b/src/lib/krb5/os/dnssrv.c
index 76f5b63a1774..d66a8f99a0af 100644
--- a/src/lib/krb5/os/dnssrv.c
+++ b/src/lib/krb5/os/dnssrv.c
@@ -104,8 +104,8 @@ place_srv_entry(struct srv_dns_entry **head, struct srv_dns_entry *new)
/* Query the URI RR, collecting weight, priority, and target. */
krb5_error_code
-k5_make_uri_query(const krb5_data *realm, const char *service,
- struct srv_dns_entry **answers)
+k5_make_uri_query(krb5_context context, const krb5_data *realm,
+ const char *service, struct srv_dns_entry **answers)
{
const unsigned char *p = NULL, *base = NULL;
char host[MAXDNAME];
@@ -121,6 +121,8 @@ k5_make_uri_query(const krb5_data *realm, const char *service,
if (ret)
return 0;
+ TRACE_DNS_URI_SEND(context, host);
+
size = krb5int_dns_init(&ds, host, C_IN, T_URI);
if (size < 0)
goto out;
@@ -148,6 +150,7 @@ k5_make_uri_query(const krb5_data *realm, const char *service,
goto out;
}
+ TRACE_DNS_URI_ANS(context, uri->host, uri->priority, uri->weight);
place_srv_entry(&head, uri);
}
@@ -165,9 +168,8 @@ out:
*/
krb5_error_code
-krb5int_make_srv_query_realm(const krb5_data *realm,
- const char *service,
- const char *protocol,
+krb5int_make_srv_query_realm(krb5_context context, const krb5_data *realm,
+ const char *service, const char *protocol,
struct srv_dns_entry **answers)
{
const unsigned char *p = NULL, *base = NULL;
@@ -192,9 +194,7 @@ krb5int_make_srv_query_realm(const krb5_data *realm,
if (ret)
return 0;
-#ifdef TEST
- fprintf(stderr, "sending DNS SRV query for %s\n", host);
-#endif
+ TRACE_DNS_SRV_SEND(context, host);
size = krb5int_dns_init(&ds, host, C_IN, T_SRV);
if (size < 0)
@@ -239,6 +239,8 @@ krb5int_make_srv_query_realm(const krb5_data *realm,
goto out;
}
+ TRACE_DNS_SRV_ANS(context, srv->host, srv->port, srv->priority,
+ srv->weight);
place_srv_entry(&head, srv);
}
diff --git a/src/lib/krb5/os/expand_path.c b/src/lib/krb5/os/expand_path.c
index a8a14f4bb28b..61fb234594e6 100644
--- a/src/lib/krb5/os/expand_path.c
+++ b/src/lib/krb5/os/expand_path.c
@@ -351,7 +351,7 @@ expand_null(krb5_context context, PTYPE param, const char *postfix, char **ret)
return 0;
}
-static const struct token {
+static const struct {
const char *tok;
PTYPE param;
const char *postfix;
diff --git a/src/lib/krb5/os/genaddrs.c b/src/lib/krb5/os/genaddrs.c
index 5ef7af5a339f..c818fdb6d79d 100644
--- a/src/lib/krb5/os/genaddrs.c
+++ b/src/lib/krb5/os/genaddrs.c
@@ -79,8 +79,8 @@ krb5_auth_con_genaddrs(krb5_context context, krb5_auth_context auth_context, int
ssize = sizeof(struct sockaddr_storage);
if ((flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) ||
(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR)) {
- if ((retval = getsockname(fd, (GETSOCKNAME_ARG2_TYPE *) &lsaddr,
- &ssize)))
+ retval = getsockname(fd, ss2sa(&lsaddr), &ssize);
+ if (retval)
return retval;
if (cvtaddr (&lsaddr, &laddrs)) {
@@ -99,8 +99,8 @@ krb5_auth_con_genaddrs(krb5_context context, krb5_auth_context auth_context, int
ssize = sizeof(struct sockaddr_storage);
if ((flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) ||
(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR)) {
- if ((retval = getpeername(fd, (GETPEERNAME_ARG2_TYPE *) &rsaddr,
- &ssize)))
+ retval = getpeername(fd, ss2sa(&rsaddr), &ssize);
+ if (retval)
return errno;
if (cvtaddr (&rsaddr, &raddrs)) {
diff --git a/src/lib/krb5/os/hostaddr.c b/src/lib/krb5/os/hostaddr.c
index 22f6ad6d48b9..d7a4a763012d 100644
--- a/src/lib/krb5/os/hostaddr.c
+++ b/src/lib/krb5/os/hostaddr.c
@@ -83,12 +83,12 @@ k5_os_hostaddr(krb5_context context, const char *name,
switch (aip->ai_addr->sa_family) {
case AF_INET:
addrlen = sizeof (struct in_addr);
- ptr = &((struct sockaddr_in *)aip->ai_addr)->sin_addr;
+ ptr = &sa2sin(aip->ai_addr)->sin_addr;
atype = ADDRTYPE_INET;
break;
case AF_INET6:
addrlen = sizeof (struct in6_addr);
- ptr = &((struct sockaddr_in6 *)aip->ai_addr)->sin6_addr;
+ ptr = &sa2sin6(aip->ai_addr)->sin6_addr;
atype = ADDRTYPE_INET6;
break;
default:
diff --git a/src/lib/krb5/os/localaddr.c b/src/lib/krb5/os/localaddr.c
index 9f7765254467..58443f6e354a 100644
--- a/src/lib/krb5/os/localaddr.c
+++ b/src/lib/krb5/os/localaddr.c
@@ -181,11 +181,11 @@ is_loopback_address(struct sockaddr *sa)
{
switch (sa->sa_family) {
case AF_INET: {
- struct sockaddr_in *s4 = (struct sockaddr_in *)sa;
+ struct sockaddr_in *s4 = sa2sin(sa);
return s4->sin_addr.s_addr == htonl(INADDR_LOOPBACK);
}
case AF_INET6: {
- struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)sa;
+ struct sockaddr_in6 *s6 = sa2sin6(sa);
return IN6_IS_ADDR_LOOPBACK(&s6->sin6_addr);
}
default:
@@ -239,16 +239,17 @@ printifaddr(struct ifaddrs *ifp)
#include <stdlib.h>
static int
-addr_eq (const struct sockaddr *s1, const struct sockaddr *s2)
+addr_eq (struct sockaddr *s1, struct sockaddr *s2)
{
if (s1->sa_family != s2->sa_family)
return 0;
-#define CMPTYPE(T,F) (!memcmp(&((const T*)s1)->F,&((const T*)s2)->F,sizeof(((const T*)s1)->F)))
switch (s1->sa_family) {
case AF_INET:
- return CMPTYPE (struct sockaddr_in, sin_addr);
+ return !memcmp(&sa2sin(s1)->sin_addr, &sa2sin(s2)->sin_addr,
+ sizeof(sa2sin(s1)->sin_addr));
case AF_INET6:
- return CMPTYPE (struct sockaddr_in6, sin6_addr);
+ return !memcmp(&sa2sin6(s1)->sin6_addr, &sa2sin6(s2)->sin6_addr,
+ sizeof(sa2sin6(s1)->sin6_addr));
default:
/* Err on side of duplicate listings. */
return 0;
@@ -861,6 +862,9 @@ get_ifreq_array(char **bufp, size_t *np, int s)
int numifs = -1;
#endif
+ *bufp = NULL;
+ *np = 0;
+
/* At least on NetBSD, an ifreq can hold an IPv4 address, but
isn't big enough for an IPv6 or ethernet address. So add a
little more space. */
@@ -937,9 +941,9 @@ foreach_localaddr (/*@null@*/ void *data,
#endif
{
struct ifreq *ifr, ifreq, *ifr2;
- int s, code;
+ int s;
char *buf = 0;
- size_t size, n, i, j;
+ size_t n, i, j;
int retval = 0;
#ifdef LINUX_IPV6_HACK
struct linux_ipv6_addr_list *linux_ipv6_addrs = get_linux_ipv6_addrs ();
@@ -1183,14 +1187,14 @@ add_addr (void *P_data, struct sockaddr *a)
#ifdef HAVE_NETINET_IN_H
case AF_INET:
address = make_addr (ADDRTYPE_INET, sizeof (struct in_addr),
- &((const struct sockaddr_in *) a)->sin_addr);
+ &sa2sin(a)->sin_addr);
if (address == NULL)
data->mem_err++;
break;
case AF_INET6:
{
- const struct sockaddr_in6 *in = (const struct sockaddr_in6 *) a;
+ const struct sockaddr_in6 *in = sa2sin6(a);
if (IN6_IS_ADDR_LINKLOCAL (&in->sin6_addr))
break;
diff --git a/src/lib/krb5/os/locate_kdc.c b/src/lib/krb5/os/locate_kdc.c
index 014ec6ecb902..b9edecc7a910 100644
--- a/src/lib/krb5/os/locate_kdc.c
+++ b/src/lib/krb5/os/locate_kdc.c
@@ -313,14 +313,16 @@ krb5_locate_srv_conf(krb5_context context, const krb5_data *realm,
#ifdef KRB5_DNS_LOOKUP
static krb5_error_code
-locate_srv_dns_1(const krb5_data *realm, const char *service,
- const char *protocol, struct serverlist *serverlist)
+locate_srv_dns_1(krb5_context context, const krb5_data *realm,
+ const char *service, const char *protocol,
+ struct serverlist *serverlist)
{
struct srv_dns_entry *head = NULL, *entry = NULL;
krb5_error_code code = 0;
k5_transport transport;
- code = krb5int_make_srv_query_realm(realm, service, protocol, &head);
+ code = krb5int_make_srv_query_realm(context, realm, service, protocol,
+ &head);
if (code)
return 0;
@@ -598,9 +600,10 @@ parse_uri_fields(const char *uri, k5_transport *transport_out,
* and transport type. Problematic entries are skipped.
*/
static krb5_error_code
-locate_uri(const krb5_data *realm, const char *req_service,
- struct serverlist *serverlist, k5_transport req_transport,
- int default_port, krb5_boolean master_only)
+locate_uri(krb5_context context, const krb5_data *realm,
+ const char *req_service, struct serverlist *serverlist,
+ k5_transport req_transport, int default_port,
+ krb5_boolean master_only)
{
krb5_error_code ret;
k5_transport transport, host_trans;
@@ -609,7 +612,7 @@ locate_uri(const krb5_data *realm, const char *req_service,
const char *host_field, *path;
int port, def_port, master;
- ret = k5_make_uri_query(realm, req_service, &answers);
+ ret = k5_make_uri_query(context, realm, req_service, &answers);
if (ret || answers == NULL)
return ret;
@@ -688,10 +691,11 @@ dns_locate_server_uri(krb5_context context, const krb5_data *realm,
return 0;
}
- ret = locate_uri(realm, svcname, serverlist, transport, def_port,
+ ret = locate_uri(context, realm, svcname, serverlist, transport, def_port,
find_master);
- if (ret)
- Tprintf("dns URI lookup returned error %d\n", ret);
+
+ if (serverlist->nservers == 0)
+ TRACE_DNS_URI_NOTFOUND(context);
return ret;
}
@@ -729,16 +733,15 @@ dns_locate_server_srv(krb5_context context, const krb5_data *realm,
}
code = 0;
- if (transport == UDP || transport == TCP_OR_UDP) {
- code = locate_srv_dns_1(realm, dnsname, "_udp", serverlist);
- if (code)
- Tprintf("dns udp lookup returned error %d\n", code);
- }
- if ((transport == TCP || transport == TCP_OR_UDP) && code == 0) {
- code = locate_srv_dns_1(realm, dnsname, "_tcp", serverlist);
- if (code)
- Tprintf("dns tcp lookup returned error %d\n", code);
- }
+ if (transport == UDP || transport == TCP_OR_UDP)
+ code = locate_srv_dns_1(context, realm, dnsname, "_udp", serverlist);
+
+ if ((transport == TCP || transport == TCP_OR_UDP) && code == 0)
+ code = locate_srv_dns_1(context, realm, dnsname, "_tcp", serverlist);
+
+ if (serverlist->nservers == 0)
+ TRACE_DNS_SRV_NOTFOUND(context);
+
return code;
}
#endif /* KRB5_DNS_LOOKUP */
diff --git a/src/lib/krb5/os/sendto_kdc.c b/src/lib/krb5/os/sendto_kdc.c
index fffe0262f6bb..e8bc0ad6e2f5 100644
--- a/src/lib/krb5/os/sendto_kdc.c
+++ b/src/lib/krb5/os/sendto_kdc.c
@@ -253,7 +253,7 @@ cm_get_ssflags(struct select_state *selstate, int fd)
struct pollfd *pfd = find_pollfd(selstate, fd);
/*
- * OS X sets POLLHUP without POLLOUT on connection error. Catch this as
+ * macOS sets POLLHUP without POLLOUT on connection error. Catch this as
* well as other error events such as POLLNVAL, but only if POLLIN and
* POLLOUT aren't set, as we can get POLLHUP along with POLLIN with TCP
* data still to be read.
@@ -1372,8 +1372,7 @@ get_endtime(time_ms endtime, struct conn_state *conns)
struct conn_state *state;
for (state = conns; state != NULL; state = state->next) {
- if (state->addr.transport == TCP &&
- (state->state == READING || state->state == WRITING) &&
+ if ((state->state == READING || state->state == WRITING) &&
state->endtime > endtime)
endtime = state->endtime;
}
diff --git a/src/lib/krb5/os/t_locate_kdc.c b/src/lib/krb5/os/t_locate_kdc.c
index 6414b8e92d79..7a53c842a80e 100644
--- a/src/lib/krb5/os/t_locate_kdc.c
+++ b/src/lib/krb5/os/t_locate_kdc.c
@@ -127,7 +127,7 @@ main (int argc, char *argv[])
break;
case LOOKUP_DNS:
- err = locate_srv_dns_1(&realm, "_kerberos", "_udp", &sl);
+ err = locate_srv_dns_1(ctx, &realm, "_kerberos", "_udp", &sl);
break;
case LOOKUP_WHATEVER:
diff --git a/src/lib/krb5/os/timeofday.c b/src/lib/krb5/os/timeofday.c
index fddb1214296f..d4e36b1c7572 100644
--- a/src/lib/krb5/os/timeofday.c
+++ b/src/lib/krb5/os/timeofday.c
@@ -60,7 +60,7 @@ krb5_check_clockskew(krb5_context context, krb5_timestamp date)
retval = krb5_timeofday(context, &currenttime);
if (retval)
return retval;
- if (!(labs((date)-currenttime) < context->clockskew))
+ if (!ts_within(date, currenttime, context->clockskew))
return KRB5KRB_AP_ERR_SKEW;
return 0;
diff --git a/src/lib/krb5/os/toffset.c b/src/lib/krb5/os/toffset.c
index 456193a41aed..4bbcdde52812 100644
--- a/src/lib/krb5/os/toffset.c
+++ b/src/lib/krb5/os/toffset.c
@@ -40,14 +40,15 @@ krb5_error_code KRB5_CALLCONV
krb5_set_real_time(krb5_context context, krb5_timestamp seconds, krb5_int32 microseconds)
{
krb5_os_context os_ctx = &context->os_context;
- krb5_int32 sec, usec;
+ krb5_timestamp sec;
+ krb5_int32 usec;
krb5_error_code retval;
retval = krb5_crypto_us_timeofday(&sec, &usec);
if (retval)
return retval;
- os_ctx->time_offset = seconds - sec;
+ os_ctx->time_offset = ts_delta(seconds, sec);
os_ctx->usec_offset = (microseconds > -1) ? microseconds - usec : 0;
os_ctx->os_flags = ((os_ctx->os_flags & ~KRB5_OS_TOFFSET_TIME) |
diff --git a/src/lib/krb5/os/trace.c b/src/lib/krb5/os/trace.c
index 83c8d4db876a..e97ce5fe5d66 100644
--- a/src/lib/krb5/os/trace.c
+++ b/src/lib/krb5/os/trace.c
@@ -173,7 +173,7 @@ trace_format(krb5_context context, const char *fmt, va_list ap)
p = va_arg(ap, const char *);
if (p == NULL && len != 0)
k5_buf_add(&buf, "(null)");
- else
+ else if (p != NULL)
buf_add_printable_len(&buf, p, len);
} else if (strcmp(tmpbuf, "hexlenstr") == 0) {
len = va_arg(ap, size_t);
@@ -340,7 +340,8 @@ krb5int_trace(krb5_context context, const char *fmt, ...)
va_list ap;
krb5_trace_info info;
char *str = NULL, *msg = NULL;
- krb5_int32 sec, usec;
+ krb5_timestamp sec;
+ krb5_int32 usec;
if (context == NULL || context->trace_callback == NULL)
return;
@@ -350,7 +351,7 @@ krb5int_trace(krb5_context context, const char *fmt, ...)
goto cleanup;
if (krb5_crypto_us_timeofday(&sec, &usec) != 0)
goto cleanup;
- if (asprintf(&msg, "[%d] %d.%d: %s\n", (int) getpid(), (int) sec,
+ if (asprintf(&msg, "[%d] %u.%d: %s\n", (int) getpid(), (unsigned int) sec,
(int) usec, str) < 0)
goto cleanup;
info.message = msg;
diff --git a/src/lib/krb5/os/ustime.c b/src/lib/krb5/os/ustime.c
index 056357683456..a80fdf68ca48 100644
--- a/src/lib/krb5/os/ustime.c
+++ b/src/lib/krb5/os/ustime.c
@@ -40,7 +40,8 @@ krb5_error_code
k5_time_with_offset(krb5_timestamp offset, krb5_int32 offset_usec,
krb5_timestamp *time_out, krb5_int32 *usec_out)
{
- krb5_int32 sec, usec;
+ krb5_timestamp sec;
+ krb5_int32 usec;
krb5_error_code retval;
retval = krb5_crypto_us_timeofday(&sec, &usec);
@@ -49,13 +50,13 @@ k5_time_with_offset(krb5_timestamp offset, krb5_int32 offset_usec,
usec += offset_usec;
if (usec > 1000000) {
usec -= 1000000;
- sec++;
+ sec = ts_incr(sec, 1);
}
if (usec < 0) {
usec += 1000000;
- sec--;
+ sec = ts_incr(sec, -1);
}
- sec += offset;
+ sec = ts_incr(sec, offset);
*time_out = sec;
*usec_out = usec;
diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c
index c4d2c744da40..1e0cb22c94e2 100644
--- a/src/lib/krb5/rcache/rc_dfl.c
+++ b/src/lib/krb5/rcache/rc_dfl.c
@@ -93,12 +93,11 @@ cmp(krb5_donot_replay *old, krb5_donot_replay *new1, krb5_deltat t)
}
static int
-alive(krb5_int32 mytime, krb5_donot_replay *new1, krb5_deltat t)
+alive(krb5_timestamp mytime, krb5_donot_replay *new1, krb5_deltat t)
{
if (mytime == 0)
return CMP_HOHUM; /* who cares? */
- /* I hope we don't have to worry about overflow */
- if (new1->ctime + t < mytime)
+ if (ts_after(mytime, ts_incr(new1->ctime, t)))
return CMP_EXPIRED;
return CMP_HOHUM;
}
@@ -130,7 +129,7 @@ struct authlist
static int
rc_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep,
- krb5_int32 now, krb5_boolean fromfile)
+ krb5_timestamp now, krb5_boolean fromfile)
{
struct dfl_data *t = (struct dfl_data *)id->data;
unsigned int rephash;
@@ -517,7 +516,7 @@ errout:
free(rep->server);
if (rep->msghash)
free(rep->msghash);
- rep->client = rep->server = 0;
+ rep->client = rep->server = rep->msghash = NULL;
return retval;
}
@@ -537,7 +536,7 @@ krb5_rc_dfl_recover_locked(krb5_context context, krb5_rcache id)
krb5_error_code retval;
long max_size;
int expired_entries = 0;
- krb5_int32 now;
+ krb5_timestamp now;
if ((retval = krb5_rc_io_open(context, &t->d, t->name))) {
return retval;
@@ -707,7 +706,7 @@ krb5_rc_dfl_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep)
{
krb5_error_code ret;
struct dfl_data *t;
- krb5_int32 now;
+ krb5_timestamp now;
ret = krb5_timeofday(context, &now);
if (ret)
@@ -763,7 +762,7 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id)
struct authlist **qt;
struct authlist *r;
struct authlist *rt;
- krb5_int32 now;
+ krb5_timestamp now;
if (krb5_timestamp(context, &now))
now = 0;
diff --git a/src/lib/krb5/rcache/ser_rc.c b/src/lib/krb5/rcache/ser_rc.c
index 556af21e5e48..5c537f08a1cc 100644
--- a/src/lib/krb5/rcache/ser_rc.c
+++ b/src/lib/krb5/rcache/ser_rc.c
@@ -72,7 +72,7 @@ krb5_rcache_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
* krb5_int32 for KV5M_RCACHE
*/
required = sizeof(krb5_int32) * 3;
- if (rcache->ops && rcache->ops->type)
+ if (rcache->ops)
required += (strlen(rcache->ops->type)+1);
/*
diff --git a/src/lib/krb5/rcache/t_replay.c b/src/lib/krb5/rcache/t_replay.c
index db273ec2f221..b99cdf1abb8e 100644
--- a/src/lib/krb5/rcache/t_replay.c
+++ b/src/lib/krb5/rcache/t_replay.c
@@ -110,7 +110,7 @@ store(krb5_context ctx, char *rcspec, char *client, char *server, char *msg,
krb5_donot_replay rep;
krb5_data d;
- if (now_timestamp > 0)
+ if (now_timestamp != 0)
krb5_set_debugging_time(ctx, now_timestamp, now_usec);
if ((retval = krb5_rc_resolve_full(ctx, &rc, rcspec)))
goto cleanup;
@@ -221,13 +221,13 @@ main(int argc, char **argv)
msg = (**argv) ? *argv : NULL;
argc--; argv++;
if (!argc) usage(progname);
- timestamp = (krb5_timestamp) atol(*argv);
+ timestamp = (krb5_timestamp) atoll(*argv);
argc--; argv++;
if (!argc) usage(progname);
usec = (krb5_int32) atol(*argv);
argc--; argv++;
if (!argc) usage(progname);
- now_timestamp = (krb5_timestamp) atol(*argv);
+ now_timestamp = (krb5_timestamp) atoll(*argv);
argc--; argv++;
if (!argc) usage(progname);
now_usec = (krb5_int32) atol(*argv);
@@ -249,7 +249,7 @@ main(int argc, char **argv)
rcspec = *argv;
argc--; argv++;
if (!argc) usage(progname);
- now_timestamp = (krb5_timestamp) atol(*argv);
+ now_timestamp = (krb5_timestamp) atoll(*argv);
argc--; argv++;
if (!argc) usage(progname);
now_usec = (krb5_int32) atol(*argv);
diff --git a/src/lib/krb5/unicode/ure/ure.c b/src/lib/krb5/unicode/ure/ure.c
index d1cfd8af945e..23a03d94ffa2 100644
--- a/src/lib/krb5/unicode/ure/ure.c
+++ b/src/lib/krb5/unicode/ure/ure.c
@@ -421,7 +421,7 @@ _ure_prop_list(ucs2_t *pp, unsigned long limit, unsigned long *mask,
b->error = _URE_INVALID_PROPERTY;
}
- if (n != 0)
+ if (b->error == _URE_OK && n != 0)
m |= cclass_flags[n];
/*