diff options
author | Andrew Tridgell <tridge@samba.org> | 2009-03-31 11:58:37 +1100 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2009-03-31 11:58:37 +1100 |
commit | 631e688c821b78d09d77f5940074800525c554aa (patch) | |
tree | 74473f1727ea0afa27d9c15e50e4638c4d8faf28 /source3/smbd | |
parent | 13be4d7ff42bd2b8bf5702a499c482404e5cd164 (diff) | |
parent | 4b8e4ea7286f045effb6feb4c7bf8c5ef4ed2f9b (diff) | |
download | samba-631e688c821b78d09d77f5940074800525c554aa.tar.gz samba-631e688c821b78d09d77f5940074800525c554aa.tar.bz2 samba-631e688c821b78d09d77f5940074800525c554aa.zip |
Merge branch 'master' into wspp-schema
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/aio.c | 13 | ||||
-rw-r--r-- | source3/smbd/avahi_register.c | 170 | ||||
-rw-r--r-- | source3/smbd/blocking.c | 5 | ||||
-rw-r--r-- | source3/smbd/globals.h | 1 | ||||
-rw-r--r-- | source3/smbd/ipc.c | 4 | ||||
-rw-r--r-- | source3/smbd/negprot.c | 2 | ||||
-rw-r--r-- | source3/smbd/notify.c | 7 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 7 | ||||
-rw-r--r-- | source3/smbd/open.c | 9 | ||||
-rw-r--r-- | source3/smbd/oplock.c | 27 | ||||
-rw-r--r-- | source3/smbd/password.c | 8 | ||||
-rw-r--r-- | source3/smbd/pipes.c | 1 | ||||
-rw-r--r-- | source3/smbd/process.c | 52 | ||||
-rw-r--r-- | source3/smbd/reply.c | 32 | ||||
-rw-r--r-- | source3/smbd/server.c | 11 | ||||
-rw-r--r-- | source3/smbd/service.c | 2 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 25 | ||||
-rw-r--r-- | source3/smbd/signing.c | 158 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 7 |
19 files changed, 435 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..7e75eea6b4 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."); @@ -440,6 +441,8 @@ void reply_ntcreate_and_X(struct smb_request *req) START_PROFILE(SMBntcreateX); + SET_STAT_INVALID(sbuf); + if (req->wct < 24) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; @@ -864,6 +867,8 @@ static void call_nt_transact_create(connection_struct *conn, uint8_t oplock_granted; TALLOC_CTX *ctx = talloc_tos(); + SET_STAT_INVALID(sbuf); + DEBUG(5,("call_nt_transact_create\n")); /* @@ -1129,9 +1134,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..3f9d5c5498 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; } @@ -1606,6 +1606,8 @@ void reply_open(struct smb_request *req) START_PROFILE(SMBopen); + SET_STAT_INVALID(sbuf); + if (req->wct < 2) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBopen); @@ -1741,6 +1743,8 @@ void reply_open_and_X(struct smb_request *req) return; } + SET_STAT_INVALID(sbuf); + open_flags = SVAL(req->vwv+2, 0); deny_mode = SVAL(req->vwv+3, 0); smb_attr = SVAL(req->vwv+5, 0); @@ -1945,6 +1949,7 @@ void reply_mknew(struct smb_request *req) START_PROFILE(SMBcreate); ZERO_STRUCT(ft); + SET_STAT_INVALID(sbuf); if (req->wct < 3) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -2123,6 +2128,7 @@ void reply_ctemp(struct smb_request *req) return; } + SET_STAT_INVALID(sbuf); SMB_VFS_STAT(conn,fname,&sbuf); /* We should fail if file does not exist. */ @@ -2673,6 +2679,7 @@ static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, return (ssize_t)nread; } +#if defined(WITH_SENDFILE) /**************************************************************************** Deal with the case of sendfile reading less bytes from the file than requested. Fill with zeros (all we can do). @@ -2729,6 +2736,7 @@ static void sendfile_short_send(files_struct *fsp, SAFE_FREE(buf); } } +#endif /* defined WITH_SENDFILE */ /**************************************************************************** Return a readbraw error (4 bytes of zero). @@ -2766,7 +2774,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 +2879,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 +3284,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 +3461,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 +3570,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 +3665,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 +4770,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..04b1145e58 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."); @@ -894,6 +895,8 @@ static void call_trans2open(connection_struct *conn, uint32 create_options = 0; TALLOC_CTX *ctx = talloc_tos(); + SET_STAT_INVALID(sbuf); + /* * Ensure we have enough parameters to perform the operation. */ @@ -2892,8 +2895,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()) { |