diff options
author | Tom Yu <tlyu@mit.edu> | 2014-04-24 17:10:58 -0400 |
---|---|---|
committer | Tom Yu <tlyu@mit.edu> | 2014-04-28 16:30:37 -0400 |
commit | 4d08c9abfee0b5978d9db2280c10c85b3bf2ae11 (patch) | |
tree | ec229b1afd1526f788671407d23432ed2bdf29cf | |
parent | f5645d30cf83398640c386a612eb6f07c543286f (diff) | |
download | krb5-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.c | 18 | ||||
-rw-r--r-- | src/kdc/do_tgs_req.c | 46 | ||||
-rw-r--r-- | src/kdc/kdc_util.h | 68 |
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); |