s4-dcerpc: fixed auth padding to be relative to the stub, not packet
authorAndrew Tridgell <tridge@samba.org>
Tue, 16 Feb 2010 09:21:29 +0000 (20:21 +1100)
committerAndrew Tridgell <tridge@samba.org>
Tue, 16 Feb 2010 10:10:52 +0000 (21:10 +1100)
The recent dcerpc padding changes made our padding relative to the
packet header, instead of the start of the stub. Surprisingly, this
broke w2k8r2 doing a dcpromo join to a s4 server. It seems that w2k8r2
is very fussy about the padding it gets in some circumstances.

source4/librpc/rpc/dcerpc.c
source4/rpc_server/dcesrv_auth.c

index ccafe070abbf0b30b42831f437b72e513c5ad0b7..63ff36768b5a9510cc82e8c5650a37273cc0dcf2 100644 (file)
@@ -318,7 +318,6 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c,
        size_t payload_length;
        enum ndr_err_code ndr_err;
        size_t hdr_size = DCERPC_REQUEST_LENGTH;
-       uint32_t offset;
 
        /* non-signed packets are simpler */
        if (sig_size == 0) {
@@ -365,13 +364,16 @@ static NTSTATUS ncacn_push_request_sign(struct dcerpc_connection *c,
        }
 
        /* pad to 16 byte multiple in the payload portion of the
-          packet. This matches what w2k3 does */
-       offset = ndr->offset;
-       ndr_err = ndr_push_align(ndr, 16);
+          packet. This matches what w2k3 does. Note that we can't use
+          ndr_push_align() as that is relative to the start of the
+          whole packet, whereas w2k8 wants it relative to the start
+          of the stub */
+       c->security_state.auth_info->auth_pad_length =
+               (16 - (pkt->u.request.stub_and_verifier.length & 15)) & 15;
+       ndr_err = ndr_push_zero(ndr, c->security_state.auth_info->auth_pad_length);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return ndr_map_error2ntstatus(ndr_err);
        }
-       c->security_state.auth_info->auth_pad_length = ndr->offset - offset;
 
        payload_length = pkt->u.request.stub_and_verifier.length + 
                c->security_state.auth_info->auth_pad_length;
index e74b2ef167cf9f1e9c5de0d5851a4301306126ce..59d8be3e24bdda1a58d226af1c3ccbf0cfb65cc0 100644 (file)
@@ -378,7 +378,7 @@ bool dcesrv_auth_response(struct dcesrv_call_state *call,
        NTSTATUS status;
        enum ndr_err_code ndr_err;
        struct ndr_push *ndr;
-       uint32_t payload_length, offset;
+       uint32_t payload_length;
        DATA_BLOB creds2;
 
        /* non-signed packets are simple */
@@ -422,13 +422,17 @@ bool dcesrv_auth_response(struct dcesrv_call_state *call,
                return false;
        }
 
-       /* pad to 16 byte multiple, match win2k3 */
-       offset = ndr->offset;
-       ndr_err = ndr_push_align(ndr, 16);
+       /* pad to 16 byte multiple in the payload portion of the
+          packet. This matches what w2k3 does. Note that we can't use
+          ndr_push_align() as that is relative to the start of the
+          whole packet, whereas w2k8 wants it relative to the start
+          of the stub */
+       dce_conn->auth_state.auth_info->auth_pad_length =
+               (16 - (pkt->u.response.stub_and_verifier.length & 15)) & 15;
+       ndr_err = ndr_push_zero(ndr, dce_conn->auth_state.auth_info->auth_pad_length);
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return false;
        }
-       dce_conn->auth_state.auth_info->auth_pad_length = ndr->offset - offset;
 
        payload_length = pkt->u.response.stub_and_verifier.length +
                dce_conn->auth_state.auth_info->auth_pad_length;
@@ -497,6 +501,7 @@ bool dcesrv_auth_response(struct dcesrv_call_state *call,
 
        if (!data_blob_append(call, blob, creds2.data, creds2.length)) {
                status = NT_STATUS_NO_MEMORY;
+               return false;
        }
        data_blob_free(&creds2);