The branch, master has been updated
       via  97d7a524abc4993f231357ef22c637994d2cdcb9 (commit)
       via  799f8d7e13cc712f32cdd779770e4868ad17486b (commit)
       via  f3979b50a9b2aacb0497df770f09950b78878fcc (commit)
      from  1a21db8ea11b3f07b007fe0cb48ff08b1ce75ba0 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 97d7a524abc4993f231357ef22c637994d2cdcb9
Author: Günther Deschner <[email protected]>
Date:   Wed Sep 16 00:52:33 2009 +0200

    s3-schannel: remove unused schannel_decode/schannel_encode.
    
    Guenther

commit 799f8d7e13cc712f32cdd779770e4868ad17486b
Author: Günther Deschner <[email protected]>
Date:   Wed Sep 16 00:26:17 2009 +0200

    schannel: fully share schannel sign/seal between s3 and 4.
    
    Guenther

commit f3979b50a9b2aacb0497df770f09950b78878fcc
Author: Günther Deschner <[email protected]>
Date:   Tue Sep 15 18:29:10 2009 +0200

    schannel: move schannel_sign to main directory.
    
    Guenther

-----------------------------------------------------------------------

Summary of changes:
 libcli/auth/schannel.h                        |   38 ++++
 libcli/auth/schannel_proto.h                  |   42 ++++
 libcli/auth/schannel_sign.c                   |  271 +++++++++++++++++++++++
 libcli/auth/schannel_state_ldb.c              |    1 +
 source3/Makefile.in                           |    1 +
 source3/auth/auth_netlogond.c                 |   26 ++--
 source3/include/client.h                      |    2 +-
 source3/include/ntdomain.h                    |    2 +-
 source3/include/proto.h                       |    9 +-
 source3/rpc_client/cli_pipe.c                 |  105 ++++++----
 source3/rpc_parse/parse_prs.c                 |  286 -------------------------
 source3/rpc_server/srv_netlog_nt.c            |    3 +-
 source3/rpc_server/srv_pipe.c                 |   85 +++++---
 source4/auth/gensec/config.mk                 |    2 +-
 source4/auth/gensec/schannel.c                |    3 +-
 source4/auth/gensec/schannel.h                |   39 ----
 source4/auth/gensec/schannel_sign.c           |  271 -----------------------
 source4/rpc_server/netlogon/dcerpc_netlogon.c |    3 +-
 18 files changed, 500 insertions(+), 689 deletions(-)
 create mode 100644 libcli/auth/schannel.h
 create mode 100644 libcli/auth/schannel_proto.h
 create mode 100644 libcli/auth/schannel_sign.c
 delete mode 100644 source4/auth/gensec/schannel.h
 delete mode 100644 source4/auth/gensec/schannel_sign.c


Changeset truncated at 500 lines:

