Blame SOURCES/Add-support-to-query-the-SSF-of-a-GSS-context.patch

963210
From 1f7d42707585e552842455857070fff8957fcb7c Mon Sep 17 00:00:00 2001
963210
From: Simo Sorce <simo@redhat.com>
963210
Date: Thu, 30 Mar 2017 11:27:09 -0400
963210
Subject: [PATCH] Add support to query the SSF of a GSS context
963210
963210
Cyrus SASL provides a Security Strength Factor number to assess the
963210
relative "strength" of the negotiated mechanism, and applications
963210
sometimes make access control decisions based on it.
963210
963210
Add a call that allows us to query the mechanism that established the
963210
GSS security context to ask what is the current SSF, based on the
963210
enctype of the session key.
963210
963210
ticket: 8569 (new)
963210
(cherry picked from commit 7feb7da54c0321b5a3eeb6c3797846a3cf7eda28)
963210
[rharwood@redhat.com: stub out GSS_KRB5_GET_CRED_IMPERSONATOR]
963210
---
963210
 src/include/k5-int.h                    |  1 +
963210
 src/lib/crypto/krb/crypto_int.h         |  1 +
167778
 src/lib/crypto/krb/enctype_util.c       | 16 ++++++++++++
167778
 src/lib/crypto/krb/etypes.c             | 33 ++++++++++++++-----------
963210
 src/lib/crypto/libk5crypto.exports      |  1 +
167778
 src/lib/gssapi/generic/gssapi_ext.h     | 11 +++++++++
167778
 src/lib/gssapi/generic/gssapi_generic.c |  9 +++++++
167778
 src/lib/gssapi/krb5/gssapiP_krb5.h      |  6 +++++
167778
 src/lib/gssapi/krb5/gssapi_krb5.c       |  4 +++
167778
 src/lib/gssapi/krb5/inq_context.c       | 27 ++++++++++++++++++++
963210
 src/lib/gssapi/libgssapi_krb5.exports   |  1 +
963210
 src/lib/gssapi32.def                    |  3 +++
963210
 src/lib/krb5_32.def                     |  3 +++
167778
 src/tests/gssapi/t_enctypes.c           | 14 +++++++++++
963210
 14 files changed, 115 insertions(+), 15 deletions(-)
963210
963210
diff --git a/src/include/k5-int.h b/src/include/k5-int.h
963210
index cea644d0a..06ca2b66d 100644
963210
--- a/src/include/k5-int.h
963210
+++ b/src/include/k5-int.h
963210
@@ -2114,6 +2114,7 @@ krb5_get_tgs_ktypes(krb5_context, krb5_const_principal, krb5_enctype **);
963210
 krb5_boolean krb5_is_permitted_enctype(krb5_context, krb5_enctype);
963210
 
963210
 krb5_boolean KRB5_CALLCONV krb5int_c_weak_enctype(krb5_enctype);
963210
+krb5_error_code k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out);
963210
 
963210
 krb5_error_code krb5_kdc_rep_decrypt_proc(krb5_context, const krb5_keyblock *,
963210
                                           krb5_const_pointer, krb5_kdc_rep *);
963210
diff --git a/src/lib/crypto/krb/crypto_int.h b/src/lib/crypto/krb/crypto_int.h
963210
index d75b49c69..e5099291e 100644
963210
--- a/src/lib/crypto/krb/crypto_int.h
963210
+++ b/src/lib/crypto/krb/crypto_int.h
963210
@@ -111,6 +111,7 @@ struct krb5_keytypes {
963210
     prf_func prf;
963210
     krb5_cksumtype required_ctype;
963210
     krb5_flags flags;
963210
+    unsigned int ssf;
963210
 };
963210
 
963210
 #define ETYPE_WEAK 1
