79613952e3
Also update account lockout patch to upstream version
485 lines
20 KiB
Diff
485 lines
20 KiB
Diff
From ab1435ed0654df9991bddb29971c913ef1f957be Mon Sep 17 00:00:00 2001
|
|
From: Greg Hudson <ghudson@mit.edu>
|
|
Date: Thu, 15 Nov 2018 13:40:43 -0500
|
|
Subject: [PATCH] Clear forwardable flag instead of denying request
|
|
|
|
If the client requests a forwardable or proxiable ticket and the
|
|
option cannot be honored by policy, issue a non-forwardable or
|
|
non-proxiable ticket rather than denying the request.
|
|
|
|
Add a test script for testing KDC request options and populate it with
|
|
tests for the forwardable and proxiable flags.
|
|
|
|
ticket: 7871
|
|
(cherry picked from commit 08e948cce2c79a3604066fcf7a64fc527456f83d)
|
|
---
|
|
src/kdc/do_as_req.c | 19 ++------
|
|
src/kdc/do_tgs_req.c | 56 ++++-----------------
|
|
src/kdc/kdc_util.c | 82 ++++++++++++++++++-------------
|
|
src/kdc/kdc_util.h | 9 ++--
|
|
src/kdc/tgs_policy.c | 8 +--
|
|
src/tests/Makefile.in | 1 +
|
|
src/tests/gcred.c | 28 ++++++++---
|
|
src/tests/t_kdcoptions.py | 100 ++++++++++++++++++++++++++++++++++++++
|
|
8 files changed, 189 insertions(+), 114 deletions(-)
|
|
create mode 100644 src/tests/t_kdcoptions.py
|
|
|
|
diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c
|
|
index 588c1375a..8a96c12a9 100644
|
|
--- a/src/kdc/do_as_req.c
|
|
+++ b/src/kdc/do_as_req.c
|
|
@@ -192,13 +192,6 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
|
|
|
|
au_state->stage = ENCR_REP;
|
|
|
|
- if ((errcode = validate_forwardable(state->request, *state->client,
|
|
- *state->server, state->kdc_time,
|
|
- &state->status))) {
|
|
- errcode += ERROR_TABLE_BASE_krb5;
|
|
- goto egress;
|
|
- }
|
|
-
|
|
errcode = check_indicators(kdc_context, state->server,
|
|
state->auth_indicators);
|
|
if (errcode) {
|
|
@@ -708,12 +701,11 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
|
|
}
|
|
|
|
/* Copy options that request the corresponding ticket flags. */
|
|
- state->enc_tkt_reply.flags = OPTS2FLAGS(state->request->kdc_options);
|
|
+ state->enc_tkt_reply.flags = get_ticket_flags(state->request->kdc_options,
|
|
+ state->client, state->server,
|
|
+ NULL);
|
|
state->enc_tkt_reply.times.authtime = state->authtime;
|
|
|
|
- setflag(state->enc_tkt_reply.flags, TKT_FLG_INITIAL);
|
|
- setflag(state->enc_tkt_reply.flags, TKT_FLG_ENC_PA_REP);
|
|
-
|
|
/*
|
|
* It should be noted that local policy may affect the
|
|
* processing of any of these flags. For example, some
|
|
@@ -732,10 +724,9 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt,
|
|
state->enc_tkt_reply.transited.tr_type = KRB5_DOMAIN_X500_COMPRESS;
|
|
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_INVALID);
|
|
+ if (isflagset(state->request->kdc_options, KDC_OPT_POSTDATED))
|
|
state->enc_tkt_reply.times.starttime = state->request->from;
|
|
- } else
|
|
+ else
|
|
state->enc_tkt_reply.times.starttime = state->kdc_time;
|
|
|
|
kdc_get_ticket_endtime(kdc_active_realm,
|
|
diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c
|
|
index 587342a6c..1da099318 100644
|
|
--- a/src/kdc/do_tgs_req.c
|
|
+++ b/src/kdc/do_tgs_req.c
|
|
@@ -378,15 +378,16 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
|
|
else
|
|
ticket_reply.server = request->server; /* XXX careful for realm... */
|
|
|
|
- enc_tkt_reply.flags = OPTS2FLAGS(request->kdc_options);
|
|
- enc_tkt_reply.flags |= COPY_TKT_FLAGS(header_enc_tkt->flags);
|
|
+ enc_tkt_reply.flags = get_ticket_flags(request->kdc_options, client,
|
|
+ server, header_enc_tkt);
|
|
enc_tkt_reply.times.starttime = 0;
|
|
|
|
- if (isflagset(server->attributes, KRB5_KDB_OK_AS_DELEGATE))
|
|
- setflag(enc_tkt_reply.flags, TKT_FLG_OK_AS_DELEGATE);
|
|
-
|
|
- /* Indicate support for encrypted padata (RFC 6806). */
|
|
- setflag(enc_tkt_reply.flags, TKT_FLG_ENC_PA_REP);
|
|
+ /* OK_TO_AUTH_AS_DELEGATE must be set on the service requesting S4U2Self
|
|
+ * for forwardable tickets to be issued. */
|
|
+ if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) &&
|
|
+ !is_referral &&
|
|
+ !isflagset(server->attributes, KRB5_KDB_OK_TO_AUTH_AS_DELEGATE))
|
|
+ clear(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
|
|
|
|
/* don't use new addresses unless forwarded, see below */
|
|
|
|
@@ -401,37 +402,6 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
|
|
* realms may refuse to issue renewable tickets
|
|
*/
|
|
|
|
- if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE)) {
|
|
-
|
|
- if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) {
|
|
- /*
|
|
- * If S4U2Self principal is not forwardable, then mark ticket as
|
|
- * unforwardable. This behaviour matches Windows, but it is
|
|
- * different to the MIT AS-REQ path, which returns an error
|
|
- * (KDC_ERR_POLICY) if forwardable tickets cannot be issued.
|
|
- *
|
|
- * Consider this block the S4U2Self equivalent to
|
|
- * validate_forwardable().
|
|
- */
|
|
- if (client != NULL &&
|
|
- isflagset(client->attributes, KRB5_KDB_DISALLOW_FORWARDABLE))
|
|
- clear(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
|
|
- /*
|
|
- * Forwardable flag is propagated along referral path.
|
|
- */
|
|
- else if (!isflagset(header_enc_tkt->flags, TKT_FLG_FORWARDABLE))
|
|
- clear(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
|
|
- /*
|
|
- * OK_TO_AUTH_AS_DELEGATE must be set on the service requesting
|
|
- * S4U2Self in order for forwardable tickets to be returned.
|
|
- */
|
|
- else if (!is_referral &&
|
|
- !isflagset(server->attributes,
|
|
- KRB5_KDB_OK_TO_AUTH_AS_DELEGATE))
|
|
- clear(enc_tkt_reply.flags, TKT_FLG_FORWARDABLE);
|
|
- }
|
|
- }
|
|
-
|
|
if (isflagset(request->kdc_options, KDC_OPT_FORWARDED) ||
|
|
isflagset(request->kdc_options, KDC_OPT_PROXY)) {
|
|
|
|
@@ -440,16 +410,10 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt,
|
|
enc_tkt_reply.caddrs = request->addresses;
|
|
reply_encpart.caddrs = request->addresses;
|
|
}
|
|
- /* 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_INVALID);
|
|
+ if (isflagset(request->kdc_options, KDC_OPT_POSTDATED))
|
|
enc_tkt_reply.times.starttime = request->from;
|
|
- } else
|
|
+ else
|
|
enc_tkt_reply.times.starttime = kdc_time;
|
|
|
|
if (isflagset(request->kdc_options, KDC_OPT_VALIDATE)) {
|
|
diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c
|
|
index 96c88edc1..f2741090e 100644
|
|
--- a/src/kdc/kdc_util.c
|
|
+++ b/src/kdc/kdc_util.c
|
|
@@ -697,29 +697,6 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
|
|
return(KDC_ERR_CANNOT_POSTDATE);
|
|
}
|
|
|
|
- /*
|
|
- * A Windows KDC will return KDC_ERR_PREAUTH_REQUIRED instead of
|
|
- * KDC_ERR_POLICY in the following case:
|
|
- *
|
|
- * - KDC_OPT_FORWARDABLE is set in KDCOptions but local
|
|
- * policy has KRB5_KDB_DISALLOW_FORWARDABLE set for the
|
|
- * client, and;
|
|
- * - KRB5_KDB_REQUIRES_PRE_AUTH is set for the client but
|
|
- * preauthentication data is absent in the request.
|
|
- *
|
|
- * Hence, this check most be done after the check for preauth
|
|
- * data, and is now performed by validate_forwardable() (the
|
|
- * contents of which were previously below).
|
|
- */
|
|
-
|
|
- /* Client and server must allow proxiable tickets */
|
|
- if (isflagset(request->kdc_options, KDC_OPT_PROXIABLE) &&
|
|
- (isflagset(client.attributes, KRB5_KDB_DISALLOW_PROXIABLE) ||
|
|
- isflagset(server.attributes, KRB5_KDB_DISALLOW_PROXIABLE))) {
|
|
- *status = "PROXIABLE NOT ALLOWED";
|
|
- return(KDC_ERR_POLICY);
|
|
- }
|
|
-
|
|
/* Check to see if client is locked out */
|
|
if (isflagset(client.attributes, KRB5_KDB_DISALLOW_ALL_TIX)) {
|
|
*status = "CLIENT LOCKED OUT";
|
|
@@ -752,19 +729,54 @@ validate_as_request(kdc_realm_t *kdc_active_realm,
|
|
return 0;
|
|
}
|
|
|
|
-int
|
|
-validate_forwardable(krb5_kdc_req *request, krb5_db_entry client,
|
|
- krb5_db_entry server, krb5_timestamp kdc_time,
|
|
- const char **status)
|
|
+/*
|
|
+ * Compute ticket flags based on the request, the client and server DB entry
|
|
+ * (which may prohibit forwardable or proxiable tickets), and the header
|
|
+ * ticket. client may be NULL for a TGS request (although it may be set, such
|
|
+ * as for an S4U2Self request). header_enc may be NULL for an AS request.
|
|
+ */
|
|
+krb5_flags
|
|
+get_ticket_flags(krb5_flags reqflags, krb5_db_entry *client,
|
|
+ krb5_db_entry *server, krb5_enc_tkt_part *header_enc)
|
|
{
|
|
- *status = NULL;
|
|
- if (isflagset(request->kdc_options, KDC_OPT_FORWARDABLE) &&
|
|
- (isflagset(client.attributes, KRB5_KDB_DISALLOW_FORWARDABLE) ||
|
|
- isflagset(server.attributes, KRB5_KDB_DISALLOW_FORWARDABLE))) {
|
|
- *status = "FORWARDABLE NOT ALLOWED";
|
|
- return(KDC_ERR_POLICY);
|
|
- } else
|
|
- return 0;
|
|
+ krb5_flags flags;
|
|
+
|
|
+ /* Indicate support for encrypted padata (RFC 6806), and set flags based on
|
|
+ * request options and the header ticket. */
|
|
+ flags = OPTS2FLAGS(reqflags) | TKT_FLG_ENC_PA_REP;
|
|
+ if (reqflags & KDC_OPT_POSTDATED)
|
|
+ flags |= TKT_FLG_INVALID;
|
|
+ if (header_enc != NULL)
|
|
+ flags |= COPY_TKT_FLAGS(header_enc->flags);
|
|
+ if (header_enc == NULL)
|
|
+ flags |= TKT_FLG_INITIAL;
|
|
+
|
|
+ /* For TGS requests, indicate if the service is marked ok-as-delegate. */
|
|
+ if (header_enc != NULL && (server->attributes & KRB5_KDB_OK_AS_DELEGATE))
|
|
+ flags |= TKT_FLG_OK_AS_DELEGATE;
|
|
+
|
|
+ /* Unset PROXIABLE if it is disallowed. */
|
|
+ if (client != NULL && (client->attributes & KRB5_KDB_DISALLOW_PROXIABLE))
|
|
+ flags &= ~TKT_FLG_PROXIABLE;
|
|
+ if (server->attributes & KRB5_KDB_DISALLOW_PROXIABLE)
|
|
+ flags &= ~TKT_FLG_PROXIABLE;
|
|
+ if (header_enc != NULL && !(header_enc->flags & TKT_FLG_PROXIABLE))
|
|
+ flags &= ~TKT_FLG_PROXIABLE;
|
|
+
|
|
+ /* Unset FORWARDABLE if it is disallowed. */
|
|
+ if (client != NULL && (client->attributes & KRB5_KDB_DISALLOW_FORWARDABLE))
|
|
+ flags &= ~TKT_FLG_FORWARDABLE;
|
|
+ if (server->attributes & KRB5_KDB_DISALLOW_FORWARDABLE)
|
|
+ flags &= ~TKT_FLG_FORWARDABLE;
|
|
+ if (header_enc != NULL && !(header_enc->flags & TKT_FLG_FORWARDABLE))
|
|
+ flags &= ~TKT_FLG_FORWARDABLE;
|
|
+
|
|
+ /* We don't currently handle issuing anonymous tickets based on
|
|
+ * non-anonymous ones. */
|
|
+ if (header_enc != NULL && !(header_enc->flags & TKT_FLG_ANONYMOUS))
|
|
+ flags &= ~TKT_FLG_ANONYMOUS;
|
|
+
|
|
+ return flags;
|
|
}
|
|
|
|
/* Return KRB5KDC_ERR_POLICY if indicators does not contain the required auth
|
|
diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h
|
|
index 25077cbf5..1314bdd58 100644
|
|
--- a/src/kdc/kdc_util.h
|
|
+++ b/src/kdc/kdc_util.h
|
|
@@ -85,16 +85,15 @@ validate_as_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry,
|
|
krb5_db_entry, krb5_timestamp,
|
|
const char **, krb5_pa_data ***);
|
|
|
|
-int
|
|
-validate_forwardable(krb5_kdc_req *, krb5_db_entry,
|
|
- krb5_db_entry, krb5_timestamp,
|
|
- const char **);
|
|
-
|
|
int
|
|
validate_tgs_request (kdc_realm_t *, krb5_kdc_req *, krb5_db_entry,
|
|
krb5_ticket *, krb5_timestamp,
|
|
const char **, krb5_pa_data ***);
|
|
|
|
+krb5_flags
|
|
+get_ticket_flags(krb5_flags reqflags, krb5_db_entry *client,
|
|
+ krb5_db_entry *server, krb5_enc_tkt_part *header_enc);
|
|
+
|
|
krb5_error_code
|
|
check_indicators(krb5_context context, krb5_db_entry *server,
|
|
krb5_data *const *indicators);
|
|
diff --git a/src/kdc/tgs_policy.c b/src/kdc/tgs_policy.c
|
|
index 907fcd330..554345ba5 100644
|
|
--- a/src/kdc/tgs_policy.c
|
|
+++ b/src/kdc/tgs_policy.c
|
|
@@ -63,9 +63,9 @@ static check_tgs_svc_pol_fn * const svc_pol_fns[] = {
|
|
};
|
|
|
|
static const struct tgsflagrule tgsflagrules[] = {
|
|
- { (KDC_OPT_FORWARDED | KDC_OPT_FORWARDABLE), TKT_FLG_FORWARDABLE,
|
|
+ { KDC_OPT_FORWARDED, TKT_FLG_FORWARDABLE,
|
|
"TGT NOT FORWARDABLE", KDC_ERR_BADOPTION },
|
|
- { (KDC_OPT_PROXY | KDC_OPT_PROXIABLE), TKT_FLG_PROXIABLE,
|
|
+ { KDC_OPT_PROXY, TKT_FLG_PROXIABLE,
|
|
"TGT NOT PROXIABLE", KDC_ERR_BADOPTION },
|
|
{ (KDC_OPT_ALLOW_POSTDATE | KDC_OPT_POSTDATED), TKT_FLG_MAY_POSTDATE,
|
|
"TGT NOT POSTDATABLE", KDC_ERR_BADOPTION },
|
|
@@ -98,12 +98,8 @@ check_tgs_opts(krb5_kdc_req *req, krb5_ticket *tkt, const char **status)
|
|
}
|
|
|
|
static const struct tgsflagrule svcdenyrules[] = {
|
|
- { KDC_OPT_FORWARDABLE, KRB5_KDB_DISALLOW_FORWARDABLE,
|
|
- "NON-FORWARDABLE TICKET", KDC_ERR_POLICY },
|
|
{ KDC_OPT_RENEWABLE, KRB5_KDB_DISALLOW_RENEWABLE,
|
|
"NON-RENEWABLE TICKET", KDC_ERR_POLICY },
|
|
- { KDC_OPT_PROXIABLE, KRB5_KDB_DISALLOW_PROXIABLE,
|
|
- "NON-PROXIABLE TICKET", KDC_ERR_POLICY },
|
|
{ KDC_OPT_ALLOW_POSTDATE, KRB5_KDB_DISALLOW_POSTDATED,
|
|
"NON-POSTDATABLE TICKET", KDC_ERR_CANNOT_POSTDATE },
|
|
{ KDC_OPT_ENC_TKT_IN_SKEY, KRB5_KDB_DISALLOW_DUP_SKEY,
|
|
diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in
|
|
index c96c5d6b7..d2a37c616 100644
|
|
--- a/src/tests/Makefile.in
|
|
+++ b/src/tests/Makefile.in
|
|
@@ -171,6 +171,7 @@ check-pytests: unlockiter
|
|
$(RUNPYTEST) $(srcdir)/t_y2038.py $(PYTESTFLAGS)
|
|
$(RUNPYTEST) $(srcdir)/t_kdcpolicy.py $(PYTESTFLAGS)
|
|
$(RUNPYTEST) $(srcdir)/t_u2u.py $(PYTESTFLAGS)
|
|
+ $(RUNPYTEST) $(srcdir)/t_kdcoptions.py $(PYTESTFLAGS)
|
|
|
|
clean:
|
|
$(RM) adata etinfo forward gcred hist hooks hrealm icinterleave icred
|
|
diff --git a/src/tests/gcred.c b/src/tests/gcred.c
|
|
index cb0ae6af5..b14e4fc9a 100644
|
|
--- a/src/tests/gcred.c
|
|
+++ b/src/tests/gcred.c
|
|
@@ -66,20 +66,32 @@ main(int argc, char **argv)
|
|
krb5_principal client, server;
|
|
krb5_ccache ccache;
|
|
krb5_creds in_creds, *creds;
|
|
+ krb5_flags options = 0;
|
|
char *name;
|
|
+ int c;
|
|
|
|
check(krb5_init_context(&ctx));
|
|
|
|
- /* Parse arguments. */
|
|
- assert(argc == 3);
|
|
- check(krb5_parse_name(ctx, argv[2], &server));
|
|
- if (strcmp(argv[1], "unknown") == 0)
|
|
+ while ((c = getopt(argc, argv, "f")) != -1) {
|
|
+ switch (c) {
|
|
+ case 'f':
|
|
+ options |= KRB5_GC_FORWARDABLE;
|
|
+ break;
|
|
+ default:
|
|
+ abort();
|
|
+ }
|
|
+ }
|
|
+ argc -= optind;
|
|
+ argv += optind;
|
|
+ assert(argc == 2);
|
|
+ check(krb5_parse_name(ctx, argv[1], &server));
|
|
+ if (strcmp(argv[0], "unknown") == 0)
|
|
server->type = KRB5_NT_UNKNOWN;
|
|
- else if (strcmp(argv[1], "principal") == 0)
|
|
+ else if (strcmp(argv[0], "principal") == 0)
|
|
server->type = KRB5_NT_PRINCIPAL;
|
|
- else if (strcmp(argv[1], "srv-inst") == 0)
|
|
+ else if (strcmp(argv[0], "srv-inst") == 0)
|
|
server->type = KRB5_NT_SRV_INST;
|
|
- else if (strcmp(argv[1], "srv-hst") == 0)
|
|
+ else if (strcmp(argv[0], "srv-hst") == 0)
|
|
server->type = KRB5_NT_SRV_HST;
|
|
else
|
|
abort();
|
|
@@ -89,7 +101,7 @@ main(int argc, char **argv)
|
|
memset(&in_creds, 0, sizeof(in_creds));
|
|
in_creds.client = client;
|
|
in_creds.server = server;
|
|
- check(krb5_get_credentials(ctx, 0, ccache, &in_creds, &creds));
|
|
+ check(krb5_get_credentials(ctx, options, ccache, &in_creds, &creds));
|
|
check(krb5_unparse_name(ctx, creds->server, &name));
|
|
printf("%s\n", name);
|
|
|
|
diff --git a/src/tests/t_kdcoptions.py b/src/tests/t_kdcoptions.py
|
|
new file mode 100644
|
|
index 000000000..7ec57508c
|
|
--- /dev/null
|
|
+++ b/src/tests/t_kdcoptions.py
|
|
@@ -0,0 +1,100 @@
|
|
+from k5test import *
|
|
+import re
|
|
+
|
|
+# KDC option test coverage notes:
|
|
+#
|
|
+# FORWARDABLE here
|
|
+# FORWARDED no test
|
|
+# PROXIABLE here
|
|
+# PROXY no test
|
|
+# ALLOW_POSTDATE no test
|
|
+# POSTDATED no test
|
|
+# RENEWABLE t_renew.py
|
|
+# CNAME_IN_ADDL_TKT gssapi/t_s4u.py
|
|
+# CANONICALIZE t_kdb.py and various other tests
|
|
+# REQUEST_ANONYMOUS t_pkinit.py
|
|
+# DISABLE_TRANSITED_CHECK no test
|
|
+# RENEWABLE_OK t_renew.py
|
|
+# ENC_TKT_IN_SKEY t_u2u.py
|
|
+# RENEW t_renew.py
|
|
+# VALIDATE no test
|
|
+
|
|
+# Run klist -f and return the flags on the ticket for svcprinc.
|
|
+def get_flags(realm, svcprinc):
|
|
+ grab_flags = False
|
|
+ for line in realm.run([klist, '-f']).splitlines():
|
|
+ if grab_flags:
|
|
+ return re.findall(r'Flags: ([a-zA-Z]*)', line)[0]
|
|
+ grab_flags = line.endswith(svcprinc)
|
|
+
|
|
+
|
|
+# Get the flags on the ticket for svcprinc, and check for an expected
|
|
+# element and an expected-absent element, either of which can be None.
|
|
+def check_flags(realm, svcprinc, expected_flag, expected_noflag):
|
|
+ flags = get_flags(realm, svcprinc)
|
|
+ if expected_flag is not None and not expected_flag in flags:
|
|
+ fail('expected flag ' + expected_flag)
|
|
+ if expected_noflag is not None and expected_noflag in flags:
|
|
+ fail('did not expect flag ' + expected_noflag)
|
|
+
|
|
+
|
|
+# Run kinit with the given flags, and check the flags on the resulting
|
|
+# TGT.
|
|
+def kinit_check_flags(realm, flags, expected_flag, expected_noflag):
|
|
+ realm.kinit(realm.user_princ, password('user'), flags)
|
|
+ check_flags(realm, realm.krbtgt_princ, expected_flag, expected_noflag)
|
|
+
|
|
+
|
|
+# Run kinit with kflags. Then get credentials for the host principal
|
|
+# with gflags, and check the flags on the resulting ticket.
|
|
+def gcred_check_flags(realm, kflags, gflags, expected_flag, expected_noflag):
|
|
+ realm.kinit(realm.user_princ, password('user'), kflags)
|
|
+ realm.run(['./gcred'] + gflags + ['unknown', realm.host_princ])
|
|
+ check_flags(realm, realm.host_princ, expected_flag, expected_noflag)
|
|
+
|
|
+
|
|
+realm = K5Realm()
|
|
+
|
|
+mark('proxiable (AS)')
|
|
+kinit_check_flags(realm, [], None, 'P')
|
|
+kinit_check_flags(realm, ['-p'], 'P', None)
|
|
+realm.run([kadminl, 'modprinc', '-allow_proxiable', realm.user_princ])
|
|
+kinit_check_flags(realm, ['-p'], None, 'P')
|
|
+realm.run([kadminl, 'modprinc', '+allow_proxiable', realm.user_princ])
|
|
+realm.run([kadminl, 'modprinc', '-allow_proxiable', realm.krbtgt_princ])
|
|
+kinit_check_flags(realm, ['-p'], None, 'P')
|
|
+realm.run([kadminl, 'modprinc', '+allow_proxiable', realm.krbtgt_princ])
|
|
+
|
|
+mark('proxiable (TGS)')
|
|
+gcred_check_flags(realm, [], [], None, 'P')
|
|
+gcred_check_flags(realm, ['-p'], [], 'P', None)
|
|
+
|
|
+# Not tested: PROXIABLE option set with a non-proxiable TGT (because
|
|
+# there is no krb5_get_credentials() flag to request this; would
|
|
+# expect a non-proxiable ticket).
|
|
+
|
|
+# Not tested: proxiable TGT but PROXIABLE flag not set (because we
|
|
+# internally set the PROXIABLE option when using a proxiable TGT;
|
|
+# would expect a non-proxiable ticket).
|
|
+
|
|
+mark('forwardable (AS)')
|
|
+kinit_check_flags(realm, [], None, 'F')
|
|
+kinit_check_flags(realm, ['-f'], 'F', None)
|
|
+realm.run([kadminl, 'modprinc', '-allow_forwardable', realm.user_princ])
|
|
+kinit_check_flags(realm, ['-f'], None, 'F')
|
|
+realm.run([kadminl, 'modprinc', '+allow_forwardable', realm.user_princ])
|
|
+realm.run([kadminl, 'modprinc', '-allow_forwardable', realm.krbtgt_princ])
|
|
+kinit_check_flags(realm, ['-f'], None, 'F')
|
|
+realm.run([kadminl, 'modprinc', '+allow_forwardable', realm.krbtgt_princ])
|
|
+
|
|
+mark('forwardable (TGS)')
|
|
+realm.kinit(realm.user_princ, password('user'))
|
|
+gcred_check_flags(realm, [], [], None, 'F')
|
|
+gcred_check_flags(realm, [], ['-f'], None, 'F')
|
|
+gcred_check_flags(realm, ['-f'], [], 'F', None)
|
|
+
|
|
+# Not tested: forwardable TGT but FORWARDABLE flag not set (because we
|
|
+# internally set the FORWARDABLE option when using a forwardable TGT;
|
|
+# would expect a non-proxiable ticket).
|
|
+
|
|
+success('KDC option tests')
|