#include "includes.h"
#include "smbd/globals.h"
+#include "../librpc/gen_ndr/srv_dfs.h"
+#include "../librpc/gen_ndr/srv_dssetup.h"
+#include "../librpc/gen_ndr/srv_echo.h"
+#include "../librpc/gen_ndr/srv_eventlog.h"
+#include "../librpc/gen_ndr/srv_initshutdown.h"
+#include "../librpc/gen_ndr/srv_lsa.h"
+#include "../librpc/gen_ndr/srv_netlogon.h"
+#include "../librpc/gen_ndr/srv_ntsvcs.h"
+#include "../librpc/gen_ndr/srv_samr.h"
+#include "../librpc/gen_ndr/srv_spoolss.h"
+#include "../librpc/gen_ndr/srv_srvsvc.h"
+#include "../librpc/gen_ndr/srv_svcctl.h"
+#include "../librpc/gen_ndr/srv_winreg.h"
+#include "../librpc/gen_ndr/srv_wkssvc.h"
extern bool global_machine_password_needs_changing;
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);
len = smb_len(buf_out) + 4;
- while (nwritten < len) {
- ret = write_data(fd,buf_out+nwritten,len - nwritten);
- if (ret <= 0) {
- DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
- (int)len,(int)ret, strerror(errno) ));
- srv_free_enc_buffer(buf_out);
- goto out;
- }
- nwritten += ret;
+ ret = write_data(fd,buf_out+nwritten,len - nwritten);
+ if (ret <= 0) {
+ DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
+ (int)len,(int)ret, strerror(errno) ));
+ srv_free_enc_buffer(buf_out);
+ goto out;
}
SMB_PERFCOUNT_SET_MSGLEN_OUT(pcd, len);
return NT_STATUS_OK;
}
- return read_socket_with_timeout(fd, buffer, len, len, timeout, NULL);
+ return read_fd_with_timeout(fd, buffer, len, len, timeout, NULL);
}
/****************************************************************************
memcpy(writeX_header, lenbuf, 4);
- status = read_socket_with_timeout(
+ status = read_fd_with_timeout(
fd, writeX_header + 4,
STANDARD_WRITE_AND_X_HEADER_SIZE,
STANDARD_WRITE_AND_X_HEADER_SIZE,
return status;
}
- if (CVAL(lenbuf,0) == 0 &&
- min_recv_size &&
- smb_len_large(lenbuf) > (min_recv_size + STANDARD_WRITE_AND_X_HEADER_SIZE) && /* Could be a UNIX large writeX. */
- !srv_is_signing_active()) {
+ 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(smbd_server_conn)) {
return receive_smb_raw_talloc_partial_read(
mem_ctx, lenbuf, fd, buffer, timeout, p_unread, plen);
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;
}
/* 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;
* Initialize a struct smb_request from an inbuf
*/
-void init_smb_request(struct smb_request *req,
- const uint8 *inbuf,
- size_t unread_bytes,
- bool encrypted)
+static void init_smb_request(struct smb_request *req, const uint8 *inbuf,
+ size_t unread_bytes, bool encrypted)
{
+ struct smbd_server_connection *sconn = smbd_server_conn;
size_t req_size = smb_len(inbuf) + 4;
/* Ensure we have at least smb_size bytes. */
if (req_size < smb_size) {
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);
req->buf = (const uint8_t *)smb_buf(inbuf);
req->unread_bytes = unread_bytes;
req->encrypted = encrypted;
- req->conn = conn_find(req->tid);
+ req->conn = conn_find(sconn,req->tid);
req->chain_fsp = NULL;
req->chain_outbuf = NULL;
+ req->done = false;
smb_init_perfcount_data(&req->pcd);
/* Ensure we have at least wct words and 2 bytes of bcc. */
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,
struct pending_message_list *msg = talloc_get_type(private_data,
struct pending_message_list);
TALLOC_CTX *mem_ctx = talloc_tos();
+ uint16_t mid = SVAL(msg->buf.data,smb_mid);
uint8_t *inbuf;
inbuf = (uint8_t *)talloc_memdup(mem_ctx, msg->buf.data,
/* We leave this message on the queue so the open code can
know this is a retry. */
DEBUG(5,("smbd_deferred_open_timer: trigger mid %u.\n",
- (unsigned int)SVAL(msg->buf.data,smb_mid)));
+ (unsigned int)mid ));
+
+ /* Mark the message as processed so this is not
+ * re-processed in error. */
+ msg->processed = true;
process_smb(smbd_server_conn, inbuf,
msg->buf.length, 0,
- msg->encrypted, &msg->pcd);
+ msg->seqnum, msg->encrypted, &msg->pcd);
+
+ /* If it's still there and was processed, remove it. */
+ msg = get_open_deferred_message(mid);
+ if (msg && msg->processed) {
+ remove_deferred_open_smb_message(mid);
+ }
}
/****************************************************************************
}
msg->request_time = request_time;
+ msg->seqnum = req->seqnum;
msg->encrypted = req->encrypted;
+ msg->processed = false;
SMB_PERFCOUNT_DEFER_OP(&req->pcd, &msg->pcd);
if (private_data) {
for (pml = deferred_open_queue; pml; pml = pml->next) {
if (mid == SVAL(pml->buf.data,smb_mid)) {
- DEBUG(10,("remove_sharing_violation_open_smb_message: "
+ DEBUG(10,("remove_deferred_open_smb_message: "
"deleting mid %u len %u\n",
(unsigned int)mid,
(unsigned int)pml->buf.length ));
if (mid == msg_mid) {
struct timed_event *te;
+ if (pml->processed) {
+ /* A processed message should not be
+ * rescheduled. */
+ DEBUG(0,("schedule_deferred_open_smb_message: LOGIC ERROR "
+ "message mid %u was already processed\n",
+ msg_mid ));
+ continue;
+ }
+
DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
mid ));
}
/****************************************************************************
- Return true if this mid is on the deferred queue.
+ Return true if this mid is on the deferred queue and was not yet processed.
****************************************************************************/
bool open_was_deferred(uint16 mid)
struct pending_message_list *pml;
for (pml = deferred_open_queue; pml; pml = pml->next) {
- if (SVAL(pml->buf.data,smb_mid) == mid) {
+ if (SVAL(pml->buf.data,smb_mid) == mid && !pml->processed) {
return True;
}
}
/* 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 },
int flags;
uint16 session_tag;
connection_struct *conn = NULL;
+ struct smbd_server_connection *sconn = smbd_server_conn;
errno = 0;
* JRA.
*/
- if (session_tag != last_session_tag) {
+ if (session_tag != sconn->smb1.sessions.last_session_tag) {
user_struct *vuser = NULL;
- last_session_tag = session_tag;
+ sconn->smb1.sessions.last_session_tag = session_tag;
if(session_tag != UID_FIELD_INVALID) {
- vuser = get_valid_user_struct(session_tag);
+ vuser = get_valid_user_struct(sconn, session_tag);
if (vuser) {
set_current_user_info(
vuser->server_info->sanitized_username,
if (type == SMBntcreateX) {
reply_nterror(req, NT_STATUS_INVALID_HANDLE);
} else {
- reply_doserror(req, ERRSRV, ERRinvnid);
+ reply_nterror(req, NT_STATUS_NETWORK_NAME_DELETED);
}
return NULL;
}
if (!change_to_user(conn,session_tag)) {
- reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid));
- remove_deferred_open_smb_message(req->mid);
+ DEBUG(0, ("Error: Could not change to user. Removing "
+ "deferred open, mid=%d.\n", req->mid));
+ reply_force_doserror(req, ERRSRV, ERRbaduid);
return conn;
}
/* IPC services are limited */
if (IS_IPC(conn) && !(flags & CAN_IPC)) {
- reply_doserror(req, ERRSRV,ERRaccess);
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return conn;
}
} else {
if (!set_current_service(conn,SVAL(req->inbuf,smb_flg),
(flags & (AS_USER|DO_CHDIR)
?True:False))) {
- reply_doserror(req, ERRSRV, ERRaccess);
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return conn;
}
conn->num_smb_operations++;
&& (!change_to_guest() ||
!check_access(smbd_server_fd(), lp_hostsallow(-1),
lp_hostsdeny(-1)))) {
- reply_doserror(req, ERRSRV, ERRaccess);
+ reply_nterror(req, NT_STATUS_ACCESS_DENIED);
return conn;
}
****************************************************************************/
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;
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)
req->unread_bytes = 0;
}
+ if (req->done) {
+ TALLOC_FREE(req);
+ return;
+ }
+
if (req->outbuf == NULL) {
return;
}
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.");
****************************************************************************/
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);
goto done;
}
+ if (smbd_server_conn->allow_smb2) {
+ if (smbd_is_smb2_header(inbuf, nread)) {
+ smbd_smb2_first_negprot(smbd_server_conn, inbuf, nread);
+ return;
+ }
+ smbd_server_conn->allow_smb2 = false;
+ }
+
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:
- conn->num_requests++;
+ conn->smb1.num_requests++;
/* The timeout_processing function isn't run nearly
often enough to implement 'max log size' without
level 10. Checking every 50 SMBs is a nice
tradeoff of performance vs log file size overrun. */
- if ((conn->num_requests % 50) == 0 &&
+ if ((conn->smb1.num_requests % 50) == 0 &&
need_to_check_log_size()) {
change_to_root_user();
check_log_size();
SCVAL(req->outbuf, smb_vwv0, 0xff);
}
+/**
+ * @brief Find the smb_cmd offset of the last command pushed
+ * @param[in] buf The buffer we're building up
+ * @retval Where can we put our next andx cmd?
+ *
+ * While chaining requests, the "next" request we're looking at needs to put
+ * its SMB_Command before the data the previous request already built up added
+ * to the chain. Find the offset to the place where we have to put our cmd.
+ */
+
+static bool find_andx_cmd_ofs(uint8_t *buf, size_t *pofs)
+{
+ uint8_t cmd;
+ size_t ofs;
+
+ cmd = CVAL(buf, smb_com);
+
+ SMB_ASSERT(is_andx_req(cmd));
+
+ ofs = smb_vwv0;
+
+ while (CVAL(buf, ofs) != 0xff) {
+
+ if (!is_andx_req(CVAL(buf, ofs))) {
+ return false;
+ }
+
+ /*
+ * ofs is from start of smb header, so add the 4 length
+ * bytes. The next cmd is right after the wct field.
+ */
+ ofs = SVAL(buf, ofs+2) + 4 + 1;
+
+ SMB_ASSERT(ofs+4 < talloc_get_size(buf));
+ }
+
+ *pofs = ofs;
+ return true;
+}
+
+/**
+ * @brief Do the smb chaining at a buffer level
+ * @param[in] poutbuf Pointer to the talloc'ed buffer to be modified
+ * @param[in] smb_command The command that we want to issue
+ * @param[in] wct How many words?
+ * @param[in] vwv The words, already in network order
+ * @param[in] bytes_alignment How shall we align "bytes"?
+ * @param[in] num_bytes How many bytes?
+ * @param[in] bytes The data the request ships
+ *
+ * smb_splice_chain() adds the vwv and bytes to the request already present in
+ * *poutbuf.
+ */
+
+static bool smb_splice_chain(uint8_t **poutbuf, uint8_t smb_command,
+ uint8_t wct, const uint16_t *vwv,
+ size_t bytes_alignment,
+ uint32_t num_bytes, const uint8_t *bytes)
+{
+ uint8_t *outbuf;
+ size_t old_size, new_size;
+ size_t ofs;
+ size_t chain_padding = 0;
+ size_t bytes_padding = 0;
+ bool first_request;
+
+ old_size = talloc_get_size(*poutbuf);
+
+ /*
+ * old_size == smb_wct means we're pushing the first request in for
+ * libsmb/
+ */
+
+ first_request = (old_size == smb_wct);
+
+ if (!first_request && ((old_size % 4) != 0)) {
+ /*
+ * Align the wct field of subsequent requests to a 4-byte
+ * boundary
+ */
+ chain_padding = 4 - (old_size % 4);
+ }
+
+ /*
+ * After the old request comes the new wct field (1 byte), the vwv's
+ * and the num_bytes field. After at we might need to align the bytes
+ * given to us to "bytes_alignment", increasing the num_bytes value.
+ */
+
+ new_size = old_size + chain_padding + 1 + wct * sizeof(uint16_t) + 2;
+
+ if ((bytes_alignment != 0) && ((new_size % bytes_alignment) != 0)) {
+ bytes_padding = bytes_alignment - (new_size % bytes_alignment);
+ }
+
+ new_size += bytes_padding + num_bytes;
+
+ if ((smb_command != SMBwriteX) && (new_size > 0xffff)) {
+ DEBUG(1, ("splice_chain: %u bytes won't fit\n",
+ (unsigned)new_size));
+ return false;
+ }
+
+ outbuf = TALLOC_REALLOC_ARRAY(NULL, *poutbuf, uint8_t, new_size);
+ if (outbuf == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ return false;
+ }
+ *poutbuf = outbuf;
+
+ if (first_request) {
+ SCVAL(outbuf, smb_com, smb_command);
+ } else {
+ size_t andx_cmd_ofs;
+
+ if (!find_andx_cmd_ofs(outbuf, &andx_cmd_ofs)) {
+ DEBUG(1, ("invalid command chain\n"));
+ *poutbuf = TALLOC_REALLOC_ARRAY(
+ NULL, *poutbuf, uint8_t, old_size);
+ return false;
+ }
+
+ if (chain_padding != 0) {
+ memset(outbuf + old_size, 0, chain_padding);
+ old_size += chain_padding;
+ }
+
+ SCVAL(outbuf, andx_cmd_ofs, smb_command);
+ SSVAL(outbuf, andx_cmd_ofs + 2, old_size - 4);
+ }
+
+ ofs = old_size;
+
+ /*
+ * Push the chained request:
+ *
+ * wct field
+ */
+
+ SCVAL(outbuf, ofs, wct);
+ ofs += 1;
+
+ /*
+ * vwv array
+ */
+
+ memcpy(outbuf + ofs, vwv, sizeof(uint16_t) * wct);
+ ofs += sizeof(uint16_t) * wct;
+
+ /*
+ * bcc (byte count)
+ */
+
+ SSVAL(outbuf, ofs, num_bytes + bytes_padding);
+ ofs += sizeof(uint16_t);
+
+ /*
+ * padding
+ */
+
+ if (bytes_padding != 0) {
+ memset(outbuf + ofs, 0, bytes_padding);
+ ofs += bytes_padding;
+ }
+
+ /*
+ * The bytes field
+ */
+
+ memcpy(outbuf + ofs, bytes, num_bytes);
+
+ return true;
+}
+
/****************************************************************************
Construct a chained reply and add it to the already made reply
****************************************************************************/
}
req->outbuf = NULL;
} else {
+ /*
+ * Update smb headers where subsequent chained commands
+ * may have updated them.
+ */
+ SCVAL(req->chain_outbuf, smb_tid, CVAL(req->outbuf, smb_tid));
+ SCVAL(req->chain_outbuf, smb_uid, CVAL(req->outbuf, smb_uid));
+
if (!smb_splice_chain(&req->chain_outbuf,
CVAL(req->outbuf, smb_com),
CVAL(req->outbuf, smb_wct),
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)) {
exit_server_cleanly("chain_reply: srv_send_smb "
"failed.");
}
- TALLOC_FREE(req);
-
+ TALLOC_FREE(req->chain_outbuf);
+ req->done = true;
return;
}
* We end up here if there's any error in the chain syntax. Report a
* DOS error, just like Windows does.
*/
- reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror));
+ reply_force_doserror(req, ERRSRV, ERRerror);
fixup_chain_error_packet(req);
done:
+ /*
+ * This scary statement intends to set the
+ * FLAGS2_32_BIT_ERROR_CODES flg2 field in req->chain_outbuf
+ * to the value req->outbuf carries
+ */
+ SSVAL(req->chain_outbuf, smb_flg2,
+ (SVAL(req->chain_outbuf, smb_flg2) & ~FLAGS2_32_BIT_ERROR_CODES)
+ | (SVAL(req->outbuf, smb_flg2) & FLAGS2_32_BIT_ERROR_CODES));
+
+ /*
+ * Transfer the error codes from the subrequest to the main one
+ */
+ SSVAL(req->chain_outbuf, smb_rcls, SVAL(req->outbuf, smb_rcls));
+ SSVAL(req->chain_outbuf, smb_err, SVAL(req->outbuf, smb_err));
+
if (!smb_splice_chain(&req->chain_outbuf,
CVAL(req->outbuf, smb_com),
CVAL(req->outbuf, smb_wct),
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.");
}
- TALLOC_FREE(req);
+ TALLOC_FREE(req->chain_outbuf);
+ req->done = true;
}
/****************************************************************************
bool encrypted = false;
TALLOC_CTX *mem_ctx = talloc_tos();
NTSTATUS status;
+ uint32_t seqnum;
/* TODO: make this completely nonblocking */
0, /* timeout */
&unread_bytes,
&encrypted,
- &inbuf_len);
+ &inbuf_len, &seqnum);
if (NT_STATUS_EQUAL(status, NT_STATUS_RETRY)) {
goto process;
}
}
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,
static void release_ip(const char *ip, void *priv)
{
char addr[INET6_ADDRSTRLEN];
+ char *p = addr;
+
+ client_socket_addr(get_client_fd(),addr,sizeof(addr));
+
+ if (strncmp("::ffff:", addr, 7) == 0) {
+ p = addr + 7;
+ }
- if (strcmp(client_socket_addr(get_client_fd(),addr,sizeof(addr)), ip) == 0) {
+ if ((strcmp(p, ip) == 0) || ((p != addr) && strcmp(addr, ip) == 0)) {
/* we can't afford to do a clean exit - that involves
database writes, which would potentially mean we
are still running after the failover has finished -
*/
static bool deadtime_fn(const struct timeval *now, void *private_data)
{
- if ((conn_num_open() == 0)
- || (conn_idle_all(now->tv_sec))) {
+ struct smbd_server_connection *sconn = smbd_server_conn;
+ if ((conn_num_open(sconn) == 0)
+ || (conn_idle_all(sconn, now->tv_sec))) {
DEBUG( 2, ( "Closing idle connection\n" ) );
messaging_send(smbd_messaging_context(), procid_self(),
MSG_SHUTDOWN, &data_blob_null);
TALLOC_CTX *frame = talloc_stackframe();
char remaddr[INET6_ADDRSTRLEN];
- smbd_server_conn = talloc_zero(smbd_event_context(), struct smbd_server_connection);
- if (!smbd_server_conn) {
- exit_server("failed to create smbd_server_connection");
+ if (lp_maxprotocol() == PROTOCOL_SMB2 &&
+ lp_security() != SEC_SHARE) {
+ smbd_server_conn->allow_smb2 = true;
}
/* Ensure child is set to blocking mode */
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");
}
if (*lp_rootdir()) {
if (chroot(lp_rootdir()) != 0) {
- DEBUG(0,("Failed changed root to %s\n", lp_rootdir()));
+ DEBUG(0,("Failed to change root to %s\n", lp_rootdir()));
+ exit_server("Failed to chroot()");
+ }
+ if (chdir("/") == -1) {
+ DEBUG(0,("Failed to chdir to / on chroot to %s\n", lp_rootdir()));
exit_server("Failed to chroot()");
}
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");
messaging_register(smbd_messaging_context(), NULL,
MSG_SMB_CLOSE_FILE, msg_close_file);
+ /*
+ * Use the default MSG_DEBUG handler to avoid rebroadcasting
+ * MSGs to all child processes
+ */
+ messaging_deregister(smbd_messaging_context(),
+ MSG_DEBUG, NULL);
+ messaging_register(smbd_messaging_context(), NULL,
+ MSG_DEBUG, debug_message);
+
if ((lp_keepalive() != 0)
&& !(event_add_idle(smbd_event_context(), NULL,
timeval_set(lp_keepalive(), 0),
#endif
- max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
+ smbd_server_conn->nbt.got_session = false;
+
+ smbd_server_conn->smb1.negprot.max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
+
+ smbd_server_conn->smb1.sessions.done_sesssetup = false;
+ smbd_server_conn->smb1.sessions.max_send = BUFFER_SIZE;
+ smbd_server_conn->smb1.sessions.last_session_tag = UID_FIELD_INVALID;
+ /* users from session setup */
+ smbd_server_conn->smb1.sessions.session_userlist = NULL;
+ /* workgroup from session setup. */
+ smbd_server_conn->smb1.sessions.session_workgroup = NULL;
+ /* this holds info on user ids that are already validated for this VC */
+ smbd_server_conn->smb1.sessions.validated_users = NULL;
+ smbd_server_conn->smb1.sessions.next_vuid = VUID_OFFSET;
+ smbd_server_conn->smb1.sessions.num_validated_vuids = 0;
+#ifdef HAVE_NETGROUP
+ smbd_server_conn->smb1.sessions.my_yp_domain = NULL;
+#endif
+
+ conn_init(smbd_server_conn);
+ if (!init_dptrs(smbd_server_conn)) {
+ exit_server("init_dptrs() failed");
+ }
- smbd_server_conn->fde = event_add_fd(smbd_event_context(),
- smbd_server_conn,
- smbd_server_fd(),
- EVENT_FD_READ,
- smbd_server_connection_handler,
- smbd_server_conn);
- if (!smbd_server_conn->fde) {
+ smbd_server_conn->smb1.fde = event_add_fd(smbd_event_context(),
+ smbd_server_conn,
+ smbd_server_fd(),
+ EVENT_FD_READ,
+ smbd_server_connection_handler,
+ smbd_server_conn);
+ if (!smbd_server_conn->smb1.fde) {
exit_server("failed to create smbd_server_connection fde");
}