963210
diff --git a/src/lib/crypto/krb/enctype_util.c b/src/lib/crypto/krb/enctype_util.c
963210
index 0ed74bd6e..b1b40e7ec 100644
963210
--- a/src/lib/crypto/krb/enctype_util.c
963210
+++ b/src/lib/crypto/krb/enctype_util.c
963210
@@ -131,3 +131,19 @@ krb5_enctype_to_name(krb5_enctype enctype, krb5_boolean shortest,
963210
         return ENOMEM;
963210
     return 0;
963210
 }
963210
+
963210
+/* The security of a mechanism cannot be summarized with a simple integer
963210
+ * value, but we provide a per-enctype value for Cyrus SASL's SSF. */
963210
+krb5_error_code
963210
+k5_enctype_to_ssf(krb5_enctype enctype, unsigned int *ssf_out)
963210
+{
963210
+    const struct krb5_keytypes *ktp;
963210
+
963210
+    *ssf_out = 0;
963210
+
963210
+    ktp = find_enctype(enctype);
963210
+    if (ktp == NULL)
963210
+        return EINVAL;
963210
+    *ssf_out = ktp->ssf;
963210
+    return 0;
963210
+}
963210
diff --git a/src/lib/crypto/krb/etypes.c b/src/lib/crypto/krb/etypes.c
963210
index 0e5e977d4..53d4a5c79 100644
963210
--- a/src/lib/crypto/krb/etypes.c
963210
+++ b/src/lib/crypto/krb/etypes.c
963210
@@ -42,7 +42,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_des_string_to_key, k5_rand2key_des,
963210
       krb5int_des_prf,
963210
       CKSUMTYPE_RSA_MD5_DES,
963210
-      ETYPE_WEAK },
963210
+      ETYPE_WEAK, 56 },
963210
     { ENCTYPE_DES_CBC_MD4,
963210
       "des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4",
963210
       &krb5int_enc_des, &krb5int_hash_md4,
963210
@@ -51,7 +51,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_des_string_to_key, k5_rand2key_des,
963210
       krb5int_des_prf,
963210
       CKSUMTYPE_RSA_MD4_DES,
963210
-      ETYPE_WEAK },
963210
+      ETYPE_WEAK, 56 },
963210
     { ENCTYPE_DES_CBC_MD5,
963210
       "des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5",
963210
       &krb5int_enc_des, &krb5int_hash_md5,
963210
@@ -60,7 +60,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_des_string_to_key, k5_rand2key_des,
963210
       krb5int_des_prf,
963210
       CKSUMTYPE_RSA_MD5_DES,
963210
-      ETYPE_WEAK },
963210
+      ETYPE_WEAK, 56 },
963210
     { ENCTYPE_DES_CBC_RAW,
963210
       "des-cbc-raw", { 0 }, "DES cbc mode raw",
963210
       &krb5int_enc_des, NULL,
963210
@@ -69,7 +69,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_des_string_to_key, k5_rand2key_des,
963210
       krb5int_des_prf,
963210
       0,
963210
-      ETYPE_WEAK },
963210
+      ETYPE_WEAK, 56 },
963210
     { ENCTYPE_DES3_CBC_RAW,
963210
       "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw",
963210
       &krb5int_enc_des3, NULL,
963210
@@ -78,7 +78,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_dk_string_to_key, k5_rand2key_des3,
963210
       NULL, /*PRF*/
963210
       0,
963210
-      ETYPE_WEAK },
963210
+      ETYPE_WEAK, 112 },
963210
 
963210
     { ENCTYPE_DES3_CBC_SHA1,
963210
       "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" },
963210
@@ -89,7 +89,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_dk_string_to_key, k5_rand2key_des3,
963210
       krb5int_dk_prf,
963210
       CKSUMTYPE_HMAC_SHA1_DES3,
963210
-      0 /*flags*/ },
963210
+      0 /*flags*/, 112 },
963210
 
