summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2009-03-09 09:47:59 +0100
committerStefan Metzmacher <metze@samba.org>2009-03-23 12:21:13 +0100
commitc16c90a1cb3b0e2ceadd3dea835a4e69acfc2fae (patch)
treeda998f5b8d22a1183603e8d21f82035ffa52a6ec
parent2654653f55ed5744cc9fca6a79127386f55425e1 (diff)
downloadsamba-c16c90a1cb3b0e2ceadd3dea835a4e69acfc2fae.tar.gz
s3:smbd: use new simplified snb_signing code in the server
We keep the seqnum/mid mapping in the smb_request structure. This also moves one global variable into the smbd_server_connection struct. metze
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/include/proto.h32
-rw-r--r--source3/include/smb.h2
-rw-r--r--source3/libsmb/clisigning.c333
-rw-r--r--source3/param/loadparm.c11
-rw-r--r--source3/smbd/aio.c13
-rw-r--r--source3/smbd/blocking.c5
-rw-r--r--source3/smbd/globals.h1
-rw-r--r--source3/smbd/ipc.c4
-rw-r--r--source3/smbd/negprot.c2
-rw-r--r--source3/smbd/notify.c7
-rw-r--r--source3/smbd/nttrans.c3
-rw-r--r--source3/smbd/open.c9
-rw-r--r--source3/smbd/oplock.c27
-rw-r--r--source3/smbd/password.c8
-rw-r--r--source3/smbd/pipes.c1
-rw-r--r--source3/smbd/process.c50
-rw-r--r--source3/smbd/reply.c24
-rw-r--r--source3/smbd/service.c2
-rw-r--r--source3/smbd/sesssetup.c25
-rw-r--r--source3/smbd/signing.c158
-rw-r--r--source3/smbd/trans2.c5
22 files changed, 270 insertions, 454 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 8dbb7b5d67c..46216c7f085 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -733,7 +733,7 @@ SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
smbd/change_trust_pw.o smbd/fake_file.o \
smbd/quotas.o smbd/ntquotas.o $(AFS_OBJ) smbd/msdfs.o \
$(AFS_SETTOKEN_OBJ) smbd/aio.o smbd/statvfs.o \
- smbd/dmapi.o \
+ smbd/dmapi.o smbd/signing.o \
smbd/file_access.o \
smbd/dnsregister.o smbd/globals.o \
$(MANGLE_OBJ) @VFS_STATIC@
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 1ed623c4cb2..356eb4935fd 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -3194,16 +3194,22 @@ bool cli_check_sign_mac(struct cli_state *cli, char *buf);
bool client_set_trans_sign_state_on(struct cli_state *cli, uint16 mid);
bool client_set_trans_sign_state_off(struct cli_state *cli, uint16 mid);
bool client_is_signing_on(struct cli_state *cli);
-bool srv_oplock_set_signing(bool onoff);
-bool srv_check_sign_mac(const char *inbuf, bool must_be_ok);
-void srv_calculate_sign_mac(char *outbuf);
-void srv_defer_sign_response(uint16 mid);
-void srv_cancel_sign_response(uint16 mid, bool cancel);
-void srv_set_signing_negotiated(void);
-bool srv_is_signing_active(void);
-bool srv_is_signing_negotiated(void);
-bool srv_signing_started(void);
-void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response);
+
+/* The following definitions come from smbd/signing.c */
+
+struct smbd_server_connection;
+bool srv_check_sign_mac(struct smbd_server_connection *conn,
+ const char *inbuf, uint32_t *seqnum);
+void srv_calculate_sign_mac(struct smbd_server_connection *conn,
+ char *outbuf, uint32_t seqnum);
+void srv_cancel_sign_response(struct smbd_server_connection *conn);
+bool srv_init_signing(struct smbd_server_connection *conn);
+void srv_set_signing_negotiated(struct smbd_server_connection *conn);
+bool srv_is_signing_active(struct smbd_server_connection *conn);
+bool srv_is_signing_negotiated(struct smbd_server_connection *conn);
+void srv_set_signing(struct smbd_server_connection *conn,
+ const DATA_BLOB user_session_key,
+ const DATA_BLOB response);
/* The following definitions come from libsmb/smbdes.c */
@@ -4347,7 +4353,7 @@ const char *lp_printcapname(void);
bool lp_disable_spoolss( void );
void lp_set_spoolss_state( uint32 state );
uint32 lp_get_spoolss_state( void );
-bool lp_use_sendfile(int snum);
+bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state);
void set_use_sendfile(int snum, bool val);
void set_store_dos_attributes(int snum, bool val);
void lp_set_mangling_method(const char *new_method);
@@ -6722,7 +6728,9 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname);
void smbd_setup_sig_term_handler(void);
void smbd_setup_sig_hup_handler(void);
-bool srv_send_smb(int fd, char *buffer, bool do_encrypt,
+bool srv_send_smb(int fd, char *buffer,
+ bool no_signing, uint32_t seqnum,
+ bool do_encrypt,
struct smb_perfcount_data *pcd);
int srv_set_message(char *buf,
int num_words,
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 281a218256f..215adba1b4a 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -621,6 +621,7 @@ struct smb_request {
uint16 flags2;
uint16 smbpid;
uint16 mid;
+ uint32_t seqnum;
uint16 vuid;
uint16 tid;
uint8 wct;
@@ -722,6 +723,7 @@ struct pending_message_list {
struct timeval request_time; /* When was this first issued? */
struct timed_event *te;
struct smb_perfcount_data pcd;
+ uint32_t seqnum;
bool encrypted;
DATA_BLOB buf;
DATA_BLOB private_data;
diff --git a/source3/libsmb/clisigning.c b/source3/libsmb/clisigning.c
index a3ed0e75729..6644bc0d600 100644
--- a/source3/libsmb/clisigning.c
+++ b/source3/libsmb/clisigning.c
@@ -671,336 +671,3 @@ bool client_is_signing_on(struct cli_state *cli)
struct smb_sign_info *si = &cli->sign_info;
return si->doing_signing;
}
-
-/***********************************************************
- SMB signing - Server implementation - send the MAC.
-************************************************************/
-
-static void srv_sign_outgoing_message(char *outbuf, struct smb_sign_info *si)
-{
- unsigned char calc_md5_mac[16];
- struct smb_basic_signing_context *data =
- (struct smb_basic_signing_context *)si->signing_context;
- uint32 send_seq_number = data->send_seq_num-1;
- uint16 mid;
-
- if (!si->doing_signing) {
- return;
- }
-
- /* JRA Paranioa test - we should be able to get rid of this... */
- if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
- DEBUG(1, ("srv_sign_outgoing_message: Logic error. Can't send signature on short packet! smb_len = %u\n",
- smb_len(outbuf) ));
- abort();
- }
-
- /* mark the packet as signed - BEFORE we sign it...*/
- mark_packet_signed(outbuf);
-
- mid = SVAL(outbuf, smb_mid);
-
- /* See if this is a reply for a deferred packet. */
- get_sequence_for_reply(&data->outstanding_packet_list, mid, &send_seq_number);
-
- simple_packet_signature(data, (const unsigned char *)outbuf, send_seq_number, calc_md5_mac);
-
- DEBUG(10, ("srv_sign_outgoing_message: seq %u: sent SMB signature of\n", (unsigned int)send_seq_number));
- dump_data(10, calc_md5_mac, 8);
-
- memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);
-
-/* cli->outbuf[smb_ss_field+2]=0;
- Uncomment this to test if the remote client actually verifies signatures...*/
-}
-
-/***********************************************************
- SMB signing - Server implementation - check a MAC sent by server.
-************************************************************/
-
-static bool srv_check_incoming_message(const char *inbuf,
- struct smb_sign_info *si,
- bool must_be_ok)
-{
- bool good;
- struct smb_basic_signing_context *data =
- (struct smb_basic_signing_context *)si->signing_context;
- uint32 reply_seq_number = data->send_seq_num;
- uint32 saved_seq;
- unsigned char calc_md5_mac[16];
- unsigned char *server_sent_mac;
-
- if (!si->doing_signing)
- return True;
-
- if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
- DEBUG(1, ("srv_check_incoming_message: Can't check signature on short packet! smb_len = %u\n", smb_len(inbuf)));
- return False;
- }
-
- /* We always increment the sequence number. */
- data->send_seq_num += 2;
-
- saved_seq = reply_seq_number;
- simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
-
- server_sent_mac = (unsigned char *)&inbuf[smb_ss_field];
- good = (memcmp(server_sent_mac, calc_md5_mac, 8) == 0);
-
- if (!good) {
-
- if (saved_seq) {
- DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u wanted SMB signature of\n",
- (unsigned int)saved_seq));
- dump_data(5, calc_md5_mac, 8);
-
- DEBUG(0, ("srv_check_incoming_message: BAD SIG: seq %u got SMB signature of\n",
- (unsigned int)reply_seq_number));
- dump_data(5, server_sent_mac, 8);
- }
-
-#if 1 /* JRATEST */
- {
- int i;
- reply_seq_number -= 5;
- for (i = 0; i < 10; i++, reply_seq_number++) {
- simple_packet_signature(data, (const unsigned char *)inbuf, reply_seq_number, calc_md5_mac);
- if (memcmp(server_sent_mac, calc_md5_mac, 8) == 0) {
- DEBUG(0,("srv_check_incoming_message: out of seq. seq num %u matches. \
-We were expecting seq %u\n", reply_seq_number, saved_seq ));
- break;
- }
- }
- }
-#endif /* JRATEST */
-
- } else {
- DEBUG(10, ("srv_check_incoming_message: seq %u: (current is %u) got good SMB signature of\n", (unsigned int)reply_seq_number, (unsigned int)data->send_seq_num));
- dump_data(10, server_sent_mac, 8);
- }
-
- return (signing_good(inbuf, si, good, saved_seq, must_be_ok));
-}
-
-/***********************************************************
- SMB signing - server API's.
-************************************************************/
-
-static struct smb_sign_info srv_sign_info = {
- null_sign_outgoing_message,
- null_check_incoming_message,
- null_free_signing_context,
- NULL,
- False,
- False,
- False,
- False
-};
-
-/***********************************************************
- Turn signing off or on for oplock break code.
-************************************************************/
-
-bool srv_oplock_set_signing(bool onoff)
-{
- bool ret = srv_sign_info.doing_signing;
- srv_sign_info.doing_signing = onoff;
- return ret;
-}
-
-/***********************************************************
- Called to validate an incoming packet from the client.
-************************************************************/
-
-bool srv_check_sign_mac(const char *inbuf, bool must_be_ok)
-{
- /* Check if it's a non-session message. */
- if(CVAL(inbuf,0)) {
- return True;
- }
-
- return srv_sign_info.check_incoming_message(inbuf, &srv_sign_info, must_be_ok);
-}
-
-/***********************************************************
- Called to sign an outgoing packet to the client.
-************************************************************/
-
-void srv_calculate_sign_mac(char *outbuf)
-{
- /* Check if it's a non-session message. */
- if(CVAL(outbuf,0)) {
- return;
- }
-
- srv_sign_info.sign_outgoing_message(outbuf, &srv_sign_info);
-}
-
-/***********************************************************
- Called by server to defer an outgoing packet.
-************************************************************/
-
-void srv_defer_sign_response(uint16 mid)
-{
- struct smb_basic_signing_context *data;
-
- if (!srv_sign_info.doing_signing)
- return;
-
- data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
-
- if (!data)
- return;
-
- /*
- * Ensure we only store this mid reply once...
- */
-
- store_sequence_for_reply(&data->outstanding_packet_list, mid,
- data->send_seq_num-1);
-}
-
-/***********************************************************
- Called to remove sequence records when a deferred packet is
- cancelled by mid. This should never find one....
-************************************************************/
-
-void srv_cancel_sign_response(uint16 mid, bool cancel)
-{
- struct smb_basic_signing_context *data;
- uint32 dummy_seq;
-
- if (!srv_sign_info.doing_signing)
- return;
-
- data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
-
- if (!data)
- return;
-
- DEBUG(10,("srv_cancel_sign_response: for mid %u\n", (unsigned int)mid ));
-
- while (get_sequence_for_reply(&data->outstanding_packet_list, mid, &dummy_seq))
- ;
-
- /* cancel doesn't send a reply so doesn't burn a sequence number. */
- if (cancel) {
- data->send_seq_num -= 1;
- }
-}
-
-/***********************************************************
- Called by server negprot when signing has been negotiated.
-************************************************************/
-
-void srv_set_signing_negotiated(void)
-{
- srv_sign_info.allow_smb_signing = True;
- srv_sign_info.negotiated_smb_signing = True;
- if (lp_server_signing() == Required)
- srv_sign_info.mandatory_signing = True;
-
- srv_sign_info.sign_outgoing_message = temp_sign_outgoing_message;
- srv_sign_info.check_incoming_message = temp_check_incoming_message;
- srv_sign_info.free_signing_context = temp_free_signing_context;
-}
-
-/***********************************************************
- Returns whether signing is active. We can't use sendfile or raw
- reads/writes if it is.
-************************************************************/
-
-bool srv_is_signing_active(void)
-{
- return srv_sign_info.doing_signing;
-}
-
-
-/***********************************************************
- Returns whether signing is negotiated. We can't use it unless it was
- in the negprot.
-************************************************************/
-
-bool srv_is_signing_negotiated(void)
-{
- return srv_sign_info.negotiated_smb_signing;
-}
-
-/***********************************************************
- Returns whether signing is actually happening
-************************************************************/
-
-bool srv_signing_started(void)
-{
- struct smb_basic_signing_context *data;
-
- if (!srv_sign_info.doing_signing) {
- return False;
- }
-
- data = (struct smb_basic_signing_context *)srv_sign_info.signing_context;
- if (!data)
- return False;
-
- if (data->send_seq_num == 0) {
- return False;
- }
-
- return True;
-}
-
-/***********************************************************
- Turn on signing from this packet onwards.
-************************************************************/
-
-void srv_set_signing(const DATA_BLOB user_session_key, const DATA_BLOB response)
-{
- struct smb_basic_signing_context *data;
-
- if (!user_session_key.length)
- return;
-
- if (!srv_sign_info.negotiated_smb_signing && !srv_sign_info.mandatory_signing) {
- DEBUG(5,("srv_set_signing: signing negotiated = %u, mandatory_signing = %u. Not allowing smb signing.\n",
- (unsigned int)srv_sign_info.negotiated_smb_signing,
- (unsigned int)srv_sign_info.mandatory_signing ));
- return;
- }
-
- /* Once we've turned on, ignore any more sessionsetups. */
- if (srv_sign_info.doing_signing) {
- return;
- }
-
- if (srv_sign_info.free_signing_context)
- srv_sign_info.free_signing_context(&srv_sign_info);
-
- srv_sign_info.doing_signing = True;
-
- data = SMB_XMALLOC_P(struct smb_basic_signing_context);
- memset(data, '\0', sizeof(*data));
-
- srv_sign_info.signing_context = data;
-
- data->mac_key = data_blob(NULL, response.length + user_session_key.length);
-
- memcpy(&data->mac_key.data[0], user_session_key.data, user_session_key.length);
- if (response.length)
- memcpy(&data->mac_key.data[user_session_key.length],response.data, response.length);
-
- dump_data_pw("MAC ssession key is:\n", data->mac_key.data, data->mac_key.length);
-
- DEBUG(3,("srv_set_signing: turning on SMB signing: signing negotiated = %s, mandatory_signing = %s.\n",
- BOOLSTR(srv_sign_info.negotiated_smb_signing),
- BOOLSTR(srv_sign_info.mandatory_signing) ));
-
- /* Initialise the sequence number */
- data->send_seq_num = 0;
-
- /* Initialise the list of outstanding packets */
- data->outstanding_packet_list = NULL;
-
- srv_sign_info.sign_outgoing_message = srv_sign_outgoing_message;
- srv_sign_info.check_incoming_message = srv_check_incoming_message;
- srv_sign_info.free_signing_context = simple_free_signing_context;
-}
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index f49a1bc4c94..8460fea5671 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -9572,15 +9572,20 @@ uint32 lp_get_spoolss_state( void )
Ensure we don't use sendfile if server smb signing is active.
********************************************************************/
-bool lp_use_sendfile(int snum)
+bool lp_use_sendfile(int snum, struct smb_signing_state *signing_state)
{
+ bool sign_active = false;
+
/* Using sendfile blows the brains out of any DOS or Win9x TCP stack... JRA. */
if (Protocol < PROTOCOL_NT1) {
- return False;
+ return false;
+ }
+ if (signing_state) {
+ sign_active = smb_signing_is_active(signing_state);
}
return (_lp_use_sendfile(snum) &&
(get_remote_arch() != RA_WIN95) &&
- !srv_is_signing_active());
+ !sign_active);
}
/*******************************************************************
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c
index cfa4b430ebf..77616be48c6 100644
--- a/source3/smbd/aio.c
+++ b/source3/smbd/aio.c
@@ -197,7 +197,6 @@ bool schedule_aio_read_and_X(connection_struct *conn,
fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt,
(unsigned int)aio_ex->req->mid ));
- srv_defer_sign_response(aio_ex->req->mid);
outstanding_aio_calls++;
return True;
}
@@ -303,6 +302,7 @@ bool schedule_aio_write_and_X(connection_struct *conn,
SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1);
show_msg(aio_ex->outbuf);
if (!srv_send_smb(smbd_server_fd(),aio_ex->outbuf,
+ true, aio_ex->req->seqnum+1,
IS_CONN_ENCRYPTED(fsp->conn),
&req->pcd)) {
exit_server_cleanly("handle_aio_write: srv_send_smb "
@@ -310,8 +310,6 @@ bool schedule_aio_write_and_X(connection_struct *conn,
}
DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write "
"behind for file %s\n", fsp->fsp_name ));
- } else {
- srv_defer_sign_response(aio_ex->req->mid);
}
outstanding_aio_calls++;
@@ -347,7 +345,6 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
/* If errno is ECANCELED then don't return anything to the
* client. */
if (errno == ECANCELED) {
- srv_cancel_sign_response(aio_ex->req->mid, false);
return 0;
}
@@ -378,6 +375,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
smb_setlen(outbuf,outsize - 4);
show_msg(outbuf);
if (!srv_send_smb(smbd_server_fd(),outbuf,
+ true, aio_ex->req->seqnum+1,
IS_CONN_ENCRYPTED(aio_ex->fsp->conn), NULL)) {
exit_server_cleanly("handle_aio_read_complete: srv_send_smb "
"failed.");
@@ -441,7 +439,6 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
/* If errno is ECANCELED then don't return anything to the
* client. */
if (errno == ECANCELED) {
- srv_cancel_sign_response(aio_ex->req->mid, false);
return 0;
}
@@ -475,7 +472,9 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
}
show_msg(outbuf);
- if (!srv_send_smb(smbd_server_fd(),outbuf,IS_CONN_ENCRYPTED(fsp->conn),
+ if (!srv_send_smb(smbd_server_fd(),outbuf,
+ true, aio_ex->req->seqnum+1,
+ IS_CONN_ENCRYPTED(fsp->conn),
NULL)) {
exit_server_cleanly("handle_aio_write: srv_send_smb failed.");
}
@@ -534,7 +533,6 @@ void smbd_aio_complete_mid(unsigned int mid)
if (!aio_ex) {
DEBUG(3,("smbd_aio_complete_mid: Can't find record to "
"match mid %u.\n", mid));
- srv_cancel_sign_response(mid, false);
return;
}
@@ -544,7 +542,6 @@ void smbd_aio_complete_mid(unsigned int mid)
* ignore. */
DEBUG( 3,( "smbd_aio_complete_mid: file closed whilst "
"aio outstanding (mid[%u]).\n", mid));
- srv_cancel_sign_response(mid, false);
return;
}
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index 42849931f3a..4c61428692d 100644
--- a/source3/smbd/blocking.c
+++ b/source3/smbd/blocking.c
@@ -204,9 +204,6 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck,
(unsigned int)blr->expire_time.tv_usec, lock_timeout,
blr->fsp->fnum, blr->fsp->fsp_name ));
- /* Push the MID of this packet on the signing queue. */
- srv_defer_sign_response(blr->req->mid);
-
return True;
}
@@ -260,6 +257,7 @@ static void generic_blocking_lock_error(struct blocking_lock_record *blr, NTSTAT
reply_nterror(blr->req, status);
if (!srv_send_smb(smbd_server_fd(), (char *)blr->req->outbuf,
+ true, blr->req->seqnum+1,
blr->req->encrypted, NULL)) {
exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed.");
}
@@ -343,6 +341,7 @@ static void blocking_lock_reply_error(struct blocking_lock_record *blr, NTSTATUS
if (!srv_send_smb(smbd_server_fd(),
(char *)blr->req->outbuf,
+ true, blr->req->seqnum+1,
IS_CONN_ENCRYPTED(blr->fsp->conn),
NULL)) {
exit_server_cleanly("blocking_lock_reply_error: "
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h
index 6ac92ed3ddb..b646bc30fda 100644
--- a/source3/smbd/globals.h
+++ b/source3/smbd/globals.h
@@ -202,6 +202,7 @@ extern int num_children;
struct smbd_server_connection {
struct fd_event *fde;
uint64_t num_requests;
+ struct smb_signing_state *signing_state;
};
extern struct smbd_server_connection *smbd_server_conn;
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index f20c8512975..d39aab4f471 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -134,6 +134,7 @@ void send_trans_reply(connection_struct *conn,
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
+ true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn), &req->pcd)) {
exit_server_cleanly("send_trans_reply: srv_send_smb failed.");
}
@@ -190,6 +191,7 @@ void send_trans_reply(connection_struct *conn,
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
+ true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn), &req->pcd))
exit_server_cleanly("send_trans_reply: srv_send_smb "
"failed.");
@@ -296,6 +298,7 @@ static void api_dcerpc_cmd_write_done(struct tevent_req *subreq)
send:
if (!srv_send_smb(
smbd_server_fd(), (char *)req->outbuf,
+ true, req->seqnum+1,
IS_CONN_ENCRYPTED(req->conn) || req->encrypted,
&req->pcd)) {
exit_server_cleanly("construct_reply: srv_send_smb failed.");
@@ -322,6 +325,7 @@ static void api_dcerpc_cmd_read_done(struct tevent_req *subreq)
reply_nterror(req, status);
if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
+ true, req->seqnum+1,
IS_CONN_ENCRYPTED(req->conn)
||req->encrypted, &req->pcd)) {
exit_server_cleanly("construct_reply: srv_send_smb "
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index a921954c49c..e548c587c15 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -316,7 +316,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice)
capabilities &= ~CAP_RAW_MODE;
if (lp_server_signing() == Required)
secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
- srv_set_signing_negotiated();
+ srv_set_signing_negotiated(smbd_server_conn);
} else {
DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
if (lp_server_signing() == Required) {
diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c
index 8ceeaf5f558..fdab2ca8485 100644
--- a/source3/smbd/notify.c
+++ b/source3/smbd/notify.c
@@ -143,7 +143,9 @@ static void change_notify_reply_packet(connection_struct *conn,
}
show_msg((char *)req->outbuf);
- if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
+ if (!srv_send_smb(smbd_server_fd(),
+ (char *)req->outbuf,
+ true, req->seqnum+1,
req->encrypted, &req->pcd)) {
exit_server_cleanly("change_notify_reply_packet: srv_send_smb "
"failed.");
@@ -260,9 +262,6 @@ NTSTATUS change_notify_add_request(struct smb_request *req,
map->mid = request->req->mid;
DLIST_ADD(notify_changes_by_mid, map);
- /* Push the MID of this packet on the signing queue. */
- srv_defer_sign_response(request->req->mid);
-
return NT_STATUS_OK;
}
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 9c7fb1914e8..628fc1bd32b 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -230,6 +230,7 @@ void send_nt_replies(connection_struct *conn,
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(),
(char *)req->outbuf,
+ true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn),
&req->pcd)) {
exit_server_cleanly("send_nt_replies: srv_send_smb failed.");
@@ -1129,9 +1130,9 @@ void reply_ntcancel(struct smb_request *req)
*/
START_PROFILE(SMBntcancel);
+ srv_cancel_sign_response(smbd_server_conn);
remove_pending_change_notify_requests_by_mid(req->mid);
remove_pending_lock_requests_by_mid(req->mid);
- srv_cancel_sign_response(req->mid, true);
DEBUG(3,("reply_ntcancel: cancel called on mid = %d.\n", req->mid));
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index d529b009d50..52df4fa1431 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1033,15 +1033,6 @@ static void defer_open(struct share_mode_lock *lck,
exit_server("push_deferred_smb_message failed");
}
add_deferred_open(lck, req->mid, request_time, state->id);
-
- /*
- * Push the MID of this packet on the signing queue.
- * We only do this once, the first time we push the packet
- * onto the deferred open queue, as this has a side effect
- * of incrementing the response sequence number.
- */
-
- srv_defer_sign_response(req->mid);
}
diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c
index 22870283fa5..ce00397bbde 100644
--- a/source3/smbd/oplock.c
+++ b/source3/smbd/oplock.c
@@ -361,7 +361,6 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx
struct share_mode_entry msg;
files_struct *fsp;
char *break_msg;
- bool sign_state;
if (data->data == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
@@ -423,20 +422,14 @@ void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx
wait_before_sending_break();
}
- /* Save the server smb signing state. */
- sign_state = srv_oplock_set_signing(False);
-
show_msg(break_msg);
if (!srv_send_smb(smbd_server_fd(),
- break_msg,
+ break_msg, false, 0,
IS_CONN_ENCRYPTED(fsp->conn),
NULL)) {
exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
- /* Restore the sign state to what it was. */
- srv_oplock_set_signing(sign_state);
-
TALLOC_FREE(break_msg);
/* Async level2 request, don't send a reply, just remove the oplock. */
@@ -457,7 +450,6 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
files_struct *fsp;
char *break_msg;
bool break_to_level2 = False;
- bool sign_state;
if (data->data == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
@@ -530,20 +522,14 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
wait_before_sending_break();
}
- /* Save the server smb signing state. */
- sign_state = srv_oplock_set_signing(False);
-
show_msg(break_msg);
if (!srv_send_smb(smbd_server_fd(),
- break_msg,
+ break_msg, false, 0,
IS_CONN_ENCRYPTED(fsp->conn),
NULL)) {
exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
- /* Restore the sign state to what it was. */
- srv_oplock_set_signing(sign_state);
-
TALLOC_FREE(break_msg);
fsp->sent_oplock_break = break_to_level2 ? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT;
@@ -570,7 +556,6 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
unsigned long file_id;
files_struct *fsp;
char *break_msg;
- bool sign_state;
if (data->data == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
@@ -610,20 +595,14 @@ static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
exit_server("Could not talloc break_msg\n");
}
- /* Save the server smb signing state. */
- sign_state = srv_oplock_set_signing(False);
-
show_msg(break_msg);
if (!srv_send_smb(smbd_server_fd(),
- break_msg,
+ break_msg, false, 0,
IS_CONN_ENCRYPTED(fsp->conn),
NULL)) {
exit_server_cleanly("oplock_break: srv_send_smb failed.");
}
- /* Restore the sign state to what it was. */
- srv_oplock_set_signing(sign_state);
-
TALLOC_FREE(break_msg);
fsp->sent_oplock_break = BREAK_TO_NONE_SENT;
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index 15d120a79c4..076965e783c 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -298,11 +298,13 @@ int register_existing_vuid(uint16 vuid,
vuser->server_info->unix_name);
}
- if (srv_is_signing_negotiated() && !vuser->server_info->guest &&
- !srv_signing_started()) {
+ if (srv_is_signing_negotiated(smbd_server_conn) &&
+ !vuser->server_info->guest) {
/* Try and turn on server signing on the first non-guest
* sessionsetup. */
- srv_set_signing(vuser->server_info->user_session_key, response_blob);
+ srv_set_signing(smbd_server_conn,
+ vuser->server_info->user_session_key,
+ response_blob);
}
/* fill in the current_user_info struct */
diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c
index 2686cf41d93..7ae74356462 100644
--- a/source3/smbd/pipes.c
+++ b/source3/smbd/pipes.c
@@ -216,6 +216,7 @@ static void pipe_write_done(struct tevent_req *subreq)
send:
if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf,
+ true, req->seqnum+1,
IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
&req->pcd)) {
exit_server_cleanly("construct_reply: srv_send_smb failed.");
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 6d53bbe929e..65778ab0fc2 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -32,16 +32,20 @@ static void construct_reply_common(struct smb_request *req, const char *inbuf,
Send an smb to a fd.
****************************************************************************/
-bool srv_send_smb(int fd, char *buffer, bool do_encrypt,
- struct smb_perfcount_data *pcd)
+bool srv_send_smb(int fd, char *buffer,
+ bool do_signing, uint32_t seqnum,
+ bool do_encrypt,
+ struct smb_perfcount_data *pcd)
{
size_t len = 0;
size_t nwritten=0;
ssize_t ret;
char *buf_out = buffer;
- /* Sign the outgoing packet if required. */
- srv_calculate_sign_mac(buf_out);
+ if (do_signing) {
+ /* Sign the outgoing packet if required. */
+ srv_calculate_sign_mac(smbd_server_conn, buf_out, seqnum);
+ }
if (do_encrypt) {
NTSTATUS status = srv_encrypt_buffer(buffer, &buf_out);
@@ -275,7 +279,7 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
if (CVAL(lenbuf,0) == 0 && min_recv_size &&
(smb_len_large(lenbuf) > /* Could be a UNIX large writeX. */
(min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE)) &&
- !srv_is_signing_active()) {
+ !srv_is_signing_active(smbd_server_conn)) {
return receive_smb_raw_talloc_partial_read(
mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen);
@@ -311,7 +315,8 @@ static NTSTATUS receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd,
char **buffer, unsigned int timeout,
size_t *p_unread, bool *p_encrypted,
- size_t *p_len)
+ size_t *p_len,
+ uint32_t *seqnum)
{
size_t len = 0;
NTSTATUS status;
@@ -336,7 +341,7 @@ static NTSTATUS receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd,
}
/* Check the incoming SMB signature. */
- if (!srv_check_sign_mac(*buffer, true)) {
+ if (!srv_check_sign_mac(smbd_server_conn, *buffer, seqnum)) {
DEBUG(0, ("receive_smb: SMB Signature verification failed on "
"incoming packet!\n"));
return NT_STATUS_INVALID_NETWORK_RESPONSE;
@@ -366,6 +371,7 @@ void init_smb_request(struct smb_request *req,
req->flags2 = SVAL(inbuf, smb_flg2);
req->smbpid = SVAL(inbuf, smb_pid);
req->mid = SVAL(inbuf, smb_mid);
+ req->seqnum = 0;
req->vuid = SVAL(inbuf, smb_uid);
req->tid = SVAL(inbuf, smb_tid);
req->wct = CVAL(inbuf, smb_wct);
@@ -401,7 +407,8 @@ void init_smb_request(struct smb_request *req,
static void process_smb(struct smbd_server_connection *conn,
uint8_t *inbuf, size_t nread, size_t unread_bytes,
- bool encrypted, struct smb_perfcount_data *deferred_pcd);
+ uint32_t seqnum, bool encrypted,
+ struct smb_perfcount_data *deferred_pcd);
static void smbd_deferred_open_timer(struct event_context *ev,
struct timed_event *te,
@@ -427,7 +434,7 @@ static void smbd_deferred_open_timer(struct event_context *ev,
process_smb(smbd_server_conn, inbuf,
msg->buf.length, 0,
- msg->encrypted, &msg->pcd);
+ msg->seqnum, msg->encrypted, &msg->pcd);
}
/****************************************************************************
@@ -458,6 +465,7 @@ static bool push_queued_message(struct smb_request *req,
}
msg->request_time = request_time;
+ msg->seqnum = req->seqnum;
msg->encrypted = req->encrypted;
SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
@@ -1362,7 +1370,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
****************************************************************************/
static void construct_reply(char *inbuf, int size, size_t unread_bytes,
- bool encrypted,
+ uint32_t seqnum, bool encrypted,
struct smb_perfcount_data *deferred_pcd)
{
connection_struct *conn;
@@ -1374,6 +1382,7 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes,
init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted);
req->inbuf = (uint8_t *)talloc_move(req, &inbuf);
+ req->seqnum = seqnum;
/* we popped this message off the queue - keep original perf data */
if (deferred_pcd)
@@ -1405,6 +1414,7 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes,
if (!srv_send_smb(smbd_server_fd(),
(char *)req->outbuf,
+ true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn)||req->encrypted,
&req->pcd)) {
exit_server_cleanly("construct_reply: srv_send_smb failed.");
@@ -1420,7 +1430,8 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes,
****************************************************************************/
static void process_smb(struct smbd_server_connection *conn,
uint8_t *inbuf, size_t nread, size_t unread_bytes,
- bool encrypted, struct smb_perfcount_data *deferred_pcd)
+ uint32_t seqnum, bool encrypted,
+ struct smb_perfcount_data *deferred_pcd)
{
int msg_type = CVAL(inbuf,0);
@@ -1442,7 +1453,7 @@ static void process_smb(struct smbd_server_connection *conn,
show_msg((char *)inbuf);
- construct_reply((char *)inbuf,nread,unread_bytes,encrypted,deferred_pcd);
+ construct_reply((char *)inbuf,nread,unread_bytes,seqnum,encrypted,deferred_pcd);
trans_num++;
done:
@@ -1637,6 +1648,7 @@ void chain_reply(struct smb_request *req)
talloc_get_size(req->chain_outbuf) - 4);
if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
+ true, req->seqnum+1,
IS_CONN_ENCRYPTED(req->conn)
||req->encrypted,
&req->pcd)) {
@@ -1761,6 +1773,7 @@ void chain_reply(struct smb_request *req)
show_msg((char *)(req->chain_outbuf));
if (!srv_send_smb(smbd_server_fd(), (char *)req->chain_outbuf,
+ true, req->seqnum+1,
IS_CONN_ENCRYPTED(req->conn)||req->encrypted,
&req->pcd)) {
exit_server_cleanly("construct_reply: srv_send_smb failed.");
@@ -1830,6 +1843,7 @@ static void smbd_server_connection_read_handler(struct smbd_server_connection *c
bool encrypted = false;
TALLOC_CTX *mem_ctx = talloc_tos();
NTSTATUS status;
+ uint32_t seqnum;
/* TODO: make this completely nonblocking */
@@ -1838,7 +1852,7 @@ static void smbd_server_connection_read_handler(struct smbd_server_connection *c
0, /* timeout */
&unread_bytes,
&encrypted,
- &inbuf_len);
+ &inbuf_len, &seqnum);
if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
goto process;
}
@@ -1850,7 +1864,8 @@ static void smbd_server_connection_read_handler(struct smbd_server_connection *c
}
process:
- process_smb(conn, inbuf, inbuf_len, unread_bytes, encrypted, NULL);
+ process_smb(conn, inbuf, inbuf_len, unread_bytes,
+ seqnum, encrypted, NULL);
}
static void smbd_server_connection_handler(struct event_context *ev,
@@ -2015,7 +2030,8 @@ void smbd_process(void)
unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
DEBUG( 1, ("Connection denied from %s\n",
client_addr(get_client_fd(),addr,sizeof(addr)) ) );
- (void)srv_send_smb(smbd_server_fd(),(char *)buf,false, NULL);
+ (void)srv_send_smb(smbd_server_fd(),(char *)buf, false,
+ 0, false, NULL);
exit_server_cleanly("connection denied");
}
@@ -2041,6 +2057,10 @@ void smbd_process(void)
DEBUG(0,("Changed root to %s\n", lp_rootdir()));
}
+ if (!srv_init_signing(smbd_server_conn)) {
+ exit_server("Failed to init smb_signing");
+ }
+
/* Setup oplocks */
if (!init_oplocks(smbd_messaging_context()))
exit_server("Failed to init oplocks");
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 8b560bd8ca6..6f19a58178b 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -497,7 +497,7 @@ void reply_special(char *inbuf)
DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n",
msg_type, msg_flags));
- srv_send_smb(smbd_server_fd(), outbuf, false, NULL);
+ srv_send_smb(smbd_server_fd(), outbuf, false, 0, false, NULL);
return;
}
@@ -2766,7 +2766,8 @@ static void send_file_readbraw(connection_struct *conn,
*/
if ( !req_is_in_chain(req) && (nread > 0) && (fsp->base_fsp == NULL) &&
- (fsp->wcp == NULL) && lp_use_sendfile(SNUM(conn)) ) {
+ (fsp->wcp == NULL) &&
+ lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
ssize_t sendfile_read = -1;
char header[4];
DATA_BLOB header_blob;
@@ -2870,7 +2871,8 @@ void reply_readbraw(struct smb_request *req)
START_PROFILE(SMBreadbraw);
- if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
+ if (srv_is_signing_active(smbd_server_conn) ||
+ is_encrypted_packet(req->inbuf)) {
exit_server_cleanly("reply_readbraw: SMB signing/sealing is active - "
"raw reads/writes are disallowed.");
}
@@ -3274,7 +3276,8 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req,
if (!req_is_in_chain(req) &&
!is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) &&
- lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
+ (fsp->wcp == NULL) &&
+ lp_use_sendfile(SNUM(conn), smbd_server_conn->signing_state) ) {
uint8 headerbuf[smb_size + 12 * 2];
DATA_BLOB header;
@@ -3450,7 +3453,8 @@ void reply_read_and_X(struct smb_request *req)
return;
}
/* We currently don't do this on signed or sealed data. */
- if (srv_is_signing_active() || is_encrypted_packet(req->inbuf)) {
+ if (srv_is_signing_active(smbd_server_conn) ||
+ is_encrypted_packet(req->inbuf)) {
reply_nterror(req, NT_STATUS_NOT_SUPPORTED);
END_PROFILE(SMBreadX);
return;
@@ -3558,7 +3562,7 @@ void reply_writebraw(struct smb_request *req)
*/
SCVAL(req->inbuf,smb_com,SMBwritec);
- if (srv_is_signing_active()) {
+ if (srv_is_signing_active(smbd_server_conn)) {
END_PROFILE(SMBwritebraw);
exit_server_cleanly("reply_writebraw: SMB signing is active - "
"raw reads/writes are disallowed.");
@@ -3653,9 +3657,10 @@ void reply_writebraw(struct smb_request *req)
SSVALS(buf,smb_vwv0,0xFFFF);
show_msg(buf);
if (!srv_send_smb(smbd_server_fd(),
- buf,
- IS_CONN_ENCRYPTED(conn),
- &req->pcd)) {
+ buf,
+ false, 0, /* no signing */
+ IS_CONN_ENCRYPTED(conn),
+ &req->pcd)) {
exit_server_cleanly("reply_writebraw: srv_send_smb "
"failed.");
}
@@ -4757,6 +4762,7 @@ void reply_echo(struct smb_request *req)
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(),
(char *)req->outbuf,
+ true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn)||req->encrypted,
cur_pcd))
exit_server_cleanly("reply_echo: srv_send_smb failed.");
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index eb16a2601e3..e33f04d971b 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -1110,7 +1110,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
dbgtext( "%s (%s) ", get_remote_machine_name(),
conn->client_address );
- dbgtext( "%s", srv_is_signing_active() ? "signed " : "");
+ dbgtext( "%s", srv_is_signing_active(smbd_server_conn) ? "signed " : "");
dbgtext( "connect to service %s ", lp_servicename(snum) );
dbgtext( "initially as user %s ",
conn->server_info->unix_name );
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 2c29192220b..e8878a29ab3 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -91,25 +91,6 @@ static int push_signature(uint8 **outbuf)
}
/****************************************************************************
- Start the signing engine if needed. Don't fail signing here.
-****************************************************************************/
-
-static void sessionsetup_start_signing_engine(
- const auth_serversupplied_info *server_info,
- const uint8 *inbuf)
-{
- if (!server_info->guest && !srv_signing_started()) {
- /* We need to start the signing engine
- * here but a W2K client sends the old
- * "BSRSPYL " signature instead of the
- * correct one. Subsequent packets will
- * be correct.
- */
- srv_check_sign_mac((char *)inbuf, False);
- }
-}
-
-/****************************************************************************
Send a security blob via a session setup reply.
****************************************************************************/
@@ -579,7 +560,6 @@ static void reply_spnego_kerberos(struct smb_request *req,
SSVAL(req->outbuf, smb_uid, sess_vuid);
- sessionsetup_start_signing_engine(server_info, req->inbuf);
/* Successful logon. Keep this vuid. */
*p_invalidate_vuid = False;
}
@@ -668,9 +648,6 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
if (server_info->guest) {
SSVAL(req->outbuf,smb_vwv2,1);
}
-
- sessionsetup_start_signing_engine(server_info,
- (uint8 *)req->inbuf);
}
out:
@@ -1804,8 +1781,6 @@ void reply_sesssetup_and_X(struct smb_request *req)
/* current_user_info is changed on new vuid */
reload_services( True );
-
- sessionsetup_start_signing_engine(server_info, req->inbuf);
}
data_blob_free(&nt_resp);
diff --git a/source3/smbd/signing.c b/source3/smbd/signing.c
new file mode 100644
index 00000000000..b56eb71f45c
--- /dev/null
+++ b/source3/smbd/signing.c
@@ -0,0 +1,158 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB Signing Code
+ Copyright (C) Jeremy Allison 2003.
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2002-2003
+ Copyright (C) Stefan Metzmacher 2009
+
+ 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 "smbd/globals.h"
+
+
+/***********************************************************
+ Called to validate an incoming packet from the client.
+************************************************************/
+
+bool srv_check_sign_mac(struct smbd_server_connection *conn,
+ const char *inbuf, uint32_t *seqnum)
+{
+ /* Check if it's a non-session message. */
+ if(CVAL(inbuf,0)) {
+ return true;
+ }
+
+ *seqnum = smb_signing_next_seqnum(conn->signing_state, false);
+ return smb_signing_check_pdu(conn->signing_state,
+ (const uint8_t *)inbuf,
+ *seqnum);
+}
+
+/***********************************************************
+ Called to sign an outgoing packet to the client.
+************************************************************/
+
+void srv_calculate_sign_mac(struct smbd_server_connection *conn,
+ char *outbuf, uint32_t seqnum)
+{
+ /* Check if it's a non-session message. */
+ if(CVAL(outbuf,0)) {
+ return;
+ }
+
+ smb_signing_sign_pdu(conn->signing_state, (uint8_t *)outbuf, seqnum);
+}
+
+
+/***********************************************************
+ Called to indicate a oneway request
+************************************************************/
+void srv_cancel_sign_response(struct smbd_server_connection *conn)
+{
+ smb_signing_cancel_reply(conn->signing_state, true);
+}
+
+/***********************************************************
+ Called by server negprot when signing has been negotiated.
+************************************************************/
+
+bool srv_init_signing(struct smbd_server_connection *conn)
+{
+ bool allowed = true;
+ bool mandatory = false;
+
+ switch (lp_server_signing()) {
+ case Required:
+ mandatory = true;
+ break;
+ case Auto:
+ break;
+ case True:
+ break;
+ case False:
+ allowed = false;
+ break;
+ }
+
+ conn->signing_state = smb_signing_init(smbd_event_context(),
+ allowed, mandatory);
+ if (!conn->signing_state) {
+ return false;
+ }
+
+ return true;
+}
+
+void srv_set_signing_negotiated(struct smbd_server_connection *conn)
+{
+ smb_signing_set_negotiated(conn->signing_state);
+}
+
+/***********************************************************
+ Returns whether signing is active. We can't use sendfile or raw
+ reads/writes if it is.
+************************************************************/
+
+bool srv_is_signing_active(struct smbd_server_connection *conn)
+{
+ return smb_signing_is_active(conn->signing_state);
+}
+
+
+/***********************************************************
+ Returns whether signing is negotiated. We can't use it unless it was
+ in the negprot.
+************************************************************/
+
+bool srv_is_signing_negotiated(struct smbd_server_connection *conn)
+{
+ return smb_signing_is_negotiated(conn->signing_state);
+}
+
+/***********************************************************
+ Turn on signing from this packet onwards.
+************************************************************/
+
+void srv_set_signing(struct smbd_server_connection *conn,
+ const DATA_BLOB user_session_key,
+ const DATA_BLOB response)
+{
+ bool negotiated;
+ bool mandatory;
+
+ if (!user_session_key.length)
+ return;
+
+ negotiated = smb_signing_is_negotiated(conn->signing_state);
+ mandatory = smb_signing_is_mandatory(conn->signing_state);
+
+ if (!negotiated && !mandatory) {
+ DEBUG(5,("srv_set_signing: signing negotiated = %u, "
+ "mandatory_signing = %u. Not allowing smb signing.\n",
+ negotiated, mandatory));
+ return;
+ }
+
+ if (!smb_signing_activate(conn->signing_state,
+ user_session_key, response)) {
+ return;
+ }
+
+ DEBUG(3,("srv_set_signing: turning on SMB signing: "
+ "signing negotiated = %u, mandatory_signing = %u.\n",
+ negotiated, mandatory));
+}
+
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index ee1dda98b22..df01a398934 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -832,6 +832,7 @@ void send_trans2_replies(connection_struct *conn,
show_msg((char *)req->outbuf);
if (!srv_send_smb(smbd_server_fd(),
(char *)req->outbuf,
+ true, req->seqnum+1,
IS_CONN_ENCRYPTED(conn),
&req->pcd))
exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
@@ -2892,8 +2893,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
case SMB_QUERY_CIFS_UNIX_INFO:
{
bool large_write = lp_min_receive_file_size() &&
- !srv_is_signing_active();
- bool large_read = !srv_is_signing_active();
+ !srv_is_signing_active(smbd_server_conn);
+ bool large_read = !srv_is_signing_active(smbd_server_conn);
int encrypt_caps = 0;
if (!lp_unix_extensions()) {