diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/include/krb5/krb5.hin | 2 | ||||
-rw-r--r-- | src/lib/gssapi/krb5/init_sec_context.c | 11 | ||||
-rw-r--r-- | src/lib/krb5/krb/mk_req_ext.c | 21 | ||||
-rw-r--r-- | src/tests/gssapi/t_bindings.c | 31 | ||||
-rw-r--r-- | src/tests/gssapi/t_bindings.py | 18 |
5 files changed, 62 insertions, 21 deletions
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin index 4e09ed3..7496383 100644 --- a/src/include/krb5/krb5.hin +++ b/src/include/krb5/krb5.hin @@ -1658,6 +1658,7 @@ krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype, #define AP_OPTS_USE_SESSION_KEY 0x40000000 /**< Use session key */ #define AP_OPTS_MUTUAL_REQUIRED 0x20000000 /**< Perform a mutual authentication exchange */ +#define AP_OPTS_CBT_FLAG 0x00000004 /* include KERB_AP_OPTIONS_CBT */ #define AP_OPTS_ETYPE_NEGOTIATION 0x00000002 #define AP_OPTS_USE_SUBKEY 0x00000001 /**< Generate a subsession key from the current session key @@ -1689,7 +1690,6 @@ krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype, /* #define AP_OPTS_RESERVED 0x00000020 */ /* #define AP_OPTS_RESERVED 0x00000010 */ /* #define AP_OPTS_RESERVED 0x00000008 */ -/* #define AP_OPTS_RESERVED 0x00000004 */ #define AP_OPTS_WIRE_MASK 0xfffffff0 diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c index 0397fe1..3cc9d4c 100644 --- a/src/lib/gssapi/krb5/init_sec_context.c +++ b/src/lib/gssapi/krb5/init_sec_context.c @@ -365,7 +365,7 @@ make_ap_req_v1(krb5_context context, krb5_gss_ctx_id_rec *ctx, krb5_gss_cred_id_t cred, krb5_creds *k_cred, krb5_authdata_context ad_context, gss_channel_bindings_t chan_bindings, gss_OID mech_type, - gss_buffer_t token, krb5_gss_ctx_ext_t exts) + int cbt_flag, gss_buffer_t token, krb5_gss_ctx_ext_t exts) { krb5_flags mk_req_flags = 0; krb5_error_code code; @@ -400,6 +400,8 @@ make_ap_req_v1(krb5_context context, krb5_gss_ctx_id_rec *ctx, if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_ETYPE_NEGOTIATION; + if (cbt_flag) + mk_req_flags |= AP_OPTS_CBT_FLAG; krb5_auth_con_set_authdata_context(context, ctx->auth_context, ad_context); code = krb5_mk_req_extended(context, &ctx->auth_context, mk_req_flags, @@ -481,6 +483,7 @@ kg_new_connection( krb5_timestamp now; gss_buffer_desc token; krb5_keyblock *keyblock; + int cbt_flag = (req_flags & GSS_C_CHANNEL_BOUND_FLAG) != 0; k5_mutex_assert_locked(&cred->lock); major_status = GSS_S_FAILURE; @@ -538,6 +541,8 @@ kg_new_connection( req_flags |= GSS_C_DELEG_POLICY_FLAG; } + /* Don't include GSS_C_CHANNEL_BOUND_FLAG here; we don't want to put it on + * the wire, and we only need to know about it for the first token. */ ctx->gss_flags = req_flags & (GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG | @@ -595,8 +600,8 @@ kg_new_connection( krb5_int32 seq_temp; if ((code = make_ap_req_v1(context, ctx, cred, k_cred, ctx->here->ad_context, - input_chan_bindings, - mech_type, &token, exts))) { + input_chan_bindings, mech_type, cbt_flag, + &token, exts))) { if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) || (code == KG_EMPTY_CCACHE)) major_status = GSS_S_NO_CRED; diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c index 0850486..3eae2e7 100644 --- a/src/lib/krb5/krb/mk_req_ext.c +++ b/src/lib/krb5/krb/mk_req_ext.c @@ -78,7 +78,7 @@ generate_authenticator(krb5_context, krb5_checksum *, krb5_key, krb5_ui_4, krb5_authdata **, krb5_authdata_context ad_context, - krb5_enctype *desired_etypes, + krb5_enctype *desired_etypes, krb5_boolean cbt_flag, krb5_enctype tkt_enctype); krb5_error_code KRB5_CALLCONV @@ -95,6 +95,7 @@ krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context, krb5_ap_req request; krb5_data *scratch = 0; krb5_data *toutbuf; + krb5_boolean cbt_flag = (ap_req_options & AP_OPTS_CBT_FLAG) != 0; request.ap_options = ap_req_options & AP_OPTS_WIRE_MASK; request.authenticator.ciphertext.data = NULL; @@ -201,7 +202,7 @@ krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context, (*auth_context)->local_seq_number, in_creds->authdata, (*auth_context)->ad_context, - desired_etypes, + desired_etypes, cbt_flag, in_creds->keyblock.enctype))) goto cleanup_cksum; @@ -258,7 +259,7 @@ generate_authenticator(krb5_context context, krb5_authenticator *authent, krb5_key key, krb5_ui_4 seq_number, krb5_authdata **authorization, krb5_authdata_context ad_context, - krb5_enctype *desired_etypes, + krb5_enctype *desired_etypes, krb5_boolean cbt_flag, krb5_enctype tkt_enctype) { krb5_error_code retval; @@ -297,11 +298,15 @@ generate_authenticator(krb5_context context, krb5_authenticator *authent, krb5_free_authdata(context, ext_authdata); } - retval = profile_get_boolean(context->profile, KRB5_CONF_LIBDEFAULTS, - KRB5_CONF_CLIENT_AWARE_GSS_BINDINGS, NULL, - FALSE, &client_aware_cb); - if (retval) - return retval; + if (cbt_flag) { + client_aware_cb = TRUE; + } else { + retval = profile_get_boolean(context->profile, KRB5_CONF_LIBDEFAULTS, + KRB5_CONF_CLIENT_AWARE_GSS_BINDINGS, NULL, + FALSE, &client_aware_cb); + if (retval) + return retval; + } /* Add etype negotiation or channel-binding awareness authdata to the * front, if appropriate. */ diff --git a/src/tests/gssapi/t_bindings.c b/src/tests/gssapi/t_bindings.c index e890671..3d6a70a 100644 --- a/src/tests/gssapi/t_bindings.c +++ b/src/tests/gssapi/t_bindings.c @@ -43,34 +43,46 @@ * reported as channel-bound on the acceptor. Exit with status 0 if all * operations are successful, or 1 if not. * - * Usage: ./t_bindings [-s] targetname icb acb + * Usage: ./t_bindings [-s] [-b] targetname icb acb * - * An icb or abc value of "-" will not specify channel bindings. + * An icb or abc value of "-" will not specify channel bindings. The -s flag + * uses the SPNEGO mechanism instead of the krb5 mecanism. The -b flag + * includes GSS_C_CHANNEL_BOUND in req_flags, which requests strict enforcement + * of channel bindings by the acceptor. */ int main(int argc, char *argv[]) { + OM_uint32 client_flags = 0; OM_uint32 minor, flags1, flags2; gss_name_t target_name; gss_ctx_id_t ictx, actx; struct gss_channel_bindings_struct icb_data = {0}, acb_data = {0}; gss_channel_bindings_t icb = GSS_C_NO_CHANNEL_BINDINGS; gss_channel_bindings_t acb = GSS_C_NO_CHANNEL_BINDINGS; - gss_OID_desc *mech; + gss_OID_desc *mech = GSS_C_NO_OID; argv++; argc--; + if (*argv != NULL && strcmp(*argv, "-s") == 0) { mech = &mech_spnego; argv++; argc--; - } else { - mech = &mech_krb5; } + if (*argv != NULL && strcmp(*argv, "-b") == 0) { + client_flags |= GSS_C_CHANNEL_BOUND_FLAG; + argv++; + argc--; + } + + if (mech == GSS_C_NO_OID) + mech = &mech_krb5; + if (argc != 3) { - fprintf(stderr, "Usage: t_bindings [-s] targetname icb acb\n"); + fprintf(stderr, "Usage: t_bindings [-s] [-b] targetname icb acb\n"); return 1; } @@ -89,15 +101,16 @@ main(int argc, char *argv[]) } establish_contexts_ex(mech, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, - target_name, 0, &ictx, &actx, icb, acb, &flags1, - NULL, NULL, NULL); + target_name, client_flags, &ictx, &actx, icb, acb, + &flags1, NULL, NULL, NULL); /* Try again with GSS_C_DCE_STYLE */ (void)gss_delete_sec_context(&minor, &ictx, NULL); (void)gss_delete_sec_context(&minor, &actx, NULL); + client_flags |= GSS_C_DCE_STYLE; establish_contexts_ex(mech, GSS_C_NO_CREDENTIAL, GSS_C_NO_CREDENTIAL, - target_name, GSS_C_DCE_STYLE, &ictx, &actx, icb, acb, + target_name, client_flags, &ictx, &actx, icb, acb, &flags2, NULL, NULL, NULL); assert((flags1 & GSS_C_CHANNEL_BOUND_FLAG) == (flags2 & GSS_C_CHANNEL_BOUND_FLAG)); diff --git a/src/tests/gssapi/t_bindings.py b/src/tests/gssapi/t_bindings.py index f377977..1bb4966 100644 --- a/src/tests/gssapi/t_bindings.py +++ b/src/tests/gssapi/t_bindings.py @@ -40,4 +40,22 @@ realm.run(['./t_bindings', '-s', server, '-', 'a'], env=e, realm.run(['./t_bindings', '-s', server, 'a', 'x'], env=e, expected_code=1, expected_msg='Incorrect channel bindings') +mark('krb5 GSS_C_CHANNEL_BOUND_FLAG initiator input flag') +realm.run(['./t_bindings', '-b', server, '-', '-'], expected_msg='no') +realm.run(['./t_bindings', '-b', server, 'a', '-'], expected_msg='no') +realm.run(['./t_bindings', '-b', server, 'a', 'a'], expected_msg='yes') +realm.run(['./t_bindings', '-b', server, '-', 'a'], + expected_code=1, expected_msg='Incorrect channel bindings') +realm.run(['./t_bindings', '-b', server, 'a', 'x'], + expected_code=1, expected_msg='Incorrect channel bindings') + +mark('SPNEGO GSS_C_CHANNEL_BOUND_FLAG initiator input flag') +realm.run(['./t_bindings', '-s', '-b', server, '-', '-'], expected_msg='no') +realm.run(['./t_bindings', '-s', '-b', server, 'a', '-'], expected_msg='no') +realm.run(['./t_bindings', '-s', '-b', server, 'a', 'a'], expected_msg='yes') +realm.run(['./t_bindings', '-s', '-b', server, '-', 'a'], + expected_code=1, expected_msg='Incorrect channel bindings') +realm.run(['./t_bindings', '-s', '-b', server, 'a', 'x'], + expected_code=1, expected_msg='Incorrect channel bindings') + success('channel bindings tests') |