From 554dc66bf059efef988b05d70e60a89ad4448df1 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Apr 18 2019 19:29:44 +0000 Subject: Add support to return SSF value Signed-off-by: Simo Sorce --- diff --git a/src/gss_sec_ctx.c b/src/gss_sec_ctx.c index a926e24..300f334 100644 --- a/src/gss_sec_ctx.c +++ b/src/gss_sec_ctx.c @@ -15,6 +15,7 @@ License along with this library; if not, see . */ +#include #include #include #include @@ -1219,6 +1220,48 @@ uint32_t gssntlm_spnego_req_mic(uint32_t *minor_status, return GSSERRS(retmin, retmaj); } +static const gss_OID_desc sasl_ssf_oid = { + 11, discard_const("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f") +}; + +static uint32_t gssntlm_sasl_ssf(uint32_t *minor_status, + struct gssntlm_ctx *ctx, + gss_buffer_set_t *data_set) +{ + uint32_t retmin; + uint32_t retmaj; + uint32_t tmpmin; + gss_buffer_desc ssf_buf; + uint32_t ssf = 0; + + /* Handwaving a bit here but this is what SSF is all about */ + if (ctx->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { + if (ctx->neg_flags & NTLMSSP_NEGOTIATE_128) { + /* Technically we use RC4 with a 128 bit key, but we + * consider the RC4 strenght degraded so we assign + * it a value of 64, this is consistent with what + * the krb5 mechanism does for the Rc4-HMAC enctype */ + ssf = 64; + } else if (ctx->neg_flags & NTLMSSP_NEGOTIATE_56) { + ssf = 56; + } else { + ssf = 40; + } + } else if (ctx->neg_flags & NTLMSSP_NEGOTIATE_SIGN) { + ssf = 1; + } + + ssf = htobe32(ssf); + ssf_buf.value = &ssf; + ssf_buf.length = 4; + + retmaj = gss_add_buffer_set_member(&retmin, &ssf_buf, data_set); + if (retmaj != GSS_S_COMPLETE) { + (void)gss_release_buffer_set(&tmpmin, data_set); + } + + return GSSERRS(retmin, retmaj); +} uint32_t gssntlm_inquire_sec_context_by_oid(uint32_t *minor_status, const gss_ctx_id_t context_handle, @@ -1244,6 +1287,8 @@ uint32_t gssntlm_inquire_sec_context_by_oid(uint32_t *minor_status, if (gss_oid_equal(desired_object, &spnego_req_mic_oid)) { return gssntlm_spnego_req_mic(minor_status, ctx, data_set); + } else if (gss_oid_equal(desired_object, &sasl_ssf_oid)){ + return gssntlm_sasl_ssf(minor_status, ctx, data_set); } return GSSERRS(ERR_NOTSUPPORTED, GSS_S_UNAVAILABLE); diff --git a/tests/ntlmssptest.c b/tests/ntlmssptest.c index e8c4d58..ec78fca 100644 --- a/tests/ntlmssptest.c +++ b/tests/ntlmssptest.c @@ -1471,6 +1471,11 @@ int test_gssapi_1(bool user_env_file, bool use_cb, bool no_seal) uint8_t rand_cb[128]; struct gss_channel_bindings_struct cbts = { 0 }; gss_channel_bindings_t cbt = GSS_C_NO_CHANNEL_BINDINGS; + gss_buffer_set_t data_set; + gss_OID_desc sasl_ssf_oid = { + 11, discard_const("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f") + }; + uint32_t ssf, expect_ssf; uint32_t req_flags; int ret; @@ -1758,6 +1763,29 @@ int test_gssapi_1(bool user_env_file, bool use_cb, bool no_seal) gss_release_buffer(&retmin, &nbuf); + retmaj = gssntlm_inquire_sec_context_by_oid(&retmin, srv_ctx, + &sasl_ssf_oid, &data_set); + if (retmaj != GSS_S_COMPLETE) { + print_gss_error("gssntlm_inquire_sec_context_by_oid failed!", + retmaj, retmin); + ret = EINVAL; + goto done; + } + if (data_set == NULL || data_set->count != 1) { + fprintf(stderr, "Expected 1 data_set element\n"); + return EINVAL; + } + ssf = be32toh(*(uint32_t *)data_set->elements[0].value); + expect_ssf = 64; + if (no_seal) { + expect_ssf = 1; + } + if (ssf != expect_ssf) { + fprintf(stderr, "Expected SSF of %u, got: %u\n", + (unsigned int)expect_ssf, (unsigned int)ssf); + return EINVAL; + } + ret = 0; done: @@ -1769,6 +1797,7 @@ done: gssntlm_release_cred(&retmin, &srv_cred); gss_release_buffer(&retmin, &cli_token); gss_release_buffer(&retmin, &srv_token); + gss_release_buffer_set(&retmin, &data_set); return ret; }