summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2009-03-25 20:51:29 +0100
committerJelmer Vernooij <jelmer@samba.org>2009-03-25 20:51:29 +0100
commit9a61758c1e3b3893fda1aca5dae291d86cec82e3 (patch)
tree9b96685d6439a00617e19f502389e40d6f3dfe5e /source3/smbd
parentca202cf464aec82e63be4b2160f394f56b8c195e (diff)
parent365b5cfcbeb041ce84718717f30ac02183c9af7f (diff)
downloadsamba-9a61758c1e3b3893fda1aca5dae291d86cec82e3.tar.gz
samba-9a61758c1e3b3893fda1aca5dae291d86cec82e3.tar.bz2
samba-9a61758c1e3b3893fda1aca5dae291d86cec82e3.zip
Merge branch 'master' of ssh://git.samba.org/data/git/samba into displaysec
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/aio.c13
-rw-r--r--source3/smbd/avahi_register.c170
-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.c52
-rw-r--r--source3/smbd/reply.c24
-rw-r--r--source3/smbd/server.c11
-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
19 files changed, 421 insertions, 106 deletions
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c
index cfa4b430eb..77616be48c 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/avahi_register.c b/source3/smbd/avahi_register.c
new file mode 100644
index 0000000000..1903b0ef96
--- /dev/null
+++ b/source3/smbd/avahi_register.c
@@ -0,0 +1,170 @@
+/*
+ * Unix SMB/CIFS implementation.
+ * Register _smb._tcp with avahi
+ *
+ * Copyright (C) Volker Lendecke 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 <avahi-client/client.h>
+#include <avahi-client/publish.h>
+#include <avahi-common/error.h>
+
+struct avahi_state_struct {
+ struct AvahiPoll *poll;
+ AvahiClient *client;
+ AvahiEntryGroup *entry_group;
+ uint16_t port;
+};
+
+static void avahi_entry_group_callback(AvahiEntryGroup *g,
+ AvahiEntryGroupState status,
+ void *userdata)
+{
+ struct avahi_state_struct *state = talloc_get_type_abort(
+ userdata, struct avahi_state_struct);
+ int error;
+
+ switch (status) {
+ case AVAHI_ENTRY_GROUP_ESTABLISHED:
+ DEBUG(10, ("avahi_entry_group_callback: "
+ "AVAHI_ENTRY_GROUP_ESTABLISHED\n"));
+ break;
+ case AVAHI_ENTRY_GROUP_FAILURE:
+ error = avahi_client_errno(state->client);
+
+ DEBUG(10, ("avahi_entry_group_callback: "
+ "AVAHI_ENTRY_GROUP_FAILURE: %s\n",
+ avahi_strerror(error)));
+ break;
+ case AVAHI_ENTRY_GROUP_COLLISION:
+ DEBUG(10, ("avahi_entry_group_callback: "
+ "AVAHI_ENTRY_GROUP_COLLISION\n"));
+ break;
+ case AVAHI_ENTRY_GROUP_UNCOMMITED:
+ DEBUG(10, ("avahi_entry_group_callback: "
+ "AVAHI_ENTRY_GROUP_UNCOMMITED\n"));
+ break;
+ case AVAHI_ENTRY_GROUP_REGISTERING:
+ DEBUG(10, ("avahi_entry_group_callback: "
+ "AVAHI_ENTRY_GROUP_REGISTERING\n"));
+ break;
+ }
+}
+
+static void avahi_client_callback(AvahiClient *c, AvahiClientState status,
+ void *userdata)
+{
+ struct avahi_state_struct *state = talloc_get_type_abort(
+ userdata, struct avahi_state_struct);
+ int error;
+
+ switch (status) {
+ case AVAHI_CLIENT_S_RUNNING:
+ DEBUG(10, ("avahi_client_callback: AVAHI_CLIENT_S_RUNNING\n"));
+
+ state->entry_group = avahi_entry_group_new(
+ c, avahi_entry_group_callback, state);
+ if (state->entry_group == NULL) {
+ error = avahi_client_errno(c);
+ DEBUG(10, ("avahi_entry_group_new failed: %s\n",
+ avahi_strerror(error)));
+ break;
+ }
+ if (avahi_entry_group_add_service(
+ state->entry_group, AVAHI_IF_UNSPEC,
+ AVAHI_PROTO_UNSPEC, 0, global_myname(),
+ "_smb._tcp", NULL, NULL, state->port, NULL) < 0) {
+ error = avahi_client_errno(c);
+ DEBUG(10, ("avahi_entry_group_add_service failed: "
+ "%s\n", avahi_strerror(error)));
+ avahi_entry_group_free(state->entry_group);
+ state->entry_group = NULL;
+ break;
+ }
+ if (avahi_entry_group_commit(state->entry_group) < 0) {
+ error = avahi_client_errno(c);
+ DEBUG(10, ("avahi_entry_group_commit failed: "
+ "%s\n", avahi_strerror(error)));
+ avahi_entry_group_free(state->entry_group);
+ state->entry_group = NULL;
+ break;
+ }
+ break;
+ case AVAHI_CLIENT_FAILURE:
+ error = avahi_client_errno(c);
+
+ DEBUG(10, ("avahi_client_callback: AVAHI_CLIENT_FAILURE: %s\n",
+ avahi_strerror(error)));
+
+ if (error != AVAHI_ERR_DISCONNECTED) {
+ break;
+ }
+ avahi_client_free(c);
+ state->client = avahi_client_new(state->poll, AVAHI_CLIENT_NO_FAIL,
+ avahi_client_callback, state,
+ &error);
+ if (state->client == NULL) {
+ DEBUG(10, ("avahi_client_new failed: %s\n",
+ avahi_strerror(error)));
+ break;
+ }
+ break;
+ case AVAHI_CLIENT_S_COLLISION:
+ DEBUG(10, ("avahi_client_callback: "
+ "AVAHI_CLIENT_S_COLLISION\n"));
+ break;
+ case AVAHI_CLIENT_S_REGISTERING:
+ DEBUG(10, ("avahi_client_callback: "
+ "AVAHI_CLIENT_S_REGISTERING\n"));
+ break;
+ case AVAHI_CLIENT_CONNECTING:
+ DEBUG(10, ("avahi_client_callback: "
+ "AVAHI_CLIENT_CONNECTING\n"));
+ break;
+ }
+}
+
+void *avahi_start_register(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+ uint16_t port)
+{
+ struct avahi_state_struct *state;
+ int error;
+
+ state = talloc(mem_ctx, struct avahi_state_struct);
+ if (state == NULL) {
+ return state;
+ }
+ state->port = port;
+ state->poll = tevent_avahi_poll(state, ev);
+ if (state->poll == NULL) {
+ goto fail;
+ }
+ state->client = avahi_client_new(state->poll, AVAHI_CLIENT_NO_FAIL,
+ avahi_client_callback, state,
+ &error);
+ if (state->client == NULL) {
+ DEBUG(10, ("avahi_client_new failed: %s\n",
+ avahi_strerror(error)));
+ goto fail;
+ }
+ return state;
+
+ fail:
+ TALLOC_FREE(state);
+ return NULL;
+}
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c
index 42849931f3..4c61428692 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 6ac92ed3dd..b646bc30fd 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 f20c851297..d39aab4f47 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 a921954c49..e548c587c1 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 8ceeaf5f55..fdab2ca848 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 9c7fb1914e..628fc1bd32 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 d529b009d5..52df4fa143 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 22870283fa..ce00397bbd 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 15d120a79c..076965e783 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 2686cf41d9..7ae7435646 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 18fbdd7939..65778ab0fc 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);
@@ -913,7 +921,7 @@ static const struct smb_message_struct {
/* 0x30 */ { NULL, NULL, 0 },
/* 0x31 */ { NULL, NULL, 0 },
/* 0x32 */ { "SMBtrans2",reply_trans2, AS_USER | CAN_IPC },
-/* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER},
+/* 0x33 */ { "SMBtranss2",reply_transs2, AS_USER | CAN_IPC },
/* 0x34 */ { "SMBfindclose",reply_findclose,AS_USER},
/* 0x35 */ { "SMBfindnclose",reply_findnclose,AS_USER},
/* 0x36 */ { NULL, NULL, 0 },
@@ -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 8b560bd8ca..6f19a58178 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/server.c b/source3/smbd/server.c
index d27f98281b..67836f785b 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -643,8 +643,19 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent,
#endif
if (dns_port != 0) {
+#ifdef WITH_DNSSD_SUPPORT
smbd_setup_mdns_registration(smbd_event_context(),
parent, dns_port);
+#endif
+#ifdef WITH_AVAHI_SUPPORT
+ void *avahi_conn;
+
+ avahi_conn = avahi_start_register(
+ smbd_event_context(), smbd_event_context(), dns_port);
+ if (avahi_conn == NULL) {
+ DEBUG(10, ("avahi_start_register failed\n"));
+ }
+#endif
}
return true;
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index eb16a2601e..e33f04d971 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 2c29192220..e8878a29ab 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 0000000000..b56eb71f45
--- /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 ee1dda98b2..df01a39893 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()) {