]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Add support to query the SSF of a GSS context 625/head
authorSimo Sorce <simo@redhat.com>
Thu, 30 Mar 2017 15:27:09 +0000 (11:27 -0400)
committerGreg Hudson <ghudson@mit.edu>
Mon, 10 Apr 2017 15:32:51 +0000 (11:32 -0400)
Cyrus SASL provides a Security Strength Factor number to assess the
relative "strength" of the negotiated mechanism, and applications
sometimes make access control decisions based on it.

Add a call that allows us to query the mechanism that established the
GSS security context to ask what is the current SSF, based on the
enctype of the session key.

ticket: 8569 (new)

14 files changed:
src/include/k5-int.h
src/lib/crypto/krb/crypto_int.h
src/lib/crypto/krb/enctype_util.c
src/lib/crypto/krb/etypes.c
src/lib/crypto/libk5crypto.exports
src/lib/gssapi/generic/gssapi_ext.h
src/lib/gssapi/generic/gssapi_generic.c
src/lib/gssapi/krb5/gssapiP_krb5.h
src/lib/gssapi/krb5/gssapi_krb5.c
src/lib/gssapi/krb5/inq_context.c
src/lib/gssapi/libgssapi_krb5.exports
src/lib/gssapi32.def
src/lib/krb5_32.def
src/tests/gssapi/t_enctypes.c

index ddeebc45e55f70cfa2d191a67942a772623ddebd..78ebaf3aa093f4d59a592f1e0313840d77af5b8e 100644 (file)
@@ -2113,6 +2113,7 @@ krb5_get_tgs_ktypes(krb5_context, krb5_const_principal, krb5_enctype **);
 krb5_boolean krb5_is_permitted_enctype(krb5_context, krb5_enctype);
 
 krb5_boolean KRB5_CALLCONV krb5int_c_weak_enctype(krb5_enctype);
+krb5_error_code k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out);
 
 krb5_error_code krb5_kdc_rep_decrypt_proc(krb5_context, const krb5_keyblock *,
                                           krb5_const_pointer, krb5_kdc_rep *);
index d75b49c693f03fe9bfe906302df4c1a0fce4d525..e5099291e3094e609ac7e65c18feafce95d40b9d 100644 (file)
@@ -111,6 +111,7 @@ struct krb5_keytypes {
     prf_func prf;
     krb5_cksumtype required_ctype;
     krb5_flags flags;
+    unsigned int ssf;
 };
 
 #define ETYPE_WEAK 1
index 0ed74bd6ebde8f69cf97fc19ed18204e7357cd2e..b1b40e7ecd6e9192337b92dfe50e1f2f944ee469 100644 (file)
@@ -131,3 +131,19 @@ krb5_enctype_to_name(krb5_enctype enctype, krb5_boolean shortest,
         return ENOMEM;
     return 0;
 }
+
+/* The security of a mechanism cannot be summarized with a simple integer
+ * value, but we provide a per-enctype value for Cyrus SASL's SSF. */
+krb5_error_code
+k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out)
+{
+    const struct krb5_keytypes *ktp;
+
+    *ssf_out = 0;
+
+    ktp = find_enctype(enctype);
+    if (ktp == NULL)
+        return EINVAL;
+    *ssf_out = ktp->ssf;
+    return 0;
+}
index 0e5e977d418a6bff551f68da5b6e49c494552ebf..53d4a5c79b47b04ac480a01659d4fc1b65d8e06c 100644 (file)
@@ -42,7 +42,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_des_string_to_key, k5_rand2key_des,
       krb5int_des_prf,
       CKSUMTYPE_RSA_MD5_DES,
-      ETYPE_WEAK },
+      ETYPE_WEAK, 56 },
     { ENCTYPE_DES_CBC_MD4,
       "des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4",
       &krb5int_enc_des, &krb5int_hash_md4,
@@ -51,7 +51,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_des_string_to_key, k5_rand2key_des,
       krb5int_des_prf,
       CKSUMTYPE_RSA_MD4_DES,
-      ETYPE_WEAK },
+      ETYPE_WEAK, 56 },
     { ENCTYPE_DES_CBC_MD5,
       "des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5",
       &krb5int_enc_des, &krb5int_hash_md5,
@@ -60,7 +60,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_des_string_to_key, k5_rand2key_des,
       krb5int_des_prf,
       CKSUMTYPE_RSA_MD5_DES,
-      ETYPE_WEAK },
+      ETYPE_WEAK, 56 },
     { ENCTYPE_DES_CBC_RAW,
       "des-cbc-raw", { 0 }, "DES cbc mode raw",
       &krb5int_enc_des, NULL,
@@ -69,7 +69,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_des_string_to_key, k5_rand2key_des,
       krb5int_des_prf,
       0,
-      ETYPE_WEAK },
+      ETYPE_WEAK, 56 },
     { ENCTYPE_DES3_CBC_RAW,
       "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw",
       &krb5int_enc_des3, NULL,
@@ -78,7 +78,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_dk_string_to_key, k5_rand2key_des3,
       NULL, /*PRF*/
       0,
-      ETYPE_WEAK },
+      ETYPE_WEAK, 112 },
 
     { ENCTYPE_DES3_CBC_SHA1,
       "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" },
