summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/auth/gensec/gensec_gssapi.c63
-rw-r--r--source4/librpc/rpc/dcerpc.c35
-rw-r--r--source4/rpc_server/dcesrv_auth.c54
3 files changed, 87 insertions, 65 deletions
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index d9f6edc7d7..364c0c3499 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -818,46 +818,6 @@ static NTSTATUS gensec_gssapi_unwrap(struct gensec_security *gensec_security,
return NT_STATUS_OK;
}
-/* Find out the size of the signature, assuming (incorrectly) that it
- * GSSAPI provides any guarantees as to it's size.
- *
- * This is needed by the DCE/RPC code, which uses AEAD
- * (signed headers, including signature legnth and a sealed body)
- */
-static size_t gensec_gssapi_sig_size(struct gensec_security *gensec_security, size_t data_size)
-{
- struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
- OM_uint32 maj_stat, min_stat;
- OM_uint32 output_size;
- if ((gensec_gssapi_state->gss_oid->length != gss_mech_krb5->length)
- || (memcmp(gensec_gssapi_state->gss_oid->elements, gss_mech_krb5->elements,
- gensec_gssapi_state->gss_oid->length) != 0)) {
- DEBUG(1, ("NO sig size available for this mech\n"));
- return 0;
- }
-
- maj_stat = gsskrb5_wrap_size(&min_stat,
- gensec_gssapi_state->gssapi_context,
- gensec_have_feature(gensec_security, GENSEC_FEATURE_SEAL),
- GSS_C_QOP_DEFAULT,
- data_size,
- &output_size);
- if (GSS_ERROR(maj_stat)) {
- TALLOC_CTX *mem_ctx = talloc_new(NULL);
- DEBUG(1, ("gensec_gssapi_sig_size: determinaing signature size with gsskrb5_wrap_size failed: %s\n",
- gssapi_error_string(mem_ctx, maj_stat, min_stat)));
- talloc_free(mem_ctx);
- return 0;
- }
-
- if (output_size < data_size) {
- return 0;
- }
-
- /* The difference between the max output and the max input must be the signature */
- return output_size - data_size;
-}
-
/* Find out the maximum input size negotiated on this connection */
static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security)
@@ -918,14 +878,12 @@ static NTSTATUS gensec_gssapi_seal_packet(struct gensec_security *gensec_securit
return NT_STATUS_ACCESS_DENIED;
}
- sig_length = gensec_gssapi_sig_size(gensec_security, length);
-
- /* Caller must pad to right boundary */
- if (output_token.length != (length + sig_length)) {
- DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap length [%ld] does not match caller length [%ld] plus sig size [%ld] = [%ld]\n",
- (long)output_token.length, (long)length, (long)sig_length, (long)(length + sig_length)));
+ if (output_token.length < input_token.length) {
+ DEBUG(1, ("gensec_gssapi_seal_packet: GSS Wrap length [%ld] *less* than caller length [%ld]\n",
+ (long)output_token.length, (long)length));
return NT_STATUS_INTERNAL_ERROR;
}
+ sig_length = output_token.length - input_token.length;
memcpy(data, ((uint8_t *)output_token.value) + sig_length, length);
*sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
@@ -1021,18 +979,14 @@ static NTSTATUS gensec_gssapi_sign_packet(struct gensec_security *gensec_securit
return NT_STATUS_ACCESS_DENIED;
}
- if (output_token.length < length) {
+ if (output_token.length < input_token.length) {
+ DEBUG(1, ("gensec_gssapi_sign_packet: GSS Wrap length [%ld] *less* than caller length [%ld]\n",
+ (long)output_token.length, (long)length));
return NT_STATUS_INTERNAL_ERROR;
}
- sig_length = gensec_gssapi_sig_size(gensec_security, length);
-
/* Caller must pad to right boundary */
- if (output_token.length != (length + sig_length)) {
- DEBUG(1, ("gensec_gssapi_sign_packet: GSS Wrap length [%ld] does not match caller length [%ld] plus sig size [%ld] = [%ld]\n",
- (long)output_token.length, (long)length, (long)sig_length, (long)(length + sig_length)));
- return NT_STATUS_INTERNAL_ERROR;
- }
+ sig_length = output_token.length - input_token.length;
*sig = data_blob_talloc(mem_ctx, (uint8_t *)output_token.value, sig_length);
@@ -1352,7 +1306,6 @@ static const struct gensec_security_ops gensec_gssapi_krb5_security_ops = {
.update = gensec_gssapi_update,
.session_key = gensec_gssapi_session_key,
.session_info = gensec_gssapi_session_info,
- .sig_size = gensec_gssapi_sig_size,
.sign_packet = gensec_gssapi_sign_packet,
.check_packet = gensec_gssapi_check_packet,
.seal_packet = gensec_gssapi_seal_packet,
diff --git a/source4/librpc/rpc/dcerpc.c b/source4/librpc/rpc/dcerpc.c
index bfdf93a0f3..53d0e1b65b 100644
--- a/source4/librpc/rpc/dcerpc.c
+++ b/source4/librpc/rpc/dcerpc.c
@@ -369,6 +369,9 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c,
switch (c->security_state.auth_info->auth_level) {
case DCERPC_AUTH_LEVEL_PRIVACY:
case DCERPC_AUTH_LEVEL_INTEGRITY:
+ /* We hope this length is accruate. If must be if the
+ * GENSEC mech does AEAD signing of the packet
+ * headers */
c->security_state.auth_info->credentials
= data_blob_talloc(mem_ctx, NULL, gensec_sig_size(c->security_state.generic_state,
payload_length));
@@ -405,6 +408,8 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c,
in these earlier as we don't know the signature length (it
could be variable length) */
dcerpc_set_frag_length(blob, blob->length);
+ /* We hope this value is accruate. If must be if the GENSEC
+ * mech does AEAD signing of the packet headers */
dcerpc_set_auth_length(blob, c->security_state.auth_info->credentials.length);
/* sign or seal the packet */
@@ -421,7 +426,20 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c,
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- memcpy(blob->data + blob->length - creds2.length, creds2.data, creds2.length);
+ status = data_blob_realloc(mem_ctx, blob,
+ blob->length - c->security_state.auth_info->credentials.length +
+ creds2.length);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ memcpy(blob->data + blob->length - c->security_state.auth_info->credentials.length,
+ creds2.data, creds2.length);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ dcerpc_set_auth_length(blob, creds2.length);
break;
case DCERPC_AUTH_LEVEL_INTEGRITY:
@@ -436,7 +454,20 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c,
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- memcpy(blob->data + blob->length - creds2.length, creds2.data, creds2.length);
+ status = data_blob_realloc(mem_ctx, blob,
+ blob->length - c->security_state.auth_info->credentials.length +
+ creds2.length);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ memcpy(blob->data + blob->length - c->security_state.auth_info->credentials.length,
+ creds2.data, creds2.length);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ dcerpc_set_auth_length(blob, creds2.length);
break;
case DCERPC_AUTH_LEVEL_CONNECT:
diff --git a/source4/rpc_server/dcesrv_auth.c b/source4/rpc_server/dcesrv_auth.c
index 3f848ca381..e6e9bb7fc5 100644
--- a/source4/rpc_server/dcesrv_auth.c
+++ b/source4/rpc_server/dcesrv_auth.c
@@ -393,6 +393,7 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
NTSTATUS status;
struct ndr_push *ndr;
uint32_t payload_length;
+ DATA_BLOB creds2;
/* non-signed packets are simple */
if (!dce_conn->auth_state.auth_info || !dce_conn->auth_state.gensec_security) {
@@ -427,14 +428,20 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
return False;
}
} else {
+
+ /* We hope this length is accruate. If must be if the
+ * GENSEC mech does AEAD signing of the packet
+ * headers */
dce_conn->auth_state.auth_info->credentials
= data_blob_talloc(call, NULL,
gensec_sig_size(dce_conn->auth_state.gensec_security,
payload_length));
+ data_blob_clear(&dce_conn->auth_state.auth_info->credentials);
}
/* add the auth verifier */
- status = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, dce_conn->auth_state.auth_info);
+ status = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS,
+ dce_conn->auth_state.auth_info);
if (!NT_STATUS_IS_OK(status)) {
return False;
}
@@ -446,6 +453,9 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
in these earlier as we don't know the signature length (it
could be variable length) */
dcerpc_set_frag_length(blob, blob->length);
+
+ /* We hope this value is accruate. If must be if the GENSEC
+ * mech does AEAD signing of the packet headers */
dcerpc_set_auth_length(blob, dce_conn->auth_state.auth_info->credentials.length);
/* sign or seal the packet */
@@ -457,7 +467,23 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
payload_length,
blob->data,
blob->length - dce_conn->auth_state.auth_info->credentials.length,
- &dce_conn->auth_state.auth_info->credentials);
+ &creds2);
+
+ if (NT_STATUS_IS_OK(status)) {
+ status = data_blob_realloc(call, blob,
+ blob->length - dce_conn->auth_state.auth_info->credentials.length +
+ creds2.length);
+ }
+
+ if (NT_STATUS_IS_OK(status)) {
+ memcpy(blob->data + blob->length - dce_conn->auth_state.auth_info->credentials.length,
+ creds2.data, creds2.length);
+ }
+
+ /* If we did AEAD signing of the packet headers, then we hope
+ * this value didn't change... */
+ dcerpc_set_auth_length(blob, creds2.length);
+ data_blob_free(&creds2);
break;
case DCERPC_AUTH_LEVEL_INTEGRITY:
@@ -467,8 +493,23 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
payload_length,
blob->data,
blob->length - dce_conn->auth_state.auth_info->credentials.length,
- &dce_conn->auth_state.auth_info->credentials);
+ &creds2);
+ if (NT_STATUS_IS_OK(status)) {
+ status = data_blob_realloc(call, blob,
+ blob->length - dce_conn->auth_state.auth_info->credentials.length +
+ creds2.length);
+ }
+ if (NT_STATUS_IS_OK(status)) {
+ memcpy(blob->data + blob->length - dce_conn->auth_state.auth_info->credentials.length,
+ creds2.data, creds2.length);
+ }
+
+ /* If we did AEAD signing of the packet headers, then we hope
+ * this value didn't change... */
+ dcerpc_set_auth_length(blob, creds2.length);
+
+ data_blob_free(&creds2);
break;
case DCERPC_AUTH_LEVEL_CONNECT:
@@ -479,14 +520,11 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
break;
}
+ data_blob_free(&dce_conn->auth_state.auth_info->credentials);
+
if (!NT_STATUS_IS_OK(status)) {
return False;
}
- memcpy(blob->data + blob->length - dce_conn->auth_state.auth_info->credentials.length,
- dce_conn->auth_state.auth_info->credentials.data, dce_conn->auth_state.auth_info->credentials.length);
-
- data_blob_free(&dce_conn->auth_state.auth_info->credentials);
-
return True;
}