summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Yu <tlyu@mit.edu>2014-04-24 17:10:58 -0400
committerTom Yu <tlyu@mit.edu>2014-04-28 16:30:37 -0400
commit4d08c9abfee0b5978d9db2280c10c85b3bf2ae11 (patch)
treeec229b1afd1526f788671407d23432ed2bdf29cf
parentf5645d30cf83398640c386a612eb6f07c543286f (diff)
downloadkrb5-4d08c9abfee0b5978d9db2280c10c85b3bf2ae11.tar.gz
krb5-4d08c9abfee0b5978d9db2280c10c85b3bf2ae11.tar.xz
krb5-4d08c9abfee0b5978d9db2280c10c85b3bf2ae11.zip
Refactor KDC option/flag processing
A lot of KDC code was spent copying options to flags, and copying header_ticket flags to the output ticket. Behavior change: previous code didn't copy PROXY from the header_ticket, but this seems to have been a minor bug rather than intentional. This also seems to have been an omission from RFC 4120.
-rw-r--r--src/kdc/do_as_req.c18
-rw-r--r--src/kdc/do_tgs_req.c46
-rw-r--r--src/kdc/kdc_util.h68
3 files changed, 82 insertions, 50 deletions
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
index 5057067bd..a1db9244c 100644
--- a/src/kdc/do_as_req.c
+++ b/src/kdc/do_as_req.c
@@ -2,8 +2,8 @@
/* kdc/do_as_req.c */
/*
* Portions Copyright (C) 2007 Apple Inc.
- * Copyright 1990, 1991, 2007, 2008, 2009, 2013 by the Massachusetts Institute
- * of Technology. All Rights Reserved.
+ * Copyright 1990, 1991, 2007, 2008, 2009, 2013, 2014 by the
+ * Massachusetts Institute of Technology. All Rights Reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
@@ -686,7 +686,8 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
state->ticket_reply.server = state->request->server;
}
- state->enc_tkt_reply.flags = 0;
+ /* Copy options that request the corresponding ticket flags. */
+ state->enc_tkt_reply.flags = OPTS2FLAGS(state->request->kdc_options);
state->enc_tkt_reply.times.authtime = state->authtime;
setflag(state->enc_tkt_reply.flags, TKT_FLG_INITIAL);
@@ -698,15 +699,6 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
* realms may refuse to issue renewable tickets
*/
- if (isflagset(state->request->kdc_options, KDC_OPT_FORWARDABLE))
- setflag(state->enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
-
- if (isflagset(state->request->kdc_options, KDC_OPT_PROXIABLE))
- setflag(state->enc_tkt_reply.flags, TKT_FLG_PROXIABLE);
-
- if (isflagset(state->request->kdc_options, KDC_OPT_ALLOW_POSTDATE))
- setflag(state->enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE);
-
state->enc_tkt_reply.session = &state->session_key;
if (isflagset(state->c_flags, KRB5_KDB_FLAG_CANONICALIZE)) {
state->client_princ = *(state->client->princ);
@@ -720,7 +712,6 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
state->enc_tkt_reply.transited.tr_contents = empty_string;
if (isflagset(state->request->kdc_options, KDC_OPT_POSTDATED)) {
- setflag(state->enc_tkt_reply.flags, TKT_FLG_POSTDATED);
setflag(state->enc_tkt_reply.flags, TKT_FLG_INVALID);
state->enc_tkt_reply.times.starttime = state->request->from;
} else
@@ -757,7 +748,6 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
state->status = "VALIDATE_ANONYMOUS_PRINCIPAL";
goto errout;
}
- setflag(state->enc_tkt_reply.flags, TKT_FLG_ANONYMOUS);
krb5_free_principal(kdc_context, state->request->client);
state->request->client = NULL;
errcode = krb5_copy_principal(kdc_context, krb5_anonymous_principal(),
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
index 49a6ea68c..fce478ed7 100644
--- a/src/kdc/do_tgs_req.c
+++ b/src/kdc/do_tgs_req.c
@@ -1,8 +1,8 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/* kdc/do_tgs_req.c - KDC Routines to deal with TGS_REQ's */
/*
- * Copyright 1990, 1991, 2001, 2007, 2008, 2009, 2013 by the Massachusetts
- * Institute of Technology. All Rights Reserved.
+ * Copyright 1990, 1991, 2001, 2007, 2008, 2009, 2013, 2014 by the
+ * Massachusetts Institute of Technology. All Rights Reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
@@ -376,7 +376,8 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
else
ticket_reply.server = request->server; /* XXX careful for realm... */
- enc_tkt_reply.flags = 0;
+ enc_tkt_reply.flags = OPTS2FLAGS(request->kdc_options);
+ enc_tkt_reply.flags |= COPY_TKT_FLAGS(header_enc_tkt->flags);
enc_tkt_reply.times.starttime = 0;
if (isflagset(server->attributes, KRB5_KDB_OK_AS_DELEGATE))
@@ -404,7 +405,6 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
*/
if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE)) {
- setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) {
/*
@@ -435,34 +435,21 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
}
}
- if (isflagset(request->kdc_options, KDC_OPT_FORWARDED)) {
- setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDED);
+ if (isflagset(request->kdc_options, KDC_OPT_FORWARDED) ||
+ isflagset(request->kdc_options, KDC_OPT_PROXY)) {
/* include new addresses in ticket & reply */
enc_tkt_reply.caddrs = request->addresses;
reply_encpart.caddrs = request->addresses;
}
- if (isflagset(header_enc_tkt->flags, TKT_FLG_FORWARDED))
- setflag(enc_tkt_reply.flags, TKT_FLG_FORWARDED);
-
- if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE))
- setflag(enc_tkt_reply.flags, TKT_FLG_PROXIABLE);
-
- if (isflagset(request->kdc_options, KDC_OPT_PROXY)) {
- setflag(enc_tkt_reply.flags, TKT_FLG_PROXY);
-
- /* include new addresses in ticket & reply */
-
- enc_tkt_reply.caddrs = request->addresses;
- reply_encpart.caddrs = request->addresses;
- }
-
- if (isflagset(request->kdc_options, KDC_OPT_ALLOW_POSTDATE))
- setflag(enc_tkt_reply.flags, TKT_FLG_MAY_POSTDATE);
+ /* We don't currently handle issuing anonymous tickets based on
+ * non-anonymous ones, so just ignore the option. */
+ if (isflagset(request->kdc_options, KDC_OPT_REQUEST_ANONYMOUS) &&
+ !isflagset(header_enc_tkt->flags, TKT_FLG_ANONYMOUS))
+ clear(enc_tkt_reply.flags, TKT_FLG_ANONYMOUS);
if (isflagset(request->kdc_options, KDC_OPT_POSTDATED)) {
- setflag(enc_tkt_reply.flags, TKT_FLG_POSTDATED);
setflag(enc_tkt_reply.flags, TKT_FLG_INVALID);
enc_tkt_reply.times.starttime = request->from;
} else
@@ -506,22 +493,11 @@ process_tgs_req(struct server_handle *handle, krb5_data *pkt,
kdc_get_ticket_renewtime(kdc_active_realm, request, header_enc_tkt, client,
server, &enc_tkt_reply);
- if (isflagset(header_enc_tkt->flags, TKT_FLG_ANONYMOUS))
- setflag(enc_tkt_reply.flags, TKT_FLG_ANONYMOUS);
/*
* Set authtime to be the same as header or evidence ticket's
*/
enc_tkt_reply.times.authtime = authtime;
- /*
- * Propagate the preauthentication flags through to the returned ticket.
- */
- if (isflagset(header_enc_tkt->flags, TKT_FLG_PRE_AUTH))
- setflag(enc_tkt_reply.flags, TKT_FLG_PRE_AUTH);
-
- if (isflagset(header_enc_tkt->flags, TKT_FLG_HW_AUTH))
- setflag(enc_tkt_reply.flags, TKT_FLG_HW_AUTH);
-
/* starttime is optional, and treated as authtime if not present.
so we can nuke it if it matches */
if (enc_tkt_reply.times.starttime == enc_tkt_reply.times.authtime)
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
index 6c5433361..479a13cba 100644
--- a/src/kdc/kdc_util.h
+++ b/src/kdc/kdc_util.h
@@ -2,7 +2,7 @@
/* kdc/kdc_util.h */
/*
* Portions Copyright (C) 2007 Apple Inc.
- * Copyright 1990, 2007 by the Massachusetts Institute of Technology.
+ * Copyright 1990, 2007, 2014 by the Massachusetts Institute of Technology.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
@@ -414,6 +414,72 @@ struct krb5_kdcpreauth_rock_st {
/* TGS-REQ options which are not compatible with referrals */
#define NO_REFERRAL_OPTION (NON_TGT_OPTION | KDC_OPT_ENC_TKT_IN_SKEY)
+/*
+ * Mask of KDC options that request the corresponding ticket flag with
+ * the same number. Some of these are invalid for AS-REQs, but
+ * validate_as_request() takes care of that. KDC_OPT_RENEWABLE isn't
+ * here because it needs special handling in
+ * kdc_get_ticket_renewtime().
+ *
+ * According to RFC 4120 section 3.1.3 the following AS-REQ options
+ * request their corresponding ticket flags if local policy allows:
+ *
+ * KDC_OPT_FORWARDABLE KDC_OPT_ALLOW_POSTDATE
+ * KDC_OPT_POSTDATED KDC_OPT_PROXIABLE
+ * KDC_OPT_RENEWABLE
+ *
+ * RFC 1510 section A.6 shows pseudocode indicating that the following
+ * TGS-REQ options request their corresponding ticket flags if local
+ * policy allows:
+ *
+ * KDC_OPT_FORWARDABLE KDC_OPT_FORWARDED
+ * KDC_OPT_PROXIABLE KDC_OPT_PROXY
+ * KDC_OPT_POSTDATED KDC_OPT_RENEWABLE
+ *
+ * The above list omits KDC_OPT_ALLOW_POSTDATE, but RFC 4120 section
+ * 5.4.1 says the TGS also handles it.
+ *
+ * RFC 6112 makes KDC_OPT_REQUEST_ANONYMOUS the same bit number as
+ * TKT_FLG_ANONYMOUS.
+ */
+#define OPTS_COMMON_FLAGS_MASK \
+ (KDC_OPT_FORWARDABLE | KDC_OPT_FORWARDED | \
+ KDC_OPT_PROXIABLE | KDC_OPT_PROXY | \
+ KDC_OPT_ALLOW_POSTDATE | KDC_OPT_POSTDATED | \
+ KDC_OPT_REQUEST_ANONYMOUS)
+
+/* Copy KDC options that request the corresponding ticket flags. */
+#define OPTS2FLAGS(x) (x & OPTS_COMMON_FLAGS_MASK)
+
+/*
+ * Mask of ticket flags for the TGS to propagate from a ticket to a
+ * derivative ticket.
+ *
+ * RFC 4120 section 2.1 says the following flags are carried forward
+ * from an initial ticket to derivative tickets:
+ *
+ * TKT_FLG_PRE_AUTH
+ * TKT_FLG_HW_AUTH
+ *
+ * RFC 4120 section 2.6 says TKT_FLG_FORWARDED is carried forward to
+ * derivative tickets. Proxy tickets are basically identical to
+ * forwarded tickets except that a TGT may never be proxied, therefore
+ * tickets derived from proxy tickets should have TKT_FLAG_PROXY set.
+ * RFC 4120 and RFC 1510 apparently have an accidental omission in not
+ * requiring that tickets derived from a proxy ticket have
+ * TKT_FLG_PROXY set. Previous code also omitted this behavior.
+ *
+ * RFC 6112 section 4.2 implies that TKT_FLG_ANONYMOUS must be
+ * propagated from an anonymous ticket to derivative tickets.
+ */
+#define TGS_COPIED_FLAGS_MASK \
+ (TKT_FLG_FORWARDED | TKT_FLG_PROXY | \
+ TKT_FLG_PRE_AUTH | TKT_FLG_HW_AUTH | \
+ TKT_FLG_ANONYMOUS)
+
+/* Copy appropriate header ticket flags to new ticket. */
+#define COPY_TKT_FLAGS(x) (x & TGS_COPIED_FLAGS_MASK)
+
int check_anon(kdc_realm_t *kdc_active_realm,
krb5_principal client, krb5_principal server);
int errcode_to_protocol(krb5_error_code code);