summaryrefslogtreecommitdiff
path: root/source/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source/smbd')
-rw-r--r--source/smbd/aio.c178
-rw-r--r--source/smbd/blocking.c266
-rw-r--r--source/smbd/chgpasswd.c20
-rw-r--r--source/smbd/close.c56
-rw-r--r--source/smbd/conn.c43
-rw-r--r--source/smbd/connection.c239
-rw-r--r--source/smbd/dir.c59
-rw-r--r--source/smbd/dmapi.c4
-rw-r--r--source/smbd/error.c31
-rw-r--r--source/smbd/fileio.c38
-rw-r--r--source/smbd/filename.c25
-rw-r--r--source/smbd/files.c51
-rw-r--r--source/smbd/ipc.c183
-rw-r--r--source/smbd/lanman.c36
-rw-r--r--source/smbd/mangle_hash.c5
-rw-r--r--source/smbd/message.c20
-rw-r--r--source/smbd/msdfs.c26
-rw-r--r--source/smbd/negprot.c23
-rw-r--r--source/smbd/notify.c56
-rw-r--r--source/smbd/notify_internal.c118
-rw-r--r--source/smbd/nttrans.c448
-rw-r--r--source/smbd/open.c220
-rw-r--r--source/smbd/oplock.c240
-rw-r--r--source/smbd/oplock_irix.c49
-rw-r--r--source/smbd/oplock_linux.c24
-rw-r--r--source/smbd/password.c66
-rw-r--r--source/smbd/pipes.c19
-rw-r--r--source/smbd/posix_acls.c102
-rw-r--r--source/smbd/process.c149
-rw-r--r--source/smbd/quotas.c3
-rw-r--r--source/smbd/reply.c960
-rw-r--r--source/smbd/seal.c704
-rw-r--r--source/smbd/sec_ctx.c89
-rw-r--r--source/smbd/server.c437
-rw-r--r--source/smbd/service.c133
-rw-r--r--source/smbd/session.c192
-rw-r--r--source/smbd/sesssetup.c126
-rw-r--r--source/smbd/share_access.c6
-rw-r--r--source/smbd/sockinit.c201
-rw-r--r--source/smbd/statcache.c151
-rw-r--r--source/smbd/trans2.c503
-rw-r--r--source/smbd/vfs.c2
42 files changed, 2506 insertions, 3795 deletions
diff --git a/source/smbd/aio.c b/source/smbd/aio.c
index f747cf5c065..2559dc95057 100644
--- a/source/smbd/aio.c
+++ b/source/smbd/aio.c
@@ -49,10 +49,8 @@ static struct aio_extra *aio_list_head;
of the aio_read call.
*****************************************************************************/
-static struct aio_extra *create_aio_ex_read(files_struct *fsp,
- size_t buflen,
- uint16 mid,
- const char *inbuf)
+static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen,
+ uint16 mid)
{
struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra);
@@ -68,14 +66,6 @@ static struct aio_extra *create_aio_ex_read(files_struct *fsp,
SAFE_FREE(aio_ex);
return NULL;
}
- /* Save the first 8 bytes of inbuf for possible enc data. */
- aio_ex->inbuf = SMB_MALLOC_ARRAY(char, 8);
- if (!aio_ex->inbuf) {
- SAFE_FREE(aio_ex->outbuf);
- SAFE_FREE(aio_ex);
- return NULL;
- }
- memcpy(aio_ex->inbuf, inbuf, 8);
DLIST_ADD(aio_list_head, aio_ex);
aio_ex->fsp = fsp;
aio_ex->read_req = True;
@@ -242,7 +232,7 @@ BOOL schedule_aio_read_and_X(connection_struct *conn,
bufsize = PTR_DIFF(smb_buf(outbuf),outbuf) + smb_maxcnt;
if ((aio_ex = create_aio_ex_read(fsp, bufsize,
- SVAL(inbuf,smb_mid), inbuf)) == NULL) {
+ SVAL(inbuf,smb_mid))) == NULL) {
DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n"));
return False;
}
@@ -294,6 +284,7 @@ BOOL schedule_aio_write_and_X(connection_struct *conn,
struct aio_extra *aio_ex;
SMB_STRUCT_AIOCB *a;
size_t inbufsize, outbufsize;
+ BOOL write_through = BITSETW(inbuf+smb_vwv7,0);
size_t min_aio_write_size = lp_aio_write_size(SNUM(conn));
if (!min_aio_write_size || (numtowrite < min_aio_write_size)) {
@@ -359,7 +350,22 @@ BOOL schedule_aio_write_and_X(connection_struct *conn,
return False;
}
- srv_defer_sign_response(aio_ex->mid);
+ if (!write_through && !lp_syncalways(SNUM(fsp->conn))
+ && fsp->aio_write_behind) {
+ /* Lie to the client and immediately claim we finished the
+ * write. */
+ SSVAL(aio_ex->outbuf,smb_vwv2,numtowrite);
+ SSVAL(aio_ex->outbuf,smb_vwv4,(numtowrite>>16)&1);
+ show_msg(aio_ex->outbuf);
+ if (!send_smb(smbd_server_fd(),aio_ex->outbuf)) {
+ exit_server_cleanly("handle_aio_write: send_smb "
+ "failed.");
+ }
+ 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->mid);
+ }
outstanding_aio_calls++;
DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write for file "
@@ -382,7 +388,6 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
int ret = 0;
int outsize;
char *outbuf = aio_ex->outbuf;
- char *inbuf = aio_ex->inbuf;
char *data = smb_buf(outbuf);
ssize_t nread = SMB_VFS_AIO_RETURN(aio_ex->fsp,&aio_ex->acb);
@@ -406,7 +411,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
outsize = (UNIXERROR(ERRDOS,ERRnoaccess));
ret = errno;
} else {
- outsize = set_message(inbuf,outbuf,12,nread,False);
+ outsize = set_message(outbuf,12,nread,False);
SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be * -1. */
SSVAL(outbuf,smb_vwv5,nread);
SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
@@ -419,7 +424,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex)
aio_ex->acb.aio_nbytes, (int)nread ) );
}
- smb_setlen(inbuf,outbuf,outsize - 4);
+ smb_setlen(outbuf,outsize - 4);
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf)) {
exit_server_cleanly("handle_aio_read_complete: send_smb "
@@ -444,10 +449,34 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex)
int ret = 0;
files_struct *fsp = aio_ex->fsp;
char *outbuf = aio_ex->outbuf;
- char *inbuf = aio_ex->inbuf;
ssize_t numtowrite = aio_ex->acb.aio_nbytes;
ssize_t nwritten = SMB_VFS_AIO_RETURN(fsp,&aio_ex->acb);
+ if (fsp->aio_write_behind) {
+ if (nwritten != numtowrite) {
+ if (nwritten == -1) {
+ DEBUG(5,("handle_aio_write_complete: "
+ "aio_write_behind failed ! File %s "
+ "is corrupt ! Error %s\n",
+ fsp->fsp_name, strerror(errno) ));
+ ret = errno;
+ } else {
+ DEBUG(0,("handle_aio_write_complete: "
+ "aio_write_behind failed ! File %s "
+ "is corrupt ! Wanted %u bytes but "
+ "only wrote %d\n", fsp->fsp_name,
+ (unsigned int)numtowrite,
+ (int)nwritten ));
+ ret = EIO;
+ }
+ } else {
+ DEBUG(10,("handle_aio_write_complete: "
+ "aio_write_behind completed for file %s\n",
+ fsp->fsp_name ));
+ }
+ return 0;
+ }
+
/* We don't need outsize or set_message here as we've already set the
fixed size length when we set up the aio call. */
@@ -590,6 +619,115 @@ int process_aio_queue(void)
}
/****************************************************************************
+ We're doing write behind and the client closed the file. Wait up to 30
+ seconds (my arbitrary choice) for the aio to complete. Return 0 if all writes
+ completed, errno to return if not.
+*****************************************************************************/
+
+#define SMB_TIME_FOR_AIO_COMPLETE_WAIT 29
+
+int wait_for_aio_completion(files_struct *fsp)
+{
+ struct aio_extra *aio_ex;
+ const SMB_STRUCT_AIOCB **aiocb_list;
+ int aio_completion_count = 0;
+ time_t start_time = time(NULL);
+ int seconds_left;
+
+ for (seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT;
+ seconds_left >= 0;) {
+ int err = 0;
+ int i;
+ struct timespec ts;
+
+ aio_completion_count = 0;
+ for( aio_ex = aio_list_head; aio_ex; aio_ex = aio_ex->next) {
+ if (aio_ex->fsp == fsp) {
+ aio_completion_count++;
+ }
+ }
+
+ if (!aio_completion_count) {
+ return 0;
+ }
+
+ DEBUG(3,("wait_for_aio_completion: waiting for %d aio events "
+ "to complete.\n", aio_completion_count ));
+
+ aiocb_list = SMB_MALLOC_ARRAY(const SMB_STRUCT_AIOCB *,
+ aio_completion_count);
+ if (!aiocb_list) {
+ return ENOMEM;
+ }
+
+ for( i = 0, aio_ex = aio_list_head;
+ aio_ex;
+ aio_ex = aio_ex->next) {
+ if (aio_ex->fsp == fsp) {
+ aiocb_list[i++] = &aio_ex->acb;
+ }
+ }
+
+ /* Now wait up to seconds_left for completion. */
+ ts.tv_sec = seconds_left;
+ ts.tv_nsec = 0;
+
+ DEBUG(10,("wait_for_aio_completion: %d events, doing a wait "
+ "of %d seconds.\n",
+ aio_completion_count, seconds_left ));
+
+ err = SMB_VFS_AIO_SUSPEND(fsp, aiocb_list,
+ aio_completion_count, &ts);
+
+ DEBUG(10,("wait_for_aio_completion: returned err = %d, "
+ "errno = %s\n", err, strerror(errno) ));
+
+ if (err == -1 && errno == EAGAIN) {
+ DEBUG(0,("wait_for_aio_completion: aio_suspend timed "
+ "out waiting for %d events after a wait of "
+ "%d seconds\n", aio_completion_count,
+ seconds_left));
+ /* Timeout. */
+ cancel_aio_by_fsp(fsp);
+ SAFE_FREE(aiocb_list);
+ return EIO;
+ }
+
+ /* One or more events might have completed - process them if
+ * so. */
+ for( i = 0; i < aio_completion_count; i++) {
+ uint16 mid = aiocb_list[i]->aio_sigevent.sigev_value.sival_int;
+
+ aio_ex = find_aio_ex(mid);
+
+ if (!aio_ex) {
+ DEBUG(0, ("wait_for_aio_completion: mid %u "
+ "doesn't match an aio record\n",
+ (unsigned int)mid ));
+ continue;
+ }
+
+ if (!handle_aio_completed(aio_ex, &err)) {
+ continue;
+ }
+ delete_aio_ex(aio_ex);
+ }
+
+ SAFE_FREE(aiocb_list);
+ seconds_left = SMB_TIME_FOR_AIO_COMPLETE_WAIT
+ - (time(NULL) - start_time);
+ }
+
+ /* We timed out - we don't know why. Return ret if already an error,
+ * else EIO. */
+ DEBUG(10,("wait_for_aio_completion: aio_suspend timed out waiting "
+ "for %d events\n",
+ aio_completion_count));
+
+ return EIO;
+}
+
+/****************************************************************************
Cancel any outstanding aio requests. The client doesn't care about the reply.
*****************************************************************************/
@@ -647,4 +785,8 @@ void cancel_aio_by_fsp(files_struct *fsp)
{
}
+BOOL wait_for_aio_completion(files_struct *fsp)
+{
+ return True;
+}
#endif
diff --git a/source/smbd/blocking.c b/source/smbd/blocking.c
index 924b99b113f..b9e7c144705 100644
--- a/source/smbd/blocking.c
+++ b/source/smbd/blocking.c
@@ -52,9 +52,6 @@ static blocking_lock_record *blocking_lock_queue;
/* dlink list we move cancelled lock records onto. */
static blocking_lock_record *blocking_lock_cancelled_queue;
-/* The event that makes us process our blocking lock queue */
-static struct timed_event *brl_timeout;
-
/****************************************************************************
Destructor for the above structure.
****************************************************************************/
@@ -74,78 +71,9 @@ static BOOL in_chained_smb(void)
return (chain_size != 0);
}
-static void received_unlock_msg(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_type,
- struct server_id server_id,
- DATA_BLOB *data);
-static void process_blocking_lock_queue(void);
-
-static void brl_timeout_fn(struct event_context *event_ctx,
- struct timed_event *te,
- const struct timeval *now,
- void *private_data)
-{
- SMB_ASSERT(brl_timeout == te);
- TALLOC_FREE(brl_timeout);
-
- change_to_root_user(); /* TODO: Possibly run all timed events as
- * root */
-
- process_blocking_lock_queue();
-}
-
-/****************************************************************************
- After a change to blocking_lock_queue, recalculate the timed_event for the
- next processing.
-****************************************************************************/
-
-static BOOL recalc_brl_timeout(void)
-{
- blocking_lock_record *brl;
- struct timeval next_timeout;
-
- TALLOC_FREE(brl_timeout);
-
- next_timeout = timeval_zero();
-
- for (brl = blocking_lock_queue; brl; brl = brl->next) {
- if (timeval_is_zero(&brl->expire_time)) {
- /*
- * If we're blocked on pid 0xFFFFFFFF this is
- * a POSIX lock, so calculate a timeout of
- * 10 seconds into the future.
- */
- if (brl->blocking_pid == 0xFFFFFFFF) {
- struct timeval psx_to = timeval_current_ofs(10, 0);
- next_timeout = timeval_min(&next_timeout, &psx_to);
- }
-
- continue;
- }
-
- if (timeval_is_zero(&next_timeout)) {
- next_timeout = brl->expire_time;
- }
- else {
- next_timeout = timeval_min(&next_timeout,
- &brl->expire_time);
- }
- }
-
- if (timeval_is_zero(&next_timeout)) {
- return True;
- }
-
- if (!(brl_timeout = event_add_timed(smbd_event_context(), NULL,
- next_timeout, "brl_timeout",
- brl_timeout_fn, NULL))) {
- return False;
- }
-
- return True;
-}
-
+static void received_unlock_msg(int msg_type, struct process_id src,
+ void *buf, size_t len,
+ void *private_data);
/****************************************************************************
Function to push a blocking lock request onto the lock queue.
@@ -211,7 +139,7 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck,
blr->length = length;
/* Add a pending lock record for this. */
- status = brl_lock(smbd_messaging_context(), br_lck,
+ status = brl_lock(br_lck,
lock_pid,
procid_self(),
offset,
@@ -229,12 +157,11 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck,
}
DLIST_ADD_END(blocking_lock_queue, blr, blocking_lock_record *);
- recalc_brl_timeout();
/* Ensure we'll receive messages when this is unlocked. */
if (!set_lock_msg) {
- messaging_register(smbd_messaging_context(), NULL,
- MSG_SMB_UNLOCK, received_unlock_msg);
+ message_register(MSG_SMB_UNLOCK, received_unlock_msg,
+ NULL);
set_lock_msg = True;
}
@@ -254,15 +181,13 @@ BOOL push_blocking_lock_request( struct byte_range_lock *br_lck,
Return a smd with a given size.
*****************************************************************************/
-static void send_blocking_reply(char *outbuf, int outsize, const char *inbuf)
+static void send_blocking_reply(char *outbuf, int outsize)
{
- if(outsize > 4) {
- smb_setlen(inbuf, outbuf,outsize - 4);
- }
+ if(outsize > 4)
+ smb_setlen(outbuf,outsize - 4);
- if (!send_smb(smbd_server_fd(),outbuf)) {
+ if (!send_smb(smbd_server_fd(),outbuf))
exit_server_cleanly("send_blocking_reply: send_smb failed.");
- }
}
/****************************************************************************
@@ -277,7 +202,7 @@ static void reply_lockingX_success(blocking_lock_record *blr)
int outsize = 0;
construct_reply_common(inbuf, outbuf);
- set_message(inbuf,outbuf,2,0,True);
+ set_message(outbuf,2,0,True);
/*
* As this message is a lockingX call we must handle
@@ -291,7 +216,7 @@ static void reply_lockingX_success(blocking_lock_record *blr)
outsize += chain_size;
- send_blocking_reply(outbuf,outsize,inbuf);
+ send_blocking_reply(outbuf,outsize);
}
/****************************************************************************
@@ -372,8 +297,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status)
* request would never have been queued. JRA.
*/
- do_unlock(smbd_messaging_context(),
- fsp,
+ do_unlock(fsp,
lock_pid,
count,
offset,
@@ -453,8 +377,7 @@ static BOOL process_lockingX(blocking_lock_record *blr)
* request would never have been queued. JRA.
*/
errno = 0;
- br_lck = do_lock(smbd_messaging_context(),
- fsp,
+ br_lck = do_lock(fsp,
lock_pid,
count,
offset,
@@ -516,8 +439,7 @@ static BOOL process_trans2(blocking_lock_record *blr)
char *outbuf;
char params[2];
NTSTATUS status;
- struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
- blr->fsp,
+ struct byte_range_lock *br_lck = do_lock(blr->fsp,
blr->lock_pid,
blr->count,
blr->offset,
@@ -547,7 +469,7 @@ static BOOL process_trans2(blocking_lock_record *blr)
SCVAL(outbuf,smb_com,SMBtrans2);
SSVAL(params,0,0);
/* Fake up max_data_bytes here - we know it fits. */
- send_trans2_replies(inbuf, outbuf, max_send, params, 2, NULL, 0, 0xffff);
+ send_trans2_replies(outbuf, max_send, params, 2, NULL, 0, 0xffff);
return True;
}
@@ -667,25 +589,75 @@ BOOL blocking_lock_was_deferred(int mid)
Set a flag as an unlock request affects one of our pending locks.
*****************************************************************************/
-static void received_unlock_msg(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_type,
- struct server_id server_id,
- DATA_BLOB *data)
+static void received_unlock_msg(int msg_type, struct process_id src,
+ void *buf, size_t len,
+ void *private_data)
{
DEBUG(10,("received_unlock_msg\n"));
process_blocking_lock_queue();
}
/****************************************************************************
+ Return the number of milliseconds to the next blocking locks timeout, or default_timeout
+*****************************************************************************/
+
+unsigned int blocking_locks_timeout_ms(unsigned int default_timeout_ms)
+{
+ unsigned int timeout_ms = default_timeout_ms;
+ struct timeval tv_curr;
+ SMB_BIG_INT min_tv_dif_us = default_timeout_ms * 1000;
+ blocking_lock_record *blr = blocking_lock_queue;
+
+ /* note that we avoid the GetTimeOfDay() syscall if there are no blocking locks */
+ if (!blr) {
+ return timeout_ms;
+ }
+
+ tv_curr = timeval_current();
+
+ for (; blr; blr = blr->next) {
+ SMB_BIG_INT tv_dif_us;
+
+ if (timeval_is_zero(&blr->expire_time)) {
+ /*
+ * If we're blocked on pid 0xFFFFFFFF this is
+ * a POSIX lock, so calculate a timeout of
+ * 10 seconds.
+ */
+ if (blr->blocking_pid == 0xFFFFFFFF) {
+ tv_dif_us = 10 * 1000 * 1000;
+ min_tv_dif_us = MIN(min_tv_dif_us, tv_dif_us);
+ }
+ continue; /* Never timeout. */
+ }
+
+ tv_dif_us = usec_time_diff(&blr->expire_time, &tv_curr);
+ min_tv_dif_us = MIN(min_tv_dif_us, tv_dif_us);
+ }
+
+ if (min_tv_dif_us < 0) {
+ min_tv_dif_us = 0;
+ }
+
+ timeout_ms = (unsigned int)(min_tv_dif_us / (SMB_BIG_INT)1000);
+
+ if (timeout_ms < 1) {
+ timeout_ms = 1;
+ }
+
+ DEBUG(10,("blocking_locks_timeout_ms: returning %u\n", timeout_ms));
+
+ return timeout_ms;
+}
+
+/****************************************************************************
Process the blocking lock queue. Note that this is only called as root.
*****************************************************************************/
-static void process_blocking_lock_queue(void)
+void process_blocking_lock_queue(void)
{
struct timeval tv_curr = timeval_current();
blocking_lock_record *blr, *next = NULL;
- BOOL recalc_timeout = False;
/*
* Go through the queue and see if we can get any of the locks.
@@ -713,18 +685,14 @@ static void process_blocking_lock_queue(void)
DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n",
fsp->fnum, fsp->fsp_name ));
- if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
+ if(!change_to_user(conn,vuid)) {
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
/*
- * Lock expired - throw away all previously
- * obtained locks and return lock error.
+ * Remove the entry and return an error to the client.
*/
if (br_lck) {
- DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
- fsp->fnum, fsp->fsp_name ));
-
brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
@@ -734,14 +702,15 @@ static void process_blocking_lock_queue(void)
TALLOC_FREE(br_lck);
}
- blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
+ DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
+ vuid ));
+ blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
- recalc_timeout = True;
continue;
}
- if(!change_to_user(conn,vuid)) {
+ if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) {
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
/*
@@ -758,21 +727,22 @@ static void process_blocking_lock_queue(void)
TALLOC_FREE(br_lck);
}
- DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",
- vuid ));
+ DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
- recalc_timeout = True;
+ change_to_root_user();
continue;
}
- if(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) {
- struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
+ /*
+ * Go through the remaining locks and try and obtain them.
+ * The call returns True if all locks were obtained successfully
+ * and False if we still need to wait.
+ */
- /*
- * Remove the entry and return an error to the client.
- */
+ if(blocking_lock_record_process(blr)) {
+ struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
if (br_lck) {
brl_lock_cancel(br_lck,
@@ -784,25 +754,31 @@ static void process_blocking_lock_queue(void)
TALLOC_FREE(br_lck);
}
- DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));
- blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);
DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
- recalc_timeout = True;
change_to_root_user();
continue;
}
+ change_to_root_user();
+
/*
- * Go through the remaining locks and try and obtain them.
- * The call returns True if all locks were obtained successfully
- * and False if we still need to wait.
+ * We couldn't get the locks for this record on the list.
+ * If the time has expired, return a lock error.
*/
- if(blocking_lock_record_process(blr)) {
+ if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) {
struct byte_range_lock *br_lck = brl_get_locks(NULL, fsp);
+ /*
+ * Lock expired - throw away all previously
+ * obtained locks and return lock error.
+ */
+
if (br_lck) {
+ DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n",
+ fsp->fnum, fsp->fsp_name ));
+
brl_lock_cancel(br_lck,
blr->lock_pid,
procid_self(),
@@ -812,15 +788,12 @@ static void process_blocking_lock_queue(void)
TALLOC_FREE(br_lck);
}
+ blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT);
DLIST_REMOVE(blocking_lock_queue, blr);
free_blocking_lock_record(blr);
- recalc_timeout = True;
+ continue;
}
- change_to_root_user();
- }
- if (recalc_timeout) {
- recalc_brl_timeout();
}
}
@@ -830,24 +803,23 @@ static void process_blocking_lock_queue(void)
#define MSG_BLOCKING_LOCK_CANCEL_SIZE (sizeof(blocking_lock_record *) + sizeof(NTSTATUS))
-static void process_blocking_lock_cancel_message(struct messaging_context *ctx,
- void *private_data,
- uint32_t msg_type,
- struct server_id server_id,
- DATA_BLOB *data)
+static void process_blocking_lock_cancel_message(int msg_type,
+ struct process_id src,
+ void *buf, size_t len,
+ void *private_data)
{
NTSTATUS err;
- const char *msg = (const char *)data->data;
+ const char *msg = (const char *)buf;
blocking_lock_record *blr;
- if (data->data == NULL) {
- smb_panic("process_blocking_lock_cancel_message: null msg");
+ if (buf == NULL) {
+ smb_panic("process_blocking_lock_cancel_message: null msg\n");
}
- if (data->length != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
+ if (len != MSG_BLOCKING_LOCK_CANCEL_SIZE) {
DEBUG(0, ("process_blocking_lock_cancel_message: "
- "Got invalid msg len %d\n", (int)data->length));
- smb_panic("process_blocking_lock_cancel_message: bad msg");
+ "Got invalid msg len %d\n", (int)len));
+ smb_panic("process_blocking_lock_cancel_message: bad msg\n");
}
memcpy(&blr, msg, sizeof(blr));
@@ -879,9 +851,9 @@ BOOL blocking_lock_cancel(files_struct *fsp,
if (!initialized) {
/* Register our message. */
- messaging_register(smbd_messaging_context(), NULL,
- MSG_SMB_BLOCKING_LOCK_CANCEL,
- process_blocking_lock_cancel_message);
+ message_register(MSG_SMB_BLOCKING_LOCK_CANCEL,
+ process_blocking_lock_cancel_message,
+ NULL);
initialized = True;
}
@@ -915,9 +887,9 @@ BOOL blocking_lock_cancel(files_struct *fsp,
memcpy(msg, &blr, sizeof(blr));
memcpy(&msg[sizeof(blr)], &err, sizeof(NTSTATUS));
- messaging_send_buf(smbd_messaging_context(), procid_self(),
- MSG_SMB_BLOCKING_LOCK_CANCEL,
- (uint8 *)&msg, sizeof(msg));
+ message_send_pid(pid_to_procid(sys_getpid()),
+ MSG_SMB_BLOCKING_LOCK_CANCEL,
+ &msg, sizeof(msg), True);
return True;
}
diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c
index 1227163c224..7c6886b81c9 100644
--- a/source/smbd/chgpasswd.c
+++ b/source/smbd/chgpasswd.c
@@ -983,8 +983,8 @@ static BOOL check_passwd_history(struct samu *sampass, const char *plaintext)
return True;
}
- dump_data(100, new_nt_p16, NT_HASH_LEN);
- dump_data(100, pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen);
+ dump_data(100, (const char *)new_nt_p16, NT_HASH_LEN);
+ dump_data(100, (const char *)pwhistory, PW_HISTORY_ENTRY_LEN*pwHisLen);
memset(zero_md5_nt_pw, '\0', SALTED_MD5_HASH_LEN);
for (i=0; i<pwHisLen; i++) {
@@ -1019,7 +1019,6 @@ static BOOL check_passwd_history(struct samu *sampass, const char *plaintext)
NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passwd, BOOL as_root, uint32 *samr_reject_reason)
{
uint32 min_len;
- uint32 refuse;
struct passwd *pass = NULL;
const char *username = pdb_get_username(hnd);
time_t can_change_time = pdb_get_pass_can_change_time(hnd);
@@ -1037,21 +1036,6 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw
return NT_STATUS_ACCOUNT_RESTRICTION;
}
- /* check to see if it is a Machine account and if the policy
- * denies machines to change the password. *
- * Should we deny also SRVTRUST and/or DOMSTRUST ? .SSS. */
- if (pdb_get_acct_ctrl(hnd) & ACB_WSTRUST) {
- if (pdb_get_account_policy(AP_REFUSE_MACHINE_PW_CHANGE, &refuse) && refuse) {
- DEBUG(1, ("Machine %s cannot change password now, "
- "denied by Refuse Machine Password Change policy\n",
- username));
- if (samr_reject_reason) {
- *samr_reject_reason = REJECT_REASON_OTHER;
- }
- return NT_STATUS_ACCOUNT_RESTRICTION;
- }
- }
-
/* removed calculation here, becuase passdb now calculates
based on policy. jmcd */
if ((can_change_time != 0) && (time(NULL) < can_change_time)) {
diff --git a/source/smbd/close.c b/source/smbd/close.c
index c4aa2e2e28c..a094d8a4da0 100644
--- a/source/smbd/close.c
+++ b/source/smbd/close.c
@@ -135,10 +135,8 @@ static void notify_deferred_opens(struct share_mode_lock *lck)
share_mode_entry_to_message(msg, e);
- messaging_send_buf(smbd_messaging_context(),
- e->pid, MSG_SMB_OPEN_RETRY,
- (uint8 *)msg,
- MSG_SMB_SHARE_MODE_ENTRY_SIZE);
+ message_send_pid(e->pid, MSG_SMB_OPEN_RETRY,
+ msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
}
}
}
@@ -155,7 +153,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
struct share_mode_lock *lck;
SMB_STRUCT_STAT sbuf;
NTSTATUS status = NT_STATUS_OK;
- struct file_id id;
+ int ret;
/*
* Lock the share entries, and determine if we should delete
@@ -163,7 +161,7 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
* This prevents race conditions with the file being created. JRA.
*/
- lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0, ("close_remove_share_mode: Could not get share mode "
@@ -248,8 +246,14 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
/* We can only delete the file if the name we have is still valid and
hasn't been renamed. */
-
- if(SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf) != 0) {
+
+ if (fsp->posix_open) {
+ ret = SMB_VFS_LSTAT(conn,fsp->fsp_name,&sbuf);
+ } else {
+ ret = SMB_VFS_STAT(conn,fsp->fsp_name,&sbuf);
+ }
+
+ if (ret != 0) {
DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
"was set and stat failed with error %s\n",
fsp->fsp_name, strerror(errno) ));
@@ -259,17 +263,15 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
goto done;
}
- id = file_id_sbuf(&sbuf);
-
- if (!file_id_equal(&fsp->file_id, &id)) {
+ if(sbuf.st_dev != fsp->dev || sbuf.st_ino != fsp->inode) {
DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
"was set and dev and/or inode does not match\n",
fsp->fsp_name ));
- DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
- "stat file_id %s\n",
+ DEBUG(5,("close_remove_share_mode: file %s. stored dev = %x, "
+ "inode = %.0f stat dev = %x, inode = %.0f\n",
fsp->fsp_name,
- file_id_static_string(&fsp->file_id),
- file_id_static_string2(&id)));
+ (unsigned int)fsp->dev, (double)fsp->inode,
+ (unsigned int)sbuf.st_dev, (double)sbuf.st_ino ));
/*
* Don't save the errno here, we ignore this error
*/
@@ -327,16 +329,28 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
NTSTATUS status = NT_STATUS_OK;
NTSTATUS saved_status1 = NT_STATUS_OK;
NTSTATUS saved_status2 = NT_STATUS_OK;
+ NTSTATUS saved_status3 = NT_STATUS_OK;
connection_struct *conn = fsp->conn;
- cancel_aio_by_fsp(fsp);
+ if (fsp->aio_write_behind) {
+ /*
+ * If we're finishing write behind on a close we can get a write
+ * error here, we must remember this.
+ */
+ int ret = wait_for_aio_completion(fsp);
+ if (ret) {
+ saved_status1 = map_nt_error_from_unix(ret);
+ }
+ } else {
+ cancel_aio_by_fsp(fsp);
+ }
/*
* If we're flushing on a close we can get a write
* error here, we must remember this.
*/
- saved_status1 = close_filestruct(fsp);
+ saved_status2 = close_filestruct(fsp);
if (fsp->print_file) {
print_fsp_end(fsp, close_type);
@@ -350,14 +364,14 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
if (fsp->fh->ref_count == 1) {
/* Should we return on error here... ? */
- saved_status2 = close_remove_share_mode(fsp, close_type);
+ saved_status3 = close_remove_share_mode(fsp, close_type);
}
if(fsp->oplock_type) {
release_file_oplock(fsp);
}
- locking_close_file(smbd_messaging_context(), fsp);
+ locking_close_file(fsp);
status = fd_close(conn, fsp);
@@ -381,6 +395,8 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_
status = saved_status1;
} else if (!NT_STATUS_IS_OK(saved_status2)) {
status = saved_status2;
+ } else if (!NT_STATUS_IS_OK(saved_status3)) {
+ status = saved_status3;
}
}
@@ -408,7 +424,7 @@ static NTSTATUS close_directory(files_struct *fsp, enum file_close_type close_ty
* reference to a directory also.
*/
- lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0, ("close_directory: Could not get share mode lock for %s\n", fsp->fsp_name));
diff --git a/source/smbd/conn.c b/source/smbd/conn.c
index da55c0a6459..282a82ce049 100644
--- a/source/smbd/conn.c
+++ b/source/smbd/conn.c
@@ -187,18 +187,14 @@ void conn_close_all(void)
Idle inactive connections.
****************************************************************************/
-BOOL conn_idle_all(time_t t)
+BOOL conn_idle_all(time_t t, int deadtime)
{
- int deadtime = lp_deadtime()*60;
pipes_struct *plist = NULL;
- connection_struct *conn;
-
- if (deadtime <= 0)
- deadtime = DEFAULT_SMBD_TIMEOUT;
-
- for (conn=Connections;conn;conn=conn->next) {
+ BOOL allidle = True;
+ connection_struct *conn, *next;
- time_t age = t - conn->lastused;
+ for (conn=Connections;conn;conn=next) {
+ next=conn->next;
/* Update if connection wasn't idle. */
if (conn->lastused != conn->lastused_count) {
@@ -207,12 +203,12 @@ BOOL conn_idle_all(time_t t)
}
/* close dirptrs on connections that are idle */
- if (age > DPTR_IDLE_TIMEOUT) {
+ if ((t-conn->lastused) > DPTR_IDLE_TIMEOUT) {
dptr_idlecnum(conn);
}
- if (conn->num_files_open > 0 || age < deadtime) {
- return False;
+ if (conn->num_files_open > 0 || (t-conn->lastused)<deadtime) {
+ allidle = False;
}
}
@@ -221,14 +217,11 @@ BOOL conn_idle_all(time_t t)
* idle with a handle open.
*/
- for (plist = get_first_internal_pipe(); plist;
- plist = get_next_internal_pipe(plist)) {
- if (plist->pipe_handles && plist->pipe_handles->count) {
- return False;
- }
- }
+ for (plist = get_first_internal_pipe(); plist; plist = get_next_internal_pipe(plist))
+ if (plist->pipe_handles && plist->pipe_handles->count)
+ allidle = False;
- return True;
+ return allidle;
}
/****************************************************************************
@@ -286,6 +279,7 @@ void conn_free_internal(connection_struct *conn)
free_namearray(conn->veto_list);
free_namearray(conn->hide_list);
free_namearray(conn->veto_oplock_list);
+ free_namearray(conn->aio_write_behind_list);
string_free(&conn->user);
string_free(&conn->dirpath);
@@ -306,8 +300,6 @@ void conn_free(connection_struct *conn)
DLIST_REMOVE(Connections, conn);
bitmap_clear(bmap, conn->cnum);
-
- SMB_ASSERT(num_open > 0);
num_open--;
conn_free_internal(conn);
@@ -319,16 +311,13 @@ the message contains just a share name and all instances of that
share are unmounted
the special sharename '*' forces unmount of all shares
****************************************************************************/
-void msg_force_tdis(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_type,
- struct server_id server_id,
- DATA_BLOB *data)
+void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len,
+ void *private_data)
{
connection_struct *conn, *next;
fstring sharename;
- fstrcpy(sharename, (const char *)data->data);
+ fstrcpy(sharename, (const char *)buf);
if (strcmp(sharename, "*") == 0) {
DEBUG(1,("Forcing close of all shares\n"));
diff --git a/source/smbd/connection.c b/source/smbd/connection.c
index 211f0e6acba..325d4a58c64 100644
--- a/source/smbd/connection.c
+++ b/source/smbd/connection.c
@@ -20,31 +20,64 @@
#include "includes.h"
+static TDB_CONTEXT *tdb;
+
+/****************************************************************************
+ Return the connection tdb context (used for message send all).
+****************************************************************************/
+
+TDB_CONTEXT *conn_tdb_ctx(void)
+{
+ if (!tdb)
+ tdb = tdb_open_log(lock_path("connections.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
+ O_RDWR | O_CREAT, 0644);
+
+ return tdb;
+}
+
+static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *pkbuf, struct connections_key *pkey)
+{
+ ZERO_STRUCTP(pkey);
+ pkey->pid = procid_self();
+ pkey->cnum = conn?conn->cnum:-1;
+ fstrcpy(pkey->name, name);
+#ifdef DEVELOPER
+ /* valgrind fixer... */
+ {
+ size_t sl = strlen(pkey->name);
+ if (sizeof(fstring)-sl)
+ memset(&pkey->name[sl], '\0', sizeof(fstring)-sl);
+ }
+#endif
+
+ pkbuf->dptr = (char *)pkey;
+ pkbuf->dsize = sizeof(*pkey);
+}
+
/****************************************************************************
Delete a connection record.
****************************************************************************/
BOOL yield_connection(connection_struct *conn, const char *name)
{
- struct db_record *rec;
- NTSTATUS status;
+ struct connections_key key;
+ TDB_DATA kbuf;
+
+ if (!tdb)
+ return False;
DEBUG(3,("Yielding connection to %s\n",name));
- if (!(rec = connections_fetch_entry(NULL, conn, name))) {
- DEBUG(0, ("connections_fetch_entry failed\n"));
- return False;
- }
+ make_conn_key(conn, name, &kbuf, &key);
- status = rec->delete_rec(rec);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG( NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND) ? 3 : 0,
- ("deleting connection record returned %s\n",
- nt_errstr(status)));
+ if (tdb_delete(tdb, kbuf) != 0) {
+ int dbg_lvl = (!conn && (tdb_error(tdb) == TDB_ERR_NOEXIST)) ? 3 : 0;
+ DEBUG(dbg_lvl,("yield_connection: tdb_delete for name %s failed with error %s.\n",
+ name, tdb_errorstr(tdb) ));
+ return (False);
}
- TALLOC_FREE(rec);
- return NT_STATUS_IS_OK(status);
+ return(True);
}
struct count_stat {
@@ -58,45 +91,31 @@ struct count_stat {
Count the entries belonging to a service in the connection db.
****************************************************************************/
-static int count_fn(struct db_record *rec,
- const struct connections_key *ckey,
- const struct connections_data *crec,
- void *udp)
+static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *udp)
{
+ struct connections_data crec;
struct count_stat *cs = (struct count_stat *)udp;
- if (crec->cnum == -1) {
+ if (dbuf.dsize != sizeof(crec))
+ return 0;
+
+ memcpy(&crec, dbuf.dptr, sizeof(crec));
+
+ if (crec.cnum == -1)
return 0;
- }
/* If the pid was not found delete the entry from connections.tdb */
- if (cs->Clear && !process_exists(crec->pid) && (errno == ESRCH)) {
- NTSTATUS status;
+ if (cs->Clear && !process_exists(crec.pid) && (errno == ESRCH)) {
DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n",
- procid_str_static(&crec->pid), crec->cnum,
- crec->servicename));
-
- status = rec->delete_rec(rec);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("count_fn: tdb_delete failed with error %s\n",
- nt_errstr(status)));
- }
+ procid_str_static(&crec.pid), crec.cnum, crec.servicename));
+ if (tdb_delete(the_tdb, kbuf) != 0)
+ DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(tdb) ));
return 0;
}
-
- if (cs->name) {
- /* We are counting all the connections to a given share. */
- if (strequal(crec->servicename, cs->name)) {
- cs->curr_connections++;
- }
- } else {
- /* We are counting all the connections. Static registrations
- * like the lpq backgroud process and the smbd daemon process
- * have a cnum of -1, so won't be counted here.
- */
+
+ if (strequal(crec.servicename, cs->name))
cs->curr_connections++;
- }
return 0;
}
@@ -119,50 +138,51 @@ int count_current_connections( const char *sharename, BOOL clear )
* as it leads to deadlock.
*/
- if (connections_forall(count_fn, &cs) == -1) {
- DEBUG(0,("count_current_connections: traverse of "
- "connections.tdb failed\n"));
- DEBUGADD(0, ("count_current_connections: connection count of %d might not be accurate",
- cs.curr_connections));
+ if (tdb_traverse(tdb, count_fn, &cs) == -1) {
+ DEBUG(0,("claim_connection: traverse of connections.tdb failed with error %s.\n",
+ tdb_errorstr(tdb) ));
+ return False;
}
-
- /* If the traverse failed part-way through, we at least return
- * as many connections as we had already counted. If it failed
- * right at the start, we will return 0, which is about all we
- * can do anywway.
- */
-
+
return cs.curr_connections;
}
/****************************************************************************
- Count the number of connections open across all shares.
-****************************************************************************/
-
-int count_all_current_connections(void)
-{
- return count_current_connections(NULL, True /* clear stale entries */);
-}
-
-/****************************************************************************
Claim an entry in the connections database.
****************************************************************************/
-BOOL claim_connection(connection_struct *conn, const char *name,
- uint32 msg_flags)
+BOOL claim_connection(connection_struct *conn, const char *name,int max_connections,BOOL Clear, uint32 msg_flags)
{
- struct db_record *rec;
+ struct connections_key key;
struct connections_data crec;
- TDB_DATA dbuf;
- NTSTATUS status;
+ TDB_DATA kbuf, dbuf;
+
+ if (!tdb) {
+ if ( (tdb =conn_tdb_ctx()) == NULL ) {
+ return False;
+ }
+ }
+
+ /*
+ * Enforce the max connections parameter.
+ */
- DEBUG(5,("claiming [%s]\n", name));
+ if (max_connections > 0) {
+ int curr_connections;
+
+ curr_connections = count_current_connections( lp_servicename(SNUM(conn)), True );
- if (!(rec = connections_fetch_entry(NULL, conn, name))) {
- DEBUG(0, ("connections_fetch_entry failed\n"));
- return False;
+ if (curr_connections >= max_connections) {
+ DEBUG(1,("claim_connection: Max connections (%d) exceeded for %s\n",
+ max_connections, name ));
+ return False;
+ }
}
+ DEBUG(5,("claiming %s %d\n",name,max_connections));
+
+ make_conn_key(conn, name, &kbuf, &key);
+
/* fill in the crec */
ZERO_STRUCT(crec);
crec.magic = 0x280267;
@@ -171,26 +191,21 @@ BOOL claim_connection(connection_struct *conn, const char *name,
if (conn) {
crec.uid = conn->uid;
crec.gid = conn->gid;
- strlcpy(crec.servicename, lp_servicename(SNUM(conn)),
- sizeof(crec.servicename));
+ safe_strcpy(crec.servicename,
+ lp_servicename(SNUM(conn)),sizeof(crec.servicename)-1);
}
crec.start = time(NULL);
crec.bcast_msg_flags = msg_flags;
- strlcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine));
- strlcpy(crec.addr,conn?conn->client_address:client_addr(),
- sizeof(crec.addr));
+ safe_strcpy(crec.machine,get_remote_machine_name(),sizeof(crec.machine)-1);
+ safe_strcpy(crec.addr,conn?conn->client_address:client_addr(),sizeof(crec.addr)-1);
- dbuf.dptr = (uint8 *)&crec;
+ dbuf.dptr = (char *)&crec;
dbuf.dsize = sizeof(crec);
- status = rec->store(rec, dbuf, TDB_REPLACE);
-
- TALLOC_FREE(rec);
-
- if (!NT_STATUS_IS_OK(status)) {
+ if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
DEBUG(0,("claim_connection: tdb_store failed with error %s.\n",
- nt_errstr(status)));
+ tdb_errorstr(tdb) ));
return False;
}
@@ -199,44 +214,43 @@ BOOL claim_connection(connection_struct *conn, const char *name,
BOOL register_message_flags(BOOL doreg, uint32 msg_flags)
{
- struct db_record *rec;
+ struct connections_key key;
struct connections_data *pcrec;
- NTSTATUS status;
+ TDB_DATA kbuf, dbuf;
+
+ if (!tdb)
+ return False;
DEBUG(10,("register_message_flags: %s flags 0x%x\n",
doreg ? "adding" : "removing",
(unsigned int)msg_flags ));
- if (!(rec = connections_fetch_entry(NULL, NULL, NULL))) {
- DEBUG(0, ("connections_fetch_entry failed\n"));
- return False;
- }
+ make_conn_key(NULL, "", &kbuf, &key);
- if (rec->value.dsize != sizeof(struct connections_data)) {
- DEBUG(0,("register_message_flags: Got wrong record size\n"));
- TALLOC_FREE(rec);
+ dbuf = tdb_fetch(tdb, kbuf);
+ if (!dbuf.dptr) {
+ DEBUG(0,("register_message_flags: tdb_fetch failed: %s\n",
+ tdb_errorstr(tdb)));
return False;
}
- pcrec = (struct connections_data *)rec->value.dptr;
+ pcrec = (struct connections_data *)dbuf.dptr;
if (doreg)
pcrec->bcast_msg_flags |= msg_flags;
else
pcrec->bcast_msg_flags &= ~msg_flags;
- status = rec->store(rec, rec->value, TDB_REPLACE);
-
- TALLOC_FREE(rec);
-
- if (!NT_STATUS_IS_OK(status)) {
+ if (tdb_store(tdb, kbuf, dbuf, TDB_REPLACE) != 0) {
DEBUG(0,("register_message_flags: tdb_store failed: %s.\n",
- nt_errstr(status)));
+ tdb_errorstr(tdb) ));
+ SAFE_FREE(dbuf.dptr);
return False;
}
DEBUG(10,("register_message_flags: new flags 0x%x\n",
(unsigned int)pcrec->bcast_msg_flags ));
+ SAFE_FREE(dbuf.dptr);
return True;
}
@@ -258,10 +272,11 @@ static TDB_DATA* make_pipe_rec_key( struct pipe_open_rec *prec )
snprintf( key_string, sizeof(key_string), "%s/%d/%d",
prec->name, procid_to_pid(&prec->pid), prec->pnum );
- *kbuf = string_term_tdb_data(talloc_strdup(prec, key_string));
- if (kbuf->dptr == NULL )
+ if ( (kbuf->dptr = talloc_strdup(prec, key_string)) == NULL )
return NULL;
-
+
+ kbuf->dsize = strlen(key_string)+1;
+
return kbuf;
}
@@ -283,10 +298,10 @@ static void fill_pipe_open_rec( struct pipe_open_rec *prec, smb_np_struct *p )
BOOL store_pipe_opendb( smb_np_struct *p )
{
- struct db_record *dbrec;
struct pipe_open_rec *prec;
TDB_DATA *key;
TDB_DATA data;
+ TDB_CONTEXT *pipe_tdb;
BOOL ret = False;
if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) {
@@ -299,15 +314,14 @@ BOOL store_pipe_opendb( smb_np_struct *p )
goto done;
}
- data.dptr = (uint8 *)prec;
+ data.dptr = (char*)prec;
data.dsize = sizeof(struct pipe_open_rec);
-
- if (!(dbrec = connections_fetch_record(prec, *key))) {
- DEBUG(0, ("connections_fetch_record failed\n"));
+
+ if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) {
goto done;
}
-
- ret = NT_STATUS_IS_OK(dbrec->store(dbrec, data, TDB_REPLACE));
+
+ ret = (tdb_store( pipe_tdb, *key, data, TDB_REPLACE ) != -1);
done:
TALLOC_FREE( prec );
@@ -319,9 +333,9 @@ done:
BOOL delete_pipe_opendb( smb_np_struct *p )
{
- struct db_record *dbrec;
struct pipe_open_rec *prec;
TDB_DATA *key;
+ TDB_CONTEXT *pipe_tdb;
BOOL ret = False;
if ( (prec = TALLOC_P( NULL, struct pipe_open_rec)) == NULL ) {
@@ -334,12 +348,11 @@ BOOL delete_pipe_opendb( smb_np_struct *p )
goto done;
}
- if (!(dbrec = connections_fetch_record(prec, *key))) {
- DEBUG(0, ("connections_fetch_record failed\n"));
+ if ( (pipe_tdb = conn_tdb_ctx() ) == NULL ) {
goto done;
}
- ret = NT_STATUS_IS_OK(dbrec->delete_rec(dbrec));
+ ret = (tdb_delete( pipe_tdb, *key ) != -1 );
done:
TALLOC_FREE( prec );
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index e7baf2b759c..57ed1df6ac3 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -33,8 +33,6 @@ extern struct current_user current_user;
/* Make directory handle internals available. */
-#define NAME_CACHE_SIZE 100
-
struct name_cache_entry {
char *name;
long offset;
@@ -45,6 +43,7 @@ struct smb_Dir {
SMB_STRUCT_DIR *dir;
long offset;
char *dir_path;
+ size_t name_cache_size;
struct name_cache_entry *name_cache;
unsigned int name_cache_index;
unsigned int file_number;
@@ -879,7 +878,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S
/* Pseudo-open the file (note - no fd's created). */
if(S_ISDIR(pst->st_mode)) {
- status = open_directory(conn, NULL, name, pst,
+ status = open_directory(conn, name, pst,
READ_CONTROL_ACCESS,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
@@ -887,7 +886,7 @@ static BOOL user_can_read_file(connection_struct *conn, char *name, SMB_STRUCT_S
FILE_ATTRIBUTE_DIRECTORY,
NULL, &fsp);
} else {
- status = open_file_stat(conn, NULL, name, pst, &fsp);
+ status = open_file_stat(conn, name, pst, &fsp);
}
if (!NT_STATUS_IS_OK(status)) {
@@ -943,7 +942,7 @@ static BOOL user_can_write_file(connection_struct *conn, char *name, SMB_STRUCT_
if(S_ISDIR(pst->st_mode)) {
return True;
} else {
- status = open_file_ntcreate(conn, NULL, name, pst,
+ status = open_file_ntcreate(conn, name, pst,
FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
@@ -1062,12 +1061,14 @@ BOOL is_visible_file(connection_struct *conn, const char *dir_path, const char *
struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *mask, uint32 attr)
{
struct smb_Dir *dirp = SMB_MALLOC_P(struct smb_Dir);
+
if (!dirp) {
return NULL;
}
ZERO_STRUCTP(dirp);
dirp->conn = conn;
+ dirp->name_cache_size = lp_directory_name_cache_size(SNUM(conn));
dirp->dir_path = SMB_STRDUP(name);
if (!dirp->dir_path) {
@@ -1079,9 +1080,14 @@ struct smb_Dir *OpenDir(connection_struct *conn, const char *name, const char *m
goto fail;
}
- dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry, NAME_CACHE_SIZE);
- if (!dirp->name_cache) {
- goto fail;
+ if (dirp->name_cache_size) {
+ dirp->name_cache = SMB_CALLOC_ARRAY(struct name_cache_entry,
+ dirp->name_cache_size);
+ if (!dirp->name_cache) {
+ goto fail;
+ }
+ } else {
+ dirp->name_cache = NULL;
}
dirhandles_open++;
@@ -1114,7 +1120,7 @@ int CloseDir(struct smb_Dir *dirp)
}
SAFE_FREE(dirp->dir_path);
if (dirp->name_cache) {
- for (i = 0; i < NAME_CACHE_SIZE; i++) {
+ for (i = 0; i < dirp->name_cache_size; i++) {
SAFE_FREE(dirp->name_cache[i].name);
}
}
@@ -1230,7 +1236,12 @@ void DirCacheAdd(struct smb_Dir *dirp, const char *name, long offset)
{
struct name_cache_entry *e;
- dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE;
+ if (!dirp->name_cache_size || !dirp->name_cache) {
+ return;
+ }
+
+ dirp->name_cache_index = (dirp->name_cache_index+1) %
+ dirp->name_cache_size;
e = &dirp->name_cache[dirp->name_cache_index];
SAFE_FREE(e->name);
e->name = SMB_STRDUP(name);
@@ -1249,20 +1260,22 @@ BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset)
connection_struct *conn = dirp->conn;
/* Search back in the name cache. */
- for (i = dirp->name_cache_index; i >= 0; i--) {
- struct name_cache_entry *e = &dirp->name_cache[i];
- if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
- *poffset = e->offset;
- SeekDir(dirp, e->offset);
- return True;
+ if (dirp->name_cache_size && dirp->name_cache) {
+ for (i = dirp->name_cache_index; i >= 0; i--) {
+ struct name_cache_entry *e = &dirp->name_cache[i];
+ if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
+ *poffset = e->offset;
+ SeekDir(dirp, e->offset);
+ return True;
+ }
}
- }
- for (i = NAME_CACHE_SIZE-1; i > dirp->name_cache_index; i--) {
- struct name_cache_entry *e = &dirp->name_cache[i];
- if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
- *poffset = e->offset;
- SeekDir(dirp, e->offset);
- return True;
+ for (i = dirp->name_cache_size - 1; i > dirp->name_cache_index; i--) {
+ struct name_cache_entry *e = &dirp->name_cache[i];
+ if (e->name && (conn->case_sensitive ? (strcmp(e->name, name) == 0) : strequal(e->name, name))) {
+ *poffset = e->offset;
+ SeekDir(dirp, e->offset);
+ return True;
+ }
}
}
diff --git a/source/smbd/dmapi.c b/source/smbd/dmapi.c
index c433a7329eb..b8c23c2dce6 100644
--- a/source/smbd/dmapi.c
+++ b/source/smbd/dmapi.c
@@ -152,9 +152,7 @@ retry:
/* No session already defined. */
if (dmapi_session == DM_NO_SESSION) {
- err = dm_create_session(DM_NO_SESSION,
- CONST_DISCARD(char *,
- DMAPI_SESSION_NAME),
+ err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME,
&dmapi_session);
if (err < 0) {
DEBUGADD(DMAPI_TRACE,
diff --git a/source/smbd/error.c b/source/smbd/error.c
index dc35c0fa648..fa344e372e5 100644
--- a/source/smbd/error.c
+++ b/source/smbd/error.c
@@ -29,7 +29,7 @@ extern uint32 global_client_caps;
Create an error packet from a cached error.
****************************************************************************/
-int cached_error_packet(const char *inbuf,char *outbuf,files_struct *fsp,int line,const char *file)
+int cached_error_packet(char *outbuf,files_struct *fsp,int line,const char *file)
{
write_bmpx_struct *wbmpx = fsp->wbmpx_ptr;
int32 eclass = wbmpx->wr_errclass;
@@ -38,14 +38,14 @@ int cached_error_packet(const char *inbuf,char *outbuf,files_struct *fsp,int lin
/* We can now delete the auxiliary struct */
SAFE_FREE(fsp->wbmpx_ptr);
- return error_packet(inbuf,outbuf,eclass,err,ntstatus,line,file);
+ return error_packet(outbuf,eclass,err,ntstatus,line,file);
}
/****************************************************************************
Create an error packet from errno.
****************************************************************************/
-int unix_error_packet(const char *inbuf,char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file)
+int unix_error_packet(char *outbuf,int def_class,uint32 def_code, NTSTATUS def_status, int line, const char *file)
{
int eclass=def_class;
int ecode=def_code;
@@ -66,7 +66,7 @@ int unix_error_packet(const char *inbuf,char *outbuf,int def_class,uint32 def_co
}
}
- return error_packet(inbuf,outbuf,eclass,ecode,ntstatus,line,file);
+ return error_packet(outbuf,eclass,ecode,ntstatus,line,file);
}
BOOL use_nt_status(void)
@@ -126,9 +126,28 @@ void error_packet_set(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatu
}
}
-int error_packet(const char *inbuf, char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
+int error_packet(char *outbuf, uint8 eclass, uint32 ecode, NTSTATUS ntstatus, int line, const char *file)
{
- int outsize = set_message(inbuf,outbuf,0,0,True);
+ int outsize = set_message(outbuf,0,0,True);
error_packet_set(outbuf, eclass, ecode, ntstatus, line, file);
return outsize;
}
+
+/*******************************************************************************
+ Special error map processing needed for returning DOS errors on open calls.
+*******************************************************************************/
+
+int error_open(char *outbuf, NTSTATUS status, int line, const char *file)
+{
+ if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
+ /*
+ * We hit an existing file, and if we're returning DOS
+ * error codes OBJECT_NAME_COLLISION would map to
+ * ERRDOS/183, we need to return ERRDOS/80, see bug
+ * 4852.
+ */
+ return error_packet(outbuf, ERRDOS, ERRfilexists,
+ NT_STATUS_OBJECT_NAME_COLLISION, line, file);
+ }
+ return error_packet(outbuf,0,0,status,line,file);
+}
diff --git a/source/smbd/fileio.c b/source/smbd/fileio.c
index 946d57da7e5..a5f8242d06e 100644
--- a/source/smbd/fileio.c
+++ b/source/smbd/fileio.c
@@ -509,15 +509,20 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n",
write_path = 3;
- } else if ( (pos >= wcp->file_size) &&
+ } else if ( (pos >= wcp->file_size) &&
(n == 1) &&
- (pos < wcp->offset + 2*wcp->alloc_size) &&
- (wcp->file_size == wcp->offset + wcp->data_size)) {
+ (wcp->file_size == wcp->offset + wcp->data_size) &&
+ (pos < wcp->file_size + wcp->alloc_size)) {
/*
- +---------------+
- | Cached data |
- +---------------+
+
+ End of file ---->|
+
+ +---------------+---------------+
+ | Cached data | Cache buffer |
+ +---------------+---------------+
+
+ |<------- allocated size ---------------->|
+--------+
| 1 Byte |
@@ -525,13 +530,18 @@ nonop=%u allocated=%u active=%u direct=%u perfect=%u readhits=%u\n",
MS-Office seems to do this a lot to determine if there's enough
space on the filesystem to write a new file.
- */
- SMB_BIG_UINT new_start = wcp->offset + wcp->data_size;
+ Change to :
+
+ End of file ---->|
+ +-----------------------+--------+
+ | Zeroed Cached data | 1 Byte |
+ +-----------------------+--------+
+ */
flush_write_cache(fsp, WRITE_FLUSH);
- wcp->offset = new_start;
- wcp->data_size = pos - new_start + 1;
+ wcp->offset = wcp->file_size;
+ wcp->data_size = pos - wcp->file_size + 1;
memset(wcp->data, '\0', wcp->data_size);
memcpy(wcp->data + wcp->data_size-1, data, 1);
@@ -780,11 +790,9 @@ void set_filelen_write_cache(files_struct *fsp, SMB_OFF_T file_size)
if(fsp->wcp) {
/* The cache *must* have been flushed before we do this. */
if (fsp->wcp->data_size != 0) {
- char *msg;
- asprintf(&msg, "set_filelen_write_cache: size change "
- "on file %s with write cache size = %lu\n",
- fsp->fsp_name,
- (unsigned long)fsp->wcp->data_size);
+ pstring msg;
+ slprintf(msg, sizeof(msg)-1, "set_filelen_write_cache: size change \
+on file %s with write cache size = %lu\n", fsp->fsp_name, (unsigned long)fsp->wcp->data_size );
smb_panic(msg);
}
fsp->wcp->file_size = file_size;
diff --git a/source/smbd/filename.c b/source/smbd/filename.c
index de15d923b89..570297bf69f 100644
--- a/source/smbd/filename.c
+++ b/source/smbd/filename.c
@@ -392,20 +392,25 @@ NTSTATUS unix_convert(connection_struct *conn,
* these two errors.
*/
- /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND
- in the filename walk. */
+ /* ENOENT, ENOTDIR and ELOOP all map to
+ * NT_STATUS_OBJECT_PATH_NOT_FOUND
+ * in the filename walk. */
- if (errno == ENOENT || errno == ENOTDIR) {
+ if (errno == ENOENT ||
+ errno == ENOTDIR ||
+ errno == ELOOP) {
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
return map_nt_error_from_unix(errno);
}
-
+
/* ENOENT is the only valid error here. */
if (errno != ENOENT) {
- /* ENOENT and ENOTDIR both map to NT_STATUS_OBJECT_PATH_NOT_FOUND
- in the filename walk. */
- if (errno == ENOTDIR) {
+ /* ENOTDIR and ELOOP both map to
+ * NT_STATUS_OBJECT_PATH_NOT_FOUND
+ * in the filename walk. */
+ if (errno == ENOTDIR ||
+ errno == ELOOP) {
return NT_STATUS_OBJECT_PATH_NOT_FOUND;
}
return map_nt_error_from_unix(errno);
@@ -463,7 +468,7 @@ NTSTATUS unix_convert(connection_struct *conn,
} /* end else */
#ifdef DEVELOPER
- if (VALID_STAT(st) && get_delete_on_close_flag(file_id_sbuf(&st))) {
+ if (VALID_STAT(st) && get_delete_on_close_flag(st.st_dev, st.st_ino)) {
return NT_STATUS_DELETE_PENDING;
}
#endif
@@ -512,7 +517,7 @@ NTSTATUS unix_convert(connection_struct *conn,
}
/****************************************************************************
- Check a filename - possibly calling check_reduced_name.
+ Check a filename - possibly caling reducename.
This is called by every routine before it allows an operation on a filename.
It does any final confirmation necessary to ensure that the filename is
a valid one for the user to access.
@@ -529,7 +534,7 @@ NTSTATUS check_name(connection_struct *conn, const pstring name)
}
if (!lp_widelinks(SNUM(conn)) || !lp_symlinks(SNUM(conn))) {
- NTSTATUS status = check_reduced_name(conn,name);
+ NTSTATUS status = reduce_name(conn,name);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("check_name: name %s failed with %s\n",name, nt_errstr(status)));
return status;
diff --git a/source/smbd/files.c b/source/smbd/files.c
index 9994b50d15a..9f3f72a4000 100644
--- a/source/smbd/files.c
+++ b/source/smbd/files.c
@@ -38,7 +38,8 @@ static int files_used;
/* A singleton cache to speed up searching by dev/inode. */
static struct fsp_singleton_cache {
files_struct *fsp;
- struct file_id id;
+ SMB_DEV_T dev;
+ SMB_INO_T inode;
} fsp_fi_cache;
/****************************************************************************
@@ -103,7 +104,7 @@ NTSTATUS file_new(connection_struct *conn, files_struct **result)
fsp->fh->fd = -1;
fsp->conn = conn;
- fsp->fh->gen_id = get_gen_count();
+ fsp->fh->file_id = get_gen_count();
GetTimeOfDay(&fsp->open_time);
first_file = (i+1) % real_max_open_files;
@@ -232,9 +233,9 @@ void file_dump_open_table(void)
files_struct *fsp;
for (fsp=Files;fsp;fsp=fsp->next,count++) {
- DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, gen = %lu, fileid=%s\n",
- count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->gen_id,
- file_id_static_string(&fsp->file_id)));
+ DEBUG(10,("Files[%d], fnum = %d, name %s, fd = %d, fileid = %lu, dev = %x, inode = %.0f\n",
+ count, fsp->fnum, fsp->fsp_name, fsp->fh->fd, (unsigned long)fsp->fh->file_id,
+ (unsigned int)fsp->dev, (double)fsp->inode ));
}
}
@@ -263,15 +264,16 @@ files_struct *file_find_fd(int fd)
Find a fsp given a device, inode and file_id.
****************************************************************************/
-files_struct *file_find_dif(struct file_id id, unsigned long gen_id)
+files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id)
{
int count=0;
files_struct *fsp;
for (fsp=Files;fsp;fsp=fsp->next,count++) {
/* We can have a fsp->fh->fd == -1 here as it could be a stat open. */
- if (file_id_equal(&fsp->file_id, &id) &&
- fsp->fh->gen_id == gen_id ) {
+ if (fsp->dev == dev &&
+ fsp->inode == inode &&
+ fsp->fh->file_id == file_id ) {
if (count > 10) {
DLIST_PROMOTE(Files, fsp);
}
@@ -279,12 +281,11 @@ files_struct *file_find_dif(struct file_id id, unsigned long gen_id)
if ((fsp->fh->fd == -1) &&
(fsp->oplock_type != NO_OPLOCK) &&
(fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) {
- DEBUG(0,("file_find_dif: file %s file_id = %s, gen = %u \
-oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name,
- file_id_static_string(&fsp->file_id),
- (unsigned int)fsp->fh->gen_id,
- (unsigned int)fsp->oplock_type ));
- smb_panic("file_find_dif");
+ DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \
+oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev,
+ (double)fsp->inode, (unsigned int)fsp->fh->file_id,
+ (unsigned int)fsp->oplock_type ));
+ smb_panic("file_find_dif\n");
}
return fsp;
}
@@ -315,20 +316,22 @@ files_struct *file_find_fsp(files_struct *orig_fsp)
calls.
****************************************************************************/
-files_struct *file_find_di_first(struct file_id id)
+files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
{
files_struct *fsp;
- if (file_id_equal(&fsp_fi_cache.id, &id)) {
+ if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) {
/* Positive or negative cache hit. */
return fsp_fi_cache.fsp;
}
- fsp_fi_cache.id = id;
+ fsp_fi_cache.dev = dev;
+ fsp_fi_cache.inode = inode;
for (fsp=Files;fsp;fsp=fsp->next) {
if ( fsp->fh->fd != -1 &&
- file_id_equal(&fsp->file_id, &id)) {
+ fsp->dev == dev &&
+ fsp->inode == inode ) {
/* Setup positive cache. */
fsp_fi_cache.fsp = fsp;
return fsp;
@@ -350,9 +353,9 @@ files_struct *file_find_di_next(files_struct *start_fsp)
for (fsp = start_fsp->next;fsp;fsp=fsp->next) {
if ( fsp->fh->fd != -1 &&
- file_id_equal(&fsp->file_id, &start_fsp->file_id)) {
+ fsp->dev == start_fsp->dev &&
+ fsp->inode == start_fsp->inode )
return fsp;
- }
}
return NULL;
@@ -389,7 +392,9 @@ void fsp_set_pending_modtime(files_struct *tfsp, const struct timespec mod)
}
for (fsp = Files;fsp;fsp=fsp->next) {
- if ( fsp->fh->fd != -1 && file_id_equal(&fsp->file_id, &tfsp->file_id)) {
+ if ( fsp->fh->fd != -1 &&
+ fsp->dev == tfsp->dev &&
+ fsp->inode == tfsp->inode ) {
fsp->pending_modtime = mod;
fsp->pending_modtime_owner = False;
}
@@ -540,7 +545,8 @@ NTSTATUS dup_file_fsp(files_struct *fsp,
dup_fsp->fh = fsp->fh;
dup_fsp->fh->ref_count++;
- dup_fsp->file_id = fsp->file_id;
+ dup_fsp->dev = fsp->dev;
+ dup_fsp->inode = fsp->inode;
dup_fsp->initial_allocation_size = fsp->initial_allocation_size;
dup_fsp->mode = fsp->mode;
dup_fsp->file_pid = fsp->file_pid;
@@ -563,6 +569,7 @@ NTSTATUS dup_file_fsp(files_struct *fsp,
dup_fsp->modified = fsp->modified;
dup_fsp->is_directory = fsp->is_directory;
dup_fsp->is_stat = fsp->is_stat;
+ dup_fsp->aio_write_behind = fsp->aio_write_behind;
string_set(&dup_fsp->fsp_name,fsp->fsp_name);
*result = dup_fsp;
diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c
index ce26b53e1b9..6e5ff9f0359 100644
--- a/source/smbd/ipc.c
+++ b/source/smbd/ipc.c
@@ -72,13 +72,10 @@ static void copy_trans_params_and_data(char *outbuf, int align,
Send a trans reply.
****************************************************************************/
-void send_trans_reply(const char *inbuf,
- char *outbuf,
- char *rparam,
- int rparam_len,
- char *rdata,
- int rdata_len,
- BOOL buffer_too_large)
+void send_trans_reply(char *outbuf,
+ char *rparam, int rparam_len,
+ char *rdata, int rdata_len,
+ BOOL buffer_too_large)
{
int this_ldata,this_lparam;
int tot_data_sent = 0;
@@ -100,11 +97,11 @@ void send_trans_reply(const char *inbuf,
ERROR_BOTH(STATUS_BUFFER_OVERFLOW,ERRDOS,ERRmoredata);
}
- set_message(inbuf,outbuf,10,1+align+this_ldata+this_lparam,True);
+ set_message(outbuf,10,1+align+this_ldata+this_lparam,True);
copy_trans_params_and_data(outbuf, align,
- rparam, tot_param_sent, this_lparam,
- rdata, tot_data_sent, this_ldata);
+ rparam, tot_param_sent, this_lparam,
+ rdata, tot_data_sent, this_ldata);
SSVAL(outbuf,smb_vwv0,lparam);
SSVAL(outbuf,smb_vwv1,ldata);
@@ -136,7 +133,7 @@ void send_trans_reply(const char *inbuf,
align = (this_lparam%4);
- set_message(inbuf,outbuf,10,1+this_ldata+this_lparam+align,False);
+ set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
copy_trans_params_and_data(outbuf, align,
rparam, tot_param_sent, this_lparam,
@@ -163,9 +160,7 @@ void send_trans_reply(const char *inbuf,
Start the first part of an RPC reply which began with an SMBtrans request.
****************************************************************************/
-static BOOL api_rpc_trans_reply(const char *inbuf,
- char *outbuf,
- smb_np_struct *p)
+static BOOL api_rpc_trans_reply(char *outbuf, smb_np_struct *p)
{
BOOL is_data_outstanding;
char *rdata = (char *)SMB_MALLOC(p->max_trans_reply);
@@ -182,7 +177,7 @@ static BOOL api_rpc_trans_reply(const char *inbuf,
return False;
}
- send_trans_reply(inbuf, outbuf, NULL, 0, rdata, data_len, is_data_outstanding);
+ send_trans_reply(outbuf, NULL, 0, rdata, data_len, is_data_outstanding);
SAFE_FREE(rdata);
return True;
@@ -192,11 +187,7 @@ static BOOL api_rpc_trans_reply(const char *inbuf,
WaitNamedPipeHandleState
****************************************************************************/
-static BOOL api_WNPHS(const char *inbuf,
- char *outbuf,
- smb_np_struct *p,
- char *param,
- int param_len)
+static BOOL api_WNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len)
{
uint16 priority;
@@ -208,7 +199,7 @@ static BOOL api_WNPHS(const char *inbuf,
if (wait_rpc_pipe_hnd_state(p, priority)) {
/* now send the reply */
- send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False);
+ send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
return True;
}
return False;
@@ -219,11 +210,7 @@ static BOOL api_WNPHS(const char *inbuf,
SetNamedPipeHandleState
****************************************************************************/
-static BOOL api_SNPHS(const char *inbuf,
- char *outbuf,
- smb_np_struct *p,
- char *param,
- int param_len)
+static BOOL api_SNPHS(char *outbuf, smb_np_struct *p, char *param, int param_len)
{
uint16 id;
@@ -235,7 +222,7 @@ static BOOL api_SNPHS(const char *inbuf,
if (set_rpc_pipe_hnd_state(p, id)) {
/* now send the reply */
- send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False);
+ send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
return True;
}
return False;
@@ -246,7 +233,7 @@ static BOOL api_SNPHS(const char *inbuf,
When no reply is generated, indicate unsupported.
****************************************************************************/
-static BOOL api_no_reply(const char *inbuf, char *outbuf, int max_rdata_len)
+static BOOL api_no_reply(char *outbuf, int max_rdata_len)
{
char rparam[4];
@@ -257,7 +244,7 @@ static BOOL api_no_reply(const char *inbuf, char *outbuf, int max_rdata_len)
DEBUG(3,("Unsupported API fd command\n"));
/* now send the reply */
- send_trans_reply(inbuf, outbuf, rparam, 4, NULL, 0, False);
+ send_trans_reply(outbuf, rparam, 4, NULL, 0, False);
return -1;
}
@@ -266,18 +253,9 @@ static BOOL api_no_reply(const char *inbuf, char *outbuf, int max_rdata_len)
Handle remote api calls delivered to a named pipe already opened.
****************************************************************************/
-static int api_fd_reply(connection_struct *conn,
- uint16 vuid,
- const char *inbuf,
- char *outbuf,
- uint16 *setup,
- char *data,
- char *params,
- int suwcnt,
- int tdscnt,
- int tpscnt,
- int mdrcnt,
- int mprcnt)
+static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
+ uint16 *setup,char *data,char *params,
+ int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
{
BOOL reply = False;
smb_np_struct *p = NULL;
@@ -305,7 +283,7 @@ static int api_fd_reply(connection_struct *conn,
/* Win9x does this call with a unicode pipe name, not a pnum. */
/* Just return success for now... */
DEBUG(3,("Got TRANSACT_WAITNAMEDPIPEHANDLESTATE on text pipe name\n"));
- send_trans_reply(inbuf, outbuf, NULL, 0, NULL, 0, False);
+ send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
return -1;
}
@@ -331,94 +309,51 @@ static int api_fd_reply(connection_struct *conn,
/* dce/rpc command */
reply = write_to_pipe(p, data, tdscnt);
if (reply)
- reply = api_rpc_trans_reply(inbuf, outbuf, p);
+ reply = api_rpc_trans_reply(outbuf, p);
break;
case TRANSACT_WAITNAMEDPIPEHANDLESTATE:
/* Wait Named Pipe Handle state */
- reply = api_WNPHS(inbuf, outbuf, p, params, tpscnt);
+ reply = api_WNPHS(outbuf, p, params, tpscnt);
break;
case TRANSACT_SETNAMEDPIPEHANDLESTATE:
/* Set Named Pipe Handle state */
- reply = api_SNPHS(inbuf, outbuf, p, params, tpscnt);
+ reply = api_SNPHS(outbuf, p, params, tpscnt);
break;
default:
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
if (!reply)
- return api_no_reply(inbuf, outbuf, mdrcnt);
+ return api_no_reply(outbuf, mdrcnt);
return -1;
}
/****************************************************************************
- Handle named pipe commands.
-****************************************************************************/
-
-static int named_pipe(connection_struct *conn,
- uint16 vuid,
- const char *inbuf,
- char *outbuf,
- char *name,
- uint16 *setup,
- char *data,
- char *params,
- int suwcnt,
- int tdscnt,
- int tpscnt,
- int msrcnt,
- int mdrcnt,
- int mprcnt)
+ handle named pipe commands
+ ****************************************************************************/
+static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
+ uint16 *setup,char *data,char *params,
+ int suwcnt,int tdscnt,int tpscnt,
+ int msrcnt,int mdrcnt,int mprcnt)
{
DEBUG(3,("named pipe command on <%s> name\n", name));
- if (strequal(name,"LANMAN")) {
- return api_reply(conn,
- vuid,
- inbuf,
- outbuf,
- data,
- params,
- tdscnt,
- tpscnt,
- mdrcnt,
- mprcnt);
- }
+ if (strequal(name,"LANMAN"))
+ return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
if (strequal(name,"WKSSVC") ||
strequal(name,"SRVSVC") ||
strequal(name,"WINREG") ||
strequal(name,"SAMR") ||
- strequal(name,"LSARPC")) {
+ strequal(name,"LSARPC"))
+ {
DEBUG(4,("named pipe command from Win95 (wow!)\n"));
- return api_fd_reply(conn,
- vuid,
- inbuf,
- outbuf,
- setup,
- data,
- params,
- suwcnt,
- tdscnt,
- tpscnt,
- mdrcnt,
- mprcnt);
+ return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
}
- if (strlen(name) < 1) {
- return api_fd_reply(conn,
- vuid,
- inbuf,
- outbuf,
- setup,
- data,
- params,
- suwcnt,
- tdscnt,
- tpscnt,
- mdrcnt,
- mprcnt);
- }
+ if (strlen(name) < 1)
+ return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
if (setup)
DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
@@ -427,10 +362,8 @@ static int named_pipe(connection_struct *conn,
}
static NTSTATUS handle_trans(connection_struct *conn,
- struct trans_state *state,
- const char *inbuf,
- char *outbuf,
- int *outsize)
+ struct trans_state *state,
+ char *outbuf, int *outsize)
{
char *local_machine_name;
int name_offset = 0;
@@ -469,18 +402,15 @@ static NTSTATUS handle_trans(connection_struct *conn,
name_offset++;
DEBUG(5,("calling named_pipe\n"));
- *outsize = named_pipe(conn,
- state->vuid,
- inbuf,
- outbuf,
- state->name+name_offset,
- state->setup,state->data,
- state->param,
- state->setup_count,state->total_data,
- state->total_param,
- state->max_setup_return,
- state->max_data_return,
- state->max_param_return);
+ *outsize = named_pipe(conn, state->vuid, outbuf,
+ state->name+name_offset,
+ state->setup,state->data,
+ state->param,
+ state->setup_count,state->total_data,
+ state->total_param,
+ state->max_setup_return,
+ state->max_data_return,
+ state->max_param_return);
if (*outsize == 0) {
return NT_STATUS_NOT_SUPPORTED;
@@ -496,11 +426,8 @@ static NTSTATUS handle_trans(connection_struct *conn,
Reply to a SMBtrans.
****************************************************************************/
-int reply_trans(connection_struct *conn,
- char *inbuf,
- char *outbuf,
- int size,
- int bufsize)
+int reply_trans(connection_struct *conn, char *inbuf,char *outbuf,
+ int size, int bufsize)
{
int outsize = 0;
unsigned int dsoff = SVAL(inbuf, smb_dsoff);
@@ -543,8 +470,8 @@ int reply_trans(connection_struct *conn,
state->one_way = BITSETW(inbuf+smb_vwv5,1);
memset(state->name, '\0',sizeof(state->name));
- srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), state->name,
- smb_buf(inbuf), sizeof(state->name), STR_TERMINATE);
+ srvstr_pull_buf(inbuf, state->name, smb_buf(inbuf),
+ sizeof(state->name), STR_TERMINATE);
if ((dscnt > state->total_data) || (pscnt > state->total_param))
goto bad_param;
@@ -625,7 +552,7 @@ int reply_trans(connection_struct *conn,
if ((state->received_param == state->total_param) &&
(state->received_data == state->total_data)) {
- result = handle_trans(conn, state, inbuf, outbuf, &outsize);
+ result = handle_trans(conn, state, outbuf, &outsize);
SAFE_FREE(state->data);
SAFE_FREE(state->param);
@@ -649,7 +576,7 @@ int reply_trans(connection_struct *conn,
/* We need to send an interim response then receive the rest
of the parameter/data bytes */
- outsize = set_message(inbuf,outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,True);
show_msg(outbuf);
END_PROFILE(SMBtrans);
return outsize;
@@ -760,7 +687,7 @@ int reply_transs(connection_struct *conn, char *inbuf,char *outbuf,
*/
SCVAL(outbuf,smb_com,SMBtrans);
- result = handle_trans(conn, state, inbuf, outbuf, &outsize);
+ result = handle_trans(conn, state, outbuf, &outsize);
DLIST_REMOVE(conn->pending_trans, state);
SAFE_FREE(state->data);
diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c
index 0a9a529a85f..ff2044b2eb9 100644
--- a/source/smbd/lanman.c
+++ b/source/smbd/lanman.c
@@ -1720,7 +1720,6 @@ static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
/* Ensure all the usershares are loaded. */
become_root();
- load_registry_shares();
count = load_usershare_shares();
unbecome_root();
@@ -1894,8 +1893,7 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
goto error_exit;
} else {
SAFE_FREE(command);
- message_send_all(smbd_messaging_context(),
- MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
+ message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
}
} else {
return False;
@@ -4191,7 +4189,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
char *p = skip_string(param,tpscnt,str2);
int uLevel;
struct pack_desc desc;
- struct sessionid *session_list;
+ struct sessionid *session_list = NULL;
int i, num_sessions;
if (!str1 || !str2 || !p) {
@@ -4214,11 +4212,12 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
return False;
}
- num_sessions = list_sessions(tmp_talloc_ctx(), &session_list);
+ num_sessions = list_sessions(&session_list);
if (mdrcnt > 0) {
*rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
if (!*rdata) {
+ SAFE_FREE(session_list);
return False;
}
}
@@ -4227,6 +4226,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
desc.buflen = mdrcnt;
desc.format = str2;
if (!init_package(&desc,num_sessions,0)) {
+ SAFE_FREE(session_list);
return False;
}
@@ -4247,6 +4247,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
*rparam_len = 8;
*rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
if (!*rparam) {
+ SAFE_FREE(session_list);
return False;
}
SSVALS(*rparam,0,desc.errcode);
@@ -4255,6 +4256,7 @@ static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
+ SAFE_FREE(session_list);
return True;
}
@@ -4361,19 +4363,11 @@ static const struct {
/****************************************************************************
- Handle remote api calls.
-****************************************************************************/
+ Handle remote api calls
+ ****************************************************************************/
-int api_reply(connection_struct *conn,
- uint16 vuid,
- const char *inbuf,
- char *outbuf,
- char *data,
- char *params,
- int tdscnt,
- int tpscnt,
- int mdrcnt,
- int mprcnt)
+int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
+ int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
{
int api_command;
char *rdata = NULL;
@@ -4466,13 +4460,7 @@ int api_reply(connection_struct *conn,
/* If api_Unsupported returns false we can't return anything. */
if (reply) {
- send_trans_reply(inbuf,
- outbuf,
- rparam,
- rparam_len,
- rdata,
- rdata_len,
- False);
+ send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
}
SAFE_FREE(rdata);
diff --git a/source/smbd/mangle_hash.c b/source/smbd/mangle_hash.c
index 3cc7d1e5c22..320e31ab679 100644
--- a/source/smbd/mangle_hash.c
+++ b/source/smbd/mangle_hash.c
@@ -437,7 +437,8 @@ static void cache_mangled_name( const char mangled_name[13], char *raw_name )
}
/* Allocate a new cache entry. If the allocation fails, just return. */
- data_val = string_term_tdb_data(raw_name);
+ data_val.dptr = raw_name;
+ data_val.dsize = strlen(raw_name)+1;
if (tdb_store_bystring(tdb_mangled_cache, mangled_name_key, data_val, TDB_REPLACE) != 0) {
DEBUG(0,("cache_mangled_name: Error storing entry %s -> %s\n", mangled_name_key, raw_name));
} else {
@@ -502,7 +503,7 @@ static BOOL check_cache( char *s, size_t maxlen, const struct share_params *p )
}
/* If we *did* find it, we need to copy it into the string buffer. */
- (void)safe_strcpy( s, (const char *)data_val.dptr, maxlen );
+ (void)safe_strcpy( s, data_val.dptr, maxlen );
if( saved_ext ) {
/* Replace the saved_ext as it was truncated. */
(void)safe_strcat( s, saved_ext, maxlen );
diff --git a/source/smbd/message.c b/source/smbd/message.c
index f390e539b05..fd53e60c141 100644
--- a/source/smbd/message.c
+++ b/source/smbd/message.c
@@ -131,13 +131,11 @@ int reply_sends(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return(ERROR_DOS(ERRSRV,ERRmsgoff));
}
- outsize = set_message(inbuf,outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,True);
p = smb_buf(inbuf)+1;
- p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgfrom, p,
- sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1;
- p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgto, p,
- sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1;
msg = p;
@@ -172,16 +170,14 @@ int reply_sendstrt(connection_struct *conn, char *inbuf,char *outbuf, int dum_si
return(ERROR_DOS(ERRSRV,ERRmsgoff));
}
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
memset(msgbuf,'\0',sizeof(msgbuf));
msgpos = 0;
p = smb_buf(inbuf)+1;
- p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgfrom, p,
- sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1;
- p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), msgto, p,
- sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, msgfrom, p, sizeof(msgfrom), STR_ASCII|STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, msgto, p, sizeof(msgto), STR_ASCII|STR_TERMINATE) + 1;
DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", msgfrom, msgto ) );
@@ -206,7 +202,7 @@ int reply_sendtxt(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
return(ERROR_DOS(ERRSRV,ERRmsgoff));
}
- outsize = set_message(inbuf,outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,True);
msg = smb_buf(inbuf) + 1;
@@ -237,7 +233,7 @@ int reply_sendend(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
return(ERROR_DOS(ERRSRV,ERRmsgoff));
}
- outsize = set_message(inbuf,outbuf,0,0,True);
+ outsize = set_message(outbuf,0,0,True);
DEBUG(3,("SMBsendend\n"));
diff --git a/source/smbd/msdfs.c b/source/smbd/msdfs.c
index a3de1991162..74acf3d37e3 100644
--- a/source/smbd/msdfs.c
+++ b/source/smbd/msdfs.c
@@ -144,16 +144,14 @@ static NTSTATUS parse_dfs_path(const char *pathname,
*ppath_contains_wcard = False;
- pstrcpy(pdp->reqpath, p);
-
/* Rest is reqpath. */
if (pdp->posix_path) {
- status = check_path_syntax_posix(pdp->reqpath);
+ status = check_path_syntax_posix(pdp->reqpath, p);
} else {
if (allow_wcards) {
- status = check_path_syntax_wcard(pdp->reqpath, ppath_contains_wcard);
+ status = check_path_syntax_wcard(pdp->reqpath, p, ppath_contains_wcard);
} else {
- status = check_path_syntax(pdp->reqpath);
+ status = check_path_syntax(pdp->reqpath, p);
}
}
@@ -390,7 +388,8 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,
pstrcpy(localpath, pdp->reqpath);
status = unix_convert(conn, localpath, search_flag, NULL, &sbuf);
- if (!NT_STATUS_IS_OK(status)) {
+ if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status,
+ NT_STATUS_OBJECT_PATH_NOT_FOUND)) {
return status;
}
@@ -422,6 +421,14 @@ static NTSTATUS dfs_path_lookup(connection_struct *conn,
}
/*
+ * localpath comes out of unix_convert, so it has
+ * no trailing backslash. Make sure that canon_dfspath hasn't either.
+ * Fix for bug #4860 from Jan Martin <Jan.Martin@rwedea.com>.
+ */
+
+ trim_char(canon_dfspath,0,'/');
+
+ /*
* Redirect if any component in the path is a link.
* We do this by walking backwards through the
* local path, chopping off the last component
@@ -722,7 +729,7 @@ static int setup_ver2_dfs_referral(const char *pathname,
STR_TERMINATE);
if (DEBUGLVL(10)) {
- dump_data(0, uni_requestedpath,requestedpathlen);
+ dump_data(0, (const char *) uni_requestedpath,requestedpathlen);
}
DEBUG(10,("ref count = %u\n",junction->referral_count));
@@ -822,7 +829,7 @@ static int setup_ver3_dfs_referral(const char *pathname,
reqpathlen = rpcstr_push(uni_reqpath, pathname, sizeof(pstring), STR_TERMINATE);
if (DEBUGLVL(10)) {
- dump_data(0, uni_reqpath,reqpathlen);
+ dump_data(0, (char *) uni_reqpath,reqpathlen);
}
uni_reqpathoffset1 = REFERRAL_HEADER_SIZE + VERSION3_REFERRAL_SIZE * junction->referral_count;
@@ -979,7 +986,7 @@ int setup_dfs_referral(connection_struct *orig_conn,
if (DEBUGLVL(10)) {
DEBUGADD(0,("DFS Referral pdata:\n"));
- dump_data(0,(uint8 *)*ppdata,reply_size);
+ dump_data(0,*ppdata,reply_size);
}
talloc_destroy(ctx);
@@ -1247,7 +1254,6 @@ int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max)
/* Ensure all the usershares are loaded. */
become_root();
- load_registry_shares();
sharecount = load_usershare_shares();
unbecome_root();
diff --git a/source/smbd/negprot.c b/source/smbd/negprot.c
index 3fdae1e06b8..bc7c75aab4c 100644
--- a/source/smbd/negprot.c
+++ b/source/smbd/negprot.c
@@ -43,7 +43,7 @@ static void get_challenge(char buff[8])
DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
- smb_panic("cannot make_negprot_global_auth_context!");
+ smb_panic("cannot make_negprot_global_auth_context!\n");
}
DEBUG(10, ("get challenge: getting challenge\n"));
cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
@@ -56,7 +56,7 @@ static void get_challenge(char buff[8])
static int reply_corep(char *inbuf, char *outbuf)
{
- int outsize = set_message(inbuf,outbuf,1,0,True);
+ int outsize = set_message(outbuf,1,0,True);
Protocol = PROTOCOL_CORE;
@@ -70,7 +70,7 @@ static int reply_corep(char *inbuf, char *outbuf)
static int reply_coreplus(char *inbuf, char *outbuf)
{
int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int outsize = set_message(inbuf,outbuf,13,0,True);
+ int outsize = set_message(outbuf,13,0,True);
SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
readbraw and writebraw (possibly) */
/* Reply, SMBlockread, SMBwritelock supported. */
@@ -99,7 +99,7 @@ static int reply_lanman1(char *inbuf, char *outbuf)
if (global_encrypted_passwords_negotiated)
secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
- set_message(inbuf,outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
+ set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
SSVAL(outbuf,smb_vwv1,secword);
/* Create a token value and add it to the outgoing packet. */
if (global_encrypted_passwords_negotiated) {
@@ -141,7 +141,7 @@ static int reply_lanman2(char *inbuf, char *outbuf)
if (global_encrypted_passwords_negotiated)
secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
- set_message(inbuf,outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
+ set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
SSVAL(outbuf,smb_vwv1,secword);
SIVAL(outbuf,smb_vwv6,sys_getpid());
@@ -228,10 +228,6 @@ static DATA_BLOB negprot_spnego(void)
name_to_fqdn(myname, global_myname());
strlower_m(myname);
asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
- if (host_princ_s == NULL) {
- blob = data_blob_null;
- return blob;
- }
blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
SAFE_FREE(host_princ_s);
}
@@ -325,7 +321,7 @@ static int reply_nt1(char *inbuf, char *outbuf)
}
}
- set_message(inbuf,outbuf,17,0,True);
+ set_message(outbuf,17,0,True);
SCVAL(outbuf,smb_vwv1,secword);
@@ -369,7 +365,7 @@ static int reply_nt1(char *inbuf, char *outbuf)
}
SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
- set_message_end(inbuf,outbuf, p);
+ set_message_end(outbuf, p);
return (smb_len(outbuf)+4);
}
@@ -485,7 +481,7 @@ int reply_negprot(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size,
int dum_buffsize)
{
- int outsize = set_message(inbuf,outbuf,1,0,True);
+ int outsize = set_message(outbuf,1,0,True);
int Index=0;
int choice= -1;
int protocol;
@@ -584,8 +580,7 @@ int reply_negprot(connection_struct *conn,
when the client connects to port 445. Of course there is a small
window where we are listening to messages -- jerry */
- claim_connection(
- NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
+ claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
/* Check for protocols, most desirable first */
for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
diff --git a/source/smbd/notify.c b/source/smbd/notify.c
index cbafeccd943..df9d8ad1378 100644
--- a/source/smbd/notify.c
+++ b/source/smbd/notify.c
@@ -22,15 +22,12 @@
#include "includes.h"
-/* Max size we can send to client in a notify response. */
-extern int max_send;
-
struct notify_change_request {
struct notify_change_request *prev, *next;
struct files_struct *fsp; /* backpointer for cancel by mid */
char request_buf[smb_size];
uint32 filter;
- uint32 current_bufsize;
+ uint32 max_param;
struct notify_mid_map *mid_map;
void *backend_data;
};
@@ -62,8 +59,9 @@ static BOOL notify_change_record_identical(struct notify_change *c1,
}
static BOOL notify_marshall_changes(int num_changes,
- struct notify_change *changes,
- prs_struct *ps)
+ uint32 max_offset,
+ struct notify_change *changes,
+ prs_struct *ps)
{
int i;
UNISTR uni_name;
@@ -113,6 +111,11 @@ static BOOL notify_marshall_changes(int num_changes,
prs_set_offset(ps, prs_offset(ps)-2);
SAFE_FREE(uni_name.buffer);
+
+ if (prs_offset(ps) > max_offset) {
+ /* Too much data for client. */
+ return False;
+ }
}
return True;
@@ -129,7 +132,6 @@ static BOOL notify_marshall_changes(int num_changes,
static void change_notify_reply_packet(const char *request_buf,
NTSTATUS error_code)
{
- const char *inbuf = request_buf;
char outbuf[smb_size+38];
memset(outbuf, '\0', sizeof(outbuf));
@@ -141,7 +143,7 @@ static void change_notify_reply_packet(const char *request_buf,
* Seems NT needs a transact command with an error code
* in it. This is a longer packet than a simple error.
*/
- set_message(inbuf,outbuf,18,0,False);
+ set_message(outbuf,18,0,False);
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
@@ -149,7 +151,7 @@ static void change_notify_reply_packet(const char *request_buf,
"failed.");
}
-void change_notify_reply(const char *request_buf,
+void change_notify_reply(const char *request_buf, uint32 max_param,
struct notify_change_buf *notify_buf)
{
char *outbuf = NULL;
@@ -158,19 +160,14 @@ void change_notify_reply(const char *request_buf,
if (notify_buf->num_changes == -1) {
change_notify_reply_packet(request_buf, NT_STATUS_OK);
+ notify_buf->num_changes = 0;
return;
}
- if (!prs_init(&ps, 0, NULL, False)
- || !notify_marshall_changes(notify_buf->num_changes,
- notify_buf->changes, &ps)) {
- change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
- goto done;
- }
+ prs_init(&ps, 0, NULL, MARSHALL);
- buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */;
-
- if (buflen > max_send) {
+ if (!notify_marshall_changes(notify_buf->num_changes, max_param,
+ notify_buf->changes, &ps)) {
/*
* We exceed what the client is willing to accept. Send
* nothing.
@@ -179,6 +176,8 @@ void change_notify_reply(const char *request_buf,
goto done;
}
+ buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */;
+
if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) {
change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY);
goto done;
@@ -186,7 +185,7 @@ void change_notify_reply(const char *request_buf,
construct_reply_common(request_buf, outbuf);
- if (send_nt_replies(request_buf, outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps),
+ if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps),
prs_offset(&ps), NULL, 0) == -1) {
exit_server("change_notify_reply_packet: send_smb failed.");
}
@@ -239,7 +238,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter,
return status;
}
-NTSTATUS change_notify_add_request(const char *inbuf,
+NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param,
uint32 filter, BOOL recursive,
struct files_struct *fsp)
{
@@ -256,11 +255,11 @@ NTSTATUS change_notify_add_request(const char *inbuf,
map->req = request;
memcpy(request->request_buf, inbuf, sizeof(request->request_buf));
- request->current_bufsize = 0;
+ request->max_param = max_param;
request->filter = filter;
request->fsp = fsp;
request->backend_data = NULL;
-
+
DLIST_ADD_END(fsp->notify->requests, request,
struct notify_change_request *);
@@ -293,7 +292,7 @@ static void change_notify_remove_request(struct notify_change_request *remove_re
}
if (req == NULL) {
- smb_panic("notify_req not found in fsp's requests");
+ smb_panic("notify_req not found in fsp's requests\n");
}
DLIST_REMOVE(fsp->notify->requests, req);
@@ -360,7 +359,7 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter,
static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
{
struct notify_change *change, *changes;
- char *tmp;
+ pstring name2;
if (fsp->notify == NULL) {
/*
@@ -369,6 +368,9 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
return;
}
+ pstrcpy(name2, name);
+ string_replace(name2, '/', '\\');
+
/*
* Someone has triggered a notify previously, queue the change for
* later.
@@ -399,14 +401,11 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
change = &(fsp->notify->changes[fsp->notify->num_changes]);
- if (!(tmp = talloc_strdup(changes, name))) {
+ if (!(change->name = talloc_strdup(changes, name2))) {
DEBUG(0, ("talloc_strdup failed\n"));
return;
}
- string_replace(tmp, '/', '\\');
- change->name = tmp;
-
change->action = action;
fsp->notify->num_changes += 1;
@@ -432,6 +431,7 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name)
*/
change_notify_reply(fsp->notify->requests->request_buf,
+ fsp->notify->requests->max_param,
fsp->notify);
change_notify_remove_request(fsp->notify->requests);
diff --git a/source/smbd/notify_internal.c b/source/smbd/notify_internal.c
index 20bfb74a291..d2b69c9d9e6 100644
--- a/source/smbd/notify_internal.c
+++ b/source/smbd/notify_internal.c
@@ -28,14 +28,13 @@
#include "librpc/gen_ndr/ndr_notify.h"
struct notify_context {
- struct db_context *db;
+ struct tdb_wrap *w;
struct server_id server;
struct messaging_context *messaging_ctx;
struct notify_list *list;
struct notify_array *array;
int seqnum;
struct sys_notify_context *sys_notify_ctx;
- TDB_DATA key;
};
@@ -92,10 +91,10 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
return NULL;
}
- notify->db = db_open(notify, lock_path("notify.tdb"),
+ notify->w = tdb_wrap_open(notify, lock_path("notify.tdb"),
0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
O_RDWR|O_CREAT, 0644);
- if (notify->db == NULL) {
+ if (notify->w == NULL) {
talloc_free(notify);
return NULL;
}
@@ -104,8 +103,7 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
notify->messaging_ctx = messaging_ctx;
notify->list = NULL;
notify->array = NULL;
- notify->seqnum = notify->db->get_seqnum(notify->db);
- notify->key = string_term_tdb_data(NOTIFY_KEY);
+ notify->seqnum = tdb_get_seqnum(notify->w->tdb);
talloc_set_destructor(notify, notify_destructor);
@@ -119,29 +117,37 @@ struct notify_context *notify_init(TALLOC_CTX *mem_ctx, struct server_id server,
return notify;
}
+
/*
- lock and fetch the record
+ lock the notify db
*/
-static NTSTATUS notify_fetch_locked(struct notify_context *notify, struct db_record **rec)
+static NTSTATUS notify_lock(struct notify_context *notify)
{
- *rec = notify->db->fetch_locked(notify->db, notify, notify->key);
- if (*rec == NULL) {
+ if (tdb_lock_bystring(notify->w->tdb, NOTIFY_KEY) != 0) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
return NT_STATUS_OK;
}
/*
+ unlock the notify db
+*/
+static void notify_unlock(struct notify_context *notify)
+{
+ tdb_unlock_bystring(notify->w->tdb, NOTIFY_KEY);
+}
+
+/*
load the notify array
*/
-static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec)
+static NTSTATUS notify_load(struct notify_context *notify)
{
TDB_DATA dbuf;
DATA_BLOB blob;
NTSTATUS status;
int seqnum;
- seqnum = notify->db->get_seqnum(notify->db);
+ seqnum = tdb_get_seqnum(notify->w->tdb);
if (seqnum == notify->seqnum && notify->array != NULL) {
return NT_STATUS_OK;
@@ -153,32 +159,23 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec
notify->array = TALLOC_ZERO_P(notify, struct notify_array);
NT_STATUS_HAVE_NO_MEMORY(notify->array);
- if (!rec) {
- if (notify->db->fetch(notify->db, notify, notify->key, &dbuf) != 0) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
- } else {
- dbuf = rec->value;
+ dbuf = tdb_fetch_bystring(notify->w->tdb, NOTIFY_KEY);
+ if (dbuf.dptr == NULL) {
+ return NT_STATUS_OK;
}
blob.data = (uint8 *)dbuf.dptr;
blob.length = dbuf.dsize;
- if (blob.length == 0) {
- status = NT_STATUS_OK;
- } else {
- status = ndr_pull_struct_blob(&blob, notify->array, notify->array,
- (ndr_pull_flags_fn_t)ndr_pull_notify_array);
- }
+ status = ndr_pull_struct_blob(&blob, notify->array, notify->array,
+ (ndr_pull_flags_fn_t)ndr_pull_notify_array);
if (DEBUGLEVEL >= 10) {
DEBUG(10, ("notify_load:\n"));
NDR_PRINT_DEBUG(notify_array, notify->array);
}
- if (!rec) {
- talloc_free(dbuf.dptr);
- }
+ free(dbuf.dptr);
return status;
}
@@ -196,11 +193,12 @@ static int notify_compare(const void *p1, const void *p2)
/*
save the notify array
*/
-static NTSTATUS notify_save(struct notify_context *notify, struct db_record *rec)
+static NTSTATUS notify_save(struct notify_context *notify)
{
TDB_DATA dbuf;
DATA_BLOB blob;
NTSTATUS status;
+ int ret;
TALLOC_CTX *tmp_ctx;
/* if possible, remove some depth arrays */
@@ -211,7 +209,11 @@ static NTSTATUS notify_save(struct notify_context *notify, struct db_record *rec
/* we might just be able to delete the record */
if (notify->array->num_depths == 0) {
- return rec->delete_rec(rec);
+ ret = tdb_delete_bystring(notify->w->tdb, NOTIFY_KEY);
+ if (ret != 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ return NT_STATUS_OK;
}
tmp_ctx = talloc_new(notify);
@@ -229,13 +231,16 @@ static NTSTATUS notify_save(struct notify_context *notify, struct db_record *rec
NDR_PRINT_DEBUG(notify_array, notify->array);
}
- dbuf.dptr = blob.data;
+ dbuf.dptr = (char *)blob.data;
dbuf.dsize = blob.length;
-
- status = rec->store(rec, dbuf, TDB_REPLACE);
+
+ ret = tdb_store_bystring(notify->w->tdb, NOTIFY_KEY, dbuf, TDB_REPLACE);
talloc_free(tmp_ctx);
+ if (ret != 0) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
- return status;
+ return NT_STATUS_OK;
}
@@ -288,8 +293,7 @@ static void sys_notify_callback(struct sys_notify_context *ctx,
/*
add an entry to the notify array
*/
-static NTSTATUS notify_add_array(struct notify_context *notify, struct db_record *rec,
- struct notify_entry *e,
+static NTSTATUS notify_add_array(struct notify_context *notify, struct notify_entry *e,
void *private_data, int depth)
{
int i;
@@ -337,7 +341,7 @@ static NTSTATUS notify_add_array(struct notify_context *notify, struct db_record
d->max_mask_subdir |= d->entries[i].subdir_filter;
}
- return notify_save(notify, rec);
+ return notify_save(notify);
}
/*
@@ -354,20 +358,18 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0,
struct notify_list *listel;
size_t len;
int depth;
- struct db_record *rec;
/* see if change notify is enabled at all */
if (notify == NULL) {
return NT_STATUS_NOT_IMPLEMENTED;
}
- status = notify_fetch_locked(notify, &rec);
+ status = notify_lock(notify);
NT_STATUS_NOT_OK_RETURN(status);
- status = notify_load(notify, rec);
+ status = notify_load(notify);
if (!NT_STATUS_IS_OK(status)) {
- talloc_free(rec);
- return status;
+ goto done;
}
/* cope with /. on the end of the path */
@@ -413,11 +415,11 @@ NTSTATUS notify_add(struct notify_context *notify, struct notify_entry *e0,
then we need to install it in the array used for the
intra-samba notify handling */
if (e.filter != 0 || e.subdir_filter != 0) {
- status = notify_add_array(notify, rec, &e, private_data, depth);
+ status = notify_add_array(notify, &e, private_data, depth);
}
done:
- talloc_free(rec);
+ notify_unlock(notify);
talloc_free(tmp_path);
return status;
@@ -432,7 +434,6 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private_data)
struct notify_list *listel;
int i, depth;
struct notify_depth *d;
- struct db_record *rec;
/* see if change notify is enabled at all */
if (notify == NULL) {
@@ -453,17 +454,17 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private_data)
talloc_free(listel);
- status = notify_fetch_locked(notify, &rec);
+ status = notify_lock(notify);
NT_STATUS_NOT_OK_RETURN(status);
- status = notify_load(notify, rec);
+ status = notify_load(notify);
if (!NT_STATUS_IS_OK(status)) {
- talloc_free(rec);
+ notify_unlock(notify);
return status;
}
if (depth >= notify->array->num_depths) {
- talloc_free(rec);
+ notify_unlock(notify);
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
@@ -477,7 +478,7 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private_data)
}
}
if (i == d->num_entries) {
- talloc_free(rec);
+ notify_unlock(notify);
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
@@ -487,9 +488,9 @@ NTSTATUS notify_remove(struct notify_context *notify, void *private_data)
}
d->num_entries--;
- status = notify_save(notify, rec);
+ status = notify_save(notify);
- talloc_free(rec);
+ notify_unlock(notify);
return status;
}
@@ -502,14 +503,13 @@ static NTSTATUS notify_remove_all(struct notify_context *notify,
{
NTSTATUS status;
int i, depth, del_count=0;
- struct db_record *rec;
- status = notify_fetch_locked(notify, &rec);
+ status = notify_lock(notify);
NT_STATUS_NOT_OK_RETURN(status);
- status = notify_load(notify, rec);
+ status = notify_load(notify);
if (!NT_STATUS_IS_OK(status)) {
- talloc_free(rec);
+ notify_unlock(notify);
return status;
}
@@ -531,10 +531,10 @@ static NTSTATUS notify_remove_all(struct notify_context *notify,
}
if (del_count > 0) {
- status = notify_save(notify, rec);
+ status = notify_save(notify);
}
- talloc_free(rec);
+ notify_unlock(notify);
return status;
}
@@ -594,7 +594,7 @@ void notify_trigger(struct notify_context *notify,
}
again:
- status = notify_load(notify, NULL);
+ status = notify_load(notify);
if (!NT_STATUS_IS_OK(status)) {
return;
}
@@ -677,7 +677,7 @@ void notify_trigger(struct notify_context *notify,
DEBUG(10, ("Deleting notify entries for "
"process %s because it's gone\n",
- procid_str_static(&e->server)));
+ procid_str_static(&e->server.id)));
notify_remove_all(notify, &server);
goto again;
}
diff --git a/source/smbd/nttrans.c b/source/smbd/nttrans.c
index ef5f299c43f..45563b4a4f6 100644
--- a/source/smbd/nttrans.c
+++ b/source/smbd/nttrans.c
@@ -50,7 +50,7 @@ static const char *known_nt_pipes[] = {
static char *nttrans_realloc(char **ptr, size_t size)
{
if (ptr==NULL) {
- smb_panic("nttrans_realloc() called with NULL ptr");
+ smb_panic("nttrans_realloc() called with NULL ptr\n");
}
*ptr = (char *)SMB_REALLOC(*ptr, size);
@@ -68,14 +68,8 @@ static char *nttrans_realloc(char **ptr, size_t size)
HACK ! Always assumes smb_setup field is zero.
****************************************************************************/
-int send_nt_replies(const char *inbuf,
- char *outbuf,
- int bufsize,
- NTSTATUS nt_error,
- char *params,
- int paramsize,
- char *pdata,
- int datasize)
+int send_nt_replies(char *outbuf, int bufsize, NTSTATUS nt_error,
+ char *params, int paramsize, char *pdata, int datasize)
{
int data_to_send = datasize;
int params_to_send = paramsize;
@@ -91,7 +85,7 @@ int send_nt_replies(const char *inbuf,
* transNT replies.
*/
- set_message(inbuf,outbuf,18,0,True);
+ set_message(outbuf,18,0,True);
if (NT_STATUS_V(nt_error)) {
ERROR_NT(nt_error);
@@ -155,7 +149,7 @@ int send_nt_replies(const char *inbuf,
total_sent_thistime = MIN(total_sent_thistime, useable_space);
- set_message(inbuf,outbuf, 18, total_sent_thistime, True);
+ set_message(outbuf, 18, total_sent_thistime, True);
/*
* Set total params and data to be sent.
@@ -275,49 +269,49 @@ BOOL is_ntfs_stream_name(const char *fname)
return (strchr_m(fname, ':') != NULL) ? True : False;
}
-struct case_semantics_state {
- connection_struct *conn;
- BOOL case_sensitive;
- BOOL case_preserve;
- BOOL short_case_preserve;
-};
-
/****************************************************************************
- Restore case semantics.
+ Save case statics.
****************************************************************************/
-static int restore_case_semantics(struct case_semantics_state *state)
-{
- state->conn->case_sensitive = state->case_sensitive;
- state->conn->case_preserve = state->case_preserve;
- state->conn->short_case_preserve = state->short_case_preserve;
- return 0;
-}
+
+static BOOL saved_case_sensitive;
+static BOOL saved_case_preserve;
+static BOOL saved_short_case_preserve;
/****************************************************************************
Save case semantics.
****************************************************************************/
-static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx,
- connection_struct *conn)
-{
- struct case_semantics_state *result;
- if (!(result = talloc(mem_ctx, struct case_semantics_state))) {
- DEBUG(0, ("talloc failed\n"));
- return NULL;
+static uint32 set_posix_case_semantics(connection_struct *conn, uint32 file_attributes)
+{
+ if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
+ return file_attributes;
}
- result->case_sensitive = conn->case_sensitive;
- result->case_preserve = conn->case_preserve;
- result->short_case_preserve = conn->short_case_preserve;
+ saved_case_sensitive = conn->case_sensitive;
+ saved_case_preserve = conn->case_preserve;
+ saved_short_case_preserve = conn->short_case_preserve;
/* Set to POSIX. */
conn->case_sensitive = True;
conn->case_preserve = True;
conn->short_case_preserve = True;
- talloc_set_destructor(result, restore_case_semantics);
+ return (file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
+}
- return result;
+/****************************************************************************
+ Restore case semantics.
+****************************************************************************/
+
+static void restore_case_semantics(connection_struct *conn, uint32 file_attributes)
+{
+ if(!(file_attributes & FILE_FLAG_POSIX_SEMANTICS)) {
+ return;
+ }
+
+ conn->case_sensitive = saved_case_sensitive;
+ conn->case_preserve = saved_case_preserve;
+ conn->short_case_preserve = saved_short_case_preserve;
}
/****************************************************************************
@@ -359,7 +353,7 @@ static int nt_open_pipe(char *fname, connection_struct *conn,
return(ERROR_DOS(ERRSRV,ERRnofids));
}
- /* TODO: Add pipe to db */
+ /* Add pipe to db */
if ( !store_pipe_opendb( p ) ) {
DEBUG(3,("nt_open_pipe: failed to store %s pipe open.\n", fname));
@@ -382,8 +376,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
char *p = NULL;
uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
- srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), fname, smb_buf(inbuf),
- sizeof(fname), STR_TERMINATE);
+ srvstr_pull_buf(inbuf, fname, smb_buf(inbuf), sizeof(fname), STR_TERMINATE);
if ((ret = nt_open_pipe(fname, conn, inbuf, outbuf, &pnum)) != 0) {
return ret;
@@ -399,10 +392,10 @@ static int do_ntcreate_pipe_open(connection_struct *conn,
* the wcnt to 42 ? It's definately
* what happens on the wire....
*/
- set_message(inbuf,outbuf,50,0,True);
+ set_message(outbuf,50,0,True);
SCVAL(outbuf,smb_wct,42);
} else {
- set_message(inbuf,outbuf,34,0,True);
+ set_message(outbuf,34,0,True);
}
p = outbuf + smb_vwv2;
@@ -461,7 +454,7 @@ int reply_ntcreate_and_X_quota(connection_struct *conn,
return ERROR_NT(status);
}
- set_message(inbuf,outbuf,34,0,True);
+ set_message(outbuf,34,0,True);
p = outbuf + smb_vwv2;
@@ -487,6 +480,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
uint32 flags = IVAL(inbuf,smb_ntcreate_Flags);
uint32 access_mask = IVAL(inbuf,smb_ntcreate_DesiredAccess);
uint32 file_attributes = IVAL(inbuf,smb_ntcreate_FileAttributes);
+ uint32 new_file_attributes;
uint32 share_access = IVAL(inbuf,smb_ntcreate_ShareAccess);
uint32 create_disposition = IVAL(inbuf,smb_ntcreate_CreateDisposition);
uint32 create_options = IVAL(inbuf,smb_ntcreate_CreateOptions);
@@ -505,8 +499,6 @@ int reply_ntcreate_and_X(connection_struct *conn,
struct timespec m_timespec;
BOOL extended_oplock_granted = False;
NTSTATUS status;
- struct smb_request req;
- struct case_semantics_state *case_state = NULL;
START_PROFILE(SMBntcreateX);
@@ -522,8 +514,6 @@ int reply_ntcreate_and_X(connection_struct *conn,
(unsigned int)create_options,
(unsigned int)root_dir_fid ));
- init_smb_request(&req, (uint8 *)inbuf);
-
/*
* If it's an IPC, use the pipe handler.
*/
@@ -553,7 +543,6 @@ int reply_ntcreate_and_X(connection_struct *conn,
*/
pstring rel_fname;
files_struct *dir_fsp = file_fsp(inbuf,smb_ntcreate_RootDirectoryFid);
- size_t dir_name_len;
if(!dir_fsp) {
END_PROFILE(SMBntcreateX);
@@ -562,9 +551,7 @@ int reply_ntcreate_and_X(connection_struct *conn,
if(!dir_fsp->is_directory) {
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname,
- smb_buf(inbuf), sizeof(fname), 0,
- STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
@@ -595,29 +582,28 @@ int reply_ntcreate_and_X(connection_struct *conn,
*/
pstrcpy( fname, dir_fsp->fsp_name );
- dir_name_len = strlen(fname);
- /*
- * Ensure it ends in a '\'.
- */
+ if (ISDOT(fname)) {
+ fname[0] = '\0';
+ } else {
+ size_t dir_name_len = strlen(fname);
+ /*
+ * Ensure it ends in a '\'.
+ */
- if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
- pstrcat(fname, "/");
- dir_name_len++;
+ if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
+ pstrcat(fname, "/");
+ }
}
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), rel_fname,
- smb_buf(inbuf), sizeof(rel_fname), 0,
- STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, rel_fname, smb_buf(inbuf), sizeof(rel_fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
pstrcat(fname, rel_fname);
} else {
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname,
- smb_buf(inbuf), sizeof(fname), 0,
- STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
@@ -676,21 +662,18 @@ int reply_ntcreate_and_X(connection_struct *conn,
* Check if POSIX semantics are wanted.
*/
- if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
- case_state = set_posix_case_semantics(NULL, conn);
- file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
- }
+ new_file_attributes = set_posix_case_semantics(conn, file_attributes);
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
/* All file access must go through check_name() */
status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
return ERROR_NT(status);
}
@@ -709,23 +692,12 @@ int reply_ntcreate_and_X(connection_struct *conn,
&& (access_mask & DELETE_ACCESS)) {
if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) ||
!can_delete_file_in_directory(conn, fname)) {
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
}
-#if 0
- /* We need to support SeSecurityPrivilege for this. */
- if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) &&
- !user_has_privileges(current_user.nt_user_token,
- &se_security)) {
- TALLOC_FREE(case_state);
- END_PROFILE(SMBntcreateX);
- return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD);
- }
-#endif
-
/*
* If it's a request for a directory open, deal with it separately.
*/
@@ -734,31 +706,18 @@ int reply_ntcreate_and_X(connection_struct *conn,
/* Can't open a temp directory. IFS kit test. */
if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
- TALLOC_FREE(case_state);
END_PROFILE(SMBntcreateX);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
oplock_request = 0;
- status = open_directory(conn, &req, fname, &sbuf,
+ status = open_directory(conn, fname, &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- file_attributes,
+ new_file_attributes,
&info, &fsp);
-
- TALLOC_FREE(case_state);
-
- if(!NT_STATUS_IS_OK(status)) {
- if (!use_nt_status() && NT_STATUS_EQUAL(
- status, NT_STATUS_OBJECT_NAME_COLLISION)) {
- status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
- }
- END_PROFILE(SMBntcreateX);
- return ERROR_NT(status);
- }
-
} else {
/*
@@ -778,16 +737,16 @@ int reply_ntcreate_and_X(connection_struct *conn,
* before issuing an oplock break request to
* our client. JRA. */
- status = open_file_ntcreate(conn, &req, fname, &sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- file_attributes,
+ new_file_attributes,
oplock_request,
&info, &fsp);
- if (!NT_STATUS_IS_OK(status)) {
+ if (!NT_STATUS_IS_OK(status)) {
/* We cheat here. There are two cases we
* care about. One is a directory rename,
* where the NT client will attempt to
@@ -815,43 +774,36 @@ int reply_ntcreate_and_X(connection_struct *conn,
*/
if (create_options & FILE_NON_DIRECTORY_FILE) {
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
END_PROFILE(SMBntcreateX);
return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
}
-
+
oplock_request = 0;
- status = open_directory(conn, &req, fname,
- &sbuf,
+ status = open_directory(conn, fname, &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- file_attributes,
+ new_file_attributes,
&info, &fsp);
- if(!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(case_state);
- if (!use_nt_status() && NT_STATUS_EQUAL(
- status, NT_STATUS_OBJECT_NAME_COLLISION)) {
- status = NT_STATUS_DOS(ERRDOS, ERRfilexists);
- }
- END_PROFILE(SMBntcreateX);
- return ERROR_NT(status);
- }
- } else {
- TALLOC_FREE(case_state);
- END_PROFILE(SMBntcreateX);
- if (open_was_deferred(SVAL(inbuf,smb_mid))) {
- /* We have re-scheduled this call. */
- return -1;
- }
- return ERROR_NT(status);
}
- }
+ }
+ }
+
+ restore_case_semantics(conn, file_attributes);
+
+ if(!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBntcreateX);
+
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ return -1;
+ }
+
+ return ERROR_OPEN(status);
}
-
- TALLOC_FREE(case_state);
file_len = sbuf.st_size;
fattr = dos_mode(conn,fname,&sbuf);
@@ -908,10 +860,10 @@ int reply_ntcreate_and_X(connection_struct *conn,
* the wcnt to 42 ? It's definately
* what happens on the wire....
*/
- set_message(inbuf,outbuf,50,0,True);
+ set_message(outbuf,50,0,True);
SCVAL(outbuf,smb_wct,42);
} else {
- set_message(inbuf,outbuf,34,0,True);
+ set_message(outbuf,34,0,True);
}
p = outbuf + smb_vwv2;
@@ -1021,9 +973,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
flags = IVAL(params,0);
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, params+53,
- sizeof(fname), parameter_count-53, STR_TERMINATE,
- &status);
+ srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@@ -1076,7 +1026,7 @@ static int do_nt_transact_create_pipe( connection_struct *conn, char *inbuf, cha
DEBUG(5,("do_nt_transact_create_pipe: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
return -1;
}
@@ -1090,7 +1040,7 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
prs_struct pd;
SEC_DESC *psd = NULL;
TALLOC_CTX *mem_ctx;
- NTSTATUS status;
+ BOOL ret;
if (sd_len == 0 || !lp_nt_acl_support(SNUM(fsp->conn))) {
return NT_STATUS_OK;
@@ -1140,10 +1090,16 @@ static NTSTATUS set_sd(files_struct *fsp, char *data, uint32 sd_len, uint32 secu
security_info_sent &= ~DACL_SECURITY_INFORMATION;
}
- status = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd);
+ ret = SMB_VFS_FSET_NT_ACL( fsp, fsp->fh->fd, security_info_sent, psd);
+
+ if (!ret) {
+ talloc_destroy(mem_ctx);
+ return NT_STATUS_ACCESS_DENIED;
+ }
talloc_destroy(mem_ctx);
- return status;
+
+ return NT_STATUS_OK;
}
/****************************************************************************
@@ -1201,6 +1157,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
uint32 flags;
uint32 access_mask;
uint32 file_attributes;
+ uint32 new_file_attributes;
uint32 share_access;
uint32 create_disposition;
uint32 create_options;
@@ -1215,8 +1172,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
char *pdata = NULL;
NTSTATUS status;
size_t param_len;
- struct smb_request req;
- struct case_semantics_state *case_state = NULL;
DEBUG(5,("call_nt_transact_create\n"));
@@ -1245,8 +1200,6 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- init_smb_request(&req, (uint8 *)inbuf);
-
flags = IVAL(params,0);
access_mask = IVAL(params,8);
file_attributes = IVAL(params,20);
@@ -1293,17 +1246,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
* This filename is relative to a directory fid.
*/
files_struct *dir_fsp = file_fsp(params,4);
- size_t dir_name_len;
if(!dir_fsp) {
return ERROR_DOS(ERRDOS,ERRbadfid);
}
if(!dir_fsp->is_directory) {
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname,
- params+53, sizeof(fname),
- parameter_count-53, STR_TERMINATE,
- &status);
+ srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@@ -1324,32 +1273,30 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
*/
pstrcpy( fname, dir_fsp->fsp_name );
- dir_name_len = strlen(fname);
- /*
- * Ensure it ends in a '\'.
- */
+ if (ISDOT(fname)) {
+ fname[0] = '\0';
+ } else {
+ size_t dir_name_len = strlen(fname);
+ /*
+ * Ensure it ends in a '\'.
+ */
- if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
- pstrcat(fname, "/");
- dir_name_len++;
+ if((fname[dir_name_len-1] != '\\') && (fname[dir_name_len-1] != '/')) {
+ pstrcat(fname, "/");
+ }
}
{
pstring tmpname;
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), tmpname,
- params+53, sizeof(tmpname),
- parameter_count-53, STR_TERMINATE,
- &status);
+ srvstr_get_path(inbuf, tmpname, params+53, sizeof(tmpname), parameter_count-53, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
pstrcat(fname, tmpname);
}
} else {
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, params+53,
- sizeof(fname), parameter_count-53,
- STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, params+53, sizeof(fname), parameter_count-53, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@@ -1375,15 +1322,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
/*
* Check if POSIX semantics are wanted.
*/
-
- if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
- case_state = set_posix_case_semantics(NULL, conn);
- file_attributes &= ~FILE_FLAG_POSIX_SEMANTICS;
- }
+ new_file_attributes = set_posix_case_semantics(conn, file_attributes);
+
status = resolve_dfspath(conn, SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES, fname);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(case_state);
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
}
@@ -1392,13 +1335,13 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
status = unix_convert(conn, fname, False, NULL, &sbuf);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
return ERROR_NT(status);
}
/* All file access must go through check_name() */
status = check_name(conn, fname);
if (!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
return ERROR_NT(status);
}
@@ -1416,21 +1359,11 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
&& (access_mask & DELETE_ACCESS)) {
if ((dos_mode(conn, fname, &sbuf) & FILE_ATTRIBUTE_READONLY) ||
!can_delete_file_in_directory(conn, fname)) {
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
return ERROR_NT(NT_STATUS_ACCESS_DENIED);
}
}
-#if 0
- /* We need to support SeSecurityPrivilege for this. */
- if ((access_mask & SEC_RIGHT_SYSTEM_SECURITY) &&
- !user_has_privileges(current_user.nt_user_token,
- &se_security)) {
- TALLOC_FREE(case_state);
- return ERROR_NT(NT_STATUS_PRIVILEGE_NOT_HELD);
- }
-#endif
-
if (ea_len) {
pdata = data + sd_len;
@@ -1438,7 +1371,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
ea_list = read_nttrans_ea_list(tmp_talloc_ctx(), pdata,
ea_len);
if (!ea_list ) {
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
}
@@ -1451,7 +1384,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
/* Can't open a temp directory. IFS kit test. */
if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) {
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
@@ -1462,34 +1395,29 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
*/
oplock_request = 0;
- status = open_directory(conn, &req, fname, &sbuf,
+ status = open_directory(conn, fname, &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- file_attributes,
+ new_file_attributes,
&info, &fsp);
- if(!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(case_state);
- return ERROR_NT(status);
- }
-
} else {
/*
* Ordinary file case.
*/
- status = open_file_ntcreate(conn,&req,fname,&sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- file_attributes,
+ new_file_attributes,
oplock_request,
&info, &fsp);
- if (!NT_STATUS_IS_OK(status)) {
+ if (!NT_STATUS_IS_OK(status)) {
if (NT_STATUS_EQUAL(status,
NT_STATUS_FILE_IS_A_DIRECTORY)) {
@@ -1498,39 +1426,38 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
*/
if (create_options & FILE_NON_DIRECTORY_FILE) {
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
return ERROR_FORCE_NT(NT_STATUS_FILE_IS_A_DIRECTORY);
}
-
+
oplock_request = 0;
- status = open_directory(conn, &req, fname,
- &sbuf,
+ status = open_directory(conn, fname, &sbuf,
access_mask,
share_access,
create_disposition,
create_options,
- file_attributes,
+ new_file_attributes,
&info, &fsp);
- if(!NT_STATUS_IS_OK(status)) {
- TALLOC_FREE(case_state);
- return ERROR_NT(status);
- }
- } else {
- TALLOC_FREE(case_state);
- if (open_was_deferred(SVAL(inbuf,smb_mid))) {
- /* We have re-scheduled this call. */
- return -1;
- }
- return ERROR_NT(status);
}
- }
+ }
+ }
+
+ restore_case_semantics(conn, file_attributes);
+ if(!NT_STATUS_IS_OK(status)) {
+
+ if (open_was_deferred(SVAL(inbuf,smb_mid))) {
+ /* We have re-scheduled this call. */
+ return -1;
+ }
+
+ return ERROR_OPEN(status);
}
/*
* According to the MS documentation, the only time the security
* descriptor is applied to the opened file is iff we *created* the
* file; an existing file stays the same.
- *
+ *
* Also, it seems (from observation) that you can open the file with
* any access mask but you can still write the sd. We need to override
* the granted access before we call set_sd
@@ -1548,7 +1475,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
if (!NT_STATUS_IS_OK(status)) {
talloc_destroy(ctx);
close_file(fsp,ERROR_CLOSE);
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
return ERROR_NT(status);
}
fsp->access_mask = saved_access_mask;
@@ -1558,12 +1485,12 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
status = set_ea(conn, fsp, fname, ea_list);
if (!NT_STATUS_IS_OK(status)) {
close_file(fsp,ERROR_CLOSE);
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
return ERROR_NT(status);
}
}
- TALLOC_FREE(case_state);
+ restore_case_semantics(conn, file_attributes);
file_len = sbuf.st_size;
fattr = dos_mode(conn,fname,&sbuf);
@@ -1691,7 +1618,7 @@ static int call_nt_transact_create(connection_struct *conn, char *inbuf, char *o
DEBUG(5,("call_nt_transact_create: open name = %s\n", fname));
/* Send the required number of replies */
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len, *ppdata, 0);
return -1;
}
@@ -1724,9 +1651,7 @@ int reply_ntcancel(connection_struct *conn,
Copy a file.
****************************************************************************/
-static NTSTATUS copy_internals(connection_struct *conn,
- struct smb_request *req,
- char *oldname, char *newname, uint32 attrs)
+static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *newname, uint32 attrs)
{
SMB_STRUCT_STAT sbuf1, sbuf2;
pstring last_component_oldname;
@@ -1785,14 +1710,14 @@ static NTSTATUS copy_internals(connection_struct *conn,
}
/* Ensure this is within the share. */
- status = check_reduced_name(conn, oldname);
+ status = reduce_name(conn, oldname);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
DEBUG(10,("copy_internals: doing file copy %s to %s\n", oldname, newname));
- status = open_file_ntcreate(conn, req, oldname, &sbuf1,
+ status = open_file_ntcreate(conn,oldname,&sbuf1,
FILE_READ_DATA, /* Read-only. */
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,
@@ -1805,7 +1730,7 @@ static NTSTATUS copy_internals(connection_struct *conn,
return status;
}
- status = open_file_ntcreate(conn, req, newname, &sbuf2,
+ status = open_file_ntcreate(conn,newname,&sbuf2,
FILE_WRITE_DATA, /* Read-only. */
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_CREATE,
@@ -1869,16 +1794,11 @@ int reply_ntrename(connection_struct *conn,
BOOL dest_has_wcard = False;
uint32 attrs = SVAL(inbuf,smb_vwv0);
uint16 rename_type = SVAL(inbuf,smb_vwv1);
- struct smb_request req;
START_PROFILE(SMBntrename);
- init_smb_request(&req, (uint8 *)inbuf);
-
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), oldname, p,
- sizeof(oldname), 0, STR_TERMINATE, &status,
- &src_has_wcard);
+ p += srvstr_get_path_wcard(inbuf, oldname, p, sizeof(oldname), 0, STR_TERMINATE, &status, &src_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntrename);
return ERROR_NT(status);
@@ -1896,9 +1816,7 @@ int reply_ntrename(connection_struct *conn,
}
p++;
- p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
- sizeof(newname), 0, STR_TERMINATE, &status,
- &dest_has_wcard);
+ p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBntrename);
return ERROR_NT(status);
@@ -1926,9 +1844,7 @@ int reply_ntrename(connection_struct *conn,
switch(rename_type) {
case RENAME_FLAG_RENAME:
- status = rename_internals(conn, &req, oldname, newname,
- attrs, False, src_has_wcard,
- dest_has_wcard);
+ status = rename_internals(conn, oldname, newname, attrs, False, src_has_wcard, dest_has_wcard);
break;
case RENAME_FLAG_HARD_LINK:
if (src_has_wcard || dest_has_wcard) {
@@ -1943,8 +1859,7 @@ int reply_ntrename(connection_struct *conn,
/* No wildcards. */
status = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
} else {
- status = copy_internals(conn, &req, oldname,
- newname, attrs);
+ status = copy_internals(conn, oldname, newname, attrs);
}
break;
case RENAME_FLAG_MOVE_CLUSTER_INFORMATION:
@@ -1964,7 +1879,7 @@ int reply_ntrename(connection_struct *conn,
return ERROR_NT(status);
}
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
END_PROFILE(SMBntrename);
return(outsize);
@@ -2045,7 +1960,7 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
* here.
*/
- change_notify_reply(inbuf, fsp->notify);
+ change_notify_reply(inbuf, max_param_count, fsp->notify);
/*
* change_notify_reply() above has independently sent its
@@ -2058,7 +1973,8 @@ static int call_nt_transact_notify_change(connection_struct *conn, char *inbuf,
* No changes pending, queue the request
*/
- status = change_notify_add_request(inbuf, filter, recursive, fsp);
+ status = change_notify_add_request(inbuf, max_param_count, filter,
+ recursive, fsp);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@@ -2081,9 +1997,6 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
BOOL replace_if_exists = False;
BOOL dest_has_wcard = False;
NTSTATUS status;
- struct smb_request req;
-
- init_smb_request(&req, (uint8 *)inbuf);
if(parameter_count < 5) {
return ERROR_DOS(ERRDOS,ERRbadfunc);
@@ -2092,14 +2005,13 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
fsp = file_fsp(params, 0);
replace_if_exists = (SVAL(params,2) & RENAME_REPLACE_IF_EXISTS) ? True : False;
CHECK_FSP(fsp, conn);
- srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), new_name, params+4,
- sizeof(new_name), parameter_count - 4,
- STR_TERMINATE, &status, &dest_has_wcard);
+ srvstr_get_path_wcard(inbuf, new_name, params+4, sizeof(new_name), parameter_count - 4,
+ STR_TERMINATE, &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
- status = rename_internals(conn, &req, fsp->fsp_name,
+ status = rename_internals(conn, fsp->fsp_name,
new_name, 0, replace_if_exists, False, dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
@@ -2113,7 +2025,7 @@ static int call_nt_transact_rename(connection_struct *conn, char *inbuf, char *o
/*
* Rename was successful.
*/
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
DEBUG(3,("nt transact rename from = %s, to = %s succeeded.\n",
fsp->fsp_name, new_name));
@@ -2201,7 +2113,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i
if(max_data_count < sd_size) {
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL,
+ send_nt_replies(outbuf, bufsize, NT_STATUS_BUFFER_TOO_SMALL,
params, 4, *ppdata, 0);
talloc_destroy(mem_ctx);
return -1;
@@ -2250,7 +2162,7 @@ security descriptor.\n"));
talloc_destroy(mem_ctx);
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, 4, data,
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, 4, data,
(int)sd_size);
return -1;
}
@@ -2297,7 +2209,7 @@ static int call_nt_transact_set_security_desc(connection_struct *conn, char *inb
done:
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL, 0);
return -1;
}
@@ -2343,31 +2255,19 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
so we can know if we need to pre-allocate or not */
DEBUG(10,("FSCTL_SET_SPARSE: called on FID[0x%04X](but not implemented)\n", fidnum));
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
0);
return -1;
- case FSCTL_CREATE_OR_GET_OBJECT_ID:
- {
- unsigned char objid[16];
-
- /* This should return the object-id on this file.
- * I think I'll make this be the inode+dev. JRA.
+ case FSCTL_0x000900C0:
+ /* pretend this succeeded - don't know what this really is
+ but works ok like this --metze
*/
- DEBUG(10,("FSCTL_CREATE_OR_GET_OBJECT_ID: called on FID[0x%04X]\n",fidnum));
-
- data_count = 64;
- pdata = nttrans_realloc(ppdata, data_count);
- if (pdata == NULL) {
- return ERROR_NT(NT_STATUS_NO_MEMORY);
- }
- push_file_id_16(pdata, &fsp->file_id);
- memcpy(pdata+16,create_volume_objectid(conn,objid),16);
- push_file_id_16(pdata+32, &fsp->file_id);
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0, pdata, data_count);
+ DEBUG(10,("FSCTL_0x000900C0: called on FID[0x%04X](but not implemented)\n",fidnum));
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0, NULL,
+ 0);
return -1;
- }
case FSCTL_GET_REPARSE_POINT:
/* pretend this fail - my winXP does it like this
@@ -2375,7 +2275,9 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
*/
DEBUG(10,("FSCTL_GET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
- return ERROR_NT(NT_STATUS_NOT_A_REPARSE_POINT);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT,
+ NULL, 0, NULL, 0);
+ return -1;
case FSCTL_SET_REPARSE_POINT:
/* pretend this fail - I'm assuming this because of the FSCTL_GET_REPARSE_POINT case.
@@ -2383,7 +2285,9 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
*/
DEBUG(10,("FSCTL_SET_REPARSE_POINT: called on FID[0x%04X](but not implemented)\n",fidnum));
- return ERROR_NT(NT_STATUS_NOT_A_REPARSE_POINT);
+ send_nt_replies(outbuf, bufsize, NT_STATUS_NOT_A_REPARSE_POINT,
+ NULL, 0, NULL, 0);
+ return -1;
case FSCTL_GET_SHADOW_COPY_DATA: /* don't know if this name is right...*/
{
@@ -2495,7 +2399,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
talloc_destroy(shadow_data->mem_ctx);
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0,
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0,
pdata, data_count);
return -1;
@@ -2548,7 +2452,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
*/
/* this works for now... */
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, NULL, 0,
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, NULL, 0,
NULL, 0);
return -1;
}
@@ -2815,7 +2719,7 @@ static int call_nt_transact_get_user_quota(connection_struct *conn, char *inbuf,
break;
}
- send_nt_replies(inbuf, outbuf, bufsize, nt_status, params, param_len,
+ send_nt_replies(outbuf, bufsize, nt_status, params, param_len,
pdata, data_len);
return -1;
@@ -2933,7 +2837,7 @@ static int call_nt_transact_set_user_quota(connection_struct *conn, char *inbuf,
return ERROR_DOS(ERRSRV,ERRerror);
}
- send_nt_replies(inbuf, outbuf, bufsize, NT_STATUS_OK, params, param_len,
+ send_nt_replies(outbuf, bufsize, NT_STATUS_OK, params, param_len,
pdata, data_len);
return -1;
@@ -3199,7 +3103,7 @@ int reply_nttrans(connection_struct *conn,
}
memcpy( state->setup, &inbuf[smb_nt_SetupStart], state->setup_count);
- dump_data(10, (uint8 *)state->setup, state->setup_count);
+ dump_data(10, (char *)state->setup, state->setup_count);
}
if ((state->received_data == state->total_data) &&
@@ -3217,7 +3121,7 @@ int reply_nttrans(connection_struct *conn,
/* We need to send an interim response then receive the rest
of the parameter/data bytes */
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
show_msg(outbuf);
END_PROFILE(SMBnttrans);
return outsize;
diff --git a/source/smbd/open.c b/source/smbd/open.c
index 5cb8340e0e0..0fa11a56c81 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -25,11 +25,13 @@
extern struct generic_mapping file_generic_mapping;
extern struct current_user current_user;
extern userdom_struct current_user_info;
+extern uint16 global_smbpid;
extern BOOL global_client_failed_oplock_break;
struct deferred_open_record {
BOOL delayed_for_oplocks;
- struct file_id id;
+ SMB_DEV_T dev;
+ SMB_INO_T inode;
};
/****************************************************************************
@@ -200,7 +202,6 @@ static void change_dir_owner_to_parent(connection_struct *conn,
static NTSTATUS open_file(files_struct *fsp,
connection_struct *conn,
- struct smb_request *req,
const char *parent_dir,
const char *name,
const char *path,
@@ -358,9 +359,10 @@ static NTSTATUS open_file(files_struct *fsp,
}
fsp->mode = psbuf->st_mode;
- fsp->file_id = file_id_sbuf(psbuf);
- fsp->vuid = req ? req->vuid : UID_FIELD_INVALID;
- fsp->file_pid = req ? req->smbpid : 0;
+ fsp->inode = psbuf->st_ino;
+ fsp->dev = psbuf->st_dev;
+ fsp->vuid = current_user.vuid;
+ fsp->file_pid = global_smbpid;
fsp->can_lock = True;
fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
if (!CAN_WRITE(conn)) {
@@ -374,6 +376,10 @@ static NTSTATUS open_file(files_struct *fsp,
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->is_directory = False;
fsp->is_stat = False;
+ if (conn->aio_write_behind_list &&
+ is_in_path(path, conn->aio_write_behind_list, conn->case_sensitive)) {
+ fsp->aio_write_behind = True;
+ }
string_set(&fsp->fsp_name, path);
fsp->wcp = NULL; /* Write cache pointer. */
@@ -511,7 +517,7 @@ static void validate_my_share_entries(int num,
return;
}
- fsp = file_find_dif(share_entry->id,
+ fsp = file_find_dif(share_entry->dev, share_entry->inode,
share_entry->share_file_id);
if (!fsp) {
DEBUG(0,("validate_my_share_entries: PANIC : %s\n",
@@ -644,7 +650,6 @@ static BOOL is_delete_request(files_struct *fsp) {
static BOOL delay_for_oplocks(struct share_mode_lock *lck,
files_struct *fsp,
- uint16 mid,
int pass_number,
int oplock_request)
{
@@ -729,7 +734,7 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck,
DEBUG(10, ("Sending break request to PID %s\n",
procid_str_static(&exclusive->pid)));
- exclusive->op_mid = mid;
+ exclusive->op_mid = get_current_mid();
/* Create the message. */
share_mode_entry_to_message(msg, exclusive);
@@ -741,10 +746,8 @@ static BOOL delay_for_oplocks(struct share_mode_lock *lck,
SSVAL(msg,6,exclusive->op_type | FORCE_OPLOCK_BREAK_TO_NONE);
}
- status = messaging_send_buf(smbd_messaging_context(), exclusive->pid,
- MSG_SMB_BREAK_REQUEST,
- (uint8 *)msg,
- MSG_SMB_SHARE_MODE_ENTRY_SIZE);
+ status = message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST,
+ msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3, ("Could not send oplock break message: %s\n",
nt_errstr(status)));
@@ -769,9 +772,9 @@ static BOOL request_timed_out(struct timeval request_time,
static void defer_open(struct share_mode_lock *lck,
struct timeval request_time,
struct timeval timeout,
- uint16 mid,
struct deferred_open_record *state)
{
+ uint16 mid = get_current_mid();
int i;
/* Paranoia check */
@@ -802,7 +805,7 @@ static void defer_open(struct share_mode_lock *lck,
(char *)state, sizeof(*state))) {
exit_server("push_deferred_smb_message failed");
}
- add_deferred_open(lck, mid, request_time, state->id);
+ add_deferred_open(lck, mid, request_time, state->dev, state->inode);
/*
* Push the MID of this packet on the signing queue.
@@ -870,10 +873,8 @@ static BOOL open_match_attributes(connection_struct *conn,
****************************************************************************/
static files_struct *fcb_or_dos_open(connection_struct *conn,
- const char *fname,
- struct file_id id,
- uint16 file_pid,
- uint16 vuid,
+ const char *fname, SMB_DEV_T dev,
+ SMB_INO_T inode,
uint32 access_mask,
uint32 share_access,
uint32 create_options)
@@ -884,7 +885,7 @@ static files_struct *fcb_or_dos_open(connection_struct *conn,
DEBUG(5,("fcb_or_dos_open: attempting old open semantics for "
"file %s.\n", fname ));
- for(fsp = file_find_di_first(id); fsp;
+ for(fsp = file_find_di_first(dev, inode); fsp;
fsp = file_find_di_next(fsp)) {
DEBUG(10,("fcb_or_dos_open: checking file %s, fd = %d, "
@@ -896,8 +897,8 @@ static files_struct *fcb_or_dos_open(connection_struct *conn,
(unsigned int)fsp->access_mask ));
if (fsp->fh->fd != -1 &&
- fsp->vuid == vuid &&
- fsp->file_pid == file_pid &&
+ fsp->vuid == current_user.vuid &&
+ fsp->file_pid == global_smbpid &&
(fsp->fh->private_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) &&
(fsp->access_mask & FILE_WRITE_DATA) &&
@@ -1066,9 +1067,7 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func
}
-static void schedule_defer_open(struct share_mode_lock *lck,
- struct timeval request_time,
- uint16 mid)
+static void schedule_defer_open(struct share_mode_lock *lck, struct timeval request_time)
{
struct deferred_open_record state;
@@ -1096,10 +1095,11 @@ static void schedule_defer_open(struct share_mode_lock *lck,
a 1 second delay for share mode conflicts. */
state.delayed_for_oplocks = True;
- state.id = lck->id;
+ state.dev = lck->dev;
+ state.inode = lck->ino;
if (!request_timed_out(request_time, timeout)) {
- defer_open(lck, request_time, timeout, mid, &state);
+ defer_open(lck, request_time, timeout, &state);
}
}
@@ -1108,7 +1108,6 @@ static void schedule_defer_open(struct share_mode_lock *lck,
****************************************************************************/
NTSTATUS open_file_ntcreate(connection_struct *conn,
- struct smb_request *req,
const char *fname,
SMB_STRUCT_STAT *psbuf,
uint32 access_mask, /* access bits (FILE_READ_DATA etc.) */
@@ -1127,7 +1126,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
BOOL def_acl = False;
BOOL posix_open = False;
BOOL new_file_created = False;
- struct file_id id;
+ SMB_DEV_T dev = 0;
+ SMB_INO_T inode = 0;
NTSTATUS fsp_open = NT_STATUS_ACCESS_DENIED;
files_struct *fsp = NULL;
mode_t new_unx_mode = (mode_t)0;
@@ -1135,6 +1135,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
int info;
uint32 existing_dos_attributes = 0;
struct pending_message_list *pml = NULL;
+ uint16 mid = get_current_mid();
struct timeval request_time = timeval_zero();
struct share_mode_lock *lck = NULL;
uint32 open_access_mask = access_mask;
@@ -1143,8 +1144,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
char *parent_dir;
const char *newname;
- ZERO_STRUCT(id);
-
if (conn->printer) {
/*
* Printers are handled completely differently.
@@ -1184,17 +1183,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
create_disposition, create_options, unx_mode,
oplock_request));
- if ((req == NULL) && ((oplock_request & INTERNAL_OPEN_ONLY) == 0)) {
- DEBUG(0, ("No smb request but not an internal only open!\n"));
- return NT_STATUS_INTERNAL_ERROR;
- }
-
- /*
- * Only non-internal opens can be deferred at all
- */
-
- if ((req != NULL)
- && ((pml = get_open_deferred_message(req->mid)) != NULL)) {
+ if ((pml = get_open_deferred_message(mid)) != NULL) {
struct deferred_open_record *state =
(struct deferred_open_record *)pml->private_data.data;
@@ -1205,16 +1194,16 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
request_time = pml->request_time;
/* Remove the deferred open entry under lock. */
- lck = get_share_mode_lock(NULL, state->id, NULL, NULL);
+ lck = get_share_mode_lock(NULL, state->dev, state->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0, ("could not get share mode lock\n"));
} else {
- del_deferred_open_entry(lck, req->mid);
+ del_deferred_open_entry(lck, mid);
TALLOC_FREE(lck);
}
/* Ensure we don't reprocess this message. */
- remove_deferred_open_smb_message(req->mid);
+ remove_deferred_open_smb_message(mid);
}
status = check_name(conn, fname);
@@ -1417,7 +1406,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
return status;
}
- fsp->file_id = file_id_sbuf(psbuf);
+ fsp->dev = psbuf->st_dev;
+ fsp->inode = psbuf->st_ino;
fsp->share_access = share_access;
fsp->fh->private_options = create_options;
fsp->access_mask = open_access_mask; /* We change this to the
@@ -1433,9 +1423,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
}
if (file_existed) {
- id = file_id_sbuf(psbuf);
+ dev = psbuf->st_dev;
+ inode = psbuf->st_ino;
- lck = get_share_mode_lock(NULL, id,
+ lck = get_share_mode_lock(NULL, dev, inode,
conn->connectpath,
fname);
@@ -1446,10 +1437,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
}
/* First pass - send break only on batch oplocks. */
- if ((req != NULL)
- && delay_for_oplocks(lck, fsp, req->mid, 1,
- oplock_request)) {
- schedule_defer_open(lck, request_time, req->mid);
+ if (delay_for_oplocks(lck, fsp, 1, oplock_request)) {
+ schedule_defer_open(lck, request_time);
TALLOC_FREE(lck);
file_free(fsp);
return NT_STATUS_SHARING_VIOLATION;
@@ -1466,11 +1455,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
* status again. */
/* Second pass - send break for both batch or
* exclusive oplocks. */
- if ((req != NULL)
- && delay_for_oplocks(lck, fsp, req->mid, 2,
- oplock_request)) {
- schedule_defer_open(lck, request_time,
- req->mid);
+ if (delay_for_oplocks(lck, fsp, 2, oplock_request)) {
+ schedule_defer_open(lck, request_time);
TALLOC_FREE(lck);
file_free(fsp);
return NT_STATUS_SHARING_VIOLATION;
@@ -1497,20 +1483,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) {
files_struct *fsp_dup;
- if (req == NULL) {
- DEBUG(0, ("DOS open without an SMB "
- "request!\n"));
- TALLOC_FREE(lck);
- file_free(fsp);
- return NT_STATUS_INTERNAL_ERROR;
- }
-
/* Use the client requested access mask here,
* not the one we open with. */
- fsp_dup = fcb_or_dos_open(conn, fname, id,
- req->smbpid,
- req->vuid,
- access_mask,
+ fsp_dup = fcb_or_dos_open(conn, fname, dev,
+ inode, access_mask,
share_access,
create_options);
@@ -1582,13 +1558,13 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
a 1 second delay for share mode conflicts. */
state.delayed_for_oplocks = False;
- state.id = id;
+ state.dev = dev;
+ state.inode = inode;
- if ((req != NULL)
- && !request_timed_out(request_time,
- timeout)) {
+ if (!request_timed_out(request_time,
+ timeout)) {
defer_open(lck, request_time, timeout,
- req->mid, &state);
+ &state);
}
}
@@ -1632,7 +1608,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
* open_file strips any O_TRUNC flags itself.
*/
- fsp_open = open_file(fsp, conn, req, parent_dir, newname, fname, psbuf,
+ fsp_open = open_file(fsp, conn, parent_dir, newname, fname, psbuf,
flags|flags2, unx_mode, access_mask,
open_access_mask);
@@ -1661,9 +1637,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
* Nadav Danieli <nadavd@exanet.com>. JRA.
*/
- id = fsp->file_id;
+ dev = fsp->dev;
+ inode = fsp->inode;
- lck = get_share_mode_lock(NULL, id,
+ lck = get_share_mode_lock(NULL, dev, inode,
conn->connectpath,
fname);
@@ -1676,10 +1653,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
}
/* First pass - send break only on batch oplocks. */
- if ((req != NULL)
- && delay_for_oplocks(lck, fsp, req->mid, 1,
- oplock_request)) {
- schedule_defer_open(lck, request_time, req->mid);
+ if (delay_for_oplocks(lck, fsp, 1, oplock_request)) {
+ schedule_defer_open(lck, request_time);
TALLOC_FREE(lck);
fd_close(conn, fsp);
file_free(fsp);
@@ -1695,11 +1670,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
* status again. */
/* Second pass - send break for both batch or
* exclusive oplocks. */
- if ((req != NULL)
- && delay_for_oplocks(lck, fsp, req->mid, 2,
- oplock_request)) {
- schedule_defer_open(lck, request_time,
- req->mid);
+ if (delay_for_oplocks(lck, fsp, 2, oplock_request)) {
+ schedule_defer_open(lck, request_time);
TALLOC_FREE(lck);
fd_close(conn, fsp);
file_free(fsp);
@@ -1714,7 +1686,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
file_free(fsp);
state.delayed_for_oplocks = False;
- state.id = id;
+ state.dev = dev;
+ state.inode = inode;
/* Do it all over again immediately. In the second
* round we will find that the file existed and handle
@@ -1723,10 +1696,8 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
* "goto top of this function", but don't tell
* anybody... */
- if (req != NULL) {
- defer_open(lck, request_time, timeval_zero(),
- req->mid, &state);
- }
+ defer_open(lck, request_time, timeval_zero(),
+ &state);
TALLOC_FREE(lck);
return status;
}
@@ -1900,9 +1871,7 @@ NTSTATUS open_file_ntcreate(connection_struct *conn,
/* If this is a successful open, we must remove any deferred open
* records. */
- if (req != NULL) {
- del_deferred_open_entry(lck, req->mid);
- }
+ del_deferred_open_entry(lck, mid);
TALLOC_FREE(lck);
conn->num_files_open++;
@@ -1932,8 +1901,8 @@ NTSTATUS open_file_fchmod(connection_struct *conn, const char *fname,
/* note! we must use a non-zero desired access or we don't get
a real file descriptor. Oh what a twisted web we weave. */
- status = open_file(fsp, conn, NULL, NULL, NULL, fname, psbuf, O_WRONLY,
- 0, FILE_WRITE_DATA, FILE_WRITE_DATA);
+ status = open_file(fsp, conn, NULL, NULL, fname, psbuf, O_WRONLY, 0,
+ FILE_WRITE_DATA, FILE_WRITE_DATA);
/*
* This is not a user visible file open.
@@ -1970,6 +1939,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
char *parent_dir;
const char *dirname;
NTSTATUS status;
+ BOOL posix_open = False;
if(!CAN_WRITE(conn)) {
DEBUG(5,("mkdir_internal: failing create on read-only share "
@@ -1988,6 +1958,7 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
}
if (file_attributes & FILE_FLAG_POSIX_SEMANTICS) {
+ posix_open = True;
mode = (mode_t)(file_attributes & ~FILE_FLAG_POSIX_SEMANTICS);
} else {
mode = unix_mode(conn, aDIR, name, parent_dir);
@@ -2012,6 +1983,14 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
return NT_STATUS_ACCESS_DENIED;
}
+ if (lp_store_dos_attributes(SNUM(conn))) {
+ if (!posix_open) {
+ file_set_dosmode(conn, name,
+ file_attributes | aDIR, NULL,
+ parent_dir);
+ }
+ }
+
if (lp_inherit_perms(SNUM(conn))) {
inherit_access_acl(conn, parent_dir, name, mode);
}
@@ -2045,7 +2024,6 @@ static NTSTATUS mkdir_internal(connection_struct *conn,
****************************************************************************/
NTSTATUS open_directory(connection_struct *conn,
- struct smb_request *req,
const char *fname,
SMB_STRUCT_STAT *psbuf,
uint32 access_mask,
@@ -2161,9 +2139,10 @@ NTSTATUS open_directory(connection_struct *conn,
*/
fsp->mode = psbuf->st_mode;
- fsp->file_id = file_id_sbuf(psbuf);
- fsp->vuid = req ? req->vuid : UID_FIELD_INVALID;
- fsp->file_pid = req ? req->smbpid : 0;
+ fsp->inode = psbuf->st_ino;
+ fsp->dev = psbuf->st_dev;
+ fsp->vuid = current_user.vuid;
+ fsp->file_pid = global_smbpid;
fsp->can_lock = False;
fsp->can_read = False;
fsp->can_write = False;
@@ -2182,7 +2161,7 @@ NTSTATUS open_directory(connection_struct *conn,
string_set(&fsp->fsp_name,fname);
- lck = get_share_mode_lock(NULL, fsp->file_id,
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode,
conn->connectpath,
fname);
@@ -2241,7 +2220,7 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory)
SET_STAT_INVALID(sbuf);
- status = open_directory(conn, NULL, directory, &sbuf,
+ status = open_directory(conn, directory, &sbuf,
FILE_READ_ATTRIBUTES, /* Just a stat open */
FILE_SHARE_NONE, /* Ignored for stat opens */
FILE_CREATE,
@@ -2261,9 +2240,8 @@ NTSTATUS create_directory(connection_struct *conn, const char *directory)
Open a pseudo-file (no locking checks - a 'stat' open).
****************************************************************************/
-NTSTATUS open_file_stat(connection_struct *conn, struct smb_request *req,
- const char *fname, SMB_STRUCT_STAT *psbuf,
- files_struct **result)
+NTSTATUS open_file_stat(connection_struct *conn, const char *fname,
+ SMB_STRUCT_STAT *psbuf, files_struct **result)
{
files_struct *fsp = NULL;
NTSTATUS status;
@@ -2289,9 +2267,10 @@ NTSTATUS open_file_stat(connection_struct *conn, struct smb_request *req,
*/
fsp->mode = psbuf->st_mode;
- fsp->file_id = file_id_sbuf(psbuf);
- fsp->vuid = req ? req->vuid : UID_FIELD_INVALID;
- fsp->file_pid = req ? req->smbpid : 0;
+ fsp->inode = psbuf->st_ino;
+ fsp->dev = psbuf->st_dev;
+ fsp->vuid = current_user.vuid;
+ fsp->file_pid = global_smbpid;
fsp->can_lock = False;
fsp->can_read = False;
fsp->can_write = False;
@@ -2314,37 +2293,34 @@ NTSTATUS open_file_stat(connection_struct *conn, struct smb_request *req,
smbd process.
****************************************************************************/
-void msg_file_was_renamed(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_type,
- struct server_id server_id,
- DATA_BLOB *data)
+void msg_file_was_renamed(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
files_struct *fsp;
- char *frm = (char *)data->data;
- struct file_id id;
+ char *frm = (char *)buf;
+ SMB_DEV_T dev;
+ SMB_INO_T inode;
const char *sharepath;
const char *newname;
size_t sp_len;
- if (data->data == NULL
- || data->length < MSG_FILE_RENAMED_MIN_SIZE + 2) {
- DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n",
- (int)data->length));
+ if (buf == NULL || len < MSG_FILE_RENAMED_MIN_SIZE + 2) {
+ DEBUG(0, ("msg_file_was_renamed: Got invalid msg len %d\n", (int)len));
return;
}
/* Unpack the message. */
- pull_file_id_16(frm, &id);
+ dev = DEV_T_VAL(frm,0);
+ inode = INO_T_VAL(frm,8);
sharepath = &frm[16];
newname = sharepath + strlen(sharepath) + 1;
sp_len = strlen(sharepath);
DEBUG(10,("msg_file_was_renamed: Got rename message for sharepath %s, new name %s, "
- "file_id %s\n",
- sharepath, newname, file_id_static_string(&id)));
+ "dev %x, inode %.0f\n",
+ sharepath, newname, (unsigned int)dev, (double)inode ));
- for(fsp = file_find_di_first(id); fsp; fsp = file_find_di_next(fsp)) {
+ for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
if (memcmp(fsp->conn->connectpath, sharepath, sp_len) == 0) {
DEBUG(10,("msg_file_was_renamed: renaming file fnum %d from %s -> %s\n",
fsp->fnum, fsp->fsp_name, newname ));
diff --git a/source/smbd/oplock.c b/source/smbd/oplock.c
index 39fc847d6ff..54c949254ee 100644
--- a/source/smbd/oplock.c
+++ b/source/smbd/oplock.c
@@ -62,7 +62,7 @@ BOOL oplock_message_waiting(fd_set *fds)
we're calling this in a shutting down state.
****************************************************************************/
-void process_kernel_oplocks(struct messaging_context *msg_ctx, fd_set *pfds)
+void process_kernel_oplocks(fd_set *pfds)
{
/*
* We need to check for kernel oplocks before going into the select
@@ -87,15 +87,16 @@ void process_kernel_oplocks(struct messaging_context *msg_ctx, fd_set *pfds)
}
/* Put the kernel break info into the message. */
- push_file_id_16(msg, &fsp->file_id);
- SIVAL(msg,16,fsp->fh->gen_id);
+ SDEV_T_VAL(msg,0,fsp->dev);
+ SINO_T_VAL(msg,8,fsp->inode);
+ SIVAL(msg,16,fsp->fh->file_id);
/* Don't need to be root here as we're only ever
sending to ourselves. */
- messaging_send_buf(msg_ctx, procid_self(),
- MSG_SMB_KERNEL_BREAK,
- (uint8 *)&msg, MSG_SMB_KERNEL_BREAK_SIZE);
+ message_send_pid(pid_to_procid(sys_getpid()),
+ MSG_SMB_KERNEL_BREAK,
+ &msg, MSG_SMB_KERNEL_BREAK_SIZE, True);
}
}
@@ -118,10 +119,10 @@ BOOL set_file_oplock(files_struct *fsp, int oplock_type)
exclusive_oplocks_open++;
}
- DEBUG(5,("set_file_oplock: granted oplock on file %s, %s/%lu, "
+ DEBUG(5,("set_file_oplock: granted oplock on file %s, 0x%x/%.0f/%lu, "
"tv_sec = %x, tv_usec = %x\n",
- fsp->fsp_name, file_id_static_string(&fsp->file_id),
- fsp->fh->gen_id, (int)fsp->open_time.tv_sec,
+ fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id, (int)fsp->open_time.tv_sec,
(int)fsp->open_time.tv_usec ));
return True;
@@ -179,11 +180,13 @@ static void downgrade_file_oplock(files_struct *fsp)
BOOL remove_oplock(files_struct *fsp)
{
+ SMB_DEV_T dev = fsp->dev;
+ SMB_INO_T inode = fsp->inode;
BOOL ret;
struct share_mode_lock *lck;
/* Remove the oplock flag from the sharemode. */
- lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0,("remove_oplock: failed to lock share entry for "
"file %s\n", fsp->fsp_name ));
@@ -192,8 +195,9 @@ BOOL remove_oplock(files_struct *fsp)
ret = remove_share_oplock(lck, fsp);
if (!ret) {
DEBUG(0,("remove_oplock: failed to remove share oplock for "
- "file %s fnum %d, %s\n",
- fsp->fsp_name, fsp->fnum, file_id_static_string(&fsp->file_id)));
+ "file %s fnum %d, 0x%x/%.0f\n",
+ fsp->fsp_name, fsp->fnum, (unsigned int)dev,
+ (double)inode));
}
release_file_oplock(fsp);
TALLOC_FREE(lck);
@@ -205,10 +209,12 @@ BOOL remove_oplock(files_struct *fsp)
*/
BOOL downgrade_oplock(files_struct *fsp)
{
+ SMB_DEV_T dev = fsp->dev;
+ SMB_INO_T inode = fsp->inode;
BOOL ret;
struct share_mode_lock *lck;
- lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0,("downgrade_oplock: failed to lock share entry for "
"file %s\n", fsp->fsp_name ));
@@ -217,8 +223,9 @@ BOOL downgrade_oplock(files_struct *fsp)
ret = downgrade_share_oplock(lck, fsp);
if (!ret) {
DEBUG(0,("downgrade_oplock: failed to downgrade share oplock "
- "for file %s fnum %d, file_id %s\n",
- fsp->fsp_name, fsp->fnum, file_id_static_string(&fsp->file_id)));
+ "for file %s fnum %d, dev = %x, inode = %.0f\n",
+ fsp->fsp_name, fsp->fnum, (unsigned int)dev,
+ (double)inode));
}
downgrade_file_oplock(fsp);
@@ -254,7 +261,7 @@ static char *new_break_smb_message(TALLOC_CTX *mem_ctx,
}
memset(result,'\0',smb_size);
- set_message(NULL,result,8,0,True);
+ set_message(result,8,0,True);
SCVAL(result,smb_com,SMBlockingX);
SSVAL(result,smb_tid,fsp->conn->cnum);
SSVAL(result,smb_pid,0xFFFF);
@@ -284,13 +291,13 @@ static void wait_before_sending_break(void)
Ensure that we have a valid oplock.
****************************************************************************/
-static files_struct *initial_break_processing(struct file_id id, unsigned long file_id)
+static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id)
{
files_struct *fsp = NULL;
if( DEBUGLVL( 3 ) ) {
- dbgtext( "initial_break_processing: called for %s/%u\n",
- file_id_static_string(&id), (int)file_id);
+ dbgtext( "initial_break_processing: called for 0x%x/%.0f/%u\n",
+ (unsigned int)dev, (double)inode, (int)file_id);
dbgtext( "Current oplocks_open (exclusive = %d, levelII = %d)\n",
exclusive_oplocks_open, level_II_oplocks_open );
}
@@ -301,13 +308,14 @@ static files_struct *initial_break_processing(struct file_id id, unsigned long f
* we have an oplock on it.
*/
- fsp = file_find_dif(id, file_id);
+ fsp = file_find_dif(dev, inode, file_id);
if(fsp == NULL) {
/* The file could have been closed in the meantime - return success. */
if( DEBUGLVL( 3 ) ) {
dbgtext( "initial_break_processing: cannot find open file with " );
- dbgtext( "file_id %s gen_id = %lu", file_id_static_string(&id), file_id);
+ dbgtext( "dev = 0x%x, inode = %.0f file_id = %lu", (unsigned int)dev,
+ (double)inode, file_id);
dbgtext( "allowing break to succeed.\n" );
}
return NULL;
@@ -326,8 +334,8 @@ static files_struct *initial_break_processing(struct file_id id, unsigned long f
if(fsp->oplock_type == NO_OPLOCK) {
if( DEBUGLVL( 3 ) ) {
dbgtext( "initial_break_processing: file %s ", fsp->fsp_name );
- dbgtext( "(file_id = %s gen_id = %lu) has no oplock.\n",
- file_id_static_string(&id), fsp->fh->gen_id );
+ dbgtext( "(dev = %x, inode = %.0f, file_id = %lu) has no oplock.\n",
+ (unsigned int)dev, (double)inode, fsp->fh->file_id );
dbgtext( "Allowing break to succeed regardless.\n" );
}
return NULL;
@@ -381,34 +389,34 @@ static void add_oplock_timeout_handler(files_struct *fsp)
the client for LEVEL2.
*******************************************************************/
-static void process_oplock_async_level2_break_message(struct messaging_context *msg_ctx,
- void *private_data,
- uint32_t msg_type,
- struct server_id src,
- DATA_BLOB *data)
+static void process_oplock_async_level2_break_message(int msg_type, struct process_id src,
+ void *buf, size_t len,
+ void *private_data)
{
struct share_mode_entry msg;
files_struct *fsp;
char *break_msg;
BOOL sign_state;
- if (data->data == NULL) {
+ if (buf == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
return;
}
- if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
- DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
+ if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
+ DEBUG(0, ("Got invalid msg len %d\n", (int)len));
return;
}
/* De-linearize incoming message. */
- message_to_share_mode_entry(&msg, (char *)data->data);
+ message_to_share_mode_entry(&msg, (char *)buf);
- DEBUG(10, ("Got oplock async level 2 break message from pid %d: %s/%lu\n",
- (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id));
+ DEBUG(10, ("Got oplock async level 2 break message from pid %d: 0x%x/%.0f/%lu\n",
+ (int)procid_to_pid(&src), (unsigned int)msg.dev,
+ (double)msg.inode, msg.share_file_id));
- fsp = initial_break_processing(msg.id, msg.share_file_id);
+ fsp = initial_break_processing(msg.dev, msg.inode,
+ msg.share_file_id);
if (fsp == NULL) {
/* We hit a race here. Break messages are sent, and before we
@@ -468,11 +476,9 @@ static void process_oplock_async_level2_break_message(struct messaging_context *
This handles the generic oplock break message from another smbd.
*******************************************************************/
-static void process_oplock_break_message(struct messaging_context *msg_ctx,
- void *private_data,
- uint32_t msg_type,
- struct server_id src,
- DATA_BLOB *data)
+static void process_oplock_break_message(int msg_type, struct process_id src,
+ void *buf, size_t len,
+ void *private_data)
{
struct share_mode_entry msg;
files_struct *fsp;
@@ -480,23 +486,25 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
BOOL break_to_level2 = False;
BOOL sign_state;
- if (data->data == NULL) {
+ if (buf == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
return;
}
- if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
- DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
+ if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
+ DEBUG(0, ("Got invalid msg len %d\n", (int)len));
return;
}
/* De-linearize incoming message. */
- message_to_share_mode_entry(&msg, (char *)data->data);
+ message_to_share_mode_entry(&msg, (char *)buf);
- DEBUG(10, ("Got oplock break message from pid %d: %s/%lu\n",
- (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id));
+ DEBUG(10, ("Got oplock break message from pid %d: 0x%x/%.0f/%lu\n",
+ (int)procid_to_pid(&src), (unsigned int)msg.dev,
+ (double)msg.inode, msg.share_file_id));
- fsp = initial_break_processing(msg.id, msg.share_file_id);
+ fsp = initial_break_processing(msg.dev, msg.inode,
+ msg.share_file_id);
if (fsp == NULL) {
/* a We hit race here. Break messages are sent, and before we
@@ -505,9 +513,8 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
DEBUG(3, ("Did not find fsp\n"));
/* We just send the same message back. */
- messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE,
- (uint8 *)data->data,
- MSG_SMB_SHARE_MODE_ENTRY_SIZE);
+ message_send_pid(src, MSG_SMB_BREAK_RESPONSE,
+ buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
return;
}
@@ -523,13 +530,12 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
if (EXCLUSIVE_OPLOCK_TYPE(msg.op_type) &&
!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
- DEBUG(3, ("Already downgraded oplock on %s: %s\n",
- file_id_static_string(&fsp->file_id),
+ DEBUG(3, ("Already downgraded oplock on 0x%x/%.0f: %s\n",
+ (unsigned int)fsp->dev, (double)fsp->inode,
fsp->fsp_name));
/* We just send the same message back. */
- messaging_send_buf(msg_ctx, src, MSG_SMB_BREAK_RESPONSE,
- (uint8 *)data->data,
- MSG_SMB_SHARE_MODE_ENTRY_SIZE);
+ message_send_pid(src, MSG_SMB_BREAK_RESPONSE,
+ buf, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
return;
}
@@ -579,37 +585,37 @@ static void process_oplock_break_message(struct messaging_context *msg_ctx,
This handles the kernel oplock break message.
*******************************************************************/
-static void process_kernel_oplock_break(struct messaging_context *msg_ctx,
- void *private_data,
- uint32_t msg_type,
- struct server_id src,
- DATA_BLOB *data)
+static void process_kernel_oplock_break(int msg_type, struct process_id src,
+ void *buf, size_t len,
+ void *private_data)
{
- struct file_id id;
+ SMB_DEV_T dev;
+ SMB_INO_T inode;
unsigned long file_id;
files_struct *fsp;
char *break_msg;
BOOL sign_state;
- if (data->data == NULL) {
+ if (buf == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
return;
}
- if (data->length != MSG_SMB_KERNEL_BREAK_SIZE) {
- DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
+ if (len != MSG_SMB_KERNEL_BREAK_SIZE) {
+ DEBUG(0, ("Got invalid msg len %d\n", (int)len));
return;
}
/* Pull the data from the message. */
- pull_file_id_16((char *)data->data, &id);
- file_id = (unsigned long)IVAL(data->data, 16);
+ dev = DEV_T_VAL(buf, 0);
+ inode = INO_T_VAL(buf, 8);
+ file_id = (unsigned long)IVAL(buf, 16);
- DEBUG(10, ("Got kernel oplock break message from pid %d: %s/%u\n",
- (int)procid_to_pid(&src), file_id_static_string(&id),
+ DEBUG(10, ("Got kernel oplock break message from pid %d: 0x%x/%.0f/%u\n",
+ (int)procid_to_pid(&src), (unsigned int)dev, (double)inode,
(unsigned int)file_id));
- fsp = initial_break_processing(id, file_id);
+ fsp = initial_break_processing(dev, inode, file_id);
if (fsp == NULL) {
DEBUG(3, ("Got a kernel oplock break message for a file "
@@ -657,10 +663,8 @@ void reply_to_oplock_break_requests(files_struct *fsp)
share_mode_entry_to_message(msg, e);
- messaging_send_buf(smbd_messaging_context(), e->pid,
- MSG_SMB_BREAK_RESPONSE,
- (uint8 *)msg,
- MSG_SMB_SHARE_MODE_ENTRY_SIZE);
+ message_send_pid(e->pid, MSG_SMB_BREAK_RESPONSE,
+ msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
}
SAFE_FREE(fsp->pending_break_messages);
@@ -673,59 +677,56 @@ void reply_to_oplock_break_requests(files_struct *fsp)
return;
}
-static void process_oplock_break_response(struct messaging_context *msg_ctx,
- void *private_data,
- uint32_t msg_type,
- struct server_id src,
- DATA_BLOB *data)
+static void process_oplock_break_response(int msg_type, struct process_id src,
+ void *buf, size_t len,
+ void *private_data)
{
struct share_mode_entry msg;
- if (data->data == NULL) {
+ if (buf == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
return;
}
- if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
- DEBUG(0, ("Got invalid msg len %u\n",
- (unsigned int)data->length));
+ if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
+ DEBUG(0, ("Got invalid msg len %u\n", (unsigned int)len));
return;
}
/* De-linearize incoming message. */
- message_to_share_mode_entry(&msg, (char *)data->data);
+ message_to_share_mode_entry(&msg, (char *)buf);
- DEBUG(10, ("Got oplock break response from pid %d: %s/%lu mid %u\n",
- (int)procid_to_pid(&src), file_id_static_string(&msg.id), msg.share_file_id,
+ DEBUG(10, ("Got oplock break response from pid %d: 0x%x/%.0f/%lu mid %u\n",
+ (int)procid_to_pid(&src), (unsigned int)msg.dev,
+ (double)msg.inode, msg.share_file_id,
(unsigned int)msg.op_mid));
/* Here's the hack from open.c, store the mid in the 'port' field */
schedule_deferred_open_smb_message(msg.op_mid);
}
-static void process_open_retry_message(struct messaging_context *msg_ctx,
- void *private_data,
- uint32_t msg_type,
- struct server_id src,
- DATA_BLOB *data)
+static void process_open_retry_message(int msg_type, struct process_id src,
+ void *buf, size_t len,
+ void *private_data)
{
struct share_mode_entry msg;
- if (data->data == NULL) {
+ if (buf == NULL) {
DEBUG(0, ("Got NULL buffer\n"));
return;
}
- if (data->length != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
- DEBUG(0, ("Got invalid msg len %d\n", (int)data->length));
+ if (len != MSG_SMB_SHARE_MODE_ENTRY_SIZE) {
+ DEBUG(0, ("Got invalid msg len %d\n", (int)len));
return;
}
/* De-linearize incoming message. */
- message_to_share_mode_entry(&msg, (char *)data->data);
+ message_to_share_mode_entry(&msg, (char *)buf);
- DEBUG(10, ("Got open retry msg from pid %d: %s mid %u\n",
- (int)procid_to_pid(&src), file_id_static_string(&msg.id),
+ DEBUG(10, ("Got open retry msg from pid %d: 0x%x/%.0f/%lu mid %u\n",
+ (int)procid_to_pid(&src), (unsigned int)msg.dev,
+ (double)msg.inode, msg.share_file_id,
(unsigned int)msg.op_mid));
schedule_deferred_open_smb_message(msg.op_mid);
@@ -753,7 +754,7 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type))
return;
- lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if (lck == NULL) {
DEBUG(0,("release_level_2_oplocks_on_change: failed to lock "
"share mode entry for file %s.\n", fsp->fsp_name ));
@@ -801,10 +802,8 @@ void release_level_2_oplocks_on_change(files_struct *fsp)
share_mode_entry_to_message(msg, share_entry);
- messaging_send_buf(smbd_messaging_context(), share_entry->pid,
- MSG_SMB_ASYNC_LEVEL2_BREAK,
- (uint8 *)msg,
- MSG_SMB_SHARE_MODE_ENTRY_SIZE);
+ message_send_pid(share_entry->pid, MSG_SMB_ASYNC_LEVEL2_BREAK,
+ msg, MSG_SMB_SHARE_MODE_ENTRY_SIZE, True);
}
/* We let the message receivers handle removing the oplock state
@@ -827,13 +826,11 @@ void share_mode_entry_to_message(char *msg, struct share_mode_entry *e)
SIVAL(msg,16,e->private_options);
SIVAL(msg,20,(uint32)e->time.tv_sec);
SIVAL(msg,24,(uint32)e->time.tv_usec);
- push_file_id_16(msg+28, &e->id);
+ SDEV_T_VAL(msg,28,e->dev);
+ SINO_T_VAL(msg,36,e->inode);
SIVAL(msg,44,e->share_file_id);
SIVAL(msg,48,e->uid);
SSVAL(msg,52,e->flags);
-#ifdef CLUSTER_SUPPORT
- SIVAL(msg,54,e->pid.vnn);
-#endif
}
/****************************************************************************
@@ -850,33 +847,36 @@ void message_to_share_mode_entry(struct share_mode_entry *e, char *msg)
e->private_options = IVAL(msg,16);
e->time.tv_sec = (time_t)IVAL(msg,20);
e->time.tv_usec = (int)IVAL(msg,24);
- pull_file_id_16(msg+28, &e->id);
+ e->dev = DEV_T_VAL(msg,28);
+ e->inode = INO_T_VAL(msg,36);
e->share_file_id = (unsigned long)IVAL(msg,44);
e->uid = (uint32)IVAL(msg,48);
e->flags = (uint16)SVAL(msg,52);
-#ifdef CLUSTER_SUPPORT
- e->pid.vnn = IVAL(msg,54);
-#endif
}
/****************************************************************************
Setup oplocks for this process.
****************************************************************************/
-BOOL init_oplocks(struct messaging_context *msg_ctx)
+BOOL init_oplocks(void)
{
DEBUG(3,("init_oplocks: initializing messages.\n"));
- messaging_register(msg_ctx, NULL, MSG_SMB_BREAK_REQUEST,
- process_oplock_break_message);
- messaging_register(msg_ctx, NULL, MSG_SMB_ASYNC_LEVEL2_BREAK,
- process_oplock_async_level2_break_message);
- messaging_register(msg_ctx, NULL, MSG_SMB_BREAK_RESPONSE,
- process_oplock_break_response);
- messaging_register(msg_ctx, NULL, MSG_SMB_KERNEL_BREAK,
- process_kernel_oplock_break);
- messaging_register(msg_ctx, NULL, MSG_SMB_OPEN_RETRY,
- process_open_retry_message);
+ message_register(MSG_SMB_BREAK_REQUEST,
+ process_oplock_break_message,
+ NULL);
+ message_register(MSG_SMB_ASYNC_LEVEL2_BREAK,
+ process_oplock_async_level2_break_message,
+ NULL);
+ message_register(MSG_SMB_BREAK_RESPONSE,
+ process_oplock_break_response,
+ NULL);
+ message_register(MSG_SMB_KERNEL_BREAK,
+ process_kernel_oplock_break,
+ NULL);
+ message_register(MSG_SMB_OPEN_RETRY,
+ process_open_retry_message,
+ NULL);
if (lp_kernel_oplocks()) {
#if HAVE_KERNEL_OPLOCKS_IRIX
diff --git a/source/smbd/oplock_irix.c b/source/smbd/oplock_irix.c
index eb0164ae50e..c1159cd73b4 100644
--- a/source/smbd/oplock_irix.c
+++ b/source/smbd/oplock_irix.c
@@ -140,9 +140,8 @@ static files_struct *irix_oplock_receive_message(fd_set *fds)
* is the first fsp open with this dev,ino pair.
*/
- if ((fsp = file_find_di_first(
- file_id_create((SMB_DEV_T)os.os_dev,
- (SMB_INO_T)os.os_ino))) == NULL) {
+ if ((fsp = file_find_di_first((SMB_DEV_T)os.os_dev,
+ (SMB_INO_T)os.os_ino)) == NULL) {
DEBUG(0,("irix_oplock_receive_message: unable to find open "
"file with dev = %x, inode = %.0f\n",
(unsigned int)os.os_dev, (double)os.os_ino ));
@@ -150,9 +149,9 @@ static files_struct *irix_oplock_receive_message(fd_set *fds)
}
DEBUG(5,("irix_oplock_receive_message: kernel oplock break request "
- "received for file_id %s gen_id = %ul",
- file_id_static_string(&fsp->file_id),
- fsp->fh->gen_id ));
+ "received for dev = %x, inode = %.0f\n, file_id = %ul",
+ (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id ));
return fsp;
}
@@ -166,27 +165,27 @@ static BOOL irix_set_kernel_oplock(files_struct *fsp, int oplock_type)
if (sys_fcntl_long(fsp->fh->fd, F_OPLKREG, oplock_pipe_write) == -1) {
if(errno != EAGAIN) {
DEBUG(0,("irix_set_kernel_oplock: Unable to get "
- "kernel oplock on file %s, file_id %s "
- "gen_id = %ul. Error was %s\n",
- fsp->fsp_name, file_id_static_string(&fsp->file_id),
- fsp->fh->gen_id,
+ "kernel oplock on file %s, dev = %x, inode "
+ "= %.0f, file_id = %ul. Error was %s\n",
+ fsp->fsp_name, (unsigned int)fsp->dev,
+ (double)fsp->inode, fsp->fh->file_id,
strerror(errno) ));
} else {
DEBUG(5,("irix_set_kernel_oplock: Refused oplock on "
- "file %s, fd = %d, file_id = 5s, "
- "gen_id = %ul. Another process had the file "
+ "file %s, fd = %d, dev = %x, inode = %.0f, "
+ "file_id = %ul. Another process had the file "
"open.\n",
fsp->fsp_name, fsp->fh->fd,
- file_id_static_string(&fsp->file_id),
- fsp->fh->gen_id ));
+ (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id ));
}
return False;
}
- DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, file_id = %s "
- "gen_id = %ul\n",
- fsp->fsp_name, file_id_static_string(&fsp->file_id),
- fsp->fh->gen_id));
+ DEBUG(10,("irix_set_kernel_oplock: got kernel oplock on file %s, dev "
+ "= %x, inode = %.0f, file_id = %ul\n",
+ fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id));
return True;
}
@@ -203,10 +202,10 @@ static void irix_release_kernel_oplock(files_struct *fsp)
* oplock state of this file.
*/
int state = sys_fcntl_long(fsp->fh->fd, F_OPLKACK, -1);
- dbgtext("irix_release_kernel_oplock: file %s, file_id = %s"
- "gen_id = %ul, has kernel oplock state "
- "of %x.\n", fsp->fsp_name, file_id_static_string(&fsp->file_id),
- fsp->fh->gen_id, state );
+ dbgtext("irix_release_kernel_oplock: file %s, dev = %x, "
+ "inode = %.0f file_id = %ul, has kernel oplock state "
+ "of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
+ (double)fsp->inode, fsp->fh->file_id, state );
}
/*
@@ -216,10 +215,10 @@ static void irix_release_kernel_oplock(files_struct *fsp)
if( DEBUGLVL( 0 )) {
dbgtext("irix_release_kernel_oplock: Error when "
"removing kernel oplock on file " );
- dbgtext("%s, file_id = %s gen_id = %ul. "
+ dbgtext("%s, dev = %x, inode = %.0f, file_id = %ul. "
"Error was %s\n",
- fsp->fsp_name, file_id_static_string(&fsp->file_id),
- fsp->fh->gen_id,
+ fsp->fsp_name, (unsigned int)fsp->dev,
+ (double)fsp->inode, fsp->fh->file_id,
strerror(errno) );
}
}
diff --git a/source/smbd/oplock_linux.c b/source/smbd/oplock_linux.c
index e12a9d66ca9..14db98cde6c 100644
--- a/source/smbd/oplock_linux.c
+++ b/source/smbd/oplock_linux.c
@@ -167,17 +167,17 @@ static BOOL linux_set_kernel_oplock(files_struct *fsp, int oplock_type)
{
if ( SMB_VFS_LINUX_SETLEASE(fsp,fsp->fh->fd, F_WRLCK) == -1) {
DEBUG(3,("linux_set_kernel_oplock: Refused oplock on file %s, "
- "fd = %d, file_id = %s. (%s)\n",
+ "fd = %d, dev = %x, inode = %.0f. (%s)\n",
fsp->fsp_name, fsp->fh->fd,
- file_id_static_string(&fsp->file_id),
+ (unsigned int)fsp->dev, (double)fsp->inode,
strerror(errno)));
return False;
}
DEBUG(3,("linux_set_kernel_oplock: got kernel oplock on file %s, "
- "file_id = %s gen_id = %lu\n",
- fsp->fsp_name, file_id_static_string(&fsp->file_id),
- fsp->fh->gen_id));
+ "dev = %x, inode = %.0f, file_id = %lu\n",
+ fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id));
return True;
}
@@ -194,10 +194,10 @@ static void linux_release_kernel_oplock(files_struct *fsp)
* oplock state of this file.
*/
int state = fcntl(fsp->fh->fd, F_GETLEASE, 0);
- dbgtext("linux_release_kernel_oplock: file %s, file_id = %s "
- "gen_id = %lu has kernel oplock state "
- "of %x.\n", fsp->fsp_name, file_id_static_string(&fsp->file_id),
- fsp->fh->gen_id, state );
+ dbgtext("linux_release_kernel_oplock: file %s, dev = %x, "
+ "inode = %.0f file_id = %lu has kernel oplock state "
+ "of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev,
+ (double)fsp->inode, fsp->fh->file_id, state );
}
/*
@@ -207,10 +207,10 @@ static void linux_release_kernel_oplock(files_struct *fsp)
if (DEBUGLVL(0)) {
dbgtext("linux_release_kernel_oplock: Error when "
"removing kernel oplock on file " );
- dbgtext("%s, file_id = %s, gen_id = %lu. "
+ dbgtext("%s, dev = %x, inode = %.0f, file_id = %lu. "
"Error was %s\n", fsp->fsp_name,
- file_id_static_string(&fsp->file_id),
- fsp->fh->gen_id, strerror(errno) );
+ (unsigned int)fsp->dev, (double)fsp->inode,
+ fsp->fh->file_id, strerror(errno) );
}
}
}
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 00f687dc274..bf4e9258ff2 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -92,7 +92,14 @@ void invalidate_vuid(uint16 vuid)
if (vuser == NULL)
return;
+ SAFE_FREE(vuser->homedir);
+ SAFE_FREE(vuser->unix_homedir);
+ SAFE_FREE(vuser->logon_script);
+
session_yield(vuser);
+ SAFE_FREE(vuser->session_keystr);
+
+ TALLOC_FREE(vuser->server_info);
data_blob_free(&vuser->session_key);
@@ -102,7 +109,10 @@ void invalidate_vuid(uint16 vuid)
from the vuid 'owner' of connections */
conn_clear_vuid_cache(vuid);
- TALLOC_FREE(vuser);
+ SAFE_FREE(vuser->groups);
+ TALLOC_FREE(vuser->nt_user_token);
+
+ SAFE_FREE(vuser);
num_validated_vuids--;
}
@@ -143,11 +153,11 @@ int register_vuid(auth_serversupplied_info *server_info,
DATA_BLOB session_key, DATA_BLOB response_blob,
const char *smb_name)
{
- user_struct *vuser;
+ user_struct *vuser = NULL;
/* Paranoia check. */
if(lp_security() == SEC_SHARE) {
- smb_panic("Tried to register uid in security=share");
+ smb_panic("Tried to register uid in security=share\n");
}
/* Limit allowed vuids to 16bits - VUID_OFFSET. */
@@ -156,12 +166,14 @@ int register_vuid(auth_serversupplied_info *server_info,
return UID_FIELD_INVALID;
}
- if((vuser = TALLOC_ZERO_P(NULL, user_struct)) == NULL) {
- DEBUG(0,("Failed to talloc users struct!\n"));
+ if((vuser = SMB_MALLOC_P(user_struct)) == NULL) {
+ DEBUG(0,("Failed to malloc users struct!\n"));
data_blob_free(&session_key);
return UID_FIELD_INVALID;
}
+ ZERO_STRUCTP(vuser);
+
/* Allocate a free vuid. Yes this is a linear search... :-) */
while( get_valid_user_struct(next_vuid) != NULL ) {
next_vuid++;
@@ -191,11 +203,6 @@ int register_vuid(auth_serversupplied_info *server_info,
return vuser->vuid;
}
- /* use this to keep tabs on all our info from the authentication */
- vuser->server_info = server_info;
- /* Ensure that the server_info will dissapear with the vuser it is now attached to */
- talloc_steal(vuser, vuser->server_info);
-
/* the next functions should be done by a SID mapping system (SMS) as
* the new real sam db won't have reference to unix uids or gids
*/
@@ -205,13 +212,14 @@ int register_vuid(auth_serversupplied_info *server_info,
vuser->n_groups = server_info->n_groups;
if (vuser->n_groups) {
- if (!(vuser->groups = (gid_t *)talloc_memdup(vuser, server_info->groups,
- sizeof(gid_t) *
- vuser->n_groups))) {
- DEBUG(0,("register_vuid: failed to talloc_memdup "
+ if (!(vuser->groups = (gid_t *)memdup(server_info->groups,
+ sizeof(gid_t) *
+ vuser->n_groups))) {
+ DEBUG(0,("register_vuid: failed to memdup "
"vuser->groups\n"));
data_blob_free(&session_key);
- TALLOC_FREE(vuser);
+ free(vuser);
+ TALLOC_FREE(server_info);
return UID_FIELD_INVALID;
}
}
@@ -239,26 +247,24 @@ int register_vuid(auth_serversupplied_info *server_info,
const char *unix_homedir =
pdb_get_unix_homedir(server_info->sam_account);
if (unix_homedir) {
- vuser->unix_homedir = unix_homedir;
+ vuser->unix_homedir =
+ smb_xstrdup(unix_homedir);
}
} else {
struct passwd *passwd =
- getpwnam_alloc(vuser, vuser->user.unix_name);
+ getpwnam_alloc(NULL, vuser->user.unix_name);
if (passwd) {
- vuser->unix_homedir = passwd->pw_dir;
- /* Ensure that the unix_homedir now
- * belongs to vuser, so it goes away
- * with it, not with passwd below: */
- talloc_steal(vuser, vuser->unix_homedir);
+ vuser->unix_homedir =
+ smb_xstrdup(passwd->pw_dir);
TALLOC_FREE(passwd);
}
}
if (homedir) {
- vuser->homedir = homedir;
+ vuser->homedir = smb_xstrdup(homedir);
}
if (logon_script) {
- vuser->logon_script = logon_script;
+ vuser->logon_script = smb_xstrdup(logon_script);
}
}
@@ -274,15 +280,23 @@ int register_vuid(auth_serversupplied_info *server_info,
vuser->user.full_name));
if (server_info->ptok) {
- vuser->nt_user_token = dup_nt_token(vuser, server_info->ptok);
+ vuser->nt_user_token = dup_nt_token(NULL, server_info->ptok);
} else {
DEBUG(1, ("server_info does not contain a user_token - "
"cannot continue\n"));
- TALLOC_FREE(vuser);
+ TALLOC_FREE(server_info);
data_blob_free(&session_key);
+ SAFE_FREE(vuser->homedir);
+ SAFE_FREE(vuser->unix_homedir);
+ SAFE_FREE(vuser->logon_script);
+
+ SAFE_FREE(vuser);
return UID_FIELD_INVALID;
}
+ /* use this to keep tabs on all our info from the authentication */
+ vuser->server_info = server_info;
+
DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",
(int)vuser->uid,vuser->user.unix_name, vuser->vuid));
diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c
index 1da2f0c22f4..58756a0b5a6 100644
--- a/source/smbd/pipes.c
+++ b/source/smbd/pipes.c
@@ -37,7 +37,7 @@
#define PIPEDB_KEY_FORMAT "PIPE/%s/%u/%d"
struct pipe_dbrec {
- struct server_id pid;
+ struct process_id pid;
int pnum;
uid_t uid;
@@ -65,8 +65,7 @@ int reply_open_pipe_and_X(connection_struct *conn,
int i;
/* XXXX we need to handle passed times, sattr and flags */
- srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), pipe_name,
- smb_buf(inbuf), sizeof(pipe_name), STR_TERMINATE);
+ srvstr_pull_buf(inbuf, pipe_name, smb_buf(inbuf), sizeof(pipe_name), STR_TERMINATE);
/* If the name doesn't start \PIPE\ then this is directed */
/* at a mailslot or something we really, really don't understand, */
@@ -109,7 +108,7 @@ int reply_open_pipe_and_X(connection_struct *conn,
}
/* Prepare the reply */
- set_message(inbuf,outbuf,15,0,True);
+ set_message(outbuf,15,0,True);
/* Mark the opened file as an existing named pipe in message mode. */
SSVAL(outbuf,smb_vwv9,2);
@@ -163,7 +162,7 @@ int reply_pipe_write(char *inbuf,char *outbuf,int length,int dum_bufsize)
return (UNIXERROR(ERRDOS,ERRnoaccess));
}
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,nwritten);
@@ -225,7 +224,7 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize)
return (UNIXERROR(ERRDOS,ERRnoaccess));
}
- set_message(inbuf,outbuf,6,0,True);
+ set_message(outbuf,6,0,True);
nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten);
SSVAL(outbuf,smb_vwv2,nwritten);
@@ -261,7 +260,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
return(ERROR_DOS(ERRDOS,ERRbadfid));
}
- set_message(inbuf,outbuf,12,0,True);
+ set_message(outbuf,12,0,True);
data = smb_buf(outbuf);
nread = read_from_pipe(p, data, smb_maxcnt, &unused);
@@ -278,7 +277,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
p->pnum, smb_mincnt, smb_maxcnt, nread));
/* Ensure we set up the message length to include the data length read. */
- set_message_bcc(inbuf,outbuf,nread);
+ set_message_bcc(outbuf,nread);
return chain_reply(inbuf,outbuf,length,bufsize);
}
@@ -289,7 +288,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize)
int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf)
{
smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv0);
- int outsize = set_message(inbuf,outbuf,0,0,True);
+ int outsize = set_message(outbuf,0,0,True);
if (!p) {
return(ERROR_DOS(ERRDOS,ERRbadfid));
@@ -301,7 +300,5 @@ int reply_pipe_close(connection_struct *conn, char *inbuf,char *outbuf)
return ERROR_DOS(ERRDOS,ERRbadfid);
}
- /* TODO: REMOVE PIPE FROM DB */
-
return(outsize);
}
diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c
index 947c30fb4a3..ade64c1c6cc 100644
--- a/source/smbd/posix_acls.c
+++ b/source/smbd/posix_acls.c
@@ -926,7 +926,7 @@ static mode_t map_nt_perms( uint32 *mask, int type)
Unpack a SEC_DESC into a UNIX owner and group.
****************************************************************************/
-NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
+BOOL unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_info_sent, SEC_DESC *psd)
{
DOM_SID owner_sid;
DOM_SID grp_sid;
@@ -936,7 +936,7 @@ NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_i
if(security_info_sent == 0) {
DEBUG(0,("unpack_nt_owners: no security info sent !\n"));
- return NT_STATUS_OK;
+ return True;
}
/*
@@ -964,11 +964,9 @@ NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_i
DEBUG(3,("unpack_nt_owners: unable to validate"
" owner sid for %s\n",
sid_string_static(&owner_sid)));
- return NT_STATUS_INVALID_OWNER;
+ return False;
}
}
- DEBUG(3,("unpack_nt_owners: owner sid mapped to uid %u\n",
- (unsigned int)*puser ));
}
/*
@@ -986,16 +984,14 @@ NTSTATUS unpack_nt_owners(int snum, uid_t *puser, gid_t *pgrp, uint32 security_i
} else {
DEBUG(3,("unpack_nt_owners: unable to validate"
" group sid.\n"));
- return NT_STATUS_INVALID_OWNER;
+ return False;
}
}
- DEBUG(3,("unpack_nt_owners: group sid mapped to gid %u\n",
- (unsigned int)*pgrp));
- }
+ }
DEBUG(5,("unpack_nt_owners: owner_sids validated.\n"));
- return NT_STATUS_OK;
+ return True;
}
/****************************************************************************
@@ -3076,7 +3072,6 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid)
/* Case (4). */
if (!lp_dos_filemode(SNUM(conn))) {
- errno = EPERM;
return -1;
}
@@ -3112,7 +3107,7 @@ static NTSTATUS append_ugw_ace(files_struct *fsp,
{
mode_t perms;
SEC_ACCESS acc;
- int acl_type;
+ int nt_acl_type; /* Tru64 has "acl_type" as a macro.. */
DOM_SID trustee;
switch (ugw) {
@@ -3141,13 +3136,13 @@ static NTSTATUS append_ugw_ace(files_struct *fsp,
return NT_STATUS_INVALID_PARAMETER;
}
acc = map_canon_ace_perms(SNUM(fsp->conn),
- &acl_type,
+ &nt_acl_type,
perms,
fsp->is_directory);
init_sec_ace(se,
&trustee,
- acl_type,
+ nt_acl_type,
acc,
0);
return NT_STATUS_OK;
@@ -3195,14 +3190,13 @@ static NTSTATUS append_parent_acl(files_struct *fsp,
parent_name);
status = open_directory(fsp->conn,
- NULL,
parent_name,
&sbuf,
FILE_READ_ATTRIBUTES, /* Just a stat open */
FILE_SHARE_NONE, /* Ignored for stat opens */
FILE_OPEN,
0,
- INTERNAL_OPEN_ONLY,
+ 0,
&info,
&parent_fsp);
@@ -3303,7 +3297,7 @@ static NTSTATUS append_parent_acl(files_struct *fsp,
This should be the only external function needed for the UNIX style set ACL.
****************************************************************************/
-NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
+BOOL set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
{
connection_struct *conn = fsp->conn;
uid_t user = (uid_t)-1;
@@ -3315,13 +3309,15 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
canon_ace *dir_ace_list = NULL;
BOOL acl_perms = False;
mode_t orig_mode = (mode_t)0;
- NTSTATUS status;
+ uid_t orig_uid;
+ gid_t orig_gid;
+ BOOL need_chown = False;
DEBUG(10,("set_nt_acl: called for file %s\n", fsp->fsp_name ));
if (!CAN_WRITE(conn)) {
DEBUG(10,("set acl rejected on read-only share\n"));
- return NT_STATUS_MEDIA_WRITE_PROTECTED;
+ return False;
}
/*
@@ -3330,29 +3326,40 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
if(fsp->is_directory || fsp->fh->fd == -1) {
if(SMB_VFS_STAT(fsp->conn,fsp->fsp_name, &sbuf) != 0)
- return map_nt_error_from_unix(errno);
+ return False;
} else {
if(SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) != 0)
- return map_nt_error_from_unix(errno);
+ return False;
}
/* Save the original elements we check against. */
orig_mode = sbuf.st_mode;
+ orig_uid = sbuf.st_uid;
+ orig_gid = sbuf.st_gid;
/*
* Unpack the user/group/world id's.
*/
- status = unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
+ if (!unpack_nt_owners( SNUM(conn), &user, &grp, security_info_sent, psd)) {
+ return False;
}
/*
* Do we need to chown ?
*/
- if (((user != (uid_t)-1) && (sbuf.st_uid != user)) || (( grp != (gid_t)-1) && (sbuf.st_gid != grp))) {
+ if (((user != (uid_t)-1) && (orig_uid != user)) || (( grp != (gid_t)-1) && (orig_gid != grp))) {
+ need_chown = True;
+ }
+
+ /*
+ * Chown before setting ACL only if we don't change the user, or
+ * if we change to the current user, but not if we want to give away
+ * the file.
+ */
+
+ if (need_chown && (user == (uid_t)-1 || user == current_user.ut.uid)) {
DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
@@ -3360,10 +3367,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n",
fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
- if (errno == EPERM) {
- return NT_STATUS_INVALID_OWNER;
- }
- return map_nt_error_from_unix(errno);
+ return False;
}
/*
@@ -3373,7 +3377,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
if(fsp->is_directory) {
if(SMB_VFS_STAT(fsp->conn, fsp->fsp_name, &sbuf) != 0) {
- return map_nt_error_from_unix(errno);
+ return False;
}
} else {
@@ -3385,11 +3389,16 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
ret = SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf);
if(ret != 0)
- return map_nt_error_from_unix(errno);
+ return False;
}
/* Save the original elements we check against. */
orig_mode = sbuf.st_mode;
+ orig_uid = sbuf.st_uid;
+ orig_gid = sbuf.st_gid;
+
+ /* We did it, don't try again */
+ need_chown = False;
}
create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid);
@@ -3400,9 +3409,9 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
SE_DESC_DACL_AUTO_INHERIT_REQ))==
(SE_DESC_DACL_AUTO_INHERITED|
SE_DESC_DACL_AUTO_INHERIT_REQ) ) {
- status = append_parent_acl(fsp, &sbuf, psd, &psd);
+ NTSTATUS status = append_parent_acl(fsp, &sbuf, psd, &psd);
if (!NT_STATUS_IS_OK(status)) {
- return status;
+ return False;
}
}
@@ -3416,7 +3425,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
DEBUG(3,("set_nt_acl: cannot set permissions\n"));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return NT_STATUS_ACCESS_DENIED;
+ return False;
}
/*
@@ -3439,7 +3448,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
DEBUG(3,("set_nt_acl: failed to set file acl on file %s (%s).\n", fsp->fsp_name, strerror(errno) ));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return map_nt_error_from_unix(errno);
+ return False;
}
}
@@ -3449,7 +3458,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
DEBUG(3,("set_nt_acl: failed to set default acl on directory %s (%s).\n", fsp->fsp_name, strerror(errno) ));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return map_nt_error_from_unix(errno);
+ return False;
}
} else {
@@ -3474,7 +3483,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
DEBUG(3,("set_nt_acl: sys_acl_delete_def_file failed (%s)\n", strerror(errno)));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return map_nt_error_from_unix(errno);
+ return False;
}
}
}
@@ -3497,7 +3506,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
free_canon_ace_list(dir_ace_list);
DEBUG(3,("set_nt_acl: failed to convert file acl to posix permissions for file %s.\n",
fsp->fsp_name ));
- return NT_STATUS_ACCESS_DENIED;
+ return False;
}
if (orig_mode != posix_perms) {
@@ -3522,7 +3531,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
fsp->fsp_name, (unsigned int)posix_perms, strerror(errno) ));
free_canon_ace_list(file_ace_list);
free_canon_ace_list(dir_ace_list);
- return map_nt_error_from_unix(errno);
+ return False;
}
}
}
@@ -3533,7 +3542,20 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, SEC_DESC *psd)
free_canon_ace_list(dir_ace_list);
}
- return NT_STATUS_OK;
+ /* Any chown pending? */
+ if (need_chown) {
+
+ DEBUG(3,("set_nt_acl: chown %s. uid = %u, gid = %u.\n",
+ fsp->fsp_name, (unsigned int)user, (unsigned int)grp ));
+
+ if(try_chown( fsp->conn, fsp->fsp_name, user, grp) == -1) {
+ DEBUG(3,("set_nt_acl: chown %s, %u, %u failed. Error = %s.\n",
+ fsp->fsp_name, (unsigned int)user, (unsigned int)grp, strerror(errno) ));
+ return False;
+ }
+ }
+
+ return True;
}
/****************************************************************************
diff --git a/source/smbd/process.c b/source/smbd/process.c
index 1cb2c27fd39..8dec71958ea 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -22,6 +22,7 @@
#include "includes.h"
uint16 global_smbpid;
+extern int keepalive;
extern struct auth_context *negprot_global_auth_context;
extern int smb_echo_count;
@@ -48,16 +49,13 @@ SIG_ATOMIC_T got_sig_term = 0;
extern BOOL global_machine_password_needs_changing;
extern int max_send;
-/*
- * Initialize a struct smb_request from an inbuf
- */
+/****************************************************************************
+ Function to return the current request mid from Inbuffer.
+****************************************************************************/
-void init_smb_request(struct smb_request *req, const uint8 *inbuf)
+uint16 get_current_mid(void)
{
- req->flags2 = SVAL(inbuf, smb_flg2);
- req->smbpid = SVAL(inbuf, smb_pid);
- req->mid = SVAL(inbuf, smb_mid);
- req->vuid = SVAL(inbuf, smb_uid);
+ return SVAL(InBuffer,smb_mid);
}
/****************************************************************************
@@ -68,8 +66,8 @@ void init_smb_request(struct smb_request *req, const uint8 *inbuf)
static struct pending_message_list *deferred_open_queue;
/****************************************************************************
- Function to push a message onto the tail of a linked list of smb messages
- ready for processing.
+ Function to push a message onto the tail of a linked list of smb messages ready
+ for processing.
****************************************************************************/
static BOOL push_queued_message(char *buf, int msg_len,
@@ -124,7 +122,7 @@ void remove_deferred_open_smb_message(uint16 mid)
for (pml = deferred_open_queue; pml; pml = pml->next) {
if (mid == SVAL(pml->buf.data,smb_mid)) {
- DEBUG(10,("remove_deferred_open_smb_message: "
+ DEBUG(10,("remove_sharing_violation_open_smb_message: "
"deleting mid %u len %u\n",
(unsigned int)mid,
(unsigned int)pml->buf.length ));
@@ -147,11 +145,11 @@ void schedule_deferred_open_smb_message(uint16 mid)
for (pml = deferred_open_queue; pml; pml = pml->next) {
uint16 msg_mid = SVAL(pml->buf.data,smb_mid);
- DEBUG(10, ("schedule_deferred_open_smb_message: [%d] "
- "msg_mid = %u\n", i++, (unsigned int)msg_mid ));
+ DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++,
+ (unsigned int)msg_mid ));
if (mid == msg_mid) {
- DEBUG(10, ("schedule_deferred_open_smb_message: "
- "scheduling mid %u\n", mid));
+ DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n",
+ mid ));
pml->end_time.tv_sec = 0;
pml->end_time.tv_usec = 0;
DLIST_PROMOTE(deferred_open_queue, pml);
@@ -159,8 +157,8 @@ void schedule_deferred_open_smb_message(uint16 mid)
}
}
- DEBUG(10, ("schedule_deferred_open_smb_message: failed to find "
- "message mid %u\n", mid ));
+ DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n",
+ mid ));
}
/****************************************************************************
@@ -223,7 +221,6 @@ BOOL push_deferred_smb_message(uint16 mid,
struct idle_event {
struct timed_event *te;
struct timeval interval;
- char *name;
BOOL (*handler)(const struct timeval *now, void *private_data);
void *private_data;
};
@@ -244,19 +241,17 @@ static void idle_event_handler(struct event_context *ctx,
return;
}
- event->te = event_add_timed(ctx, event,
+ event->te = event_add_timed(smbd_event_context(), event,
timeval_sum(now, &event->interval),
- event->name,
+ "idle_event_handler",
idle_event_handler, event);
/* We can't do much but fail here. */
SMB_ASSERT(event->te != NULL);
}
-struct idle_event *event_add_idle(struct event_context *event_ctx,
- TALLOC_CTX *mem_ctx,
+struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx,
struct timeval interval,
- const char *name,
BOOL (*handler)(const struct timeval *now,
void *private_data),
void *private_data)
@@ -274,15 +269,9 @@ struct idle_event *event_add_idle(struct event_context *event_ctx,
result->handler = handler;
result->private_data = private_data;
- if (!(result->name = talloc_asprintf(result, "idle_evt(%s)", name))) {
- DEBUG(0, ("talloc failed\n"));
- TALLOC_FREE(result);
- return NULL;
- }
-
- result->te = event_add_timed(event_ctx, result,
+ result->te = event_add_timed(smbd_event_context(), result,
timeval_sum(&now, &interval),
- result->name,
+ "idle_event_handler",
idle_event_handler, result);
if (result->te == NULL) {
DEBUG(0, ("event_add_timed failed\n"));
@@ -304,7 +293,7 @@ static void async_processing(fd_set *pfds)
process_aio_queue();
- process_kernel_oplocks(smbd_messaging_context(), pfds);
+ process_kernel_oplocks(pfds);
/* Do the aio check again after receive_local_message as it does a
select and may have eaten our signal. */
@@ -383,7 +372,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
* messages as we need to synchronously process any messages
* we may have sent to ourselves from the previous SMB.
*/
- message_dispatch(smbd_messaging_context());
+ message_dispatch();
/*
* Check to see if we already have a message on the deferred open queue
@@ -577,7 +566,7 @@ void respond_to_all_remaining_local_messages(void)
return;
}
- process_kernel_oplocks(smbd_messaging_context(), NULL);
+ process_kernel_oplocks(NULL);
return;
}
@@ -1042,9 +1031,8 @@ static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
outsize += chain_size;
- if(outsize > 4) {
- smb_setlen(inbuf,outbuf,outsize - 4);
- }
+ if(outsize > 4)
+ smb_setlen(outbuf,outsize - 4);
return(outsize);
}
@@ -1132,7 +1120,7 @@ void remove_from_common_flags2(uint32 v)
void construct_reply_common(const char *inbuf, char *outbuf)
{
- set_message(inbuf,outbuf,0,0,False);
+ set_message(outbuf,0,0,False);
SCVAL(outbuf,smb_com,CVAL(inbuf,smb_com));
SIVAL(outbuf,smb_rcls,0);
@@ -1214,15 +1202,16 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize)
/* work out the new size for the in buffer. */
new_size = size - (inbuf2 - inbuf);
if (new_size < 0) {
- DEBUG(0,("chain_reply: chain packet size incorrect "
- "(orig size = %d, offset = %d)\n",
- size, (int)(inbuf2 - inbuf) ));
+ DEBUG(0,("chain_reply: chain packet size incorrect (orig size = %d, "
+ "offset = %d)\n",
+ size,
+ (inbuf2 - inbuf) ));
exit_server_cleanly("Bad chained packet");
return(-1);
}
/* And set it in the header. */
- smb_setlen(inbuf, inbuf2, new_size);
+ smb_setlen(inbuf2, new_size);
/* create the out buffer */
construct_reply_common(inbuf2, outbuf2);
@@ -1262,7 +1251,7 @@ static int setup_select_timeout(void)
{
int select_timeout;
- select_timeout = SMBD_SELECT_TIMEOUT*1000;
+ select_timeout = blocking_locks_timeout_ms(SMBD_SELECT_TIMEOUT*1000);
if (print_notify_messages_pending()) {
select_timeout = MIN(select_timeout, 1000);
@@ -1328,10 +1317,12 @@ void check_reload(time_t t)
Process any timeout housekeeping. Return False if the caller should exit.
****************************************************************************/
-static BOOL timeout_processing(int *select_timeout,
- time_t *last_timeout_processing_time)
+static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_timeout_processing_time)
{
+ static time_t last_keepalive_sent_time = 0;
+ static time_t last_idle_closed_check = 0;
time_t t;
+ BOOL allidle = True;
if (smb_read_error == READ_EOF) {
DEBUG(3,("timeout_processing: End of file from client (client has disconnected).\n"));
@@ -1351,12 +1342,56 @@ static BOOL timeout_processing(int *select_timeout,
*last_timeout_processing_time = t = time(NULL);
+ if(last_keepalive_sent_time == 0)
+ last_keepalive_sent_time = t;
+
+ if(last_idle_closed_check == 0)
+ last_idle_closed_check = t;
+
/* become root again if waiting */
change_to_root_user();
+ /* run all registered idle events */
+ smb_run_idle_events(t);
+
/* check if we need to reload services */
check_reload(t);
+ /* automatic timeout if all connections are closed */
+ if (conn_num_open()==0 && (t - last_idle_closed_check) >= IDLE_CLOSED_TIMEOUT) {
+ DEBUG( 2, ( "Closing idle connection\n" ) );
+ return False;
+ } else {
+ last_idle_closed_check = t;
+ }
+
+ if (keepalive && (t - last_keepalive_sent_time)>keepalive) {
+ if (!send_keepalive(smbd_server_fd())) {
+ DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
+ return False;
+ }
+
+ /* send a keepalive for a password server or the like.
+ This is attached to the auth_info created in the
+ negprot */
+ if (negprot_global_auth_context && negprot_global_auth_context->challenge_set_method
+ && negprot_global_auth_context->challenge_set_method->send_keepalive) {
+
+ negprot_global_auth_context->challenge_set_method->send_keepalive
+ (&negprot_global_auth_context->challenge_set_method->private_data);
+ }
+
+ last_keepalive_sent_time = t;
+ }
+
+ /* check for connection timeouts */
+ allidle = conn_idle_all(t, deadtime);
+
+ if (allidle && conn_num_open()>0) {
+ DEBUG(2,("Closing idle connection 2.\n"));
+ return False;
+ }
+
if(global_machine_password_needs_changing &&
/* for ADS we need to do a regular ADS password change, not a domain
password change */
@@ -1405,6 +1440,12 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup()));
secrets_lock_trust_account_password(lp_workgroup(), False);
}
+ /*
+ * Check to see if we have any blocking locks
+ * outstanding on the queue.
+ */
+ process_blocking_lock_queue();
+
/* update printer queue caches if necessary */
update_monitored_printq_cache();
@@ -1418,7 +1459,7 @@ machine %s in domain %s.\n", global_myname(), lp_workgroup()));
/* Send any queued printer notify message to interested smbd's. */
- print_notify_send_messages(smbd_messaging_context(), 0);
+ print_notify_send_messages(0);
/*
* Modify the select timeout depending upon
@@ -1503,9 +1544,13 @@ void smbd_process(void)
max_recv = MIN(lp_maxxmit(),BUFFER_SIZE);
while (True) {
+ int deadtime = lp_deadtime()*60;
int select_timeout = setup_select_timeout();
int num_echos;
+ if (deadtime <= 0)
+ deadtime = DEFAULT_SMBD_TIMEOUT;
+
errno = 0;
/* free up temporary memory */
@@ -1514,8 +1559,7 @@ void smbd_process(void)
/* Did someone ask for immediate checks on things like blocking locks ? */
if (select_timeout == 0) {
- if(!timeout_processing(&select_timeout,
- &last_timeout_processing_time))
+ if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
return;
num_smbs = 0; /* Reset smb counter. */
}
@@ -1527,8 +1571,7 @@ void smbd_process(void)
#endif
while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) {
- if(!timeout_processing(&select_timeout,
- &last_timeout_processing_time))
+ if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
return;
num_smbs = 0; /* Reset smb counter. */
}
@@ -1549,7 +1592,7 @@ void smbd_process(void)
process_smb(InBuffer, OutBuffer);
if (smb_echo_count != num_echos) {
- if(!timeout_processing( &select_timeout, &last_timeout_processing_time))
+ if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
return;
num_smbs = 0; /* Reset smb counter. */
}
@@ -1566,9 +1609,7 @@ void smbd_process(void)
if ((num_smbs % 200) == 0) {
time_t new_check_time = time(NULL);
if(new_check_time - last_timeout_processing_time >= (select_timeout/1000)) {
- if(!timeout_processing(
- &select_timeout,
- &last_timeout_processing_time))
+ if(!timeout_processing( deadtime, &select_timeout, &last_timeout_processing_time))
return;
num_smbs = 0; /* Reset smb counter. */
last_timeout_processing_time = new_check_time; /* Reset time. */
diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c
index feb28e2c743..b6d3257c0ff 100644
--- a/source/smbd/quotas.c
+++ b/source/smbd/quotas.c
@@ -1225,6 +1225,9 @@ BOOL disk_quotas(const char *path, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB
D.dqb_curblocks = user_quota.bused;
D.dqb_bsoftlimit = user_quota.bsoft;
D.dqb_bhardlimit = user_quota.bhard;
+ D.dqb_curfiles = user_quota.iused;
+ D.dqb_fsoftlimit = user_quota.isoft;
+ D.dqb_fhardlimit = user_quota.ihard;
}
else if(statbuf.f_vfstype == MNT_JFS)
{
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index b17fa1949bc..55f62a26f7c 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -47,12 +47,13 @@ extern BOOL global_encrypted_passwords_negotiated;
/* Custom version for processing POSIX paths. */
#define IS_PATH_SEP(c,posix_only) ((c) == '/' || (!(posix_only) && (c) == '\\'))
-static NTSTATUS check_path_syntax_internal(char *path,
- BOOL posix_path,
- BOOL *p_last_component_contains_wcard)
+NTSTATUS check_path_syntax_internal(pstring destname,
+ const pstring srcname,
+ BOOL posix_path,
+ BOOL *p_last_component_contains_wcard)
{
- char *d = path;
- const char *s = path;
+ char *d = destname;
+ const char *s = srcname;
NTSTATUS ret = NT_STATUS_OK;
BOOL start_of_name_component = True;
@@ -61,14 +62,13 @@ static NTSTATUS check_path_syntax_internal(char *path,
while (*s) {
if (IS_PATH_SEP(*s,posix_path)) {
/*
- * Safe to assume is not the second part of a mb char
- * as this is handled below.
+ * Safe to assume is not the second part of a mb char as this is handled below.
*/
/* Eat multiple '/' or '\\' */
while (IS_PATH_SEP(*s,posix_path)) {
s++;
}
- if ((d != path) && (*s != '\0')) {
+ if ((d != destname) && (*s != '\0')) {
/* We only care about non-leading or trailing '/' or '\\' */
*d++ = '/';
}
@@ -88,13 +88,13 @@ static NTSTATUS check_path_syntax_internal(char *path,
*/
/* If we just added a '/' - delete it */
- if ((d > path) && (*(d-1) == '/')) {
+ if ((d > destname) && (*(d-1) == '/')) {
*(d-1) = '\0';
d--;
}
/* Are we at the start ? Can't go back further if so. */
- if (d <= path) {
+ if (d <= destname) {
ret = NT_STATUS_OBJECT_PATH_SYNTAX_BAD;
break;
}
@@ -102,7 +102,7 @@ static NTSTATUS check_path_syntax_internal(char *path,
/* We know this is safe as '/' cannot be part of a mb sequence. */
/* NOTE - if this assumption is invalid we are not in good shape... */
/* Decrement d first as d points to the *next* char to write into. */
- for (d--; d > path; d--) {
+ for (d--; d > destname; d--) {
if (*d == '/')
break;
}
@@ -176,10 +176,10 @@ static NTSTATUS check_path_syntax_internal(char *path,
No wildcards allowed.
****************************************************************************/
-NTSTATUS check_path_syntax(char *path)
+NTSTATUS check_path_syntax(pstring destname, const pstring srcname)
{
BOOL ignore;
- return check_path_syntax_internal(path, False, &ignore);
+ return check_path_syntax_internal(destname, srcname, False, &ignore);
}
/****************************************************************************
@@ -188,9 +188,9 @@ NTSTATUS check_path_syntax(char *path)
a wildcard.
****************************************************************************/
-NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
+NTSTATUS check_path_syntax_wcard(pstring destname, const pstring srcname, BOOL *p_contains_wcard)
{
- return check_path_syntax_internal(path, False, p_contains_wcard);
+ return check_path_syntax_internal(destname, srcname, False, p_contains_wcard);
}
/****************************************************************************
@@ -199,48 +199,48 @@ NTSTATUS check_path_syntax_wcard(char *path, BOOL *p_contains_wcard)
set (a safe assumption).
****************************************************************************/
-NTSTATUS check_path_syntax_posix(char *path)
+NTSTATUS check_path_syntax_posix(pstring destname, const pstring srcname)
{
BOOL ignore;
- return check_path_syntax_internal(path, True, &ignore);
+ return check_path_syntax_internal(destname, srcname, True, &ignore);
}
/****************************************************************************
Pull a string and check the path allowing a wilcard - provide for error return.
****************************************************************************/
-size_t srvstr_get_path_wcard(char *inbuf, uint16 smb_flags2, char *dest,
- const char *src, size_t dest_len, size_t src_len,
- int flags, NTSTATUS *err, BOOL *contains_wcard)
+size_t srvstr_get_path_wcard(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags,
+ NTSTATUS *err, BOOL *contains_wcard)
{
+ pstring tmppath;
+ char *tmppath_ptr = tmppath;
size_t ret;
#ifdef DEVELOPER
SMB_ASSERT(dest_len == sizeof(pstring));
#endif
if (src_len == 0) {
- ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
- dest_len, flags);
+ ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
} else {
- ret = srvstr_pull(inbuf, smb_flags2, dest, src,
- dest_len, src_len, flags);
+ ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
}
*contains_wcard = False;
- if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
+ if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
/*
* For a DFS path the function parse_dfs_path()
* will do the path processing, just make a copy.
*/
+ pstrcpy(dest, tmppath);
*err = NT_STATUS_OK;
return ret;
}
if (lp_posix_pathnames()) {
- *err = check_path_syntax_posix(dest);
+ *err = check_path_syntax_posix(dest, tmppath);
} else {
- *err = check_path_syntax_wcard(dest, contains_wcard);
+ *err = check_path_syntax_wcard(dest, tmppath, contains_wcard);
}
return ret;
@@ -250,36 +250,35 @@ size_t srvstr_get_path_wcard(char *inbuf, uint16 smb_flags2, char *dest,
Pull a string and check the path - provide for error return.
****************************************************************************/
-size_t srvstr_get_path(char *inbuf, uint16 smb_flags2, char *dest,
- const char *src, size_t dest_len, size_t src_len,
- int flags, NTSTATUS *err)
+size_t srvstr_get_path(char *inbuf, char *dest, const char *src, size_t dest_len, size_t src_len, int flags, NTSTATUS *err)
{
+ pstring tmppath;
+ char *tmppath_ptr = tmppath;
size_t ret;
#ifdef DEVELOPER
SMB_ASSERT(dest_len == sizeof(pstring));
#endif
if (src_len == 0) {
- ret = srvstr_pull_buf(inbuf, smb_flags2, dest, src,
- dest_len, flags);
+ ret = srvstr_pull_buf( inbuf, tmppath_ptr, src, dest_len, flags);
} else {
- ret = srvstr_pull(inbuf, smb_flags2, dest, src,
- dest_len, src_len, flags);
+ ret = srvstr_pull( inbuf, tmppath_ptr, src, dest_len, src_len, flags);
}
- if (smb_flags2 & FLAGS2_DFS_PATHNAMES) {
+ if (SVAL(inbuf,smb_flg2) & FLAGS2_DFS_PATHNAMES) {
/*
* For a DFS path the function parse_dfs_path()
* will do the path processing, just make a copy.
*/
+ pstrcpy(dest, tmppath);
*err = NT_STATUS_OK;
return ret;
}
if (lp_posix_pathnames()) {
- *err = check_path_syntax_posix(dest);
+ *err = check_path_syntax_posix(dest, tmppath);
} else {
- *err = check_path_syntax(dest);
+ *err = check_path_syntax(dest, tmppath);
}
return ret;
@@ -303,7 +302,7 @@ int reply_special(char *inbuf,char *outbuf)
memset(outbuf,'\0',smb_size);
- smb_setlen(inbuf,outbuf,0);
+ smb_setlen(outbuf,0);
switch (msg_type) {
case 0x81: /* session request */
@@ -398,13 +397,10 @@ int reply_tcon(connection_struct *conn,
*service_buf = *password = *dev = 0;
p = smb_buf(inbuf)+1;
- p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), service_buf, p,
- sizeof(service_buf), STR_TERMINATE) + 1;
- pwlen = srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), password, p,
- sizeof(password), STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, service_buf, p, sizeof(service_buf), STR_TERMINATE) + 1;
+ pwlen = srvstr_pull_buf(inbuf, password, p, sizeof(password), STR_TERMINATE) + 1;
p += pwlen;
- p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), dev, p, sizeof(dev),
- STR_TERMINATE) + 1;
+ p += srvstr_pull_buf(inbuf, dev, p, sizeof(dev), STR_TERMINATE) + 1;
p = strrchr_m(service_buf,'\\');
if (p) {
@@ -424,7 +420,7 @@ int reply_tcon(connection_struct *conn,
return ERROR_NT(nt_status);
}
- outsize = set_message(inbuf,outbuf,2,0,True);
+ outsize = set_message(outbuf,2,0,True);
SSVAL(outbuf,smb_vwv0,max_recv);
SSVAL(outbuf,smb_vwv1,conn->cnum);
SSVAL(outbuf,smb_tid,conn->cnum);
@@ -488,8 +484,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
p = smb_buf(inbuf) + passlen + 1;
}
- p += srvstr_pull_buf(inbuf, SVAL(inbuf, smb_flg2), path, p,
- sizeof(path), STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, path, p, sizeof(path), STR_TERMINATE);
/*
* the service name can be either: \\server\share
@@ -506,8 +501,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
else
fstrcpy(service,path);
- p += srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), client_devicetype, p,
- sizeof(client_devicetype), 6, STR_ASCII);
+ p += srvstr_pull(inbuf, client_devicetype, p, sizeof(client_devicetype), 6, STR_ASCII);
DEBUG(4,("Client requested device type [%s] for share [%s]\n", client_devicetype, service));
@@ -528,11 +522,11 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
server_devicetype = "A:";
if (Protocol < PROTOCOL_NT1) {
- set_message(inbuf,outbuf,2,0,True);
+ set_message(outbuf,2,0,True);
p = smb_buf(outbuf);
p += srvstr_push(outbuf, p, server_devicetype, -1,
STR_TERMINATE|STR_ASCII);
- set_message_end(inbuf,outbuf,p);
+ set_message_end(outbuf,p);
} else {
/* NT sets the fstype of IPC$ to the null string */
const char *fstype = IS_IPC(conn) ? "" : lp_fstype(SNUM(conn));
@@ -542,7 +536,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
uint32 perm1 = 0;
uint32 perm2 = 0;
- set_message(inbuf,outbuf,7,0,True);
+ set_message(outbuf,7,0,True);
if (IS_IPC(conn)) {
perm1 = FILE_ALL_ACCESS;
@@ -556,7 +550,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
SIVAL(outbuf, smb_vwv3, perm1);
SIVAL(outbuf, smb_vwv5, perm2);
} else {
- set_message(inbuf,outbuf,3,0,True);
+ set_message(outbuf,3,0,True);
}
p = smb_buf(outbuf);
@@ -565,7 +559,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
p += srvstr_push(outbuf, p, fstype, -1,
STR_TERMINATE);
- set_message_end(inbuf,outbuf,p);
+ set_message_end(outbuf,p);
/* what does setting this bit do? It is set by NT4 and
may affect the ability to autorun mounted cdroms */
@@ -628,7 +622,7 @@ int reply_ioctl(connection_struct *conn,
return(ERROR_DOS(ERRSRV,ERRnosupport));
}
- outsize = set_message(inbuf,outbuf,8,replysize+1,True);
+ outsize = set_message(outbuf,8,replysize+1,True);
SSVAL(outbuf,smb_vwv1,replysize); /* Total data bytes returned */
SSVAL(outbuf,smb_vwv5,replysize); /* Data bytes this buffer */
SSVAL(outbuf,smb_vwv6,52); /* Offset to data */
@@ -684,8 +678,7 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s
START_PROFILE(SMBcheckpath);
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), name, smb_buf(inbuf) + 1,
- sizeof(name), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcheckpath);
status = map_checkpath_error(inbuf, status);
@@ -725,7 +718,7 @@ int reply_checkpath(connection_struct *conn, char *inbuf,char *outbuf, int dum_s
return ERROR_BOTH(NT_STATUS_NOT_A_DIRECTORY,ERRDOS,ERRbadpath);
}
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
END_PROFILE(SMBcheckpath);
return outsize;
@@ -772,8 +765,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
START_PROFILE(SMBgetatr);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
- sizeof(fname), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBgetatr);
return ERROR_NT(status);
@@ -822,7 +814,7 @@ int reply_getatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
}
}
- outsize = set_message(inbuf,outbuf,10,0,True);
+ outsize = set_message(outbuf,10,0,True);
SSVAL(outbuf,smb_vwv0,mode);
if(lp_dos_filetime_resolution(SNUM(conn)) ) {
@@ -859,8 +851,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
START_PROFILE(SMBsetatr);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, p,
- sizeof(fname), 0, STR_TERMINATE, &status);
+ p += srvstr_get_path(inbuf, fname, p, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBsetatr);
return ERROR_NT(status);
@@ -916,7 +907,7 @@ int reply_setatr(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return UNIXERROR(ERRDOS, ERRnoaccess);
}
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
DEBUG( 3, ( "setatr name=%s mode=%d\n", fname, mode ) );
@@ -939,7 +930,7 @@ int reply_dskattr(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
return(UNIXERROR(ERRHRD,ERRgeneral));
}
- outsize = set_message(inbuf,outbuf,5,0,True);
+ outsize = set_message(outbuf,5,0,True);
if (Protocol <= PROTOCOL_LANMAN2) {
double total_space, free_space;
@@ -1018,13 +1009,11 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
expect_close = True;
}
- outsize = set_message(inbuf,outbuf,1,3,True);
+ outsize = set_message(outbuf,1,3,True);
maxentries = SVAL(inbuf,smb_vwv0);
dirtype = SVAL(inbuf,smb_vwv1);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
- sizeof(path), 0, STR_TERMINATE, &nt_status,
- &mask_contains_wcard);
+ p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &nt_status, &mask_contains_wcard);
if (!NT_STATUS_IS_OK(nt_status)) {
END_PROFILE(SMBsearch);
return ERROR_NT(nt_status);
@@ -1192,7 +1181,7 @@ int reply_search(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
SSVAL(outbuf,smb_flg2, (SVAL(outbuf, smb_flg2) & (~FLAGS2_UNICODE_STRINGS)));
outsize += DIR_STRUCT_SIZE*numentries;
- smb_setlen(inbuf,outbuf,outsize - 4);
+ smb_setlen(outbuf,outsize - 4);
if ((! *directory) && dptr_path(dptr_num))
slprintf(directory, sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
@@ -1227,11 +1216,9 @@ int reply_fclose(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return reply_unknown(inbuf, outbuf);
}
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), path, p,
- sizeof(path), 0, STR_TERMINATE, &err,
- &path_contains_wcard);
+ p += srvstr_get_path_wcard(inbuf, path, p, sizeof(path), 0, STR_TERMINATE, &err, &path_contains_wcard);
if (!NT_STATUS_IS_OK(err)) {
END_PROFILE(SMBfclose);
return ERROR_NT(err);
@@ -1282,16 +1269,11 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
uint32 create_disposition;
uint32 create_options = 0;
NTSTATUS status;
- struct smb_request req;
-
START_PROFILE(SMBopen);
-
- init_smb_request(&req, (uint8 *)inbuf);
deny_mode = SVAL(inbuf,smb_vwv0);
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
- sizeof(fname), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopen);
return ERROR_NT(status);
@@ -1324,7 +1306,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
}
- status = open_file_ntcreate(conn, &req, fname, &sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_mode,
create_disposition,
@@ -1339,7 +1321,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
/* We have re-scheduled this call. */
return -1;
}
- return ERROR_NT(status);
+ return ERROR_OPEN(status);
}
size = sbuf.st_size;
@@ -1353,7 +1335,7 @@ int reply_open(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- outsize = set_message(inbuf,outbuf,7,0,True);
+ outsize = set_message(outbuf,7,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
SSVAL(outbuf,smb_vwv1,fattr);
if(lp_dos_filetime_resolution(SNUM(conn)) ) {
@@ -1407,12 +1389,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
uint32 share_mode;
uint32 create_disposition;
uint32 create_options = 0;
- struct smb_request req;
START_PROFILE(SMBopenX);
- init_smb_request(&req, (uint8 *)inbuf);
-
/* If it's an IPC, pass off the pipe handler. */
if (IS_IPC(conn)) {
if (lp_nt_pipe_support()) {
@@ -1425,8 +1404,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
/* XXXX we need to handle passed times, sattr and flags */
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf),
- sizeof(fname), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf), sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBopenX);
return ERROR_NT(status);
@@ -1462,7 +1440,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
return ERROR_NT(NT_STATUS_DOS(ERRDOS, ERRbadaccess));
}
- status = open_file_ntcreate(conn, &req, fname, &sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_mode,
create_disposition,
@@ -1477,7 +1455,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
/* We have re-scheduled this call. */
return -1;
}
- return ERROR_NT(status);
+ return ERROR_OPEN(status);
}
/* Setting the "size" field in vwv9 and vwv10 causes the file to be set to this size,
@@ -1533,9 +1511,9 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
if (open_flags & EXTENDED_RESPONSE_REQUIRED) {
- set_message(inbuf,outbuf,19,0,True);
+ set_message(outbuf,19,0,True);
} else {
- set_message(inbuf,outbuf,15,0,True);
+ set_message(outbuf,15,0,True);
}
SSVAL(outbuf,smb_vwv2,fsp->fnum);
SSVAL(outbuf,smb_vwv3,fattr);
@@ -1577,7 +1555,7 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,
invalidate_vuid(vuid);
- set_message(inbuf,outbuf,2,0,True);
+ set_message(outbuf,2,0,True);
DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) );
@@ -1604,18 +1582,14 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
uint32 share_mode = FILE_SHARE_READ|FILE_SHARE_WRITE;
uint32 create_disposition;
uint32 create_options = 0;
- struct smb_request req;
START_PROFILE(SMBcreate);
-
- init_smb_request(&req, (uint8 *)inbuf);
com = SVAL(inbuf,smb_com);
ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(inbuf + smb_vwv1)); /* mtime. */
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf) + 1,
- sizeof(fname), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf) + 1, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcreate);
return ERROR_NT(status);
@@ -1655,7 +1629,7 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
}
/* Open file using ntcreate. */
- status = open_file_ntcreate(conn, &req, fname, &sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_mode,
create_disposition,
@@ -1670,13 +1644,13 @@ int reply_mknew(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
/* We have re-scheduled this call. */
return -1;
}
- return ERROR_NT(status);
+ return ERROR_OPEN(status);
}
ts[0] = get_atimespec(&sbuf); /* atime. */
file_ntimes(conn, fname, ts);
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
@@ -1710,14 +1684,10 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
char *p, *s;
NTSTATUS status;
unsigned int namelen;
- struct smb_request req;
START_PROFILE(SMBctemp);
- init_smb_request(&req, (uint8 *)inbuf);
-
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, smb_buf(inbuf)+1,
- sizeof(fname), 0, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, smb_buf(inbuf)+1, sizeof(fname), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBctemp);
return ERROR_NT(status);
@@ -1758,7 +1728,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
SMB_VFS_STAT(conn,fname,&sbuf);
/* We should fail if file does not exist. */
- status = open_file_ntcreate(conn, &req, fname, &sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
@@ -1776,10 +1746,10 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
/* We have re-scheduled this call. */
return -1;
}
- return ERROR_NT(status);
+ return ERROR_OPEN(status);
}
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
/* the returned filename is relative to the directory */
@@ -1798,7 +1768,7 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
#endif
namelen = srvstr_push(outbuf, p, s, -1, STR_ASCII|STR_TERMINATE);
p += namelen;
- outsize = set_message_end(inbuf,outbuf, p);
+ outsize = set_message_end(outbuf, p);
if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
SCVAL(outbuf,smb_flg,CVAL(outbuf,smb_flg)|CORE_OPLOCK_GRANTED);
@@ -1820,16 +1790,17 @@ int reply_ctemp(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
Check if a user is allowed to rename a file.
********************************************************************/
-static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
- uint16 dirtype, SMB_STRUCT_STAT *pst)
+static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, SMB_STRUCT_STAT *pst, BOOL self_open)
{
+ files_struct *fsp;
uint32 fmode;
+ NTSTATUS status;
if (!CAN_WRITE(conn)) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
- fmode = dos_mode(conn, fsp->fsp_name, pst);
+ fmode = dos_mode(conn,fname,pst);
if ((fmode & ~dirtype) & (aHIDDEN | aSYSTEM)) {
return NT_STATUS_NO_SUCH_FILE;
}
@@ -1838,19 +1809,31 @@ static NTSTATUS can_rename(connection_struct *conn, files_struct *fsp,
return NT_STATUS_OK;
}
- if (fsp->access_mask & DELETE_ACCESS) {
- return NT_STATUS_OK;
- }
+ status = open_file_ntcreate(conn, fname, pst,
+ DELETE_ACCESS,
+ /* If we're checking our fsp don't deny for delete. */
+ self_open ?
+ FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE :
+ FILE_SHARE_READ|FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ NULL, &fsp);
- return NT_STATUS_ACCESS_DENIED;
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ close_file(fsp,NORMAL_CLOSE);
+ return NT_STATUS_OK;
}
/*******************************************************************
- * unlink a file with all relevant access checks
- *******************************************************************/
+ Check if a user is allowed to delete a file.
+********************************************************************/
-static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
- char *fname, uint32 dirtype)
+static NTSTATUS can_delete(connection_struct *conn, char *fname,
+ uint32 dirtype, BOOL can_defer)
{
SMB_STRUCT_STAT sbuf;
uint32 fattr;
@@ -1858,7 +1841,7 @@ static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
uint32 dirtype_orig = dirtype;
NTSTATUS status;
- DEBUG(10,("do_unlink: %s, dirtype = %d\n", fname, dirtype ));
+ DEBUG(10,("can_delete: %s, dirtype = %d\n", fname, dirtype ));
if (!CAN_WRITE(conn)) {
return NT_STATUS_MEDIA_WRITE_PROTECTED;
@@ -1942,28 +1925,19 @@ static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
/* On open checks the open itself will check the share mode, so
don't do it here as we'll get it wrong. */
- status = open_file_ntcreate(conn, req, fname, &sbuf,
+ status = open_file_ntcreate(conn, fname, &sbuf,
DELETE_ACCESS,
FILE_SHARE_NONE,
FILE_OPEN,
0,
FILE_ATTRIBUTE_NORMAL,
- req != NULL ? 0 : INTERNAL_OPEN_ONLY,
+ can_defer ? 0 : INTERNAL_OPEN_ONLY,
NULL, &fsp);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(10, ("open_file_ntcreate failed: %s\n",
- nt_errstr(status)));
- return status;
- }
-
- /* The set is across all open files on this dev/inode pair. */
- if (!set_delete_on_close(fsp, True, &current_user.ut)) {
- close_file(fsp, NORMAL_CLOSE);
- return NT_STATUS_ACCESS_DENIED;
+ if (NT_STATUS_IS_OK(status)) {
+ close_file(fsp,NORMAL_CLOSE);
}
-
- return close_file(fsp,NORMAL_CLOSE);
+ return status;
}
/****************************************************************************
@@ -1971,8 +1945,8 @@ static NTSTATUS do_unlink(connection_struct *conn, struct smb_request *req,
code.
****************************************************************************/
-NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
- uint32 dirtype, char *name, BOOL has_wild)
+NTSTATUS unlink_internals(connection_struct *conn, uint32 dirtype,
+ char *name, BOOL has_wild, BOOL can_defer)
{
pstring directory;
pstring mask;
@@ -2022,12 +1996,17 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
return status;
}
- status = do_unlink(conn, req, directory, dirtype);
+ status = can_delete(conn,directory,dirtype,can_defer);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
- count++;
+ if (SMB_VFS_UNLINK(conn,directory) == 0) {
+ count++;
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ directory);
+ }
} else {
struct smb_Dir *dir_hnd = NULL;
long offset = 0;
@@ -2086,14 +2065,19 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
return status;
}
- status = do_unlink(conn, req, fname, dirtype);
+ status = can_delete(conn, fname, dirtype, can_defer);
if (!NT_STATUS_IS_OK(status)) {
continue;
}
-
- count++;
- DEBUG(3,("unlink_internals: succesful unlink [%s]\n",
- fname));
+ if (SMB_VFS_UNLINK(conn,fname) == 0) {
+ count++;
+ DEBUG(3,("unlink_internals: succesful unlink "
+ "[%s]\n",fname));
+ notify_fname(conn, NOTIFY_ACTION_REMOVED,
+ FILE_NOTIFY_CHANGE_FILE_NAME,
+ fname);
+ }
+
}
CloseDir(dir_hnd);
}
@@ -2117,17 +2101,12 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
uint32 dirtype;
NTSTATUS status;
BOOL path_contains_wcard = False;
- struct smb_request req;
START_PROFILE(SMBunlink);
- init_smb_request(&req, (uint8 *)inbuf);
-
dirtype = SVAL(inbuf,smb_vwv0);
- srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name,
- smb_buf(inbuf) + 1, sizeof(name), 0,
- STR_TERMINATE, &status, &path_contains_wcard);
+ srvstr_get_path_wcard(inbuf, name, smb_buf(inbuf) + 1, sizeof(name), 0, STR_TERMINATE, &status, &path_contains_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBunlink);
return ERROR_NT(status);
@@ -2144,9 +2123,10 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
DEBUG(3,("reply_unlink : %s\n",name));
- status = unlink_internals(conn, &req, dirtype, name,
- path_contains_wcard);
+ status = unlink_internals(conn, dirtype, name, path_contains_wcard,
+ True);
if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBunlink);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
return -1;
@@ -2154,7 +2134,7 @@ int reply_unlink(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_NT(status);
}
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
END_PROFILE(SMBunlink);
return outsize;
@@ -2172,42 +2152,39 @@ static void fail_readraw(void)
exit_server_cleanly(errstr);
}
+#if defined(WITH_SENDFILE)
/****************************************************************************
Fake (read/write) sendfile. Returns -1 on read or write fail.
****************************************************************************/
-static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, size_t bufsize)
+static ssize_t fake_sendfile(files_struct *fsp, SMB_OFF_T startpos, size_t nread, char *buf, int bufsize)
{
- size_t tosend = nread;
+ ssize_t ret=0;
- while (tosend > 0) {
- ssize_t ret;
- size_t cur_read;
+ /* Paranioa check... */
+ if (nread > bufsize) {
+ fail_readraw();
+ }
- if (tosend > bufsize) {
- cur_read = bufsize;
- } else {
- cur_read = tosend;
- }
- ret = read_file(fsp,buf,startpos,cur_read);
+ if (nread > 0) {
+ ret = read_file(fsp,buf,startpos,nread);
if (ret == -1) {
return -1;
}
+ }
- /* If we had a short read, fill with zeros. */
- if (ret < cur_read) {
- memset(buf, '\0', cur_read - ret);
- }
-
- if (write_data(smbd_server_fd(),buf,cur_read) != cur_read) {
- return -1;
- }
- tosend -= cur_read;
- startpos += cur_read;
+ /* If we had a short read, fill with zeros. */
+ if (ret < nread) {
+ memset(buf, '\0', nread - ret);
}
+ if (write_data(smbd_server_fd(),buf,nread) != nread) {
+ return -1;
+ }
+
return (ssize_t)nread;
}
+#endif
/****************************************************************************
Use sendfile in readbraw.
@@ -2266,9 +2243,10 @@ void send_file_readbraw(connection_struct *conn, files_struct *fsp, SMB_OFF_T st
return;
}
-#endif
-normal_readbraw:
+ normal_readbraw:
+
+#endif
if (nread > 0) {
ret = read_file(fsp,outbuf+4,startpos,nread);
@@ -2428,7 +2406,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
numtoread = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
- outsize = set_message(inbuf,outbuf,5,3,True);
+ outsize = set_message(outbuf,5,3,True);
numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
data = smb_buf(outbuf) + 3;
@@ -2440,8 +2418,7 @@ int reply_lockread(connection_struct *conn, char *inbuf,char *outbuf, int length
* Note that the requested lock size is unaffected by max_recv.
*/
- br_lck = do_lock(smbd_messaging_context(),
- fsp,
+ br_lck = do_lock(fsp,
(uint32)SVAL(inbuf,smb_pid),
(SMB_BIG_UINT)numtoread,
(SMB_BIG_UINT)startpos,
@@ -2511,7 +2488,7 @@ int reply_read(connection_struct *conn, char *inbuf,char *outbuf, int size, int
numtoread = SVAL(inbuf,smb_vwv1);
startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv2);
- outsize = set_message(inbuf,outbuf,5,3,True);
+ outsize = set_message(outbuf,5,3,True);
numtoread = MIN(BUFFER_SIZE-outsize,numtoread);
/*
* The requested read size cannot be greater than max_recv. JRA.
@@ -2552,52 +2529,16 @@ Returning short read of maximum allowed for compatibility with Windows 2000.\n",
}
/****************************************************************************
- Setup readX header.
-****************************************************************************/
-
-static int setup_readX_header(char *inbuf, char *outbuf, size_t smb_maxcnt)
-{
- int outsize;
- char *data = smb_buf(outbuf);
-
- SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
- SSVAL(outbuf,smb_vwv5,smb_maxcnt);
- SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
- SSVAL(outbuf,smb_vwv7,(smb_maxcnt >> 16));
- SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
- SCVAL(outbuf,smb_vwv0,0xFF);
- outsize = set_message(inbuf, outbuf,12,smb_maxcnt,False);
- /* Reset the outgoing length, set_message truncates at 0x1FFFF. */
- _smb_setlen_large(outbuf,(smb_size + 12*2 + smb_maxcnt - 4));
- return outsize;
-}
-
-/****************************************************************************
Reply to a read and X - possibly using sendfile.
****************************************************************************/
int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length, int len_outbuf,
files_struct *fsp, SMB_OFF_T startpos, size_t smb_maxcnt)
{
- SMB_STRUCT_STAT sbuf;
int outsize = 0;
ssize_t nread = -1;
char *data = smb_buf(outbuf);
- if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1) {
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
-
- if (startpos > sbuf.st_size) {
- smb_maxcnt = 0;
- } else if (smb_maxcnt > (sbuf.st_size - startpos)) {
- smb_maxcnt = (sbuf.st_size - startpos);
- }
-
- if (smb_maxcnt == 0) {
- goto normal_read;
- }
-
#if defined(WITH_SENDFILE)
/*
* We can only use sendfile on a non-chained packet
@@ -2607,16 +2548,34 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
if ((chain_size == 0) && (CVAL(inbuf,smb_vwv0) == 0xFF) &&
lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) {
+ SMB_STRUCT_STAT sbuf;
DATA_BLOB header;
+ if(SMB_VFS_FSTAT(fsp,fsp->fh->fd, &sbuf) == -1)
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+
+ if (startpos > sbuf.st_size)
+ goto normal_read;
+
+ if (smb_maxcnt > (sbuf.st_size - startpos))
+ smb_maxcnt = (sbuf.st_size - startpos);
+
+ if (smb_maxcnt == 0)
+ goto normal_read;
+
/*
* Set up the packet header before send. We
* assume here the sendfile will work (get the
* correct amount of data).
*/
- setup_readX_header(inbuf,outbuf,smb_maxcnt);
- set_message(inbuf,outbuf,12,smb_maxcnt,False);
+ SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
+ SSVAL(outbuf,smb_vwv5,smb_maxcnt);
+ SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+ SSVAL(outbuf,smb_vwv7,((smb_maxcnt >> 16) & 1));
+ SSVAL(smb_buf(outbuf),-2,smb_maxcnt);
+ SCVAL(outbuf,smb_vwv0,0xFF);
+ set_message(outbuf,12,smb_maxcnt,False);
header.data = (uint8 *)outbuf;
header.length = data - outbuf;
header.free = NULL;
@@ -2661,40 +2620,28 @@ int send_file_readX(connection_struct *conn, char *inbuf,char *outbuf,int length
return -1;
}
-#endif
-
-normal_read:
-
- if ((smb_maxcnt & 0xFF0000) > 0x10000) {
- int sendlen = setup_readX_header(inbuf,outbuf,smb_maxcnt) - smb_maxcnt;
- /* Send out the header. */
- if (write_data(smbd_server_fd(),outbuf,sendlen) != sendlen) {
- DEBUG(0,("send_file_readX: write_data failed for file %s (%s). Terminating\n",
- fsp->fsp_name, strerror(errno) ));
- exit_server_cleanly("send_file_readX sendfile failed");
- }
- if ((nread = fake_sendfile(fsp, startpos, smb_maxcnt, data,
- len_outbuf - (data-outbuf))) == -1) {
- DEBUG(0,("send_file_readX: fake_sendfile failed for file %s (%s).\n",
- fsp->fsp_name, strerror(errno) ));
- exit_server_cleanly("send_file_readX: fake_sendfile failed");
- }
- return -1;
- } else {
- nread = read_file(fsp,data,startpos,smb_maxcnt);
+ normal_read:
- if (nread < 0) {
- return(UNIXERROR(ERRDOS,ERRnoaccess));
- }
+#endif
- outsize = setup_readX_header(inbuf, outbuf,nread);
+ nread = read_file(fsp,data,startpos,smb_maxcnt);
+
+ if (nread < 0) {
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
- DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
- fsp->fnum, (int)smb_maxcnt, (int)nread ) );
+ outsize = set_message(outbuf,12,nread,False);
+ SSVAL(outbuf,smb_vwv2,0xFFFF); /* Remaining - must be -1. */
+ SSVAL(outbuf,smb_vwv5,nread);
+ SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf));
+ SSVAL(outbuf,smb_vwv7,((nread >> 16) & 1));
+ SSVAL(smb_buf(outbuf),-2,nread);
+
+ DEBUG( 3, ( "send_file_readX fnum=%d max=%d nread=%d\n",
+ fsp->fnum, (int)smb_maxcnt, (int)nread ) );
- /* Returning the number of bytes we want to send back - including header. */
- return outsize;
- }
+ /* Returning the number of bytes we want to send back - including header. */
+ return outsize;
}
/****************************************************************************
@@ -2707,7 +2654,6 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
SMB_OFF_T startpos = IVAL_TO_SMB_OFF_T(inbuf,smb_vwv3);
ssize_t nread = -1;
size_t smb_maxcnt = SVAL(inbuf,smb_vwv5);
- BOOL big_readX = False;
#if 0
size_t smb_mincnt = SVAL(inbuf,smb_vwv6);
#endif
@@ -2725,25 +2671,17 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
return(ERROR_DOS(ERRDOS,ERRbadaccess));
}
- set_message(inbuf,outbuf,12,0,True);
+ set_message(outbuf,12,0,True);
if (global_client_caps & CAP_LARGE_READX) {
- size_t upper_size = SVAL(inbuf,smb_vwv7);
- smb_maxcnt |= (upper_size<<16);
- if (upper_size > 1) {
- /* Can't do this on a chained packet. */
- if ((CVAL(inbuf,smb_vwv0) != 0xFF)) {
- return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
- }
- /* We currently don't do this on signed or sealed data. */
- if (srv_is_signing_active() || srv_encryption_on()) {
- return ERROR_NT(NT_STATUS_NOT_SUPPORTED);
- }
- /* Is there room in the reply for this data ? */
- if (smb_maxcnt > (0xFFFFFF - (smb_size -4 + 12*2))) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
- big_readX = True;
+ if (SVAL(inbuf,smb_vwv7) == 1) {
+ smb_maxcnt |= (1<<16);
+ }
+ if (smb_maxcnt > BUFFER_SIZE) {
+ DEBUG(0,("reply_read_and_X - read too large (%u) for reply buffer %u\n",
+ (unsigned int)smb_maxcnt, (unsigned int)BUFFER_SIZE));
+ END_PROFILE(SMBreadX);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
}
@@ -2776,7 +2714,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
return ERROR_DOS(ERRDOS,ERRlock);
}
- if (!big_readX && schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
+ if (schedule_aio_read_and_X(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt)) {
END_PROFILE(SMBreadX);
return -1;
}
@@ -2858,7 +2796,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
/* Return a message to the redirector to tell it to send more bytes */
SCVAL(outbuf,smb_com,SMBwritebraw);
SSVALS(outbuf,smb_vwv0,-1);
- outsize = set_message(inbuf,outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
+ outsize = set_message(outbuf,Protocol>PROTOCOL_COREPLUS?1:0,0,True);
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
exit_server_cleanly("reply_writebraw: send_smb failed.");
@@ -2872,7 +2810,7 @@ int reply_writebraw(connection_struct *conn, char *inbuf,char *outbuf, int size,
numtowrite = smb_len(inbuf);
/* Set up outbuf to return the correct return */
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SCVAL(outbuf,smb_com,SMBwritec);
if (numtowrite != 0) {
@@ -2996,8 +2934,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
}
if (numtowrite) {
- status = do_unlock(smbd_messaging_context(),
- fsp,
+ status = do_unlock(fsp,
(uint32)SVAL(inbuf,smb_pid),
(SMB_BIG_UINT)numtowrite,
(SMB_BIG_UINT)startpos,
@@ -3009,7 +2946,7 @@ int reply_writeunlock(connection_struct *conn, char *inbuf,char *outbuf,
}
}
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,nwritten);
@@ -3095,7 +3032,7 @@ int reply_write(connection_struct *conn, char *inbuf,char *outbuf,int size,int d
return(UNIXERROR(ERRHRD,ERRdiskfull));
}
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,nwritten);
@@ -3139,7 +3076,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng
return(ERROR_DOS(ERRDOS,ERRbadaccess));
}
- set_message(inbuf,outbuf,6,0,True);
+ set_message(outbuf,6,0,True);
/* Deal with possible LARGE_WRITEX */
if (large_writeX) {
@@ -3292,7 +3229,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
fsp->fh->pos = res;
- outsize = set_message(inbuf,outbuf,2,0,True);
+ outsize = set_message(outbuf,2,0,True);
SIVAL(outbuf,smb_vwv0,res);
DEBUG(3,("lseek fnum=%d ofs=%.0f newpos = %.0f mode=%d\n",
@@ -3308,7 +3245,7 @@ int reply_lseek(connection_struct *conn, char *inbuf,char *outbuf, int size, int
int reply_flush(connection_struct *conn, char *inbuf,char *outbuf, int size, int dum_buffsize)
{
- int outsize = set_message(inbuf,outbuf,0,0,False);
+ int outsize = set_message(outbuf,0,0,False);
uint16 fnum = SVAL(inbuf,smb_vwv0);
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBflush);
@@ -3346,7 +3283,7 @@ int reply_exit(connection_struct *conn,
file_close_pid(SVAL(inbuf,smb_pid),SVAL(inbuf,smb_uid));
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
DEBUG(3,("exit\n"));
@@ -3366,7 +3303,7 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
files_struct *fsp = NULL;
START_PROFILE(SMBclose);
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
/* If it's an IPC, pass off to the pipe handler. */
if (IS_IPC(conn)) {
@@ -3486,7 +3423,7 @@ int reply_writeclose(connection_struct *conn,
return ERROR_NT(close_status);
}
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,nwritten);
END_PROFILE(SMBwriteclose);
@@ -3503,7 +3440,7 @@ int reply_writeclose(connection_struct *conn,
int reply_lock(connection_struct *conn,
char *inbuf,char *outbuf, int length, int dum_buffsize)
{
- int outsize = set_message(inbuf,outbuf,0,0,False);
+ int outsize = set_message(outbuf,0,0,False);
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
@@ -3521,8 +3458,7 @@ int reply_lock(connection_struct *conn,
DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n",
fsp->fh->fd, fsp->fnum, (double)offset, (double)count));
- br_lck = do_lock(smbd_messaging_context(),
- fsp,
+ br_lck = do_lock(fsp,
(uint32)SVAL(inbuf,smb_pid),
count,
offset,
@@ -3550,7 +3486,7 @@ int reply_lock(connection_struct *conn,
int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
int dum_buffsize)
{
- int outsize = set_message(inbuf,outbuf,0,0,False);
+ int outsize = set_message(outbuf,0,0,False);
SMB_BIG_UINT count,offset;
NTSTATUS status;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
@@ -3561,8 +3497,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
count = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv1);
offset = (SMB_BIG_UINT)IVAL(inbuf,smb_vwv3);
- status = do_unlock(smbd_messaging_context(),
- fsp,
+ status = do_unlock(fsp,
(uint32)SVAL(inbuf,smb_pid),
count,
offset,
@@ -3591,7 +3526,7 @@ int reply_unlock(connection_struct *conn, char *inbuf,char *outbuf, int size,
int reply_tdis(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- int outsize = set_message(inbuf,outbuf,0,0,False);
+ int outsize = set_message(outbuf,0,0,False);
uint16 vuid;
START_PROFILE(SMBtdis);
@@ -3622,7 +3557,7 @@ int reply_echo(connection_struct *conn,
int smb_reverb = SVAL(inbuf,smb_vwv0);
int seq_num;
unsigned int data_len = smb_buflen(inbuf);
- int outsize = set_message(inbuf,outbuf,1,data_len,True);
+ int outsize = set_message(outbuf,1,data_len,True);
START_PROFILE(SMBecho);
if (data_len > BUFFER_SIZE) {
@@ -3643,7 +3578,7 @@ int reply_echo(connection_struct *conn,
for (seq_num =1 ; seq_num <= smb_reverb ; seq_num++) {
SSVAL(outbuf,smb_vwv0,seq_num);
- smb_setlen(inbuf,outbuf,outsize - 4);
+ smb_setlen(outbuf,outsize - 4);
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
@@ -3684,7 +3619,7 @@ int reply_printopen(connection_struct *conn,
return(ERROR_NT(status));
}
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fsp->fnum);
DEBUG(3,("openprint fd=%d fnum=%d\n",
@@ -3701,7 +3636,7 @@ int reply_printopen(connection_struct *conn,
int reply_printclose(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- int outsize = set_message(inbuf,outbuf,0,0,False);
+ int outsize = set_message(outbuf,0,0,False);
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
NTSTATUS status;
START_PROFILE(SMBsplclose);
@@ -3734,7 +3669,7 @@ int reply_printclose(connection_struct *conn,
int reply_printqueue(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
- int outsize = set_message(inbuf,outbuf,2,3,True);
+ int outsize = set_message(outbuf,2,3,True);
int max_count = SVAL(inbuf,smb_vwv0);
int start_index = SVAL(inbuf,smb_vwv1);
START_PROFILE(SMBsplretq);
@@ -3782,7 +3717,7 @@ int reply_printqueue(connection_struct *conn,
}
if (count > 0) {
- outsize = set_message(inbuf,outbuf,2,28*count+3,False);
+ outsize = set_message(outbuf,2,28*count+3,False);
SSVAL(outbuf,smb_vwv0,count);
SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1));
SCVAL(smb_buf(outbuf),0,1);
@@ -3805,7 +3740,7 @@ int reply_printqueue(connection_struct *conn,
int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)
{
int numtowrite;
- int outsize = set_message(inbuf,outbuf,0,0,False);
+ int outsize = set_message(outbuf,0,0,False);
char *data;
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
@@ -3848,9 +3783,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
START_PROFILE(SMBmkdir);
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
- smb_buf(inbuf) + 1, sizeof(directory), 0,
- STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmkdir);
return ERROR_NT(status);
@@ -3898,7 +3831,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
DEBUG( 3, ( "mkdir %s ret=%d\n", directory, outsize ) );
@@ -4091,9 +4024,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
NTSTATUS status;
START_PROFILE(SMBrmdir);
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory,
- smb_buf(inbuf) + 1, sizeof(directory), 0,
- STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, directory, smb_buf(inbuf) + 1, sizeof(directory), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBrmdir);
return ERROR_NT(status);
@@ -4127,7 +4058,7 @@ int reply_rmdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
DEBUG( 3, ( "rmdir %s\n", directory ) );
@@ -4225,15 +4156,13 @@ static BOOL resolve_wildcards(const char *name1, char *name2)
asynchronously.
****************************************************************************/
-static void rename_open_files(connection_struct *conn,
- struct share_mode_lock *lck,
- const char *newname)
+static void rename_open_files(connection_struct *conn, struct share_mode_lock *lck,
+ SMB_DEV_T dev, SMB_INO_T inode, const char *newname)
{
files_struct *fsp;
BOOL did_rename = False;
- for(fsp = file_find_di_first(lck->id); fsp;
- fsp = file_find_di_next(fsp)) {
+ for(fsp = file_find_di_first(dev, inode); fsp; fsp = file_find_di_next(fsp)) {
/* fsp_name is a relative path under the fsp. To change this for other
sharepaths we need to manipulate relative paths. */
/* TODO - create the absolute path and manipulate the newname
@@ -4241,21 +4170,20 @@ static void rename_open_files(connection_struct *conn,
if (fsp->conn != conn) {
continue;
}
- DEBUG(10,("rename_open_files: renaming file fnum %d (file_id %s) from %s -> %s\n",
- fsp->fnum, file_id_static_string(&fsp->file_id),
+ DEBUG(10,("rename_open_files: renaming file fnum %d (dev = %x, inode = %.0f) from %s -> %s\n",
+ fsp->fnum, (unsigned int)fsp->dev, (double)fsp->inode,
fsp->fsp_name, newname ));
string_set(&fsp->fsp_name, newname);
did_rename = True;
}
if (!did_rename) {
- DEBUG(10,("rename_open_files: no open files on file_id %s for %s\n",
- file_id_static_string(&lck->id), newname ));
+ DEBUG(10,("rename_open_files: no open files on dev %x, inode %.0f for %s\n",
+ (unsigned int)dev, (double)inode, newname ));
}
/* Send messages to all smbd's (not ourself) that the name has changed. */
- rename_share_filename(smbd_messaging_context(), lck, conn->connectpath,
- newname);
+ rename_share_filename(lck, conn->connectpath, newname);
}
/****************************************************************************
@@ -4287,59 +4215,17 @@ static BOOL rename_path_prefix_equal(const char *src, const char *dest)
return ((memcmp(psrc, pdst, slen) == 0) && pdst[slen] == '/');
}
-/*
- * Do the notify calls from a rename
- */
-
-static void notify_rename(connection_struct *conn, BOOL is_dir,
- const char *oldpath, const char *newpath)
-{
- char *olddir, *newdir;
- const char *oldname, *newname;
- uint32 mask;
-
- mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
- : FILE_NOTIFY_CHANGE_FILE_NAME;
-
- if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
- || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
- TALLOC_FREE(olddir);
- return;
- }
-
- if (strcmp(olddir, newdir) == 0) {
- notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
- notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
- }
- else {
- notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
- notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
- }
- TALLOC_FREE(olddir);
- TALLOC_FREE(newdir);
-
- /* this is a strange one. w2k3 gives an additional event for
- CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
- files, but not directories */
- if (!is_dir) {
- notify_fname(conn, NOTIFY_ACTION_MODIFIED,
- FILE_NOTIFY_CHANGE_ATTRIBUTES
- |FILE_NOTIFY_CHANGE_CREATION,
- newpath);
- }
-}
-
/****************************************************************************
Rename an open file - given an fsp.
****************************************************************************/
NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstring newname, uint32 attrs, BOOL replace_if_exists)
{
- SMB_STRUCT_STAT sbuf, sbuf1;
+ SMB_STRUCT_STAT sbuf;
pstring newname_last_component;
NTSTATUS status = NT_STATUS_OK;
+ BOOL dest_exists;
struct share_mode_lock *lck = NULL;
- BOOL dst_exists;
ZERO_STRUCT(sbuf);
@@ -4407,22 +4293,14 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
return NT_STATUS_OK;
}
- /*
- * Have vfs_object_exist also fill sbuf1
- */
- dst_exists = vfs_object_exist(conn, newname, &sbuf1);
+ dest_exists = vfs_object_exist(conn,newname,NULL);
- if(!replace_if_exists && dst_exists) {
+ if(!replace_if_exists && dest_exists) {
DEBUG(3,("rename_internals_fsp: dest exists doing rename %s -> %s\n",
fsp->fsp_name,newname));
return NT_STATUS_OBJECT_NAME_COLLISION;
}
- if (dst_exists && file_find_di_first(file_id_sbuf(&sbuf1)) != NULL) {
- DEBUG(3, ("rename_internals_fsp: Target file open\n"));
- return NT_STATUS_ACCESS_DENIED;
- }
-
/* Ensure we have a valid stat struct for the source. */
if (fsp->fh->fd != -1) {
if (SMB_VFS_FSTAT(fsp,fsp->fh->fd,&sbuf) == -1) {
@@ -4434,7 +4312,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
}
}
- status = can_rename(conn, fsp, attrs, &sbuf);
+ status = can_rename(conn,fsp->fsp_name,attrs,&sbuf,True);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(3,("rename_internals_fsp: Error %s rename %s -> %s\n",
@@ -4448,14 +4326,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
return NT_STATUS_ACCESS_DENIED;
}
- lck = get_share_mode_lock(NULL, fsp->file_id, NULL, NULL);
-
- /*
- * We have the file open ourselves, so not being able to get the
- * corresponding share mode lock is a fatal error.
- */
-
- SMB_ASSERT(lck != NULL);
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
if(SMB_VFS_RENAME(conn,fsp->fsp_name, newname) == 0) {
uint32 create_options = fsp->fh->private_options;
@@ -4463,9 +4334,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
DEBUG(3,("rename_internals_fsp: succeeded doing rename on %s -> %s\n",
fsp->fsp_name,newname));
- rename_open_files(conn, lck, newname);
-
- notify_rename(conn, fsp->is_directory, fsp->fsp_name, newname);
+ rename_open_files(conn, lck, fsp->dev, fsp->inode, newname);
/*
* A rename acts as a new file create w.r.t. allowing an initial delete
@@ -4505,12 +4374,54 @@ NTSTATUS rename_internals_fsp(connection_struct *conn, files_struct *fsp, pstrin
return status;
}
+/*
+ * Do the notify calls from a rename
+ */
+
+static void notify_rename(connection_struct *conn, BOOL is_dir,
+ const char *oldpath, const char *newpath)
+{
+ char *olddir, *newdir;
+ const char *oldname, *newname;
+ uint32 mask;
+
+ mask = is_dir ? FILE_NOTIFY_CHANGE_DIR_NAME
+ : FILE_NOTIFY_CHANGE_FILE_NAME;
+
+ if (!parent_dirname_talloc(NULL, oldpath, &olddir, &oldname)
+ || !parent_dirname_talloc(NULL, newpath, &newdir, &newname)) {
+ TALLOC_FREE(olddir);
+ return;
+ }
+
+ if (strcmp(olddir, newdir) == 0) {
+ notify_fname(conn, NOTIFY_ACTION_OLD_NAME, mask, oldpath);
+ notify_fname(conn, NOTIFY_ACTION_NEW_NAME, mask, newpath);
+ }
+ else {
+ notify_fname(conn, NOTIFY_ACTION_REMOVED, mask, oldpath);
+ notify_fname(conn, NOTIFY_ACTION_ADDED, mask, newpath);
+ }
+ TALLOC_FREE(olddir);
+ TALLOC_FREE(newdir);
+
+ /* this is a strange one. w2k3 gives an additional event for
+ CHANGE_ATTRIBUTES and CHANGE_CREATION on the new file when renaming
+ files, but not directories */
+ if (!is_dir) {
+ notify_fname(conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_ATTRIBUTES
+ |FILE_NOTIFY_CHANGE_CREATION,
+ newpath);
+ }
+}
+
/****************************************************************************
The guts of the rename command, split out so it may be called by the NT SMB
code.
****************************************************************************/
-NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
+NTSTATUS rename_internals(connection_struct *conn,
pstring name,
pstring newname,
uint32 attrs,
@@ -4526,6 +4437,7 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
int count=0;
NTSTATUS status = NT_STATUS_OK;
SMB_STRUCT_STAT sbuf1, sbuf2;
+ struct share_mode_lock *lck = NULL;
struct smb_Dir *dir_hnd = NULL;
const char *dname;
long offset = 0;
@@ -4580,8 +4492,6 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
}
if (!src_has_wild) {
- files_struct *fsp;
-
/*
* No wildcards - just process the one file.
*/
@@ -4608,6 +4518,12 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
conn->short_case_preserve, directory,
newname, last_component_dest, is_short_name));
+ /* Ensure the source name is valid for us to access. */
+ status = check_name(conn, directory);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
/* The dest name still may have wildcards. */
if (dest_has_wild) {
if (!resolve_wildcards(directory,newname)) {
@@ -4617,34 +4533,133 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
}
}
- ZERO_STRUCT(sbuf1);
- SMB_VFS_STAT(conn, directory, &sbuf1);
-
- status = S_ISDIR(sbuf1.st_mode) ?
- open_directory(conn, req, directory, &sbuf1,
- DELETE_ACCESS,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN, 0, 0, NULL,
- &fsp)
- : open_file_ntcreate(conn, req, directory, &sbuf1,
- DELETE_ACCESS,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN, 0, 0, 0, NULL,
- &fsp);
+ /*
+ * Check for special case with case preserving and not
+ * case sensitive, if directory and newname are identical,
+ * and the old last component differs from the original
+ * last component only by case, then we should allow
+ * the rename (user is trying to change the case of the
+ * filename).
+ */
+ if((conn->case_sensitive == False) &&
+ (((conn->case_preserve == True) &&
+ (is_short_name == False)) ||
+ ((conn->short_case_preserve == True) &&
+ (is_short_name == True))) &&
+ strcsequal(directory, newname)) {
+ pstring modified_last_component;
+
+ /*
+ * Get the last component of the modified name.
+ * Note that we guarantee that newname contains a '/'
+ * character above.
+ */
+ p = strrchr_m(newname,'/');
+ pstrcpy(modified_last_component,p+1);
+
+ if(strcsequal(modified_last_component,
+ last_component_dest) == False) {
+ /*
+ * Replace the modified last component with
+ * the original.
+ */
+ pstrcpy(p+1, last_component_dest);
+ }
+ }
+
+ /* Ensure the dest name is valid for us to access. */
+ status = check_name(conn, newname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /*
+ * The source object must exist.
+ */
+
+ if (!vfs_object_exist(conn, directory, &sbuf1)) {
+ DEBUG(3, ("rename_internals: source doesn't exist "
+ "doing rename %s -> %s\n",
+ directory,newname));
+
+ if (errno == ENOTDIR || errno == EISDIR
+ || errno == ENOENT) {
+ /*
+ * Must return different errors depending on
+ * whether the parent directory existed or
+ * not.
+ */
+
+ p = strrchr_m(directory, '/');
+ if (!p)
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ *p = '\0';
+ if (vfs_object_exist(conn, directory, NULL))
+ return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ return NT_STATUS_OBJECT_PATH_NOT_FOUND;
+ }
+ status = map_nt_error_from_unix(errno);
+ DEBUG(3, ("rename_internals: Error %s rename %s -> "
+ "%s\n", nt_errstr(status), directory,
+ newname));
+
+ return status;
+ }
+
+ status = can_rename(conn,directory,attrs,&sbuf1,False);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("Could not open rename source %s: %s\n",
- directory, nt_errstr(status)));
+ DEBUG(3,("rename_internals: Error %s rename %s -> "
+ "%s\n", nt_errstr(status), directory,
+ newname));
return status;
}
- status = rename_internals_fsp(conn, fsp, newname, attrs,
- replace_if_exists);
+ /*
+ * If the src and dest names are identical - including case,
+ * don't do the rename, just return success.
+ */
- close_file(fsp, NORMAL_CLOSE);
+ if (strcsequal(directory, newname)) {
+ DEBUG(3, ("rename_internals: identical names in "
+ "rename %s - returning success\n",
+ directory));
+ return NT_STATUS_OK;
+ }
+
+ if(!replace_if_exists && vfs_object_exist(conn,newname,NULL)) {
+ DEBUG(3,("rename_internals: dest exists doing "
+ "rename %s -> %s\n", directory, newname));
+ return NT_STATUS_OBJECT_NAME_COLLISION;
+ }
+
+ if (rename_path_prefix_equal(directory, newname)) {
+ return NT_STATUS_SHARING_VIOLATION;
+ }
- DEBUG(3, ("rename_internals: Error %s rename %s -> %s\n",
- nt_errstr(status), directory,newname));
+ lck = get_share_mode_lock(NULL, sbuf1.st_dev, sbuf1.st_ino,
+ NULL, NULL);
+
+ if(SMB_VFS_RENAME(conn,directory, newname) == 0) {
+ DEBUG(3,("rename_internals: succeeded doing rename "
+ "on %s -> %s\n", directory, newname));
+ rename_open_files(conn, lck, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
+ TALLOC_FREE(lck);
+ notify_rename(conn, S_ISDIR(sbuf1.st_mode),
+ directory, newname);
+ return NT_STATUS_OK;
+ }
+
+ TALLOC_FREE(lck);
+ if (errno == ENOTDIR || errno == EISDIR) {
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
+ } else {
+ status = map_nt_error_from_unix(errno);
+ }
+
+ DEBUG(3,("rename_internals: Error %s rename %s -> %s\n",
+ nt_errstr(status), directory,newname));
return status;
}
@@ -4673,7 +4688,6 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
*/
while ((dname = ReadDirName(dir_hnd, &offset))) {
- files_struct *fsp;
pstring fname;
BOOL sysdir_entry = False;
@@ -4703,8 +4717,26 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
break;
}
+ status = NT_STATUS_ACCESS_DENIED;
slprintf(fname, sizeof(fname)-1, "%s/%s", directory, dname);
+ /* Ensure the source name is valid for us to access. */
+ status = check_name(conn, fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ if (!vfs_object_exist(conn, fname, &sbuf1)) {
+ status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ DEBUG(6, ("rename %s failed. Error %s\n",
+ fname, nt_errstr(status)));
+ continue;
+ }
+ status = can_rename(conn,fname,attrs,&sbuf1,False);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(6, ("rename %s refused\n", fname));
+ continue;
+ }
pstrcpy(destname,newname);
if (!resolve_wildcards(fname,destname)) {
@@ -4713,42 +4745,41 @@ NTSTATUS rename_internals(connection_struct *conn, struct smb_request *req,
continue;
}
- ZERO_STRUCT(sbuf1);
- SMB_VFS_STAT(conn, fname, &sbuf1);
-
- status = S_ISDIR(sbuf1.st_mode) ?
- open_directory(conn, req, fname, &sbuf1,
- DELETE_ACCESS,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN, 0, 0, NULL,
- &fsp)
- : open_file_ntcreate(conn, req, fname, &sbuf1,
- DELETE_ACCESS,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN, 0, 0, 0, NULL,
- &fsp);
-
+ /* Ensure the dest name is valid for us to access. */
+ status = check_name(conn, destname);
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3,("rename_internals: open_file_ntcreate "
- "returned %s rename %s -> %s\n",
- nt_errstr(status), directory, newname));
- break;
+ return status;
}
- status = rename_internals_fsp(conn, fsp, destname, attrs,
- replace_if_exists);
-
- close_file(fsp, NORMAL_CLOSE);
+ if (strcsequal(fname,destname)) {
+ DEBUG(3,("rename_internals: identical names "
+ "in wildcard rename %s - success\n",
+ fname));
+ count++;
+ status = NT_STATUS_OK;
+ continue;
+ }
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3, ("rename_internals_fsp returned %s for "
- "rename %s -> %s\n", nt_errstr(status),
- directory, newname));
- break;
+ if (!replace_if_exists && vfs_file_exist(conn,destname, NULL)) {
+ DEBUG(6,("file_exist %s\n", destname));
+ status = NT_STATUS_OBJECT_NAME_COLLISION;
+ continue;
+ }
+
+ if (rename_path_prefix_equal(fname, destname)) {
+ return NT_STATUS_SHARING_VIOLATION;
}
- count++;
+ lck = get_share_mode_lock(NULL, sbuf1.st_dev,
+ sbuf1.st_ino, NULL, NULL);
+ if (!SMB_VFS_RENAME(conn,fname,destname)) {
+ rename_open_files(conn, lck, sbuf1.st_dev,
+ sbuf1.st_ino, newname);
+ count++;
+ status = NT_STATUS_OK;
+ }
+ TALLOC_FREE(lck);
DEBUG(3,("rename_internals: doing rename on %s -> "
"%s\n",fname,destname));
}
@@ -4776,24 +4807,17 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
NTSTATUS status;
BOOL src_has_wcard = False;
BOOL dest_has_wcard = False;
- struct smb_request req;
START_PROFILE(SMBmv);
- init_smb_request(&req, (uint8 *)inbuf);
-
p = smb_buf(inbuf) + 1;
- p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
- sizeof(name), 0, STR_TERMINATE, &status,
- &src_has_wcard);
+ p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &src_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
}
p++;
- p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
- sizeof(newname), 0, STR_TERMINATE, &status,
- &dest_has_wcard);
+ p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
return ERROR_NT(status);
@@ -4819,8 +4843,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
DEBUG(3,("reply_mv : %s -> %s\n",name,newname));
- status = rename_internals(conn, &req, name, newname, attrs, False,
- src_has_wcard, dest_has_wcard);
+ status = rename_internals(conn, name, newname, attrs, False, src_has_wcard, dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBmv);
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
@@ -4830,7 +4853,7 @@ int reply_mv(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_NT(status);
}
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
END_PROFILE(SMBmv);
return(outsize);
@@ -4884,7 +4907,7 @@ NTSTATUS copy_file(connection_struct *conn,
}
}
- status = open_file_ntcreate(conn, NULL, src, &src_sbuf,
+ status = open_file_ntcreate(conn,src,&src_sbuf,
FILE_GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
@@ -4902,7 +4925,7 @@ NTSTATUS copy_file(connection_struct *conn,
ZERO_STRUCTP(&sbuf2);
}
- status = open_file_ntcreate(conn, NULL, dest, &sbuf2,
+ status = open_file_ntcreate(conn,dest,&sbuf2,
FILE_GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
new_create_disposition,
@@ -4982,16 +5005,12 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
*directory = *mask = 0;
p = smb_buf(inbuf);
- p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), name, p,
- sizeof(name), 0, STR_TERMINATE, &status,
- &source_has_wild);
+ p += srvstr_get_path_wcard(inbuf, name, p, sizeof(name), 0, STR_TERMINATE, &status, &source_has_wild);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
return ERROR_NT(status);
}
- p += srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, p,
- sizeof(newname), 0, STR_TERMINATE, &status,
- &dest_has_wild);
+ p += srvstr_get_path_wcard(inbuf, newname, p, sizeof(newname), 0, STR_TERMINATE, &status, &dest_has_wild);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(SMBcopy);
return ERROR_NT(status);
@@ -5181,7 +5200,7 @@ int reply_copy(connection_struct *conn, char *inbuf,char *outbuf, int dum_size,
return ERROR_DOS(ERRDOS,error);
}
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,count);
END_PROFILE(SMBcopy);
@@ -5207,9 +5226,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), newdir,
- smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE,
- &status);
+ srvstr_get_path(inbuf, newdir, smb_buf(inbuf) + 1, sizeof(newdir), 0, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
END_PROFILE(pathworks_setdir);
return ERROR_NT(status);
@@ -5232,7 +5249,7 @@ int reply_setdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size
set_conn_connectpath(conn,newdir);
}
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
SCVAL(outbuf,smb_reh,CVAL(inbuf,smb_reh));
DEBUG(3,("setdir %s\n", newdir));
@@ -5509,8 +5526,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
"pid %u, file %s\n", (double)offset, (double)count,
(unsigned int)lock_pid, fsp->fsp_name ));
- status = do_unlock(smbd_messaging_context(),
- fsp,
+ status = do_unlock(fsp,
lock_pid,
count,
offset,
@@ -5584,8 +5600,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
struct byte_range_lock *br_lck;
uint32 block_smbpid;
- br_lck = do_lock(smbd_messaging_context(),
- fsp,
+ br_lck = do_lock(fsp,
lock_pid,
count,
offset,
@@ -5673,8 +5688,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_DOS(ERRDOS,ERRnoaccess);
}
- do_unlock(smbd_messaging_context(),
- fsp,
+ do_unlock(fsp,
lock_pid,
count,
offset,
@@ -5684,7 +5698,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_NT(status);
}
- set_message(inbuf,outbuf,2,0,True);
+ set_message(outbuf,2,0,True);
DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n",
fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks));
@@ -5720,7 +5734,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
return ERROR_DOS(ERRSRV,ERRuseSTD);
}
- outsize = set_message(inbuf,outbuf,8,0,True);
+ outsize = set_message(outbuf,8,0,True);
CHECK_FSP(fsp,conn);
if (!CHECK_READ(fsp,inbuf)) {
@@ -5756,7 +5770,7 @@ int reply_readbmpx(connection_struct *conn, char *inbuf,char *outbuf,int length,
if (nread < (ssize_t)N)
tcount = total_read + nread;
- set_message(inbuf,outbuf,8,nread+pad,False);
+ set_message(outbuf,8,nread+pad,False);
SIVAL(outbuf,smb_vwv0,startpos);
SSVAL(outbuf,smb_vwv2,tcount);
SSVAL(outbuf,smb_vwv6,nread);
@@ -5785,7 +5799,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBsetattrE);
- outsize = set_message(inbuf,outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
if(!fsp || (fsp->conn != conn)) {
END_PROFILE(SMBsetattrE);
@@ -5923,7 +5937,7 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
SMBwritebmpx */
SCVAL(outbuf,smb_com,SMBwriteBmpx);
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SSVALS(outbuf,smb_vwv0,-1); /* We don't support smb_remaining */
@@ -5932,13 +5946,13 @@ int reply_writebmpx(connection_struct *conn, char *inbuf,char *outbuf, int size,
if (write_through && tcount==nwritten) {
/* We need to send both a primary and a secondary response */
- smb_setlen(inbuf,outbuf,outsize - 4);
+ smb_setlen(outbuf,outsize - 4);
show_msg(outbuf);
if (!send_smb(smbd_server_fd(),outbuf))
exit_server_cleanly("reply_writebmpx: send_smb failed.");
/* Now the secondary */
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SCVAL(outbuf,smb_com,SMBwritec);
SSVAL(outbuf,smb_vwv0,nwritten);
}
@@ -6025,7 +6039,7 @@ int reply_writebs(connection_struct *conn, char *inbuf,char *outbuf, int dum_siz
wbms->wr_total_written += nwritten;
if(wbms->wr_total_written >= tcount) {
if (write_through) {
- outsize = set_message(inbuf,outbuf,1,0,True);
+ outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,wbms->wr_total_written);
send_response = True;
}
@@ -6055,7 +6069,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
files_struct *fsp = file_fsp(inbuf,smb_vwv0);
START_PROFILE(SMBgetattrE);
- outsize = set_message(inbuf,outbuf,11,0,True);
+ outsize = set_message(outbuf,11,0,True);
if(!fsp || (fsp->conn != conn)) {
END_PROFILE(SMBgetattrE);
diff --git a/source/smbd/seal.c b/source/smbd/seal.c
deleted file mode 100644
index 5d8ef9b63c8..00000000000
--- a/source/smbd/seal.c
+++ /dev/null
@@ -1,704 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- SMB Transport encryption (sealing) code - server code.
- Copyright (C) Jeremy Allison 2007.
-
- 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 2 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, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-
-/******************************************************************************
- Server side encryption.
-******************************************************************************/
-
-/******************************************************************************
- Global server state.
-******************************************************************************/
-
-struct smb_srv_trans_enc_ctx {
- struct smb_trans_enc_state *es;
- AUTH_NTLMSSP_STATE *auth_ntlmssp_state; /* Must be kept in sync with pointer in ec->ntlmssp_state. */
-};
-
-static struct smb_srv_trans_enc_ctx *partial_srv_trans_enc_ctx;
-static struct smb_srv_trans_enc_ctx *srv_trans_enc_ctx;
-
-/******************************************************************************
- Is server encryption on ?
-******************************************************************************/
-
-BOOL srv_encryption_on(void)
-{
- if (srv_trans_enc_ctx) {
- return common_encryption_on(srv_trans_enc_ctx->es);
- }
- return False;
-}
-
-/******************************************************************************
- Create an auth_ntlmssp_state and ensure pointer copy is correct.
-******************************************************************************/
-
-static NTSTATUS make_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec)
-{
- NTSTATUS status = auth_ntlmssp_start(&ec->auth_ntlmssp_state);
- if (!NT_STATUS_IS_OK(status)) {
- return nt_status_squash(status);
- }
-
- /*
- * We must remember to update the pointer copy for the common
- * functions after any auth_ntlmssp_start/auth_ntlmssp_end.
- */
- ec->es->s.ntlmssp_state = ec->auth_ntlmssp_state->ntlmssp_state;
- return status;
-}
-
-/******************************************************************************
- Destroy an auth_ntlmssp_state and ensure pointer copy is correct.
-******************************************************************************/
-
-static void destroy_auth_ntlmssp(struct smb_srv_trans_enc_ctx *ec)
-{
- /*
- * We must remember to update the pointer copy for the common
- * functions after any auth_ntlmssp_start/auth_ntlmssp_end.
- */
-
- if (ec->auth_ntlmssp_state) {
- auth_ntlmssp_end(&ec->auth_ntlmssp_state);
- /* The auth_ntlmssp_end killed this already. */
- ec->es->s.ntlmssp_state = NULL;
- }
-}
-
-#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
-
-/******************************************************************************
- Import a name.
-******************************************************************************/
-
-static NTSTATUS get_srv_gss_creds(const char *service,
- const char *name,
- gss_cred_usage_t cred_type,
- gss_cred_id_t *p_srv_cred)
-{
- OM_uint32 ret;
- OM_uint32 min;
- gss_name_t srv_name;
- gss_buffer_desc input_name;
- char *host_princ_s = NULL;
- NTSTATUS status = NT_STATUS_OK;
-
- gss_OID_desc nt_hostbased_service =
- {10, CONST_DISCARD(char *,"\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04")};
-
- asprintf(&host_princ_s, "%s@%s", service, name);
- if (host_princ_s == NULL) {
- return NT_STATUS_NO_MEMORY;
- }
-
- input_name.value = host_princ_s;
- input_name.length = strlen(host_princ_s) + 1;
-
- ret = gss_import_name(&min,
- &input_name,
- &nt_hostbased_service,
- &srv_name);
-
- DEBUG(10,("get_srv_gss_creds: imported name %s\n",
- host_princ_s ));
-
- if (ret != GSS_S_COMPLETE) {
- SAFE_FREE(host_princ_s);
- return map_nt_error_from_gss(ret, min);
- }
-
- /*
- * We're accessing the krb5.keytab file here.
- * ensure we have permissions to do so.
- */
- become_root();
-
- ret = gss_acquire_cred(&min,
- srv_name,
- GSS_C_INDEFINITE,
- GSS_C_NULL_OID_SET,
- cred_type,
- p_srv_cred,
- NULL,
- NULL);
- unbecome_root();
-
- if (ret != GSS_S_COMPLETE) {
- ADS_STATUS adss = ADS_ERROR_GSS(ret, min);
- DEBUG(10,("get_srv_gss_creds: gss_acquire_cred failed with %s\n",
- ads_errstr(adss)));
- status = map_nt_error_from_gss(ret, min);
- }
-
- SAFE_FREE(host_princ_s);
- gss_release_name(&min, &srv_name);
- return status;
-}
-
-/******************************************************************************
- Create a gss state.
- Try and get the cifs/server@realm principal first, then fall back to
- host/server@realm.
-******************************************************************************/
-
-static NTSTATUS make_auth_gss(struct smb_srv_trans_enc_ctx *ec)
-{
- NTSTATUS status;
- gss_cred_id_t srv_cred;
- fstring fqdn;
-
- name_to_fqdn(fqdn, global_myname());
- strlower_m(fqdn);
-
- status = get_srv_gss_creds("cifs", fqdn, GSS_C_ACCEPT, &srv_cred);
- if (!NT_STATUS_IS_OK(status)) {
- status = get_srv_gss_creds("host", fqdn, GSS_C_ACCEPT, &srv_cred);
- if (!NT_STATUS_IS_OK(status)) {
- return nt_status_squash(status);
- }
- }
-
- ec->es->s.gss_state = SMB_MALLOC_P(struct smb_tran_enc_state_gss);
- if (!ec->es->s.gss_state) {
- OM_uint32 min;
- gss_release_cred(&min, &srv_cred);
- return NT_STATUS_NO_MEMORY;
- }
- ZERO_STRUCTP(ec->es->s.gss_state);
- ec->es->s.gss_state->creds = srv_cred;
-
- /* No context yet. */
- ec->es->s.gss_state->gss_ctx = GSS_C_NO_CONTEXT;
-
- return NT_STATUS_OK;
-}
-#endif
-
-/******************************************************************************
- Shutdown a server encryption context.
-******************************************************************************/
-
-static void srv_free_encryption_context(struct smb_srv_trans_enc_ctx **pp_ec)
-{
- struct smb_srv_trans_enc_ctx *ec = *pp_ec;
-
- if (!ec) {
- return;
- }
-
- if (ec->es) {
- switch (ec->es->smb_enc_type) {
- case SMB_TRANS_ENC_NTLM:
- destroy_auth_ntlmssp(ec);
- break;
-#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
- case SMB_TRANS_ENC_GSS:
- break;
-#endif
- }
- common_free_encryption_state(&ec->es);
- }
-
- SAFE_FREE(ec);
- *pp_ec = NULL;
-}
-
-/******************************************************************************
- Create a server encryption context.
-******************************************************************************/
-
-static NTSTATUS make_srv_encryption_context(enum smb_trans_enc_type smb_enc_type, struct smb_srv_trans_enc_ctx **pp_ec)
-{
- struct smb_srv_trans_enc_ctx *ec;
-
- *pp_ec = NULL;
-
- ec = SMB_MALLOC_P(struct smb_srv_trans_enc_ctx);
- if (!ec) {
- return NT_STATUS_NO_MEMORY;
- }
- ZERO_STRUCTP(partial_srv_trans_enc_ctx);
- ec->es = SMB_MALLOC_P(struct smb_trans_enc_state);
- if (!ec->es) {
- SAFE_FREE(ec);
- return NT_STATUS_NO_MEMORY;
- }
- ZERO_STRUCTP(ec->es);
- ec->es->smb_enc_type = smb_enc_type;
- switch (smb_enc_type) {
- case SMB_TRANS_ENC_NTLM:
- {
- NTSTATUS status = make_auth_ntlmssp(ec);
- if (!NT_STATUS_IS_OK(status)) {
- srv_free_encryption_context(&ec);
- return status;
- }
- }
- break;
-
-#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
- case SMB_TRANS_ENC_GSS:
- /* Acquire our credentials by calling gss_acquire_cred here. */
- {
- NTSTATUS status = make_auth_gss(ec);
- if (!NT_STATUS_IS_OK(status)) {
- srv_free_encryption_context(&ec);
- return status;
- }
- }
- break;
-#endif
- default:
- srv_free_encryption_context(&ec);
- return NT_STATUS_INVALID_PARAMETER;
- }
- *pp_ec = ec;
- return NT_STATUS_OK;
-}
-
-/******************************************************************************
- Free an encryption-allocated buffer.
-******************************************************************************/
-
-void srv_free_enc_buffer(char *buf)
-{
- /* We know this is an smb buffer, and we
- * didn't malloc, only copy, for a keepalive,
- * so ignore session keepalives. */
-
- if(CVAL(buf,0) == SMBkeepalive) {
- return;
- }
-
- if (srv_trans_enc_ctx) {
- common_free_enc_buffer(srv_trans_enc_ctx->es, buf);
- }
-}
-
-/******************************************************************************
- Decrypt an incoming buffer.
-******************************************************************************/
-
-NTSTATUS srv_decrypt_buffer(char *buf)
-{
- /* Ignore session keepalives. */
- if(CVAL(buf,0) == SMBkeepalive) {
- return NT_STATUS_OK;
- }
-
- if (srv_trans_enc_ctx) {
- return common_decrypt_buffer(srv_trans_enc_ctx->es, buf);
- }
-
- return NT_STATUS_OK;
-}
-
-/******************************************************************************
- Encrypt an outgoing buffer. Return the encrypted pointer in buf_out.
-******************************************************************************/
-
-NTSTATUS srv_encrypt_buffer(char *buf, char **buf_out)
-{
- *buf_out = buf;
-
- /* Ignore session keepalives. */
- if(CVAL(buf,0) == SMBkeepalive) {
- return NT_STATUS_OK;
- }
-
- if (srv_trans_enc_ctx) {
- return common_encrypt_buffer(srv_trans_enc_ctx->es, buf, buf_out);
- }
- /* Not encrypting. */
- return NT_STATUS_OK;
-}
-
-/******************************************************************************
- Do the gss encryption negotiation. Parameters are in/out.
- Until success we do everything on the partial enc ctx.
-******************************************************************************/
-
-#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
-static NTSTATUS srv_enc_spnego_gss_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob)
-{
- OM_uint32 ret;
- OM_uint32 min;
- OM_uint32 flags = 0;
- gss_buffer_desc in_buf, out_buf;
- struct smb_tran_enc_state_gss *gss_state;
- DATA_BLOB auth_reply = data_blob_null;
- DATA_BLOB response = data_blob_null;
- NTSTATUS status;
-
- if (!partial_srv_trans_enc_ctx) {
- status = make_srv_encryption_context(SMB_TRANS_ENC_GSS, &partial_srv_trans_enc_ctx);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- }
-
- gss_state = partial_srv_trans_enc_ctx->es->s.gss_state;
-
- in_buf.value = secblob.data;
- in_buf.length = secblob.length;
-
- out_buf.value = NULL;
- out_buf.length = 0;
-
- become_root();
-
- ret = gss_accept_sec_context(&min,
- &gss_state->gss_ctx,
- gss_state->creds,
- &in_buf,
- GSS_C_NO_CHANNEL_BINDINGS,
- NULL,
- NULL, /* Ignore oids. */
- &out_buf, /* To return. */
- &flags,
- NULL, /* Ingore time. */
- NULL); /* Ignore delegated creds. */
- unbecome_root();
-
- status = gss_err_to_ntstatus(ret, min);
- if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
- return status;
- }
-
- /* Ensure we've got sign+seal available. */
- if (ret == GSS_S_COMPLETE) {
- if ((flags & (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) !=
- (GSS_C_INTEG_FLAG|GSS_C_CONF_FLAG|GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) {
- DEBUG(0,("srv_enc_spnego_gss_negotiate: quality of service not good enough "
- "for SMB sealing.\n"));
- gss_release_buffer(&min, &out_buf);
- return NT_STATUS_ACCESS_DENIED;
- }
- }
-
- auth_reply = data_blob(out_buf.value, out_buf.length);
- gss_release_buffer(&min, &out_buf);
-
- /* Wrap in SPNEGO. */
- response = spnego_gen_auth_response(&auth_reply, status, OID_KERBEROS5);
- data_blob_free(&auth_reply);
-
- SAFE_FREE(*ppdata);
- *ppdata = response.data;
- *p_data_size = response.length;
-
- return status;
-}
-#endif
-
-/******************************************************************************
- Do the NTLM SPNEGO (or raw) encryption negotiation. Parameters are in/out.
- Until success we do everything on the partial enc ctx.
-******************************************************************************/
-
-static NTSTATUS srv_enc_ntlm_negotiate(unsigned char **ppdata, size_t *p_data_size, DATA_BLOB secblob, BOOL spnego_wrap)
-{
- NTSTATUS status;
- DATA_BLOB chal = data_blob_null;
- DATA_BLOB response = data_blob_null;
-
- status = make_srv_encryption_context(SMB_TRANS_ENC_NTLM, &partial_srv_trans_enc_ctx);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, secblob, &chal);
-
- /* status here should be NT_STATUS_MORE_PROCESSING_REQUIRED
- * for success ... */
-
- if (spnego_wrap) {
- response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP);
- data_blob_free(&chal);
- } else {
- /* Return the raw blob. */
- response = chal;
- }
-
- SAFE_FREE(*ppdata);
- *ppdata = response.data;
- *p_data_size = response.length;
- return status;
-}
-
-/******************************************************************************
- Do the SPNEGO encryption negotiation. Parameters are in/out.
- Based off code in smbd/sesssionsetup.c
- Until success we do everything on the partial enc ctx.
-******************************************************************************/
-
-static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn,
- unsigned char **ppdata,
- size_t *p_data_size,
- unsigned char **pparam,
- size_t *p_param_size)
-{
- NTSTATUS status;
- DATA_BLOB blob = data_blob_null;
- DATA_BLOB secblob = data_blob_null;
- BOOL got_kerberos_mechanism = False;
-
- blob = data_blob_const(*ppdata, *p_data_size);
-
- status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism);
- if (!NT_STATUS_IS_OK(status)) {
- return nt_status_squash(status);
- }
-
- /* We should have no partial context at this point. */
-
- srv_free_encryption_context(&partial_srv_trans_enc_ctx);
-
-#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
- if (got_kerberos_mechanism && lp_use_kerberos_keytab() ) {
- status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob);
- } else
-#endif
- {
- status = srv_enc_ntlm_negotiate(ppdata, p_data_size, secblob, True);
- }
-
- data_blob_free(&secblob);
-
- if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
- srv_free_encryption_context(&partial_srv_trans_enc_ctx);
- return nt_status_squash(status);
- }
-
- if (NT_STATUS_IS_OK(status)) {
- /* Return the context we're using for this encryption state. */
- if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
- return NT_STATUS_NO_MEMORY;
- }
- SSVAL(*pparam,0,partial_srv_trans_enc_ctx->es->enc_ctx_num);
- *p_param_size = 2;
- }
-
- return status;
-}
-
-/******************************************************************************
- Complete a SPNEGO encryption negotiation. Parameters are in/out.
- We only get this for a NTLM auth second stage.
-******************************************************************************/
-
-static NTSTATUS srv_enc_spnego_ntlm_auth(connection_struct *conn,
- unsigned char **ppdata,
- size_t *p_data_size,
- unsigned char **pparam,
- size_t *p_param_size)
-{
- NTSTATUS status;
- DATA_BLOB blob = data_blob_null;
- DATA_BLOB auth = data_blob_null;
- DATA_BLOB auth_reply = data_blob_null;
- DATA_BLOB response = data_blob_null;
- struct smb_srv_trans_enc_ctx *ec = partial_srv_trans_enc_ctx;
-
- /* We must have a partial context here. */
-
- if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) {
- srv_free_encryption_context(&partial_srv_trans_enc_ctx);
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- blob = data_blob_const(*ppdata, *p_data_size);
- if (!spnego_parse_auth(blob, &auth)) {
- srv_free_encryption_context(&partial_srv_trans_enc_ctx);
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- status = auth_ntlmssp_update(ec->auth_ntlmssp_state, auth, &auth_reply);
- data_blob_free(&auth);
-
- response = spnego_gen_auth_response(&auth_reply, status, OID_NTLMSSP);
- data_blob_free(&auth_reply);
-
- if (NT_STATUS_IS_OK(status)) {
- /* Return the context we're using for this encryption state. */
- if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
- return NT_STATUS_NO_MEMORY;
- }
- SSVAL(*pparam,0,ec->es->enc_ctx_num);
- *p_param_size = 2;
- }
-
- SAFE_FREE(*ppdata);
- *ppdata = response.data;
- *p_data_size = response.length;
- return status;
-}
-
-/******************************************************************************
- Raw NTLM encryption negotiation. Parameters are in/out.
- This function does both steps.
-******************************************************************************/
-
-static NTSTATUS srv_enc_raw_ntlm_auth(connection_struct *conn,
- unsigned char **ppdata,
- size_t *p_data_size,
- unsigned char **pparam,
- size_t *p_param_size)
-{
- NTSTATUS status;
- DATA_BLOB blob = data_blob_const(*ppdata, *p_data_size);
- DATA_BLOB response = data_blob_null;
- struct smb_srv_trans_enc_ctx *ec;
-
- if (!partial_srv_trans_enc_ctx) {
- /* This is the initial step. */
- status = srv_enc_ntlm_negotiate(ppdata, p_data_size, blob, False);
- if (!NT_STATUS_EQUAL(status,NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
- srv_free_encryption_context(&partial_srv_trans_enc_ctx);
- return nt_status_squash(status);
- }
- return status;
- }
-
- ec = partial_srv_trans_enc_ctx;
- if (!ec || !ec->es || ec->auth_ntlmssp_state == NULL || ec->es->smb_enc_type != SMB_TRANS_ENC_NTLM) {
- srv_free_encryption_context(&partial_srv_trans_enc_ctx);
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- /* Second step. */
- status = auth_ntlmssp_update(partial_srv_trans_enc_ctx->auth_ntlmssp_state, blob, &response);
-
- if (NT_STATUS_IS_OK(status)) {
- /* Return the context we're using for this encryption state. */
- if (!(*pparam = SMB_MALLOC_ARRAY(unsigned char, 2))) {
- return NT_STATUS_NO_MEMORY;
- }
- SSVAL(*pparam,0,ec->es->enc_ctx_num);
- *p_param_size = 2;
- }
-
- /* Return the raw blob. */
- SAFE_FREE(*ppdata);
- *ppdata = response.data;
- *p_data_size = response.length;
- return status;
-}
-
-/******************************************************************************
- Do the SPNEGO encryption negotiation. Parameters are in/out.
-******************************************************************************/
-
-NTSTATUS srv_request_encryption_setup(connection_struct *conn,
- unsigned char **ppdata,
- size_t *p_data_size,
- unsigned char **pparam,
- size_t *p_param_size)
-{
- unsigned char *pdata = *ppdata;
-
- SAFE_FREE(*pparam);
- *p_param_size = 0;
-
- if (*p_data_size < 1) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (pdata[0] == ASN1_APPLICATION(0)) {
- /* its a negTokenTarg packet */
- return srv_enc_spnego_negotiate(conn, ppdata, p_data_size, pparam, p_param_size);
- }
-
- if (pdata[0] == ASN1_CONTEXT(1)) {
- /* It's an auth packet */
- return srv_enc_spnego_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size);
- }
-
- /* Maybe it's a raw unwrapped auth ? */
- if (*p_data_size < 7) {
- return NT_STATUS_INVALID_PARAMETER;
- }
-
- if (strncmp((char *)pdata, "NTLMSSP", 7) == 0) {
- return srv_enc_raw_ntlm_auth(conn, ppdata, p_data_size, pparam, p_param_size);
- }
-
- DEBUG(1,("srv_request_encryption_setup: Unknown packet\n"));
-
- return NT_STATUS_LOGON_FAILURE;
-}
-
-/******************************************************************************
- Negotiation was successful - turn on server-side encryption.
-******************************************************************************/
-
-static NTSTATUS check_enc_good(struct smb_srv_trans_enc_ctx *ec)
-{
- if (!ec || !ec->es) {
- return NT_STATUS_LOGON_FAILURE;
- }
-
- if (ec->es->smb_enc_type == SMB_TRANS_ENC_NTLM) {
- if ((ec->es->s.ntlmssp_state->neg_flags & (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) !=
- (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL)) {
- return NT_STATUS_INVALID_PARAMETER;
- }
- }
- /* Todo - check gssapi case. */
-
- return NT_STATUS_OK;
-}
-
-/******************************************************************************
- Negotiation was successful - turn on server-side encryption.
-******************************************************************************/
-
-NTSTATUS srv_encryption_start(connection_struct *conn)
-{
- NTSTATUS status;
-
- /* Check that we are really doing sign+seal. */
- status = check_enc_good(partial_srv_trans_enc_ctx);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- /* Throw away the context we're using currently (if any). */
- srv_free_encryption_context(&srv_trans_enc_ctx);
-
- /* Steal the partial pointer. Deliberate shallow copy. */
- srv_trans_enc_ctx = partial_srv_trans_enc_ctx;
- srv_trans_enc_ctx->es->enc_on = True;
-
- partial_srv_trans_enc_ctx = NULL;
- return NT_STATUS_OK;
-}
-
-/******************************************************************************
- Shutdown all server contexts.
-******************************************************************************/
-
-void server_encryption_shutdown(void)
-{
- srv_free_encryption_context(&partial_srv_trans_enc_ctx);
- srv_free_encryption_context(&srv_trans_enc_ctx);
-}
diff --git a/source/smbd/sec_ctx.c b/source/smbd/sec_ctx.c
index 97842419d5c..be00db9adb8 100644
--- a/source/smbd/sec_ctx.c
+++ b/source/smbd/sec_ctx.c
@@ -192,7 +192,7 @@ BOOL push_sec_ctx(void)
if (sec_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) {
DEBUG(0, ("Security context stack overflow!\n"));
- smb_panic("Security context stack overflow!");
+ smb_panic("Security context stack overflow!\n");
}
/* Store previous user context */
@@ -228,70 +228,6 @@ BOOL push_sec_ctx(void)
}
/****************************************************************************
- Change UNIX security context. Calls panic if not successful so no return value.
-****************************************************************************/
-
-#ifndef HAVE_DARWIN_INITGROUPS
-
-/* Normal credential switch path. */
-
-static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups)
-{
- /* Start context switch */
- gain_root();
-#ifdef HAVE_SETGROUPS
- sys_setgroups(gid, ngroups, groups);
-#endif
- become_id(uid, gid);
- /* end context switch */
-}
-
-#else /* HAVE_DARWIN_INITGROUPS */
-
-/* The Darwin groups implementation is a little unusual. The list of
-* groups in the kernel credential is not exhaustive, but more like
-* a cache. The full group list is held in userspace and checked
-* dynamically.
-*
-* This is an optional mechanism, and setgroups(2) opts out
-* of it. That is, if you call setgroups, then the list of groups you
-* set are the only groups that are ever checked. This is not what we
-* want. We want to opt in to the dynamic resolution mechanism, so we
-* need to specify the uid of the user whose group list (cache) we are
-* setting.
-*
-* The Darwin rules are:
-* 1. Thou shalt setegid, initgroups and seteuid IN THAT ORDER
-* 2. Thou shalt not pass more that NGROUPS_MAX to initgroups
-* 3. Thou shalt leave the first entry in the groups list well alone
-*/
-
-#include <sys/syscall.h>
-
-static void set_unix_security_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups)
-{
- int max = groups_max();
-
- /* Start context switch */
- gain_root();
-
- become_gid(gid);
-
-
- if (syscall(SYS_initgroups, (ngroups > max) ? max : ngroups,
- groups, uid) == 1) {
- DEBUG(0, ("WARNING: failed to set group list "
- "(%d groups) for UID %ld: %s\n",
- ngroups, uid, strerror(errno)));
- }
-
- become_uid(uid);
- /* end context switch */
-}
-
-#endif /* HAVE_DARWIN_INITGROUPS */
-
-/****************************************************************************
Set the current security context to a given user.
****************************************************************************/
@@ -307,8 +243,11 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN
debug_nt_user_token(DBGC_CLASS, 5, token);
debug_unix_user_token(DBGC_CLASS, 5, uid, gid, ngroups, groups);
- /* Change uid, gid and supplementary group list. */
- set_unix_security_ctx(uid, gid, ngroups, groups);
+ gain_root();
+
+#ifdef HAVE_SETGROUPS
+ sys_setgroups(ngroups, groups);
+#endif
ctx_p->ut.ngroups = ngroups;
@@ -338,6 +277,8 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN
ctx_p->token = NULL;
}
+ become_id(uid, gid);
+
ctx_p->ut.uid = uid;
ctx_p->ut.gid = gid;
@@ -374,7 +315,7 @@ BOOL pop_sec_ctx(void)
if (sec_ctx_stack_ndx == 0) {
DEBUG(0, ("Security context stack underflow!\n"));
- smb_panic("Security context stack underflow!");
+ smb_panic("Security context stack underflow!\n");
}
ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];
@@ -393,13 +334,15 @@ BOOL pop_sec_ctx(void)
sec_ctx_stack_ndx--;
+ gain_root();
+
prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];
- /* Change uid, gid and supplementary group list. */
- set_unix_security_ctx(prev_ctx_p->ut.uid,
- prev_ctx_p->ut.gid,
- prev_ctx_p->ut.ngroups,
- prev_ctx_p->ut.groups);
+#ifdef HAVE_SETGROUPS
+ sys_setgroups(prev_ctx_p->ut.ngroups, prev_ctx_p->ut.groups);
+#endif
+
+ become_id(prev_ctx_p->ut.uid, prev_ctx_p->ut.gid);
/* Update current_user stuff */
diff --git a/source/smbd/server.c b/source/smbd/server.c
index edbd8798474..89cceae2a6d 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -4,7 +4,6 @@
Copyright (C) Andrew Tridgell 1992-1998
Copyright (C) Martin Pool 2002
Copyright (C) Jelmer Vernooij 2002-2003
- Copyright (C) James Peach 2007
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
@@ -67,7 +66,7 @@ struct event_context *smbd_event_context(void)
static struct event_context *ctx;
if (!ctx && !(ctx = event_context_init(NULL))) {
- smb_panic("Could not init smbd event context");
+ smb_panic("Could not init smbd event context\n");
}
return ctx;
}
@@ -78,7 +77,7 @@ struct messaging_context *smbd_messaging_context(void)
if (!ctx && !(ctx = messaging_init(NULL, server_id_self(),
smbd_event_context()))) {
- smb_panic("Could not init smbd messaging context");
+ smb_panic("Could not init smbd messaging context\n");
}
return ctx;
}
@@ -87,14 +86,10 @@ struct messaging_context *smbd_messaging_context(void)
What to do when smb.conf is updated.
********************************************************************/
-static void smb_conf_updated(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_type,
- struct server_id server_id,
- DATA_BLOB *data)
+static void smb_conf_updated(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
- DEBUG(10,("smb_conf_updated: Got message saying smb.conf was "
- "updated. Reloading.\n"));
+ DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n"));
reload_services(False);
}
@@ -103,13 +98,10 @@ static void smb_conf_updated(struct messaging_context *msg,
Delete a statcache entry.
********************************************************************/
-static void smb_stat_cache_delete(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_tnype,
- struct server_id server_id,
- DATA_BLOB *data)
+static void smb_stat_cache_delete(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
- const char *name = (const char *)data->data;
+ const char *name = (const char *)buf;
DEBUG(10,("smb_stat_cache_delete: delete name %s\n", name));
stat_cache_delete(name);
}
@@ -157,11 +149,9 @@ static void killkids(void)
somewhere else.
****************************************************************************/
-static void msg_sam_sync(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_type,
- struct server_id server_id,
- DATA_BLOB *data)
+static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid),
+ void *UNUSED(buf), size_t UNUSED(len),
+ void *private_data)
{
DEBUG(10, ("** sam sync message received, ignoring\n"));
}
@@ -171,18 +161,15 @@ static void msg_sam_sync(struct messaging_context *msg,
somewhere else.
****************************************************************************/
-static void msg_sam_repl(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_type,
- struct server_id server_id,
- DATA_BLOB *data)
+static void msg_sam_repl(int msg_type, struct process_id pid,
+ void *buf, size_t len, void *private_data)
{
uint32 low_serial;
- if (data->length != sizeof(low_serial))
+ if (len != sizeof(uint32))
return;
- low_serial = *((uint32 *)data->data);
+ low_serial = *((uint32 *)buf);
DEBUG(3, ("received sam replication message, serial = 0x%04x\n",
low_serial));
@@ -208,44 +195,38 @@ static BOOL open_sockets_inetd(void)
return True;
}
-static void msg_exit_server(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_type,
- struct server_id server_id,
- DATA_BLOB *data)
+static void msg_exit_server(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
DEBUG(3, ("got a SHUTDOWN message\n"));
exit_server_cleanly(NULL);
}
#ifdef DEVELOPER
-static void msg_inject_fault(struct messaging_context *msg,
- void *private_data,
- uint32_t msg_type,
- struct server_id src,
- DATA_BLOB *data)
+static void msg_inject_fault(int msg_type, struct process_id src,
+ void *buf, size_t len, void *private_data)
{
int sig;
- if (data->length != sizeof(sig)) {
+ if (len != sizeof(int)) {
- DEBUG(0, ("Process %s sent bogus signal injection request\n",
- procid_str_static(&src)));
+ DEBUG(0, ("Process %llu sent bogus signal injection request\n",
+ (unsigned long long)src.pid));
return;
}
- sig = *(int *)data->data;
+ sig = *(int *)buf;
if (sig == -1) {
exit_server("internal error injected");
return;
}
#if HAVE_STRSIGNAL
- DEBUG(0, ("Process %s requested injection of signal %d (%s)\n",
- procid_str_static(&src), sig, strsignal(sig)));
+ DEBUG(0, ("Process %llu requested injection of signal %d (%s)\n",
+ (unsigned long long)src.pid, sig, strsignal(sig)));
#else
- DEBUG(0, ("Process %s requested injection of signal %d\n",
- procid_str_static(&src), sig));
+ DEBUG(0, ("Process %llu requested injection of signal %d\n",
+ (unsigned long long)src.pid, sig));
#endif
kill(sys_getpid(), sig);
@@ -316,33 +297,25 @@ static BOOL allowable_number_of_smbd_processes(void)
}
/****************************************************************************
- Are we idle enough that we could safely exit?
-****************************************************************************/
-
-static BOOL smbd_is_idle(void)
-{
- /* Currently we define "idle" as having no client connections. */
- return count_all_current_connections() == 0;
-}
-
-/****************************************************************************
Open the socket communication.
****************************************************************************/
-static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_ports)
+static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_ports)
{
+ int num_interfaces = iface_count();
int num_sockets = 0;
int fd_listenset[FD_SETSIZE];
fd_set listen_set;
int s;
int maxfd = 0;
int i;
- struct timeval idle_timeout = timeval_zero();
+ char *ports;
- if (server_mode == SERVER_MODE_INETD) {
+ if (!is_daemon) {
return open_sockets_inetd();
}
+
#ifdef HAVE_ATEXIT
{
static int atexit_set;
@@ -355,56 +328,143 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_
/* Stop zombies */
CatchSignal(SIGCLD, sig_cld);
-
+
FD_ZERO(&listen_set);
- /* At this point, it doesn't matter what daemon mode we are in, we
- * need some sockets to listen on.
- */
- num_sockets = smbd_sockinit(smb_ports, fd_listenset, &idle_timeout);
- if (num_sockets == 0) {
- return False;
+ /* use a reasonable default set of ports - listing on 445 and 139 */
+ if (!smb_ports) {
+ ports = lp_smb_ports();
+ if (!ports || !*ports) {
+ ports = smb_xstrdup(SMB_PORTS);
+ } else {
+ ports = smb_xstrdup(ports);
+ }
+ } else {
+ ports = smb_xstrdup(smb_ports);
}
- for (i = 0; i < num_sockets; ++i) {
- FD_SET(fd_listenset[i], &listen_set);
- maxfd = MAX(maxfd, fd_listenset[i]);
- }
+ if (lp_interfaces() && lp_bind_interfaces_only()) {
+ /* We have been given an interfaces line, and been
+ told to only bind to those interfaces. Create a
+ socket per interface and bind to only these.
+ */
+
+ /* Now open a listen socket for each of the
+ interfaces. */
+ for(i = 0; i < num_interfaces; i++) {
+ struct in_addr *ifip = iface_n_ip(i);
+ fstring tok;
+ const char *ptr;
+
+ if(ifip == NULL) {
+ DEBUG(0,("open_sockets_smbd: interface %d has NULL IP address !\n", i));
+ continue;
+ }
+
+ for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
+ unsigned port = atoi(tok);
+ if (port == 0 || port > 0xffff) {
+ continue;
+ }
+ s = fd_listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True);
+ if(s == -1)
+ return False;
+
+ /* ready to listen */
+ set_socket_options(s,"SO_KEEPALIVE");
+ set_socket_options(s,user_socket_options);
+
+ /* Set server socket to non-blocking for the accept. */
+ set_blocking(s,False);
+
+ if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
+ DEBUG(0,("listen: %s\n",strerror(errno)));
+ close(s);
+ return False;
+ }
+ FD_SET(s,&listen_set);
+ maxfd = MAX( maxfd, s);
+
+ num_sockets++;
+ if (num_sockets >= FD_SETSIZE) {
+ DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n"));
+ return False;
+ }
+ }
+ }
+ } else {
+ /* Just bind to 0.0.0.0 - accept connections
+ from anywhere. */
+
+ fstring tok;
+ const char *ptr;
+
+ num_interfaces = 1;
+
+ for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
+ unsigned port = atoi(tok);
+ if (port == 0 || port > 0xffff) continue;
+ /* open an incoming socket */
+ s = open_socket_in(SOCK_STREAM, port, 0,
+ interpret_addr(lp_socket_address()),True);
+ if (s == -1)
+ return(False);
+
+ /* ready to listen */
+ set_socket_options(s,"SO_KEEPALIVE");
+ set_socket_options(s,user_socket_options);
+
+ /* Set server socket to non-blocking for the accept. */
+ set_blocking(s,False);
+
+ if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
+ DEBUG(0,("open_sockets_smbd: listen: %s\n",
+ strerror(errno)));
+ close(s);
+ return False;
+ }
+
+ fd_listenset[num_sockets] = s;
+ FD_SET(s,&listen_set);
+ maxfd = MAX( maxfd, s);
+
+ num_sockets++;
+
+ if (num_sockets >= FD_SETSIZE) {
+ DEBUG(0,("open_sockets_smbd: Too many sockets to bind to\n"));
+ return False;
+ }
+ }
+ }
+
+ SAFE_FREE(ports);
/* Listen to messages */
- messaging_register(smbd_messaging_context(), NULL,
- MSG_SMB_SAM_SYNC, msg_sam_sync);
- messaging_register(smbd_messaging_context(), NULL,
- MSG_SMB_SAM_REPL, msg_sam_repl);
- messaging_register(smbd_messaging_context(), NULL,
- MSG_SHUTDOWN, msg_exit_server);
- messaging_register(smbd_messaging_context(), NULL,
- MSG_SMB_FILE_RENAME, msg_file_was_renamed);
- messaging_register(smbd_messaging_context(), NULL,
- MSG_SMB_CONF_UPDATED, smb_conf_updated);
- messaging_register(smbd_messaging_context(), NULL,
- MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete);
- brl_register_msgs(smbd_messaging_context());
+ message_register(MSG_SMB_SAM_SYNC, msg_sam_sync, NULL);
+ message_register(MSG_SMB_SAM_REPL, msg_sam_repl, NULL);
+ message_register(MSG_SHUTDOWN, msg_exit_server, NULL);
+ message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed, NULL);
+ message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated, NULL);
+ message_register(MSG_SMB_STAT_CACHE_DELETE, smb_stat_cache_delete,
+ NULL);
#ifdef DEVELOPER
- messaging_register(smbd_messaging_context(), NULL,
- MSG_SMB_INJECT_FAULT, msg_inject_fault);
+ message_register(MSG_SMB_INJECT_FAULT, msg_inject_fault, NULL);
#endif
/* now accept incoming connections - forking a new process
for each incoming connection */
DEBUG(2,("waiting for a connection\n"));
while (1) {
- struct timeval now;
- fd_set r_fds, w_fds;
+ fd_set lfds;
int num;
/* Free up temporary memory from the main smbd. */
lp_TALLOC_FREE();
/* Ensure we respond to PING and DEBUG messages from the main smbd. */
- message_dispatch(smbd_messaging_context());
+ message_dispatch();
if (got_sig_cld) {
pid_t pid;
@@ -415,31 +475,11 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_
}
}
- memcpy((char *)&r_fds, (char *)&listen_set,
+ memcpy((char *)&lfds, (char *)&listen_set,
sizeof(listen_set));
- FD_ZERO(&w_fds);
- GetTimeOfDay(&now);
-
- event_add_to_select_args(smbd_event_context(), &now,
- &r_fds, &w_fds, &idle_timeout,
- &maxfd);
-
- if (timeval_is_zero(&idle_timeout)) {
- num = sys_select(maxfd + 1, &r_fds, &w_fds,
- NULL, NULL);
- } else {
- num = sys_select(maxfd + 1, &r_fds, &w_fds,
- NULL, &idle_timeout);
-
- /* If the idle timeout fired and we are idle, exit
- * gracefully. We expect to be running under a process
- * controller that will restart us if necessry.
- */
- if (num == 0 && smbd_is_idle()) {
- exit_server_cleanly("idle timeout");
- }
- }
-
+
+ num = sys_select(maxfd+1,&lfds,NULL,NULL,NULL);
+
if (num == -1 && errno == EINTR) {
if (got_sig_term) {
exit_server_cleanly(NULL);
@@ -455,11 +495,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_
continue;
}
-
- if (run_events(smbd_event_context(), num, &r_fds, &w_fds)) {
- continue;
- }
-
+
/* check if we need to reload services */
check_reload(time(NULL));
@@ -472,11 +508,11 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_
s = -1;
for(i = 0; i < num_sockets; i++) {
- if(FD_ISSET(fd_listenset[i],&r_fds)) {
+ if(FD_ISSET(fd_listenset[i],&lfds)) {
s = fd_listenset[i];
/* Clear this so we don't look
at it again. */
- FD_CLR(fd_listenset[i],&r_fds);
+ FD_CLR(fd_listenset[i],&lfds);
break;
}
}
@@ -495,13 +531,8 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_
/* Ensure child is set to blocking mode */
set_blocking(smbd_server_fd(),True);
- /* In interactive mode, return with a connected socket.
- * Foreground and daemon modes should fork worker
- * processes.
- */
- if (server_mode == SERVER_MODE_INTERACTIVE) {
+ if (smbd_server_fd() != -1 && interactive)
return True;
- }
if (allowable_number_of_smbd_processes() &&
smbd_server_fd() != -1 &&
@@ -539,7 +570,7 @@ static BOOL open_sockets_smbd(enum smb_server_mode server_mode, const char *smb_
* CLEAR_IF_FIRST flags */
if (tdb_reopen_all(1) == -1) {
DEBUG(0,("tdb_reopen_all failed.\n"));
- smb_panic("tdb_reopen_all failed");
+ smb_panic("tdb_reopen_all failed.");
}
return True;
@@ -696,8 +727,7 @@ static void exit_server_common(enum server_exit_reason how,
invalidate_all_vuids();
- /* 3 second timeout. */
- print_notify_send_messages(smbd_messaging_context(), 3);
+ print_notify_send_messages(3); /* 3 second timeout. */
/* delete our entry in the connections database. */
yield_connection(NULL,"");
@@ -713,8 +743,6 @@ static void exit_server_common(enum server_exit_reason how,
locking_end();
printing_end();
- server_encryption_shutdown();
-
if (how != SERVER_EXIT_NORMAL) {
int oldlevel = DEBUGLEVEL;
char *last_inbuf = get_InBuffer();
@@ -786,35 +814,6 @@ static BOOL init_structs(void )
return True;
}
-/*
- * Send keepalive packets to our client
- */
-static BOOL keepalive_fn(const struct timeval *now, void *private_data)
-{
- if (!send_keepalive(smbd_server_fd())) {
- DEBUG( 2, ( "Keepalive failed - exiting.\n" ) );
- return False;
- }
- return True;
-}
-
-/*
- * Do the recurring check if we're idle
- */
-static BOOL deadtime_fn(const struct timeval *now, void *private_data)
-{
- if ((conn_num_open() == 0)
- || (conn_idle_all(now->tv_sec))) {
- DEBUG( 2, ( "Closing idle connection\n" ) );
- messaging_send(smbd_messaging_context(), procid_self(),
- MSG_SHUTDOWN, &data_blob_null);
- return False;
- }
-
- return True;
-}
-
-
/****************************************************************************
main program.
****************************************************************************/
@@ -828,25 +827,22 @@ extern void build_options(BOOL screen);
int main(int argc,const char *argv[])
{
/* shall I run as a daemon */
- BOOL no_process_group = False;
- BOOL log_stdout = False;
- const char *ports = NULL;
- const char *profile_level = NULL;
+ static BOOL is_daemon = False;
+ static BOOL interactive = False;
+ static BOOL Fork = True;
+ static BOOL no_process_group = False;
+ static BOOL log_stdout = False;
+ static char *ports = NULL;
+ static char *profile_level = NULL;
int opt;
poptContext pc;
- enum smb_server_mode server_mode = SERVER_MODE_DAEMON;
-
struct poptOption long_options[] = {
POPT_AUTOHELP
- {"daemon", 'D', POPT_ARG_VAL, &server_mode, SERVER_MODE_DAEMON,
- "Become a daemon (default)" },
- {"interactive", 'i', POPT_ARG_VAL, &server_mode, SERVER_MODE_INTERACTIVE,
- "Run interactive (not a daemon)"},
- {"foreground", 'F', POPT_ARG_VAL, &server_mode, SERVER_MODE_FOREGROUND,
- "Run daemon in foreground (for daemontools, etc.)" },
- {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True,
- "Don't create a new process group" },
+ {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon (default)" },
+ {"interactive", 'i', POPT_ARG_VAL, &interactive, True, "Run interactive (not a daemon)"},
+ {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools, etc.)" },
+ {"no-process-group", '\0', POPT_ARG_VAL, &no_process_group, True, "Don't create a new process group" },
{"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
{"build-options", 'b', POPT_ARG_NONE, NULL, 'b', "Print build options" },
{"port", 'p', POPT_ARG_STRING, &ports, 0, "Listen on the specified ports"},
@@ -886,14 +882,16 @@ extern void build_options(BOOL screen);
set_remote_machine_name("smbd", False);
- if (server_mode == SERVER_MODE_INTERACTIVE) {
+ if (interactive) {
+ Fork = False;
log_stdout = True;
- if (DEBUGLEVEL >= 9) {
- talloc_enable_leak_report();
- }
}
- if (log_stdout && server_mode == SERVER_MODE_DAEMON) {
+ if (interactive && (DEBUGLEVEL >= 9)) {
+ talloc_enable_leak_report();
+ }
+
+ if (log_stdout && Fork) {
DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
exit(1);
}
@@ -967,13 +965,13 @@ extern void build_options(BOOL screen);
init_structs();
#ifdef WITH_PROFILE
- if (!profile_setup(smbd_messaging_context(), False)) {
+ if (!profile_setup(False)) {
DEBUG(0,("ERROR: failed to setup profiling\n"));
return -1;
}
if (profile_level != NULL) {
int pl = atoi(profile_level);
- struct server_id src;
+ struct process_id src;
DEBUG(1, ("setting profiling level: %s\n",profile_level));
src.pid = getpid();
@@ -983,19 +981,21 @@ extern void build_options(BOOL screen);
DEBUG(3,( "loaded services\n"));
- if (is_a_socket(0)) {
- if (server_mode == SERVER_MODE_DAEMON) {
- DEBUG(0,("standard input is a socket, "
- "assuming -F option\n"));
- }
- server_mode = SERVER_MODE_INETD;
+ if (!is_daemon && !is_a_socket(0)) {
+ if (!interactive)
+ DEBUG(0,("standard input is not a socket, assuming -D option\n"));
+
+ /*
+ * Setting is_daemon here prevents us from eventually calling
+ * the open_sockets_inetd()
+ */
+
+ is_daemon = True;
}
- if (server_mode == SERVER_MODE_DAEMON) {
+ if (is_daemon && !interactive) {
DEBUG( 3, ( "Becoming a daemon.\n" ) );
- become_daemon(True, no_process_group);
- } else if (server_mode == SERVER_MODE_FOREGROUND) {
- become_daemon(False, no_process_group);
+ become_daemon(Fork, no_process_group);
}
#if HAVE_SETPGID
@@ -1003,28 +1003,24 @@ extern void build_options(BOOL screen);
* If we're interactive we want to set our own process group for
* signal management.
*/
- if (server_mode == SERVER_MODE_INTERACTIVE && !no_process_group) {
+ if (interactive && !no_process_group)
setpgid( (pid_t)0, (pid_t)0);
- }
#endif
if (!directory_exist(lp_lockdir(), NULL))
mkdir(lp_lockdir(), 0755);
- if (server_mode != SERVER_MODE_INETD &&
- server_mode != SERVER_MODE_INTERACTIVE) {
+ if (is_daemon)
pidfile_create("smbd");
- }
/* Setup all the TDB's - including CLEAR_IF_FIRST tdb's. */
-
- if (smbd_messaging_context() == NULL)
+ if (!message_init())
exit(1);
/* Initialise the password backed before the global_sam_sid
to ensure that we fetch from ldap before we make a domain sid up */
- if(!initialize_password_db(False, smbd_event_context()))
+ if(!initialize_password_db(False))
exit(1);
if (!secrets_init()) {
@@ -1040,7 +1036,7 @@ extern void build_options(BOOL screen);
if (!session_init())
exit(1);
- if (!connections_init(True))
+ if (conn_tdb_ctx() == NULL)
exit(1);
if (!locking_init(0))
@@ -1056,7 +1052,7 @@ extern void build_options(BOOL screen);
exit(1);
#endif
- if (!print_backend_init(smbd_messaging_context()))
+ if (!print_backend_init())
exit(1);
if (!init_guest_info()) {
@@ -1067,16 +1063,15 @@ extern void build_options(BOOL screen);
/* Setup the main smbd so that we can get messages. */
/* don't worry about general printing messages here */
- claim_connection(NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
+ claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD);
/* only start the background queue daemon if we are
running as a daemon -- bad things will happen if
smbd is launched via inetd and we fork a copy of
ourselves here */
- if (server_mode != SERVER_MODE_INETD &&
- server_mode != SERVER_MODE_INTERACTIVE) {
+
+ if ( is_daemon && !interactive )
start_background_queue();
- }
/* Always attempt to initialize DMAPI. We will only use it later if
* lp_dmapi_support is set on the share, but we need a single global
@@ -1084,9 +1079,8 @@ extern void build_options(BOOL screen);
*/
dmapi_init_session();
- if (!open_sockets_smbd(server_mode, ports)) {
+ if (!open_sockets_smbd(is_daemon, interactive, ports))
exit(1);
- }
/*
* everything after this point is run after the fork()
@@ -1099,8 +1093,7 @@ extern void build_options(BOOL screen);
/* Possibly reload the services file. Only worth doing in
* daemon mode. In inetd mode, we know we only just loaded this.
*/
- if (server_mode != SERVER_MODE_INETD &&
- server_mode != SERVER_MODE_INTERACTIVE) {
+ if (is_daemon) {
reload_services(True);
}
@@ -1115,38 +1108,14 @@ extern void build_options(BOOL screen);
}
/* Setup oplocks */
- if (!init_oplocks(smbd_messaging_context()))
+ if (!init_oplocks())
exit(1);
/* Setup aio signal handler. */
initialize_async_io_handler();
- /*
- * For clustering, we need to re-init our ctdbd connection after the
- * fork
- */
- if (!NT_STATUS_IS_OK(messaging_reinit(smbd_messaging_context())))
- exit(1);
-
/* register our message handlers */
- messaging_register(smbd_messaging_context(), NULL,
- MSG_SMB_FORCE_TDIS, msg_force_tdis);
-
- if ((lp_keepalive() != 0)
- && !(event_add_idle(smbd_event_context(), NULL,
- timeval_set(lp_keepalive(), 0),
- "keepalive", keepalive_fn,
- NULL))) {
- DEBUG(0, ("Could not add keepalive event\n"));
- exit(1);
- }
-
- if (!(event_add_idle(smbd_event_context(), NULL,
- timeval_set(IDLE_CLOSED_TIMEOUT, 0),
- "deadtime", deadtime_fn, NULL))) {
- DEBUG(0, ("Could not add deadtime event\n"));
- exit(1);
- }
+ message_register(MSG_SMB_FORCE_TDIS, msg_force_tdis, NULL);
smbd_process();
diff --git a/source/smbd/service.c b/source/smbd/service.c
index 2b842236958..bfe9649ea4a 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -254,104 +254,6 @@ int add_home_service(const char *service, const char *username, const char *home
}
-static int load_registry_service(const char *servicename)
-{
- struct registry_key *key;
- char *path;
- WERROR err;
-
- uint32 i;
- char *value_name;
- struct registry_value *value;
-
- int res = -1;
-
- if (!lp_registry_shares()) {
- return -1;
- }
-
- if (asprintf(&path, "%s\\%s", KEY_SMBCONF, servicename) == -1) {
- return -1;
- }
-
- err = reg_open_path(NULL, path, REG_KEY_READ, get_root_nt_token(),
- &key);
- SAFE_FREE(path);
-
- if (!W_ERROR_IS_OK(err)) {
- return -1;
- }
-
- res = lp_add_service(servicename, -1);
- if (res == -1) {
- goto error;
- }
-
- for (i=0;
- W_ERROR_IS_OK(reg_enumvalue(key, key, i, &value_name, &value));
- i++) {
- switch (value->type) {
- case REG_DWORD: {
- char *tmp;
- if (asprintf(&tmp, "%d", value->v.dword) == -1) {
- continue;
- }
- lp_do_parameter(res, value_name, tmp);
- SAFE_FREE(tmp);
- break;
- }
- case REG_SZ: {
- lp_do_parameter(res, value_name, value->v.sz.str);
- break;
- }
- default:
- /* Ignore all the rest */
- break;
- }
-
- TALLOC_FREE(value_name);
- TALLOC_FREE(value);
- }
-
- if (!service_ok(res)) {
- /* this is actually never reached, since
- * service_ok only returns False if the service
- * entry does not have a service name, and we _know_
- * we do have a service name here... */
- res = -1;
- }
-
- error:
-
- TALLOC_FREE(key);
- return res;
-}
-
-void load_registry_shares(void)
-{
- struct registry_key *key;
- char *name;
- WERROR err;
- int i;
-
- if (!lp_registry_shares()) {
- return;
- }
-
- err = reg_open_path(NULL, KEY_SMBCONF, REG_KEY_READ,
- get_root_nt_token(), &key);
- if (!(W_ERROR_IS_OK(err))) {
- return;
- }
-
- for (i=0; W_ERROR_IS_OK(reg_enumkey(key, key, i, &name, NULL)); i++) {
- load_registry_service(name);
- TALLOC_FREE(name);
- }
-
- TALLOC_FREE(key);
- return;
-}
/**
* Find a service entry.
@@ -445,10 +347,6 @@ int find_service(fstring service)
}
}
- if (iService < 0) {
- iService = load_registry_service(service);
- }
-
if (iService >= 0) {
if (!VALID_SNUM(iService)) {
DEBUG(0,("Invalid snum %d for %s\n",iService, service));
@@ -790,6 +688,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
conn->veto_list = NULL;
conn->hide_list = NULL;
conn->veto_oplock_list = NULL;
+ conn->aio_write_behind_list = NULL;
string_set(&conn->dirpath,"");
string_set(&conn->user,user);
@@ -989,31 +888,17 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
}
/* ROOT Activities: */
- /*
- * Enforce the max connections parameter.
- */
-
- if ((lp_max_connections(snum) > 0)
- && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
- lp_max_connections(snum))) {
-
- DEBUG(1, ("Max connections (%d) exceeded for %s\n",
- lp_max_connections(snum), lp_servicename(snum)));
+ /* check number of connections */
+ if (!claim_connection(conn,
+ lp_servicename(snum),
+ lp_max_connections(snum),
+ False,0)) {
+ DEBUG(1,("too many connections - rejected\n"));
conn_free(conn);
*status = NT_STATUS_INSUFFICIENT_RESOURCES;
return NULL;
}
- /*
- * Get us an entry in the connections db
- */
- if (!claim_connection(conn, lp_servicename(snum), 0)) {
- DEBUG(1, ("Could not store connections entry\n"));
- conn_free(conn);
- *status = NT_STATUS_INTERNAL_DB_ERROR;
- return NULL;
- }
-
/* Preexecs are done here as they might make the dir we are to ChDir
* to below */
/* execute any "root preexec = " line */
@@ -1244,7 +1129,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password,
if (strequal(service_in,HOMES_NAME)) {
if(lp_security() != SEC_SHARE) {
- DATA_BLOB no_pw = data_blob_null;
+ DATA_BLOB no_pw = data_blob(NULL, 0);
if (vuser->homes_snum == -1) {
DEBUG(2, ("[homes] share not available for "
"this user because it was not found "
@@ -1280,7 +1165,7 @@ connection_struct *make_connection(const char *service_in, DATA_BLOB password,
} else if ((lp_security() != SEC_SHARE) && (vuser->homes_snum != -1)
&& strequal(service_in,
lp_servicename(vuser->homes_snum))) {
- DATA_BLOB no_pw = data_blob_null;
+ DATA_BLOB no_pw = data_blob(NULL, 0);
DEBUG(5, ("making a connection to 'homes' service [%s] "
"created at session setup time\n", service_in));
return make_connection_snum(vuser->homes_snum,
diff --git a/source/smbd/session.c b/source/smbd/session.c
index 6b1bb0cbee5..bcb840a3fe4 100644
--- a/source/smbd/session.c
+++ b/source/smbd/session.c
@@ -29,25 +29,19 @@
#include "includes.h"
+static TDB_CONTEXT *tdb;
+
/********************************************************************
********************************************************************/
-static struct db_context *session_db_ctx(void)
-{
- static struct db_context *ctx;
-
- if (ctx)
- return ctx;
-
- ctx = db_open(NULL, lock_path("sessionid.tdb"), 0,
- TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
- O_RDWR | O_CREAT, 0644);
- return ctx;
-}
-
BOOL session_init(void)
{
- if (session_db_ctx() == NULL) {
+ if (tdb)
+ return True;
+
+ tdb = tdb_open_log(lock_path("sessionid.tdb"), 0, TDB_CLEAR_IF_FIRST|TDB_DEFAULT,
+ O_RDWR | O_CREAT, 0644);
+ if (!tdb) {
DEBUG(1,("session_init: failed to open sessionid tdb\n"));
return False;
}
@@ -61,17 +55,18 @@ BOOL session_init(void)
BOOL session_claim(user_struct *vuser)
{
- TDB_DATA key, data;
int i = 0;
+ TDB_DATA data;
struct sockaddr sa;
struct in_addr *client_ip;
struct sessionid sessionid;
- struct server_id pid = procid_self();
+ uint32 pid = (uint32)sys_getpid();
+ TDB_DATA key;
fstring keystr;
char * hostname;
- struct db_context *ctx;
- struct db_record *rec;
- NTSTATUS status;
+ int tdb_store_flag; /* If using utmp, we do an inital 'lock hold' store,
+ but we don't need this if we are just using the
+ (unique) pid/vuid combination */
vuser->session_keystr = NULL;
@@ -81,9 +76,8 @@ BOOL session_claim(user_struct *vuser)
return True;
}
- if (!(ctx = session_db_ctx())) {
+ if (!session_init())
return False;
- }
ZERO_STRUCT(sessionid);
@@ -91,69 +85,35 @@ BOOL session_claim(user_struct *vuser)
data.dsize = 0;
if (lp_utmp()) {
-
for (i=1;i<MAX_SESSION_ID;i++) {
-
- /*
- * This is very inefficient and needs fixing -- vl
- */
-
- struct server_id sess_pid;
-
- snprintf(keystr, sizeof(keystr), "ID/%d", i);
- key = string_term_tdb_data(keystr);
-
- rec = ctx->fetch_locked(ctx, NULL, key);
-
- if (rec == NULL) {
- DEBUG(1, ("Could not lock \"%s\"\n", keystr));
- return False;
- }
-
- if (rec->value.dsize != sizeof(sessionid)) {
- DEBUG(1, ("Re-using invalid record\n"));
- break;
- }
-
- sess_pid = ((struct sessionid *)rec->value.dptr)->pid;
-
- if (!process_exists(sess_pid)) {
- DEBUG(5, ("%s has died -- re-using session\n",
- procid_str_static(&sess_pid)));
- break;
- }
-
- TALLOC_FREE(rec);
+ slprintf(keystr, sizeof(keystr)-1, "ID/%d", i);
+ key.dptr = keystr;
+ key.dsize = strlen(keystr)+1;
+
+ if (tdb_store(tdb, key, data, TDB_INSERT) == 0) break;
}
if (i == MAX_SESSION_ID) {
- SMB_ASSERT(rec == NULL);
- DEBUG(1,("session_claim: out of session IDs "
- "(max is %d)\n", MAX_SESSION_ID));
+ DEBUG(1,("session_claim: out of session IDs (max is %d)\n",
+ MAX_SESSION_ID));
return False;
}
-
- snprintf(sessionid.id_str, sizeof(sessionid.id_str),
- SESSION_UTMP_TEMPLATE, i);
+ slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1, SESSION_UTMP_TEMPLATE, i);
+ tdb_store_flag = TDB_MODIFY;
} else
{
- snprintf(keystr, sizeof(keystr), "ID/%s/%u",
- procid_str_static(&pid), vuser->vuid);
- key = string_term_tdb_data(keystr);
-
- rec = ctx->fetch_locked(ctx, NULL, key);
-
- if (rec == NULL) {
- DEBUG(1, ("Could not lock \"%s\"\n", keystr));
- return False;
- }
-
- snprintf(sessionid.id_str, sizeof(sessionid.id_str),
+ slprintf(keystr, sizeof(keystr)-1, "ID/%lu/%u",
+ (long unsigned int)sys_getpid(),
+ vuser->vuid);
+ slprintf(sessionid.id_str, sizeof(sessionid.id_str)-1,
SESSION_TEMPLATE, (long unsigned int)sys_getpid(),
vuser->vuid);
- }
- SMB_ASSERT(rec != NULL);
+ key.dptr = keystr;
+ key.dsize = strlen(keystr)+1;
+
+ tdb_store_flag = TDB_REPLACE;
+ }
/* If 'hostname lookup' == yes, then do the DNS lookup. This is
needed because utmp and PAM both expect DNS names
@@ -178,25 +138,19 @@ BOOL session_claim(user_struct *vuser)
client_ip = client_inaddr(&sa);
- if (!smb_pam_claim_session(sessionid.username, sessionid.id_str,
- sessionid.hostname)) {
+ if (!smb_pam_claim_session(sessionid.username, sessionid.id_str, sessionid.hostname)) {
DEBUG(1,("pam_session rejected the session for %s [%s]\n",
sessionid.username, sessionid.id_str));
-
- TALLOC_FREE(rec);
+ if (tdb_store_flag == TDB_MODIFY) {
+ tdb_delete(tdb, key);
+ }
return False;
}
- data.dptr = (uint8 *)&sessionid;
+ data.dptr = (char *)&sessionid;
data.dsize = sizeof(sessionid);
-
- status = rec->store(rec, data, TDB_REPLACE);
-
- TALLOC_FREE(rec);
-
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(1,("session_claim: unable to create session id "
- "record: %s\n", nt_errstr(status)));
+ if (tdb_store(tdb, key, data, tdb_store_flag) != 0) {
+ DEBUG(1,("session_claim: unable to create session id record\n"));
return False;
}
@@ -206,12 +160,9 @@ BOOL session_claim(user_struct *vuser)
sessionid.id_str, sessionid.id_num);
}
- TALLOC_FREE(rec);
-
- vuser->session_keystr = talloc_strdup(vuser, keystr);
+ vuser->session_keystr = SMB_STRDUP(keystr);
if (!vuser->session_keystr) {
- DEBUG(0, ("session_claim: talloc_strdup() failed for "
- "session_keystr\n"));
+ DEBUG(0, ("session_claim: strdup() failed for session_keystr\n"));
return False;
}
return True;
@@ -223,60 +174,54 @@ BOOL session_claim(user_struct *vuser)
void session_yield(user_struct *vuser)
{
- TDB_DATA key;
+ TDB_DATA dbuf;
struct sessionid sessionid;
struct in_addr *client_ip;
- struct db_context *ctx;
- struct db_record *rec;
+ TDB_DATA key;
- if (!(ctx = session_db_ctx())) return;
+ if (!tdb) return;
if (!vuser->session_keystr) {
return;
}
- key = string_term_tdb_data(vuser->session_keystr);
+ key.dptr = vuser->session_keystr;
+ key.dsize = strlen(vuser->session_keystr)+1;
- if (!(rec = ctx->fetch_locked(ctx, NULL, key))) {
- return;
- }
+ dbuf = tdb_fetch(tdb, key);
- if (rec->value.dsize != sizeof(sessionid))
+ if (dbuf.dsize != sizeof(sessionid))
return;
- memcpy(&sessionid, rec->value.dptr, sizeof(sessionid));
+ memcpy(&sessionid, dbuf.dptr, sizeof(sessionid));
client_ip = interpret_addr2(sessionid.ip_addr);
+ SAFE_FREE(dbuf.dptr);
+
if (lp_utmp()) {
sys_utmp_yield(sessionid.username, sessionid.hostname,
client_ip,
sessionid.id_str, sessionid.id_num);
}
- smb_pam_close_session(sessionid.username, sessionid.id_str,
- sessionid.hostname);
+ smb_pam_close_session(sessionid.username, sessionid.id_str, sessionid.hostname);
- rec->delete_rec(rec);
-
- TALLOC_FREE(rec);
+ tdb_delete(tdb, key);
}
/********************************************************************
********************************************************************/
-static BOOL session_traverse(int (*fn)(struct db_record *db,
- void *private_data),
- void *private_data)
+BOOL session_traverse(int (*fn)(TDB_CONTEXT *, TDB_DATA, TDB_DATA, void *),
+ void *state)
{
- struct db_context *ctx;
-
- if (!(ctx = session_db_ctx())) {
+ if (!session_init()) {
DEBUG(3, ("No tdb opened\n"));
return False;
}
- ctx->traverse_read(ctx, fn, private_data);
+ tdb_traverse(tdb, fn, state);
return True;
}
@@ -284,29 +229,25 @@ static BOOL session_traverse(int (*fn)(struct db_record *db,
********************************************************************/
struct session_list {
- TALLOC_CTX *mem_ctx;
int count;
struct sessionid *sessions;
};
-static int gather_sessioninfo(struct db_record *rec, void *state)
+static int gather_sessioninfo(TDB_CONTEXT *stdb, TDB_DATA kbuf, TDB_DATA dbuf, void *state)
{
+ uint32 i;
struct session_list *sesslist = (struct session_list *) state;
- const struct sessionid *current =
- (const struct sessionid *) rec->value.dptr;
-
- sesslist->sessions = TALLOC_REALLOC_ARRAY(
- sesslist->mem_ctx, sesslist->sessions, struct sessionid,
- sesslist->count+1);
+ const struct sessionid *current = (const struct sessionid *) dbuf.dptr;
+ i = sesslist->count;
+
+ sesslist->sessions = SMB_REALLOC_ARRAY(sesslist->sessions, struct sessionid, i+1);
if (!sesslist->sessions) {
sesslist->count = 0;
return -1;
}
- memcpy(&sesslist->sessions[sesslist->count], current,
- sizeof(struct sessionid));
-
+ memcpy(&sesslist->sessions[i], current, sizeof(struct sessionid));
sesslist->count++;
DEBUG(7,("gather_sessioninfo session from %s@%s\n",
@@ -318,11 +259,10 @@ static int gather_sessioninfo(struct db_record *rec, void *state)
/********************************************************************
********************************************************************/
-int list_sessions(TALLOC_CTX *mem_ctx, struct sessionid **session_list)
+int list_sessions(struct sessionid **session_list)
{
struct session_list sesslist;
- sesslist.mem_ctx = mem_ctx;
sesslist.count = 0;
sesslist.sessions = NULL;
diff --git a/source/smbd/sesssetup.c b/source/smbd/sesssetup.c
index e938c0bbaca..05a5962056c 100644
--- a/source/smbd/sesssetup.c
+++ b/source/smbd/sesssetup.c
@@ -96,18 +96,15 @@ static void sessionsetup_start_signing_engine(const auth_serversupplied_info *se
Send a security blob via a session setup reply.
****************************************************************************/
-static BOOL reply_sesssetup_blob(connection_struct *conn,
- const char *inbuf,
- char *outbuf,
- DATA_BLOB blob,
- NTSTATUS nt_status)
+static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
+ DATA_BLOB blob, NTSTATUS nt_status)
{
char *p;
if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
ERROR_NT(nt_status_squash(nt_status));
} else {
- set_message(inbuf,outbuf,4,0,True);
+ set_message(outbuf,4,0,True);
nt_status = nt_status_squash(nt_status);
SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
@@ -121,7 +118,7 @@ static BOOL reply_sesssetup_blob(connection_struct *conn,
p += add_signature( outbuf, p );
- set_message_end(inbuf,outbuf,p);
+ set_message_end(outbuf,p);
}
show_msg(outbuf);
@@ -177,7 +174,7 @@ static BOOL make_krb5_skew_error(DATA_BLOB *pblob_out)
char *host_princ_s = NULL;
BOOL ret = False;
- *pblob_out = data_blob_null;
+ *pblob_out = data_blob(NULL,0);
initialize_krb5_error_table();
kerr = krb5_init_context(&context);
@@ -243,9 +240,9 @@ static int reply_spnego_kerberos(connection_struct *conn,
PAC_DATA *pac_data;
DATA_BLOB ap_rep, ap_rep_wrapped, response;
auth_serversupplied_info *server_info = NULL;
- DATA_BLOB session_key = data_blob_null;
+ DATA_BLOB session_key = data_blob(NULL, 0);
uint8 tok_id[2];
- DATA_BLOB nullblob = data_blob_null;
+ DATA_BLOB nullblob = data_blob(NULL, 0);
fstring real_username;
BOOL map_domainuser_to_guest = False;
BOOL username_was_mapped;
@@ -270,9 +267,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
- ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
- &client, &pac_data, &ap_rep,
- &session_key, True);
+ ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key);
data_blob_free(&ticket);
@@ -297,7 +292,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
}
ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_ERROR);
response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
- reply_sesssetup_blob(conn, inbuf, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
+ reply_sesssetup_blob(conn, outbuf, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
/*
* In this one case we don't invalidate the intermediate vuid.
@@ -525,7 +520,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
/* current_user_info is changed on new vuid */
reload_services( True );
- set_message(inbuf,outbuf,4,0,True);
+ set_message(outbuf,4,0,True);
SSVAL(outbuf, smb_vwv3, 0);
if (server_info->guest) {
@@ -541,10 +536,10 @@ static int reply_spnego_kerberos(connection_struct *conn,
if (NT_STATUS_IS_OK(ret)) {
ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
} else {
- ap_rep_wrapped = data_blob_null;
+ ap_rep_wrapped = data_blob(NULL, 0);
}
response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
- reply_sesssetup_blob(conn, inbuf, outbuf, response, ret);
+ reply_sesssetup_blob(conn, outbuf, response, ret);
data_blob_free(&ap_rep);
data_blob_free(&ap_rep_wrapped);
@@ -584,7 +579,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
if (NT_STATUS_IS_OK(nt_status)) {
int sess_vuid;
- DATA_BLOB nullblob = data_blob_null;
+ DATA_BLOB nullblob = data_blob(NULL, 0);
DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
/* register_vuid keeps the server info */
@@ -598,7 +593,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
/* current_user_info is changed on new vuid */
reload_services( True );
- set_message(inbuf,outbuf,4,0,True);
+ set_message(outbuf,4,0,True);
SSVAL(outbuf, smb_vwv3, 0);
if (server_info->guest) {
@@ -617,7 +612,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
response = *ntlmssp_blob;
}
- ret = reply_sesssetup_blob(conn, inbuf, outbuf, response, nt_status);
+ ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
if (wrap) {
data_blob_free(&response);
}
@@ -639,7 +634,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out
Is this a krb5 mechanism ?
****************************************************************************/
-NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5)
+static NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5)
{
char *OIDs[ASN1_MAX_OIDS];
int i;
@@ -750,9 +745,9 @@ static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
DATA_BLOB blob1,
AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
{
- DATA_BLOB auth = data_blob_null;
- DATA_BLOB auth_reply = data_blob_null;
- DATA_BLOB secblob = data_blob_null;
+ DATA_BLOB auth = data_blob(NULL,0);
+ DATA_BLOB auth_reply = data_blob(NULL,0);
+ DATA_BLOB secblob = data_blob(NULL,0);
NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
if (!spnego_parse_auth(blob1, &auth)) {
@@ -992,7 +987,8 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB
}
/* We must store this blob until complete. */
- if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
+ pad = SMB_MALLOC(sizeof(struct pending_auth_data));
+ if (!pad) {
return NT_STATUS_NO_MEMORY;
}
pad->needed_len = needed_len - pblob->length;
@@ -1029,7 +1025,6 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
user_struct *vuser = NULL;
NTSTATUS status = NT_STATUS_OK;
uint16 smbpid = SVAL(inbuf,smb_pid);
- uint16 smb_flag2 = SVAL(inbuf, smb_flg2);
DEBUG(3,("Doing spnego session setup\n"));
@@ -1058,12 +1053,9 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
#endif
p2 = inbuf + smb_vwv13 + data_blob_len;
- p2 += srvstr_pull_buf(inbuf, smb_flag2, native_os, p2,
- sizeof(native_os), STR_TERMINATE);
- p2 += srvstr_pull_buf(inbuf, smb_flag2, native_lanman, p2,
- sizeof(native_lanman), STR_TERMINATE);
- p2 += srvstr_pull_buf(inbuf, smb_flag2, primary_domain, p2,
- sizeof(primary_domain), STR_TERMINATE);
+ p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
+ p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
+ p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
native_os, native_lanman, primary_domain));
@@ -1095,7 +1087,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
}
if (!vuser) {
- vuid = register_vuid(NULL, data_blob_null, data_blob_null, NULL);
+ vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
if (vuid == UID_FIELD_INVALID ) {
data_blob_free(&blob1);
return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
@@ -1180,27 +1172,26 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
a new session setup with VC==0 is ignored.
****************************************************************************/
-static int shutdown_other_smbds(struct db_record *rec,
- const struct connections_key *key,
- const struct connections_data *crec,
- void *private_data)
+static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
+ void *p)
{
- const char *ip = (const char *)private_data;
+ struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
+ const char *ip = (const char *)p;
- if (!process_exists(crec->pid)) {
+ if (!process_exists(pid_to_procid(sessionid->pid))) {
return 0;
}
- if (procid_is_me(&crec->pid)) {
+ if (sessionid->pid == sys_getpid()) {
return 0;
}
- if (strcmp(ip, crec->addr) != 0) {
+ if (strcmp(ip, sessionid->ip_addr) != 0) {
return 0;
}
- messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
- &data_blob_null);
+ message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
+ NULL, 0, True);
return 0;
}
@@ -1212,7 +1203,7 @@ static void setup_new_vc_session(void)
invalidate_all_vuids();
#endif
if (lp_reset_on_zero_vc()) {
- connections_forall(shutdown_other_smbds, client_addr());
+ session_traverse(shutdown_other_smbds, client_addr());
}
}
@@ -1237,7 +1228,6 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
static BOOL done_sesssetup = False;
auth_usersupplied_info *user_info = NULL;
auth_serversupplied_info *server_info = NULL;
- uint16 smb_flag2 = SVAL(inbuf, smb_flg2);
NTSTATUS nt_status;
@@ -1251,12 +1241,12 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
ZERO_STRUCT(nt_resp);
ZERO_STRUCT(plaintext_password);
- DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), smb_flag2));
+ DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
/* a SPNEGO session setup has 12 command words, whereas a normal
NT1 session setup has 13. See the cifs spec. */
if (CVAL(inbuf, smb_wct) == 12 &&
- (smb_flag2 & FLAGS2_EXTENDED_SECURITY)) {
+ (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
if (!global_spnego_negotiated) {
DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
@@ -1288,9 +1278,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
plaintext_password.data[passlen1] = 0;
}
- srvstr_pull_buf(inbuf, smb_flag2, user,
- smb_buf(inbuf)+passlen1, sizeof(user),
- STR_TERMINATE);
+ srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
*domain = 0;
} else {
@@ -1358,7 +1346,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
nt_resp = data_blob(p+passlen1, passlen2);
} else {
pstring pass;
- BOOL unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
+ BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
#if 0
/* This was the previous fix. Not sure if it's still valid. JRA. */
@@ -1370,28 +1358,21 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
if (unic && (passlen2 == 0) && passlen1) {
/* Only a ascii plaintext password was sent. */
- srvstr_pull(inbuf, smb_flag2, pass,
- smb_buf(inbuf), sizeof(pass),
- passlen1, STR_TERMINATE|STR_ASCII);
+ srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
+ passlen1, STR_TERMINATE|STR_ASCII);
} else {
- srvstr_pull(inbuf, smb_flag2, pass,
- smb_buf(inbuf), sizeof(pass),
- unic ? passlen2 : passlen1,
- STR_TERMINATE);
+ srvstr_pull(inbuf, pass, smb_buf(inbuf),
+ sizeof(pass), unic ? passlen2 : passlen1,
+ STR_TERMINATE);
}
plaintext_password = data_blob(pass, strlen(pass)+1);
}
p += passlen1 + passlen2;
- p += srvstr_pull_buf(inbuf, smb_flag2, user, p,
- sizeof(user), STR_TERMINATE);
- p += srvstr_pull_buf(inbuf, smb_flag2, domain, p,
- sizeof(domain), STR_TERMINATE);
- p += srvstr_pull_buf(inbuf, smb_flag2, native_os,
- p, sizeof(native_os), STR_TERMINATE);
- p += srvstr_pull_buf(inbuf, smb_flag2,
- native_lanman, p, sizeof(native_lanman),
- STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
/* not documented or decoded by Ethereal but there is one more string
in the extra bytes which is the same as the PrimaryDomain when using
@@ -1401,10 +1382,7 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
byte_count = SVAL(inbuf, smb_vwv13);
if ( PTR_DIFF(p, save_p) < byte_count)
- p += srvstr_pull_buf(inbuf, smb_flag2,
- primary_domain, p,
- sizeof(primary_domain),
- STR_TERMINATE);
+ p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
else
fstrcpy( primary_domain, "null" );
@@ -1529,17 +1507,17 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
if (server_info->user_session_key.data) {
session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
} else {
- session_key = data_blob_null;
+ session_key = data_blob(NULL, 0);
}
data_blob_clear_free(&plaintext_password);
/* it's ok - setup a reply */
- set_message(inbuf,outbuf,3,0,True);
+ set_message(outbuf,3,0,True);
if (Protocol >= PROTOCOL_NT1) {
char *p = smb_buf( outbuf );
p += add_signature( outbuf, p );
- set_message_end(inbuf, outbuf, p );
+ set_message_end( outbuf, p );
/* perhaps grab OS version here?? */
}
diff --git a/source/smbd/share_access.c b/source/smbd/share_access.c
index b12d543f5a1..adb9d169642 100644
--- a/source/smbd/share_access.c
+++ b/source/smbd/share_access.c
@@ -86,7 +86,7 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx,
if (name == NULL) {
/* This is too security sensitive, better panic than return a
* result that might be interpreted in a wrong way. */
- smb_panic("substitutions failed");
+ smb_panic("substitutions failed\n");
}
/* check to see is we already have a SID */
@@ -136,7 +136,7 @@ static BOOL token_contains_name(TALLOC_CTX *mem_ctx,
}
continue;
}
- smb_panic("got invalid prefix from do_groups_check");
+ smb_panic("got invalid prefix from do_groups_check\n");
}
return False;
}
@@ -164,7 +164,7 @@ BOOL token_contains_name_in_list(const char *username,
}
if ( (mem_ctx = talloc_new(NULL)) == NULL ) {
- smb_panic("talloc_new failed");
+ smb_panic("talloc_new failed\n");
}
while (*list != NULL) {
diff --git a/source/smbd/sockinit.c b/source/smbd/sockinit.c
deleted file mode 100644
index 9d46776f892..00000000000
--- a/source/smbd/sockinit.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
-
- Copyright (C) Andrew Tridgell 1992-1998
- Copyright (C) James Peach 2007
-
- 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 2 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, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include "includes.h"
-#include "smb_launchd.h"
-
-extern pstring user_socket_options;
-
-static int init_sockets_smbd(const char *smb_ports, int listenset[FD_SETSIZE])
-{
- int num_interfaces = iface_count();
- char * ports;
- int num_sockets = 0;
- int i, s;
-
- /* use a reasonable default set of ports - listing on 445 and 139 */
- if (!smb_ports) {
- ports = lp_smb_ports();
- if (!ports || !*ports) {
- ports = smb_xstrdup(SMB_PORTS);
- } else {
- ports = smb_xstrdup(ports);
- }
- } else {
- ports = smb_xstrdup(smb_ports);
- }
-
- if (lp_interfaces() && lp_bind_interfaces_only()) {
- /* We have been given an interfaces line, and been
- told to only bind to those interfaces. Create a
- socket per interface and bind to only these.
- */
-
- /* Now open a listen socket for each of the
- interfaces. */
- for(i = 0; i < num_interfaces; i++) {
- struct in_addr *ifip = iface_n_ip(i);
- fstring tok;
- const char *ptr;
-
- if(ifip == NULL) {
- DEBUG(0,("init_sockets_smbd: interface %d has NULL IP address !\n", i));
- continue;
- }
-
- for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
- unsigned port = atoi(tok);
- if (port == 0 || port > 0xffff) {
- continue;
- }
- s = listenset[num_sockets] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr, True);
- if(s == -1)
- return 0;
-
- /* ready to listen */
- set_socket_options(s,"SO_KEEPALIVE");
- set_socket_options(s,user_socket_options);
-
- /* Set server socket to non-blocking for the accept. */
- set_blocking(s,False);
-
- if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
- DEBUG(0,("listen: %s\n",strerror(errno)));
- close(s);
- return 0;
- }
-
- num_sockets++;
- if (num_sockets >= FD_SETSIZE) {
- DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n"));
- return 0;
- }
- }
- }
- } else {
- /* Just bind to 0.0.0.0 - accept connections
- from anywhere. */
-
- fstring tok;
- const char *ptr;
-
- num_interfaces = 1;
-
- for (ptr=ports; next_token(&ptr, tok, " \t,", sizeof(tok)); ) {
- unsigned port = atoi(tok);
- if (port == 0 || port > 0xffff) continue;
- /* open an incoming socket */
- s = open_socket_in(SOCK_STREAM, port, 0,
- interpret_addr(lp_socket_address()),True);
- if (s == -1)
- return 0;
-
- /* ready to listen */
- set_socket_options(s,"SO_KEEPALIVE");
- set_socket_options(s,user_socket_options);
-
- /* Set server socket to non-blocking for the accept. */
- set_blocking(s,False);
-
- if (listen(s, SMBD_LISTEN_BACKLOG) == -1) {
- DEBUG(0,("init_sockets_smbd: listen: %s\n",
- strerror(errno)));
- close(s);
- return 0;
- }
-
- listenset[num_sockets] = s;
- num_sockets++;
-
- if (num_sockets >= FD_SETSIZE) {
- DEBUG(0,("init_sockets_smbd: Too many sockets to bind to\n"));
- return 0;
- }
- }
- }
-
- SAFE_FREE(ports);
- return num_sockets;
-}
-
-static int init_sockets_launchd(const struct smb_launch_info *linfo,
- const char * smb_ports,
- int listenset[FD_SETSIZE])
-{
- int num_sockets;
- int i;
-
- /* The launchd service configuration does not have to provide sockets,
- * even though it's basically useless without it.
- */
- if (!linfo->num_sockets) {
- return init_sockets_smbd(smb_ports, listenset);
- }
-
- /* Make sure we don't get more sockets than we can handle. */
- num_sockets = MIN(FD_SETSIZE, linfo->num_sockets);
- memcpy(listenset, linfo->socket_list, num_sockets * sizeof(int));
-
- /* Get the sockets ready. This could be hoisted into
- * open_sockets_smbd(), but the order of socket operations might
- * matter for some platforms, so this approach seems less risky.
- * --jpeach
- */
- for (i = 0; i < num_sockets; ++i) {
- set_socket_options(listenset[i], "SO_KEEPALIVE");
- set_socket_options(listenset[i], user_socket_options);
-
- /* Set server socket to non-blocking for the accept. */
- set_blocking(listenset[i], False);
- }
-
- return num_sockets;
-}
-
-/* This function is responsible for opening (or retrieving) all the sockets we
- * smbd will be listening on. It should apply all the configured socket options
- * and return the number of valid sockets in listenset.
- */
-int smbd_sockinit(const char *cmdline_ports, int listenset[FD_SETSIZE],
- struct timeval *idle)
-{
- int num_sockets;
- struct smb_launch_info linfo;
-
- ZERO_STRUCTP(idle);
-
- if (smb_launchd_checkin(&linfo)) {
- /* We are running under launchd and launchd has
- * opened some sockets for us.
- */
- num_sockets = init_sockets_launchd(&linfo,
- cmdline_ports,
- listenset);
- idle->tv_sec = linfo.idle_timeout_secs;
- smb_launchd_checkout(&linfo);
- } else {
- num_sockets = init_sockets_smbd(cmdline_ports,
- listenset);
- }
-
- return num_sockets;
-}
-
diff --git a/source/smbd/statcache.c b/source/smbd/statcache.c
index 92c845ce2e8..1a2b7a8237b 100644
--- a/source/smbd/statcache.c
+++ b/source/smbd/statcache.c
@@ -131,7 +131,7 @@ void stat_cache_add( const char *full_orig_name, const char *orig_translated_pat
*/
data_val.dsize = translated_path_length + 1;
- data_val.dptr = (uint8 *)translated_path;
+ data_val.dptr = translated_path;
if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) {
DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path));
@@ -165,9 +165,6 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
size_t namelen;
BOOL sizechanged = False;
unsigned int num_components = 0;
- char *translated_path;
- size_t translated_path_length;
- TDB_DATA data_val;
if (!lp_stat_cache())
return False;
@@ -210,87 +207,82 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
}
while (1) {
+ TDB_DATA data_val;
char *sp;
data_val = tdb_fetch_bystring(tdb_stat_cache, chk_name);
-
- if (data_val.dptr != NULL && data_val.dsize != 0) {
- break;
- }
-
- DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name ));
- /*
- * Didn't find it - remove last component for next try.
- */
- if (!(sp = strrchr_m(chk_name, '/'))) {
+ if(data_val.dptr == NULL || data_val.dsize == 0) {
+ DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name ));
/*
- * We reached the end of the name - no match.
+ * Didn't find it - remove last component for next try.
*/
- DO_PROFILE_INC(statcache_misses);
- SAFE_FREE(chk_name);
- return False;
- }
-
- *sp = '\0';
-
- /*
- * Count the number of times we have done this, we'll
- * need it when reconstructing the string.
- */
- if (sizechanged)
- num_components++;
-
- if ((*chk_name == '\0')
- || ISDOT(chk_name) || ISDOTDOT(chk_name)) {
- DO_PROFILE_INC(statcache_misses);
- SAFE_FREE(chk_name);
- return False;
- }
- }
-
- translated_path = (char *)data_val.dptr;
- translated_path_length = data_val.dsize - 1;
-
- DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] "
- "-> [%s]\n", chk_name, translated_path ));
- DO_PROFILE_INC(statcache_hits);
-
- if (SMB_VFS_STAT(conn, translated_path, pst) != 0) {
- /* Discard this entry - it doesn't exist in the filesystem. */
- tdb_delete_bystring(tdb_stat_cache, chk_name);
- SAFE_FREE(chk_name);
- SAFE_FREE(data_val.dptr);
- return False;
- }
-
- if (!sizechanged) {
- memcpy(name, translated_path,
- MIN(sizeof(pstring)-1, translated_path_length));
- } else if (num_components == 0) {
- pstrcpy(name, translated_path);
- } else {
- char *sp;
-
- sp = strnrchr_m(name, '/', num_components);
- if (sp) {
- pstring last_component;
- pstrcpy(last_component, sp);
- pstrcpy(name, translated_path);
- pstrcat(name, last_component);
+ sp = strrchr_m(chk_name, '/');
+ if (sp) {
+ *sp = '\0';
+ /*
+ * Count the number of times we have done this,
+ * we'll need it when reconstructing the string.
+ */
+ if (sizechanged)
+ num_components++;
+
+ } else {
+ /*
+ * We reached the end of the name - no match.
+ */
+ DO_PROFILE_INC(statcache_misses);
+ SAFE_FREE(chk_name);
+ return False;
+ }
+ if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0)
+ || (strcmp(chk_name, "..") == 0)) {
+ DO_PROFILE_INC(statcache_misses);
+ SAFE_FREE(chk_name);
+ return False;
+ }
} else {
- pstrcpy(name, translated_path);
+ BOOL retval;
+ char *translated_path = data_val.dptr;
+ size_t translated_path_length = data_val.dsize - 1;
+
+ DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, translated_path ));
+ DO_PROFILE_INC(statcache_hits);
+ if(SMB_VFS_STAT(conn,translated_path, pst) != 0) {
+ /* Discard this entry - it doesn't exist in the filesystem. */
+ tdb_delete_bystring(tdb_stat_cache, chk_name);
+ SAFE_FREE(chk_name);
+ SAFE_FREE(data_val.dptr);
+ return False;
+ }
+
+ if (!sizechanged) {
+ memcpy(name, translated_path, MIN(sizeof(pstring)-1, translated_path_length));
+ } else if (num_components == 0) {
+ pstrcpy(name, translated_path);
+ } else {
+ sp = strnrchr_m(name, '/', num_components);
+ if (sp) {
+ pstring last_component;
+ pstrcpy(last_component, sp);
+ pstrcpy(name, translated_path);
+ pstrcat(name, last_component);
+ } else {
+ pstrcpy(name, translated_path);
+ }
+ }
+
+ /* set pointer for 'where to start' on fixing the rest of the name */
+ *start = &name[translated_path_length];
+ if(**start == '/')
+ ++*start;
+
+ pstrcpy(dirpath, translated_path);
+ retval = (namelen == translated_path_length) ? True : False;
+ SAFE_FREE(chk_name);
+ SAFE_FREE(data_val.dptr);
+ return retval;
}
}
-
- /* set pointer for 'where to start' on fixing the rest of the name */
- *start = &name[translated_path_length];
- if (**start == '/')
- ++*start;
-
- pstrcpy(dirpath, translated_path);
- SAFE_FREE(chk_name);
- SAFE_FREE(data_val.dptr);
- return (namelen == translated_path_length);
}
/***************************************************************************
@@ -300,10 +292,11 @@ BOOL stat_cache_lookup(connection_struct *conn, pstring name, pstring dirpath,
void send_stat_cache_delete_message(const char *name)
{
#ifdef DEVELOPER
- message_send_all(smbd_messaging_context(),
+ message_send_all(conn_tdb_ctx(),
MSG_SMB_STAT_CACHE_DELETE,
name,
strlen(name)+1,
+ True,
NULL);
#endif
}
@@ -336,7 +329,7 @@ unsigned int fast_string_hash(TDB_DATA *key)
{
unsigned int n = 0;
const char *p;
- for (p = (const char *)key->dptr; *p != '\0'; p++) {
+ for (p = key->dptr; *p != '\0'; p++) {
n = ((n << 5) + n) ^ (unsigned int)(*p);
}
return n;
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 005983f133c..b2ce5b8c26d 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -147,7 +147,7 @@ static BOOL get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str
}
DEBUG(10,("get_ea_value: EA %s is of length %u: ", ea_name, (unsigned int)sizeret));
- dump_data(10, (uint8 *)val, sizeret);
+ dump_data(10, val, sizeret);
pea->flags = 0;
if (strnequal(ea_name, "user.", 5)) {
@@ -487,7 +487,7 @@ struct ea_list *read_ea_list_entry(TALLOC_CTX *ctx, const char *pdata, size_t da
}
DEBUG(10,("read_ea_list_entry: read ea name %s\n", eal->ea.name));
- dump_data(10, eal->ea.value.data, eal->ea.value.length);
+ dump_data(10, (const char *)eal->ea.value.data, eal->ea.value.length);
return eal;
}
@@ -577,8 +577,7 @@ static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *
HACK ! Always assumes smb_setup field is zero.
****************************************************************************/
-int send_trans2_replies(const char *inbuf,
- char *outbuf,
+int send_trans2_replies(char *outbuf,
int bufsize,
const char *params,
int paramsize,
@@ -603,7 +602,7 @@ int send_trans2_replies(const char *inbuf,
/* Initially set the wcnt area to be 10 - this is true for all trans2 replies */
- set_message(inbuf,outbuf,10,0,True);
+ set_message(outbuf,10,0,True);
/* Modify the data_to_send and datasize and set the error if
we're trying to send more than max_data_bytes. We still send
@@ -658,7 +657,7 @@ int send_trans2_replies(const char *inbuf,
total_sent_thistime = MIN(total_sent_thistime, useable_space+ alignment_offset + data_alignment_offset);
- set_message(inbuf, outbuf, 10, total_sent_thistime, True);
+ set_message(outbuf, 10, total_sent_thistime, True);
/* Set total params and data to be sent */
SSVAL(outbuf,smb_tprcnt,paramsize);
@@ -740,12 +739,9 @@ int send_trans2_replies(const char *inbuf,
Reply to a TRANSACT2_OPEN.
****************************************************************************/
-static int call_trans2open(connection_struct *conn,
- struct smb_request *req,
- char *inbuf, char *outbuf, int bufsize,
- char **pparams, int total_params,
- char **ppdata, int total_data,
- unsigned int max_data_bytes)
+static int call_trans2open(connection_struct *conn, char *inbuf, char *outbuf, int bufsize,
+ char **pparams, int total_params, char **ppdata, int total_data,
+ unsigned int max_data_bytes)
{
char *params = *pparams;
char *pdata = *ppdata;
@@ -804,9 +800,7 @@ static int call_trans2open(connection_struct *conn,
return(ERROR_DOS(ERRSRV,ERRaccess));
}
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, pname,
- sizeof(fname), total_params - 28, STR_TERMINATE,
- &status);
+ srvstr_get_path(inbuf, fname, pname, sizeof(fname), total_params - 28, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@@ -864,7 +858,7 @@ static int call_trans2open(connection_struct *conn,
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- status = open_file_ntcreate(conn, req, fname, &sbuf,
+ status = open_file_ntcreate(conn,fname,&sbuf,
access_mask,
share_mode,
create_disposition,
@@ -872,13 +866,13 @@ static int call_trans2open(connection_struct *conn,
open_attr,
oplock_request,
&smb_action, &fsp);
-
+
if (!NT_STATUS_IS_OK(status)) {
if (open_was_deferred(SVAL(inbuf,smb_mid))) {
/* We have re-scheduled this call. */
return -1;
}
- return ERROR_NT(status);
+ return ERROR_OPEN(status);
}
size = get_file_size(sbuf);
@@ -956,7 +950,7 @@ static int call_trans2open(connection_struct *conn,
}
/* Send the required number of replies */
- send_trans2_replies(inbuf, outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(outbuf, bufsize, params, 30, *ppdata, 0, max_data_bytes);
return -1;
}
@@ -1166,28 +1160,16 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %ld\n",
(long)conn->dirptr,curr_dirpos));
- if (!dname) {
+ if (!dname)
return(False);
- }
-
- /*
- * fname may get mangled, dname is never mangled.
- * Whenever we're accessing the filesystem we use
- * pathreal which is composed from dname.
- */
pstrcpy(fname,dname);
- /* This will mangle fname if it's an illegal name. */
- mangle_map(fname,False,True,conn->params);
-
- if(!(got_match = *got_exact_match = exact_match(conn, fname, mask))) {
+ if(!(got_match = *got_exact_match = exact_match(conn, fname, mask)))
got_match = mask_match(fname, mask, conn->case_sensitive);
- }
if(!got_match && check_mangled_names &&
!mangle_is_8_3(fname, False, conn->params)) {
- pstring mangled_name;
/*
* It turns out that NT matches wildcards against
@@ -1196,25 +1178,21 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
* that some people have been seeing.... JRA.
*/
- pstrcpy(mangled_name, fname);
-
- /* Force the mangling into 8.3. */
- mangle_map( mangled_name, True, False, conn->params);
- if(!(got_match = *got_exact_match = exact_match(conn, mangled_name, mask))) {
- got_match = mask_match(mangled_name, mask, conn->case_sensitive);
- }
+ pstring newname;
+ pstrcpy( newname, fname);
+ mangle_map( newname, True, False, conn->params);
+ if(!(got_match = *got_exact_match = exact_match(conn, newname, mask)))
+ got_match = mask_match(newname, mask, conn->case_sensitive);
}
- if (got_match) {
- BOOL isdots = (strequal(dname,"..") || strequal(dname,"."));
- if (dont_descend && !isdots) {
+ if(got_match) {
+ BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
+ if (dont_descend && !isdots)
continue;
- }
pstrcpy(pathreal,conn->dirpath);
- if(needslash) {
+ if(needslash)
pstrcat(pathreal,"/");
- }
pstrcat(pathreal,dname);
if (INFO_LEVEL_IS_UNIX(info_level)) {
@@ -1252,13 +1230,12 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
}
if (!dir_check_ftype(conn,mode,dirtype)) {
- DEBUG(5,("get_lanman2_dir_entry: [%s] attribs didn't match %x\n",fname,dirtype));
+ DEBUG(5,("[%s] attribs didn't match %x\n",fname,dirtype));
continue;
}
- if (!(mode & aDIR)) {
+ if (!(mode & aDIR))
file_size = get_file_size(sbuf);
- }
allocation_size = get_allocation_size(conn,NULL,&sbuf);
mdate_ts = get_mtimespec(&sbuf);
@@ -1275,7 +1252,7 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
mdate = convert_timespec_to_time_t(mdate_ts);
adate = convert_timespec_to_time_t(adate_ts);
- DEBUG(5,("get_lanman2_dir_entry: found %s fname=%s\n",pathreal,fname));
+ DEBUG(5,("get_lanman2_dir_entry found %s fname=%s\n",pathreal,fname));
found = True;
@@ -1283,6 +1260,8 @@ static BOOL get_lanman2_dir_entry(connection_struct *conn,
}
}
+ mangle_map(fname,False,True,conn->params);
+
p = pdata;
last_entry_ptr = p;
@@ -1749,9 +1728,7 @@ close_if_end = %d requires_resume_key = %d level = 0x%x, max_data_bytes = %d\n",
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
- srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), directory,
- params+12, sizeof(directory), total_params - 12,
- STR_TERMINATE, &ntstatus, &mask_contains_wcard);
+ srvstr_get_path_wcard(inbuf, directory, params+12, sizeof(directory), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
if (!NT_STATUS_IS_OK(ntstatus)) {
return ERROR_NT(ntstatus);
}
@@ -1937,7 +1914,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
SSVAL(params,6,0); /* Never an EA error */
SSVAL(params,8,last_entry_off);
- send_trans2_replies(inbuf, outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
+ send_trans2_replies( outbuf, bufsize, params, 10, pdata, PTR_DIFF(p,pdata), max_data_bytes);
if ((! *directory) && dptr_path(dptr_num))
slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
@@ -2016,20 +1993,17 @@ static int call_trans2findnext(connection_struct *conn, char *inbuf, char *outbu
*mask = *directory = *resume_name = 0;
- srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), resume_name,
- params+12, sizeof(resume_name),
- total_params - 12, STR_TERMINATE, &ntstatus,
- &mask_contains_wcard);
+ srvstr_get_path_wcard(inbuf, resume_name, params+12, sizeof(resume_name), total_params - 12, STR_TERMINATE, &ntstatus, &mask_contains_wcard);
if (!NT_STATUS_IS_OK(ntstatus)) {
/* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
complain (it thinks we're asking for the directory above the shared
path or an invalid name). Catch this as the resume name is only compared, never used in
a file access. JRA. */
- if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) {
- pstrcpy(resume_name, "..");
- } else if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_OBJECT_NAME_INVALID)) {
- pstrcpy(resume_name, ".");
- } else {
+ srvstr_pull(inbuf, resume_name, params+12,
+ sizeof(resume_name), total_params - 12,
+ STR_TERMINATE);
+
+ if (!(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
return ERROR_NT(ntstatus);
}
}
@@ -2233,7 +2207,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
SSVAL(params,4,0); /* Never an EA error */
SSVAL(params,6,last_entry_off);
- send_trans2_replies(inbuf, outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
+ send_trans2_replies( outbuf, bufsize, params, 8, pdata, PTR_DIFF(p,pdata), max_data_bytes);
if ((! *directory) && dptr_path(dptr_num))
slprintf(directory,sizeof(directory)-1, "(%s)",dptr_path(dptr_num));
@@ -2245,12 +2219,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
return(-1);
}
-unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
-{
- E_md4hash(lp_servicename(SNUM(conn)),objid);
- return objid;
-}
-
/****************************************************************************
Reply to a TRANS2_QFSINFO (query filesystem info).
****************************************************************************/
@@ -2358,8 +2326,6 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_dev, (unsi
SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
(lp_nt_acl_support(SNUM(conn)) ? FILE_PERSISTENT_ACLS : 0)|
- FILE_SUPPORTS_OBJECT_IDS|
- FILE_UNICODE_ON_DISK|
quota_flag); /* FS ATTRIBUTES */
SIVAL(pdata,4,255); /* Max filename component length */
@@ -2541,12 +2507,8 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
}
#endif /* HAVE_SYS_QUOTAS */
case SMB_FS_OBJECTID_INFORMATION:
- {
- unsigned char objid[16];
- memcpy(pdata,create_volume_objectid(conn, objid),16);
data_len = 64;
break;
- }
/*
* Query the version and capabilities of the CIFS UNIX extensions
@@ -2566,10 +2528,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
CIFS_UNIX_POSIX_PATHNAMES_CAP|
CIFS_UNIX_FCNTL_LOCKS_CAP|
CIFS_UNIX_EXTATTR_CAP|
- CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
- /* Ensure we don't do this on signed or sealed data. */
- (srv_is_signing_active() ? 0 : CIFS_UNIX_LARGE_READ_CAP)
- )));
+ CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)));
break;
case SMB_QUERY_POSIX_FS_INFO:
@@ -2729,7 +2688,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned
}
- send_trans2_replies(inbuf, outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
+ send_trans2_replies( outbuf, bufsize, params, 0, pdata, data_len, max_data_bytes);
DEBUG( 4, ( "%s info_level = %d\n", smb_fn_name(CVAL(inbuf,smb_com)), info_level) );
@@ -2805,42 +2764,6 @@ cap_low = 0x%x, cap_high = 0x%x\n",
}
break;
}
- case SMB_REQUEST_TRANSPORT_ENCRYPTION:
- {
- NTSTATUS status;
- size_t param_len = 0;
- size_t data_len = total_data;
-
- if (!lp_unix_extensions()) {
- return ERROR_NT(NT_STATUS_INVALID_LEVEL);
- }
-
- DEBUG( 4,("call_trans2setfsinfo: request transport encrption.\n"));
-
- status = srv_request_encryption_setup(conn,
- (unsigned char **)ppdata,
- &data_len,
- (unsigned char **)pparams,
- &param_len
- );
-
- if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- error_packet_set(outbuf, 0, 0, status, __LINE__,__FILE__);
- } else if (!NT_STATUS_IS_OK(status)) {
- return ERROR_NT(status);
- }
-
- send_trans2_replies(inbuf, outbuf, bufsize, *pparams, param_len, *ppdata, data_len, max_data_bytes);
-
- if (NT_STATUS_IS_OK(status)) {
- /* Server-side transport encryption is now *on*. */
- status = srv_encryption_start(conn);
- if (!NT_STATUS_IS_OK(status)) {
- exit_server_cleanly("Failure in setting up encrypted transport");
- }
- }
- return -1;
- }
case SMB_FS_QUOTA_INFORMATION:
{
files_struct *fsp = NULL;
@@ -2925,7 +2848,7 @@ cap_low = 0x%x, cap_high = 0x%x\n",
* like windows do...
* --metze
*/
- outsize = set_message(inbuf, outbuf,10,0,True);
+ outsize = set_message(outbuf,10,0,True);
return outsize;
}
@@ -3219,68 +3142,6 @@ static char *store_file_unix_basic_info2(connection_struct *conn,
}
/****************************************************************************
- Reply to a TRANSACT2_QFILEINFO on a PIPE !
-****************************************************************************/
-
-static int call_trans2qpipeinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
- unsigned int tran_call,
- char **pparams, int total_params, char **ppdata, int total_data,
- unsigned int max_data_bytes)
-{
- char *params = *pparams;
- char *pdata = *ppdata;
- unsigned int data_size = 0;
- unsigned int param_size = 2;
- uint16 info_level;
- smb_np_struct *p_pipe = NULL;
-
- if (!params) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
-
- if (total_params < 4) {
- return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
- }
-
- p_pipe = get_rpc_pipe_p(params,0);
- if (p_pipe == NULL) {
- return ERROR_NT(NT_STATUS_INVALID_HANDLE);
- }
-
- info_level = SVAL(params,2);
-
- *pparams = (char *)SMB_REALLOC(*pparams,2);
- if (*pparams == NULL) {
- return ERROR_NT(NT_STATUS_NO_MEMORY);
- }
- params = *pparams;
- SSVAL(params,0,0);
- data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
- *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
- if (*ppdata == NULL ) {
- return ERROR_NT(NT_STATUS_NO_MEMORY);
- }
- pdata = *ppdata;
-
- switch (info_level) {
- case SMB_FILE_STANDARD_INFORMATION:
- memset(pdata,24,0);
- SOFF_T(pdata,0,4096LL);
- SIVAL(pdata,16,1);
- SIVAL(pdata,20,1);
- data_size = 24;
- break;
-
- default:
- return ERROR_NT(NT_STATUS_INVALID_LEVEL);
- }
-
- send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
-
- return(-1);
-}
-
-/****************************************************************************
Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
file name or file id).
****************************************************************************/
@@ -3325,20 +3186,6 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- if (IS_IPC(conn)) {
- return call_trans2qpipeinfo(conn,
- inbuf,
- outbuf,
- length,
- bufsize,
- tran_call,
- pparams,
- total_params,
- ppdata,
- total_data,
- max_data_bytes);
- }
-
fsp = file_fsp(params,0);
info_level = SVAL(params,2);
@@ -3376,7 +3223,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
return UNIXERROR(ERRDOS,ERRbadpath);
}
- delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
+ delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
} else {
/*
* Original code - this is an open file.
@@ -3389,7 +3236,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
return(UNIXERROR(ERRDOS,ERRbadfid));
}
pos = fsp->fh->position_information;
- delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
+ delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
access_mask = fsp->access_mask;
}
} else {
@@ -3408,9 +3255,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, &params[6],
- sizeof(fname), total_params - 6,
- STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@@ -3444,7 +3289,7 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
return UNIXERROR(ERRDOS,ERRbadpath);
}
- delete_pending = get_delete_on_close_flag(file_id_sbuf(&sbuf));
+ delete_pending = get_delete_on_close_flag(sbuf.st_dev, sbuf.st_ino);
if (delete_pending) {
return ERROR_NT(NT_STATUS_DELETE_PENDING);
}
@@ -3571,7 +3416,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
}
} else {
/* Do we have this path open ? */
- files_struct *fsp1 = file_find_di_first(file_id_sbuf(&sbuf));
+ files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
/* the pending modtime overrides the current modtime */
mtime_ts = fsp1->pending_modtime;
@@ -4121,7 +3966,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
- send_trans2_replies(inbuf, outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
+ send_trans2_replies(outbuf, bufsize, params, param_size, *ppdata, data_size, max_data_bytes);
return(-1);
}
@@ -4177,7 +4022,7 @@ NTSTATUS hardlink_internals(connection_struct *conn, pstring oldname, pstring ne
}
/* Ensure this is within the share. */
- status = check_reduced_name(conn, oldname);
+ status = reduce_name(conn, oldname);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -4311,7 +4156,6 @@ static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
****************************************************************************/
static NTSTATUS smb_set_file_size(connection_struct *conn,
- struct smb_request *req,
files_struct *fsp,
const char *fname,
SMB_STRUCT_STAT *psbuf,
@@ -4341,7 +4185,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
return NT_STATUS_OK;
}
- status = open_file_ntcreate(conn, req, fname, psbuf,
+ status = open_file_ntcreate(conn, fname, psbuf,
FILE_WRITE_DATA,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,
@@ -4539,8 +4383,7 @@ static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
return NT_STATUS_ACCESS_DENIED;
}
- srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), link_target, pdata,
- sizeof(link_target), total_data, STR_TERMINATE);
+ srvstr_pull(inbuf, link_target, pdata, sizeof(link_target), total_data, STR_TERMINATE);
/* !widelinks forces the target path to be within the share. */
/* This means we can interpret the target as a pathname. */
@@ -4596,8 +4439,7 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
return NT_STATUS_INVALID_PARAMETER;
}
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), oldname, pdata,
- sizeof(oldname), total_data, STR_TERMINATE, &status);
+ srvstr_get_path(inbuf, oldname, pdata, sizeof(oldname), total_data, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -4618,7 +4460,6 @@ static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
****************************************************************************/
static NTSTATUS smb_file_rename_information(connection_struct *conn,
- struct smb_request *req,
char *inbuf,
char *outbuf,
const char *pdata,
@@ -4627,7 +4468,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
pstring fname)
{
BOOL overwrite;
- uint32 root_fid;
+ /* uint32 root_fid; */ /* Not used */
uint32 len;
pstring newname;
pstring base_name;
@@ -4640,16 +4481,14 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
}
overwrite = (CVAL(pdata,0) ? True : False);
- root_fid = IVAL(pdata,4);
+ /* root_fid = IVAL(pdata,4); */
len = IVAL(pdata,8);
- if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
+ if (len > (total_data - 12) || (len == 0)) {
return NT_STATUS_INVALID_PARAMETER;
}
- srvstr_get_path_wcard(inbuf, SVAL(inbuf,smb_flg2), newname, &pdata[12],
- sizeof(newname), len, 0, &status,
- &dest_has_wcard);
+ srvstr_get_path_wcard(inbuf, newname, &pdata[12], sizeof(newname), len, 0, &status, &dest_has_wcard);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -4682,8 +4521,7 @@ static NTSTATUS smb_file_rename_information(connection_struct *conn,
} else {
DEBUG(10,("smb_file_rename_information: SMB_FILE_RENAME_INFORMATION %s -> %s\n",
fname, newname ));
- status = rename_internals(conn, req, fname, base_name, 0,
- overwrite, False, dest_has_wcard);
+ status = rename_internals(conn, fname, base_name, 0, overwrite, False, dest_has_wcard);
}
return status;
@@ -4828,8 +4666,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
(double)offset ));
if (lock_type == UNLOCK_LOCK) {
- status = do_unlock(smbd_messaging_context(),
- fsp,
+ status = do_unlock(fsp,
lock_pid,
count,
offset,
@@ -4837,8 +4674,7 @@ static NTSTATUS smb_set_posix_lock(connection_struct *conn,
} else {
uint32 block_smbpid;
- struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(),
- fsp,
+ struct byte_range_lock *br_lck = do_lock(fsp,
lock_pid,
count,
offset,
@@ -4974,7 +4810,6 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
****************************************************************************/
static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
- struct smb_request *req,
const char *pdata,
int total_data,
files_struct *fsp,
@@ -5010,24 +4845,31 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
allocation_size = smb_roundup(conn, allocation_size);
}
- if(allocation_size == get_file_size(*psbuf)) {
- return NT_STATUS_OK;
- }
-
DEBUG(10,("smb_set_file_allocation_info: file %s : setting new allocation size to %.0f\n",
fname, (double)allocation_size ));
-
+
if (fsp && fsp->fh->fd != -1) {
/* Open file handle. */
- if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
- return map_nt_error_from_unix(errno);
+ /* Only change if needed. */
+ if (allocation_size != get_file_size(*psbuf)) {
+ if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
+ return map_nt_error_from_unix(errno);
+ }
+ }
+ /* But always update the time. */
+ if (null_timespec(fsp->pending_modtime)) {
+ /*
+ * This is equivalent to a write. Ensure it's seen immediately
+ * if there are no pending writes.
+ */
+ set_filetime(fsp->conn, fsp->fsp_name, timespec_current());
}
return NT_STATUS_OK;
}
/* Pathname or stat or directory file. */
- status = open_file_ntcreate(conn, req, fname, psbuf,
+ status = open_file_ntcreate(conn, fname, psbuf,
FILE_WRITE_DATA,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,
@@ -5035,17 +4877,27 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
FILE_ATTRIBUTE_NORMAL,
FORCE_OPLOCK_BREAK_TO_NONE,
NULL, &new_fsp);
-
+
if (!NT_STATUS_IS_OK(status)) {
/* NB. We check for open_was_deferred in the caller. */
return status;
}
- if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
- status = map_nt_error_from_unix(errno);
- close_file(new_fsp,NORMAL_CLOSE);
- return status;
+
+ /* Only change if needed. */
+ if (allocation_size != get_file_size(*psbuf)) {
+ if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
+ status = map_nt_error_from_unix(errno);
+ close_file(new_fsp,NORMAL_CLOSE);
+ return status;
+ }
}
+ /* Changing the allocation size should set the last mod time. */
+ /* Don't need to call set_filetime as this will be flushed on
+ * close. */
+
+ fsp_set_pending_modtime(new_fsp, timespec_current());
+
close_file(new_fsp,NORMAL_CLOSE);
return NT_STATUS_OK;
}
@@ -5055,7 +4907,6 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
****************************************************************************/
static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
- struct smb_request *req,
const char *pdata,
int total_data,
files_struct *fsp,
@@ -5080,7 +4931,7 @@ static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
"file %s to %.0f\n", fname, (double)size ));
- return smb_set_file_size(conn, req,
+ return smb_set_file_size(conn,
fsp,
fname,
psbuf,
@@ -5176,7 +5027,6 @@ static NTSTATUS smb_unix_mknod(connection_struct *conn,
****************************************************************************/
static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
- struct smb_request *req,
const char *pdata,
int total_data,
files_struct *fsp,
@@ -5290,18 +5140,9 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
*/
if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) && (psbuf->st_uid != set_owner)) {
- int ret;
-
- DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for path %s\n",
+ DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC changing owner %u for file %s\n",
(unsigned int)set_owner, fname ));
-
- if (S_ISLNK(psbuf->st_mode)) {
- ret = SMB_VFS_LCHOWN(conn, fname, set_owner, (gid_t)-1);
- } else {
- ret = SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1);
- }
-
- if (ret != 0) {
+ if (SMB_VFS_CHOWN(conn, fname, set_owner, (gid_t)-1) != 0) {
status = map_nt_error_from_unix(errno);
if (delete_on_fail) {
SMB_VFS_UNLINK(conn,fname);
@@ -5328,7 +5169,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
/* Deal with any size changes. */
- status = smb_set_file_size(conn, req,
+ status = smb_set_file_size(conn,
fsp,
fname,
psbuf,
@@ -5351,7 +5192,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
****************************************************************************/
static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
- struct smb_request *req,
const char *pdata,
int total_data,
files_struct *fsp,
@@ -5369,7 +5209,7 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
/* Start by setting all the fields that are common between UNIX_BASIC
* and UNIX_INFO2.
*/
- status = smb_set_file_unix_basic(conn, req, pdata, total_data,
+ status = smb_set_file_unix_basic(conn, pdata, total_data,
fsp, fname, psbuf);
if (!NT_STATUS_IS_OK(status)) {
return status;
@@ -5413,7 +5253,6 @@ static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
****************************************************************************/
static NTSTATUS smb_posix_mkdir(connection_struct *conn,
- struct smb_request *req,
char **ppdata,
int total_data,
const char *fname,
@@ -5446,7 +5285,7 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
fname, (unsigned int)unixmode ));
- status = open_directory(conn, req,
+ status = open_directory(conn,
fname,
psbuf,
FILE_READ_ATTRIBUTES, /* Just a stat open */
@@ -5508,7 +5347,6 @@ static NTSTATUS smb_posix_mkdir(connection_struct *conn,
****************************************************************************/
static NTSTATUS smb_posix_open(connection_struct *conn,
- struct smb_request *req,
char **ppdata,
int total_data,
const char *fname,
@@ -5544,7 +5382,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
wire_open_mode = IVAL(pdata,4);
if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
- return smb_posix_mkdir(conn, req,
+ return smb_posix_mkdir(conn,
ppdata,
total_data,
fname,
@@ -5612,7 +5450,7 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
(unsigned int)wire_open_mode,
(unsigned int)unixmode ));
- status = open_file_ntcreate(conn, req,
+ status = open_file_ntcreate(conn,
fname,
psbuf,
access_mask,
@@ -5696,7 +5534,6 @@ static NTSTATUS smb_posix_open(connection_struct *conn,
****************************************************************************/
static NTSTATUS smb_posix_unlink(connection_struct *conn,
- struct smb_request *req,
const char *pdata,
int total_data,
const char *fname,
@@ -5705,7 +5542,10 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
NTSTATUS status = NT_STATUS_OK;
files_struct *fsp = NULL;
uint16 flags = 0;
+ char del = 1;
int info = 0;
+ int i;
+ struct share_mode_lock *lck = NULL;
if (total_data < 2) {
return NT_STATUS_INVALID_PARAMETER;
@@ -5727,20 +5567,19 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
fname));
if (VALID_STAT_OF_DIR(*psbuf)) {
- status = open_directory(conn, req,
+ status = open_directory(conn,
fname,
psbuf,
DELETE_ACCESS,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
FILE_OPEN,
- FILE_DELETE_ON_CLOSE,
+ 0,
FILE_FLAG_POSIX_SEMANTICS|0777,
- &info,
+ &info,
&fsp);
} else {
- char del = 1;
- status = open_file_ntcreate(conn, req,
+ status = open_file_ntcreate(conn,
fname,
psbuf,
DELETE_ACCESS,
@@ -5751,26 +5590,59 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
0, /* No oplock, but break existing ones. */
&info,
&fsp);
- /*
- * For file opens we must set the delete on close
- * after the open.
- */
+ }
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
- status = smb_set_file_disposition_info(conn,
- &del,
- 1,
- fsp,
- fname,
- psbuf);
+ /*
+ * Don't lie to client. If we can't really delete due to
+ * non-POSIX opens return SHARING_VIOLATION.
+ */
+
+ lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL, NULL);
+ if (lck == NULL) {
+ DEBUG(0, ("smb_posix_unlink: Could not get share mode "
+ "lock for file %s\n", fsp->fsp_name));
+ close_file(fsp, NORMAL_CLOSE);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ /*
+ * See if others still have the file open. If this is the case, then
+ * don't delete. If all opens are POSIX delete we can set the delete
+ * on close disposition.
+ */
+ for (i=0; i<lck->num_share_modes; i++) {
+ struct share_mode_entry *e = &lck->share_modes[i];
+ if (is_valid_share_mode_entry(e)) {
+ if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
+ continue;
+ }
+ /* Fail with sharing violation. */
+ close_file(fsp, NORMAL_CLOSE);
+ TALLOC_FREE(lck);
+ return NT_STATUS_SHARING_VIOLATION;
+ }
}
+ /*
+ * Set the delete on close.
+ */
+ status = smb_set_file_disposition_info(conn,
+ &del,
+ 1,
+ fsp,
+ fname,
+ psbuf);
+
if (!NT_STATUS_IS_OK(status)) {
+ close_file(fsp, NORMAL_CLOSE);
+ TALLOC_FREE(lck);
return status;
}
+ TALLOC_FREE(lck);
return close_file(fsp, NORMAL_CLOSE);
}
@@ -5778,10 +5650,7 @@ static NTSTATUS smb_posix_unlink(connection_struct *conn,
Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
****************************************************************************/
-static int call_trans2setfilepathinfo(connection_struct *conn,
- struct smb_request *req,
- char *inbuf, char *outbuf, int length,
- int bufsize,
+static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char *outbuf, int length, int bufsize,
unsigned int tran_call,
char **pparams, int total_params, char **ppdata, int total_data,
unsigned int max_data_bytes)
@@ -5838,7 +5707,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
DEBUG(3,("call_trans2setfilepathinfo: Cancelling print job (%s)\n", fsp->fsp_name ));
SSVAL(params,0,0);
- send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
return(-1);
} else
return (UNIXERROR(ERRDOS,ERRbadpath));
@@ -5862,9 +5731,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
}
info_level = SVAL(params,0);
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), fname, &params[6],
- sizeof(fname), total_params - 6, STR_TERMINATE,
- &status);
+ srvstr_get_path(inbuf, fname, &params[6], sizeof(fname), total_params - 6, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@@ -5964,7 +5831,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
case SMB_FILE_ALLOCATION_INFORMATION:
case SMB_SET_FILE_ALLOCATION_INFO:
{
- status = smb_set_file_allocation_info(conn, req,
+ status = smb_set_file_allocation_info(conn,
pdata,
total_data,
fsp,
@@ -5976,7 +5843,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
case SMB_FILE_END_OF_FILE_INFORMATION:
case SMB_SET_FILE_END_OF_FILE_INFO:
{
- status = smb_set_file_end_of_file_info(conn, req,
+ status = smb_set_file_end_of_file_info(conn,
pdata,
total_data,
fsp,
@@ -6035,7 +5902,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
case SMB_SET_FILE_UNIX_BASIC:
{
- status = smb_set_file_unix_basic(conn, req,
+ status = smb_set_file_unix_basic(conn,
pdata,
total_data,
fsp,
@@ -6046,7 +5913,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
case SMB_SET_FILE_UNIX_INFO2:
{
- status = smb_set_file_unix_info2(conn, req,
+ status = smb_set_file_unix_info2(conn,
pdata,
total_data,
fsp,
@@ -6086,7 +5953,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
case SMB_FILE_RENAME_INFORMATION:
{
- status = smb_file_rename_information(conn, req,
+ status = smb_file_rename_information(conn,
inbuf,
outbuf,
pdata,
@@ -6130,7 +5997,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
- status = smb_posix_open(conn, req,
+ status = smb_posix_open(conn,
ppdata,
total_data,
fname,
@@ -6146,7 +6013,7 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
return ERROR_NT(NT_STATUS_INVALID_LEVEL);
}
- status = smb_posix_unlink(conn, req,
+ status = smb_posix_unlink(conn,
pdata,
total_data,
fname,
@@ -6171,11 +6038,14 @@ static int call_trans2setfilepathinfo(connection_struct *conn,
if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
return ERROR_BOTH(NT_STATUS_PATH_NOT_COVERED, ERRSRV, ERRbadpath);
}
+ if (info_level == SMB_POSIX_PATH_OPEN) {
+ return ERROR_OPEN(status);
+ }
return ERROR_NT(status);
}
SSVAL(params,0,0);
- send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, data_return_size, max_data_bytes);
return -1;
}
@@ -6202,9 +6072,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
}
- srvstr_get_path(inbuf, SVAL(inbuf,smb_flg2), directory, &params[4],
- sizeof(directory), total_params - 4, STR_TERMINATE,
- &status);
+ srvstr_get_path(inbuf, directory, &params[4], sizeof(directory), total_params - 4, STR_TERMINATE, &status);
if (!NT_STATUS_IS_OK(status)) {
return ERROR_NT(status);
}
@@ -6276,7 +6144,7 @@ static int call_trans2mkdir(connection_struct *conn, char *inbuf, char *outbuf,
SSVAL(params,0,0);
- send_trans2_replies(inbuf, outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0, max_data_bytes);
return(-1);
}
@@ -6325,7 +6193,7 @@ static int call_trans2findnotifyfirst(connection_struct *conn, char *inbuf, char
if(fnf_handle == 0)
fnf_handle = 257;
- send_trans2_replies(inbuf, outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(outbuf, bufsize, params, 6, *ppdata, 0, max_data_bytes);
return(-1);
}
@@ -6353,7 +6221,7 @@ static int call_trans2findnotifynext(connection_struct *conn, char *inbuf, char
SSVAL(params,0,0); /* No changes */
SSVAL(params,2,0); /* No EA errors */
- send_trans2_replies(inbuf, outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
+ send_trans2_replies(outbuf, bufsize, params, 4, *ppdata, 0, max_data_bytes);
return(-1);
}
@@ -6383,13 +6251,12 @@ static int call_trans2getdfsreferral(connection_struct *conn, char* inbuf, char*
if(!lp_host_msdfs())
return ERROR_DOS(ERRDOS,ERRbadfunc);
- srvstr_pull(inbuf, SVAL(inbuf, smb_flg2), pathname, &params[2],
- sizeof(pathname), total_params - 2, STR_TERMINATE);
+ srvstr_pull(inbuf, pathname, &params[2], sizeof(pathname), total_params - 2, STR_TERMINATE);
if((reply_size = setup_dfs_referral(conn, pathname,max_referral_level,ppdata,&status)) < 0)
return ERROR_NT(status);
SSVAL(outbuf,smb_flg2,SVAL(outbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
- send_trans2_replies(inbuf, outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
+ send_trans2_replies(outbuf,bufsize,0,0,*ppdata,reply_size, max_data_bytes);
return(-1);
}
@@ -6427,7 +6294,7 @@ static int call_trans2ioctl(connection_struct *conn, char* inbuf, char* outbuf,
SSVAL(pdata,0,fsp->rap_print_jobid); /* Job number */
srvstr_push( outbuf, pdata + 2, global_myname(), 15, STR_ASCII|STR_TERMINATE); /* Our NetBIOS name */
srvstr_push( outbuf, pdata+18, lp_servicename(SNUM(conn)), 13, STR_ASCII|STR_TERMINATE); /* Service name */
- send_trans2_replies(inbuf, outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
+ send_trans2_replies(outbuf,bufsize,*pparams,0,*ppdata,32, max_data_bytes);
return(-1);
} else {
DEBUG(2,("Unknown TRANS2_IOCTL\n"));
@@ -6450,7 +6317,7 @@ int reply_findclose(connection_struct *conn,
dptr_close(&dptr_num);
- outsize = set_message(inbuf, outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
@@ -6477,7 +6344,7 @@ int reply_findnclose(connection_struct *conn,
findnotifyfirst - so any dptr_num is ok here.
Just ignore it. */
- outsize = set_message(inbuf, outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
@@ -6485,9 +6352,9 @@ int reply_findnclose(connection_struct *conn,
return(outsize);
}
-static int handle_trans2(connection_struct *conn, struct smb_request *req,
- struct trans_state *state,
- char *inbuf, char *outbuf, int size, int bufsize)
+int handle_trans2(connection_struct *conn,
+ struct trans_state *state,
+ char *inbuf, char *outbuf, int size, int bufsize)
{
int outsize;
@@ -6501,7 +6368,7 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req,
{
START_PROFILE(Trans2_open);
outsize = call_trans2open(
- conn, req, inbuf, outbuf, bufsize,
+ conn, inbuf, outbuf, bufsize,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
@@ -6575,7 +6442,7 @@ static int handle_trans2(connection_struct *conn, struct smb_request *req,
{
START_PROFILE(Trans2_setpathinfo);
outsize = call_trans2setfilepathinfo(
- conn, req, inbuf, outbuf, size, bufsize, state->call,
+ conn, inbuf, outbuf, size, bufsize, state->call,
&state->param, state->total_param,
&state->data, state->total_data,
state->max_data_return);
@@ -6679,8 +6546,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
}
if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN)
- && (tran_call != TRANSACT2_GET_DFS_REFERRAL)
- && (tran_call != TRANSACT2_QFILEINFO)) {
+ && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) {
END_PROFILE(SMBtrans2);
return ERROR_DOS(ERRSRV,ERRaccess);
}
@@ -6783,10 +6649,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
if ((state->received_param == state->total_param) &&
(state->received_data == state->total_data)) {
- struct smb_request req;
- init_smb_request(&req, (uint8 *)inbuf);
-
- outsize = handle_trans2(conn, &req, state, inbuf, outbuf,
+ outsize = handle_trans2(conn, state, inbuf, outbuf,
size, bufsize);
SAFE_FREE(state->data);
SAFE_FREE(state->param);
@@ -6799,7 +6662,7 @@ int reply_trans2(connection_struct *conn, char *inbuf,char *outbuf,
/* We need to send an interim response then receive the rest
of the parameter/data bytes */
- outsize = set_message(inbuf, outbuf,0,0,False);
+ outsize = set_message(outbuf,0,0,False);
show_msg(outbuf);
END_PROFILE(SMBtrans2);
return outsize;
@@ -6825,7 +6688,6 @@ int reply_transs2(connection_struct *conn,
int outsize = 0;
unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
struct trans_state *state;
- struct smb_request req;
START_PROFILE(SMBtranss2);
@@ -6911,10 +6773,7 @@ int reply_transs2(connection_struct *conn,
*/
SCVAL(outbuf,smb_com,SMBtrans2);
- init_smb_request(&req, (uint8 *)inbuf);
-
- outsize = handle_trans2(conn, &req, state, inbuf, outbuf, size,
- bufsize);
+ outsize = handle_trans2(conn, state, inbuf, outbuf, size, bufsize);
DLIST_REMOVE(conn->pending_trans, state);
SAFE_FREE(state->data);
diff --git a/source/smbd/vfs.c b/source/smbd/vfs.c
index b854c36a7ba..2fd448061e4 100644
--- a/source/smbd/vfs.c
+++ b/source/smbd/vfs.c
@@ -802,7 +802,7 @@ char *vfs_GetWd(connection_struct *conn, char *path)
it is below dir in the heirachy. This uses realpath.
********************************************************************/
-NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
+NTSTATUS reduce_name(connection_struct *conn, const pstring fname)
{
#ifdef REALPATH_TAKES_NULL
BOOL free_resolved_name = True;