@@ -89,7 +89,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_dk_string_to_key, k5_rand2key_des3,
       krb5int_dk_prf,
       CKSUMTYPE_HMAC_SHA1_DES3,
-      0 /*flags*/ },
+      0 /*flags*/, 112 },
 
     { ENCTYPE_DES_HMAC_SHA1,
       "des-hmac-sha1", { 0 }, "DES with HMAC/sha1",
@@ -99,7 +99,10 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_dk_string_to_key, k5_rand2key_des,
       NULL, /*PRF*/
       0,
-      ETYPE_WEAK },
+      ETYPE_WEAK, 56 },
+
+    /* rc4-hmac uses a 128-bit key, but due to weaknesses in the RC4 cipher, we
+     * consider its strength degraded and assign it an SSF value of 64. */
     { ENCTYPE_ARCFOUR_HMAC,
       "arcfour-hmac", { "rc4-hmac", "arcfour-hmac-md5" },
       "ArcFour with HMAC/md5",
@@ -110,7 +113,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
       k5_rand2key_direct, krb5int_arcfour_prf,
       CKSUMTYPE_HMAC_MD5_ARCFOUR,
-      0 /*flags*/ },
+      0 /*flags*/, 64 },
     { ENCTYPE_ARCFOUR_HMAC_EXP,
       "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" },
       "Exportable ArcFour with HMAC/md5",
@@ -121,7 +124,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
       k5_rand2key_direct, krb5int_arcfour_prf,
       CKSUMTYPE_HMAC_MD5_ARCFOUR,
-      ETYPE_WEAK
+      ETYPE_WEAK, 40
     },
 
     { ENCTYPE_AES128_CTS_HMAC_SHA1_96,
@@ -133,7 +136,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_aes_string_to_key, k5_rand2key_direct,
       krb5int_dk_prf,
       CKSUMTYPE_HMAC_SHA1_96_AES128,
-      0 /*flags*/ },
+      0 /*flags*/, 128 },
     { ENCTYPE_AES256_CTS_HMAC_SHA1_96,
       "aes256-cts-hmac-sha1-96", { "aes256-cts", "aes256-sha1" },
       "AES-256 CTS mode with 96-bit SHA-1 HMAC",
@@ -143,7 +146,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_aes_string_to_key, k5_rand2key_direct,
       krb5int_dk_prf,
       CKSUMTYPE_HMAC_SHA1_96_AES256,
-      0 /*flags*/ },
+      0 /*flags*/, 256 },
 
     { ENCTYPE_CAMELLIA128_CTS_CMAC,
       "camellia128-cts-cmac", { "camellia128-cts" },
@@ -155,7 +158,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_camellia_string_to_key, k5_rand2key_direct,
       krb5int_dk_cmac_prf,
       CKSUMTYPE_CMAC_CAMELLIA128,
-      0 /*flags*/ },
+      0 /*flags*/, 128 },
     { ENCTYPE_CAMELLIA256_CTS_CMAC,
       "camellia256-cts-cmac", { "camellia256-cts" },
       "Camellia-256 CTS mode with CMAC",
@@ -166,7 +169,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_camellia_string_to_key, k5_rand2key_direct,
       krb5int_dk_cmac_prf,
       CKSUMTYPE_CMAC_CAMELLIA256,
-      0 /*flags */ },
+      0 /*flags */, 256 },
 
     { ENCTYPE_AES128_CTS_HMAC_SHA256_128,
       "aes128-cts-hmac-sha256-128", { "aes128-sha2" },
@@ -177,7 +180,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_aes2_string_to_key, k5_rand2key_direct,
       krb5int_aes2_prf,
       CKSUMTYPE_HMAC_SHA256_128_AES128,
-      0 /*flags*/ },
+      0 /*flags*/, 128 },
     { ENCTYPE_AES256_CTS_HMAC_SHA384_192,
       "aes256-cts-hmac-sha384-192", { "aes256-sha2" },
       "AES-256 CTS mode with 192-bit SHA-384 HMAC",
@@ -187,7 +190,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
       krb5int_aes2_string_to_key, k5_rand2key_direct,
       krb5int_aes2_prf,
       CKSUMTYPE_HMAC_SHA384_192_AES256,
-      0 /*flags*/ },
+      0 /*flags*/, 256 },
 };
 
 const int krb5int_enctypes_length =