963210
     { ENCTYPE_DES_HMAC_SHA1,
963210
       "des-hmac-sha1", { 0 }, "DES with HMAC/sha1",
963210
@@ -99,7 +99,10 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_dk_string_to_key, k5_rand2key_des,
963210
       NULL, /*PRF*/
963210
       0,
963210
-      ETYPE_WEAK },
963210
+      ETYPE_WEAK, 56 },
963210
+
963210
+    /* rc4-hmac uses a 128-bit key, but due to weaknesses in the RC4 cipher, we
963210
+     * consider its strength degraded and assign it an SSF value of 64. */
963210
     { ENCTYPE_ARCFOUR_HMAC,
963210
       "arcfour-hmac", { "rc4-hmac", "arcfour-hmac-md5" },
963210
       "ArcFour with HMAC/md5",
963210
@@ -110,7 +113,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
963210
       k5_rand2key_direct, krb5int_arcfour_prf,
963210
       CKSUMTYPE_HMAC_MD5_ARCFOUR,
963210
-      0 /*flags*/ },
963210
+      0 /*flags*/, 64 },
963210
     { ENCTYPE_ARCFOUR_HMAC_EXP,
963210
       "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" },
963210
       "Exportable ArcFour with HMAC/md5",
963210
@@ -121,7 +124,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_arcfour_decrypt, krb5int_arcfour_string_to_key,
963210
       k5_rand2key_direct, krb5int_arcfour_prf,
963210
       CKSUMTYPE_HMAC_MD5_ARCFOUR,
963210
-      ETYPE_WEAK
963210
+      ETYPE_WEAK, 40
963210
     },
963210
 
963210
     { ENCTYPE_AES128_CTS_HMAC_SHA1_96,
963210
@@ -133,7 +136,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_aes_string_to_key, k5_rand2key_direct,
963210
       krb5int_dk_prf,
963210
       CKSUMTYPE_HMAC_SHA1_96_AES128,
963210
-      0 /*flags*/ },
963210
+      0 /*flags*/, 128 },
963210
     { ENCTYPE_AES256_CTS_HMAC_SHA1_96,
963210
       "aes256-cts-hmac-sha1-96", { "aes256-cts", "aes256-sha1" },
963210
       "AES-256 CTS mode with 96-bit SHA-1 HMAC",
963210
@@ -143,7 +146,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_aes_string_to_key, k5_rand2key_direct,
963210
       krb5int_dk_prf,
963210
       CKSUMTYPE_HMAC_SHA1_96_AES256,
963210
-      0 /*flags*/ },
963210
+      0 /*flags*/, 256 },
963210
 
963210
     { ENCTYPE_CAMELLIA128_CTS_CMAC,
963210
       "camellia128-cts-cmac", { "camellia128-cts" },
963210
@@ -155,7 +158,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_camellia_string_to_key, k5_rand2key_direct,
963210
       krb5int_dk_cmac_prf,
963210
       CKSUMTYPE_CMAC_CAMELLIA128,
963210
-      0 /*flags*/ },
963210
+      0 /*flags*/, 128 },
963210
     { ENCTYPE_CAMELLIA256_CTS_CMAC,
963210
       "camellia256-cts-cmac", { "camellia256-cts" },
963210
       "Camellia-256 CTS mode with CMAC",
963210
@@ -166,7 +169,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_camellia_string_to_key, k5_rand2key_direct,
963210
       krb5int_dk_cmac_prf,
963210
       CKSUMTYPE_CMAC_CAMELLIA256,
963210
-      0 /*flags */ },
963210
+      0 /*flags */, 256 },
963210
 
