#include "gse_krb5.h"
static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min);
+static size_t gensec_gse_sig_size(struct gensec_security *gensec_security,
+ size_t data_size);
struct gse_context {
gss_ctx_id_t gssapi_context;
gss_name_t server_name;
gss_name_t client_name;
OM_uint32 gss_want_flags, gss_got_flags;
+ size_t sig_size;
gss_cred_id_t delegated_cred_handle;
return errstr;
}
-static size_t gse_get_signature_length(struct gse_context *gse_ctx,
- bool seal, size_t payload_size)
-{
- OM_uint32 gss_min, gss_maj;
- gss_iov_buffer_desc iov[2];
- int sealed;
-
- /*
- * gss_wrap_iov_length() only needs the type and length
- */
- iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
- iov[0].buffer.value = NULL;
- iov[0].buffer.length = 0;
- iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
- iov[1].buffer.value = NULL;
- iov[1].buffer.length = payload_size;
-
- gss_maj = gss_wrap_iov_length(&gss_min, gse_ctx->gssapi_context,
- seal, GSS_C_QOP_DEFAULT,
- &sealed, iov, 2);
- if (gss_maj) {
- DEBUG(0, ("gss_wrap_iov_length failed with [%s]\n",
- gse_errstr(talloc_tos(), gss_maj, gss_min)));
- return 0;
- }
-
- return iov[0].buffer.length;
-}
-
-static NTSTATUS gse_seal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
- DATA_BLOB *data, DATA_BLOB *signature)
-{
- OM_uint32 gss_min, gss_maj;
- gss_iov_buffer_desc iov[2];
- int req_seal = 1; /* setting to 1 means we request sign+seal */
- int sealed = 1;
- NTSTATUS status;
-
- /* allocate the memory ourselves so we do not need to talloc_memdup */
- signature->length = gse_get_signature_length(gse_ctx, true, data->length);
- if (!signature->length) {
- return NT_STATUS_INTERNAL_ERROR;
- }
- signature->data = (uint8_t *)talloc_size(mem_ctx, signature->length);
- if (!signature->data) {
- return NT_STATUS_NO_MEMORY;
- }
- iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
- iov[0].buffer.value = signature->data;
- iov[0].buffer.length = signature->length;
-
- /* data is encrypted in place, which is ok */
- iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
- iov[1].buffer.value = data->data;
- iov[1].buffer.length = data->length;
-
- gss_maj = gss_wrap_iov(&gss_min, gse_ctx->gssapi_context,
- req_seal, GSS_C_QOP_DEFAULT,
- &sealed, iov, 2);
- if (gss_maj) {
- DEBUG(0, ("gss_wrap_iov failed with [%s]\n",
- gse_errstr(talloc_tos(), gss_maj, gss_min)));
- status = NT_STATUS_ACCESS_DENIED;
- goto done;
- }
-
- if (!sealed) {
- DEBUG(0, ("gss_wrap_iov says data was not sealed!\n"));
- status = NT_STATUS_ACCESS_DENIED;
- goto done;
- }
-
- status = NT_STATUS_OK;
-
- DEBUG(10, ("Sealed %d bytes, and got %d bytes header/signature.\n",
- (int)iov[1].buffer.length, (int)iov[0].buffer.length));
-
-done:
- return status;
-}
-
-static NTSTATUS gse_unseal(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
- DATA_BLOB *data, const DATA_BLOB *signature)
-{
- OM_uint32 gss_min, gss_maj;
- gss_iov_buffer_desc iov[2];
- int sealed;
- NTSTATUS status;
-
- iov[0].type = GSS_IOV_BUFFER_TYPE_HEADER;
- iov[0].buffer.value = signature->data;
- iov[0].buffer.length = signature->length;
-
- /* data is decrypted in place, which is ok */
- iov[1].type = GSS_IOV_BUFFER_TYPE_DATA;
- iov[1].buffer.value = data->data;
- iov[1].buffer.length = data->length;
-
- gss_maj = gss_unwrap_iov(&gss_min, gse_ctx->gssapi_context,
- &sealed, NULL, iov, 2);
- if (gss_maj) {
- DEBUG(0, ("gss_unwrap_iov failed with [%s]\n",
- gse_errstr(talloc_tos(), gss_maj, gss_min)));
- status = NT_STATUS_ACCESS_DENIED;
- goto done;
- }
-
- if (!sealed) {
- DEBUG(0, ("gss_unwrap_iov says data is not sealed!\n"));
- status = NT_STATUS_ACCESS_DENIED;
- goto done;
- }
-
- status = NT_STATUS_OK;
-
- DEBUG(10, ("Unsealed %d bytes, with %d bytes header/signature.\n",
- (int)iov[1].buffer.length, (int)iov[0].buffer.length));
-
-done:
- return status;
-}
-
-static NTSTATUS gse_sign(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
- DATA_BLOB *data, DATA_BLOB *signature)
-{
- OM_uint32 gss_min, gss_maj;
- gss_buffer_desc in_data = { 0, NULL };
- gss_buffer_desc out_data = { 0, NULL};
- NTSTATUS status;
-
- in_data.value = data->data;
- in_data.length = data->length;
-
- gss_maj = gss_get_mic(&gss_min, gse_ctx->gssapi_context,
- GSS_C_QOP_DEFAULT,
- &in_data, &out_data);
- if (gss_maj) {
- DEBUG(0, ("gss_get_mic failed with [%s]\n",
- gse_errstr(talloc_tos(), gss_maj, gss_min)));
- status = NT_STATUS_ACCESS_DENIED;
- goto done;
- }
-
- *signature = data_blob_talloc(mem_ctx,
- out_data.value, out_data.length);
- if (!signature->data) {
- status = NT_STATUS_NO_MEMORY;
- goto done;
- }
-
- status = NT_STATUS_OK;
-
-done:
- if (out_data.value) {
- gss_maj = gss_release_buffer(&gss_min, &out_data);
- }
- return status;
-}
-
-static NTSTATUS gse_sigcheck(TALLOC_CTX *mem_ctx, struct gse_context *gse_ctx,
- const DATA_BLOB *data, const DATA_BLOB *signature)
-{
- OM_uint32 gss_min, gss_maj;
- gss_buffer_desc in_data = { 0, NULL };
- gss_buffer_desc in_token = { 0, NULL};
- NTSTATUS status;
-
- in_data.value = data->data;
- in_data.length = data->length;
- in_token.value = signature->data;
- in_token.length = signature->length;
-
- gss_maj = gss_verify_mic(&gss_min, gse_ctx->gssapi_context,
- &in_data, &in_token, NULL);
- if (gss_maj) {
- DEBUG(0, ("gss_verify_mic failed with [%s]\n",
- gse_errstr(talloc_tos(), gss_maj, gss_min)));
- status = NT_STATUS_ACCESS_DENIED;
- goto done;
- }
-
- status = NT_STATUS_OK;
-
-done:
- return status;
-}
-
static NTSTATUS gensec_gse_client_start(struct gensec_security *gensec_security)
{
struct gse_context *gse_ctx;
struct gse_context *gse_ctx =
talloc_get_type_abort(gensec_security->private_data,
struct gse_context);
- DATA_BLOB payload = data_blob_const(data, length);
- return gse_seal(mem_ctx, gse_ctx, &payload, sig);
+ bool hdr_signing = false;
+ size_t sig_size = 0;
+ NTSTATUS status;
+
+ if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
+ hdr_signing = true;
+ }
+
+ sig_size = gensec_gse_sig_size(gensec_security, length);
+
+ status = gssapi_seal_packet(gse_ctx->gssapi_context,
+ &gse_ctx->gss_mech,
+ hdr_signing, sig_size,
+ data, length,
+ whole_pdu, pdu_length,
+ mem_ctx, sig);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("gssapi_seal_packet(hdr_signing=%u,sig_size=%ju,"
+ "data=%ju,pdu=%ju) failed: %s\n",
+ hdr_signing, sig_size, length, pdu_length,
+ nt_errstr(status)));
+ return status;
+ }
+
+ return NT_STATUS_OK;
}
static NTSTATUS gensec_gse_unseal_packet(struct gensec_security *gensec_security,
struct gse_context *gse_ctx =
talloc_get_type_abort(gensec_security->private_data,
struct gse_context);
- DATA_BLOB payload = data_blob_const(data, length);
- return gse_unseal(talloc_tos() /* unused */, gse_ctx, &payload, sig);
+ bool hdr_signing = false;
+ NTSTATUS status;
+
+ if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
+ hdr_signing = true;
+ }
+
+ status = gssapi_unseal_packet(gse_ctx->gssapi_context,
+ &gse_ctx->gss_mech,
+ hdr_signing,
+ data, length,
+ whole_pdu, pdu_length,
+ sig);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("gssapi_unseal_packet(hdr_signing=%u,sig_size=%ju,"
+ "data=%ju,pdu=%ju) failed: %s\n",
+ hdr_signing, sig->length, length, pdu_length,
+ nt_errstr(status)));
+ return status;
+ }
+
+ return NT_STATUS_OK;
}
static NTSTATUS gensec_gse_sign_packet(struct gensec_security *gensec_security,
struct gse_context *gse_ctx =
talloc_get_type_abort(gensec_security->private_data,
struct gse_context);
- DATA_BLOB payload = data_blob_const(data, length);
- return gse_sign(mem_ctx, gse_ctx, &payload, sig);
+ bool hdr_signing = false;
+ NTSTATUS status;
+
+ if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
+ hdr_signing = true;
+ }
+
+ status = gssapi_sign_packet(gse_ctx->gssapi_context,
+ &gse_ctx->gss_mech,
+ hdr_signing,
+ data, length,
+ whole_pdu, pdu_length,
+ mem_ctx, sig);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("gssapi_sign_packet(hdr_signing=%u,"
+ "data=%ju,pdu=%ju) failed: %s\n",
+ hdr_signing, length, pdu_length,
+ nt_errstr(status)));
+ return status;
+ }
+
+ return NT_STATUS_OK;
}
static NTSTATUS gensec_gse_check_packet(struct gensec_security *gensec_security,
struct gse_context *gse_ctx =
talloc_get_type_abort(gensec_security->private_data,
struct gse_context);
- DATA_BLOB payload = data_blob_const(data, length);
- return gse_sigcheck(NULL, gse_ctx, &payload, sig);
+ bool hdr_signing = false;
+ NTSTATUS status;
+
+ if (gensec_security->want_features & GENSEC_FEATURE_SIGN_PKT_HEADER) {
+ hdr_signing = true;
+ }
+
+ status = gssapi_check_packet(gse_ctx->gssapi_context,
+ &gse_ctx->gss_mech,
+ hdr_signing,
+ data, length,
+ whole_pdu, pdu_length,
+ sig);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0, ("gssapi_check_packet(hdr_signing=%u,sig_size=%ju"
+ "data=%ju,pdu=%ju) failed: %s\n",
+ hdr_signing, sig->length, length, pdu_length,
+ nt_errstr(status)));
+ return status;
+ }
+
+ return NT_STATUS_OK;
}
/* Try to figure out what features we actually got on the connection */
if (feature & GENSEC_FEATURE_ASYNC_REPLIES) {
return true;
}
+ if (feature & GENSEC_FEATURE_SIGN_PKT_HEADER) {
+ if (gensec_security->want_features & GENSEC_FEATURE_SEAL) {
+ return true;
+ }
+
+ if (gensec_security->want_features & GENSEC_FEATURE_SIGN) {
+ return true;
+ }
+
+ return false;
+ }
return false;
}
talloc_get_type_abort(gensec_security->private_data,
struct gse_context);
- return gse_get_signature_length(gse_ctx,
- gensec_security->want_features & GENSEC_FEATURE_SEAL,
- data_size);
+ if (gse_ctx->sig_size > 0) {
+ return gse_ctx->sig_size;
+ }
+
+ gse_ctx->sig_size = gssapi_get_sig_size(gse_ctx->gssapi_context,
+ &gse_ctx->gss_mech,
+ gse_ctx->gss_want_flags,
+ data_size);
+ return gse_ctx->sig_size;
}
static const char *gensec_gse_krb5_oids[] = {