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