r473: Fix for Microsoft hotfix MS04-011 password change breakage.
authorJeremy Allison <jra@samba.org>
Tue, 4 May 2004 20:09:24 +0000 (20:09 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:51:24 +0000 (10:51 -0500)
Jeremy.
(This used to be commit 038cae8a377b75d70a099f03cb1b8ae9b50e7613)

source3/rpc_server/srv_pipe.c

index ad7c544b681408a2ca8edfa70f2d3b9ace63b60a..076f800a4041149094ca14d5d9bf8501e1b130b8 100644 (file)
@@ -87,6 +87,7 @@ BOOL create_next_pdu(pipes_struct *p)
        RPC_HDR_RESP hdr_resp;
        BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0);
        BOOL auth_seal   = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL) != 0);
+       uint32 ss_padding_len = 0;
        uint32 data_len;
        uint32 data_space_available;
        uint32 data_len_left;
@@ -109,21 +110,22 @@ BOOL create_next_pdu(pipes_struct *p)
        p->hdr.pkt_type = RPC_RESPONSE;
 
        /* Set up rpc header flags. */
-       if (p->out_data.data_sent_length == 0)
+       if (p->out_data.data_sent_length == 0) {
                p->hdr.flags = RPC_FLG_FIRST;
-       else
+       } else {
                p->hdr.flags = 0;
+       }
 
        /*
         * Work out how much we can fit in a single PDU.
         */
 
        data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
-       if(p->ntlmssp_auth_validated)
+       if(p->ntlmssp_auth_validated) {
                data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN);
-
-       if(p->netsec_auth_validated)
+       } else if(p->netsec_auth_validated) {
                data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_CHK_LEN);
+       }
 
        /*
         * The amount we send is the minimum of the available
@@ -150,16 +152,31 @@ BOOL create_next_pdu(pipes_struct *p)
 
        hdr_resp.alloc_hint = data_len_left;
 
+       /*
+        * Work out if this PDU will be the last.
+        */
+
+       if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) {
+               p->hdr.flags |= RPC_FLG_LAST;
+               if ((auth_seal || auth_verify) && (data_len_left % 8)) {
+                       ss_padding_len = 8 - (data_len_left % 8);
+                       DEBUG(10,("create_next_pdu: adding sign/seal padding of %u\n",
+                               ss_padding_len ));
+               }
+       }
+
        /*
         * Set up the header lengths.
         */
 
        if (p->ntlmssp_auth_validated) {
-               p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len +
-                                       RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN;
+               p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
+                       data_len + ss_padding_len +
+                       RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN;
                p->hdr.auth_len = RPC_AUTH_NTLMSSP_CHK_LEN;
        } else if (p->netsec_auth_validated) {
-               p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len +
+               p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
+                       data_len + ss_padding_len +
                        RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_CHK_LEN;
                p->hdr.auth_len = RPC_AUTH_NETSEC_CHK_LEN;
        } else {
@@ -167,13 +184,6 @@ BOOL create_next_pdu(pipes_struct *p)
                p->hdr.auth_len = 0;
        }
 
-       /*
-        * Work out if this PDU will be the last.
-        */
-
-       if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata))
-               p->hdr.flags |= RPC_FLG_LAST;
-
        /*
         * Init the parse struct to point at the outgoing
         * data.
@@ -206,12 +216,26 @@ BOOL create_next_pdu(pipes_struct *p)
                return False;
        }
 
+       /* Copy the sign/seal padding data. */
+       if (ss_padding_len) {
+               char pad[8];
+               memset(pad, '\0', 8);
+               if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) {
+                       DEBUG(0,("create_next_pdu: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len));
+                       prs_mem_free(&outgoing_pdu);
+                       return False;
+               }
+       }
+
        if (p->ntlmssp_auth_validated) {
+               /*
+                * NTLMSSP processing. Mutually exclusive with Schannel.
+                */
                uint32 crc32 = 0;
                char *data;
 
                DEBUG(5,("create_next_pdu: sign: %s seal: %s data %d auth %d\n",
-                        BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len, p->hdr.auth_len));
+                        BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len + ss_padding_len, p->hdr.auth_len));
 
                /*
                 * Set data to point to where we copied the data into.
@@ -220,15 +244,16 @@ BOOL create_next_pdu(pipes_struct *p)
                data = prs_data_p(&outgoing_pdu) + data_pos;
 
                if (auth_seal) {
-                       crc32 = crc32_calc_buffer(data, data_len);
-                       NTLMSSPcalc_p(p, (uchar*)data, data_len);
+                       crc32 = crc32_calc_buffer(data, data_len + ss_padding_len);
+                       NTLMSSPcalc_p(p, (uchar*)data, data_len + ss_padding_len);
                }
 
                if (auth_seal || auth_verify) {
                        RPC_HDR_AUTH auth_info;
 
-                       init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, auth_info.auth_level,
-                                       (auth_verify ? RPC_HDR_AUTH_LEN : 0), (auth_verify ? 1 : 0));
+                       init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE,
+                                       auth_seal ? RPC_PIPE_AUTH_SEAL_LEVEL : RPC_PIPE_AUTH_SIGN_LEVEL,
+                                       (auth_verify ? ss_padding_len : 0), (auth_verify ? 1 : 0));
                        if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
                                DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n"));
                                prs_mem_free(&outgoing_pdu);
@@ -251,9 +276,10 @@ BOOL create_next_pdu(pipes_struct *p)
                        }
                        NTLMSSPcalc_p(p, (uchar*)auth_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4);
                }
-       }
-
-       if (p->netsec_auth_validated) {
+       } else if (p->netsec_auth_validated) {
+               /*
+                * Schannel processing. Mutually exclusive with NTLMSSP.
+                */
                int auth_type, auth_level;
                char *data;
                RPC_HDR_AUTH auth_info;
@@ -267,7 +293,7 @@ BOOL create_next_pdu(pipes_struct *p)
 
                get_auth_type_level(p->netsec_auth.auth_flags, &auth_type, &auth_level);
                init_rpc_hdr_auth(&auth_info, auth_type, auth_level, 
-                                 RPC_HDR_AUTH_LEN, 1);
+                                 ss_padding_len, 1);
 
                if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
                        DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n"));
@@ -281,7 +307,7 @@ BOOL create_next_pdu(pipes_struct *p)
                netsec_encode(&p->netsec_auth, 
                              p->netsec_auth.auth_flags,
                              SENDER_IS_ACCEPTOR,
-                             &verf, data, data_len);
+                             &verf, data, data_len + ss_padding_len);
 
                smb_io_rpc_auth_netsec_chk("", &verf, &outgoing_pdu, 0);
 
@@ -292,7 +318,7 @@ BOOL create_next_pdu(pipes_struct *p)
         * Setup the counts for this PDU.
         */
 
-       p->out_data.data_sent_length += data_len;
+       p->out_data.data_sent_length += (data_len + ss_padding_len);
        p->out_data.current_pdu_len = p->hdr.frag_len;
        p->out_data.current_pdu_sent = 0;