gss: update SAnon for draft-howard-gss-sanon-13
authorLuke Howard <lukeh@padl.com>
Mon, 27 Apr 2020 04:52:10 +0000 (14:52 +1000)
committerLuke Howard <lukeh@padl.com>
Mon, 27 Apr 2020 05:18:14 +0000 (15:18 +1000)
draft-howard-gss-sanon-13 will move extended (RFC4757) flags from the NegoEx
metadata to an optional component of the initial context token

lib/gssapi/sanon/accept_sec_context.c
lib/gssapi/sanon/crypto.c
lib/gssapi/sanon/init_sec_context.c
lib/gssapi/sanon/inquire_context.c
lib/gssapi/sanon/negoex.c
lib/gssapi/sanon/sanon_locl.h

index bcaa3316d3b036f7712f38d6d2c702b1801d2ca0..51ba51a0a33d60cffac48c13e77e9e154d7cebb2 100644 (file)
@@ -48,8 +48,10 @@ _gss_sanon_accept_sec_context(OM_uint32 *minor,
     OM_uint32 major, tmp;
     sanon_ctx sc = (sanon_ctx)*context_handle;
     gss_buffer_desc mech_input_token = GSS_C_EMPTY_BUFFER;
+    gss_buffer_desc initiator_pk = GSS_C_EMPTY_BUFFER;
     gss_buffer_desc hok_mic = GSS_C_EMPTY_BUFFER;
     gss_buffer_desc session_key = GSS_C_EMPTY_BUFFER;
+    OM_uint32 req_flags = 0;
 
     if (output_token == GSS_C_NO_BUFFER) {
        *minor = EINVAL;
@@ -62,7 +64,7 @@ _gss_sanon_accept_sec_context(OM_uint32 *minor,
     if (input_token == GSS_C_NO_BUFFER) {
        major = GSS_S_DEFECTIVE_TOKEN;
        goto out;
-    } else if (sc != NULL && sc->rfc4121 != GSS_C_NO_CONTEXT) {
+    } else if (sc != NULL) {
        major = GSS_S_BAD_STATUS;
        goto out;
     }
@@ -73,30 +75,50 @@ _gss_sanon_accept_sec_context(OM_uint32 *minor,
     if (major != GSS_S_COMPLETE)
        goto out;
 
+    sc = calloc(1, sizeof(*sc));
     if (sc == NULL) {
-       sc = calloc(1, sizeof(*sc));
-       if (sc == NULL) {
-           *minor = ENOMEM;
-           major = GSS_S_FAILURE;
-           goto out;
-       }
+       *minor = ENOMEM;
+       major = GSS_S_FAILURE;
+       goto out;
+    }
+
+    /* initiator token can include optional 64-bit flags */
+    if (mech_input_token.length != crypto_scalarmult_curve25519_BYTES &&
+       mech_input_token.length != crypto_scalarmult_curve25519_BYTES + 8) {
+       *minor = 0;
+       major = GSS_S_DEFECTIVE_TOKEN;
+       goto out;
     }
 
+    initiator_pk = mech_input_token;
+    initiator_pk.length = crypto_scalarmult_curve25519_BYTES;
+
     /* compute public and secret keys */
     major = _gss_sanon_curve25519_base(minor, sc);
     if (major != GSS_S_COMPLETE)
        goto out;
 
+    if (mech_input_token.length > crypto_scalarmult_curve25519_BYTES) {
+       /* extra flags */
+       uint8_t *p = (uint8_t *)mech_input_token.value + crypto_scalarmult_curve25519_BYTES;
+       uint32_t dummy;
+
+       _gss_mg_decode_be_uint32(p, &dummy); /* upper 32 bits presently unused */
+       _gss_mg_decode_be_uint32(&p[4], &req_flags);
+    }
+
+    req_flags &= SANON_PROTOCOL_FLAG_MASK; /* do not let initiator set any other flags */
+
     /* compute shared secret */
-    major = _gss_sanon_curve25519(minor, sc, &mech_input_token,
+    major = _gss_sanon_curve25519(minor, sc, &initiator_pk, req_flags,
                                  input_chan_bindings, &session_key);
     if (major != GSS_S_COMPLETE)
        goto out;
 
-    sc->flags |= GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG |
+    req_flags |= GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG |
         GSS_C_INTEG_FLAG | GSS_C_ANON_FLAG | GSS_C_TRANS_FLAG;
 
-    major = _gss_sanon_import_rfc4121_context(minor, sc, &session_key);
+    major = _gss_sanon_import_rfc4121_context(minor, sc, req_flags, &session_key);
     if (major != GSS_S_COMPLETE)
        goto out;
 
@@ -124,7 +146,7 @@ _gss_sanon_accept_sec_context(OM_uint32 *minor,
     if (src_name)
        *src_name = _gss_sanon_anonymous_identity;
     if (ret_flags)
-       *ret_flags = sc->flags;
+       *ret_flags = req_flags;
     if (time_rec)
        *time_rec = GSS_C_INDEFINITE;
 
index 69d175476b3f65d1a9202adab3d2b99bf9923c6c..0c7a67f7077188aedc6847ae1d0526861a24afaa 100644 (file)
@@ -239,6 +239,7 @@ OM_uint32
 _gss_sanon_curve25519(OM_uint32 *minor,
                      sanon_ctx sc,
                      gss_buffer_t pk,
+                     OM_uint32 gss_flags,
                      const gss_channel_bindings_t input_chan_bindings,
                      gss_buffer_t session_key)
 {
@@ -268,7 +269,7 @@ _gss_sanon_curve25519(OM_uint32 *minor,
     kdf_label.length = sizeof("sanon-x25519") - 1;
 
     ret = krb5_data_alloc(&kdf_context,
-                         2 * crypto_scalarmult_curve25519_BYTES +
+                         2 * crypto_scalarmult_curve25519_BYTES + 8 +
                          (input_chan_bindings ? input_chan_bindings->application_data.length : 0));
     if (ret != 0) {
        krb5_free_context(context);
@@ -285,11 +286,15 @@ _gss_sanon_curve25519(OM_uint32 *minor,
        memcpy(p, pk->value, pk->length);
        memcpy(&p[sizeof(sc->pk)], sc->pk, sizeof(sc->pk));
     }
+    p += 2 * crypto_scalarmult_curve25519_BYTES;
+    _gss_mg_encode_be_uint32(0, p); /* upper 32 bits presently unused */
+    p += 4;
+    _gss_mg_encode_be_uint32(gss_flags, p);
+    p += 4;
 
     if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS &&
        input_chan_bindings->application_data.value != NULL) {
-       memcpy(&p[2 * crypto_scalarmult_curve25519_BYTES],
-              input_chan_bindings->application_data.value,
+       memcpy(p, input_chan_bindings->application_data.value,
               input_chan_bindings->application_data.length);
     }
 
@@ -318,9 +323,10 @@ _gss_sanon_curve25519(OM_uint32 *minor,
 OM_uint32
 _gss_sanon_import_rfc4121_context(OM_uint32 *minor,
                                  sanon_ctx sc,
+                                 OM_uint32 gss_flags,
                                  gss_const_buffer_t session_key)
 {
-    return _gss_mg_import_rfc4121_context(minor, sc->is_initiator, sc->flags,
+    return _gss_mg_import_rfc4121_context(minor, sc->is_initiator, gss_flags,
                                           KRB5_ENCTYPE_AES128_CTS_HMAC_SHA256_128,
                                           session_key, &sc->rfc4121);
 }
index c553bbdb42796a0290f85bd291a1931dfbb22bf2..be61aba9b67acdf9a9f6e72f8c30b9cf59274b97 100644 (file)
@@ -99,12 +99,13 @@ _gss_sanon_init_sec_context(OM_uint32 *minor,
     }
 
     flags |= GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_CONF_FLAG |
-            GSS_C_INTEG_FLAG | GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG |
-            GSS_C_EXTENDED_ERROR_FLAG; /* supported flags */
+            GSS_C_INTEG_FLAG | SANON_PROTOCOL_FLAG_MASK; /* supported flags */
     flags &= req_flags;
     flags |= GSS_C_ANON_FLAG; /* always set this flag */
 
     if (sc == NULL) {
+       uint8_t pk_and_flags[crypto_scalarmult_curve25519_BYTES + 8];
+
        if (input_token != GSS_C_NO_BUFFER && input_token->length != 0) {
            major = GSS_S_DEFECTIVE_TOKEN;
            goto out;
@@ -118,15 +119,23 @@ _gss_sanon_init_sec_context(OM_uint32 *minor,
        }
 
         sc->is_initiator = 1;
-       sc->flags = req_flags;
 
        /* compute public and secret keys */
        major = _gss_sanon_curve25519_base(minor, sc);
        if (major != GSS_S_COMPLETE)
            goto out;
 
-       mech_token.length = sizeof(sc->pk);
-       mech_token.value = sc->pk;
+       if (req_flags & SANON_PROTOCOL_FLAG_MASK) {
+           memcpy(pk_and_flags, sc->pk, sizeof(sc->pk));
+           _gss_mg_encode_be_uint32(0, &pk_and_flags[sizeof(sc->pk)]);
+           _gss_mg_encode_be_uint32(req_flags & SANON_PROTOCOL_FLAG_MASK,
+                                    &pk_and_flags[sizeof(sc->pk) + 4]);
+           mech_token.length = sizeof(pk_and_flags);
+           mech_token.value = pk_and_flags;
+       } else {
+           mech_token.length = sizeof(sc->pk);
+           mech_token.value = sc->pk;
+       }
 
        /* send public key to acceptor */
        major = gss_encapsulate_token(&mech_token,
@@ -154,14 +163,14 @@ _gss_sanon_init_sec_context(OM_uint32 *minor,
        pk.value = input_token->value;
 
        /* compute shared secret */
-       major = _gss_sanon_curve25519(minor, sc, &pk, input_chan_bindings, &session_key);
+       major = _gss_sanon_curve25519(minor, sc, &pk, flags & SANON_PROTOCOL_FLAG_MASK,
+                                     input_chan_bindings, &session_key);
        if (major != GSS_S_COMPLETE)
            goto out;
 
        flags |= GSS_C_TRANS_FLAG;
-        sc->flags |= GSS_C_TRANS_FLAG;
 
-       major = _gss_sanon_import_rfc4121_context(minor, sc, &session_key);
+       major = _gss_sanon_import_rfc4121_context(minor, sc, flags, &session_key);
        if (major != GSS_S_COMPLETE)
            goto out;
 
index bec1d5088777d5fc62aecedf18cfc63515e7fda7..f5aa727b53a90376185731ee4c3d9d292b6b0cee 100644 (file)
@@ -64,7 +64,8 @@ _gss_sanon_inquire_context(OM_uint32 *minor,
         if (open_context)
             *open_context = 0;
         if (ctx_flags)
-            *ctx_flags = sc->flags;
+            *ctx_flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG |
+                        GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_ANON_FLAG;
     } else {
         major = gss_inquire_context(minor, sc->rfc4121, NULL, NULL, NULL,
                                     NULL, ctx_flags, locally_initiated,
index 86df155aa4b690544a011e7e0ab946ccc4a97134..c6a21dd2b0a7369d54004e27050f2a23de9e8886 100644 (file)
@@ -97,19 +97,6 @@ _gss_sanon_inquire_negoex_key(OM_uint32 *minor,
     return major;
 }
 
-static OM_uint32
-make_flags_meta_data(OM_uint32 *minor,
-                    OM_uint32 flags,
-                    gss_buffer_t meta_data)
-{
-    uint8_t data[4];
-    gss_buffer_desc buffer = { sizeof(data), data };
-
-    _gss_mg_encode_le_uint32(flags, data);
-
-    return _gss_copy_buffer(minor, &buffer, meta_data);
-}
-
 OM_uint32 GSSAPI_CALLCONV
 _gssspi_sanon_query_meta_data(OM_uint32 *minor,
                              gss_const_OID mech_oid,
@@ -119,45 +106,13 @@ _gssspi_sanon_query_meta_data(OM_uint32 *minor,
                              OM_uint32 req_flags,
                              gss_buffer_t meta_data)
 {
-    OM_uint32 major;
-    int local = (targ_name != GSS_C_NO_NAME);
+    int is_initiator = (targ_name != GSS_C_NO_NAME);
 
     *minor = 0;
 
-    if (local) {
-       if (!_gss_sanon_available_p(cred_handle, targ_name, req_flags))
-           return GSS_S_UNAVAILABLE;
-
-       /*
-        * Obscure Windows interoperability hack: use metadata to convey
-        * RFC4757 extended flags from initiator to acceptor.
-        */
-       req_flags &= (GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG);
-       if (req_flags) {
-           major = make_flags_meta_data(minor, req_flags, meta_data);
-           if (major != GSS_S_COMPLETE)
-               return major;
-       }
-    }
-
-    return GSS_S_COMPLETE;
-}
-
-static OM_uint32
-parse_flags_meta_data(OM_uint32 *minor,
-                     gss_const_buffer_t meta_data,
-                     OM_uint32 *flags)
-{
-    *minor = 0;
-    *flags = 0;
-
-    if (meta_data->length == 0)
-       return GSS_S_COMPLETE;
-
-    if (meta_data->length < 4)
-       return GSS_S_DEFECTIVE_TOKEN;
-
-    _gss_mg_decode_le_uint32(meta_data->value, flags);
+    if (is_initiator &&
+       !_gss_sanon_available_p(cred_handle, targ_name, req_flags))
+       return GSS_S_UNAVAILABLE;
 
     return GSS_S_COMPLETE;
 }
@@ -171,30 +126,6 @@ _gssspi_sanon_exchange_meta_data(OM_uint32 *minor,
                                 OM_uint32 req_flags,
                                 gss_const_buffer_t meta_data)
 {
-    sanon_ctx sc = (sanon_ctx)*context_handle;
-    int local = (targ_name != GSS_C_NO_NAME);
-    OM_uint32 major, init_flags;
-
     *minor = 0;
-
-    if (local)
-       return GSS_S_COMPLETE;
-
-    if (sc == NULL) {
-       sc = calloc(1, sizeof(*sc));
-       if (sc == NULL) {
-           *minor = ENOMEM;
-           return GSS_S_FAILURE;
-       }
-       *context_handle = (gss_ctx_id_t)sc;
-    }
-
-    major = parse_flags_meta_data(minor, meta_data, &init_flags);
-    if (major != GSS_S_COMPLETE)
-       return major;
-
-    init_flags &= ~(GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG);
-    sc->flags |= init_flags | req_flags;
-
     return GSS_S_COMPLETE;
 }
index 9d853b6fcde72cb511d5180d731b38a3f526ad62..7b3c4780a3f87d677fb200c786ef83ed49f17388 100644 (file)
@@ -48,11 +48,9 @@ typedef struct sanon_ctx_desc {
     uint8_t sk[crypto_scalarmult_curve25519_BYTES];
     /* X25519 ECDH public key */
     uint8_t pk[crypto_scalarmult_curve25519_BYTES];
-    /* GSS_C_*_FLAG */
-    uint32_t flags;
     /* krb5 context for message protection/PRF */
     gss_ctx_id_t rfc4121;
-    int is_initiator;
+    int is_initiator : 1;
 } *sanon_ctx;
 
 extern gss_name_t _gss_sanon_anonymous_identity;
@@ -80,4 +78,7 @@ buffer_equal_p(gss_const_buffer_t b1, gss_const_buffer_t b2)
        memcmp(b1->value, b2->value, b2->length) == 0;
 }
 
+/* flags that are valid to be sent from a SAnon initiator in the flags field */
+#define SANON_PROTOCOL_FLAG_MASK ( GSS_C_DCE_STYLE | GSS_C_IDENTIFY_FLAG | GSS_C_EXTENDED_ERROR_FLAG )
+
 #endif /* SANON_LOCL_H */