r2284: Thanks to some great detective work by tridge, NTLM2 signing now works.
authorAndrew Bartlett <abartlet@samba.org>
Sat, 11 Sep 2004 15:11:36 +0000 (15:11 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:58:39 +0000 (12:58 -0500)
This means that 'require NTLMv2 session security' now works for RPC
pipe signing.  We don't yet have sealing, but it can't be much further.

This is almost all tridge's code, munged into a form that can work
with the GENSEC API.

This commit also includes more lsakey fixes - that key is used for all
DCE-RPC level authenticated connections, even over CIFS/ncacn_np.

No doubt I missed something, but I'm going to get some sleep :-)

Andrew Bartlett

16 files changed:
source/libcli/auth/gensec.c
source/libcli/auth/gensec.h
source/libcli/auth/gensec_ntlmssp.c
source/libcli/auth/ntlmssp.c
source/libcli/auth/ntlmssp.h
source/libcli/auth/ntlmssp_sign.c
source/libcli/auth/spnego.c
source/librpc/rpc/dcerpc.c
source/librpc/rpc/dcerpc.h
source/librpc/rpc/dcerpc_auth.c
source/librpc/rpc/dcerpc_schannel.c
source/librpc/rpc/dcerpc_smb.c
source/librpc/rpc/dcerpc_tcp.c
source/librpc/rpc/dcerpc_util.c
source/rpc_server/dcesrv_auth.c
source/torture/auth/ntlmssp.c

index 4b362b5305f132faeec2d7b736e92841ecf07552..a744f513dc8362a1d33c55a9d32ab9e843fa946c 100644 (file)
@@ -248,8 +248,6 @@ NTSTATUS gensec_start_mech_by_authtype(struct gensec_security *gensec_security,
                gensec_want_feature(gensec_security, GENSEC_WANT_SEAL);
        }
 
-       gensec_want_feature(gensec_security, GENSEC_WANT_SESSION_KEY);
-
        return gensec_start_mech(gensec_security);
 }
 
@@ -303,17 +301,23 @@ NTSTATUS gensec_start_mech_by_sasl_name(struct gensec_security *gensec_security,
 */
 NTSTATUS gensec_unseal_packet(struct gensec_security *gensec_security, 
                              TALLOC_CTX *mem_ctx, 
-                             uint8_t *data, size_t length, DATA_BLOB *sig)
+                             uint8_t *data, size_t length, 
+                             const uint8_t *whole_pdu, size_t pdu_length, 
+                             DATA_BLOB *sig)
 {
        if (!gensec_security->ops->unseal_packet) {
                return NT_STATUS_NOT_IMPLEMENTED;
        }
-       return gensec_security->ops->unseal_packet(gensec_security, mem_ctx, data, length, sig);
+       return gensec_security->ops->unseal_packet(gensec_security, mem_ctx, 
+                                                  data, length, 
+                                                  whole_pdu, pdu_length, 
+                                                  sig);
 }
 
 NTSTATUS gensec_check_packet(struct gensec_security *gensec_security, 
                             TALLOC_CTX *mem_ctx, 
                             const uint8_t *data, size_t length, 
+                            const uint8_t *whole_pdu, size_t pdu_length, 
                             const DATA_BLOB *sig)
 {
        if (!gensec_security->ops->check_packet) {
@@ -323,12 +327,13 @@ NTSTATUS gensec_check_packet(struct gensec_security *gensec_security,
                return NT_STATUS_INVALID_PARAMETER;
        }
        
-       return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, sig);
+       return gensec_security->ops->check_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
 }
 
 NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security, 
                            TALLOC_CTX *mem_ctx, 
                            uint8_t *data, size_t length, 
+                           const uint8_t *whole_pdu, size_t pdu_length, 
                            DATA_BLOB *sig)
 {
        if (!gensec_security->ops->seal_packet) {
@@ -338,12 +343,13 @@ NTSTATUS gensec_seal_packet(struct gensec_security *gensec_security,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, sig);
+       return gensec_security->ops->seal_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
 }
 
 NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security, 
                            TALLOC_CTX *mem_ctx, 
                            const uint8_t *data, size_t length, 
+                           const uint8_t *whole_pdu, size_t pdu_length, 
                            DATA_BLOB *sig)
 {
        if (!gensec_security->ops->sign_packet) {
@@ -353,7 +359,19 @@ NTSTATUS gensec_sign_packet(struct gensec_security *gensec_security,
                return NT_STATUS_INVALID_PARAMETER;
        }
        
-       return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, sig);
+       return gensec_security->ops->sign_packet(gensec_security, mem_ctx, data, length, whole_pdu, pdu_length, sig);
+}
+
+size_t gensec_sig_size(struct gensec_security *gensec_security) 
+{
+       if (!gensec_security->ops->sig_size) {
+               return 0;
+       }
+       if (!(gensec_security->want_features & GENSEC_WANT_SIGN)) {
+               return 0;
+       }
+       
+       return gensec_security->ops->sig_size(gensec_security);
 }
 
 NTSTATUS gensec_session_key(struct gensec_security *gensec_security, 
index 73a5f6b463dacdd7ce7a2d5cc9320cdc9ca8eddd..00c1c0dd0a51de151f4fbeb2fa4579de62dd133b 100644 (file)
@@ -60,13 +60,22 @@ struct gensec_security_ops {
        NTSTATUS (*update)(struct gensec_security *gensec_security, TALLOC_CTX *out_mem_ctx,
                           const DATA_BLOB in, DATA_BLOB *out);
        NTSTATUS (*seal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx,
-                               uint8_t *data, size_t length, DATA_BLOB *sig);
+                               uint8_t *data, size_t length, 
+                               const uint8_t *whole_pdu, size_t pdu_length, 
+                               DATA_BLOB *sig);
        NTSTATUS (*sign_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx,
-                               const uint8_t *data, size_t length, DATA_BLOB *sig);
+                               const uint8_t *data, size_t length, 
+                               const uint8_t *whole_pdu, size_t pdu_length, 
+                               DATA_BLOB *sig);
+       size_t   (*sig_size)(struct gensec_security *gensec_security);
        NTSTATUS (*check_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx, 
-                                const uint8_t *data, size_t length, const DATA_BLOB *sig);
+                                const uint8_t *data, size_t length, 
+                                const uint8_t *whole_pdu, size_t pdu_length, 
+                                const DATA_BLOB *sig);
        NTSTATUS (*unseal_packet)(struct gensec_security *gensec_security, TALLOC_CTX *sig_mem_ctx,
-                                 uint8_t *data, size_t length, DATA_BLOB *sig);
+                                 uint8_t *data, size_t length, 
+                                 const uint8_t *whole_pdu, size_t pdu_length, 
+                                 DATA_BLOB *sig);
        NTSTATUS (*session_key)(struct gensec_security *gensec_security, DATA_BLOB *session_key);
        NTSTATUS (*session_info)(struct gensec_security *gensec_security, 
                                 struct auth_session_info **session_info); 