index 447e456444534b0452e2e99b52345e6e5e73023a..82eb5f30c0315721d7ba8fa791309319a5111423 100644 (file)
@@ -108,3 +108,4 @@ krb5int_nfold
 k5_allow_weak_pbkdf2iter
 krb5_c_prfplus
 krb5_c_derive_prfplus
+k5_enctype_to_ssf
index 9ad44216d05e97bce885acac91d52c1437e39eb2..9d3a7e73673691f848013dbf70164d9a37eb64af 100644 (file)
@@ -575,4 +575,15 @@ gss_import_cred(
 }
 #endif
 
+/*
+ * When used with gss_inquire_sec_context_by_oid(), return a buffer set with
+ * the first member containing an unsigned 32-bit integer in network byte
+ * order.  This is the Security Strength Factor (SSF) associated with the
+ * secure channel established by the security context.  NOTE: This value is
+ * made available solely as an indication for use by APIs like Cyrus SASL that
+ * classify the strength of a secure channel via this number.  The strength of
+ * a channel cannot necessarily be represented by a simple number.
+ */
+GSS_DLLIMP extern gss_OID GSS_C_SEC_CONTEXT_SASL_SSF;
+
 #endif /* GSSAPI_EXT_H_ */
index 5496aa33582c990cc13d2f0343c8b2e45efd4a61..fa144c2bf9ccff910112c862f1c755290409e770 100644 (file)
@@ -157,6 +157,13 @@ static const gss_OID_desc const_oids[] = {
     {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x19"},
     {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1a"},
     {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1b"},
+
+    /*
+     * GSS_SEC_CONTEXT_SASL_SSF_OID 1.2.840.113554.1.2.2.5.15
+     * iso(1) member-body(2) United States(840) mit(113554)
+     * infosys(1) gssapi(2) krb5(2) krb5-gssapi-ext(5) sasl-ssf(15)
+     */
+    {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f"},
 };
 
 /* Here are the constants which point to the static structure above.
@@ -218,6 +225,8 @@ GSS_DLLIMP gss_const_OID GSS_C_MA_PFS               = oids+33;
 GSS_DLLIMP gss_const_OID GSS_C_MA_COMPRESS          = oids+34;
 GSS_DLLIMP gss_const_OID GSS_C_MA_CTX_TRANS         = oids+35;
 
+GSS_DLLIMP gss_OID GSS_C_SEC_CONTEXT_SASL_SSF = oids+36;
+
 static gss_OID_set_desc gss_ma_known_attrs_desc = { 27, oids+9 };
 gss_OID_set gss_ma_known_attrs = &gss_ma_known_attrs_desc;
 
index cd65966b9c52d0e19612f6af55d2009649111b1c..e92be88b473028f5b22db22c68de3303c24333f0 100644 (file)
@@ -1144,6 +1144,12 @@ gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *,
                                               const gss_OID,
                                               gss_buffer_set_t *);
 
+#define GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH 11
+#define GET_SEC_CONTEXT_SASL_SSF_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f"
+OM_uint32
+gss_krb5int_sec_context_sasl_ssf(OM_uint32 *, const gss_ctx_id_t,
+                                 const gss_OID, gss_buffer_set_t *);
+
 #define GSS_KRB5_IMPORT_CRED_OID_LENGTH 11
 #define GSS_KRB5_IMPORT_CRED_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0d"
 
index e12b66227802adbcf81d591d3a8941733152d40f..43930dd61aa69221df48c620e8f3030ab457a2f7 100644 (file)
@@ -357,6 +357,10 @@ static struct {
     {
         {GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID},
         gss_krb5int_extract_authtime_from_sec_context
+    },
+    {
+        {GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH, GET_SEC_CONTEXT_SASL_SSF_OID},
+        gss_krb5int_sec_context_sasl_ssf
     }
 };
 
index 9024b3c7ea9cc8d9c82ed876aa1a09f369ab22a6..d2e466e60a158804c698c02e5970a846d21ab1e6 100644 (file)
@@ -310,3 +310,30 @@ gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *minor_status,
 
     return generic_gss_add_buffer_set_member(minor_status, &rep, data_set);
 }
+
+OM_uint32
+gss_krb5int_sec_context_sasl_ssf(OM_uint32 *minor_status,
+                                 const gss_ctx_id_t context_handle,
+                                 const gss_OID desired_object,
+                                 gss_buffer_set_t *data_set)
+{
+    krb5_gss_ctx_id_rec *ctx;
+    krb5_key key;
+    krb5_error_code code;
+    gss_buffer_desc ssfbuf;
+    unsigned int ssf;
+    uint8_t buf[4];
+
+    ctx = (krb5_gss_ctx_id_rec *)context_handle;
+    key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey : ctx->subkey;
+
+    code = k5_enctype_to_ssf(key->keyblock.enctype, &ssf);
+    if (code)
+        return GSS_S_FAILURE;
+
+    store_32_be(ssf, buf);
+    ssfbuf.value = buf;
+    ssfbuf.length = sizeof(buf);
+
+    return generic_gss_add_buffer_set_member(minor_status, &ssfbuf, data_set);
+}
index 16d38e94b99de7f48b74f8f2a59152d30211eb80..b07f69fd157292d6881f2d173a50c69ac800e4ae 100644 (file)
@@ -38,6 +38,7 @@ GSS_C_MA_CBINDINGS
 GSS_C_MA_PFS
 GSS_C_MA_COMPRESS
 GSS_C_MA_CTX_TRANS
+GSS_C_SEC_CONTEXT_SASL_SSF
 gss_accept_sec_context
 gss_acquire_cred
 gss_acquire_cred_with_password
index 4bf8c9520286bf11c6b6fe55de69bbc1d4b18c09..842f3d52f3cdbcf034638824be74edf46573e912 100644 (file)
@@ -184,3 +184,4 @@ EXPORTS
        GSS_KRB5_CRED_NO_CI_FLAGS_X                     @147    DATA
 ; Added in 1.16
        GSS_KRB5_GET_CRED_IMPERSONATOR                  @148    DATA
+       GSS_C_SEC_CONTEXT_SASL_SSF                      @149    DATA
index e5b560dfcb26ab31346c2b2a3fa0cab723069f37..f7b428e1692868304d333bda4b3ccc042e9ec8db 100644 (file)
@@ -470,3 +470,6 @@ EXPORTS
        krb5_get_init_creds_opt_set_pac_request         @435
        krb5int_trace                                   @436 ; PRIVATE GSSAPI
        krb5_expand_hostname                            @437
+
+; new in 1.16
+       k5_enctype_to_ssf                               @438 ; PRIVATE GSSAPI
index a2ad18f47aba553c25ad75c10a8a5f201530722b..3fd31e2f8cd50f2a30a8822f09a7b233fef96099 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "k5-int.h"
 #include "common.h"
+#include "gssapi_ext.h"
 
 /*
  * This test program establishes contexts with the krb5 mech, the default
@@ -86,6 +87,9 @@ main(int argc, char *argv[])
     gss_krb5_lucid_context_v1_t *ilucid, *alucid;
     gss_krb5_rfc1964_keydata_t *i1964, *a1964;
     gss_krb5_cfx_keydata_t *icfx, *acfx;
+    gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET;
+    gss_OID ssf_oid = GSS_C_SEC_CONTEXT_SASL_SSF;
+    unsigned int ssf;
     size_t count;
     void *lptr;
     int c;
@@ -139,6 +143,16 @@ main(int argc, char *argv[])
     establish_contexts(&mech_krb5, icred, acred, tname, flags, &ictx, &actx,
                        NULL, NULL, NULL);
 
+    /* Query the SSF value and range-check the result. */
+    major = gss_inquire_sec_context_by_oid(&minor, ictx, ssf_oid, &bufset);
+    check_gsserr("gss_inquire_sec_context_by_oid(ssf)", major, minor);
+    if (bufset->elements[0].length != 4)
+        errout("SSF buffer has unexpected length");
+    ssf = load_32_be(bufset->elements[0].value);
+    if (ssf < 56 || ssf > 256)
+        errout("SSF value not within acceptable range (56-256)");
+    (void)gss_release_buffer_set(&minor, &bufset);
+
     /* Export to lucid contexts. */
     major = gss_krb5_export_lucid_sec_context(&minor, &ictx, 1, &lptr);
     check_gsserr("gss_export_lucid_sec_context(initiator)", major, minor);