summaryrefslogtreecommitdiff
path: root/source3/smbd
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 /source3/smbd
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
Diffstat (limited to 'source3/smbd')
-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
17 files changed, 239 insertions, 105 deletions
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()) {