index beee29a08800bc652667838505ebe11263a9ad12..0c96a783f16ed2240651d75e3bf45a2ad03dc422 100644 (file)
@@ -287,42 +287,52 @@ static NTSTATUS gensec_ntlmssp_client_start(struct gensec_security *gensec_secur
   wrappers for the ntlmssp_*() functions
 */
 static NTSTATUS gensec_ntlmssp_unseal_packet(struct gensec_security *gensec_security, 
-                                     TALLOC_CTX *mem_ctx, 
-                                     uint8_t *data, size_t length, DATA_BLOB *sig)
+                                            TALLOC_CTX *mem_ctx, 
+                                            uint8_t *data, size_t length, 
+                                            const uint8_t *whole_pdu, size_t pdu_length, 
+                                            DATA_BLOB *sig)
 {
        struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
 
-       return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, sig);
+       return ntlmssp_unseal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
 }
 
 static NTSTATUS gensec_ntlmssp_check_packet(struct gensec_security *gensec_security, 
-                                    TALLOC_CTX *mem_ctx, 
-                                    const uint8_t *data, size_t length, 
-                                    const DATA_BLOB *sig)
+                                           TALLOC_CTX *mem_ctx, 
+                                           const uint8_t *data, size_t length, 
+                                           const uint8_t *whole_pdu, size_t pdu_length, 
+                                           const DATA_BLOB *sig)
 {
        struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
 
-       return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, sig);
+       return ntlmssp_check_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
 }
 
 static NTSTATUS gensec_ntlmssp_seal_packet(struct gensec_security *gensec_security, 
-                                   TALLOC_CTX *mem_ctx, 
-                                   uint8_t *data, size_t length, 
-                                   DATA_BLOB *sig)
+                                          TALLOC_CTX *mem_ctx, 
+                                          uint8_t *data, size_t length, 
+                                          const uint8_t *whole_pdu, size_t pdu_length, 
+                                          DATA_BLOB *sig)
 {
        struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
 
-       return ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, sig);
+       return ntlmssp_seal_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
 }
 
 static NTSTATUS gensec_ntlmssp_sign_packet(struct gensec_security *gensec_security, 
-                                   TALLOC_CTX *mem_ctx, 
-                                   const uint8_t *data, size_t length, 
-                                   DATA_BLOB *sig)
+                                          TALLOC_CTX *mem_ctx, 
+                                          const uint8_t *data, size_t length, 
+                                          const uint8_t *whole_pdu, size_t pdu_length, 
+                                          DATA_BLOB *sig)
 {
        struct gensec_ntlmssp_state *gensec_ntlmssp_state = gensec_security->private_data;
 
-       return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, sig);
+       return ntlmssp_sign_packet(gensec_ntlmssp_state->ntlmssp_state, mem_ctx, data, length, whole_pdu, pdu_length, sig);
+}
+
+static size_t gensec_ntlmssp_sig_size(struct gensec_security *gensec_security) 
+{
+       return NTLMSSP_SIG_SIZE;
 }
 
 static NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, 
