aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/krb5/krb
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/krb5/krb')
-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
29 files changed, 664 insertions, 404 deletions
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"