uint32_t assoc_group_id;
uint8_t num_contexts;
struct dcerpc_ctx_list *ctx_list;
- DATA_BLOB _pad;/* [flag(LIBNDR_FLAG_ALIGN4)] */
DATA_BLOB auth_info;/* [flag(LIBNDR_FLAG_REMAINING)] */
};
}/* [public] */;
struct dcerpc_auth3 {
- uint32_t _pad;
DATA_BLOB auth_info;/* [flag(LIBNDR_FLAG_REMAINING)] */
}/* [public] */;
struct dcerpc_orphaned {
- uint32_t _pad;
DATA_BLOB auth_info;/* [flag(LIBNDR_FLAG_REMAINING)] */
}/* [public] */;
struct dcerpc_co_cancel {
- uint32_t _pad;
DATA_BLOB auth_info;/* [flag(LIBNDR_FLAG_REMAINING)] */
}/* [public] */;
for (cntr_ctx_list_0 = 0; cntr_ctx_list_0 < r->num_contexts; cntr_ctx_list_0++) {
NDR_CHECK(ndr_push_dcerpc_ctx_list(ndr, NDR_SCALARS, &r->ctx_list[cntr_ctx_list_0]));
}
- {
- uint32_t _flags_save_DATA_BLOB = ndr->flags;
- ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4);
- NDR_CHECK(ndr_push_DATA_BLOB(ndr, NDR_SCALARS, r->_pad));
- ndr->flags = _flags_save_DATA_BLOB;
- }
{
uint32_t _flags_save_DATA_BLOB = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
NDR_CHECK(ndr_pull_dcerpc_ctx_list(ndr, NDR_SCALARS, &r->ctx_list[cntr_ctx_list_0]));
}
NDR_PULL_SET_MEM_CTX(ndr, _mem_save_ctx_list_0, 0);
- {
- uint32_t _flags_save_DATA_BLOB = ndr->flags;
- ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN4);
- NDR_CHECK(ndr_pull_DATA_BLOB(ndr, NDR_SCALARS, &r->_pad));
- ndr->flags = _flags_save_DATA_BLOB;
- }
{
uint32_t _flags_save_DATA_BLOB = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
}
}
ndr->depth--;
- ndr_print_DATA_BLOB(ndr, "_pad", r->_pad);
ndr_print_DATA_BLOB(ndr, "auth_info", r->auth_info);
ndr->depth--;
}
{
if (ndr_flags & NDR_SCALARS) {
NDR_CHECK(ndr_push_align(ndr, 4));
- NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->_pad));
{
uint32_t _flags_save_DATA_BLOB = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
{
if (ndr_flags & NDR_SCALARS) {
NDR_CHECK(ndr_pull_align(ndr, 4));
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->_pad));
{
uint32_t _flags_save_DATA_BLOB = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
{
ndr_print_struct(ndr, name, "dcerpc_auth3");
ndr->depth++;
- ndr_print_uint32(ndr, "_pad", r->_pad);
ndr_print_DATA_BLOB(ndr, "auth_info", r->auth_info);
ndr->depth--;
}
{
if (ndr_flags & NDR_SCALARS) {
NDR_CHECK(ndr_push_align(ndr, 4));
- NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->_pad));
{
uint32_t _flags_save_DATA_BLOB = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
{
if (ndr_flags & NDR_SCALARS) {
NDR_CHECK(ndr_pull_align(ndr, 4));
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->_pad));
{
uint32_t _flags_save_DATA_BLOB = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
{
ndr_print_struct(ndr, name, "dcerpc_orphaned");
ndr->depth++;
- ndr_print_uint32(ndr, "_pad", r->_pad);
ndr_print_DATA_BLOB(ndr, "auth_info", r->auth_info);
ndr->depth--;
}
{
if (ndr_flags & NDR_SCALARS) {
NDR_CHECK(ndr_push_align(ndr, 4));
- NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->_pad));
{
uint32_t _flags_save_DATA_BLOB = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
{
if (ndr_flags & NDR_SCALARS) {
NDR_CHECK(ndr_pull_align(ndr, 4));
- NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->_pad));
{
uint32_t _flags_save_DATA_BLOB = ndr->flags;
ndr_set_flags(&ndr->flags, LIBNDR_FLAG_REMAINING);
{
ndr_print_struct(ndr, name, "dcerpc_co_cancel");
ndr->depth++;
- ndr_print_uint32(ndr, "_pad", r->_pad);
ndr_print_DATA_BLOB(ndr, "auth_info", r->auth_info);
ndr->depth--;
}
uint32 assoc_group_id;
uint8 num_contexts;
dcerpc_ctx_list ctx_list[num_contexts];
- [flag(NDR_ALIGN4)] DATA_BLOB _pad;
[flag(NDR_REMAINING)] DATA_BLOB auth_info;
} dcerpc_bind;
const uint8 DCERPC_AUTH_TRAILER_LENGTH = 8;
typedef [public] struct {
- uint32 _pad;
[flag(NDR_REMAINING)] DATA_BLOB auth_info;
} dcerpc_auth3;
typedef [public] struct {
- uint32 _pad;
[flag(NDR_REMAINING)] DATA_BLOB auth_info;
} dcerpc_orphaned;
typedef [public] struct {
- uint32 _pad;
[flag(NDR_REMAINING)] DATA_BLOB auth_info;
} dcerpc_co_cancel;
DATA_BLOB *raw_packet,
struct ncacn_packet *pkt)
{
- struct ndr_pull *ndr;
NTSTATUS status;
struct dcerpc_auth auth;
- DATA_BLOB auth_blob;
- enum ndr_err_code ndr_err;
+ uint32_t auth_length;
if (!c->security_state.auth_info ||
!c->security_state.generic_state) {
return NT_STATUS_INVALID_LEVEL;
}
- auth_blob.length = 8 + pkt->auth_length;
-
- /* check for a valid length */
- if (pkt->u.response.stub_and_verifier.length < auth_blob.length) {
- return NT_STATUS_INFO_LENGTH_MISMATCH;
- }
-
- auth_blob.data =
- pkt->u.response.stub_and_verifier.data +
- pkt->u.response.stub_and_verifier.length - auth_blob.length;
- pkt->u.response.stub_and_verifier.length -= auth_blob.length;
+ status = dcerpc_pull_auth_trailer(pkt, mem_ctx,
+ &pkt->u.response.stub_and_verifier,
+ &auth, &auth_length, false);
+ NT_STATUS_NOT_OK_RETURN(status);
- /* pull the auth structure */
- ndr = ndr_pull_init_flags(c, &auth_blob, mem_ctx);
- if (!ndr) {
- return NT_STATUS_NO_MEMORY;
- }
-
- if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
- ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
- }
-
- ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return ndr_map_error2ntstatus(ndr_err);
- }
- status = NT_STATUS_OK;
+ pkt->u.response.stub_and_verifier.length -= auth_length;
/* check signature or unseal the packet */
switch (c->security_state.auth_info->auth_level) {
break;
}
- /* remove the indicated amount of paddiing */
+ /* remove the indicated amount of padding */
if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) {
return NT_STATUS_INFO_LENGTH_MISMATCH;
}
dcerpc_request_recv_data(conn, blob, &pkt);
}
-
/*
Receive a bind reply from the transport
*/
}
/* the bind_ack might contain a reply set of credentials */
- if (conn->security_state.auth_info &&
- pkt->u.bind_ack.auth_info.length) {
- enum ndr_err_code ndr_err;
- ndr_err = ndr_pull_struct_blob(
- &pkt->u.bind_ack.auth_info, conn,
- NULL,
- conn->security_state.auth_info,
- (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- c->status = ndr_map_error2ntstatus(ndr_err);
- if (!composite_is_ok(c)) return;
+ if (conn->security_state.auth_info && pkt->u.bind_ack.auth_info.length) {
+ NTSTATUS status;
+ uint32_t auth_length;
+ status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.bind_ack.auth_info,
+ conn->security_state.auth_info, &auth_length, true);
+ if (!NT_STATUS_IS_OK(status)) {
+ composite_error(c, status);
+ return;
}
}
pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
pkt.call_id = next_call_id(p->conn);
pkt.auth_length = 0;
- pkt.u.auth3._pad = 0;
pkt.u.auth3.auth_info = data_blob(NULL, 0);
if (p->binding->flags & DCERPC_CONCURRENT_MULTIPLEX) {
/* the alter_resp might contain a reply set of credentials */
if (recv_pipe->conn->security_state.auth_info &&
pkt->u.alter_resp.auth_info.length) {
- enum ndr_err_code ndr_err;
- ndr_err = ndr_pull_struct_blob(
- &pkt->u.alter_resp.auth_info, recv_pipe,
- NULL,
- recv_pipe->conn->security_state.auth_info,
- (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- c->status = ndr_map_error2ntstatus(ndr_err);
- if (!composite_is_ok(c)) return;
+ struct dcerpc_connection *conn = recv_pipe->conn;
+ NTSTATUS status;
+ uint32_t auth_length;
+ status = dcerpc_pull_auth_trailer(pkt, conn, &pkt->u.alter_resp.auth_info,
+ conn->security_state.auth_info, &auth_length, true);
+ if (!NT_STATUS_IS_OK(status)) {
+ composite_error(c, status);
+ return;
}
}
}
if (auth_info) {
+ ndr_err = ndr_push_zero(ndr, auth_info->auth_pad_length);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return ndr_map_error2ntstatus(ndr_err);
+ }
ndr_err = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth_info);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return ndr_map_error2ntstatus(ndr_err);
return NT_STATUS_OK;
}
+
+
+/*
+ pull an dcerpc_auth structure, taking account of any auth padding in
+ the blob at the end of the structure
+ */
+NTSTATUS dcerpc_pull_auth_trailer(struct ncacn_packet *pkt,
+ TALLOC_CTX *mem_ctx,
+ DATA_BLOB *pkt_auth_blob,
+ struct dcerpc_auth *auth,
+ uint32_t *auth_length,
+ bool check_pad)
+{
+ struct ndr_pull *ndr;
+ enum ndr_err_code ndr_err;
+ uint32_t pad;
+
+ pad = pkt_auth_blob->length - (DCERPC_AUTH_TRAILER_LENGTH + pkt->auth_length);
+ *auth_length = pkt_auth_blob->length - pad;
+
+ ndr = ndr_pull_init_blob(pkt_auth_blob, mem_ctx, NULL);
+ if (!ndr) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
+ ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
+ }
+
+ ndr_err = ndr_pull_advance(ndr, pad);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(ndr);
+ return ndr_map_error2ntstatus(ndr_err);
+ }
+
+ ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, auth);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ talloc_free(ndr);
+ return ndr_map_error2ntstatus(ndr_err);
+ }
+
+ if (check_pad && pad != auth->auth_pad_length) {
+ DEBUG(1,(__location__ ": WARNING: pad length mismatch. Calculated %u got %u\n",
+ (unsigned)pad, (unsigned)auth->auth_pad_length));
+ }
+
+ DEBUG(6,(__location__ ": auth_pad_length %u\n",
+ (unsigned)auth->auth_pad_length));
+
+ talloc_steal(mem_ctx, auth->credentials.data);
+ talloc_free(ndr);
+
+ return NT_STATUS_OK;
+}
+
+
struct dcesrv_connection *dce_conn = call->conn;
struct dcesrv_auth *auth = &dce_conn->auth_state;
NTSTATUS status;
- enum ndr_err_code ndr_err;
+ uint32_t auth_length;
if (pkt->u.bind.auth_info.length == 0) {
dce_conn->auth_state.auth_info = NULL;
return false;
}
- ndr_err = ndr_pull_struct_blob(&pkt->u.bind.auth_info,
- call, NULL,
- dce_conn->auth_state.auth_info,
- (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return false;
- }
-
+ status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.bind.auth_info,
+ dce_conn->auth_state.auth_info,
+ &auth_length, false);
server_credentials
= cli_credentials_init(call);
if (!server_credentials) {
struct ncacn_packet *pkt = &call->pkt;
struct dcesrv_connection *dce_conn = call->conn;
NTSTATUS status;
- enum ndr_err_code ndr_err;
+ uint32_t auth_length;
/* We can't work without an existing gensec state, and an new blob to feed it */
if (!dce_conn->auth_state.auth_info ||
return false;
}
- ndr_err = ndr_pull_struct_blob(&pkt->u.auth3.auth_info,
- call, NULL,
- dce_conn->auth_state.auth_info,
- (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.auth3.auth_info,
+ dce_conn->auth_state.auth_info, &auth_length, true);
+ if (!NT_STATUS_IS_OK(status)) {
return false;
}
{
struct ncacn_packet *pkt = &call->pkt;
struct dcesrv_connection *dce_conn = call->conn;
- enum ndr_err_code ndr_err;
+ NTSTATUS status;
+ uint32_t auth_length;
/* on a pure interface change there is no auth blob */
if (pkt->u.alter.auth_info.length == 0) {
return false;
}
- ndr_err = ndr_pull_struct_blob(&pkt->u.alter.auth_info,
- call, NULL,
- dce_conn->auth_state.auth_info,
- (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.alter.auth_info,
+ dce_conn->auth_state.auth_info,
+ &auth_length, true);
+ if (!NT_STATUS_IS_OK(status)) {
return false;
}
{
struct ncacn_packet *pkt = &call->pkt;
struct dcesrv_connection *dce_conn = call->conn;
- DATA_BLOB auth_blob;
struct dcerpc_auth auth;
- struct ndr_pull *ndr;
NTSTATUS status;
- enum ndr_err_code ndr_err;
+ uint32_t auth_length;
size_t hdr_size = DCERPC_REQUEST_LENGTH;
if (!dce_conn->auth_state.auth_info ||
return true;
}
+ if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
+ hdr_size += 16;
+ }
+
switch (dce_conn->auth_state.auth_info->auth_level) {
case DCERPC_AUTH_LEVEL_PRIVACY:
case DCERPC_AUTH_LEVEL_INTEGRITY:
return false;
}
- auth_blob.length = 8 + pkt->auth_length;
-
- /* check for a valid length */
- if (pkt->u.request.stub_and_verifier.length < auth_blob.length) {
- return false;
- }
-
- auth_blob.data =
- pkt->u.request.stub_and_verifier.data +
- pkt->u.request.stub_and_verifier.length - auth_blob.length;
- pkt->u.request.stub_and_verifier.length -= auth_blob.length;
-
- /* pull the auth structure */
- ndr = ndr_pull_init_blob(&auth_blob, call, lp_iconv_convenience(call->conn->dce_ctx->lp_ctx));
- if (!ndr) {
+ status = dcerpc_pull_auth_trailer(pkt, call,
+ &pkt->u.request.stub_and_verifier,
+ &auth, &auth_length, false);
+ if (!NT_STATUS_IS_OK(status)) {
return false;
}
- if (!(pkt->drep[0] & DCERPC_DREP_LE)) {
- ndr->flags |= LIBNDR_FLAG_BIGENDIAN;
- }
-
- if (pkt->pfc_flags & DCERPC_PFC_FLAG_OBJECT_UUID) {
- ndr->flags |= LIBNDR_FLAG_OBJECT_PRESENT;
- hdr_size += 16;
- }
-
- ndr_err = ndr_pull_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, &auth);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- talloc_free(ndr);
- return false;
- }
+ pkt->u.request.stub_and_verifier.length -= auth_length;
/* check signature or unseal the packet */
switch (dce_conn->auth_state.auth_info->auth_level) {
/* remove the indicated amount of padding */
if (pkt->u.request.stub_and_verifier.length < auth.auth_pad_length) {
- talloc_free(ndr);
return false;
}
pkt->u.request.stub_and_verifier.length -= auth.auth_pad_length;
- talloc_free(ndr);
return NT_STATUS_IS_OK(status);
}