gss_iov_buffer_desc *, /* iov */
int); /* iov_count */
+typedef struct gss_context_stream_sizes_struct {
+ size_t header;
+ size_t trailer;
+ size_t max_msg_size;
+ size_t buffers;
+ size_t blocksize;
+} gss_context_stream_sizes;
+
+GSS_DLLIMP extern gss_OID GSS_C_ATTR_STREAM_SIZES;
+
+OM_uint32 KRB5_CALLCONV gss_context_query_attributes
+(
+ OM_uint32 *, /* minor_status */
+ const gss_ctx_id_t, /* context_handle */
+ const gss_OID, /* attribute */
+ void *, /* data */
+ size_t /* len */
+);
+
/*
* Protocol transition
*/
/* GSS_C_INQ_SSPI_SESSION_KEY 1.2.840.113554.1.2.2.5.5 */
{11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05"},
+ {10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"},
};
/* Here are the constants which point to the static structure above.
gss_OID gss_nt_exported_name = oids+6;
GSS_DLLIMP gss_OID GSS_C_INQ_SSPI_SESSION_KEY = oids+7;
+GSS_DLLIMP gss_OID GSS_C_ATTR_STREAM_SIZES = oids+8;
const gss_OID,
gss_buffer_set_t *);
+#define GSS_KRB5_CONTEXT_ATTR_STREAM_SIZES_LENGTH 10
+#define GSS_KRB5_CONTEXT_ATTR_STREAM_SIZES "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03"
+
+OM_uint32
+gss_krb5int_context_query_stream_sizes(OM_uint32 *minor_status,
+ const gss_ctx_id_t context_handle,
+ const gss_OID desired_oid,
+ void *data,
+ size_t len);
+
#ifdef _GSS_STATIC_LINK
int gss_krb5int_lib_init(void);
void gss_krb5int_lib_fini(void);
return GSS_S_UNAVAILABLE;
}
+/*
+ * gss_context_query_attributes() methods
+ */
+static struct {
+ gss_OID_desc oid;
+ OM_uint32 (*func)(OM_uint32 *, const gss_ctx_id_t, const gss_OID, void *, size_t);
+} krb5_gss_context_query_attributes_ops[] = {
+ {
+ {GSS_KRB5_CONTEXT_ATTR_STREAM_SIZES_LENGTH, GSS_KRB5_CONTEXT_ATTR_STREAM_SIZES},
+ gss_krb5int_context_query_stream_sizes
+ },
+};
+
+static OM_uint32
+krb5_gss_context_query_attributes(OM_uint32 *minor_status,
+ const gss_ctx_id_t context_handle,
+ const gss_OID desired_object,
+ void *data,
+ size_t len)
+{
+ krb5_gss_ctx_id_rec *ctx;
+ size_t i;
+
+ if (minor_status == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ *minor_status = 0;
+
+ if (desired_object == GSS_C_NO_OID)
+ return GSS_S_CALL_INACCESSIBLE_READ;
+
+ if (data == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ memset(data, 0, len);
+
+ if (!kg_validate_ctx_id(context_handle))
+ return GSS_S_NO_CONTEXT;
+
+ ctx = (krb5_gss_ctx_id_rec *) context_handle;
+
+ if (!ctx->established)
+ return GSS_S_NO_CONTEXT;
+
+ for (i = 0; i < sizeof(krb5_gss_context_query_attributes_ops)/
+ sizeof(krb5_gss_context_query_attributes_ops[0]); i++) {
+ if (g_OID_prefix_equal(desired_object, &krb5_gss_context_query_attributes_ops[i].oid)) {
+ return (*krb5_gss_context_query_attributes_ops[i].func)(minor_status,
+ context_handle,
+ desired_object,
+ data,
+ len);
+ }
+ }
+
+ *minor_status = EINVAL;
+
+ return GSS_S_UNAVAILABLE;
+}
+
static struct gss_config krb5_mechanism = {
{ GSS_MECH_KRB5_OID_LENGTH, GSS_MECH_KRB5_OID },
NULL,
krb5_gss_map_name_to_any,
krb5_gss_release_any_name_mapping,
krb5_gss_pseudo_random,
+ krb5_gss_context_query_attributes,
};
return generic_gss_add_buffer_set_member(minor_status, &rep, data_set);
}
+
+OM_uint32
+gss_krb5int_context_query_stream_sizes(OM_uint32 *minor_status,
+ const gss_ctx_id_t context_handle,
+ const gss_OID desired_oid,
+ void *data,
+ size_t len)
+{
+ const krb5_gss_ctx_id_t ctx = (const krb5_gss_ctx_id_t)context_handle;
+ gss_context_stream_sizes *sizes = (gss_context_stream_sizes *)data;
+ gss_iov_buffer_desc iov[4];
+ OM_uint32 major_status;
+ OM_uint32 max_input_size;
+
+ if (len != sizeof(*sizes)) {
+ *minor_status = EINVAL;
+ return GSS_S_FAILURE;
+ }
+
+ iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
+ iov[1].type = GSS_IOV_BUFFER_TYPE_TRAILER;
+ iov[2].type = GSS_IOV_BUFFER_TYPE_DATA;
+ iov[2].buffer.length = 1;
+ iov[2].buffer.value = "";
+ iov[3].type = GSS_IOV_BUFFER_TYPE_PADDING;
+
+ major_status = kg_seal_iov_length(minor_status, context_handle,
+ 1, GSS_C_QOP_DEFAULT, NULL,
+ iov, sizeof(iov));
+ if (GSS_ERROR(major_status))
+ return major_status;
+
+ sizes->header = iov[0].buffer.length;
+ sizes->trailer = iov[1].buffer.length;
+ sizes->buffers = 0;
+ sizes->blocksize = 1 + iov[3].buffer.length;
+
+ major_status = krb5_gss_wrap_size_limit(minor_status, context_handle,
+ 1, GSS_C_QOP_DEFAULT,
+ (OM_uint32)-1, &max_input_size);
+ if (GSS_ERROR(major_status))
+ return major_status;
+
+ sizes->max_msg_size = max_input_size;
+
+ return GSS_S_COMPLETE;
+}
+
+GSS_C_ATTR_STREAM_SIZES
GSS_C_INQ_SSPI_SESSION_KEY
GSS_C_NT_ANONYMOUS
GSS_C_NT_EXPORT_NAME
gss_canonicalize_name
gss_compare_name
gss_complete_auth_token
+gss_context_query_attributes
gss_context_time
gss_create_empty_buffer_set
gss_create_empty_oid_set
GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_release_any_name_mapping);
/* RFC 4401 (introduced in 1.8) */
GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_pseudo_random);
+ GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_context_query_attributes);
assert(mech_type != GSS_C_NO_OID);
return GSS_S_BAD_MECH;
}
+
+OM_uint32 KRB5_CALLCONV
+gss_context_query_attributes (OM_uint32 *minor_status,
+ const gss_ctx_id_t context_handle,
+ const gss_OID desired_object,
+ void *data,
+ size_t len)
+{
+ OM_uint32 status;
+ gss_union_ctx_id_t ctx;
+ gss_mechanism mech;
+
+ if (minor_status == NULL)
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+
+ if (context_handle == GSS_C_NO_CONTEXT)
+ return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_NO_CONTEXT;
+
+ /*
+ * select the approprate underlying mechanism routine and
+ * call it.
+ */
+
+ ctx = (gss_union_ctx_id_t) context_handle;
+ mech = gssint_get_mechanism (ctx->mech_type);
+
+ if (mech != NULL) {
+ if (mech->gss_inquire_sec_context_by_oid != NULL) {
+ status = mech->gss_context_query_attributes(minor_status,
+ ctx->internal_ctx_id,
+ desired_object,
+ data,
+ len);
+ if (status != GSS_S_COMPLETE)
+ map_error(minor_status, mech);
+ } else
+ status = GSS_S_UNAVAILABLE;
+
+ return status;
+ }
+
+ return GSS_S_BAD_MECH;
+}
gss_buffer_t /* prf_out */
/* */);
+ OM_uint32 (*gss_context_query_attributes)
+ (
+ OM_uint32 *, /* minor_status */
+ const gss_ctx_id_t, /* context_handle */
+ const gss_OID, /* OID */
+ void *, /* data */
+ size_t /* length */
+ /* */ );
+
} *gss_mechanism;
/* This structure MUST NOT be used by any code outside libgss */
gss_buffer_t prf_out
);
+OM_uint32
+spnego_gss_context_query_attributes
+(
+ OM_uint32 *minor_status,
+ const gss_ctx_id_t context_handle,
+ const gss_OID desired_object,
+ void *data,
+ size_t length
+);
+
#ifdef __cplusplus
}
#endif
spnego_gss_map_name_to_any,
spnego_gss_release_any_name_mapping,
spnego_gss_pseudo_random,
+ spnego_gss_context_query_attributes,
};
#ifdef _GSS_STATIC_LINK
return (ret);
}
+OM_uint32
+spnego_gss_context_query_attributes(
+ OM_uint32 *minor_status,
+ const gss_ctx_id_t context_handle,
+ const gss_OID desired_object,
+ void *data,
+ size_t length)
+{
+ OM_uint32 ret;
+ ret = gss_context_query_attributes(minor_status,
+ context_handle,
+ desired_object,
+ data,
+ length);
+ return (ret);
+}
+
+
/*
* We will release everything but the ctx_handle so that it
* can be passed back to init/accept context. This routine should
testPrf(minor, initiator_context, acceptor_context, GSS_C_PRF_KEY_PARTIAL);
}
+ {
+ gss_context_stream_sizes sizes;
+
+ major = gss_context_query_attributes(minor, acceptor_context,
+ GSS_C_ATTR_STREAM_SIZES,
+ &sizes, sizeof(sizes));
+ if (major == GSS_S_COMPLETE) {
+ printf("\nContext attributes:\n");
+ printf("-----------------------------------\n\n");
+ printf("Header length: %ld\n", sizes.header);
+ printf("Trailer length: %ld\n", sizes.trailer);
+ printf("Maximum msg size: %ld\n", sizes.max_msg_size);
+ printf("Extra buffers: %ld\n", sizes.buffers);
+ printf("Block size: %ld\n", sizes.blocksize);
+ } else
+ displayStatus("gss_context_query_attributes", major, *minor);
+ }
+
(void) gss_release_name(&tmp_minor, &source_name);
(void) gss_delete_sec_context(&tmp_minor, &acceptor_context, NULL);
(void) gss_delete_sec_context(minor, &initiator_context, NULL);