Skip to content

Commit

Permalink
Fix AS-REQ checking of KDB-modified indicators
Browse files Browse the repository at this point in the history
Commit 7196c03 (ticket 8823) gave the
KDB the ability to modify auth indicators, but it happens after the
asserted indicators are checked against the server principal
requirements.  In finish_process_as_req(), move the call to
check_indicators() after the call to handle_authdata() so that the
final indicator list is checked.

For the test case, add string attribute functionality to the test KDB
module, and fix a bug where test_get_principal() would return failure
if a principal has no keys.  Also add a test case for AS-REQ
enforcement of normally asserted auth indicators.

ticket: 8876 (new)
tags: pullup
target_version: 1.18-next
  • Loading branch information
greghudson committed Feb 21, 2020
1 parent 033fa6e commit 109e30c
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
14 changes: 7 additions & 7 deletions src/kdc/do_as_req.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,13 +211,6 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)

au_state->stage = ENCR_REP;

errcode = check_indicators(kdc_context, state->server,
state->auth_indicators);
if (errcode) {
state->status = "HIGHER_AUTHENTICATION_REQUIRED";
goto egress;
}

state->ticket_reply.enc_part2 = &state->enc_tkt_reply;

errcode = check_kdcpolicy_as(kdc_context, state->request, state->client,
Expand Down Expand Up @@ -301,6 +294,13 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode)
goto egress;
}

errcode = check_indicators(kdc_context, state->server,
state->auth_indicators);
if (errcode) {
state->status = "HIGHER_AUTHENTICATION_REQUIRED";
goto egress;
}

errcode = krb5_encrypt_tkt_part(kdc_context, &state->server_keyblock,
&state->ticket_reply);
if (errcode)
Expand Down
42 changes: 40 additions & 2 deletions src/plugins/kdb/test/kdb_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
* # Initial number is kvno; defaults to 1.
* keys = 3 aes256-cts aes128-cts:normal
* keys = 2 rc4-hmac
* strings = key1:value1
* strings = key2:value2
* }
* }
* delegation = {
Expand Down Expand Up @@ -282,6 +284,33 @@ make_keys(char **strings, const char *princstr, const krb5_data *realm,
ent->n_key_data = nkeys;
}

static void
make_strings(char **stringattrs, krb5_db_entry *ent)
{
struct k5buf buf;
char **p;
const char *str, *sep;
krb5_tl_data *tl;

k5_buf_init_dynamic(&buf);
for (p = stringattrs; *p != NULL; p++) {
str = *p;
sep = strchr(str, ':');
assert(sep != NULL);
k5_buf_add_len(&buf, str, sep - str);
k5_buf_add_len(&buf, "\0", 1);
k5_buf_add_len(&buf, sep + 1, strlen(sep + 1) + 1);
}
assert(buf.data != NULL);

tl = ealloc(sizeof(*ent->tl_data));
tl->tl_data_next = NULL;
tl->tl_data_type = KRB5_TL_STRING_ATTRS;
tl->tl_data_length = buf.len;
tl->tl_data_contents = buf.data;
ent->tl_data = tl;
}

static krb5_error_code
test_init()
{
Expand Down Expand Up @@ -360,7 +389,8 @@ test_get_principal(krb5_context context, krb5_const_principal search_for,
krb5_principal princ = NULL, tgtprinc;
krb5_principal_data empty_princ = { KV5M_PRINCIPAL };
testhandle h = context->dal_handle->db_context;
char *search_name = NULL, *canon = NULL, *flagstr, **names, **key_strings;
char *search_name = NULL, *canon = NULL, *flagstr;
char **names, **key_strings, **stringattrs;
const char *ename;
krb5_db_entry *ent;

Expand Down Expand Up @@ -439,7 +469,7 @@ test_get_principal(krb5_context context, krb5_const_principal search_for,
ent->pw_expiration = get_time(h, "princs", ename, "pwexpiration");

/* Leave last_success, last_failed, fail_auth_count zeroed. */
/* Leave tl_data and e_data empty. */
/* Leave e_data empty. */

set_names(h, "princs", ename, "keys");
ret = profile_get_values(h->profile, h->names, &key_strings);
Expand All @@ -448,11 +478,19 @@ test_get_principal(krb5_context context, krb5_const_principal search_for,
profile_free_list(key_strings);
}

set_names(h, "princs", ename, "strings");
ret = profile_get_values(h->profile, h->names, &stringattrs);
if (ret != PROF_NO_RELATION) {
make_strings(stringattrs, ent);
profile_free_list(stringattrs);
}

/* We must include mod-princ data or kadm5_get_principal() won't work and
* we can't extract keys with kadmin.local. */
check(krb5_dbe_update_mod_princ_data(context, ent, 0, &empty_princ));

*entry = ent;
ret = 0;

cleanup:
krb5_free_unparsed_name(context, search_name);
Expand Down
11 changes: 11 additions & 0 deletions src/tests/t_authdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@
mark('auth indicator enforcement')
realm.addprinc('restricted')
realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'superstrong'])
realm.kinit(realm.user_princ, password('user'), ['-S', 'restricted'],
expected_code=1, expected_msg='KDC policy rejects request')
realm.run([kvno, 'restricted'], expected_code=1,
expected_msg='KDC policy rejects request')
realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'indcl'])
Expand Down Expand Up @@ -194,6 +196,8 @@
'krbtgt/FOREIGN': {'keys': 'aes128-cts'},
'user': {'keys': 'aes128-cts', 'flags': '+preauth'},
'user2': {'keys': 'aes128-cts', 'flags': '+preauth'},
'rservice': {'keys': 'aes128-cts',
'strings': 'require_auth:strong'},
'service/1': {'keys': 'aes128-cts',
'flags': '+ok_to_auth_as_delegate'},
'service/2': {'keys': 'aes128-cts'},
Expand All @@ -208,6 +212,7 @@
realm.extract_keytab(realm.krbtgt_princ, realm.keytab)
realm.extract_keytab('krbtgt/FOREIGN', realm.keytab)
realm.extract_keytab(realm.user_princ, realm.keytab)
realm.extract_keytab('ruser', realm.keytab)
realm.extract_keytab('service/1', realm.keytab)
realm.extract_keytab('service/2', realm.keytab)
realm.extract_keytab('noauthdata', realm.keytab)
Expand Down Expand Up @@ -252,6 +257,12 @@
realm.kinit(realm.user_princ, None, ['-k', '-X', 'indicators=dummy dbincr1'])
realm.run(['./adata', realm.krbtgt_princ], expected_msg='+97: [dbincr2]')
realm.run(['./adata', 'service/1'], expected_msg='+97: [dbincr3]')
realm.kinit(realm.user_princ, None,
['-k', '-X', 'indicators=strong', '-S', 'rservice'])
# Test enforcement of altered indicators during AS request.
realm.kinit(realm.user_princ, None,
['-k', '-X', 'indicators=strong dbincr1', '-S', 'rservice'],
expected_code=1)

# Test that KDB module authdata is included in an AS request, by
# default or with an explicit PAC request.
Expand Down

0 comments on commit 109e30c

Please sign in to comment.