From: Greg Hudson Date: Wed, 7 Aug 2019 21:51:17 +0000 (-0400) Subject: Allow the KDB to see and modify auth indicators X-Git-Tag: krb5-1.18-beta1~72 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7196c03f18f14695abeb5ae4923004469b172f0f;p=thirdparty%2Fkrb5.git Allow the KDB to see and modify auth indicators Amend the sign_authdata method signature to include a modifiable auth_indicators array. Bump the DAL major version and the libkdb5 soname. Add a test case using the test KDB module. ticket: 8823 (new) --- diff --git a/src/include/kdb.h b/src/include/kdb.h index 86d4a64ae2..38419f69eb 100644 --- a/src/include/kdb.h +++ b/src/include/kdb.h @@ -69,7 +69,7 @@ /* This version will be incremented when incompatible changes are made to the * KDB API, and will be kept in sync with the libkdb major version. */ -#define KRB5_KDB_API_VERSION 9 +#define KRB5_KDB_API_VERSION 10 /* Salt types */ #define KRB5_KDB_SALTTYPE_NORMAL 0 @@ -670,6 +670,7 @@ krb5_error_code krb5_db_sign_authdata(krb5_context kcontext, krb5_keyblock *session_key, krb5_timestamp authtime, krb5_authdata **tgt_auth_data, + krb5_data ***auth_indicators, krb5_authdata ***signed_auth_data); krb5_error_code krb5_db_check_transited_realms(krb5_context kcontext, @@ -871,7 +872,7 @@ krb5_error_code krb5_db_register_keytab(krb5_context context); * This number indicates the date of the last incompatible change to the DAL. * The maj_ver field of the module's vtable structure must match this version. */ -#define KRB5_KDB_DAL_MAJOR_VERSION 7 +#define KRB5_KDB_DAL_MAJOR_VERSION 8 /* * A krb5_context can hold one database object. Modules should use @@ -1304,6 +1305,12 @@ typedef struct _kdb_vftabl { * * tgt_auth_data: For TGS requests, the authorization data present in the * subject ticket. For AS requests, NULL. + * + * auth_indicators: Points to NULL or a null-terminated list of krb5_data + * pointers, each containing an authentication indicator (RFC 8129). + * The method may modify this list, or free it and replace + * *auth_indicators with NULL, to change which auth indicators will be + * included in the ticket. */ krb5_error_code (*sign_authdata)(krb5_context kcontext, unsigned int flags, @@ -1317,6 +1324,7 @@ typedef struct _kdb_vftabl { krb5_keyblock *session_key, krb5_timestamp authtime, krb5_authdata **tgt_auth_data, + krb5_data ***auth_indicators, krb5_authdata ***signed_auth_data); /* @@ -1405,8 +1413,6 @@ typedef struct _kdb_vftabl { */ void (*free_principal_e_data)(krb5_context kcontext, krb5_octet *e_data); - /* End of minor version 0. */ - /* * Optional: get a principal entry for S4U2Self based on X509 certificate. * @@ -1426,7 +1432,7 @@ typedef struct _kdb_vftabl { unsigned int flags, krb5_db_entry **entry_out); - /* End of minor version 1 for major version 7. */ + /* End of minor version 0 for major version 8. */ } kdb_vftabl; #endif /* !defined(_WIN32) */ diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index a14e64fda9..894a9d4907 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -300,7 +300,7 @@ finish_process_as_req(struct as_req_state *state, krb5_error_code errcode) &state->local_tgt_key, &state->client_keyblock, &state->server_keyblock, NULL, state->req_pkt, state->request, NULL, NULL, - state->auth_indicators, &state->enc_tkt_reply); + &state->auth_indicators, &state->enc_tkt_reply); if (errcode) { krb5_klog_syslog(LOG_INFO, _("AS_REQ : handle_authdata (%d)"), errcode); diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 98f4cc6a4d..bed5630358 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -610,15 +610,10 @@ process_tgs_req(krb5_kdc_req *request, krb5_data *pkt, header_server, local_tgt, &local_tgt_key, subkey != NULL ? subkey : header_ticket->enc_part2->session, - encrypting_key, /* U2U or server key */ - header_key, - pkt, - request, + encrypting_key, header_key, pkt, request, s4u_x509_user ? s4u_x509_user->user_id.user : NULL, - subject_tkt, - auth_indicators, - &enc_tkt_reply); + subject_tkt, &auth_indicators, &enc_tkt_reply); if (errcode) { krb5_klog_syslog(LOG_INFO, _("TGS_REQ : handle_authdata (%d)"), errcode); diff --git a/src/kdc/kdc_authdata.c b/src/kdc/kdc_authdata.c index df670e837b..72e830dbb0 100644 --- a/src/kdc/kdc_authdata.c +++ b/src/kdc/kdc_authdata.c @@ -320,7 +320,8 @@ fetch_kdb_authdata(krb5_context context, unsigned int flags, krb5_keyblock *server_key, krb5_keyblock *header_key, krb5_kdc_req *req, krb5_const_principal for_user_princ, krb5_enc_tkt_part *enc_tkt_req, - krb5_enc_tkt_part *enc_tkt_reply) + krb5_enc_tkt_part *enc_tkt_reply, + krb5_data ***auth_indicators) { krb5_error_code ret; krb5_authdata **tgt_authdata, **db_authdata = NULL; @@ -379,7 +380,7 @@ fetch_kdb_authdata(krb5_context context, unsigned int flags, server, krbtgt, client_key, server_key, krbtgt_key, enc_tkt_reply->session, enc_tkt_reply->times.authtime, tgt_authdata, - &db_authdata); + auth_indicators, &db_authdata); if (ret) return (ret == KRB5_PLUGIN_OP_NOTSUPP) ? 0 : ret; @@ -824,7 +825,7 @@ handle_authdata(krb5_context context, unsigned int flags, krb5_data *req_pkt, krb5_kdc_req *req, krb5_const_principal for_user_princ, krb5_enc_tkt_part *enc_tkt_req, - krb5_data *const *auth_indicators, + krb5_data ***auth_indicators, krb5_enc_tkt_part *enc_tkt_reply) { kdcauthdata_handle *h; @@ -862,23 +863,26 @@ handle_authdata(krb5_context context, unsigned int flags, return ret; } + if (!isflagset(enc_tkt_reply->flags, TKT_FLG_ANONYMOUS)) { + /* Fetch authdata from the KDB if appropriate. */ + ret = fetch_kdb_authdata(context, flags, client, server, header_server, + client_key, server_key, header_key, req, + for_user_princ, enc_tkt_req, enc_tkt_reply, + auth_indicators); + if (ret) + return ret; + } + /* Add auth indicators if any were given. */ if (auth_indicators != NULL && *auth_indicators != NULL && !isflagset(server->attributes, KRB5_KDB_NO_AUTH_DATA_REQUIRED)) { - ret = add_auth_indicators(context, auth_indicators, server_key, + ret = add_auth_indicators(context, *auth_indicators, server_key, local_tgt, local_tgt_key, enc_tkt_reply); if (ret) return ret; } if (!isflagset(enc_tkt_reply->flags, TKT_FLG_ANONYMOUS)) { - /* Fetch authdata from the KDB if appropriate. */ - ret = fetch_kdb_authdata(context, flags, client, server, header_server, - client_key, server_key, header_key, req, - for_user_princ, enc_tkt_req, enc_tkt_reply); - if (ret) - return ret; - /* Validate and insert AD-SIGNTICKET authdata. This must happen last * since it contains a signature over the other authdata. */ ret = handle_signticket(context, flags, client, server, local_tgt, diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index f41c0d94da..8583a91aca 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -236,7 +236,7 @@ handle_authdata (krb5_context context, krb5_kdc_req *request, krb5_const_principal for_user_princ, krb5_enc_tkt_part *enc_tkt_request, - krb5_data *const *auth_indicators, + krb5_data ***auth_indicators, krb5_enc_tkt_part *enc_tkt_reply); /* replay.c */ diff --git a/src/lib/kdb/Makefile.in b/src/lib/kdb/Makefile.in index b77bf496d6..25da08105c 100644 --- a/src/lib/kdb/Makefile.in +++ b/src/lib/kdb/Makefile.in @@ -5,7 +5,7 @@ LOCALINCLUDES= -I. # Keep LIBMAJOR in sync with KRB5_KDB_API_VERSION in include/kdb.h. LIBBASE=kdb5 -LIBMAJOR=9 +LIBMAJOR=10 LIBMINOR=0 LIBINITFUNC=kdb_init_lock_list LIBFINIFUNC=kdb_fini_lock_list diff --git a/src/lib/kdb/kdb5.c b/src/lib/kdb/kdb5.c index b910bd3a7c..3058b4771e 100644 --- a/src/lib/kdb/kdb5.c +++ b/src/lib/kdb/kdb5.c @@ -323,12 +323,7 @@ copy_vtable(const kdb_vftabl *in, kdb_vftabl *out) out->refresh_config = in->refresh_config; out->check_allowed_to_delegate = in->check_allowed_to_delegate; out->free_principal_e_data = in->free_principal_e_data; - - /* Copy fields for minor version 1 (major version 7). */ - assert(KRB5_KDB_DAL_MAJOR_VERSION == 7); - out->get_s4u_x509_principal = NULL; - if (in->min_ver >= 1) - out->get_s4u_x509_principal = in->get_s4u_x509_principal; + out->get_s4u_x509_principal = in->get_s4u_x509_principal; /* Set defaults for optional fields. */ if (out->fetch_master_key == NULL) @@ -2599,6 +2594,7 @@ krb5_db_sign_authdata(krb5_context kcontext, unsigned int flags, krb5_keyblock *client_key, krb5_keyblock *server_key, krb5_keyblock *krbtgt_key, krb5_keyblock *session_key, krb5_timestamp authtime, krb5_authdata **tgt_auth_data, + krb5_data ***auth_indicators, krb5_authdata ***signed_auth_data) { krb5_error_code status = 0; @@ -2613,7 +2609,7 @@ krb5_db_sign_authdata(krb5_context kcontext, unsigned int flags, return v->sign_authdata(kcontext, flags, client_princ, client, server, krbtgt, client_key, server_key, krbtgt_key, session_key, authtime, tgt_auth_data, - signed_auth_data); + auth_indicators, signed_auth_data); } krb5_error_code diff --git a/src/plugins/kdb/test/kdb_test.c b/src/plugins/kdb/test/kdb_test.c index 690c025d8f..351bd8c9d3 100644 --- a/src/plugins/kdb/test/kdb_test.c +++ b/src/plugins/kdb/test/kdb_test.c @@ -544,9 +544,12 @@ test_sign_authdata(krb5_context context, unsigned int flags, krb5_keyblock *client_key, krb5_keyblock *server_key, krb5_keyblock *krbtgt_key, krb5_keyblock *session_key, krb5_timestamp authtime, krb5_authdata **tgt_auth_data, + krb5_data ***auth_indicators, krb5_authdata ***signed_auth_data) { krb5_authdata **list, *ad; + krb5_data **inds, d; + int i, val; ad = ealloc(sizeof(*ad)); ad->magic = KV5M_AUTHDATA; @@ -557,6 +560,24 @@ test_sign_authdata(krb5_context context, unsigned int flags, list[0] = ad; list[1] = NULL; *signed_auth_data = list; + + /* If we see an auth indicator "dbincrX", replace the whole indicator list + * with "dbincr{X+1}". */ + inds = *auth_indicators; + for (i = 0; inds != NULL && inds[i] != NULL; i++) { + if (inds[i]->length == 7 && memcmp(inds[i]->data, "dbincr", 6) == 0) { + val = inds[i]->data[6]; + k5_free_data_ptr_list(inds); + inds = ealloc(2 * sizeof(*inds)); + d = string2data("dbincr0"); + check(krb5_copy_data(context, &d, &inds[0])); + inds[0]->data[6] = val + 1; + inds[1] = NULL; + *auth_indicators = inds; + break; + } + } + return 0; } @@ -593,7 +614,7 @@ test_check_allowed_to_delegate(krb5_context context, kdb_vftabl PLUGIN_SYMBOL_NAME(krb5_test, kdb_function_table) = { KRB5_KDB_DAL_MAJOR_VERSION, /* major version number */ - 1, /* minor version number */ + 0, /* minor version number */ test_init, test_cleanup, test_open, diff --git a/src/tests/t_authdata.py b/src/tests/t_authdata.py index d98974b369..9b41bc0c10 100644 --- a/src/tests/t_authdata.py +++ b/src/tests/t_authdata.py @@ -228,6 +228,11 @@ out = realm.run(['./adata', '-p', realm.user_princ, 'service/2']) if '+97: [indcl]' not in out or '[inds1]' in out: fail('correct auth-indicator not seen for S4U2Proxy req') +# Test alteration of auth indicators by KDB module (AS and TGS). +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]') + # Test that KDB module authdata is included in an AS request, by # default or with an explicit PAC request. mark('AS-REQ KDB module authdata')