diff --git a/lib/gssapi/Makefile.am b/lib/gssapi/Makefile.am index ab6e7c553..464dd9b7e 100644 --- a/lib/gssapi/Makefile.am +++ b/lib/gssapi/Makefile.am @@ -202,6 +202,7 @@ ntlmsrc = \ ntlm/process_context_token.c \ ntlm/release_cred.c \ ntlm/release_name.c \ + ntlm/set_sec_context_option.c \ ntlm/kdc.c $(srcdir)/ntlm/ntlm-private.h: $(ntlmsrc) diff --git a/lib/gssapi/NTMakefile b/lib/gssapi/NTMakefile index 501345825..54a6dffe3 100644 --- a/lib/gssapi/NTMakefile +++ b/lib/gssapi/NTMakefile @@ -218,6 +218,7 @@ ntlmsrc = \ ntlm/process_context_token.c \ ntlm/release_cred.c \ ntlm/release_name.c \ + ntlm/set_sec_context_option.c \ ntlm/kdc.c $(OBJ)\ntlm\ntlm-private.h: $(ntlmsrc) @@ -442,6 +443,7 @@ libgssapi_OBJs = \ $(OBJ)\ntlm/process_context_token.obj \ $(OBJ)\ntlm/release_cred.obj \ $(OBJ)\ntlm/release_name.obj \ + $(OBJ)\ntlm/set_sec_context_option.obj \ $(OBJ)\ntlm/kdc.obj \ $(OBJ)\gkrb5_err.obj \ $(spnego_files:.x=.obj) \ diff --git a/lib/gssapi/gssapi/gssapi_oid.h b/lib/gssapi/gssapi/gssapi_oid.h index a61466144..30ffbe4ad 100644 --- a/lib/gssapi/gssapi/gssapi_oid.h +++ b/lib/gssapi/gssapi/gssapi_oid.h @@ -148,6 +148,9 @@ extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_spnego_mechanism_oid_desc; extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_peer_has_updated_spnego_oid_desc; #define GSS_C_PEER_HAS_UPDATED_SPNEGO (&__gss_c_peer_has_updated_spnego_oid_desc) +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ntlm_reset_crypto_oid_desc; +#define GSS_C_NTLM_RESET_CRYPTO (&__gss_c_ntlm_reset_crypto_oid_desc) + /* * OID mappings with name and short description and and slightly longer description */ diff --git a/lib/gssapi/mech/gss_oid.c b/lib/gssapi/mech/gss_oid.c index f2e1562e4..5b9bd3623 100644 --- a/lib/gssapi/mech/gss_oid.c +++ b/lib/gssapi/mech/gss_oid.c @@ -136,6 +136,9 @@ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_spnego_mechanism_oid_desc = { 6, rk_UNCON /* GSS_C_PEER_HAS_UPDATED_SPNEGO - 1.3.6.1.4.1.5322.19.5 */ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_peer_has_updated_spnego_oid_desc = { 9, rk_UNCONST("\x2b\x06\x01\x04\x01\xa9\x4a\x13\x05") }; +/* GSS_C_NTLM_RESET_CRYPTO - 1.3.6.1.4.1.7165.655.1.3 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ntlm_reset_crypto_oid_desc = { 11, rk_UNCONST("\x2b\x06\x01\x04\x01\xb7\x7d\x85\x0f\x01\x03") }; + /* GSS_C_MA_MECH_CONCRETE - 1.3.6.1.5.5.13.1 */ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_mech_concrete_oid_desc = { 7, rk_UNCONST("\x2b\x06\x01\x05\x05\x0d\x01") }; @@ -304,6 +307,7 @@ gss_OID _gss_ot_internal[] = { &__gss_ntlm_mechanism_oid_desc, &__gss_spnego_mechanism_oid_desc, &__gss_c_peer_has_updated_spnego_oid_desc, + &__gss_c_ntlm_reset_crypto_oid_desc, &__gss_c_ma_mech_concrete_oid_desc, &__gss_c_ma_mech_pseudo_oid_desc, &__gss_c_ma_mech_composite_oid_desc, diff --git a/lib/gssapi/ntlm/accept_sec_context.c b/lib/gssapi/ntlm/accept_sec_context.c index 1dbfb9d97..b169f788d 100644 --- a/lib/gssapi/ntlm/accept_sec_context.c +++ b/lib/gssapi/ntlm/accept_sec_context.c @@ -237,28 +237,7 @@ _gss_ntlm_accept_sec_context return GSS_S_FAILURE; } - if (session.length != 0) { - - ctx->status |= STATUS_SESSIONKEY; - - if (ctx->flags & NTLM_NEG_NTLM2_SESSION) { - _gss_ntlm_set_key(&ctx->u.v2.send, 1, - (ctx->flags & NTLM_NEG_KEYEX), - ctx->sessionkey.data, - ctx->sessionkey.length); - _gss_ntlm_set_key(&ctx->u.v2.recv, 0, - (ctx->flags & NTLM_NEG_KEYEX), - ctx->sessionkey.data, - ctx->sessionkey.length); - } else { - RC4_set_key(&ctx->u.v1.crypto_send.key, - ctx->sessionkey.length, - ctx->sessionkey.data); - RC4_set_key(&ctx->u.v1.crypto_recv.key, - ctx->sessionkey.length, - ctx->sessionkey.data); - } - } + _gss_ntlm_set_keys(ctx); if (mech_type) *mech_type = GSS_NTLM_MECHANISM; diff --git a/lib/gssapi/ntlm/crypto.c b/lib/gssapi/ntlm/crypto.c index 40469a7a7..20f7377b7 100644 --- a/lib/gssapi/ntlm/crypto.c +++ b/lib/gssapi/ntlm/crypto.c @@ -115,6 +115,37 @@ _gss_ntlm_set_key(struct ntlmv2_key *key, int acceptor, int sealsign, key->signsealkey = &key->sealkey; } +/* + * Set (or reset) keys + */ + +void +_gss_ntlm_set_keys(ntlm_ctx ctx) +{ + if (ctx->sessionkey.length == 0) + return; + + ctx->status |= STATUS_SESSIONKEY; + + if (ctx->flags & NTLM_NEG_NTLM2_SESSION) { + _gss_ntlm_set_key(&ctx->u.v2.send, 1, + (ctx->flags & NTLM_NEG_KEYEX), + ctx->sessionkey.data, + ctx->sessionkey.length); + _gss_ntlm_set_key(&ctx->u.v2.recv, 0, + (ctx->flags & NTLM_NEG_KEYEX), + ctx->sessionkey.data, + ctx->sessionkey.length); + } else { + RC4_set_key(&ctx->u.v1.crypto_send.key, + ctx->sessionkey.length, + ctx->sessionkey.data); + RC4_set_key(&ctx->u.v1.crypto_recv.key, + ctx->sessionkey.length, + ctx->sessionkey.data); + } +} + /* * */ diff --git a/lib/gssapi/ntlm/external.c b/lib/gssapi/ntlm/external.c index 986f9f3df..3c0fba86c 100644 --- a/lib/gssapi/ntlm/external.c +++ b/lib/gssapi/ntlm/external.c @@ -96,7 +96,7 @@ static gssapi_mech_interface_desc ntlm_mech = { _gss_ntlm_duplicate_name, _gss_ntlm_inquire_sec_context_by_oid, NULL, - NULL, + _gss_ntlm_set_sec_context_option, NULL, NULL, NULL, diff --git a/lib/gssapi/ntlm/set_sec_context_option.c b/lib/gssapi/ntlm/set_sec_context_option.c new file mode 100644 index 000000000..372ad9ffa --- /dev/null +++ b/lib/gssapi/ntlm/set_sec_context_option.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Portions Copyright (c) 2009 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "ntlm.h" + +OM_uint32 GSSAPI_CALLCONV +_gss_ntlm_set_sec_context_option(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID object, + const gss_buffer_t value) +{ + ntlm_ctx ctx; + + if (context_handle == NULL) + return GSS_S_UNAVAILABLE; + + *minor_status = 0; + + ctx = (ntlm_ctx)*context_handle; + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + + if (gss_oid_equal(object, GSS_C_NTLM_RESET_CRYPTO)) { + /* OM_uint32 verify = *((OM_uint32 *)value->value); */ + _gss_ntlm_set_keys(ctx); + return GSS_S_COMPLETE; + } else + return GSS_S_UNAVAILABLE; +} diff --git a/lib/gssapi/oid.txt b/lib/gssapi/oid.txt index 263202759..5eaa4f585 100644 --- a/lib/gssapi/oid.txt +++ b/lib/gssapi/oid.txt @@ -64,6 +64,8 @@ oid base GSS_SPNEGO_MECHANISM 1.3.6.1.5.5.2 # /* From Luke Howard */ oid base GSS_C_PEER_HAS_UPDATED_SPNEGO 1.3.6.1.4.1.5322.19.5 +oid base GSS_C_NTLM_RESET_CRYPTO 1.3.6.1.4.1.7165.655.1.3 + #/* # * OID mappings with name and short description and and slightly longer description diff --git a/lib/gssapi/spnego/accept_sec_context.c b/lib/gssapi/spnego/accept_sec_context.c index 4f9bc4f1e..ce73cd8b1 100644 --- a/lib/gssapi/spnego/accept_sec_context.c +++ b/lib/gssapi/spnego/accept_sec_context.c @@ -236,6 +236,10 @@ send_accept (OM_uint32 *minor_status, 0, mech_buf, &mech_mic_buf); + if (ret == GSS_S_COMPLETE && + gss_oid_equal(context_handle->negotiated_mech_type, + GSS_NTLM_MECHANISM)) + _gss_spnego_ntlm_reset_crypto(minor_status, context_handle, 0); if (ret == GSS_S_COMPLETE) { ALLOC(nt.u.negTokenResp.mechListMIC, 1); if (nt.u.negTokenResp.mechListMIC == NULL) { diff --git a/lib/gssapi/spnego/compat.c b/lib/gssapi/spnego/compat.c index b902e0469..0dc6425c8 100644 --- a/lib/gssapi/spnego/compat.c +++ b/lib/gssapi/spnego/compat.c @@ -315,3 +315,19 @@ _gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status, return ret; } + +OM_uint32 +_gss_spnego_ntlm_reset_crypto(OM_uint32 *minor_status, + gssspnego_ctx ctx, + OM_uint32 verify) +{ + gss_buffer_desc value; + + value.length = sizeof(verify); + value.value = &verify; + + return gss_set_sec_context_option(minor_status, + &ctx->negotiated_ctx_id, + GSS_C_NTLM_RESET_CRYPTO, + &value); +} diff --git a/lib/gssapi/spnego/init_sec_context.c b/lib/gssapi/spnego/init_sec_context.c index 4f7ff7fd8..1428f88fb 100644 --- a/lib/gssapi/spnego/init_sec_context.c +++ b/lib/gssapi/spnego/init_sec_context.c @@ -136,6 +136,9 @@ spnego_reply_internal(OM_uint32 *minor_status, 0, mech_buf, &mic_buf); + if (ret == GSS_S_COMPLETE && + gss_oid_equal(context_handle->negotiated_mech_type, GSS_NTLM_MECHANISM)) + _gss_spnego_ntlm_reset_crypto(minor_status, context_handle, 0); if (ret == GSS_S_COMPLETE) { ALLOC(nt.u.negTokenResp.mechListMIC, 1); if (nt.u.negTokenResp.mechListMIC == NULL) { @@ -580,6 +583,9 @@ spnego_reply &mech_buf, &mic_buf, NULL); + if (ret == GSS_S_COMPLETE && + gss_oid_equal(ctx->negotiated_mech_type, GSS_NTLM_MECHANISM)) + _gss_spnego_ntlm_reset_crypto(minor_status, ctx, 1); if (ret) { HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); free(mech_buf.value);