diff --git a/libcli/auth/schannel.h b/libcli/auth/schannel.h
new file mode 100644
index 0000000..bfccd95
--- /dev/null
+++ b/libcli/auth/schannel.h
@@ -0,0 +1,38 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   dcerpc schannel operations
+
+   Copyright (C) Andrew Tridgell 2004
+   Copyright (C) Andrew Bartlett <[email protected]> 2004-2005
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "libcli/auth/libcli_auth.h"
+#include "libcli/auth/schannel_state.h"
+
+enum schannel_position {
+       SCHANNEL_STATE_START = 0,
+       SCHANNEL_STATE_UPDATE_1
+};
+
+struct schannel_state {
+       enum schannel_position state;
+       uint32_t seq_num;
+       bool initiator;
+       struct netlogon_creds_CredentialState *creds;
+};
+
+#include "libcli/auth/schannel_proto.h"
diff --git a/libcli/auth/schannel_proto.h b/libcli/auth/schannel_proto.h
new file mode 100644
index 0000000..d31707d
--- /dev/null
+++ b/libcli/auth/schannel_proto.h
@@ -0,0 +1,42 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   dcerpc schannel operations
+
+   Copyright (C) Andrew Tridgell 2004
+   Copyright (C) Andrew Bartlett <[email protected]> 2004-2005
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _LIBCLI_AUTH_SCHANNEL_PROTO_H__
+#define _LIBCLI_AUTH_SCHANNEL_PROTO_H__
+
+NTSTATUS schannel_unseal_packet(struct schannel_state *state,
+                               TALLOC_CTX *mem_ctx,
+                               uint8_t *data, size_t length,
+                               const DATA_BLOB *sig);
+NTSTATUS schannel_check_packet(struct schannel_state *state,
+                              TALLOC_CTX *mem_ctx,
+                              const uint8_t *data, size_t length,
+                              const DATA_BLOB *sig);
+NTSTATUS schannel_seal_packet(struct schannel_state *state,
+                             TALLOC_CTX *mem_ctx,
+                             uint8_t *data, size_t length,
+                             DATA_BLOB *sig);
+NTSTATUS schannel_sign_packet(struct schannel_state *state,
+                             TALLOC_CTX *mem_ctx,
+                             const uint8_t *data, size_t length,
+                             DATA_BLOB *sig);
+#endif
diff --git a/libcli/auth/schannel_sign.c b/libcli/auth/schannel_sign.c
new file mode 100644
index 0000000..45f3989
--- /dev/null
+++ b/libcli/auth/schannel_sign.c
@@ -0,0 +1,271 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   schannel library code
+
+   Copyright (C) Andrew Tridgell 2004
+   Copyright (C) Andrew Bartlett <[email protected]> 2005
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "../libcli/auth/schannel.h"
+#include "../lib/crypto/crypto.h"
+#include "auth/gensec/gensec.h"
+#include "auth/gensec/gensec_proto.h"
+
+#define NETSEC_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 
}
+#define NETSEC_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 
}
+
+/*******************************************************************
+ Encode or Decode the sequence number (which is symmetric)
+ ********************************************************************/
+static void netsec_deal_with_seq_num(struct schannel_state *state,
+                                    const uint8_t packet_digest[8],
+                                    uint8_t seq_num[8])
+{
+       static const uint8_t zeros[4];
+       uint8_t sequence_key[16];
+       uint8_t digest1[16];
+
+       hmac_md5(state->creds->session_key, zeros, sizeof(zeros), digest1);
+       hmac_md5(digest1, packet_digest, 8, sequence_key);
+       arcfour_crypt(seq_num, sequence_key, 8);
+
+       state->seq_num++;
+}
+
+
+/*******************************************************************
+ Calculate the key with which to encode the data payload
+ ********************************************************************/
+static void netsec_get_sealing_key(const uint8_t session_key[16],
+                                  const uint8_t seq_num[8],
+                                  uint8_t sealing_key[16])
+{
+       static const uint8_t zeros[4];
+       uint8_t digest2[16];
+       uint8_t sess_kf0[16];
+       int i;
+
+       for (i = 0; i < 16; i++) {
+               sess_kf0[i] = session_key[i] ^ 0xf0;
+       }
+
+       hmac_md5(sess_kf0, zeros, 4, digest2);
+       hmac_md5(digest2, seq_num, 8, sealing_key);
+}
+
+
+/*******************************************************************
+ Create a digest over the entire packet (including the data), and
+ MD5 it with the session key.
+ ********************************************************************/
+static void schannel_digest(const uint8_t sess_key[16],
+                           const uint8_t netsec_sig[8],
+                           const uint8_t *confounder,
+                           const uint8_t *data, size_t data_len,
+                           uint8_t digest_final[16])
+{
+       uint8_t packet_digest[16];
+       static const uint8_t zeros[4];
+       struct MD5Context ctx;
+
+       MD5Init(&ctx);
+       MD5Update(&ctx, zeros, 4);
+       MD5Update(&ctx, netsec_sig, 8);
+       if (confounder) {
+               MD5Update(&ctx, confounder, 8);
+       }
+       MD5Update(&ctx, data, data_len);
+       MD5Final(packet_digest, &ctx);
+
+       hmac_md5(sess_key, packet_digest, sizeof(packet_digest), digest_final);
+}
+
+
+/*
+  unseal a packet
+*/
+NTSTATUS schannel_unseal_packet(struct schannel_state *state,
+                               TALLOC_CTX *mem_ctx,
+                               uint8_t *data, size_t length,
+                               const DATA_BLOB *sig)
+{
+       uint8_t digest_final[16];
+       uint8_t confounder[8];
+       uint8_t seq_num[8];
+       uint8_t sealing_key[16];
+       static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE;
+
+       if (sig->length != 32) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       memcpy(confounder, sig->data+24, 8);
+
+       RSIVAL(seq_num, 0, state->seq_num);
+       SIVAL(seq_num, 4, state->initiator?0:0x80);
+
+       netsec_get_sealing_key(state->creds->session_key, seq_num, sealing_key);
+       arcfour_crypt(confounder, sealing_key, 8);
+       arcfour_crypt(data, sealing_key, length);
+
+       schannel_digest(state->creds->session_key,
+                       netsec_sig, confounder,
+                       data, length, digest_final);
+
+       if (memcmp(digest_final, sig->data+16, 8) != 0) {
+               dump_data_pw("calc digest:", digest_final, 8);
+               dump_data_pw("wire digest:", sig->data+16, 8);
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       netsec_deal_with_seq_num(state, digest_final, seq_num);
+
+       if (memcmp(seq_num, sig->data+8, 8) != 0) {
+               dump_data_pw("calc seq num:", seq_num, 8);
+               dump_data_pw("wire seq num:", sig->data+8, 8);
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return NT_STATUS_OK;
+}
+
+/*
+  check the signature on a packet
+*/
+NTSTATUS schannel_check_packet(struct schannel_state *state,
+                              TALLOC_CTX *mem_ctx,
+                              const uint8_t *data, size_t length,
+                              const DATA_BLOB *sig)
+{
+       uint8_t digest_final[16];
+       uint8_t seq_num[8];
+       static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE;
+
+       /* w2k sends just 24 bytes and skip the confounder */
+       if (sig->length != 32 && sig->length != 24) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       RSIVAL(seq_num, 0, state->seq_num);
+       SIVAL(seq_num, 4, state->initiator?0:0x80);
+
+       dump_data_pw("seq_num:\n", seq_num, 8);
+       dump_data_pw("sess_key:\n", state->creds->session_key, 16);
+
+       schannel_digest(state->creds->session_key,
+                       netsec_sig, NULL,
+                       data, length, digest_final);
+
+       netsec_deal_with_seq_num(state, digest_final, seq_num);
+
+       if (memcmp(seq_num, sig->data+8, 8) != 0) {
+               dump_data_pw("calc seq num:", seq_num, 8);
+               dump_data_pw("wire seq num:", sig->data+8, 8);
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       if (memcmp(digest_final, sig->data+16, 8) != 0) {
+               dump_data_pw("calc digest:", digest_final, 8);
+               dump_data_pw("wire digest:", sig->data+16, 8);
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return NT_STATUS_OK;
+}
+
+
+/*
+  seal a packet
+*/
+NTSTATUS schannel_seal_packet(struct schannel_state *state,
+                             TALLOC_CTX *mem_ctx,
+                             uint8_t *data, size_t length,
+                             DATA_BLOB *sig)
+{
+       uint8_t digest_final[16];
+       uint8_t confounder[8];
+       uint8_t seq_num[8];
+       uint8_t sealing_key[16];
+       static const uint8_t netsec_sig[8] = NETSEC_SEAL_SIGNATURE;
+
+       generate_random_buffer(confounder, 8);
+
+       RSIVAL(seq_num, 0, state->seq_num);
+       SIVAL(seq_num, 4, state->initiator?0x80:0);
+
+       schannel_digest(state->creds->session_key,
+                       netsec_sig, confounder,
+                       data, length, digest_final);
+
+       netsec_get_sealing_key(state->creds->session_key, seq_num, sealing_key);
+       arcfour_crypt(confounder, sealing_key, 8);
+       arcfour_crypt(data, sealing_key, length);
+
+       netsec_deal_with_seq_num(state, digest_final, seq_num);
+
+       (*sig) = data_blob_talloc(mem_ctx, NULL, 32);
+
+       memcpy(sig->data, netsec_sig, 8);
+       memcpy(sig->data+8, seq_num, 8);
+       memcpy(sig->data+16, digest_final, 8);
+       memcpy(sig->data+24, confounder, 8);
+
+       dump_data_pw("signature:", sig->data+ 0, 8);
+       dump_data_pw("seq_num  :", sig->data+ 8, 8);
+       dump_data_pw("digest   :", sig->data+16, 8);
+       dump_data_pw("confound :", sig->data+24, 8);
+
+       return NT_STATUS_OK;
+}
+
+
+/*
+  sign a packet
+*/
+NTSTATUS schannel_sign_packet(struct schannel_state *state,
+                             TALLOC_CTX *mem_ctx,
+                             const uint8_t *data, size_t length,
+                             DATA_BLOB *sig)
+{
+       uint8_t digest_final[16];
+       uint8_t seq_num[8];
+       static const uint8_t netsec_sig[8] = NETSEC_SIGN_SIGNATURE;
+
+       RSIVAL(seq_num, 0, state->seq_num);
+       SIVAL(seq_num, 4, state->initiator?0x80:0);
+
+       schannel_digest(state->creds->session_key,
+                       netsec_sig, NULL,
+                       data, length, digest_final);
+
+       netsec_deal_with_seq_num(state, digest_final, seq_num);
+
+       (*sig) = data_blob_talloc(mem_ctx, NULL, 32);
+
+       memcpy(sig->data, netsec_sig, 8);
+       memcpy(sig->data+8, seq_num, 8);
+       memcpy(sig->data+16, digest_final, 8);
+       memset(sig->data+24, 0, 8);
+
+       dump_data_pw("signature:", sig->data+ 0, 8);
+       dump_data_pw("seq_num  :", sig->data+ 8, 8);
+       dump_data_pw("digest   :", sig->data+16, 8);
+       dump_data_pw("confound :", sig->data+24, 8);
+
+       return NT_STATUS_OK;
+}
diff --git a/libcli/auth/schannel_state_ldb.c b/libcli/auth/schannel_state_ldb.c
index 37458c7..69d6bad 100644
--- a/libcli/auth/schannel_state_ldb.c
+++ b/libcli/auth/schannel_state_ldb.c
@@ -29,6 +29,7 @@
 #include "auth/auth.h"
 #include "param/param.h"
 #include "auth/gensec/schannel_state.h"
+#include "../libcli/auth/schannel_state_proto.h"
 
 static struct ldb_val *schannel_dom_sid_ldb_val(TALLOC_CTX *mem_ctx,
                                                struct dom_sid *sid)
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 903ae94..65feb84 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -496,6 +496,7 @@ CLDAP_OBJ = libads/cldap.o \
 TLDAP_OBJ = lib/tldap.o lib/tldap_util.o lib/util_tsock.o
 
 SCHANNEL_OBJ = ../libcli/auth/credentials.o \
+              ../libcli/auth/schannel_sign.o \
               ../libcli/auth/schannel_state_tdb.o \
               ../librpc/gen_ndr/ndr_schannel.o \
               ../librpc/ndr/ndr_schannel.o \
diff --git a/source3/auth/auth_netlogond.c b/source3/auth/auth_netlogond.c
index 5f4d2f1..8c930a5 100644
--- a/source3/auth/auth_netlogond.c
+++ b/source3/auth/auth_netlogond.c
@@ -46,9 +46,21 @@ static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx,
                return status;
        }
 
+       /*
+        * We have to fake a struct dcinfo, so that
+        * rpccli_netlogon_sam_network_logon_ex can decrypt the session keys.
+        */
+
+       p->dc = netlogon_creds_client_init_session_key(p, schannel_key);
+       if (p->dc == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               TALLOC_FREE(p);
+               return NT_STATUS_NO_MEMORY;
+       }
+
        status = rpccli_schannel_bind_data(p, lp_workgroup(),
                                           DCERPC_AUTH_LEVEL_PRIVACY,
-                                          schannel_key, &auth);
+                                          p->dc, &auth);
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(10, ("rpccli_schannel_bind_data failed: %s\n",
                           nt_errstr(status)));
@@ -64,18 +76,6 @@ static NTSTATUS netlogond_validate(TALLOC_CTX *mem_ctx,
                return status;
        }
 
-       /*
-        * We have to fake a struct dcinfo, so that
-        * rpccli_netlogon_sam_network_logon_ex can decrypt the session keys.
-        */
-
-       p->dc = netlogon_creds_client_init_session_key(p, schannel_key);
-       if (p->dc == NULL) {
-               DEBUG(0, ("talloc failed\n"));
-               TALLOC_FREE(p);
-               return NT_STATUS_NO_MEMORY;
-       }
-
        status = rpccli_netlogon_sam_network_logon_ex(
                p, p,
                user_info->logon_parameters,/* flags such as 'allow
diff --git a/source3/include/client.h b/source3/include/client.h
index e83927c..82d94b0 100644
--- a/source3/include/client.h
+++ b/source3/include/client.h
@@ -55,7 +55,7 @@ struct cli_pipe_auth_data {
        DATA_BLOB user_session_key;
 
        union {
-               struct schannel_auth_struct *schannel_auth;
+               struct schannel_state *schannel_auth;
                NTLMSSP_STATE *ntlmssp_state;
                struct kerberos_auth_struct *kerberos_auth;
        } a_u;
diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h
index 1d303ca..f904782 100644
--- a/source3/include/ntdomain.h
+++ b/source3/include/ntdomain.h
@@ -150,7 +150,7 @@ struct pipe_auth_data {
        enum pipe_auth_type auth_type; /* switch for union below. */
        enum dcerpc_AuthLevel auth_level;
        union {
-               struct schannel_auth_struct *schannel_auth;
+               struct schannel_state *schannel_auth;
                AUTH_NTLMSSP_STATE *auth_ntlmssp_state;
 /*             struct kerberos_auth_struct *kerberos_auth; TO BE ADDED... */
        } a_u;
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 35d1a99..8af6dba 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -5298,7 +5298,7 @@ NTSTATUS rpccli_ntlmssp_bind_data(TALLOC_CTX *mem_ctx,
                                  struct cli_pipe_auth_data **presult);
 NTSTATUS rpccli_schannel_bind_data(TALLOC_CTX *mem_ctx, const char *domain,
                                   enum dcerpc_AuthLevel auth_level,
-                                  const uint8_t sess_key[16],
+                                  struct netlogon_creds_CredentialState *creds,
                                   struct cli_pipe_auth_data **presult);
 NTSTATUS rpccli_kerberos_bind_data(TALLOC_CTX *mem_ctx,
                                   enum dcerpc_AuthLevel auth_level,
@@ -5706,13 +5706,6 @@ bool prs_uint16s(bool charmode, const char *name, 
prs_struct *ps, int depth, uin
 bool prs_uint32s(bool charmode, const char *name, prs_struct *ps, int depth, 
uint32 *data32s, int len);
 bool prs_unistr(const char *name, prs_struct *ps, int depth, UNISTR *str);
 bool prs_string(const char *name, prs_struct *ps, int depth, char *str, int 
max_buf_size);
-void schannel_encode(struct schannel_auth_struct *a, enum dcerpc_AuthLevel 
auth_level,
-                  enum schannel_direction direction,
-                  struct NL_AUTH_SIGNATURE *verf,
-                  char *data, size_t data_len);
-bool schannel_decode(struct schannel_auth_struct *a, enum dcerpc_AuthLevel 
auth_level,
-                  enum schannel_direction direction, 
-                  struct NL_AUTH_SIGNATURE *verf, char *data, size_t data_len);
 bool prs_init_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx);
 bool prs_data_blob(prs_struct *prs, DATA_BLOB *blob, TALLOC_CTX *mem_ctx);
 
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index d71c561..febf787 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -21,6 +21,8 @@
 #include "../libcli/auth/libcli_auth.h"
 #include "librpc/gen_ndr/cli_epmapper.h"
 #include "../librpc/gen_ndr/ndr_schannel.h"


-- 
Samba Shared Repository

Reply via email to