@@ -413,6 +423,7 @@ static const struct gensec_security_ops gensec_ntlmssp_security_ops = {
        .server_start   = gensec_ntlmssp_server_start,
        .update         = gensec_ntlmssp_update,
        .seal_packet    = gensec_ntlmssp_seal_packet,
+       .sig_size       = gensec_ntlmssp_sig_size,
        .sign_packet    = gensec_ntlmssp_sign_packet,
        .check_packet   = gensec_ntlmssp_check_packet,
        .unseal_packet  = gensec_ntlmssp_unseal_packet,
index 4d2dd6b5768232776aaf3a07c72a9a2776ba2434..e6839e1fea4963474c3848483eb633e81356b032 100644 (file)
@@ -940,7 +940,7 @@ NTSTATUS ntlmssp_server_start(struct ntlmssp_state **ntlmssp_state)
        (*ntlmssp_state)->neg_flags = 
                NTLMSSP_NEGOTIATE_128 |
                NTLMSSP_NEGOTIATE_NTLM |
-/*             NTLMSSP_NEGOTIATE_NTLM2 | */
+               NTLMSSP_NEGOTIATE_NTLM2 |
                NTLMSSP_NEGOTIATE_KEY_EXCH;
 
        return NT_STATUS_OK;
@@ -971,7 +971,7 @@ static NTSTATUS ntlmssp_client_initial(struct ntlmssp_state *ntlmssp_state,
        }
        
        if (ntlmssp_state->use_ntlmv2) {
-/*             ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;*/
+               ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_NTLM2;
        }
 
        /* generate the ntlmssp negotiate packet */
@@ -1293,7 +1293,7 @@ NTSTATUS ntlmssp_client_start(struct ntlmssp_state **ntlmssp_state)
        (*ntlmssp_state)->neg_flags = 
                NTLMSSP_NEGOTIATE_128 |
                NTLMSSP_NEGOTIATE_NTLM |
-/*             NTLMSSP_NEGOTIATE_NTLM2 |*/
+               NTLMSSP_NEGOTIATE_NTLM2 |
                NTLMSSP_NEGOTIATE_KEY_EXCH |
                NTLMSSP_REQUEST_TARGET;
 
index 61285e472b4bcbb242109cd51c1ec0b4c24f0e20..153669f7b43ea1221f4f2580752864983b1cef09 100644 (file)
@@ -71,6 +71,8 @@ enum ntlmssp_message_type
 
 #define NTLMSSP_SIGN_VERSION 1
 
+#define NTLMSSP_SIG_SIZE 16
+
 struct ntlmssp_state 
 {
        TALLOC_CTX *mem_ctx;
@@ -162,8 +164,9 @@ struct ntlmssp_state
        const char *(*get_domain)(void);
 
        /* SMB Signing */
-       
-       uint32_t ntlmssp_seq_num;
+       uint32_t ntlm_seq_num;
+       uint32_t ntlm2_send_seq_num;
+       uint32_t ntlm2_recv_seq_num;
 
        /* ntlmv2 */
        DATA_BLOB send_sign_key;
index ca3660eea7d7c4b6d72da187128bb4584314e865..2ab54124e3c54e558f7003be1f30000a57f0828f 100644 (file)
@@ -64,31 +64,40 @@ enum ntlmssp_direction {
 static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_state,
                                              TALLOC_CTX *sig_mem_ctx, 
                                              const uint8_t *data, size_t length, 
+                                             const uint8_t *whole_pdu, size_t pdu_length, 
                                              enum ntlmssp_direction direction,
-                                             DATA_BLOB *sig) 
+                                             DATA_BLOB *sig, BOOL encrypt_sig
 {
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
 
                HMACMD5Context ctx;
                uint8_t digest[16];
                uint8_t seq_num[4];
-               SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
 
+               *sig = data_blob_talloc(sig_mem_ctx, NULL, NTLMSSP_SIG_SIZE);
+               if (!sig->data) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+                       
                switch (direction) {
                case NTLMSSP_SEND:
+                       SIVAL(seq_num, 0, ntlmssp_state->ntlm2_send_seq_num);
+                       ntlmssp_state->ntlm2_send_seq_num++;
                        hmac_md5_init_limK_to_64(ntlmssp_state->send_sign_key.data, 
                                                 ntlmssp_state->send_sign_key.length, &ctx);
                        break;
                case NTLMSSP_RECEIVE:
+                       SIVAL(seq_num, 0, ntlmssp_state->ntlm2_recv_seq_num);
+                       ntlmssp_state->ntlm2_recv_seq_num++;
                        hmac_md5_init_limK_to_64(ntlmssp_state->recv_sign_key.data, 
                                                 ntlmssp_state->recv_sign_key.length, &ctx);
                        break;
                }
                hmac_md5_update(seq_num, sizeof(seq_num), &ctx);
-               hmac_md5_update(data, length, &ctx);
+               hmac_md5_update(whole_pdu, pdu_length, &ctx);
                hmac_md5_final(digest, &ctx);
 
-               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
+               if (encrypt_sig && ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
                        switch (direction) {
                        case NTLMSSP_SEND:
                                arcfour_crypt_sbox(ntlmssp_state->send_seal_hash, digest, 8);
@@ -98,7 +107,7 @@ static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_stat
                                break;
                        }
                }
-               *sig = data_blob_talloc(sig_mem_ctx, NULL, 16);
+
                SIVAL(sig->data, 0, NTLMSSP_SIGN_VERSION);
                memcpy(sig->data + 4, digest, 8);
                memcpy(sig->data + 12, seq_num, 4);
@@ -106,11 +115,14 @@ static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_stat
        } else {
                uint32_t crc;
                crc = crc32_calc_buffer((const char *)data, length);
-               if (!msrpc_gen(sig_mem_ctx, sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
+               if (!msrpc_gen(sig_mem_ctx, sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlm_seq_num)) {
                        return NT_STATUS_NO_MEMORY;
                }
-               
-               arcfour_crypt_sbox(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4);
+               ntlmssp_state->ntlm_seq_num++;
+
+               if (encrypt_sig) {
+                       arcfour_crypt_sbox(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4);
+               }
        }
        dump_data_pw("calculated ntlmssp signature\n", sig->data, sig->length);
        return NT_STATUS_OK;
@@ -119,26 +131,23 @@ static NTSTATUS ntlmssp_make_packet_signature(struct ntlmssp_state *ntlmssp_stat
 NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state,
                             TALLOC_CTX *sig_mem_ctx, 
                             const uint8_t *data, size_t length, 
+                            const uint8_t *whole_pdu, size_t pdu_length, 
                             DATA_BLOB *sig) 
 {
-       NTSTATUS nt_status;
-
        if (!ntlmssp_state->session_key.length) {
                DEBUG(3, ("NO session key, cannot check sign packet\n"));
                return NT_STATUS_NO_USER_SESSION_KEY;
        }
-
+       
        if (!ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) {
                DEBUG(3, ("NTLMSSP Signing not negotiated - cannot sign packet!\n"));
                return NT_STATUS_INVALID_PARAMETER;
        }
-
-       nt_status = ntlmssp_make_packet_signature(ntlmssp_state, sig_mem_ctx, 
-                                                 data, length, NTLMSSP_SEND, sig);
-
-       /* increment counter on send */
-       ntlmssp_state->ntlmssp_seq_num++;
-       return nt_status;
+       
+       return ntlmssp_make_packet_signature(ntlmssp_state, sig_mem_ctx, 
+                                            data, length, 
+                                            whole_pdu, pdu_length, 
+                                            NTLMSSP_SEND, sig, True);
 }
 
 /**
@@ -149,6 +158,7 @@ NTSTATUS ntlmssp_sign_packet(struct ntlmssp_state *ntlmssp_state,
 NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
                              TALLOC_CTX *sig_mem_ctx, 
                              const uint8_t *data, size_t length, 
+                             const uint8_t *whole_pdu, size_t pdu_length, 
                              const DATA_BLOB *sig) 
 {
        DATA_BLOB local_sig;
@@ -164,17 +174,16 @@ NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
                          (unsigned long)sig->length));
        }
 
-       nt_status = ntlmssp_make_packet_signature(ntlmssp_state, sig_mem_ctx, data, 
-                                                 length, NTLMSSP_RECEIVE, &local_sig);
+       nt_status = ntlmssp_make_packet_signature(ntlmssp_state, sig_mem_ctx, 
+                                                 data, length, 
+                                                 whole_pdu, pdu_length, 
+                                                 NTLMSSP_RECEIVE, &local_sig, True);
        
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0, ("NTLMSSP packet check failed with %s\n", nt_errstr(nt_status)));
                return nt_status;
        }
 
-       /* increment counter on recv */
-       ntlmssp_state->ntlmssp_seq_num++;
-
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
                if (local_sig.length != sig->length ||
                    memcmp(local_sig.data, 
@@ -216,8 +225,10 @@ NTSTATUS ntlmssp_check_packet(struct ntlmssp_state *ntlmssp_state,
 NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
                             TALLOC_CTX *sig_mem_ctx, 
                             uint8_t *data, size_t length,
+                            const uint8_t *whole_pdu, size_t pdu_length, 
                             DATA_BLOB *sig)
 {      
+       NTSTATUS nt_status;
        if (!ntlmssp_state->session_key.length) {
                DEBUG(3, ("NO session key, cannot seal packet\n"));
                return NT_STATUS_NO_USER_SESSION_KEY;
@@ -231,35 +242,20 @@ NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
        DEBUG(10,("ntlmssp_seal_data: seal\n"));
        dump_data_pw("ntlmssp clear data\n", data, length);
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
-               HMACMD5Context ctx;
-               uint8_t seq_num[4];
-               uint8_t digest[16];
-               SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);
-
-               hmac_md5_init_limK_to_64(ntlmssp_state->send_sign_key.data, 
-                                        ntlmssp_state->send_sign_key.length, &ctx);
-               hmac_md5_update(seq_num, 4, &ctx);
-               hmac_md5_update(data, length, &ctx);
-               hmac_md5_final(digest, &ctx);
-
                /* The order of these two operations matters - we must first seal the packet,
                   then seal the sequence number - this is becouse the send_seal_hash is not
                   constant, but is is rather updated with each iteration */
                
                arcfour_crypt_sbox(ntlmssp_state->send_seal_hash, data, length);
 
-               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
-                       arcfour_crypt_sbox(ntlmssp_state->send_seal_hash,  digest, 8);
-               }
-
-               *sig = data_blob_talloc(sig_mem_ctx, NULL, 16);
-               SIVAL(sig->data, 0, NTLMSSP_SIGN_VERSION);
-               memcpy(sig->data + 4, digest, 8);
-               memcpy(sig->data + 12, seq_num, 4);
+               nt_status = ntlmssp_make_packet_signature(ntlmssp_state, sig_mem_ctx, 
+                                                         data, length, 
+                                                         whole_pdu, pdu_length, 
+                                                         NTLMSSP_SEND, sig, True);
        } else {
                uint32_t crc;
                crc = crc32_calc_buffer((const char *)data, length);
-               if (!msrpc_gen(sig_mem_ctx, sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
+               if (!msrpc_gen(sig_mem_ctx, sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlm_seq_num)) {
                        return NT_STATUS_NO_MEMORY;
                }
 
@@ -270,14 +266,15 @@ NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
                arcfour_crypt_sbox(ntlmssp_state->ntlmssp_hash, data, length);
 
                arcfour_crypt_sbox(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4);
+               /* increment counter on send */
+               ntlmssp_state->ntlm_seq_num++;
+               nt_status = NT_STATUS_OK;
        }
        dump_data_pw("ntlmssp signature\n", sig->data, sig->length);
        dump_data_pw("ntlmssp sealed data\n", data, length);
 
-       /* increment counter on send */
-       ntlmssp_state->ntlmssp_seq_num++;
 
-       return NT_STATUS_OK;
+       return nt_status;
 }
 
 /**
@@ -288,8 +285,11 @@ NTSTATUS ntlmssp_seal_packet(struct ntlmssp_state *ntlmssp_state,
 NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state,
                               TALLOC_CTX *sig_mem_ctx, 
                               uint8_t *data, size_t length,
+                              const uint8_t *whole_pdu, size_t pdu_length, 
                               DATA_BLOB *sig)
 {
+       DATA_BLOB local_sig;
+       NTSTATUS nt_status;
        if (!ntlmssp_state->session_key.length) {
                DEBUG(3, ("NO session key, cannot unseal packet\n"));
                return NT_STATUS_NO_USER_SESSION_KEY;
@@ -297,13 +297,46 @@ NTSTATUS ntlmssp_unseal_packet(struct ntlmssp_state *ntlmssp_state,
 
        dump_data_pw("ntlmssp sealed data\n", data, length);
        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
+
+               /* We have to pass the data past the arcfour pad in
+                * the correct order, so we must encrypt the signature
+                * after we decrypt the main body.  however, the
+                * signature is calculated over the encrypted data */
+
+               nt_status = ntlmssp_make_packet_signature(ntlmssp_state, sig_mem_ctx, 
+                                                         data, length, 
+                                                         whole_pdu, pdu_length, 
+                                                         NTLMSSP_RECEIVE, &local_sig, False);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       return nt_status;
+               }
+
                arcfour_crypt_sbox(ntlmssp_state->recv_seal_hash, data, length);
+
+               if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
+                       arcfour_crypt_sbox(ntlmssp_state->send_seal_hash,  local_sig.data + 4, 8);
+               }
+
+               if (local_sig.length != sig->length ||
+                   memcmp(local_sig.data, 
+                          sig->data, sig->length) != 0) {
+                       DEBUG(5, ("BAD SIG NTLM2: wanted signature of\n"));
+                       dump_data(5, local_sig.data, local_sig.length);
+                       
+                       DEBUG(5, ("BAD SIG: got signature of\n"));
+                       dump_data(5, sig->data, sig->length);
+                       
+                       DEBUG(0, ("NTLMSSP NTLM2 packet check failed due to invalid signature!\n"));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+
+               dump_data_pw("ntlmssp clear data\n", data, length);
+               return NT_STATUS_OK;
        } else {
                arcfour_crypt_sbox(ntlmssp_state->ntlmssp_hash, data, length);
+               dump_data_pw("ntlmssp clear data\n", data, length);
+               return ntlmssp_check_packet(ntlmssp_state, sig_mem_ctx, data, length, whole_pdu, pdu_length, sig);
        }
-       dump_data_pw("ntlmssp clear data\n", data, length);
-
-       return ntlmssp_check_packet(ntlmssp_state, sig_mem_ctx, data, length, sig);
 }
 
 /**
@@ -414,7 +447,9 @@ NTSTATUS ntlmssp_sign_init(struct ntlmssp_state *ntlmssp_state)
                             sizeof(ntlmssp_state->ntlmssp_hash));
        }
 
-       ntlmssp_state->ntlmssp_seq_num = 0;
+       ntlmssp_state->ntlm_seq_num = 0;
+       ntlmssp_state->ntlm2_send_seq_num = 0;
+       ntlmssp_state->ntlm2_recv_seq_num = 0;
 
        return NT_STATUS_OK;
 }
index de71814354e88f075419fd9f2329ce32e6ea3be5..f3ead5069dbc950843671b93f42a7031f4eb32fe 100644 (file)
@@ -92,8 +92,10 @@ static NTSTATUS gensec_spnego_server_start(struct gensec_security *gensec_securi
   wrappers for the spnego_*() functions
 */
 static NTSTATUS gensec_spnego_unseal_packet(struct gensec_security *gensec_security, 
-                                    TALLOC_CTX *mem_ctx, 
-                                    uint8_t *data, size_t length, DATA_BLOB *sig)
+                                           TALLOC_CTX *mem_ctx, 
+                                           uint8_t *data, size_t length, 
+                                           const uint8_t *whole_pdu, size_t pdu_length, 
+                                           DATA_BLOB *sig)
 {
        struct spnego_state *spnego_state = gensec_security->private_data;
 
@@ -103,13 +105,17 @@ static NTSTATUS gensec_spnego_unseal_packet(struct gensec_security *gensec_secur
        }
        
        return gensec_unseal_packet(spnego_state->sub_sec_security, 
-                                   mem_ctx, data, length, sig); 
+                                   mem_ctx, 
+                                   data, length, 
+                                   whole_pdu, pdu_length,
+                                   sig); 
 }
 
 static NTSTATUS gensec_spnego_check_packet(struct gensec_security *gensec_security, 
-                                    TALLOC_CTX *mem_ctx, 
-                                    const uint8_t *data, size_t length, 
-                                    const DATA_BLOB *sig)
+                                          TALLOC_CTX *mem_ctx, 
+                                          const uint8_t *data, size_t length, 
+                                          const uint8_t *whole_pdu, size_t pdu_length, 
+                                          const DATA_BLOB *sig)
 {
        struct spnego_state *spnego_state = gensec_security->private_data;
 
@@ -120,13 +126,17 @@ static NTSTATUS gensec_spnego_check_packet(struct gensec_security *gensec_securi
        }
        
        return gensec_check_packet(spnego_state->sub_sec_security, 
-                               mem_ctx, data, length, sig);
+                                  mem_ctx, 
+                                  data, length, 
+                                  whole_pdu, pdu_length,
+                                  sig);
 }
 
 static NTSTATUS gensec_spnego_seal_packet(struct gensec_security *gensec_security, 
-                                   TALLOC_CTX *mem_ctx, 
-                                   uint8_t *data, size_t length, 
-                                   DATA_BLOB *sig)
+                                         TALLOC_CTX *mem_ctx, 
+                                         uint8_t *data, size_t length, 
+                                         const uint8_t *whole_pdu, size_t pdu_length, 
+                                         DATA_BLOB *sig)
 {
        struct spnego_state *spnego_state = gensec_security->private_data;
 
@@ -137,13 +147,17 @@ static NTSTATUS gensec_spnego_seal_packet(struct gensec_security *gensec_securit
        }
        
        return gensec_seal_packet(spnego_state->sub_sec_security, 
-                                 mem_ctx, data, length, sig);
+                                 mem_ctx, 
+                                 data, length, 
+                                 whole_pdu, pdu_length,
+                                 sig);
 }
 
 static NTSTATUS gensec_spnego_sign_packet(struct gensec_security *gensec_security, 
-                                   TALLOC_CTX *mem_ctx, 
-                                   const uint8_t *data, size_t length, 
-                                   DATA_BLOB *sig)
+                                         TALLOC_CTX *mem_ctx, 
+                                         const uint8_t *data, size_t length, 
+                                         const uint8_t *whole_pdu, size_t pdu_length, 
+                                         DATA_BLOB *sig)
 {
        struct spnego_state *spnego_state = gensec_security->private_data;
 
@@ -153,11 +167,26 @@ static NTSTATUS gensec_spnego_sign_packet(struct gensec_security *gensec_securit
        }
        
        return gensec_sign_packet(spnego_state->sub_sec_security, 
-                                 mem_ctx, data, length, sig);
+                                 mem_ctx, 
+                                 data, length, 
+                                 whole_pdu, pdu_length,
+                                 sig);
+}
+
+static size_t gensec_spnego_sig_size(struct gensec_security *gensec_security) 
+{
+       struct spnego_state *spnego_state = gensec_security->private_data;
+
+       if (spnego_state->state_position != SPNEGO_DONE 
+           && spnego_state->state_position != SPNEGO_FALLBACK) {
+               return 0;
+       }
+       
+       return gensec_sig_size(spnego_state->sub_sec_security);
 }
 
 static NTSTATUS gensec_spnego_session_key(struct gensec_security *gensec_security, 
-                                   DATA_BLOB *session_key)
+                                         DATA_BLOB *session_key)
 {
        struct spnego_state *spnego_state = gensec_security->private_data;
        if (!spnego_state->sub_sec_security) {
@@ -684,6 +713,7 @@ static const struct gensec_security_ops gensec_spnego_security_ops = {
        .update         = gensec_spnego_update,
        .seal_packet    = gensec_spnego_seal_packet,
        .sign_packet    = gensec_spnego_sign_packet,
+       .sig_size       = gensec_spnego_sig_size,
        .check_packet   = gensec_spnego_check_packet,
        .unseal_packet  = gensec_spnego_unseal_packet,
        .session_key    = gensec_spnego_session_key,
index 0595d5eade77417ea5c177885f0a1c0ac8909e1b..c2f691aa09b24067ff47ee38534123c5221e5920 100644 (file)
@@ -36,6 +36,7 @@ struct dcerpc_pipe *dcerpc_pipe_init(void)
        p->reference_count = 0;
        p->call_id = 1;
        p->security_state.auth_info = NULL;
+       p->security_state.session_key = dcerpc_generic_session_key;
        p->security_state.generic_state = NULL;
        p->binding_string = NULL;
        p->flags = 0;
@@ -206,8 +207,8 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p,
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
-
-
+       
+       
        /* check signature or unseal the packet */
        switch (p->security_state.auth_info->auth_level) {
        case DCERPC_AUTH_LEVEL_PRIVACY:
@@ -215,6 +216,8 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p,
                                              mem_ctx, 
                                              pkt->u.response.stub_and_verifier.data, 
                                              pkt->u.response.stub_and_verifier.length, 
+                                             blob->data,
+                                             blob->length - auth.credentials.length,
                                              &auth.credentials);
                break;
                
@@ -223,9 +226,11 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p,
                                             mem_ctx, 
                                             pkt->u.response.stub_and_verifier.data, 
                                             pkt->u.response.stub_and_verifier.length, 
+                                            blob->data,
+                                            blob->length - auth.credentials.length,
                                             &auth.credentials);
                break;
-
+               
        case DCERPC_AUTH_LEVEL_NONE:
                break;
 
@@ -233,7 +238,7 @@ static NTSTATUS dcerpc_pull_request_sign(struct dcerpc_pipe *p,
                status = NT_STATUS_INVALID_LEVEL;
                break;
        }
-
+       
        /* remove the indicated amount of paddiing */
        if (pkt->u.response.stub_and_verifier.length < auth.auth_pad_length) {
                return NT_STATUS_INFO_LENGTH_MISMATCH;
@@ -253,6 +258,7 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p,
 {
        NTSTATUS status;
        struct ndr_push *ndr;
+       DATA_BLOB creds2;
 
        /* non-signed packets are simpler */
        if (!p->security_state.auth_info || !p->security_state.generic_state) {
@@ -282,30 +288,21 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p,
        /* sign or seal the packet */
        switch (p->security_state.auth_info->auth_level) {
        case DCERPC_AUTH_LEVEL_PRIVACY:
-               status = gensec_seal_packet(p->security_state.generic_state, 
-                                           mem_ctx, 
-                                           ndr->data + DCERPC_REQUEST_LENGTH, 
-                                           ndr->offset - DCERPC_REQUEST_LENGTH,
-                                           &p->security_state.auth_info->credentials);
-               break;
-
        case DCERPC_AUTH_LEVEL_INTEGRITY:
-               status = gensec_sign_packet(p->security_state.generic_state, 
-                                           mem_ctx, 
-                                           ndr->data + DCERPC_REQUEST_LENGTH, 
-                                           ndr->offset - DCERPC_REQUEST_LENGTH,
-                                           &p->security_state.auth_info->credentials);
+               p->security_state.auth_info->credentials
+                       = data_blob_talloc(mem_ctx, NULL, gensec_sig_size(p->security_state.generic_state));
+               data_blob_clear(&p->security_state.auth_info->credentials);
                break;
 
        case DCERPC_AUTH_LEVEL_NONE:
                p->security_state.auth_info->credentials = data_blob(NULL, 0);
                break;
-
+               
        default:
                status = NT_STATUS_INVALID_LEVEL;
                break;
        }
-
+       
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }       
@@ -325,6 +322,41 @@ static NTSTATUS dcerpc_push_request_sign(struct dcerpc_pipe *p,
        dcerpc_set_frag_length(blob, blob->length);
        dcerpc_set_auth_length(blob, p->security_state.auth_info->credentials.length);
 
+       /* sign or seal the packet */
+       switch (p->security_state.auth_info->auth_level) {
+       case DCERPC_AUTH_LEVEL_PRIVACY:
+               status = gensec_seal_packet(p->security_state.generic_state, 
+                                           mem_ctx, 
+                                           ndr->data + DCERPC_REQUEST_LENGTH, 
+                                           ndr->offset - DCERPC_REQUEST_LENGTH,
+                                           blob->data,
+                                           blob->length - 
+                                           p->security_state.auth_info->credentials.length,
+                                           &creds2);
+               memcpy(blob->data + blob->length - creds2.length, creds2.data, creds2.length);
+               break;
+
+       case DCERPC_AUTH_LEVEL_INTEGRITY:
+               status = gensec_sign_packet(p->security_state.generic_state, 
+                                           mem_ctx, 
+                                           ndr->data + DCERPC_REQUEST_LENGTH, 
+                                           ndr->offset - DCERPC_REQUEST_LENGTH,
+                                           blob->data,
+                                           blob->length - 
+                                           p->security_state.auth_info->credentials.length,
+                                           &creds2);
+               memcpy(blob->data + blob->length - creds2.length, creds2.data, creds2.length);
+               break;
+
+       case DCERPC_AUTH_LEVEL_NONE:
+               p->security_state.auth_info->credentials = data_blob(NULL, 0);
+               break;
+
+       default:
+               status = NT_STATUS_INVALID_LEVEL;
+               break;
+       }
+
        data_blob_free(&p->security_state.auth_info->credentials);
 
        return NT_STATUS_OK;
@@ -433,8 +465,8 @@ NTSTATUS dcerpc_bind(struct dcerpc_pipe *p,
        pkt.call_id = p->call_id;
        pkt.auth_length = 0;
 
-       pkt.u.bind.max_xmit_frag = 0x2000;
-       pkt.u.bind.max_recv_frag = 0x2000;
+       pkt.u.bind.max_xmit_frag = 5840;
+       pkt.u.bind.max_recv_frag = 5840;
        pkt.u.bind.assoc_group_id = 0;
        pkt.u.bind.num_contexts = 1;
        pkt.u.bind.ctx_list = talloc(mem_ctx, sizeof(pkt.u.bind.ctx_list[0]));
@@ -782,60 +814,44 @@ struct rpc_request *dcerpc_request_send(struct dcerpc_pipe *p,
        pkt.u.request.context_id = 0;
        pkt.u.request.opnum = opnum;
 
-       /* we send a series of pdus without waiting for a reply until
-          the last pdu */
-       while (remaining > chunk_size) {
+       DLIST_ADD(p->pending, req);
+
+       /* we send a series of pdus without waiting for a reply */
+       while (remaining > 0) {
+               uint32_t chunk = MIN(chunk_size, remaining);
+               BOOL last_frag = False;
+
+               pkt.pfc_flags = 0;
+
                if (remaining == stub_data->length) {
-                       pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST;
-               } else {
-                       pkt.pfc_flags = 0;
+                       pkt.pfc_flags |= DCERPC_PFC_FLAG_FIRST;
+               }
+               if (chunk == remaining) {
+                       pkt.pfc_flags |= DCERPC_PFC_FLAG_LAST;
+                       last_frag = True;
                }
 
                pkt.u.request.stub_and_verifier.data = stub_data->data + 
                        (stub_data->length - remaining);
-               pkt.u.request.stub_and_verifier.length = chunk_size;
+               pkt.u.request.stub_and_verifier.length = chunk;
 
                req->status = dcerpc_push_request_sign(p, &blob, mem_ctx, &pkt);
                if (!NT_STATUS_IS_OK(req->status)) {
                        req->state = RPC_REQUEST_DONE;
+                       DLIST_REMOVE(p->pending, req);
                        return req;
                }
                
-               req->status = p->transport.send_request(p, &blob, False);
+               req->status = p->transport.send_request(p, &blob, last_frag);
                if (!NT_STATUS_IS_OK(req->status)) {
                        req->state = RPC_REQUEST_DONE;
+                       DLIST_REMOVE(p->pending, req);
                        return req;
                }               
 
-               remaining -= chunk_size;
-       }
-
-       /* now we send a pdu with LAST_FRAG sent and get the first
-          part of the reply */
-       if (remaining == stub_data->length) {
-               pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
-       } else {
-               pkt.pfc_flags = DCERPC_PFC_FLAG_LAST;
-       }
-       pkt.u.request.stub_and_verifier.data = stub_data->data + 
-               (stub_data->length - remaining);
-       pkt.u.request.stub_and_verifier.length = remaining;
-
-       req->status = dcerpc_push_request_sign(p, &blob, mem_ctx, &pkt);
-       if (!NT_STATUS_IS_OK(req->status)) {
-               req->state = RPC_REQUEST_DONE;
-               return req;
-       }
-
-       /* send the final pdu */
-       req->status = p->transport.send_request(p, &blob, True);
-
-       if (!NT_STATUS_IS_OK(req->status)) {
-               req->state = RPC_REQUEST_DONE;
+               remaining -= chunk;
        }
 
-       DLIST_ADD(p->pending, req);
-
        return req;
 }
 
index 16bf52cec2c4d3f29e65858b27babef113607adf..242a18368f67ab6c2ad5b0334c8012ed45703f37 100644 (file)
@@ -29,6 +29,9 @@ struct dcerpc_pipe;
 struct dcerpc_security {
        struct dcerpc_auth *auth_info;
        struct gensec_security *generic_state;
+
+       /* get the session key */
+       NTSTATUS (*session_key)(struct dcerpc_pipe *, DATA_BLOB *);
 };
 
 struct dcerpc_pipe {
@@ -64,8 +67,6 @@ struct dcerpc_pipe {
                   has been received */
                void (*recv_data)(struct dcerpc_pipe *, DATA_BLOB *, NTSTATUS status);
 
-               /* get the transport level session key */
-               NTSTATUS (*session_key)(struct dcerpc_pipe *, DATA_BLOB *);
        } transport;
 
        /* the last fault code from a DCERPC fault */
index 9587fb9390ca2d0583a5213205384c3e1cdada22..0966b7033855968acdd8069dd1b7aa4fcbd8fb9a 100644 (file)
@@ -107,13 +107,16 @@ NTSTATUS dcerpc_bind_auth3(struct dcerpc_pipe *p, uint8_t auth_type, uint8_t aut
        }
 
        p->security_state.auth_info->credentials = credentials;
-
+       
        status = dcerpc_auth3(p, mem_ctx);
 done:
        talloc_destroy(mem_ctx);
 
        if (!NT_STATUS_IS_OK(status)) {
                ZERO_STRUCT(p->security_state);
+       } else {
+               /* Authenticated connections use the generic session key */
+               p->security_state.session_key = dcerpc_generic_session_key;
        }
 
        return status;
@@ -196,6 +199,9 @@ done:
 
        if (!NT_STATUS_IS_OK(status)) {
                ZERO_STRUCT(p->security_state);
+       } else {
+               /* Authenticated connections use the generic session key */
+               p->security_state.session_key = dcerpc_generic_session_key;
        }
 
        return status;
index efe609f9a368dcb2f55411d0049a78acf4ac0d2a..9aa2b0c88d48ac4fb5c8bd03c7a573fe7952051c 100644 (file)
@@ -50,7 +50,9 @@ static NTSTATUS dcerpc_schannel_key(struct dcerpc_pipe *p,
 */
 static NTSTATUS dcerpc_schannel_unseal_packet(struct gensec_security *gensec_security, 
                                              TALLOC_CTX *mem_ctx, 
-                                             uint8_t *data, size_t length, DATA_BLOB *sig)
+                                             uint8_t *data, size_t length, 
+                                             const uint8_t *whole_pdu, size_t pdu_length, 
+                                             DATA_BLOB *sig)
 {
        struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data;
        
@@ -60,6 +62,7 @@ static NTSTATUS dcerpc_schannel_unseal_packet(struct gensec_security *gensec_sec
 static NTSTATUS dcerpc_schannel_check_packet(struct gensec_security *gensec_security, 
                                             TALLOC_CTX *mem_ctx, 
                                             const uint8_t *data, size_t length, 
+                                            const uint8_t *whole_pdu, size_t pdu_length, 
                                             const DATA_BLOB *sig)
 {
        struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data;
@@ -70,6 +73,7 @@ static NTSTATUS dcerpc_schannel_check_packet(struct gensec_security *gensec_secu
 static NTSTATUS dcerpc_schannel_seal_packet(struct gensec_security *gensec_security, 
                                            TALLOC_CTX *mem_ctx, 
                                            uint8_t *data, size_t length, 
+                                           const uint8_t *whole_pdu, size_t pdu_length, 
                                            DATA_BLOB *sig)
 {
        struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data;
@@ -80,6 +84,7 @@ static NTSTATUS dcerpc_schannel_seal_packet(struct gensec_security *gensec_secur
 static NTSTATUS dcerpc_schannel_sign_packet(struct gensec_security *gensec_security, 
                                            TALLOC_CTX *mem_ctx, 
                                            const uint8_t *data, size_t length, 
+                                           const uint8_t *whole_pdu, size_t pdu_length, 
                                            DATA_BLOB *sig)
 {
        struct dcerpc_schannel_state *dce_schan_state = gensec_security->private_data;
index fa9101bbd6c91232041d2240758fb73bb1ad721b..eece07c678410ccad5d244fcca3ea7060f3a5300 100644 (file)
@@ -359,7 +359,6 @@ NTSTATUS smb_session_key(struct dcerpc_pipe *p, DATA_BLOB *session_key)
                *session_key = smb->tree->session->user_session_key;
                return NT_STATUS_OK;
        }
-
        return NT_STATUS_NO_USER_SESSION_KEY;
 }
 
@@ -425,13 +424,15 @@ NTSTATUS dcerpc_pipe_open_smb(struct dcerpc_pipe **p,
        (*p)->transport.private = NULL;
        (*p)->transport.shutdown_pipe = smb_shutdown_pipe;
        (*p)->transport.peer_name = smb_peer_name;
-       (*p)->transport.session_key = smb_session_key;
 
        (*p)->transport.send_request = smb_send_request;
        (*p)->transport.send_read = send_read_request;
        (*p)->transport.event_context = smb_event_context;
        (*p)->transport.recv_data = NULL;
        
+       /* Over-ride the default session key with the SMB session key */
+       (*p)->security_state.session_key = smb_session_key;
+
        smb = talloc((*p), sizeof(*smb));
        if (!smb) {
                dcerpc_pipe_close(*p);
index c290891b61ea44710e3fa14812289dc499123cde..2152c4c5d0fb0db580710d54c85cb49abe699222 100644 (file)
@@ -87,6 +87,10 @@ static void tcp_process_send(struct dcerpc_pipe *p)
                        }
                        break;
                }
+               if (ret == 0) {
+                       tcp_sock_dead(p, NT_STATUS_NET_WRITE_FAULT);
+                       break;
+               }
 
                blob->data.data += ret;
                blob->data.length -= ret;
@@ -271,19 +275,6 @@ static const char *tcp_peer_name(struct dcerpc_pipe *p)
        return tcp->server_name;
 }
 
-
-/*
-  fetch the user session key 
-*/
-NTSTATUS tcp_session_key(struct dcerpc_pipe *p, DATA_BLOB *session_key)
-{
-       /* this took quite a few CPU cycles to find ... */
-       session_key->data = "SystemLibraryDTC";
-       session_key->length = 16;
-
-       return NT_STATUS_OK;
-}
-
 /* 
    open a rpc connection to a named pipe 
 */
@@ -331,7 +322,6 @@ NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_pipe **p,
 
        (*p)->transport.shutdown_pipe = tcp_shutdown_pipe;
        (*p)->transport.peer_name = tcp_peer_name;
-       (*p)->transport.session_key = tcp_session_key;
        
        tcp = talloc((*p), sizeof(*tcp));
        if (!tcp) {
@@ -356,5 +346,8 @@ NTSTATUS dcerpc_pipe_open_tcp(struct dcerpc_pipe **p,
 
        (*p)->transport.private = tcp;
 
+       /* ensure we don't get SIGPIPE */
+       BlockSignals(True,SIGPIPE);
+
         return NT_STATUS_OK;
 }
index fc9f6c847dd63cdbac0517611724f5cf3a0d4575..18985750034dca8435e6e90a7fdd703b1707eef4 100644 (file)
@@ -458,8 +458,7 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p,
                pipe_name += 6;
        }
            
-       if ((binding->flags & (DCERPC_SCHANNEL_ANY | DCERPC_SIGN | DCERPC_SEAL))
-               || !username || !username[0]) {
+       if (!username || !username[0]) {
                status = smbcli_full_connection(&cli, lp_netbios_name(),
                                             binding->host, NULL, 
                                             "ipc$", "?????", 
@@ -500,6 +499,7 @@ static NTSTATUS dcerpc_pipe_connect_ncacn_np(struct dcerpc_pipe **p,
                status = dcerpc_bind_auth_ntlm(*p, pipe_uuid, pipe_version, domain, username, password);
        } else {    
                status = dcerpc_bind_auth_none(*p, pipe_uuid, pipe_version);
+
        }
 
        if (!NT_STATUS_IS_OK(status)) {
@@ -691,15 +691,22 @@ NTSTATUS dcerpc_secondary_connection(struct dcerpc_pipe *p, struct dcerpc_pipe *
        return NT_STATUS_OK;
 }
 
+NTSTATUS dcerpc_generic_session_key(struct dcerpc_pipe *p,
+                                 DATA_BLOB *session_key)
+{
+       /* this took quite a few CPU cycles to find ... */
+       session_key->data = "SystemLibraryDTC";
+       session_key->length = 16;
+       return NT_STATUS_OK;
+}
 
 /*
-  fetch the user session key for the underlying transport. Currently
-  only works for the ncacn_np transport
+  fetch the user session key - may be default (above) or the SMB session key
 */
 NTSTATUS dcerpc_fetch_session_key(struct dcerpc_pipe *p,
                                  DATA_BLOB *session_key)
 {
-       return p->transport.session_key(p, session_key);
+       return p->security_state.session_key(p, session_key);
 }
 
 
index 119732975376110c26f822f709110e109311f4c3..ea029d4d7da1cd403284755ee7d1466e48c56b40 100644 (file)
@@ -186,11 +186,10 @@ BOOL dcesrv_auth_auth3(struct dcesrv_call_state *call)
        return True;
 }
 
-
 /*
   check credentials on a request
 */
-BOOL dcesrv_auth_request(struct dcesrv_call_state *call)
+BOOL dcesrv_auth_request(struct dcesrv_call_state *call, DATA_BLOB *full_packet)
 {
        struct dcerpc_packet *pkt = &call->pkt;
        struct dcesrv_connection *dce_conn = call->conn;
@@ -238,6 +237,8 @@ BOOL dcesrv_auth_request(struct dcesrv_call_state *call)
                                              call->mem_ctx,
                                              pkt->u.request.stub_and_verifier.data, 
                                              pkt->u.request.stub_and_verifier.length, 
+                                             full_packet->data,
+                                             full_packet->length-auth.credentials.length,
                                              &auth.credentials);
                break;
 
@@ -246,6 +247,8 @@ BOOL dcesrv_auth_request(struct dcesrv_call_state *call)
                                             call->mem_ctx,
                                             pkt->u.request.stub_and_verifier.data, 
                                             pkt->u.request.stub_and_verifier.length,
+                                            full_packet->data,
+                                            full_packet->length-auth.credentials.length,
                                             &auth.credentials);
                break;
 
@@ -254,7 +257,7 @@ BOOL dcesrv_auth_request(struct dcesrv_call_state *call)
                break;
        }
 
-       /* remove the indicated amount of paddiing */
+       /* remove the indicated amount of padding */
        if (pkt->u.request.stub_and_verifier.length < auth.auth_pad_length) {
                return False;
        }
@@ -298,13 +301,35 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
        dce_conn->auth_state.auth_info->auth_pad_length = NDR_ALIGN(ndr, 8);
        ndr_push_zero(ndr, dce_conn->auth_state.auth_info->auth_pad_length);
 
+       
+       dce_conn->auth_state.auth_info->credentials
+               = data_blob_talloc(call->mem_ctx, NULL, 
+                                  gensec_sig_size(dce_conn->auth_state.gensec_security));
+
+       /* add the auth verifier */
+       status = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, dce_conn->auth_state.auth_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               return False;
+       }
+
+       /* extract the whole packet as a blob */
+       *blob = ndr_push_blob(ndr);
+
+       /* fill in the fragment length and auth_length, we can't fill
+          in these earlier as we don't know the signature length (it
+          could be variable length) */
+       dcerpc_set_frag_length(blob, blob->length);
+       dcerpc_set_auth_length(blob, dce_conn->auth_state.auth_info->credentials.length);
+
        /* sign or seal the packet */
        switch (dce_conn->auth_state.auth_info->auth_level) {
        case DCERPC_AUTH_LEVEL_PRIVACY:
                status = gensec_seal_packet(dce_conn->auth_state.gensec_security, 
-                                             call->mem_ctx,
-                                             ndr->data + DCERPC_REQUEST_LENGTH, 
-                                             ndr->offset - DCERPC_REQUEST_LENGTH,
+                                           call->mem_ctx,
+                                           ndr->data + DCERPC_REQUEST_LENGTH, 
+                                           ndr->offset - DCERPC_REQUEST_LENGTH,
+                                           blob->data,
+                                           blob->length - dce_conn->auth_state.auth_info->credentials.length,
                                              &dce_conn->auth_state.auth_info->credentials);
                break;
 
@@ -313,7 +338,10 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
                                            call->mem_ctx,
                                            ndr->data + DCERPC_REQUEST_LENGTH, 
                                            ndr->offset - DCERPC_REQUEST_LENGTH,
+                                           blob->data,
+                                           blob->length - dce_conn->auth_state.auth_info->credentials.length,
                                            &dce_conn->auth_state.auth_info->credentials);
+
                break;
        default:
                status = NT_STATUS_INVALID_LEVEL;
@@ -324,21 +352,9 @@ BOOL dcesrv_auth_response(struct dcesrv_call_state *call,
                return False;
        }       
 
-       /* add the auth verifier */
-       status = ndr_push_dcerpc_auth(ndr, NDR_SCALARS|NDR_BUFFERS, dce_conn->auth_state.auth_info);
-       if (!NT_STATUS_IS_OK(status)) {
-               return False;
-       }
-
-       /* extract the whole packet as a blob */
-       *blob = ndr_push_blob(ndr);
-
-       /* fill in the fragment length and auth_length, we can't fill
-          in these earlier as we don't know the signature length (it
-          could be variable length) */
-       dcerpc_set_frag_length(blob, blob->length);
-       dcerpc_set_auth_length(blob, dce_conn->auth_state.auth_info->credentials.length);
-
+       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;
index 57b337693f58b0379343ed271a0473f23945e138..dc4356bac150332b4b1cdd65e6872991982f87ec 100644 (file)
@@ -46,7 +46,7 @@ BOOL torture_ntlmssp_self_check(int dummy)
 
        data = strhex_to_data_blob("6a43494653");
        ntlmssp_sign_packet(ntlmssp_state, ntlmssp_state->mem_ctx, 
-                           data.data, data.length, &sig);
+                           data.data, data.length, data.data, data.length, &sig);
 
        expected_sig = strhex_to_data_blob("01000000e37f97f2544f4d7e00000000");
 
@@ -83,7 +83,7 @@ BOOL torture_ntlmssp_self_check(int dummy)
 
        data = strhex_to_data_blob("6a43494653");
        ntlmssp_sign_packet(ntlmssp_state, ntlmssp_state->mem_ctx, 
-                           data.data, data.length, &sig);
+                           data.data, data.length, data.data, data.length, &sig);
 
        expected_sig = strhex_to_data_blob("0100000078010900397420fe0e5a0f89");