963210
     { ENCTYPE_AES128_CTS_HMAC_SHA256_128,
963210
       "aes128-cts-hmac-sha256-128", { "aes128-sha2" },
963210
@@ -177,7 +180,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_aes2_string_to_key, k5_rand2key_direct,
963210
       krb5int_aes2_prf,
963210
       CKSUMTYPE_HMAC_SHA256_128_AES128,
963210
-      0 /*flags*/ },
963210
+      0 /*flags*/, 128 },
963210
     { ENCTYPE_AES256_CTS_HMAC_SHA384_192,
963210
       "aes256-cts-hmac-sha384-192", { "aes256-sha2" },
963210
       "AES-256 CTS mode with 192-bit SHA-384 HMAC",
963210
@@ -187,7 +190,7 @@ const struct krb5_keytypes krb5int_enctypes_list[] = {
963210
       krb5int_aes2_string_to_key, k5_rand2key_direct,
963210
       krb5int_aes2_prf,
963210
       CKSUMTYPE_HMAC_SHA384_192_AES256,
963210
-      0 /*flags*/ },
963210
+      0 /*flags*/, 256 },
963210
 };
963210
 
963210
 const int krb5int_enctypes_length =
963210
diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports
963210
index 447e45644..82eb5f30c 100644
963210
--- a/src/lib/crypto/libk5crypto.exports
963210
+++ b/src/lib/crypto/libk5crypto.exports
963210
@@ -108,3 +108,4 @@ krb5int_nfold
963210
 k5_allow_weak_pbkdf2iter
963210
 krb5_c_prfplus
963210
 krb5_c_derive_prfplus
963210
+k5_enctype_to_ssf
963210
diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h
963210
index 9ad44216d..9d3a7e736 100644
963210
--- a/src/lib/gssapi/generic/gssapi_ext.h
963210
+++ b/src/lib/gssapi/generic/gssapi_ext.h
963210
@@ -575,4 +575,15 @@ gss_import_cred(
963210
 }
963210
 #endif
963210
 
963210
+/*
963210
+ * When used with gss_inquire_sec_context_by_oid(), return a buffer set with
963210
+ * the first member containing an unsigned 32-bit integer in network byte
963210
+ * order.  This is the Security Strength Factor (SSF) associated with the
963210
+ * secure channel established by the security context.  NOTE: This value is
963210
+ * made available solely as an indication for use by APIs like Cyrus SASL that
963210
+ * classify the strength of a secure channel via this number.  The strength of
963210
+ * a channel cannot necessarily be represented by a simple number.
963210
+ */
963210
+GSS_DLLIMP extern gss_OID GSS_C_SEC_CONTEXT_SASL_SSF;
963210
+
963210
 #endif /* GSSAPI_EXT_H_ */
963210
diff --git a/src/lib/gssapi/generic/gssapi_generic.c b/src/lib/gssapi/generic/gssapi_generic.c
963210
index 5496aa335..fa144c2bf 100644
963210
--- a/src/lib/gssapi/generic/gssapi_generic.c
963210
+++ b/src/lib/gssapi/generic/gssapi_generic.c
963210
@@ -157,6 +157,13 @@ static const gss_OID_desc const_oids[] = {
963210
     {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x19"},
963210
     {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1a"},
963210
     {7, (void *)"\x2b\x06\x01\x05\x05\x0d\x1b"},
963210
+
963210
+    /*
963210
+     * GSS_SEC_CONTEXT_SASL_SSF_OID 1.2.840.113554.1.2.2.5.15
963210
+     * iso(1) member-body(2) United States(840) mit(113554)
963210
+     * infosys(1) gssapi(2) krb5(2) krb5-gssapi-ext(5) sasl-ssf(15)
963210
+     */
963210
+    {11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f"},
963210
 };
963210
 
963210
 /* Here are the constants which point to the static structure above.
963210
@@ -218,6 +225,8 @@ GSS_DLLIMP gss_const_OID GSS_C_MA_PFS               = oids+33;
963210
 GSS_DLLIMP gss_const_OID GSS_C_MA_COMPRESS          = oids+34;
963210
 GSS_DLLIMP gss_const_OID GSS_C_MA_CTX_TRANS         = oids+35;
963210
 
963210
+GSS_DLLIMP gss_OID GSS_C_SEC_CONTEXT_SASL_SSF = oids+36;
963210
+
963210
 static gss_OID_set_desc gss_ma_known_attrs_desc = { 27, oids+9 };
963210
 gss_OID_set gss_ma_known_attrs = &gss_ma_known_attrs_desc;
963210
 
963210
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
963210
index d7bdef7e2..ef030707e 100644
963210
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
963210
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
963210
@@ -1144,6 +1144,12 @@ gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *,
963210
                                               const gss_OID,
963210
                                               gss_buffer_set_t *);
963210
 
963210
+#define GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH 11
963210
+#define GET_SEC_CONTEXT_SASL_SSF_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0f"
963210
+OM_uint32
963210
+gss_krb5int_sec_context_sasl_ssf(OM_uint32 *, const gss_ctx_id_t,
963210
+                                 const gss_OID, gss_buffer_set_t *);
963210
+
963210
 #define GSS_KRB5_IMPORT_CRED_OID_LENGTH 11
963210
 #define GSS_KRB5_IMPORT_CRED_OID "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0d"
963210
 
963210
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
963210
index 99092ccab..de4131980 100644
963210
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
963210
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
963210
@@ -352,6 +352,10 @@ static struct {
963210
     {
963210
         {GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID_LENGTH, GSS_KRB5_EXTRACT_AUTHTIME_FROM_SEC_CONTEXT_OID},
963210
         gss_krb5int_extract_authtime_from_sec_context
963210
+    },
963210
+    {
963210
+        {GET_SEC_CONTEXT_SASL_SSF_OID_LENGTH, GET_SEC_CONTEXT_SASL_SSF_OID},
963210
+        gss_krb5int_sec_context_sasl_ssf
963210
     }
963210
 };
963210
 
963210
diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c
963210
index 9024b3c7e..d2e466e60 100644
963210
--- a/src/lib/gssapi/krb5/inq_context.c
963210
+++ b/src/lib/gssapi/krb5/inq_context.c
963210
@@ -310,3 +310,30 @@ gss_krb5int_extract_authtime_from_sec_context(OM_uint32 *minor_status,
963210
 
963210
     return generic_gss_add_buffer_set_member(minor_status, &rep, data_set);
963210
 }
963210
+
963210
+OM_uint32
963210
+gss_krb5int_sec_context_sasl_ssf(OM_uint32 *minor_status,
963210
+                                 const gss_ctx_id_t context_handle,
963210
+                                 const gss_OID desired_object,
963210
+                                 gss_buffer_set_t *data_set)
963210
+{
963210
+    krb5_gss_ctx_id_rec *ctx;
963210
+    krb5_key key;
963210
+    krb5_error_code code;
963210
+    gss_buffer_desc ssfbuf;
963210
+    unsigned int ssf;
963210
+    uint8_t buf[4];
963210
+
963210
+    ctx = (krb5_gss_ctx_id_rec *)context_handle;
963210
+    key = ctx->have_acceptor_subkey ? ctx->acceptor_subkey : ctx->subkey;
963210
+
963210
+    code = k5_enctype_to_ssf(key->keyblock.enctype, &ssf;;
963210
+    if (code)
963210
+        return GSS_S_FAILURE;
963210
+
963210
+    store_32_be(ssf, buf);
963210
+    ssfbuf.value = buf;
963210
+    ssfbuf.length = sizeof(buf);
963210
+
963210
+    return generic_gss_add_buffer_set_member(minor_status, &ssfbuf, data_set);
963210
+}
963210
diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports
963210
index 9facb3f42..936540e41 100644
963210
--- a/src/lib/gssapi/libgssapi_krb5.exports
963210
+++ b/src/lib/gssapi/libgssapi_krb5.exports
963210
@@ -37,6 +37,7 @@ GSS_C_MA_CBINDINGS
963210
 GSS_C_MA_PFS
963210
 GSS_C_MA_COMPRESS
963210
 GSS_C_MA_CTX_TRANS
963210
+GSS_C_SEC_CONTEXT_SASL_SSF
963210
 gss_accept_sec_context
963210
 gss_acquire_cred
963210
 gss_acquire_cred_with_password
963210
diff --git a/src/lib/gssapi32.def b/src/lib/gssapi32.def
963210
index 362b9bce8..dff057754 100644
963210
--- a/src/lib/gssapi32.def
963210
+++ b/src/lib/gssapi32.def
963210
@@ -182,3 +182,6 @@ EXPORTS
963210
 	gss_verify_mic_iov				@146
963210
 ; Added in 1.14
963210
 	GSS_KRB5_CRED_NO_CI_FLAGS_X			@147	DATA
963210
+; Added in 1.16
963210
+;	GSS_KRB5_GET_CRED_IMPERSONATOR			@148	DATA
963210
+	GSS_C_SEC_CONTEXT_SASL_SSF			@149	DATA
963210
diff --git a/src/lib/krb5_32.def b/src/lib/krb5_32.def
963210
index e5b560dfc..f7b428e16 100644
963210
--- a/src/lib/krb5_32.def
963210
+++ b/src/lib/krb5_32.def
963210
@@ -470,3 +470,6 @@ EXPORTS
963210
 	krb5_get_init_creds_opt_set_pac_request		@435
963210
 	krb5int_trace					@436 ; PRIVATE GSSAPI
963210
 	krb5_expand_hostname				@437
963210
+
963210
+; new in 1.16
963210
+	k5_enctype_to_ssf				@438 ; PRIVATE GSSAPI
963210
diff --git a/src/tests/gssapi/t_enctypes.c b/src/tests/gssapi/t_enctypes.c
963210
index a2ad18f47..3fd31e2f8 100644
963210
--- a/src/tests/gssapi/t_enctypes.c
963210
+++ b/src/tests/gssapi/t_enctypes.c
963210
@@ -32,6 +32,7 @@
963210
 
963210
 #include "k5-int.h"
963210
 #include "common.h"
963210
+#include "gssapi_ext.h"
963210
 
963210
 /*
963210
  * This test program establishes contexts with the krb5 mech, the default
963210
@@ -86,6 +87,9 @@ main(int argc, char *argv[])
963210
     gss_krb5_lucid_context_v1_t *ilucid, *alucid;
963210
     gss_krb5_rfc1964_keydata_t *i1964, *a1964;
963210
     gss_krb5_cfx_keydata_t *icfx, *acfx;
963210
+    gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET;
963210
+    gss_OID ssf_oid = GSS_C_SEC_CONTEXT_SASL_SSF;
963210
+    unsigned int ssf;
963210
     size_t count;
963210
     void *lptr;
963210
     int c;
963210
@@ -139,6 +143,16 @@ main(int argc, char *argv[])
963210
     establish_contexts(&mech_krb5, icred, acred, tname, flags, &ictx, &actx,
963210
                        NULL, NULL, NULL);
963210
 
963210
+    /* Query the SSF value and range-check the result. */
963210
+    major = gss_inquire_sec_context_by_oid(&minor, ictx, ssf_oid, &bufset);
963210
+    check_gsserr("gss_inquire_sec_context_by_oid(ssf)", major, minor);
963210
+    if (bufset->elements[0].length != 4)
963210
+        errout("SSF buffer has unexpected length");
963210
+    ssf = load_32_be(bufset->elements[0].value);
963210
+    if (ssf < 56 || ssf > 256)
963210
+        errout("SSF value not within acceptable range (56-256)");
963210
+    (void)gss_release_buffer_set(&minor, &bufset);
963210
+
963210
     /* Export to lucid contexts. */
963210
     major = gss_krb5_export_lucid_sec_context(&minor, &ictx, 1, &lptr);
963210
     check_gsserr("gss_export_lucid_sec_context(initiator)", major, minor);