diff options
author | Jeremy Allison <jra@samba.org> | 2008-11-11 10:20:24 -0800 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2008-11-11 10:20:24 -0800 |
commit | 4f2635b729e636e123afacb0970c3d49343b3e90 (patch) | |
tree | 76d632982f23f08b23593af78614e9414dbbac2c /source3/smbd | |
parent | 8cb23a6b2950d7419767845b6097470f76f348a7 (diff) | |
parent | 2e6bf03e519e180a1ee672dc9c9171d9e0cd114f (diff) | |
download | samba-4f2635b729e636e123afacb0970c3d49343b3e90.tar.gz samba-4f2635b729e636e123afacb0970c3d49343b3e90.tar.bz2 samba-4f2635b729e636e123afacb0970c3d49343b3e90.zip |
Merge branch 'master' of ssh://jra@git.samba.org/data/git/samba
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/aio.c | 177 | ||||
-rw-r--r-- | source3/smbd/blocking.c | 372 | ||||
-rw-r--r-- | source3/smbd/chgpasswd.c | 6 | ||||
-rw-r--r-- | source3/smbd/ipc.c | 152 | ||||
-rw-r--r-- | source3/smbd/lanman.c | 2 | ||||
-rw-r--r-- | source3/smbd/mangle.c | 2 | ||||
-rw-r--r-- | source3/smbd/map_username.c | 2 | ||||
-rw-r--r-- | source3/smbd/message.c | 40 | ||||
-rw-r--r-- | source3/smbd/negprot.c | 17 | ||||
-rw-r--r-- | source3/smbd/notify.c | 82 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 110 | ||||
-rw-r--r-- | source3/smbd/open.c | 191 | ||||
-rw-r--r-- | source3/smbd/password.c | 2 | ||||
-rw-r--r-- | source3/smbd/pipes.c | 28 | ||||
-rw-r--r-- | source3/smbd/posix_acls.c | 4 | ||||
-rw-r--r-- | source3/smbd/process.c | 31 | ||||
-rw-r--r-- | source3/smbd/reply.c | 592 | ||||
-rw-r--r-- | source3/smbd/server.c | 8 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 128 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 81 | ||||
-rw-r--r-- | source3/smbd/uid.c | 2 |
21 files changed, 975 insertions, 1054 deletions
diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index c3fd0a2bc0..8beed0744c 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -45,94 +45,52 @@ struct aio_extra { struct aio_extra *next, *prev; SMB_STRUCT_AIOCB acb; files_struct *fsp; - bool read_req; - uint16 mid; - char *inbuf; + struct smb_request *req; char *outbuf; + int (*handle_completion)(struct aio_extra *ex); }; -static struct aio_extra *aio_list_head; +static int handle_aio_read_complete(struct aio_extra *aio_ex); +static int handle_aio_write_complete(struct aio_extra *aio_ex); -/**************************************************************************** - Create the extended aio struct we must keep around for the lifetime - of the aio_read call. -*****************************************************************************/ +static struct aio_extra *aio_list_head; -static struct aio_extra *create_aio_ex_read(files_struct *fsp, size_t buflen, - uint16 mid) +static int aio_extra_destructor(struct aio_extra *aio_ex) { - struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); - - if (!aio_ex) { - return NULL; - } - ZERO_STRUCTP(aio_ex); - /* The output buffer stored in the aio_ex is the start of - the smb return buffer. The buffer used in the acb - is the start of the reply data portion of that buffer. */ - aio_ex->outbuf = SMB_MALLOC_ARRAY(char, buflen); - if (!aio_ex->outbuf) { - SAFE_FREE(aio_ex); - return NULL; - } - DLIST_ADD(aio_list_head, aio_ex); - aio_ex->fsp = fsp; - aio_ex->read_req = True; - aio_ex->mid = mid; - return aio_ex; + DLIST_REMOVE(aio_list_head, aio_ex); + return 0; } /**************************************************************************** Create the extended aio struct we must keep around for the lifetime - of the aio_write call. + of the aio call. *****************************************************************************/ -static struct aio_extra *create_aio_ex_write(files_struct *fsp, - size_t inbuflen, - size_t outbuflen, - uint16 mid) +static struct aio_extra *create_aio_extra(files_struct *fsp, size_t buflen) { - struct aio_extra *aio_ex = SMB_MALLOC_P(struct aio_extra); + struct aio_extra *aio_ex = TALLOC_ZERO_P(NULL, struct aio_extra); if (!aio_ex) { return NULL; } - ZERO_STRUCTP(aio_ex); - /* We need space for an output reply of outbuflen bytes. */ - aio_ex->outbuf = SMB_MALLOC_ARRAY(char, outbuflen); - if (!aio_ex->outbuf) { - SAFE_FREE(aio_ex); - return NULL; - } + /* The output buffer stored in the aio_ex is the start of + the smb return buffer. The buffer used in the acb + is the start of the reply data portion of that buffer. */ - if (!(aio_ex->inbuf = SMB_MALLOC_ARRAY(char, inbuflen))) { - SAFE_FREE(aio_ex->outbuf); - SAFE_FREE(aio_ex); + aio_ex->outbuf = TALLOC_ARRAY(aio_ex, char, buflen); + if (!aio_ex->outbuf) { + TALLOC_FREE(aio_ex); return NULL; } - DLIST_ADD(aio_list_head, aio_ex); + talloc_set_destructor(aio_ex, aio_extra_destructor); aio_ex->fsp = fsp; - aio_ex->read_req = False; - aio_ex->mid = mid; return aio_ex; } /**************************************************************************** - Delete the extended aio struct. -*****************************************************************************/ - -static void delete_aio_ex(struct aio_extra *aio_ex) -{ - DLIST_REMOVE(aio_list_head, aio_ex); - SAFE_FREE(aio_ex->inbuf); - SAFE_FREE(aio_ex->outbuf); - SAFE_FREE(aio_ex); -} - -/**************************************************************************** - Given the aiocb struct find the extended aio struct containing it. + Given the mid find the extended aio struct containing it. *****************************************************************************/ static struct aio_extra *find_aio_ex(uint16 mid) @@ -140,7 +98,7 @@ static struct aio_extra *find_aio_ex(uint16 mid) struct aio_extra *p; for( p = aio_list_head; p; p = p->next) { - if (mid == p->mid) { + if (mid == p->req->mid) { return p; } } @@ -221,6 +179,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, SMB_STRUCT_AIOCB *a; size_t bufsize; size_t min_aio_read_size = lp_aio_read_size(SNUM(conn)); + int ret; if (fsp->base_fsp != NULL) { /* No AIO on streams yet */ @@ -240,7 +199,7 @@ bool schedule_aio_read_and_X(connection_struct *conn, /* Only do this on non-chained and non-chaining reads not using the * write cache. */ - if (chain_size !=0 || (CVAL(req->inbuf,smb_vwv0) != 0xFF) + if (chain_size !=0 || (CVAL(req->vwv+0, 0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { return False; } @@ -257,43 +216,47 @@ bool schedule_aio_read_and_X(connection_struct *conn, bufsize = smb_size + 12 * 2 + smb_maxcnt; - if ((aio_ex = create_aio_ex_read(fsp, bufsize, req->mid)) == NULL) { + if ((aio_ex = create_aio_extra(fsp, bufsize)) == NULL) { DEBUG(10,("schedule_aio_read_and_X: malloc fail.\n")); return False; } + aio_ex->handle_completion = handle_aio_read_complete; - construct_reply_common((char *)req->inbuf, aio_ex->outbuf); + construct_reply_common_req(req, aio_ex->outbuf); srv_set_message(aio_ex->outbuf, 12, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; /* Now set up the aio record for the read call. */ - + a->aio_fildes = fsp->fh->fd; a->aio_buf = smb_buf(aio_ex->outbuf); a->aio_nbytes = smb_maxcnt; a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; - a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; + a->aio_sigevent.sigev_value.sival_int = req->mid; become_root(); - if (SMB_VFS_AIO_READ(fsp,a) == -1) { + ret = SMB_VFS_AIO_READ(fsp, a); + unbecome_root(); + + if (ret == -1) { DEBUG(0,("schedule_aio_read_and_X: aio_read failed. " "Error %s\n", strerror(errno) )); - delete_aio_ex(aio_ex); - unbecome_root(); + TALLOC_FREE(aio_ex); return False; } - unbecome_root(); + + aio_ex->req = talloc_move(aio_ex, &req); DEBUG(10,("schedule_aio_read_and_X: scheduled aio_read for file %s, " "offset %.0f, len = %u (mid = %u)\n", fsp->fsp_name, (double)startpos, (unsigned int)smb_maxcnt, - (unsigned int)aio_ex->mid )); + (unsigned int)aio_ex->req->mid )); - srv_defer_sign_response(aio_ex->mid); + srv_defer_sign_response(aio_ex->req->mid); outstanding_aio_calls++; return True; } @@ -310,9 +273,10 @@ 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(req->inbuf+smb_vwv7,0); + size_t bufsize; + bool write_through = BITSETW(req->vwv+7,0); size_t min_aio_write_size = lp_aio_write_size(SNUM(conn)); + int ret; if (fsp->base_fsp != NULL) { /* No AIO on streams yet */ @@ -332,7 +296,7 @@ bool schedule_aio_write_and_X(connection_struct *conn, /* Only do this on non-chained and non-chaining reads not using the * write cache. */ - if (chain_size !=0 || (CVAL(req->inbuf,smb_vwv0) != 0xFF) + if (chain_size !=0 || (CVAL(req->vwv+0, 0) != 0xFF) || (lp_write_cache_size(SNUM(conn)) != 0) ) { return False; } @@ -350,45 +314,43 @@ bool schedule_aio_write_and_X(connection_struct *conn, return False; } - inbufsize = smb_len(req->inbuf) + 4; - reply_outbuf(req, 6, 0); - outbufsize = smb_len(req->outbuf) + 4; - if (!(aio_ex = create_aio_ex_write(fsp, inbufsize, outbufsize, - req->mid))) { + bufsize = smb_size + 6*2; + + if (!(aio_ex = create_aio_extra(fsp, bufsize))) { DEBUG(0,("schedule_aio_write_and_X: malloc fail.\n")); return False; } + aio_ex->handle_completion = handle_aio_write_complete; - /* Copy the SMB header already setup in outbuf. */ - memcpy(aio_ex->inbuf, req->inbuf, inbufsize); - - /* Copy the SMB header already setup in outbuf. */ - memcpy(aio_ex->outbuf, req->outbuf, outbufsize); - TALLOC_FREE(req->outbuf); + construct_reply_common_req(req, aio_ex->outbuf); + srv_set_message(aio_ex->outbuf, 6, 0, True); SCVAL(aio_ex->outbuf,smb_vwv0,0xFF); /* Never a chained reply. */ a = &aio_ex->acb; /* Now set up the aio record for the write call. */ - + a->aio_fildes = fsp->fh->fd; - a->aio_buf = aio_ex->inbuf + (PTR_DIFF(data, req->inbuf)); + a->aio_buf = data; a->aio_nbytes = numtowrite; a->aio_offset = startpos; a->aio_sigevent.sigev_notify = SIGEV_SIGNAL; a->aio_sigevent.sigev_signo = RT_SIGNAL_AIO; - a->aio_sigevent.sigev_value.sival_int = aio_ex->mid; + a->aio_sigevent.sigev_value.sival_int = req->mid; become_root(); - if (SMB_VFS_AIO_WRITE(fsp,a) == -1) { + ret = SMB_VFS_AIO_WRITE(fsp, a); + unbecome_root(); + + if (ret == -1) { DEBUG(3,("schedule_aio_wrote_and_X: aio_write failed. " "Error %s\n", strerror(errno) )); - delete_aio_ex(aio_ex); - unbecome_root(); + TALLOC_FREE(aio_ex); return False; } - unbecome_root(); - + + aio_ex->req = talloc_move(aio_ex, &req); + release_level_2_oplocks_on_change(fsp); if (!write_through && !lp_syncalways(SNUM(fsp->conn)) @@ -406,7 +368,7 @@ bool schedule_aio_write_and_X(connection_struct *conn, DEBUG(10,("schedule_aio_write_and_X: scheduled aio_write " "behind for file %s\n", fsp->fsp_name )); } else { - srv_defer_sign_response(aio_ex->mid); + srv_defer_sign_response(aio_ex->req->mid); } outstanding_aio_calls++; @@ -414,7 +376,7 @@ bool schedule_aio_write_and_X(connection_struct *conn, "%s, offset %.0f, len = %u (mid = %u) " "outstanding_aio_calls = %d\n", fsp->fsp_name, (double)startpos, (unsigned int)numtowrite, - (unsigned int)aio_ex->mid, outstanding_aio_calls )); + (unsigned int)aio_ex->req->mid, outstanding_aio_calls )); return True; } @@ -442,7 +404,7 @@ static int handle_aio_read_complete(struct aio_extra *aio_ex) /* If errno is ECANCELED then don't return anything to the * client. */ if (errno == ECANCELED) { - srv_cancel_sign_response(aio_ex->mid); + srv_cancel_sign_response(aio_ex->req->mid); return 0; } @@ -536,7 +498,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) /* If errno is ECANCELED then don't return anything to the * client. */ if (errno == ECANCELED) { - srv_cancel_sign_response(aio_ex->mid); + srv_cancel_sign_response(aio_ex->req->mid); return 0; } @@ -544,7 +506,7 @@ static int handle_aio_write_complete(struct aio_extra *aio_ex) ERROR_BOTH(map_nt_error_from_unix(ret), ERRHRD, ERRdiskfull); srv_set_message(outbuf,0,0,true); } else { - bool write_through = BITSETW(aio_ex->inbuf+smb_vwv7,0); + bool write_through = BITSETW(aio_ex->req->vwv+7,0); NTSTATUS status; SSVAL(outbuf,smb_vwv2,nwritten); @@ -600,16 +562,11 @@ static bool handle_aio_completed(struct aio_extra *aio_ex, int *perr) if (SMB_VFS_AIO_ERROR(aio_ex->fsp, &aio_ex->acb) == EINPROGRESS) { DEBUG(10,( "handle_aio_completed: operation mid %u still in " "process for file %s\n", - aio_ex->mid, aio_ex->fsp->fsp_name )); + aio_ex->req->mid, aio_ex->fsp->fsp_name )); return False; } - if (aio_ex->read_req) { - err = handle_aio_read_complete(aio_ex); - } else { - err = handle_aio_write_complete(aio_ex); - } - + err = aio_ex->handle_completion(aio_ex); if (err) { *perr = err; /* Only save non-zero errors. */ } @@ -666,7 +623,7 @@ int process_aio_queue(void) continue; } - delete_aio_ex(aio_ex); + TALLOC_FREE(aio_ex); } outstanding_aio_calls -= signals_received; @@ -738,7 +695,7 @@ int wait_for_aio_completion(files_struct *fsp) 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 " @@ -767,7 +724,7 @@ int wait_for_aio_completion(files_struct *fsp) if (!handle_aio_completed(aio_ex, &err)) { continue; } - delete_aio_ex(aio_ex); + TALLOC_FREE(aio_ex); } SAFE_FREE(aiocb_list); diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 4374b50eac..2237a89ace 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -2,17 +2,17 @@ Unix SMB/CIFS implementation. Blocking Locking functions Copyright (C) Jeremy Allison 1998-2003 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -26,10 +26,9 @@ notify. It consists of the requesting SMB and the expiry time. *****************************************************************************/ -typedef struct _blocking_lock_record { - struct _blocking_lock_record *next; - struct _blocking_lock_record *prev; - int com_type; +typedef struct blocking_lock_record { + struct blocking_lock_record *next; + struct blocking_lock_record *prev; files_struct *fsp; struct timeval expire_time; int lock_num; @@ -39,9 +38,7 @@ typedef struct _blocking_lock_record { uint32_t blocking_pid; /* PID that blocks us. */ enum brl_flavour lock_flav; enum brl_type lock_type; - char *inbuf; - int length; - bool encrypted; + struct smb_request *req; } blocking_lock_record; /* dlink list we store pending lock records on. */ @@ -54,16 +51,6 @@ static blocking_lock_record *blocking_lock_cancelled_queue; static struct timed_event *brl_timeout; /**************************************************************************** - Destructor for the above structure. -****************************************************************************/ - -static void free_blocking_lock_record(blocking_lock_record *blr) -{ - SAFE_FREE(blr->inbuf); - SAFE_FREE(blr); -} - -/**************************************************************************** Determine if this is a secondary element of a chained SMB. **************************************************************************/ @@ -150,7 +137,7 @@ static bool recalc_brl_timeout(void) ****************************************************************************/ bool push_blocking_lock_request( struct byte_range_lock *br_lck, - const struct smb_request *req, + struct smb_request *req, files_struct *fsp, int lock_timeout, int lock_num, @@ -162,7 +149,6 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, uint32_t blocking_pid) { static bool set_lock_msg; - size_t length = smb_len(req->inbuf)+4; blocking_lock_record *blr; NTSTATUS status; @@ -176,7 +162,8 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, * the expiration time here. */ - if((blr = SMB_MALLOC_P(blocking_lock_record)) == NULL) { + blr = talloc(NULL, struct blocking_lock_record); + if (blr == NULL) { DEBUG(0,("push_blocking_lock_request: Malloc fail !\n" )); return False; } @@ -184,13 +171,6 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, blr->next = NULL; blr->prev = NULL; - if((blr->inbuf = (char *)SMB_MALLOC(length)) == NULL) { - DEBUG(0,("push_blocking_lock_request: Malloc fail (2)!\n" )); - SAFE_FREE(blr); - return False; - } - - blr->com_type = CVAL(req->inbuf,smb_com); blr->fsp = fsp; if (lock_timeout == -1) { blr->expire_time.tv_sec = 0; @@ -206,9 +186,6 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, blr->lock_type = lock_type; blr->offset = offset; blr->count = count; - memcpy(blr->inbuf, req->inbuf, length); - blr->length = length; - blr->encrypted = req->encrypted; /* Add a pending lock record for this. */ status = brl_lock(smbd_messaging_context(), br_lck, @@ -224,10 +201,12 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("push_blocking_lock_request: failed to add PENDING_LOCK record.\n")); DLIST_REMOVE(blocking_lock_queue, blr); - free_blocking_lock_record(blr); + TALLOC_FREE(blr); return False; } + blr->req = talloc_move(blr, &req); + DLIST_ADD_END(blocking_lock_queue, blr, blocking_lock_record *); recalc_brl_timeout(); @@ -238,14 +217,14 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, set_lock_msg = True; } - DEBUG(3,("push_blocking_lock_request: lock request length=%u blocked with " + DEBUG(3,("push_blocking_lock_request: lock request blocked with " "expiry time (%u sec. %u usec) (+%d msec) for fnum = %d, name = %s\n", - (unsigned int)length, (unsigned int)blr->expire_time.tv_sec, + (unsigned int)blr->expire_time.tv_sec, (unsigned int)blr->expire_time.tv_usec, lock_timeout, blr->fsp->fnum, blr->fsp->fsp_name )); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(req->inbuf,smb_mid)); + srv_defer_sign_response(blr->req->mid); return True; } @@ -256,14 +235,7 @@ bool push_blocking_lock_request( struct byte_range_lock *br_lck, static void reply_lockingX_success(blocking_lock_record *blr) { - struct smb_request *req; - - if (!(req = talloc(talloc_tos(), struct smb_request))) { - smb_panic("Could not allocate smb_request"); - } - - init_smb_request(req, (uint8 *)blr->inbuf, 0, blr->encrypted); - reply_outbuf(req, 2, 0); + reply_outbuf(blr->req, 2, 0); /* * As this message is a lockingX call we must handle @@ -273,13 +245,14 @@ static void reply_lockingX_success(blocking_lock_record *blr) * that here and must set up the chain info manually. */ - chain_reply(req); + chain_reply(blr->req); - if (!srv_send_smb(smbd_server_fd(), - (char *)req->outbuf, + if (!srv_send_smb(smbd_server_fd(), (char *)blr->req->outbuf, IS_CONN_ENCRYPTED(blr->fsp->conn))) { exit_server_cleanly("send_blocking_reply: srv_send_smb failed."); } + + TALLOC_FREE(blr->req->outbuf); } /**************************************************************************** @@ -288,11 +261,6 @@ static void reply_lockingX_success(blocking_lock_record *blr) static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS status) { - char outbuf[smb_size]; - char *inbuf = blr->inbuf; - - construct_reply_common(inbuf, outbuf); - /* whenever a timeout is given w2k maps LOCK_NOT_GRANTED to FILE_LOCK_CONFLICT! (tridge) */ if (NT_STATUS_EQUAL(status, NT_STATUS_LOCK_NOT_GRANTED)) { @@ -315,10 +283,12 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat } } - ERROR_NT(status); - if (!srv_send_smb(smbd_server_fd(),outbuf, blr->encrypted)) { + reply_nterror(blr->req, status); + if (!srv_send_smb(smbd_server_fd(), (char *)blr->req->outbuf, + blr->req->encrypted)) { exit_server_cleanly("generic_blocking_lock_error: srv_send_smb failed."); } + TALLOC_FREE(blr->req->outbuf); } /**************************************************************************** @@ -328,18 +298,18 @@ static void generic_blocking_lock_error(blocking_lock_record *blr, NTSTATUS stat static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) { - char *inbuf = blr->inbuf; files_struct *fsp = blr->fsp; - uint16 num_ulocks = SVAL(inbuf,smb_vwv6); + uint16 num_ulocks = SVAL(blr->req->vwv+6, 0); uint64_t count = (uint64_t)0, offset = (uint64_t) 0; uint32 lock_pid; - unsigned char locktype = CVAL(inbuf,smb_vwv3); + unsigned char locktype = CVAL(blr->req->vwv+3, 0); bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); - char *data; + uint8_t *data; int i; - data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); - + data = (uint8_t *)blr->req->buf + + ((large_file_format ? 20 : 10)*num_ulocks); + /* * Data now points at the beginning of the list * of smb_lkrng structs. @@ -350,19 +320,19 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) * as under POSIX rules, if we have a lock already there, we * will delete it (and we shouldn't) ..... */ - + for(i = blr->lock_num - 1; i >= 0; i--) { bool err; - + lock_pid = get_lock_pid( data, i, large_file_format); count = get_lock_count( data, i, large_file_format); offset = get_lock_offset( data, i, large_file_format, &err); - + /* * We know err cannot be set as if it was the lock * request would never have been queued. JRA. */ - + do_unlock(smbd_messaging_context(), fsp, lock_pid, @@ -370,7 +340,7 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) offset, WINDOWS_LOCK); } - + generic_blocking_lock_error(blr, status); } @@ -380,28 +350,28 @@ static void reply_lockingX_error(blocking_lock_record *blr, NTSTATUS status) static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status) { - switch(blr->com_type) { + switch(blr->req->cmd) { case SMBlockingX: reply_lockingX_error(blr, status); break; case SMBtrans2: case SMBtranss2: - { - char outbuf[smb_size]; - char *inbuf = blr->inbuf; - construct_reply_common(inbuf, outbuf); - /* construct_reply_common has done us the favor to pre-fill the - * command field with SMBtranss2 which is wrong :-) - */ - SCVAL(outbuf,smb_com,SMBtrans2); - ERROR_NT(status); - if (!srv_send_smb(smbd_server_fd(), - outbuf, - IS_CONN_ENCRYPTED(blr->fsp->conn))) { - exit_server_cleanly("blocking_lock_reply_error: srv_send_smb failed."); - } - break; + reply_nterror(blr->req, status); + + /* + * construct_reply_common has done us the favor to pre-fill + * the command field with SMBtranss2 which is wrong :-) + */ + SCVAL(blr->req->outbuf,smb_com,SMBtrans2); + + if (!srv_send_smb(smbd_server_fd(), + (char *)blr->req->outbuf, + IS_CONN_ENCRYPTED(blr->fsp->conn))) { + exit_server_cleanly("blocking_lock_reply_error: " + "srv_send_smb failed."); } + TALLOC_FREE(blr->req->outbuf); + break; default: DEBUG(0,("blocking_lock_reply_error: PANIC - unknown type on blocking lock queue - exiting.!\n")); exit_server("PANIC - unknown type on blocking lock queue"); @@ -415,18 +385,18 @@ static void blocking_lock_reply_error(blocking_lock_record *blr, NTSTATUS status static bool process_lockingX(blocking_lock_record *blr) { - char *inbuf = blr->inbuf; - unsigned char locktype = CVAL(inbuf,smb_vwv3); + unsigned char locktype = CVAL(blr->req->vwv+3, 0); files_struct *fsp = blr->fsp; - uint16 num_ulocks = SVAL(inbuf,smb_vwv6); - uint16 num_locks = SVAL(inbuf,smb_vwv7); + uint16 num_ulocks = SVAL(blr->req->vwv+6, 0); + uint16 num_locks = SVAL(blr->req->vwv+7, 0); uint64_t count = (uint64_t)0, offset = (uint64_t)0; uint32 lock_pid; bool large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES); - char *data; + uint8_t *data; NTSTATUS status = NT_STATUS_OK; - data = smb_buf(inbuf) + ((large_file_format ? 20 : 10)*num_ulocks); + data = (uint8_t *)blr->req->buf + + ((large_file_format ? 20 : 10)*num_ulocks); /* * Data now points at the beginning of the list @@ -440,7 +410,7 @@ static bool process_lockingX(blocking_lock_record *blr) lock_pid = get_lock_pid( data, blr->lock_num, large_file_format); count = get_lock_count( data, blr->lock_num, large_file_format); offset = get_lock_offset( data, blr->lock_num, large_file_format, &err); - + /* * We know err cannot be set as if it was the lock * request would never have been queued. JRA. @@ -469,20 +439,21 @@ static bool process_lockingX(blocking_lock_record *blr) /* * Success - we got all the locks. */ - + DEBUG(3,("process_lockingX file = %s, fnum=%d type=%d num_locks=%d\n", fsp->fsp_name, fsp->fnum, (unsigned int)locktype, num_locks) ); reply_lockingX_success(blr); return True; - } else if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && - !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { - /* - * We have other than a "can't get lock" - * error. Free any locks we had and return an error. - * Return True so we get dequeued. - */ - + } + + if (!NT_STATUS_EQUAL(status,NT_STATUS_LOCK_NOT_GRANTED) && + !NT_STATUS_EQUAL(status,NT_STATUS_FILE_LOCK_CONFLICT)) { + /* + * We have other than a "can't get lock" + * error. Free any locks we had and return an error. + * Return True so we get dequeued. + */ blocking_lock_reply_error(blr, status); return True; } @@ -490,11 +461,11 @@ static bool process_lockingX(blocking_lock_record *blr) /* * Still can't get all the locks - keep waiting. */ - + DEBUG(10,("process_lockingX: only got %d locks of %d needed for file %s, fnum = %d. \ Waiting....\n", blr->lock_num, num_locks, fsp->fsp_name, fsp->fnum)); - + return False; } @@ -505,7 +476,6 @@ Waiting....\n", static bool process_trans2(blocking_lock_record *blr) { - struct smb_request *req; char params[2]; NTSTATUS status; struct byte_range_lock *br_lck = do_lock(smbd_messaging_context(), @@ -535,17 +505,9 @@ static bool process_trans2(blocking_lock_record *blr) /* We finally got the lock, return success. */ - if (!(req = talloc(talloc_tos(), struct smb_request))) { - blocking_lock_reply_error(blr, NT_STATUS_NO_MEMORY); - return True; - } - - init_smb_request(req, (uint8 *)blr->inbuf, 0, blr->encrypted); - - SCVAL(req->inbuf, smb_com, SMBtrans2); SSVAL(params,0,0); /* Fake up max_data_bytes here - we know it fits. */ - send_trans2_replies(blr->fsp->conn, req, params, 2, NULL, 0, 0xffff); + send_trans2_replies(blr->fsp->conn, blr->req, params, 2, NULL, 0, 0xffff); return True; } @@ -557,7 +519,7 @@ static bool process_trans2(blocking_lock_record *blr) static bool blocking_lock_record_process(blocking_lock_record *blr) { - switch(blr->com_type) { + switch(blr->req->cmd) { case SMBlockingX: return process_lockingX(blr); case SMBtrans2: @@ -579,37 +541,39 @@ void cancel_pending_lock_requests_by_fid(files_struct *fsp, struct byte_range_lo blocking_lock_record *blr, *next = NULL; for(blr = blocking_lock_queue; blr; blr = next) { - next = blr->next; - if(blr->fsp->fnum == fsp->fnum) { - unsigned char locktype = 0; - - if (blr->com_type == SMBlockingX) { - locktype = CVAL(blr->inbuf,smb_vwv3); - } - - if (br_lck) { - DEBUG(10,("remove_pending_lock_requests_by_fid - removing request type %d for \ -file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); + unsigned char locktype = 0; - brl_lock_cancel(br_lck, - blr->lock_pid, - procid_self(), - blr->offset, - blr->count, - blr->lock_flav); + next = blr->next; + if (blr->fsp->fnum != fsp->fnum) { + continue; + } - blocking_lock_cancel(fsp, - blr->lock_pid, - blr->offset, - blr->count, - blr->lock_flav, - locktype, - NT_STATUS_RANGE_NOT_LOCKED); - } - /* We're closing the file fsp here, so ensure - * we don't have a dangling pointer. */ - blr->fsp = NULL; + if (blr->req->cmd == SMBlockingX) { + locktype = CVAL(blr->req->vwv+3, 0); } + + DEBUG(10, ("remove_pending_lock_requests_by_fid - removing " + "request type %d for file %s fnum = %d\n", + blr->req->cmd, fsp->fsp_name, fsp->fnum)); + + brl_lock_cancel(br_lck, + blr->lock_pid, + procid_self(), + blr->offset, + blr->count, + blr->lock_flav); + + blocking_lock_cancel(fsp, + blr->lock_pid, + blr->offset, + blr->count, + blr->lock_flav, + locktype, + NT_STATUS_RANGE_NOT_LOCKED); + + /* We're closing the file fsp here, so ensure + * we don't have a dangling pointer. */ + blr->fsp = NULL; } } @@ -622,28 +586,36 @@ void remove_pending_lock_requests_by_mid(int mid) blocking_lock_record *blr, *next = NULL; for(blr = blocking_lock_queue; blr; blr = next) { + files_struct *fsp; + struct byte_range_lock *br_lck; + next = blr->next; - if(SVAL(blr->inbuf,smb_mid) == mid) { - files_struct *fsp = blr->fsp; - struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); - if (br_lck) { - DEBUG(10,("remove_pending_lock_requests_by_mid - removing request type %d for \ -file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); + if (blr->req->mid != mid) { + continue; + } - brl_lock_cancel(br_lck, + fsp = blr->fsp; + br_lck = brl_get_locks(talloc_tos(), fsp); + + if (br_lck) { + DEBUG(10, ("remove_pending_lock_requests_by_mid - " + "removing request type %d for file %s fnum " + "= %d\n", blr->req->cmd, fsp->fsp_name, + fsp->fnum )); + + brl_lock_cancel(br_lck, blr->lock_pid, procid_self(), blr->offset, blr->count, blr->lock_flav); - 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); + TALLOC_FREE(br_lck); } + + blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); + DLIST_REMOVE(blocking_lock_queue, blr); + TALLOC_FREE(blr); } } @@ -657,7 +629,7 @@ bool blocking_lock_was_deferred(int mid) for(blr = blocking_lock_queue; blr; blr = next) { next = blr->next; - if(SVAL(blr->inbuf,smb_mid) == mid) { + if(blr->req->mid == mid) { return True; } } @@ -693,86 +665,18 @@ static void process_blocking_lock_queue(void) */ for (blr = blocking_lock_queue; blr; blr = next) { - connection_struct *conn = NULL; - uint16 vuid; - files_struct *fsp = NULL; next = blr->next; /* - * Ensure we don't have any old chain_fsp values - * sitting around.... - */ - chain_size = 0; - fsp = blr->fsp; - - conn = conn_find(SVAL(blr->inbuf,smb_tid)); - vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : - SVAL(blr->inbuf,smb_uid); - - DEBUG(5,("process_blocking_lock_queue: examining pending lock fnum = %d for file %s\n", - fsp->fnum, fsp->fsp_name )); - - if(!change_to_user(conn,vuid)) { - struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); - - /* - * Remove the entry and return an error to the client. - */ - - if (br_lck) { - brl_lock_cancel(br_lck, - blr->lock_pid, - procid_self(), - blr->offset, - blr->count, - blr->lock_flav); - TALLOC_FREE(br_lck); - } - - 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(!set_current_service(conn,SVAL(blr->inbuf,smb_flg),True)) { - struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); - - /* - * Remove the entry and return an error to the client. - */ - - if (br_lck) { - brl_lock_cancel(br_lck, - blr->lock_pid, - procid_self(), - blr->offset, - blr->count, - blr->lock_flav); - 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; - } - - /* * 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. */ if(blocking_lock_record_process(blr)) { - struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); + struct byte_range_lock *br_lck = brl_get_locks( + talloc_tos(), blr->fsp); if (br_lck) { brl_lock_cancel(br_lck, @@ -785,21 +689,19 @@ static void process_blocking_lock_queue(void) } DLIST_REMOVE(blocking_lock_queue, blr); - free_blocking_lock_record(blr); + TALLOC_FREE(blr); recalc_timeout = True; - change_to_root_user(); continue; } - change_to_root_user(); - /* * We couldn't get the locks for this record on the list. * If the time has expired, return a lock error. */ if (!timeval_is_zero(&blr->expire_time) && timeval_compare(&blr->expire_time, &tv_curr) <= 0) { - struct byte_range_lock *br_lck = brl_get_locks(talloc_tos(), fsp); + struct byte_range_lock *br_lck = brl_get_locks( + talloc_tos(), blr->fsp); /* * Lock expired - throw away all previously @@ -807,8 +709,10 @@ static void process_blocking_lock_queue(void) */ if (br_lck) { - DEBUG(5,("process_blocking_lock_queue: pending lock fnum = %d for file %s timed out.\n", - fsp->fnum, fsp->fsp_name )); + DEBUG(5,("process_blocking_lock_queue: " + "pending lock fnum = %d for file %s " + "timed out.\n", blr->fsp->fnum, + blr->fsp->fsp_name )); brl_lock_cancel(br_lck, blr->lock_pid, @@ -821,7 +725,7 @@ static void process_blocking_lock_queue(void) blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); DLIST_REMOVE(blocking_lock_queue, blr); - free_blocking_lock_record(blr); + TALLOC_FREE(blr); recalc_timeout = True; } } @@ -865,7 +769,7 @@ static void process_blocking_lock_cancel_message(struct messaging_context *ctx, blocking_lock_reply_error(blr, err); DLIST_REMOVE(blocking_lock_cancelled_queue, blr); - free_blocking_lock_record(blr); + TALLOC_FREE(blr); } /**************************************************************************** @@ -908,9 +812,9 @@ bool blocking_lock_cancel(files_struct *fsp, } /* Check the flags are right. */ - if (blr->com_type == SMBlockingX && + if (blr->req->cmd == SMBlockingX && (locktype & LOCKING_ANDX_LARGE_FILES) != - (CVAL(blr->inbuf,smb_vwv3) & LOCKING_ANDX_LARGE_FILES)) { + (CVAL(blr->req->vwv+3, 0) & LOCKING_ANDX_LARGE_FILES)) { return False; } diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 64a4311256..e6d2bbf59f 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -184,17 +184,17 @@ static int dochild(int master, const char *slavedev, const struct passwd *pass, /* Make slave stdin/out/err of child. */ - if (sys_dup2(slave, STDIN_FILENO) != STDIN_FILENO) + if (dup2(slave, STDIN_FILENO) != STDIN_FILENO) { DEBUG(3, ("Could not re-direct stdin\n")); return (False); } - if (sys_dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) + if (dup2(slave, STDOUT_FILENO) != STDOUT_FILENO) { DEBUG(3, ("Could not re-direct stdout\n")); return (False); } - if (sys_dup2(slave, STDERR_FILENO) != STDERR_FILENO) + if (dup2(slave, STDERR_FILENO) != STDERR_FILENO) { DEBUG(3, ("Could not re-direct stderr\n")); return (False); diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c index 0ce226809e..26a4212ec9 100644 --- a/source3/smbd/ipc.c +++ b/source3/smbd/ipc.c @@ -81,7 +81,8 @@ static void copy_trans_params_and_data(char *outbuf, int align, Send a trans reply. ****************************************************************************/ -void send_trans_reply(connection_struct *conn, const uint8_t *inbuf, +void send_trans_reply(connection_struct *conn, + struct smb_request *req, char *rparam, int rparam_len, char *rdata, int rdata_len, bool buffer_too_large) @@ -90,7 +91,6 @@ void send_trans_reply(connection_struct *conn, const uint8_t *inbuf, int tot_data_sent = 0; int tot_param_sent = 0; int align; - char *outbuf; int ldata = rdata ? rdata_len : 0; int lparam = rparam ? rparam_len : 0; @@ -103,38 +103,43 @@ void send_trans_reply(connection_struct *conn, const uint8_t *inbuf, align = ((this_lparam)%4); - if (!create_outbuf(talloc_tos(), (char *)inbuf, &outbuf, - 10, 1+align+this_ldata+this_lparam)) { - smb_panic("could not allocate outbuf"); - } + reply_outbuf(req, 10, 1+align+this_ldata+this_lparam); + + /* + * We might have SMBtranss in req which was transferred to the outbuf, + * fix that. + */ + SCVAL(req->outbuf, smb_com, SMBtrans); - copy_trans_params_and_data(outbuf, align, + copy_trans_params_and_data((char *)req->outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); - SSVAL(outbuf,smb_vwv0,lparam); - SSVAL(outbuf,smb_vwv1,ldata); - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); - SSVAL(outbuf,smb_vwv5,0); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align, - outbuf)); - SSVAL(outbuf,smb_vwv8,0); - SSVAL(outbuf,smb_vwv9,0); + SSVAL(req->outbuf,smb_vwv0,lparam); + SSVAL(req->outbuf,smb_vwv1,ldata); + SSVAL(req->outbuf,smb_vwv3,this_lparam); + SSVAL(req->outbuf,smb_vwv4, + smb_offset(smb_buf(req->outbuf)+1, req->outbuf)); + SSVAL(req->outbuf,smb_vwv5,0); + SSVAL(req->outbuf,smb_vwv6,this_ldata); + SSVAL(req->outbuf,smb_vwv7, + smb_offset(smb_buf(req->outbuf)+1+this_lparam+align, + req->outbuf)); + SSVAL(req->outbuf,smb_vwv8,0); + SSVAL(req->outbuf,smb_vwv9,0); if (buffer_too_large) { - error_packet_set((char *)outbuf, ERRDOS, ERRmoredata, + error_packet_set((char *)req->outbuf, ERRDOS, ERRmoredata, STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__); } - show_msg(outbuf); - if (!srv_send_smb(smbd_server_fd(), (char *)outbuf, + show_msg((char *)req->outbuf); + if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, IS_CONN_ENCRYPTED(conn))) { exit_server_cleanly("send_trans_reply: srv_send_smb failed."); } - TALLOC_FREE(outbuf); + TALLOC_FREE(req->outbuf); tot_data_sent = this_ldata; tot_param_sent = this_lparam; @@ -154,39 +159,45 @@ void send_trans_reply(connection_struct *conn, const uint8_t *inbuf, align = (this_lparam%4); - if (!create_outbuf(talloc_tos(), (char *)inbuf, &outbuf, - 10, 1+align+this_ldata+this_lparam)) { - smb_panic("could not allocate outbuf"); - } + reply_outbuf(req, 10, 1+align+this_ldata+this_lparam); + + /* + * We might have SMBtranss in req which was transferred to the + * outbuf, fix that. + */ + SCVAL(req->outbuf, smb_com, SMBtrans); - copy_trans_params_and_data(outbuf, align, + copy_trans_params_and_data((char *)req->outbuf, align, rparam, tot_param_sent, this_lparam, rdata, tot_data_sent, this_ldata); - SSVAL(outbuf,smb_vwv3,this_lparam); - SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf)); - SSVAL(outbuf,smb_vwv5,tot_param_sent); - SSVAL(outbuf,smb_vwv6,this_ldata); - SSVAL(outbuf,smb_vwv7, - smb_offset(smb_buf(outbuf)+1+this_lparam+align, outbuf)); - SSVAL(outbuf,smb_vwv8,tot_data_sent); - SSVAL(outbuf,smb_vwv9,0); + SSVAL(req->outbuf,smb_vwv3,this_lparam); + SSVAL(req->outbuf,smb_vwv4, + smb_offset(smb_buf(req->outbuf)+1,req->outbuf)); + SSVAL(req->outbuf,smb_vwv5,tot_param_sent); + SSVAL(req->outbuf,smb_vwv6,this_ldata); + SSVAL(req->outbuf,smb_vwv7, + smb_offset(smb_buf(req->outbuf)+1+this_lparam+align, + req->outbuf)); + SSVAL(req->outbuf,smb_vwv8,tot_data_sent); + SSVAL(req->outbuf,smb_vwv9,0); if (buffer_too_large) { - error_packet_set(outbuf, ERRDOS, ERRmoredata, + error_packet_set((char *)req->outbuf, + ERRDOS, ERRmoredata, STATUS_BUFFER_OVERFLOW, __LINE__, __FILE__); } - show_msg(outbuf); - if (!srv_send_smb(smbd_server_fd(), outbuf, + show_msg((char *)req->outbuf); + if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, IS_CONN_ENCRYPTED(conn))) exit_server_cleanly("send_trans_reply: srv_send_smb " "failed."); tot_data_sent += this_ldata; tot_param_sent += this_lparam; - TALLOC_FREE(outbuf); + TALLOC_FREE(req->outbuf); } } @@ -218,7 +229,7 @@ static void api_rpc_trans_reply(connection_struct *conn, return; } - send_trans_reply(conn, req->inbuf, NULL, 0, (char *)rdata, data_len, + send_trans_reply(conn, req, NULL, 0, (char *)rdata, data_len, is_data_outstanding); SAFE_FREE(rdata); return; @@ -239,7 +250,7 @@ static void api_WNPHS(connection_struct *conn, struct smb_request *req, DEBUG(4,("WaitNamedPipeHandleState priority %x\n", (int)SVAL(param,0))); - send_trans_reply(conn, req->inbuf, NULL, 0, NULL, 0, False); + send_trans_reply(conn, req, NULL, 0, NULL, 0, False); } @@ -257,7 +268,7 @@ static void api_SNPHS(connection_struct *conn, struct smb_request *req, DEBUG(4,("SetNamedPipeHandleState to code %x\n", (int)SVAL(param,0))); - send_trans_reply(conn, req->inbuf, NULL, 0, NULL, 0, False); + send_trans_reply(conn, req, NULL, 0, NULL, 0, False); } @@ -276,7 +287,7 @@ static void api_no_reply(connection_struct *conn, struct smb_request *req) DEBUG(3,("Unsupported API fd command\n")); /* now send the reply */ - send_trans_reply(conn, req->inbuf, rparam, 4, NULL, 0, False); + send_trans_reply(conn, req, rparam, 4, NULL, 0, False); return; } @@ -320,8 +331,7 @@ static void api_fd_reply(connection_struct *conn, uint16 vuid, /* 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(conn, req->inbuf, NULL, 0, NULL, 0, - False); + send_trans_reply(conn, req, NULL, 0, NULL, 0, False); return; } @@ -506,10 +516,10 @@ void reply_trans(struct smb_request *req) size = smb_len(req->inbuf) + 4; av_size = smb_len(req->inbuf); - dsoff = SVAL(req->inbuf, smb_dsoff); - dscnt = SVAL(req->inbuf, smb_dscnt); - psoff = SVAL(req->inbuf, smb_psoff); - pscnt = SVAL(req->inbuf, smb_pscnt); + dsoff = SVAL(req->vwv+12, 0); + dscnt = SVAL(req->vwv+11, 0); + psoff = SVAL(req->vwv+10, 0); + pscnt = SVAL(req->vwv+9, 0); result = allow_new_trans(conn->pending_trans, req->mid); if (!NT_STATUS_IS_OK(result)) { @@ -531,20 +541,20 @@ void reply_trans(struct smb_request *req) state->mid = req->mid; state->vuid = req->vuid; - state->setup_count = CVAL(req->inbuf, smb_suwcnt); + state->setup_count = CVAL(req->vwv+13, 0); state->setup = NULL; - state->total_param = SVAL(req->inbuf, smb_tpscnt); + state->total_param = SVAL(req->vwv+0, 0); state->param = NULL; - state->total_data = SVAL(req->inbuf, smb_tdscnt); + state->total_data = SVAL(req->vwv+1, 0); state->data = NULL; - state->max_param_return = SVAL(req->inbuf, smb_mprcnt); - state->max_data_return = SVAL(req->inbuf, smb_mdrcnt); - state->max_setup_return = CVAL(req->inbuf, smb_msrcnt); - state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0); - state->one_way = BITSETW(req->inbuf+smb_vwv5,1); + state->max_param_return = SVAL(req->vwv+2, 0); + state->max_data_return = SVAL(req->vwv+3, 0); + state->max_setup_return = CVAL(req->vwv+4, 0); + state->close_on_completion = BITSETW(req->vwv+5, 0); + state->one_way = BITSETW(req->vwv+5, 1); - srvstr_pull_buf_talloc(state, req->inbuf, req->flags2, &state->name, - smb_buf(req->inbuf), STR_TERMINATE); + srvstr_pull_req_talloc(state, req, &state->name, req->buf, + STR_TERMINATE); if ((dscnt > state->total_data) || (pscnt > state->total_param) || !state->name) @@ -710,20 +720,20 @@ void reply_transs(struct smb_request *req) /* Revise total_params and total_data in case they have changed * downwards */ - if (SVAL(req->inbuf, smb_vwv0) < state->total_param) - state->total_param = SVAL(req->inbuf,smb_vwv0); - if (SVAL(req->inbuf, smb_vwv1) < state->total_data) - state->total_data = SVAL(req->inbuf,smb_vwv1); + if (SVAL(req->vwv+0, 0) < state->total_param) + state->total_param = SVAL(req->vwv+0, 0); + if (SVAL(req->vwv+1, 0) < state->total_data) + state->total_data = SVAL(req->vwv+1, 0); av_size = smb_len(req->inbuf); - pcnt = SVAL(req->inbuf, smb_spscnt); - poff = SVAL(req->inbuf, smb_spsoff); - pdisp = SVAL(req->inbuf, smb_spsdisp); + pcnt = SVAL(req->vwv+2, 0); + poff = SVAL(req->vwv+3, 0); + pdisp = SVAL(req->vwv+4, 0); - dcnt = SVAL(req->inbuf, smb_sdscnt); - doff = SVAL(req->inbuf, smb_sdsoff); - ddisp = SVAL(req->inbuf, smb_sdsdisp); + dcnt = SVAL(req->vwv+5, 0); + doff = SVAL(req->vwv+6, 0); + ddisp = SVAL(req->vwv+7, 0); state->received_param += pcnt; state->received_data += dcnt; @@ -776,12 +786,6 @@ void reply_transs(struct smb_request *req) return; } - /* - * construct_reply_common will copy smb_com from inbuf to - * outbuf. SMBtranss is wrong here. - */ - SCVAL(req->inbuf,smb_com,SMBtrans); - handle_trans(conn, req, state); DLIST_REMOVE(conn->pending_trans, state); diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c index 0c866da706..6ed3ce2c87 100644 --- a/source3/smbd/lanman.c +++ b/source3/smbd/lanman.c @@ -4632,7 +4632,7 @@ void api_reply(connection_struct *conn, uint16 vuid, /* If api_Unsupported returns false we can't return anything. */ if (reply) { - send_trans_reply(conn, req->inbuf, rparam, rparam_len, + send_trans_reply(conn, req, rparam, rparam_len, rdata, rdata_len, False); } diff --git a/source3/smbd/mangle.c b/source3/smbd/mangle.c index 360692c546..4d4d0dc5af 100644 --- a/source3/smbd/mangle.c +++ b/source3/smbd/mangle.c @@ -140,7 +140,7 @@ bool name_to_8_3(const char *in, /* name mangling can be disabled for speed, in which case we just truncate the string */ if (!lp_manglednames(p)) { - safe_strcpy(out,in,12); + strlcpy(out, in, 13); return True; } diff --git a/source3/smbd/map_username.c b/source3/smbd/map_username.c index a8899dd538..f549f0c9f3 100644 --- a/source3/smbd/map_username.c +++ b/source3/smbd/map_username.c @@ -178,7 +178,7 @@ bool map_username(fstring user) /* skip lines like 'user = ' */ - dosuserlist = str_list_make(talloc_tos(), dosname, NULL); + dosuserlist = str_list_make_v3(talloc_tos(), dosname, NULL); if (!dosuserlist) { DEBUG(0,("Bad username map entry. Unable to build user list. Ignoring.\n")); continue; diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 62df5c37eb..65eaeca777 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -140,8 +140,8 @@ void reply_sends(struct smb_request *req) { struct msg_state *state; int len; - char *msg; - char *p; + const char *msg; + const char *p; START_PROFILE(SMBsends); @@ -153,18 +153,16 @@ void reply_sends(struct smb_request *req) state = talloc(talloc_tos(), struct msg_state); - p = smb_buf(req->inbuf)+1; - p += srvstr_pull_buf_talloc( - state, (char *)req->inbuf, req->flags2, &state->from, p, - STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf_talloc( - state, (char *)req->inbuf, req->flags2, &state->to, p, - STR_ASCII|STR_TERMINATE) + 1; + p = (const char *)req->buf + 1; + p += srvstr_pull_req_talloc( + state, req, &state->from, p, STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_req_talloc( + state, req, &state->to, p, STR_ASCII|STR_TERMINATE) + 1; msg = p; len = SVAL(msg,0); - len = MIN(len, smb_bufrem(req->inbuf, msg+2)); + len = MIN(len, smbreq_bufrem(req, msg+2)); state->msg = talloc_array(state, char, len); @@ -191,7 +189,7 @@ void reply_sends(struct smb_request *req) void reply_sendstrt(struct smb_request *req) { - char *p; + const char *p; START_PROFILE(SMBsendstrt); @@ -211,13 +209,13 @@ void reply_sendstrt(struct smb_request *req) return; } - p = smb_buf(req->inbuf)+1; - p += srvstr_pull_buf_talloc( - smbd_msg_state, (char *)req->inbuf, req->flags2, - &smbd_msg_state->from, p, STR_ASCII|STR_TERMINATE) + 1; - p += srvstr_pull_buf_talloc( - smbd_msg_state, (char *)req->inbuf, req->flags2, - &smbd_msg_state->to, p, STR_ASCII|STR_TERMINATE) + 1; + p = (const char *)req->buf+1; + p += srvstr_pull_req_talloc( + smbd_msg_state, req, &smbd_msg_state->from, p, + STR_ASCII|STR_TERMINATE) + 1; + p += srvstr_pull_req_talloc( + smbd_msg_state, req, &smbd_msg_state->to, p, + STR_ASCII|STR_TERMINATE) + 1; DEBUG( 3, ( "SMBsendstrt (from %s to %s)\n", smbd_msg_state->from, smbd_msg_state->to ) ); @@ -236,7 +234,7 @@ void reply_sendstrt(struct smb_request *req) void reply_sendtxt(struct smb_request *req) { int len; - char *msg; + const char *msg; char *tmp; size_t old_len; @@ -254,11 +252,11 @@ void reply_sendtxt(struct smb_request *req) return; } - msg = smb_buf(req->inbuf) + 1; + msg = (const char *)req->buf + 1; old_len = talloc_get_size(smbd_msg_state->msg); - len = MIN(SVAL(msg, 0), smb_bufrem(req->inbuf, msg+2)); + len = MIN(SVAL(msg, 0), smbreq_bufrem(req, msg+2)); tmp = TALLOC_REALLOC_ARRAY(smbd_msg_state, smbd_msg_state->msg, char, old_len + len); diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 84f111fb02..43fdc1d608 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -507,11 +507,9 @@ static const struct { void reply_negprot(struct smb_request *req) { - size_t size = smb_len(req->inbuf) + 4; int choice= -1; int protocol; - char *p; - int bcc = SVAL(smb_buf(req->inbuf),-2); + const char *p; int arch = ARCH_ALL; int num_cliprotos; char **cliprotos; @@ -528,19 +526,26 @@ void reply_negprot(struct smb_request *req) } done_negprot = True; - if (req->inbuf[size-1] != '\0') { + if (req->buflen == 0) { + DEBUG(0, ("negprot got no protocols\n")); + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBnegprot); + return; + } + + if (req->buf[req->buflen-1] != '\0') { DEBUG(0, ("negprot protocols not 0-terminated\n")); reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBnegprot); return; } - p = smb_buf(req->inbuf) + 1; + p = (const char *)req->buf + 1; num_cliprotos = 0; cliprotos = NULL; - while (p < (smb_buf(req->inbuf) + bcc)) { + while (smbreq_bufrem(req, p) > 0) { char **tmp; diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 139dfe7d5b..5a517654bf 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -24,7 +24,7 @@ struct notify_change_request { struct notify_change_request *prev, *next; struct files_struct *fsp; /* backpointer for cancel by mid */ - uint8 request_buf[smb_size]; + struct smb_request *req; uint32 filter; uint32 max_param; struct notify_mid_map *mid_map; @@ -133,40 +133,33 @@ static bool notify_marshall_changes(int num_changes, *****************************************************************************/ static void change_notify_reply_packet(connection_struct *conn, - const uint8 *request_buf, + struct smb_request *req, NTSTATUS error_code) { - char outbuf[smb_size+38]; + reply_outbuf(req, 18, 0); - memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common((char *)request_buf, outbuf); - - ERROR_NT(error_code); - - /* - * Seems NT needs a transact command with an error code - * in it. This is a longer packet than a simple error. - */ - srv_set_message(outbuf,18,0,False); + if (!NT_STATUS_IS_OK(error_code)) { + error_packet_set((char *)req->outbuf, 0, 0, error_code, + __LINE__,__FILE__); + } - show_msg(outbuf); - if (!srv_send_smb(smbd_server_fd(), - outbuf, - IS_CONN_ENCRYPTED(conn))) + show_msg((char *)req->outbuf); + if (!srv_send_smb(smbd_server_fd(), (char *)req->outbuf, + req->encrypted)) { exit_server_cleanly("change_notify_reply_packet: srv_send_smb " "failed."); + } + TALLOC_FREE(req->outbuf); } void change_notify_reply(connection_struct *conn, - const uint8 *request_buf, uint32 max_param, + struct smb_request *req, uint32 max_param, struct notify_change_buf *notify_buf) { prs_struct ps; - struct smb_request *req = NULL; - uint8 tmp_request[smb_size]; if (notify_buf->num_changes == -1) { - change_notify_reply_packet(conn, request_buf, NT_STATUS_OK); + change_notify_reply_packet(conn, req, NT_STATUS_OK); notify_buf->num_changes = 0; return; } @@ -179,31 +172,14 @@ void change_notify_reply(connection_struct *conn, * We exceed what the client is willing to accept. Send * nothing. */ - change_notify_reply_packet(conn, request_buf, NT_STATUS_OK); - goto done; - } - - if (!(req = talloc(talloc_tos(), struct smb_request))) { - change_notify_reply_packet(conn, request_buf, NT_STATUS_NO_MEMORY); + change_notify_reply_packet(conn, req, NT_STATUS_OK); goto done; } - memcpy(tmp_request, request_buf, smb_size); - - /* - * We're only interested in the header fields here - */ - - smb_setlen((char *)tmp_request, smb_size); - SCVAL(tmp_request, smb_wct, 0); - - init_smb_request(req, tmp_request,0, conn->encrypted_tid); - send_nt_replies(conn, req, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0); done: - TALLOC_FREE(req); prs_mem_free(&ps); TALLOC_FREE(notify_buf->changes); @@ -251,7 +227,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return status; } -NTSTATUS change_notify_add_request(const struct smb_request *req, +NTSTATUS change_notify_add_request(struct smb_request *req, uint32 max_param, uint32 filter, bool recursive, struct files_struct *fsp) @@ -262,16 +238,16 @@ NTSTATUS change_notify_add_request(const struct smb_request *req, DEBUG(10, ("change_notify_add_request: Adding request for %s: " "max_param = %d\n", fsp->fsp_name, (int)max_param)); - if (!(request = SMB_MALLOC_P(struct notify_change_request)) - || !(map = SMB_MALLOC_P(struct notify_mid_map))) { - SAFE_FREE(request); + if (!(request = talloc(NULL, struct notify_change_request)) + || !(map = talloc(request, struct notify_mid_map))) { + TALLOC_FREE(request); return NT_STATUS_NO_MEMORY; } request->mid_map = map; map->req = request; - memcpy(request->request_buf, req->inbuf, sizeof(request->request_buf)); + request->req = talloc_move(request, &req); request->max_param = max_param; request->filter = filter; request->fsp = fsp; @@ -280,11 +256,11 @@ NTSTATUS change_notify_add_request(const struct smb_request *req, DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); - map->mid = SVAL(req->inbuf, smb_mid); + map->mid = request->req->mid; DLIST_ADD(notify_changes_by_mid, map); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(req->inbuf,smb_mid)); + srv_defer_sign_response(request->req->mid); return NT_STATUS_OK; } @@ -314,9 +290,7 @@ static void change_notify_remove_request(struct notify_change_request *remove_re DLIST_REMOVE(fsp->notify->requests, req); DLIST_REMOVE(notify_changes_by_mid, req->mid_map); - SAFE_FREE(req->mid_map); - TALLOC_FREE(req->backend_data); - SAFE_FREE(req); + TALLOC_FREE(req); } /**************************************************************************** @@ -337,8 +311,8 @@ void remove_pending_change_notify_requests_by_mid(uint16 mid) return; } - change_notify_reply_packet(map->req->fsp->conn, - map->req->request_buf, NT_STATUS_CANCELLED); + change_notify_reply_packet(map->req->fsp->conn, map->req->req, + NT_STATUS_CANCELLED); change_notify_remove_request(map->req); } @@ -354,8 +328,8 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, } while (fsp->notify->requests != NULL) { - change_notify_reply_packet(fsp->conn, - fsp->notify->requests->request_buf, status); + change_notify_reply_packet( + fsp->conn, fsp->notify->requests->req, status); change_notify_remove_request(fsp->notify->requests); } } @@ -449,7 +423,7 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) */ change_notify_reply(fsp->conn, - fsp->notify->requests->request_buf, + fsp->notify->requests->req, fsp->notify->requests->max_param, fsp->notify); diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 30841686fb..1a13d962f0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -120,6 +120,11 @@ void send_nt_replies(connection_struct *conn, + data_alignment_offset); /* + * We might have had SMBnttranss in req->inbuf, fix that. + */ + SCVAL(req->outbuf, smb_com, SMBnttrans); + + /* * Set total params and data to be sent. */ @@ -304,11 +309,10 @@ static void do_ntcreate_pipe_open(connection_struct *conn, char *fname = NULL; int pnum = -1; char *p = NULL; - uint32 flags = IVAL(req->inbuf,smb_ntcreate_Flags); + uint32 flags = IVAL(req->vwv+3, 1); TALLOC_CTX *ctx = talloc_tos(); - srvstr_pull_buf_talloc(ctx, (char *)req->inbuf, req->flags2, &fname, - smb_buf(req->inbuf), STR_TERMINATE); + srvstr_pull_req_talloc(ctx, req, &fname, req->buf, STR_TERMINATE); if (!fname) { reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, @@ -408,24 +412,21 @@ void reply_ntcreate_and_X(struct smb_request *req) return; } - flags = IVAL(req->inbuf,smb_ntcreate_Flags); - access_mask = IVAL(req->inbuf,smb_ntcreate_DesiredAccess); - file_attributes = IVAL(req->inbuf,smb_ntcreate_FileAttributes); - share_access = IVAL(req->inbuf,smb_ntcreate_ShareAccess); - create_disposition = IVAL(req->inbuf,smb_ntcreate_CreateDisposition); - create_options = IVAL(req->inbuf,smb_ntcreate_CreateOptions); - root_dir_fid = (uint16)IVAL(req->inbuf,smb_ntcreate_RootDirectoryFid); + flags = IVAL(req->vwv+3, 1); + access_mask = IVAL(req->vwv+7, 1); + file_attributes = IVAL(req->vwv+13, 1); + share_access = IVAL(req->vwv+15, 1); + create_disposition = IVAL(req->vwv+17, 1); + create_options = IVAL(req->vwv+19, 1); + root_dir_fid = (uint16)IVAL(req->vwv+5, 1); - allocation_size = (uint64_t)IVAL(req->inbuf, - smb_ntcreate_AllocationSize); + allocation_size = (uint64_t)IVAL(req->vwv+9, 1); #ifdef LARGE_SMB_OFF_T - allocation_size |= (((uint64_t)IVAL( - req->inbuf, - smb_ntcreate_AllocationSize + 4)) << 32); + allocation_size |= (((uint64_t)IVAL(req->vwv+11, 1)) << 32); #endif - srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, - smb_buf(req->inbuf), 0, STR_TERMINATE, &status); + srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); @@ -729,6 +730,9 @@ static NTSTATUS set_sd(files_struct *fsp, uint8 *data, uint32 sd_len, if (psd->sacl==0) { security_info_sent &= ~SACL_SECURITY_INFORMATION; } + if (security_info_sent & DACL_SECURITY_INFORMATION) { + psd->type |= SEC_DESC_DACL_PRESENT; + } if (psd->dacl==0) { security_info_sent &= ~DACL_SECURITY_INFORMATION; } @@ -1228,7 +1232,7 @@ void reply_ntrename(struct smb_request *req) connection_struct *conn = req->conn; char *oldname = NULL; char *newname = NULL; - char *p; + const char *p; NTSTATUS status; bool src_has_wcard = False; bool dest_has_wcard = False; @@ -1244,13 +1248,12 @@ void reply_ntrename(struct smb_request *req) return; } - attrs = SVAL(req->inbuf,smb_vwv0); - rename_type = SVAL(req->inbuf,smb_vwv1); + attrs = SVAL(req->vwv+0, 0); + rename_type = SVAL(req->vwv+1, 0); - p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &oldname, p, - 0, STR_TERMINATE, &status, - &src_has_wcard); + p = (const char *)req->buf + 1; + p += srvstr_get_path_req_wcard(ctx, req, &oldname, p, STR_TERMINATE, + &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBntrename); @@ -1271,9 +1274,8 @@ void reply_ntrename(struct smb_request *req) } p++; - p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p, - 0, STR_TERMINATE, &status, - &dest_has_wcard); + p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE, + &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBntrename); @@ -1446,7 +1448,8 @@ static void call_nt_transact_notify_change(connection_struct *conn, * here. */ - change_notify_reply(fsp->conn, req->inbuf, max_param_count, fsp->notify); + change_notify_reply(fsp->conn, req, max_param_count, + fsp->notify); /* * change_notify_reply() above has independently sent its @@ -2538,11 +2541,11 @@ void reply_nttrans(struct smb_request *req) size = smb_len(req->inbuf) + 4; av_size = smb_len(req->inbuf); - pscnt = IVAL(req->inbuf,smb_nt_ParameterCount); - psoff = IVAL(req->inbuf,smb_nt_ParameterOffset); - dscnt = IVAL(req->inbuf,smb_nt_DataCount); - dsoff = IVAL(req->inbuf,smb_nt_DataOffset); - function_code = SVAL(req->inbuf, smb_nt_Function); + pscnt = IVAL(req->vwv+9, 1); + psoff = IVAL(req->vwv+11, 1); + dscnt = IVAL(req->vwv+13, 1); + dsoff = IVAL(req->vwv+15, 1); + function_code = SVAL(req->vwv+18, 0); if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) { reply_doserror(req, ERRSRV, ERRaccess); @@ -2568,15 +2571,15 @@ void reply_nttrans(struct smb_request *req) state->mid = req->mid; state->vuid = req->vuid; - state->total_data = IVAL(req->inbuf, smb_nt_TotalDataCount); + state->total_data = IVAL(req->vwv+3, 1); state->data = NULL; - state->total_param = IVAL(req->inbuf, smb_nt_TotalParameterCount); + state->total_param = IVAL(req->vwv+1, 1); state->param = NULL; - state->max_data_return = IVAL(req->inbuf,smb_nt_MaxDataCount); - state->max_param_return = IVAL(req->inbuf,smb_nt_MaxParameterCount); + state->max_data_return = IVAL(req->vwv+7, 1); + state->max_param_return = IVAL(req->vwv+5, 1); /* setup count is in *words* */ - state->setup_count = 2*CVAL(req->inbuf,smb_nt_SetupCount); + state->setup_count = 2*CVAL(req->vwv+17, 1); state->setup = NULL; state->call = function_code; @@ -2691,8 +2694,7 @@ void reply_nttrans(struct smb_request *req) goto bad_param; } - memcpy( state->setup, &req->inbuf[smb_nt_SetupStart], - state->setup_count); + memcpy(state->setup, req->vwv+19, state->setup_count); dump_data(10, (uint8 *)state->setup, state->setup_count); } @@ -2763,25 +2765,23 @@ void reply_nttranss(struct smb_request *req) /* Revise state->total_param and state->total_data in case they have changed downwards */ - if (IVAL(req->inbuf, smb_nts_TotalParameterCount) - < state->total_param) { - state->total_param = IVAL(req->inbuf, - smb_nts_TotalParameterCount); + if (IVAL(req->vwv+1, 1) < state->total_param) { + state->total_param = IVAL(req->vwv+1, 1); } - if (IVAL(req->inbuf, smb_nts_TotalDataCount) < state->total_data) { - state->total_data = IVAL(req->inbuf, smb_nts_TotalDataCount); + if (IVAL(req->vwv+3, 1) < state->total_data) { + state->total_data = IVAL(req->vwv+3, 1); } size = smb_len(req->inbuf) + 4; av_size = smb_len(req->inbuf); - pcnt = IVAL(req->inbuf,smb_nts_ParameterCount); - poff = IVAL(req->inbuf, smb_nts_ParameterOffset); - pdisp = IVAL(req->inbuf, smb_nts_ParameterDisplacement); + pcnt = IVAL(req->vwv+5, 1); + poff = IVAL(req->vwv+7, 1); + pdisp = IVAL(req->vwv+9, 1); - dcnt = IVAL(req->inbuf, smb_nts_DataCount); - ddisp = IVAL(req->inbuf, smb_nts_DataDisplacement); - doff = IVAL(req->inbuf, smb_nts_DataOffset); + dcnt = IVAL(req->vwv+11, 1); + doff = IVAL(req->vwv+13, 1); + ddisp = IVAL(req->vwv+15, 1); state->received_param += pcnt; state->received_data += dcnt; @@ -2834,12 +2834,6 @@ void reply_nttranss(struct smb_request *req) return; } - /* - * construct_reply_common will copy smb_com from inbuf to - * outbuf. SMBnttranss is wrong here. - */ - SCVAL(req->inbuf,smb_com,SMBnttrans); - handle_nttrans(conn, state, req); DLIST_REMOVE(conn->pending_trans, state); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 1564525005..3fd0d1a03a 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -30,6 +30,56 @@ struct deferred_open_record { }; /**************************************************************************** + SMB1 file varient of se_access_check. Never test FILE_READ_ATTRIBUTES. +****************************************************************************/ + +NTSTATUS smb1_file_se_access_check(const struct security_descriptor *sd, + const NT_USER_TOKEN *token, + uint32_t access_desired, + uint32_t *access_granted) +{ + return se_access_check(sd, + token, + (access_desired & ~FILE_READ_ATTRIBUTES), + access_granted); +} + +/**************************************************************************** + Check if we have open rights. +****************************************************************************/ + +static NTSTATUS check_open_rights(struct connection_struct *conn, + const char *fname, + uint32_t access_mask) +{ + /* Check if we have rights to open. */ + NTSTATUS status; + uint32_t access_granted = 0; + struct security_descriptor *sd; + + status = SMB_VFS_GET_NT_ACL(conn, fname, + (OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION),&sd); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("check_open_rights: Could not get acl " + "on %s: %s\n", + fname, + nt_errstr(status))); + return status; + } + + status = smb1_file_se_access_check(sd, + conn->server_info->ptok, + access_mask, + &access_granted); + + TALLOC_FREE(sd); + return status; +} + +/**************************************************************************** fd support routines - attempt to do a dos_open. ****************************************************************************/ @@ -337,6 +387,17 @@ static NTSTATUS open_file(files_struct *fsp, } else { fsp->fh->fd = -1; /* What we used to call a stat open. */ + if (file_existed) { + status = check_open_rights(conn, + path, + access_mask); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_file: Access denied on " + "file %s\n", + path)); + return status; + } + } } if (!file_existed) { @@ -1126,6 +1187,68 @@ static void schedule_defer_open(struct share_mode_lock *lck, } /**************************************************************************** + Work out what access_mask to use from what the client sent us. +****************************************************************************/ + +static NTSTATUS calculate_access_mask(connection_struct *conn, + const char *fname, + bool file_existed, + uint32_t access_mask, + uint32_t *access_mask_out) +{ + NTSTATUS status; + + /* + * Convert GENERIC bits to specific bits. + */ + + se_map_generic(&access_mask, &file_generic_mapping); + + /* Calculate MAXIMUM_ALLOWED_ACCESS if requested. */ + if (access_mask & MAXIMUM_ALLOWED_ACCESS) { + if (file_existed) { + + struct security_descriptor *sd; + uint32_t access_granted = 0; + + status = SMB_VFS_GET_NT_ACL(conn, fname, + (OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION),&sd); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("calculate_access_mask: Could not get acl " + "on file %s: %s\n", + fname, + nt_errstr(status))); + return NT_STATUS_ACCESS_DENIED; + } + + status = smb1_file_se_access_check(sd, + conn->server_info->ptok, + access_mask, + &access_granted); + + TALLOC_FREE(sd); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("calculate_access_mask: Access denied on " + "file %s: when calculating maximum access\n", + fname)); + return NT_STATUS_ACCESS_DENIED; + } + + access_mask = access_granted; + } else { + access_mask = FILE_GENERIC_ALL; + } + } + + *access_mask_out = access_mask; + return NT_STATUS_OK; +} + +/**************************************************************************** Open a file with a share mode. ****************************************************************************/ @@ -1206,15 +1329,6 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, create_disposition, create_options, unx_mode, oplock_request)); - if ((access_mask & FILE_READ_DATA)||(access_mask & FILE_WRITE_DATA)) { - DEBUG(10, ("open_file_ntcreate: adding FILE_READ_ATTRIBUTES " - "to requested access_mask 0x%x, new mask 0x%x", - access_mask, - access_mask | FILE_READ_ATTRIBUTES )); - - access_mask |= FILE_READ_ATTRIBUTES; - } - 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; @@ -1370,16 +1484,17 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, } } - /* This is a nasty hack - must fix... JRA. */ - if (access_mask == MAXIMUM_ALLOWED_ACCESS) { - open_access_mask = access_mask = FILE_GENERIC_ALL; + status = calculate_access_mask(conn, fname, file_existed, + access_mask, + &access_mask); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_file_ntcreate: calculate_access_mask " + "on file %s returned %s\n", + fname, + nt_errstr(status))); + return status; } - /* - * Convert GENERIC bits to specific bits. - */ - - se_map_generic(&access_mask, &file_generic_mapping); open_access_mask = access_mask; if ((flags2 & O_TRUNC) || (oplock_request & FORCE_OPLOCK_BREAK_TO_NONE)) { @@ -1819,7 +1934,10 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, /* Record the options we were opened with. */ fsp->share_access = share_access; fsp->fh->private_options = create_options; - fsp->access_mask = access_mask; + /* + * According to Samba4, SEC_FILE_READ_ATTRIBUTE is always granted, + */ + fsp->access_mask = access_mask | FILE_READ_ATTRIBUTES; if (file_existed) { /* stat opens on existing files don't get oplocks. */ @@ -2135,6 +2253,17 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_NOT_A_DIRECTORY; } + status = calculate_access_mask(conn, fname, dir_existed, + access_mask, + &access_mask); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_directory: calculate_access_mask " + "on file %s returned %s\n", + fname, + nt_errstr(status))); + return status; + } + switch( create_disposition ) { case FILE_OPEN: @@ -2209,6 +2338,19 @@ NTSTATUS open_directory(connection_struct *conn, return NT_STATUS_NOT_A_DIRECTORY; } + if (info == FILE_WAS_OPENED) { + status = check_open_rights(conn, + fname, + access_mask); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("open_directory: check_open_rights on " + "file %s failed with %s\n", + fname, + nt_errstr(status))); + return status; + } + } + status = file_new(req, conn, &fsp); if(!NT_STATUS_IS_OK(status)) { return status; @@ -2228,8 +2370,10 @@ NTSTATUS open_directory(connection_struct *conn, fsp->share_access = share_access; fsp->fh->private_options = create_options; - fsp->access_mask = access_mask; - + /* + * According to Samba4, SEC_FILE_READ_ATTRIBUTE is always granted, + */ + fsp->access_mask = access_mask | FILE_READ_ATTRIBUTES; fsp->print_file = False; fsp->modified = False; fsp->oplock_type = NO_OPLOCK; @@ -2779,7 +2923,12 @@ NTSTATUS create_file_unixpath(connection_struct *conn, security_acl_map_generic(sd->dacl, &file_generic_mapping); security_acl_map_generic(sd->sacl, &file_generic_mapping); - status = SMB_VFS_FSET_NT_ACL(fsp, sec_info_sent, sd); + if (sec_info_sent & (OWNER_SECURITY_INFORMATION| + GROUP_SECURITY_INFORMATION| + DACL_SECURITY_INFORMATION| + SACL_SECURITY_INFORMATION)) { + status = SMB_VFS_FSET_NT_ACL(fsp, sec_info_sent, sd); + } fsp->access_mask = saved_access_mask; diff --git a/source3/smbd/password.c b/source3/smbd/password.c index 88e7b766be..84b40f28cc 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -576,7 +576,7 @@ static bool user_ok(const char *user, int snum) TALLOC_FREE(valid); if (ret && lp_onlyuser(snum)) { - char **user_list = str_list_make( + char **user_list = str_list_make_v3( talloc_tos(), lp_username(snum), NULL); if (user_list && str_list_substitute(user_list, "%S", diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index d971e9dc62..b52b1b02d0 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -48,8 +48,7 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) NTSTATUS status; /* XXXX we need to handle passed times, sattr and flags */ - srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &pipe_name, - smb_buf(req->inbuf), STR_TERMINATE); + srvstr_pull_req_talloc(ctx, req, &pipe_name, req->buf, STR_TERMINATE); if (!pipe_name) { reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, ERRDOS, ERRbadpipe); @@ -119,10 +118,10 @@ void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) void reply_pipe_write(struct smb_request *req) { - files_struct *fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); - size_t numtowrite = SVAL(req->inbuf,smb_vwv1); + files_struct *fsp = file_fsp(req, SVAL(req->vwv+0, 0)); + size_t numtowrite = SVAL(req->vwv+1, 0); ssize_t nwritten; - uint8_t *data; + const uint8_t *data; if (!fsp_is_np(fsp)) { reply_doserror(req, ERRDOS, ERRbadfid); @@ -134,7 +133,7 @@ void reply_pipe_write(struct smb_request *req) return; } - data = (uint8_t *)smb_buf(req->inbuf) + 3; + data = req->buf + 3; if (numtowrite == 0) { nwritten = 0; @@ -171,13 +170,12 @@ void reply_pipe_write(struct smb_request *req) void reply_pipe_write_and_X(struct smb_request *req) { - files_struct *fsp = file_fsp(req, SVAL(req->inbuf, smb_vwv2)); - size_t numtowrite = SVAL(req->inbuf,smb_vwv10); + files_struct *fsp = file_fsp(req, SVAL(req->vwv+2, 0)); + size_t numtowrite = SVAL(req->vwv+10, 0); ssize_t nwritten; - int smb_doff = SVAL(req->inbuf, smb_vwv11); + int smb_doff = SVAL(req->vwv+11, 0); bool pipe_start_message_raw = - ((SVAL(req->inbuf, smb_vwv7) - & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) + ((SVAL(req->vwv+7, 0) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) == (PIPE_START_MESSAGE|PIPE_RAW_MODE)); uint8_t *data; @@ -247,9 +245,9 @@ void reply_pipe_write_and_X(struct smb_request *req) void reply_pipe_read_and_X(struct smb_request *req) { - files_struct *fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); - int smb_maxcnt = SVAL(req->inbuf,smb_vwv5); - int smb_mincnt = SVAL(req->inbuf,smb_vwv6); + files_struct *fsp = file_fsp(req, SVAL(req->vwv+0, 0)); + int smb_maxcnt = SVAL(req->vwv+5, 0); + int smb_mincnt = SVAL(req->vwv+6, 0); ssize_t nread; uint8_t *data; bool unused; @@ -259,7 +257,7 @@ void reply_pipe_read_and_X(struct smb_request *req) is deliberate, instead we always return the next lump of data on the pipe */ #if 0 - uint32 smb_offs = IVAL(req->inbuf,smb_vwv3); + uint32 smb_offs = IVAL(req->vwv+3, 0); #endif if (!fsp_is_np(fsp)) { diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c index cccf3087f7..7ca2ed787b 100644 --- a/source3/smbd/posix_acls.c +++ b/source3/smbd/posix_acls.c @@ -3511,7 +3511,7 @@ NTSTATUS set_nt_acl(files_struct *fsp, uint32 security_info_sent, const SEC_DESC create_file_sids(&sbuf, &file_owner_sid, &file_grp_sid); /* See here: http://www.codeproject.com/KB/winsdk/accessctrl2.aspx - * for details. JRA. + * for details and also the log trace in bug #4308. JRA. */ if ((security_info_sent & DACL_SECURITY_INFORMATION) && @@ -4301,7 +4301,7 @@ SEC_DESC *get_nt_acl_no_snum( TALLOC_CTX *ctx, const char *fname) finfo.fh->fd = -1; finfo.fsp_name = CONST_DISCARD(char *,fname); - if (!NT_STATUS_IS_OK(posix_fget_nt_acl( &finfo, DACL_SECURITY_INFORMATION, &psd))) { + if (!NT_STATUS_IS_OK(SMB_VFS_FGET_NT_ACL( &finfo, DACL_SECURITY_INFORMATION, &psd))) { DEBUG(0,("get_nt_acl_no_snum: get_nt_acl returned zero.\n")); conn_free_internal( conn ); return NULL; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a8b93d8e1c..b3cd2f26c8 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -20,8 +20,6 @@ #include "includes.h" -extern int smb_echo_count; - /* * Size of data we can send to client. Set * by the client for all protocols above CORE. @@ -39,6 +37,8 @@ SIG_ATOMIC_T got_sig_term = 0; extern bool global_machine_password_needs_changing; extern int max_send; +static void construct_reply_common(const char *inbuf, char *outbuf); + /* Accessor function for smb_read_error for smbd functions. */ /**************************************************************************** @@ -371,12 +371,16 @@ void init_smb_request(struct smb_request *req, (unsigned int)req_size )); exit_server_cleanly("Invalid SMB request"); } + req->cmd = CVAL(inbuf, smb_com); req->flags2 = SVAL(inbuf, smb_flg2); req->smbpid = SVAL(inbuf, smb_pid); req->mid = SVAL(inbuf, smb_mid); req->vuid = SVAL(inbuf, smb_uid); req->tid = SVAL(inbuf, smb_tid); req->wct = CVAL(inbuf, smb_wct); + req->vwv = (uint16_t *)(inbuf+smb_vwv); + req->buflen = smb_buflen(inbuf); + req->buf = (const uint8_t *)smb_buf(inbuf); req->unread_bytes = unread_bytes; req->encrypted = encrypted; req->conn = conn_find(req->tid); @@ -390,15 +394,14 @@ void init_smb_request(struct smb_request *req, exit_server_cleanly("Invalid SMB request"); } /* Ensure bcc is correct. */ - if (((uint8 *)smb_buf(inbuf)) + smb_buflen(inbuf) > inbuf + req_size) { + if (((uint8 *)smb_buf(inbuf)) + req->buflen > inbuf + req_size) { DEBUG(0,("init_smb_request: invalid bcc number %u " "(wct = %u, size %u)\n", - (unsigned int)smb_buflen(inbuf), + (unsigned int)req->buflen, (unsigned int)req->wct, (unsigned int)req_size)); exit_server_cleanly("Invalid SMB request"); } - req->inbuf = inbuf; req->outbuf = NULL; } @@ -1422,6 +1425,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in if (!change_to_user(conn,session_tag)) { reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid)); + remove_deferred_open_smb_message(req->mid); return conn; } @@ -1450,8 +1454,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in /* encrypted required from now on. */ conn->encrypt_level = Required; } else if (ENCRYPTION_REQUIRED(conn)) { - uint8 com = CVAL(req->inbuf,smb_com); - if (com != SMBtrans2 && com != SMBtranss2) { + if (req->cmd != SMBtrans2 && req->cmd != SMBtranss2) { exit_server_cleanly("encryption required " "on connection"); return conn; @@ -1486,7 +1489,6 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool encrypted) { - uint8 type = CVAL(inbuf,smb_com); connection_struct *conn; struct smb_request *req; @@ -1496,8 +1498,9 @@ static void construct_reply(char *inbuf, int size, size_t unread_bytes, bool enc smb_panic("could not allocate smb_request"); } init_smb_request(req, (uint8 *)inbuf, unread_bytes, encrypted); + req->inbuf = (uint8_t *)talloc_move(req, &inbuf); - conn = switch_message(type, req, size); + conn = switch_message(req->cmd, req, size); if (req->unread_bytes) { /* writeX failed. drain socket. */ @@ -1589,7 +1592,7 @@ void remove_from_common_flags2(uint32 v) common_flags2 &= ~v; } -void construct_reply_common(const char *inbuf, char *outbuf) +static void construct_reply_common(const char *inbuf, char *outbuf) { srv_set_message(outbuf,0,0,false); @@ -1607,6 +1610,11 @@ void construct_reply_common(const char *inbuf, char *outbuf) SSVAL(outbuf,smb_mid,SVAL(inbuf,smb_mid)); } +void construct_reply_common_req(struct smb_request *req, char *outbuf) +{ + construct_reply_common((char *)req->inbuf, outbuf); +} + /**************************************************************************** Construct a chained reply and add it to the already made reply ****************************************************************************/ @@ -1717,6 +1725,7 @@ void chain_reply(struct smb_request *req) smb_panic("could not allocate smb_request"); } init_smb_request(req2, (uint8 *)inbuf2,0, req->encrypted); + req2->inbuf = (uint8_t *)inbuf2; req2->chain_fsp = req->chain_fsp; /* process the request */ @@ -1925,8 +1934,6 @@ void smbd_process(void) process_smb(inbuf, inbuf_len, unread_bytes, encrypted); - TALLOC_FREE(inbuf); - num_smbs++; /* The timeout_processing function isn't run nearly diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 25480c6e3b..be39fd464d 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -208,7 +208,7 @@ NTSTATUS check_path_syntax_posix(char *path) ****************************************************************************/ size_t srvstr_get_path_wcard(TALLOC_CTX *ctx, - const char *inbuf, + const char *base_ptr, uint16 smb_flags2, char **pp_dest, const char *src, @@ -221,22 +221,8 @@ size_t srvstr_get_path_wcard(TALLOC_CTX *ctx, *pp_dest = NULL; - if (src_len == 0) { - ret = srvstr_pull_buf_talloc(ctx, - inbuf, - smb_flags2, - pp_dest, - src, - flags); - } else { - ret = srvstr_pull_talloc(ctx, - inbuf, - smb_flags2, - pp_dest, - src, - src_len, - flags); - } + ret = srvstr_pull_talloc(ctx, base_ptr, smb_flags2, pp_dest, src, + src_len, flags); if (!*pp_dest) { *err = NT_STATUS_INVALID_PARAMETER; @@ -268,7 +254,7 @@ size_t srvstr_get_path_wcard(TALLOC_CTX *ctx, ****************************************************************************/ size_t srvstr_get_path(TALLOC_CTX *ctx, - const char *inbuf, + const char *base_ptr, uint16 smb_flags2, char **pp_dest, const char *src, @@ -276,48 +262,27 @@ size_t srvstr_get_path(TALLOC_CTX *ctx, int flags, NTSTATUS *err) { - size_t ret; - - *pp_dest = NULL; - - if (src_len == 0) { - ret = srvstr_pull_buf_talloc(ctx, - inbuf, - smb_flags2, - pp_dest, - src, - flags); - } else { - ret = srvstr_pull_talloc(ctx, - inbuf, - smb_flags2, - pp_dest, - src, - src_len, - flags); - } - - if (!*pp_dest) { - *err = NT_STATUS_INVALID_PARAMETER; - return ret; - } - - if (smb_flags2 & FLAGS2_DFS_PATHNAMES) { - /* - * For a DFS path the function parse_dfs_path() - * will do the path processing, just make a copy. - */ - *err = NT_STATUS_OK; - return ret; - } + bool ignore; + return srvstr_get_path_wcard(ctx, base_ptr, smb_flags2, pp_dest, src, + src_len, flags, err, &ignore); +} - if (lp_posix_pathnames()) { - *err = check_path_syntax_posix(*pp_dest); - } else { - *err = check_path_syntax(*pp_dest); - } +size_t srvstr_get_path_req_wcard(TALLOC_CTX *mem_ctx, struct smb_request *req, + char **pp_dest, const char *src, int flags, + NTSTATUS *err, bool *contains_wcard) +{ + return srvstr_get_path_wcard(mem_ctx, (char *)req->inbuf, req->flags2, + pp_dest, src, smbreq_bufrem(req, src), + flags, err, contains_wcard); +} - return ret; +size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req, + char **pp_dest, const char *src, int flags, + NTSTATUS *err) +{ + bool ignore; + return srvstr_get_path_req_wcard(mem_ctx, req, pp_dest, src, + flags, err, &ignore); } /**************************************************************************** @@ -517,26 +482,25 @@ void reply_tcon(struct smb_request *req) char *dev = NULL; int pwlen=0; NTSTATUS nt_status; - char *p; + const char *p; DATA_BLOB password_blob; TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBtcon); - if (smb_buflen(req->inbuf) < 4) { + if (req->buflen < 4) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBtcon); return; } - p = smb_buf(req->inbuf)+1; - p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, - &service_buf, p, STR_TERMINATE) + 1; - pwlen = srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, - &password, p, STR_TERMINATE) + 1; - p += pwlen; - p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, - &dev, p, STR_TERMINATE) + 1; + p = (const char *)req->buf + 1; + p += srvstr_pull_req_talloc(ctx, req, &service_buf, p, STR_TERMINATE); + p += 1; + pwlen = srvstr_pull_req_talloc(ctx, req, &password, p, STR_TERMINATE); + p += pwlen+1; + p += srvstr_pull_req_talloc(ctx, req, &dev, p, STR_TERMINATE); + p += 1; if (service_buf == NULL || password == NULL || dev == NULL) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); @@ -583,7 +547,7 @@ void reply_tcon(struct smb_request *req) void reply_tcon_and_X(struct smb_request *req) { connection_struct *conn = req->conn; - char *service = NULL; + const char *service = NULL; DATA_BLOB password; TALLOC_CTX *ctx = talloc_tos(); /* what the cleint thinks the device is */ @@ -593,7 +557,7 @@ void reply_tcon_and_X(struct smb_request *req) NTSTATUS nt_status; int passlen; char *path = NULL; - char *p, *q; + const char *p, *q; uint16 tcon_flags; START_PROFILE(SMBtconX); @@ -604,8 +568,8 @@ void reply_tcon_and_X(struct smb_request *req) return; } - passlen = SVAL(req->inbuf,smb_vwv3); - tcon_flags = SVAL(req->inbuf,smb_vwv2); + passlen = SVAL(req->vwv+3, 0); + tcon_flags = SVAL(req->vwv+2, 0); /* we might have to close an old one */ if ((tcon_flags & 0x1) && conn) { @@ -614,34 +578,31 @@ void reply_tcon_and_X(struct smb_request *req) conn = NULL; } - if ((passlen > MAX_PASS_LEN) || (passlen >= smb_buflen(req->inbuf))) { + if ((passlen > MAX_PASS_LEN) || (passlen >= req->buflen)) { reply_doserror(req, ERRDOS, ERRbuftoosmall); END_PROFILE(SMBtconX); return; } if (global_encrypted_passwords_negotiated) { - password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf), - passlen); + password = data_blob_talloc(talloc_tos(), req->buf, passlen); if (lp_security() == SEC_SHARE) { /* * Security = share always has a pad byte * after the password. */ - p = smb_buf(req->inbuf) + passlen + 1; + p = (const char *)req->buf + passlen + 1; } else { - p = smb_buf(req->inbuf) + passlen; + p = (const char *)req->buf + passlen; } } else { - password = data_blob_talloc(talloc_tos(), smb_buf(req->inbuf), - passlen+1); + password = data_blob_talloc(talloc_tos(), req->buf, passlen+1); /* Ensure correct termination */ password.data[passlen]=0; - p = smb_buf(req->inbuf) + passlen + 1; + p = (const char *)req->buf + passlen + 1; } - p += srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &path, p, - STR_TERMINATE); + p += srvstr_pull_req_talloc(ctx, req, &path, p, STR_TERMINATE); if (path == NULL) { data_blob_clear_free(&password); @@ -669,7 +630,7 @@ void reply_tcon_and_X(struct smb_request *req) p += srvstr_pull_talloc(ctx, req->inbuf, req->flags2, &client_devicetype, p, - MIN(6,smb_bufrem(req->inbuf, p)), STR_ASCII); + MIN(6, smbreq_bufrem(req, p)), STR_ASCII); if (client_devicetype == NULL) { data_blob_clear_free(&password); @@ -803,8 +764,8 @@ void reply_ioctl(struct smb_request *req) return; } - device = SVAL(req->inbuf,smb_vwv1); - function = SVAL(req->inbuf,smb_vwv2); + device = SVAL(req->vwv+1, 0); + function = SVAL(req->vwv+2, 0); ioctl_code = (device << 16) + function; DEBUG(4, ("Received IOCTL (code 0x%x)\n", ioctl_code)); @@ -831,7 +792,7 @@ void reply_ioctl(struct smb_request *req) case IOCTL_QUERY_JOB_INFO: { files_struct *fsp = file_fsp( - req, SVAL(req->inbuf, smb_vwv0)); + req, SVAL(req->vwv+0, 0)); if (!fsp) { reply_doserror(req, ERRDOS, ERRbadfid); END_PROFILE(SMBioctl); @@ -860,10 +821,10 @@ void reply_ioctl(struct smb_request *req) Strange checkpath NTSTATUS mapping. ****************************************************************************/ -static NTSTATUS map_checkpath_error(const char *inbuf, NTSTATUS status) +static NTSTATUS map_checkpath_error(uint16_t flags2, NTSTATUS status) { /* Strange DOS error code semantics only for checkpath... */ - if (!(SVAL(inbuf,smb_flg2) & FLAGS2_32_BIT_ERROR_CODES)) { + if (!(flags2 & FLAGS2_32_BIT_ERROR_CODES)) { if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_INVALID,status)) { /* We need to map to ERRbadpath */ return NT_STATUS_OBJECT_PATH_NOT_FOUND; @@ -886,11 +847,11 @@ void reply_checkpath(struct smb_request *req) START_PROFILE(SMBcheckpath); - srvstr_get_path(ctx,(char *)req->inbuf, req->flags2, &name, - smb_buf(req->inbuf) + 1, 0, - STR_TERMINATE, &status); + srvstr_get_path_req(ctx, req, &name, (const char *)req->buf + 1, + STR_TERMINATE, &status); + if (!NT_STATUS_IS_OK(status)) { - status = map_checkpath_error((char *)req->inbuf, status); + status = map_checkpath_error(req->flags2, status); reply_nterror(req, status); END_PROFILE(SMBcheckpath); return; @@ -910,7 +871,7 @@ void reply_checkpath(struct smb_request *req) goto path_err; } - DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->inbuf,smb_vwv0))); + DEBUG(3,("reply_checkpath %s mode=%d\n", name, (int)SVAL(req->vwv+0, 0))); status = unix_convert(ctx, conn, name, False, &name, NULL, &sbuf); if (!NT_STATUS_IS_OK(status)) { @@ -950,7 +911,7 @@ void reply_checkpath(struct smb_request *req) one at a time - if a component fails it expects ERRbadpath, not ERRbadfile. */ - status = map_checkpath_error((char *)req->inbuf, status); + status = map_checkpath_error(req->flags2, status); if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { /* * Windows returns different error codes if @@ -979,15 +940,14 @@ void reply_getatr(struct smb_request *req) int mode=0; SMB_OFF_T size=0; time_t mtime=0; - char *p; + const char *p; NTSTATUS status; TALLOC_CTX *ctx = talloc_tos(); START_PROFILE(SMBgetatr); - p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p, - 0, STR_TERMINATE, &status); + p = (const char *)req->buf + 1; + p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBgetatr); @@ -1081,7 +1041,7 @@ void reply_setatr(struct smb_request *req) int mode; time_t mtime; SMB_STRUCT_STAT sbuf; - char *p; + const char *p; NTSTATUS status; TALLOC_CTX *ctx = talloc_tos(); @@ -1094,9 +1054,8 @@ void reply_setatr(struct smb_request *req) return; } - p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, p, - 0, STR_TERMINATE, &status); + p = (const char *)req->buf + 1; + p += srvstr_get_path_req(ctx, req, &fname, p, STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBsetatr); @@ -1143,8 +1102,8 @@ void reply_setatr(struct smb_request *req) return; } - mode = SVAL(req->inbuf,smb_vwv0); - mtime = srv_make_unix_date3(req->inbuf+smb_vwv1); + mode = SVAL(req->vwv+0, 0); + mtime = srv_make_unix_date3(req->vwv+1); ts[1] = convert_time_t_to_timespec(mtime); status = smb_set_file_time(conn, NULL, fname, @@ -1236,7 +1195,7 @@ void reply_dskattr(struct smb_request *req) void reply_search(struct smb_request *req) { connection_struct *conn = req->conn; - char *mask = NULL; + const char *mask = NULL; char *directory = NULL; char *fname = NULL; SMB_OFF_T size; @@ -1246,7 +1205,7 @@ void reply_search(struct smb_request *req) unsigned int numentries = 0; unsigned int maxentries = 0; bool finished = False; - char *p; + const char *p; int status_len; char *path = NULL; char status[21]; @@ -1268,29 +1227,22 @@ void reply_search(struct smb_request *req) } if (lp_posix_pathnames()) { - reply_unknown_new(req, CVAL(req->inbuf, smb_com)); + reply_unknown_new(req, req->cmd); END_PROFILE(SMBsearch); return; } /* If we were called as SMBffirst then we must expect close. */ - if(CVAL(req->inbuf,smb_com) == SMBffirst) { + if(req->cmd == SMBffirst) { expect_close = True; } reply_outbuf(req, 1, 3); - maxentries = SVAL(req->inbuf,smb_vwv0); - dirtype = SVAL(req->inbuf,smb_vwv1); - p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path_wcard(ctx, - (char *)req->inbuf, - req->flags2, - &path, - p, - 0, - STR_TERMINATE, - &nt_status, - &mask_contains_wcard); + maxentries = SVAL(req->vwv+0, 0); + dirtype = SVAL(req->vwv+1, 0); + p = (const char *)req->buf + 1; + p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE, + &nt_status, &mask_contains_wcard); if (!NT_STATUS_IS_OK(nt_status)) { reply_nterror(req, nt_status); END_PROFILE(SMBsearch); @@ -1339,27 +1291,21 @@ void reply_search(struct smb_request *req) } p = strrchr_m(directory,'/'); - if (!p) { + if ((p != NULL) && (*directory != '/')) { + mask = p + 1; + directory = talloc_strndup(ctx, directory, + PTR_DIFF(p, directory)); + } else { mask = directory; directory = talloc_strdup(ctx,"."); - if (!directory) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBsearch); - return; - } - } else { - *p = 0; - mask = p+1; } - if (*directory == '\0') { - directory = talloc_strdup(ctx,"."); - if (!directory) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBsearch); - return; - } + if (!directory) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBsearch); + return; } + memset((char *)status,'\0',21); SCVAL(status,0,(dirtype & 0x1F)); @@ -1497,7 +1443,7 @@ void reply_search(struct smb_request *req) } /* If we were called as SMBfunique, then we can close the dirptr now ! */ - if(dptr_num >= 0 && CVAL(req->inbuf,smb_com) == SMBfunique) { + if(dptr_num >= 0 && req->cmd == SMBfunique) { dptr_close(&dptr_num); } @@ -1530,7 +1476,7 @@ void reply_search(struct smb_request *req) } DEBUG(4,("%s mask=%s path=%s dtype=%d nument=%u of %u\n", - smb_fn_name(CVAL(req->inbuf,smb_com)), + smb_fn_name(req->cmd), mask, directory ? directory : "./", dirtype, @@ -1550,7 +1496,7 @@ void reply_fclose(struct smb_request *req) int status_len; char status[21]; int dptr_num= -2; - char *p; + const char *p; char *path = NULL; NTSTATUS err; bool path_contains_wcard = False; @@ -1559,21 +1505,14 @@ void reply_fclose(struct smb_request *req) START_PROFILE(SMBfclose); if (lp_posix_pathnames()) { - reply_unknown_new(req, CVAL(req->inbuf, smb_com)); + reply_unknown_new(req, req->cmd); END_PROFILE(SMBfclose); return; } - p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path_wcard(ctx, - (char *)req->inbuf, - req->flags2, - &path, - p, - 0, - STR_TERMINATE, - &err, - &path_contains_wcard); + p = (const char *)req->buf + 1; + p += srvstr_get_path_req_wcard(ctx, req, &path, p, STR_TERMINATE, + &err, &path_contains_wcard); if (!NT_STATUS_IS_OK(err)) { reply_nterror(req, err); END_PROFILE(SMBfclose); @@ -1638,12 +1577,11 @@ void reply_open(struct smb_request *req) } oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); - deny_mode = SVAL(req->inbuf,smb_vwv0); - dos_attr = SVAL(req->inbuf,smb_vwv1); + deny_mode = SVAL(req->vwv+0, 0); + dos_attr = SVAL(req->vwv+1, 0); - srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, - smb_buf(req->inbuf)+1, 0, - STR_TERMINATE, &status); + srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBopen); @@ -1739,8 +1677,8 @@ void reply_open_and_X(struct smb_request *req) int core_oplock_request; int oplock_request; #if 0 - int smb_sattr = SVAL(req->inbuf,smb_vwv4); - uint32 smb_time = make_unix_date3(req->inbuf+smb_vwv6); + int smb_sattr = SVAL(req->vwv+4, 0); + uint32 smb_time = make_unix_date3(req->vwv+6); #endif int smb_ofun; uint32 fattr=0; @@ -1765,14 +1703,14 @@ void reply_open_and_X(struct smb_request *req) return; } - open_flags = SVAL(req->inbuf,smb_vwv2); - deny_mode = SVAL(req->inbuf,smb_vwv3); - smb_attr = SVAL(req->inbuf,smb_vwv5); + open_flags = SVAL(req->vwv+2, 0); + deny_mode = SVAL(req->vwv+3, 0); + smb_attr = SVAL(req->vwv+5, 0); ex_oplock_request = EXTENDED_OPLOCK_REQUEST(req->inbuf); core_oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); oplock_request = ex_oplock_request | core_oplock_request; - smb_ofun = SVAL(req->inbuf,smb_vwv8); - allocation_size = (uint64_t)IVAL(req->inbuf,smb_vwv9); + smb_ofun = SVAL(req->vwv+8, 0); + allocation_size = (uint64_t)IVAL(req->vwv+9, 0); /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { @@ -1786,9 +1724,8 @@ void reply_open_and_X(struct smb_request *req) } /* XXXX we need to handle passed times, sattr and flags */ - srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, - smb_buf(req->inbuf), 0, STR_TERMINATE, - &status); + srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBopenX); @@ -1954,7 +1891,6 @@ void reply_mknew(struct smb_request *req) { connection_struct *conn = req->conn; char *fname = NULL; - int com; uint32 fattr = 0; struct timespec ts[2]; files_struct *fsp; @@ -1975,17 +1911,14 @@ void reply_mknew(struct smb_request *req) return; } - fattr = SVAL(req->inbuf,smb_vwv0); + fattr = SVAL(req->vwv+0, 0); oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); - com = SVAL(req->inbuf,smb_com); - ts[1] =convert_time_t_to_timespec( - srv_make_unix_date3(req->inbuf + smb_vwv1)); + ts[1] = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1)); /* mtime. */ - srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, - smb_buf(req->inbuf) + 1, 0, - STR_TERMINATE, &status); + srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcreate); @@ -1997,7 +1930,7 @@ void reply_mknew(struct smb_request *req) "please report this\n", fname)); } - if(com == SMBmknew) { + if(req->cmd == SMBmknew) { /* We should fail if file exists. */ create_disposition = FILE_CREATE; } else { @@ -2086,12 +2019,11 @@ void reply_ctemp(struct smb_request *req) return; } - fattr = SVAL(req->inbuf,smb_vwv0); + fattr = SVAL(req->vwv+0, 0); oplock_request = CORE_OPLOCK_REQUEST(req->inbuf); - srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &fname, - smb_buf(req->inbuf)+1, 0, STR_TERMINATE, - &status); + srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf+1, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBctemp); @@ -2558,11 +2490,11 @@ void reply_unlink(struct smb_request *req) return; } - dirtype = SVAL(req->inbuf,smb_vwv0); + dirtype = SVAL(req->vwv+0, 0); - srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, - smb_buf(req->inbuf) + 1, 0, - STR_TERMINATE, &status, &path_contains_wcard); + srvstr_get_path_req_wcard(ctx, req, &name, (const char *)req->buf + 1, + STR_TERMINATE, &status, + &path_contains_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBunlink); @@ -2813,7 +2745,7 @@ void reply_readbraw(struct smb_request *req) * return a zero length response here. */ - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); /* * We have to do a check_fsp by hand here, as @@ -2829,7 +2761,7 @@ void reply_readbraw(struct smb_request *req) */ DEBUG(3,("reply_readbraw: fnum %d not valid " "- cache prime?\n", - (int)SVAL(req->inbuf,smb_vwv0))); + (int)SVAL(req->vwv+0, 0))); reply_readbraw_error(); END_PROFILE(SMBreadbraw); return; @@ -2840,7 +2772,7 @@ void reply_readbraw(struct smb_request *req) ((req->flags2 & FLAGS2_READ_PERMIT_EXECUTE) && (fsp->access_mask & FILE_EXECUTE)))) { DEBUG(3,("reply_readbraw: fnum %d not readable.\n", - (int)SVAL(req->inbuf,smb_vwv0))); + (int)SVAL(req->vwv+0, 0))); reply_readbraw_error(); END_PROFILE(SMBreadbraw); return; @@ -2848,14 +2780,14 @@ void reply_readbraw(struct smb_request *req) flush_write_cache(fsp, READRAW_FLUSH); - startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv1); + startpos = IVAL_TO_SMB_OFF_T(req->vwv+1, 0); if(req->wct == 10) { /* * This is a large offset (64 bit) read. */ #ifdef LARGE_SMB_OFF_T - startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv8)) << 32); + startpos |= (((SMB_OFF_T)IVAL(req->vwv+8, 0)) << 32); #else /* !LARGE_SMB_OFF_T */ @@ -2863,11 +2795,11 @@ void reply_readbraw(struct smb_request *req) * Ensure we haven't been sent a >32 bit offset. */ - if(IVAL(req->inbuf,smb_vwv8) != 0) { + if(IVAL(req->vwv+8, 0) != 0) { DEBUG(0,("reply_readbraw: large offset " "(%x << 32) used and we don't support " "64 bit offsets.\n", - (unsigned int)IVAL(req->inbuf,smb_vwv8) )); + (unsigned int)IVAL(req->vwv+8, 0) )); reply_readbraw_error(); END_PROFILE(SMBreadbraw); return; @@ -2885,8 +2817,8 @@ void reply_readbraw(struct smb_request *req) } } - maxcount = (SVAL(req->inbuf,smb_vwv3) & 0xFFFF); - mincount = (SVAL(req->inbuf,smb_vwv4) & 0xFFFF); + maxcount = (SVAL(req->vwv+3, 0) & 0xFFFF); + mincount = (SVAL(req->vwv+4, 0) & 0xFFFF); /* ensure we don't overrun the packet size */ maxcount = MIN(65535,maxcount); @@ -2955,14 +2887,14 @@ void reply_lockread(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBlockread); return; } - if (!CHECK_READ(fsp,req->inbuf)) { + if (!CHECK_READ(fsp,req)) { reply_doserror(req, ERRDOS, ERRbadaccess); END_PROFILE(SMBlockread); return; @@ -2970,8 +2902,8 @@ void reply_lockread(struct smb_request *req) release_level_2_oplocks_on_change(fsp); - numtoread = SVAL(req->inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2); + numtoread = SVAL(req->vwv+1, 0); + startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0); numtoread = MIN(BUFFER_SIZE - (smb_size + 3*2 + 3), numtoread); @@ -3063,21 +2995,21 @@ void reply_read(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBread); return; } - if (!CHECK_READ(fsp,req->inbuf)) { + if (!CHECK_READ(fsp,req)) { reply_doserror(req, ERRDOS, ERRbadaccess); END_PROFILE(SMBread); return; } - numtoread = SVAL(req->inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2); + numtoread = SVAL(req->vwv+1, 0); + startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0); numtoread = MIN(BUFFER_SIZE-outsize,numtoread); @@ -3183,7 +3115,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, * on a train in Germany :-). JRA. */ - if ((chain_size == 0) && (CVAL(req->inbuf,smb_vwv0) == 0xFF) && + if ((chain_size == 0) && (CVAL(req->vwv+0, 0) == 0xFF) && !is_encrypted_packet(req->inbuf) && (fsp->base_fsp == NULL) && lp_use_sendfile(SNUM(conn)) && (fsp->wcp == NULL) ) { uint8 headerbuf[smb_size + 12 * 2]; @@ -3197,7 +3129,7 @@ static void send_file_readX(connection_struct *conn, struct smb_request *req, header = data_blob_const(headerbuf, sizeof(headerbuf)); - construct_reply_common((char *)req->inbuf, (char *)headerbuf); + construct_reply_common_req(req, (char *)headerbuf); setup_readX_header((char *)headerbuf, smb_maxcnt); if ((nread = SMB_VFS_SENDFILE(smbd_server_fd(), fsp, &header, startpos, smb_maxcnt)) == -1) { @@ -3249,7 +3181,7 @@ normal_read: if ((smb_maxcnt & 0xFF0000) > 0x10000) { uint8 headerbuf[smb_size + 2*12]; - construct_reply_common((char *)req->inbuf, (char *)headerbuf); + construct_reply_common_req(req, (char *)headerbuf); setup_readX_header((char *)headerbuf, smb_maxcnt); /* Send out the header. */ @@ -3297,7 +3229,7 @@ void reply_read_and_X(struct smb_request *req) size_t smb_maxcnt; bool big_readX = False; #if 0 - size_t smb_mincnt = SVAL(req->inbuf,smb_vwv6); + size_t smb_mincnt = SVAL(req->vwv+6, 0); #endif START_PROFILE(SMBreadX); @@ -3307,9 +3239,9 @@ void reply_read_and_X(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv2)); - startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3); - smb_maxcnt = SVAL(req->inbuf,smb_vwv5); + fsp = file_fsp(req, SVAL(req->vwv+2, 0)); + startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0); + smb_maxcnt = SVAL(req->vwv+5, 0); /* If it's an IPC, pass off the pipe handler. */ if (IS_IPC(conn)) { @@ -3323,18 +3255,18 @@ void reply_read_and_X(struct smb_request *req) return; } - if (!CHECK_READ(fsp,req->inbuf)) { + if (!CHECK_READ(fsp,req)) { reply_doserror(req, ERRDOS,ERRbadaccess); END_PROFILE(SMBreadX); return; } if (global_client_caps & CAP_LARGE_READX) { - size_t upper_size = SVAL(req->inbuf,smb_vwv7); + size_t upper_size = SVAL(req->vwv+7, 0); smb_maxcnt |= (upper_size<<16); if (upper_size > 1) { /* Can't do this on a chained packet. */ - if ((CVAL(req->inbuf,smb_vwv0) != 0xFF)) { + if ((CVAL(req->vwv+0, 0) != 0xFF)) { reply_nterror(req, NT_STATUS_NOT_SUPPORTED); END_PROFILE(SMBreadX); return; @@ -3361,7 +3293,7 @@ void reply_read_and_X(struct smb_request *req) /* * This is a large offset (64 bit) read. */ - startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv10)) << 32); + startpos |= (((SMB_OFF_T)IVAL(req->vwv+10, 0)) << 32); #else /* !LARGE_SMB_OFF_T */ @@ -3369,10 +3301,10 @@ void reply_read_and_X(struct smb_request *req) * Ensure we haven't been sent a >32 bit offset. */ - if(IVAL(req->inbuf,smb_vwv10) != 0) { + if(IVAL(req->vwv+10, 0) != 0) { DEBUG(0,("reply_read_and_X - large offset (%x << 32) " "used and we don't support 64 bit offsets.\n", - (unsigned int)IVAL(req->inbuf,smb_vwv10) )); + (unsigned int)IVAL(req->vwv+10, 0) )); END_PROFILE(SMBreadX); reply_doserror(req, ERRDOS, ERRbadaccess); return; @@ -3455,7 +3387,7 @@ void reply_writebraw(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if (!check_fsp(conn, req, fsp)) { error_to_writebrawerr(req); END_PROFILE(SMBwritebraw); @@ -3469,9 +3401,9 @@ void reply_writebraw(struct smb_request *req) return; } - tcount = IVAL(req->inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3); - write_through = BITSETW(req->inbuf+smb_vwv7,0); + tcount = IVAL(req->vwv+1, 0); + startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0); + write_through = BITSETW(req->vwv+7,0); /* We have to deal with slightly different formats depending on whether we are using the core+ or lanman1.0 protocol */ @@ -3480,8 +3412,8 @@ void reply_writebraw(struct smb_request *req) numtowrite = SVAL(smb_buf(req->inbuf),-2); data = smb_buf(req->inbuf); } else { - numtowrite = SVAL(req->inbuf,smb_vwv10); - data = smb_base(req->inbuf) + SVAL(req->inbuf, smb_vwv11); + numtowrite = SVAL(req->vwv+10, 0); + data = smb_base(req->inbuf) + SVAL(req->vwv+11, 0); } /* Ensure we don't write bytes past the end of this packet. */ @@ -3648,7 +3580,7 @@ void reply_writeunlock(struct smb_request *req) ssize_t nwritten = -1; size_t numtowrite; SMB_OFF_T startpos; - char *data; + const char *data; NTSTATUS status = NT_STATUS_OK; files_struct *fsp; @@ -3660,7 +3592,7 @@ void reply_writeunlock(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBwriteunlock); @@ -3673,9 +3605,9 @@ void reply_writeunlock(struct smb_request *req) return; } - numtowrite = SVAL(req->inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2); - data = smb_buf(req->inbuf) + 3; + numtowrite = SVAL(req->vwv+1, 0); + startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0); + data = (const char *)req->buf + 3; if (numtowrite && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite, @@ -3748,7 +3680,7 @@ void reply_write(struct smb_request *req) size_t numtowrite; ssize_t nwritten = -1; SMB_OFF_T startpos; - char *data; + const char *data; files_struct *fsp; NTSTATUS status; @@ -3767,7 +3699,7 @@ void reply_write(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBwrite); @@ -3780,9 +3712,9 @@ void reply_write(struct smb_request *req) return; } - numtowrite = SVAL(req->inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2); - data = smb_buf(req->inbuf) + 3; + numtowrite = SVAL(req->vwv+1, 0); + startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0); + data = (const char *)req->buf + 3; if (is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite, (uint64_t)startpos, WRITE_LOCK)) { @@ -3954,14 +3886,14 @@ void reply_write_and_X(struct smb_request *req) return; } - numtowrite = SVAL(req->inbuf,smb_vwv10); - smb_doff = SVAL(req->inbuf,smb_vwv11); + numtowrite = SVAL(req->vwv+10, 0); + smb_doff = SVAL(req->vwv+11, 0); smblen = smb_len(req->inbuf); if (req->unread_bytes > 0xFFFF || (smblen > smb_doff && smblen - smb_doff > 0xFFFF)) { - numtowrite |= (((size_t)SVAL(req->inbuf,smb_vwv9))<<16); + numtowrite |= (((size_t)SVAL(req->vwv+9, 0))<<16); } if (req->unread_bytes) { @@ -3997,9 +3929,9 @@ void reply_write_and_X(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv2)); - startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv3); - write_through = BITSETW(req->inbuf+smb_vwv7,0); + fsp = file_fsp(req, SVAL(req->vwv+2, 0)); + startpos = IVAL_TO_SMB_OFF_T(req->vwv+3, 0); + write_through = BITSETW(req->vwv+7,0); if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBwriteX); @@ -4019,7 +3951,7 @@ void reply_write_and_X(struct smb_request *req) /* * This is a large offset (64 bit) write. */ - startpos |= (((SMB_OFF_T)IVAL(req->inbuf,smb_vwv12)) << 32); + startpos |= (((SMB_OFF_T)IVAL(req->vwv+12, 0)) << 32); #else /* !LARGE_SMB_OFF_T */ @@ -4027,10 +3959,10 @@ void reply_write_and_X(struct smb_request *req) * Ensure we haven't been sent a >32 bit offset. */ - if(IVAL(req->inbuf,smb_vwv12) != 0) { + if(IVAL(req->vwv+12, 0) != 0) { DEBUG(0,("reply_write_and_X - large offset (%x << 32) " "used and we don't support 64 bit offsets.\n", - (unsigned int)IVAL(req->inbuf,smb_vwv12) )); + (unsigned int)IVAL(req->vwv+12, 0) )); reply_doserror(req, ERRDOS, ERRbadaccess); END_PROFILE(SMBwriteX); return; @@ -4118,7 +4050,7 @@ void reply_lseek(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if (!check_fsp(conn, req, fsp)) { return; @@ -4126,9 +4058,9 @@ void reply_lseek(struct smb_request *req) flush_write_cache(fsp, SEEK_FLUSH); - mode = SVAL(req->inbuf,smb_vwv1) & 3; + mode = SVAL(req->vwv+1, 0) & 3; /* NB. This doesn't use IVAL_TO_SMB_OFF_T as startpos can be signed in this case. */ - startpos = (SMB_OFF_T)IVALS(req->inbuf,smb_vwv2); + startpos = (SMB_OFF_T)IVALS(req->vwv+2, 0); switch (mode) { case 0: @@ -4203,7 +4135,7 @@ void reply_flush(struct smb_request *req) return; } - fnum = SVAL(req->inbuf,smb_vwv0); + fnum = SVAL(req->vwv+0, 0); fsp = file_fsp(req, fnum); if ((fnum != 0xFFFF) && !check_fsp(conn, req, fsp)) { @@ -4266,7 +4198,7 @@ void reply_close(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); /* * We can only use check_fsp if we know it's not a directory. @@ -4298,7 +4230,7 @@ void reply_close(struct smb_request *req) * Take care of any time sent in the close. */ - t = srv_make_unix_date3(req->inbuf+smb_vwv1); + t = srv_make_unix_date3(req->vwv+1); set_close_write_time(fsp, convert_time_t_to_timespec(t)); /* @@ -4332,7 +4264,7 @@ void reply_writeclose(struct smb_request *req) ssize_t nwritten = -1; NTSTATUS close_status = NT_STATUS_OK; SMB_OFF_T startpos; - char *data; + const char *data; struct timespec mtime; files_struct *fsp; @@ -4344,7 +4276,7 @@ void reply_writeclose(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBwriteclose); @@ -4356,11 +4288,10 @@ void reply_writeclose(struct smb_request *req) return; } - numtowrite = SVAL(req->inbuf,smb_vwv1); - startpos = IVAL_TO_SMB_OFF_T(req->inbuf,smb_vwv2); - mtime = convert_time_t_to_timespec(srv_make_unix_date3( - req->inbuf+smb_vwv4)); - data = smb_buf(req->inbuf) + 1; + numtowrite = SVAL(req->vwv+1, 0); + startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0); + mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4)); + data = (const char *)req->buf + 1; if (numtowrite && is_locked(fsp, (uint32)req->smbpid, (uint64_t)numtowrite, @@ -4431,7 +4362,7 @@ void reply_lock(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBlock); @@ -4440,8 +4371,8 @@ void reply_lock(struct smb_request *req) release_level_2_oplocks_on_change(fsp); - count = (uint64_t)IVAL(req->inbuf,smb_vwv1); - offset = (uint64_t)IVAL(req->inbuf,smb_vwv3); + count = (uint64_t)IVAL(req->vwv+1, 0); + offset = (uint64_t)IVAL(req->vwv+3, 0); DEBUG(3,("lock fd=%d fnum=%d offset=%.0f count=%.0f\n", fsp->fh->fd, fsp->fnum, (double)offset, (double)count)); @@ -4490,15 +4421,15 @@ void reply_unlock(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBunlock); return; } - count = (uint64_t)IVAL(req->inbuf,smb_vwv1); - offset = (uint64_t)IVAL(req->inbuf,smb_vwv3); + count = (uint64_t)IVAL(req->vwv+1, 0); + offset = (uint64_t)IVAL(req->vwv+3, 0); status = do_unlock(smbd_messaging_context(), fsp, @@ -4562,7 +4493,6 @@ void reply_echo(struct smb_request *req) connection_struct *conn = req->conn; int smb_reverb; int seq_num; - unsigned int data_len = smb_buflen(req->inbuf); START_PROFILE(SMBecho); @@ -4572,20 +4502,13 @@ void reply_echo(struct smb_request *req) return; } - if (data_len > BUFFER_SIZE) { - DEBUG(0,("reply_echo: data_len too large.\n")); - reply_nterror(req, NT_STATUS_INSUFFICIENT_RESOURCES); - END_PROFILE(SMBecho); - return; - } + smb_reverb = SVAL(req->vwv+0, 0); - smb_reverb = SVAL(req->inbuf,smb_vwv0); - - reply_outbuf(req, 1, data_len); + reply_outbuf(req, 1, req->buflen); /* copy any incoming data back out */ - if (data_len > 0) { - memcpy(smb_buf(req->outbuf),smb_buf(req->inbuf),data_len); + if (req->buflen > 0) { + memcpy(smb_buf(req->outbuf), req->buf, req->buflen); } if (smb_reverb > 100) { @@ -4672,7 +4595,7 @@ void reply_printclose(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBsplclose); @@ -4720,8 +4643,8 @@ void reply_printqueue(struct smb_request *req) return; } - max_count = SVAL(req->inbuf,smb_vwv0); - start_index = SVAL(req->inbuf,smb_vwv1); + max_count = SVAL(req->vwv+0, 0); + start_index = SVAL(req->vwv+1, 0); /* we used to allow the client to get the cnum wrong, but that is really quite gross and only worked when there was only @@ -4803,7 +4726,7 @@ void reply_printwrite(struct smb_request *req) { connection_struct *conn = req->conn; int numtowrite; - char *data; + const char *data; files_struct *fsp; START_PROFILE(SMBsplwr); @@ -4814,7 +4737,7 @@ void reply_printwrite(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if (!check_fsp(conn, req, fsp)) { END_PROFILE(SMBsplwr); @@ -4833,15 +4756,15 @@ void reply_printwrite(struct smb_request *req) return; } - numtowrite = SVAL(smb_buf(req->inbuf),1); + numtowrite = SVAL(req->buf, 1); - if (smb_buflen(req->inbuf) < numtowrite + 3) { + if (req->buflen < numtowrite + 3) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBsplwr); return; } - data = smb_buf(req->inbuf) + 3; + data = (const char *)req->buf + 3; if (write_file(req,fsp,data,-1,numtowrite) != numtowrite) { reply_unixerror(req, ERRHRD, ERRdiskfull); @@ -4869,9 +4792,8 @@ void reply_mkdir(struct smb_request *req) START_PROFILE(SMBmkdir); - srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory, - smb_buf(req->inbuf) + 1, 0, - STR_TERMINATE, &status); + srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBmkdir); @@ -5140,9 +5062,8 @@ void reply_rmdir(struct smb_request *req) START_PROFILE(SMBrmdir); - srvstr_get_path(ctx, (char *)req->inbuf, req->flags2, &directory, - smb_buf(req->inbuf) + 1, 0, - STR_TERMINATE, &status); + srvstr_get_path_req(ctx, req, &directory, (const char *)req->buf + 1, + STR_TERMINATE, &status); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBrmdir); @@ -5922,7 +5843,7 @@ void reply_mv(struct smb_request *req) connection_struct *conn = req->conn; char *name = NULL; char *newname = NULL; - char *p; + const char *p; uint32 attrs; NTSTATUS status; bool src_has_wcard = False; @@ -5937,21 +5858,19 @@ void reply_mv(struct smb_request *req) return; } - attrs = SVAL(req->inbuf,smb_vwv0); + attrs = SVAL(req->vwv+0, 0); - p = smb_buf(req->inbuf) + 1; - p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p, - 0, STR_TERMINATE, &status, - &src_has_wcard); + p = (const char *)req->buf + 1; + p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE, + &status, &src_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBmv); return; } p++; - p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p, - 0, STR_TERMINATE, &status, - &dest_has_wcard); + p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE, + &status, &dest_has_wcard); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBmv); @@ -6155,8 +6074,9 @@ void reply_copy(struct smb_request *req) char *name = NULL; char *newname = NULL; char *directory = NULL; - char *mask = NULL; - char *p; + const char *mask = NULL; + const char mask_star[] = "*"; + const char *p; int count=0; int error = ERRnoaccess; int err = 0; @@ -6178,22 +6098,20 @@ void reply_copy(struct smb_request *req) return; } - tid2 = SVAL(req->inbuf,smb_vwv0); - ofun = SVAL(req->inbuf,smb_vwv1); - flags = SVAL(req->inbuf,smb_vwv2); + tid2 = SVAL(req->vwv+0, 0); + ofun = SVAL(req->vwv+1, 0); + flags = SVAL(req->vwv+2, 0); - p = smb_buf(req->inbuf); - p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &name, p, - 0, STR_TERMINATE, &status, - &source_has_wild); + p = (const char *)req->buf; + p += srvstr_get_path_req_wcard(ctx, req, &name, p, STR_TERMINATE, + &status, &source_has_wild); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcopy); return; } - p += srvstr_get_path_wcard(ctx, (char *)req->inbuf, req->flags2, &newname, p, - 0, STR_TERMINATE, &status, - &dest_has_wild); + p += srvstr_get_path_req_wcard(ctx, req, &newname, p, STR_TERMINATE, + &status, &dest_has_wild); if (!NT_STATUS_IS_OK(status)) { reply_nterror(req, status); END_PROFILE(SMBcopy); @@ -6283,23 +6201,18 @@ void reply_copy(struct smb_request *req) } p = strrchr_m(name,'/'); - if (!p) { + if (p != NULL) { + directory = talloc_strndup(ctx, name, PTR_DIFF(p, name)); + mask = p+1; + } else { directory = talloc_strdup(ctx, "./"); - if (!directory) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBcopy); - return; - } mask = name; - } else { - *p = 0; - directory = talloc_strdup(ctx, name); - if (!directory) { - reply_nterror(req, NT_STATUS_NO_MEMORY); - END_PROFILE(SMBcopy); - return; - } - mask = p+1; + } + + if (!directory) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBcopy); + return; } /* @@ -6367,8 +6280,7 @@ void reply_copy(struct smb_request *req) long offset = 0; if (strequal(mask,"????????.???")) { - mask[0] = '*'; - mask[1] = '\0'; + mask = mask_star; } status = check_name(conn, directory); @@ -6484,7 +6396,8 @@ void reply_copy(struct smb_request *req) Get a lock pid, dealing with large count requests. ****************************************************************************/ -uint32 get_lock_pid( char *data, int data_offset, bool large_file_format) +uint32 get_lock_pid(const uint8_t *data, int data_offset, + bool large_file_format) { if(!large_file_format) return (uint32)SVAL(data,SMB_LPID_OFFSET(data_offset)); @@ -6496,7 +6409,8 @@ uint32 get_lock_pid( char *data, int data_offset, bool large_file_format) Get a lock count, dealing with large count requests. ****************************************************************************/ -uint64_t get_lock_count( char *data, int data_offset, bool large_file_format) +uint64_t get_lock_count(const uint8_t *data, int data_offset, + bool large_file_format) { uint64_t count = 0; @@ -6568,7 +6482,8 @@ static uint32 map_lock_offset(uint32 high, uint32 low) Get a lock offset, dealing with large offset requests. ****************************************************************************/ -uint64_t get_lock_offset( char *data, int data_offset, bool large_file_format, bool *err) +uint64_t get_lock_offset(const uint8_t *data, int data_offset, + bool large_file_format, bool *err) { uint64_t offset = 0; @@ -6629,7 +6544,7 @@ void reply_lockingX(struct smb_request *req) uint32 lock_pid; int32 lock_timeout; int i; - char *data; + const uint8_t *data; bool large_file_format; bool err; NTSTATUS status = NT_STATUS_UNSUCCESSFUL; @@ -6642,12 +6557,12 @@ void reply_lockingX(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv2)); - locktype = CVAL(req->inbuf,smb_vwv3); - oplocklevel = CVAL(req->inbuf,smb_vwv3+1); - num_ulocks = SVAL(req->inbuf,smb_vwv6); - num_locks = SVAL(req->inbuf,smb_vwv7); - lock_timeout = IVAL(req->inbuf,smb_vwv4); + fsp = file_fsp(req, SVAL(req->vwv+2, 0)); + locktype = CVAL(req->vwv+3, 0); + oplocklevel = CVAL(req->vwv+3, 1); + num_ulocks = SVAL(req->vwv+6, 0); + num_locks = SVAL(req->vwv+7, 0); + lock_timeout = IVAL(req->vwv+4, 0); large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; if (!check_fsp(conn, req, fsp)) { @@ -6655,7 +6570,7 @@ void reply_lockingX(struct smb_request *req) return; } - data = smb_buf(req->inbuf); + data = req->buf; if (locktype & LOCKING_ANDX_CHANGE_LOCKTYPE) { /* we don't support these - and CANCEL_LOCK makes w2k @@ -6729,11 +6644,10 @@ void reply_lockingX(struct smb_request *req) if (num_locks == 0 && num_ulocks == 0) { /* Sanity check - ensure a pure oplock break is not a chained request. */ - if(CVAL(req->inbuf,smb_vwv0) != 0xff) + if(CVAL(req->vwv+0, 0) != 0xff) DEBUG(0,("reply_lockingX: Error : pure oplock " "break is a chained %d request !\n", - (unsigned int)CVAL(req->inbuf, - smb_vwv0) )); + (unsigned int)CVAL(req->vwv+0, 0))); END_PROFILE(SMBlockingX); return; } @@ -6746,7 +6660,7 @@ void reply_lockingX(struct smb_request *req) release_level_2_oplocks_on_change(fsp); - if (smb_buflen(req->inbuf) < + if (req->buflen < (num_ulocks + num_locks) * (large_file_format ? 20 : 10)) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); END_PROFILE(SMBlockingX); @@ -7018,7 +6932,7 @@ void reply_setattrE(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if(!fsp || (fsp->conn != conn)) { reply_doserror(req, ERRDOS, ERRbadfid); @@ -7033,9 +6947,9 @@ void reply_setattrE(struct smb_request *req) */ ts[0] = convert_time_t_to_timespec( - srv_make_unix_date2(req->inbuf+smb_vwv3)); /* atime. */ + srv_make_unix_date2(req->vwv+3)); /* atime. */ ts[1] = convert_time_t_to_timespec( - srv_make_unix_date2(req->inbuf+smb_vwv5)); /* mtime. */ + srv_make_unix_date2(req->vwv+5)); /* mtime. */ reply_outbuf(req, 0, 0); @@ -7129,7 +7043,7 @@ void reply_getattrE(struct smb_request *req) return; } - fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv0)); + fsp = file_fsp(req, SVAL(req->vwv+0, 0)); if(!fsp || (fsp->conn != conn)) { reply_doserror(req, ERRDOS, ERRbadfid); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 4e81263ee4..fff05a3aac 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -80,7 +80,7 @@ struct event_context *smbd_event_context(void) { static struct event_context *ctx; - if (!ctx && !(ctx = event_context_init(NULL))) { + if (!ctx && !(ctx = event_context_init(talloc_autofree_context()))) { smb_panic("Could not init smbd event context"); } return ctx; @@ -91,7 +91,7 @@ struct messaging_context *smbd_messaging_context(void) static struct messaging_context *ctx; if (ctx == NULL) { - ctx = messaging_init(NULL, server_id_self(), + ctx = messaging_init(talloc_autofree_context(), server_id_self(), smbd_event_context()); } if (ctx == NULL) { @@ -105,7 +105,7 @@ struct memcache *smbd_memcache(void) static struct memcache *cache; if (!cache - && !(cache = memcache_init(NULL, + && !(cache = memcache_init(talloc_autofree_context(), lp_max_stat_cache_size()*1024))) { smb_panic("Could not init smbd memcache"); @@ -1415,7 +1415,7 @@ extern void build_options(bool screen); } if (*lp_rootdir()) { - if (sys_chroot(lp_rootdir()) == 0) + if (chroot(lp_rootdir()) == 0) DEBUG(2,("Changed root to %s\n", lp_rootdir())); } diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index a482b3398a..fde6cdc160 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1161,23 +1161,25 @@ static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, static void reply_sesssetup_and_X_spnego(struct smb_request *req) { - uint8 *p; + const uint8 *p; DATA_BLOB blob1; size_t bufrem; - fstring native_os, native_lanman, primary_domain; + char *tmp; + const char *native_os; + const char *native_lanman; + const char *primary_domain; const char *p2; - uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7); + uint16 data_blob_len = SVAL(req->vwv+7, 0); enum remote_arch_types ra_type = get_remote_arch(); int vuid = SVAL(req->inbuf,smb_uid); user_struct *vuser = NULL; NTSTATUS status = NT_STATUS_OK; uint16 smbpid = req->smbpid; - uint16 smb_flag2 = req->flags2; DEBUG(3,("Doing spnego session setup\n")); if (global_client_caps == 0) { - global_client_caps = IVAL(req->inbuf,smb_vwv10); + global_client_caps = IVAL(req->vwv+10, 0); if (!(global_client_caps & CAP_STATUS32)) { remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); @@ -1185,7 +1187,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) } - p = (uint8 *)smb_buf(req->inbuf); + p = req->buf; if (data_blob_len == 0) { /* an invalid request */ @@ -1193,7 +1195,7 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) return; } - bufrem = smb_bufrem(req->inbuf, p); + bufrem = smbreq_bufrem(req, p); /* pull the spnego blob */ blob1 = data_blob(p, MIN(bufrem, data_blob_len)); @@ -1202,12 +1204,19 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req) #endif p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len; - p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2, - sizeof(native_os), STR_TERMINATE); - p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2, - sizeof(native_lanman), STR_TERMINATE); - p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2, - sizeof(primary_domain), STR_TERMINATE); + + p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2, + STR_TERMINATE); + native_os = tmp ? tmp : ""; + + p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2, + STR_TERMINATE); + native_lanman = tmp ? tmp : ""; + + p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2, + STR_TERMINATE); + primary_domain = tmp ? tmp : ""; + DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", native_os, native_lanman, primary_domain)); @@ -1390,12 +1399,13 @@ void reply_sesssetup_and_X(struct smb_request *req) DATA_BLOB lm_resp; DATA_BLOB nt_resp; DATA_BLOB plaintext_password; - fstring user; + char *tmp; + const char *user; fstring sub_user; /* Sainitised username for substituion */ - fstring domain; - fstring native_os; - fstring native_lanman; - fstring primary_domain; + const char *domain; + const char *native_os; + const char *native_lanman; + const char *primary_domain; static bool done_sesssetup = False; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; @@ -1428,7 +1438,7 @@ void reply_sesssetup_and_X(struct smb_request *req) return; } - if (SVAL(req->inbuf,smb_vwv4) == 0) { + if (SVAL(req->vwv+4, 0) == 0) { setup_new_vc_session(); } @@ -1437,18 +1447,16 @@ void reply_sesssetup_and_X(struct smb_request *req) return; } - smb_bufsize = SVAL(req->inbuf,smb_vwv2); + smb_bufsize = SVAL(req->vwv+2, 0); if (Protocol < PROTOCOL_NT1) { - uint16 passlen1 = SVAL(req->inbuf,smb_vwv7); + uint16 passlen1 = SVAL(req->vwv+7, 0); /* Never do NT status codes with protocols before NT1 as we * don't get client caps. */ remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); - if ((passlen1 > MAX_PASS_LEN) - || (passlen1 > smb_bufrem(req->inbuf, - smb_buf(req->inbuf)))) { + if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) { reply_nterror(req, nt_status_squash( NT_STATUS_INVALID_PARAMETER)); END_PROFILE(SMBsesssetupX); @@ -1456,30 +1464,30 @@ void reply_sesssetup_and_X(struct smb_request *req) } if (doencrypt) { - lm_resp = data_blob(smb_buf(req->inbuf), passlen1); + lm_resp = data_blob(req->buf, passlen1); } else { - plaintext_password = data_blob(smb_buf(req->inbuf), - passlen1+1); + plaintext_password = data_blob(req->buf, passlen1+1); /* Ensure null termination */ plaintext_password.data[passlen1] = 0; } - srvstr_pull_buf(req->inbuf, req->flags2, user, - smb_buf(req->inbuf)+passlen1, sizeof(user), - STR_TERMINATE); - *domain = 0; + srvstr_pull_req_talloc(talloc_tos(), req, &tmp, + req->buf + passlen1, STR_TERMINATE); + user = tmp ? tmp : ""; + + domain = ""; } else { - uint16 passlen1 = SVAL(req->inbuf,smb_vwv7); - uint16 passlen2 = SVAL(req->inbuf,smb_vwv8); + uint16 passlen1 = SVAL(req->vwv+7, 0); + uint16 passlen2 = SVAL(req->vwv+8, 0); enum remote_arch_types ra_type = get_remote_arch(); - char *p = smb_buf(req->inbuf); - char *save_p = smb_buf(req->inbuf); + const uint8_t *p = req->buf; + const uint8_t *save_p = req->buf; uint16 byte_count; if(global_client_caps == 0) { - global_client_caps = IVAL(req->inbuf,smb_vwv11); + global_client_caps = IVAL(req->vwv+11, 0); if (!(global_client_caps & CAP_STATUS32)) { remove_from_common_flags2( @@ -1521,7 +1529,7 @@ void reply_sesssetup_and_X(struct smb_request *req) /* check for nasty tricks */ if (passlen1 > MAX_PASS_LEN - || passlen1 > smb_bufrem(req->inbuf, p)) { + || passlen1 > smbreq_bufrem(req, p)) { reply_nterror(req, nt_status_squash( NT_STATUS_INVALID_PARAMETER)); END_PROFILE(SMBsesssetupX); @@ -1529,7 +1537,7 @@ void reply_sesssetup_and_X(struct smb_request *req) } if (passlen2 > MAX_PASS_LEN - || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) { + || passlen2 > smbreq_bufrem(req, p+passlen1)) { reply_nterror(req, nt_status_squash( NT_STATUS_INVALID_PARAMETER)); END_PROFILE(SMBsesssetupX); @@ -1559,7 +1567,7 @@ void reply_sesssetup_and_X(struct smb_request *req) req->inbuf, req->flags2, &pass, - smb_buf(req->inbuf), + req->buf, passlen1, STR_TERMINATE|STR_ASCII); } else { @@ -1567,7 +1575,7 @@ void reply_sesssetup_and_X(struct smb_request *req) req->inbuf, req->flags2, &pass, - smb_buf(req->inbuf), + req->buf, unic ? passlen2 : passlen1, STR_TERMINATE); } @@ -1581,15 +1589,22 @@ void reply_sesssetup_and_X(struct smb_request *req) } p += passlen1 + passlen2; - p += srvstr_pull_buf(req->inbuf, req->flags2, user, p, - sizeof(user), STR_TERMINATE); - p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p, - sizeof(domain), STR_TERMINATE); - p += srvstr_pull_buf(req->inbuf, req->flags2, native_os, - p, sizeof(native_os), STR_TERMINATE); - p += srvstr_pull_buf(req->inbuf, req->flags2, - native_lanman, p, sizeof(native_lanman), - STR_TERMINATE); + + p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p, + STR_TERMINATE); + user = tmp ? tmp : ""; + + p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p, + STR_TERMINATE); + domain = tmp ? tmp : ""; + + p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p, + STR_TERMINATE); + native_os = tmp ? tmp : ""; + + p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p, + STR_TERMINATE); + native_lanman = tmp ? tmp : ""; /* not documented or decoded by Ethereal but there is one more * string in the extra bytes which is the same as the @@ -1598,14 +1613,13 @@ void reply_sesssetup_and_X(struct smb_request *req) * Windows 9x does not include a string here at all so we have * to check if we have any extra bytes left */ - byte_count = SVAL(req->inbuf, smb_vwv13); + byte_count = SVAL(req->vwv+13, 0); if ( PTR_DIFF(p, save_p) < byte_count) { - p += srvstr_pull_buf(req->inbuf, req->flags2, - primary_domain, p, - sizeof(primary_domain), - STR_TERMINATE); + p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p, + STR_TERMINATE); + primary_domain = tmp ? tmp : ""; } else { - fstrcpy( primary_domain, "null" ); + primary_domain = talloc_strdup(talloc_tos(), "null"); } DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] " @@ -1621,7 +1635,7 @@ void reply_sesssetup_and_X(struct smb_request *req) } - if (SVAL(req->inbuf,smb_vwv4) == 0) { + if (SVAL(req->vwv+4, 0) == 0) { setup_new_vc_session(); } @@ -1662,7 +1676,7 @@ void reply_sesssetup_and_X(struct smb_request *req) add_session_user(sub_user); add_session_workgroup(domain); /* Then force it to null for the benfit of the code below */ - *user = 0; + user = ""; } if (!*user) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1da45a8b58..c385c6ccb1 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -768,6 +768,12 @@ void send_trans2_replies(connection_struct *conn, reply_outbuf(req, 10, total_sent_thistime + alignment_offset + data_alignment_offset); + /* + * We might have SMBtrans2s in req which was transferred to + * the outbuf, fix that. + */ + SCVAL(req->outbuf, smb_com, SMBtrans2); + /* Set total params and data to be sent */ SSVAL(req->outbuf,smb_tprcnt,paramsize); SSVAL(req->outbuf,smb_tdrcnt,datasize); @@ -2183,7 +2189,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", - smb_fn_name(CVAL(req->inbuf,smb_com)), + smb_fn_name(req->cmd), mask, directory, dirtype, numentries ) ); /* @@ -2481,7 +2487,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd } DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n", - smb_fn_name(CVAL(req->inbuf,smb_com)), + smb_fn_name(req->cmd), mask, directory, dirtype, numentries ) ); /* Check if we can close the dirptr */ @@ -3118,7 +3124,7 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned max_data_bytes); DEBUG( 4, ( "%s info_level = %d\n", - smb_fn_name(CVAL(req->inbuf,smb_com)), info_level) ); + smb_fn_name(req->cmd), info_level) ); return; } @@ -3846,7 +3852,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn, files_struct *fsp = NULL; struct file_id fileid; struct ea_list *ea_list = NULL; - uint32 access_mask = 0x12019F; /* Default - GENERIC_EXECUTE mapping from Windows */ char *lock_data = NULL; bool ms_dfs_link = false; TALLOC_CTX *ctx = talloc_tos(); @@ -3939,7 +3944,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn, pos = fsp->fh->position_information; fileid = vfs_file_id_from_sbuf(conn, &sbuf); get_file_infos(fileid, &delete_pending, &write_time_ts); - access_mask = fsp->access_mask; } } else { @@ -4403,7 +4407,12 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd case SMB_FILE_ACCESS_INFORMATION: DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n")); - SIVAL(pdata,0,access_mask); + if (fsp) { + SIVAL(pdata,0,fsp->access_mask); + } else { + /* GENERIC_EXECUTE mapping from Windows */ + SIVAL(pdata,0,0x12019F); + } data_size = 4; break; @@ -5470,7 +5479,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn, ****************************************************************************/ static NTSTATUS smb_set_posix_lock(connection_struct *conn, - const struct smb_request *req, + struct smb_request *req, const char *pdata, int total_data, files_struct *fsp) @@ -7251,7 +7260,7 @@ static void call_trans2ioctl(connection_struct *conn, unsigned int max_data_bytes) { char *pdata = *ppdata; - files_struct *fsp = file_fsp(req, SVAL(req->inbuf,smb_vwv15)); + files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0)); /* check for an invalid fid before proceeding */ @@ -7304,7 +7313,7 @@ void reply_findclose(struct smb_request *req) return; } - dptr_num = SVALS(req->inbuf,smb_vwv0); + dptr_num = SVALS(req->vwv+0, 0); DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num)); @@ -7334,7 +7343,7 @@ void reply_findnclose(struct smb_request *req) return; } - dptr_num = SVAL(req->inbuf,smb_vwv0); + dptr_num = SVAL(req->vwv+0, 0); DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num)); @@ -7537,11 +7546,11 @@ void reply_trans2(struct smb_request *req) return; } - dsoff = SVAL(req->inbuf, smb_dsoff); - dscnt = SVAL(req->inbuf, smb_dscnt); - psoff = SVAL(req->inbuf, smb_psoff); - pscnt = SVAL(req->inbuf, smb_pscnt); - tran_call = SVAL(req->inbuf, smb_setup0); + dsoff = SVAL(req->vwv+12, 0); + dscnt = SVAL(req->vwv+11, 0); + psoff = SVAL(req->vwv+10, 0); + pscnt = SVAL(req->vwv+9, 0); + tran_call = SVAL(req->vwv+14, 0); size = smb_len(req->inbuf) + 4; av_size = smb_len(req->inbuf); @@ -7581,17 +7590,17 @@ void reply_trans2(struct smb_request *req) state->mid = req->mid; state->vuid = req->vuid; - state->setup_count = SVAL(req->inbuf, smb_suwcnt); + state->setup_count = SVAL(req->vwv+13, 0); state->setup = NULL; - state->total_param = SVAL(req->inbuf, smb_tpscnt); + state->total_param = SVAL(req->vwv+0, 0); state->param = NULL; - state->total_data = SVAL(req->inbuf, smb_tdscnt); + state->total_data = SVAL(req->vwv+1, 0); state->data = NULL; - state->max_param_return = SVAL(req->inbuf, smb_mprcnt); - state->max_data_return = SVAL(req->inbuf, smb_mdrcnt); - state->max_setup_return = SVAL(req->inbuf, smb_msrcnt); - state->close_on_completion = BITSETW(req->inbuf+smb_vwv5,0); - state->one_way = BITSETW(req->inbuf+smb_vwv5,1); + state->max_param_return = SVAL(req->vwv+2, 0); + state->max_data_return = SVAL(req->vwv+3, 0); + state->max_setup_return = SVAL(req->vwv+4, 0); + state->close_on_completion = BITSETW(req->vwv+5, 0); + state->one_way = BITSETW(req->vwv+5, 1); state->call = tran_call; @@ -7755,18 +7764,18 @@ void reply_transs2(struct smb_request *req) /* Revise state->total_param and state->total_data in case they have changed downwards */ - if (SVAL(req->inbuf, smb_tpscnt) < state->total_param) - state->total_param = SVAL(req->inbuf, smb_tpscnt); - if (SVAL(req->inbuf, smb_tdscnt) < state->total_data) - state->total_data = SVAL(req->inbuf, smb_tdscnt); + if (SVAL(req->vwv+0, 0) < state->total_param) + state->total_param = SVAL(req->vwv+0, 0); + if (SVAL(req->vwv+1, 0) < state->total_data) + state->total_data = SVAL(req->vwv+1, 0); - pcnt = SVAL(req->inbuf, smb_spscnt); - poff = SVAL(req->inbuf, smb_spsoff); - pdisp = SVAL(req->inbuf, smb_spsdisp); + pcnt = SVAL(req->vwv+2, 0); + poff = SVAL(req->vwv+3, 0); + pdisp = SVAL(req->vwv+4, 0); - dcnt = SVAL(req->inbuf, smb_sdscnt); - doff = SVAL(req->inbuf, smb_sdsoff); - ddisp = SVAL(req->inbuf, smb_sdsdisp); + dcnt = SVAL(req->vwv+5, 0); + doff = SVAL(req->vwv+6, 0); + ddisp = SVAL(req->vwv+7, 0); state->received_param += pcnt; state->received_data += dcnt; @@ -7819,12 +7828,6 @@ void reply_transs2(struct smb_request *req) return; } - /* - * construct_reply_common will copy smb_com from inbuf to - * outbuf. SMBtranss2 is wrong here. - */ - SCVAL(req->inbuf,smb_com,SMBtrans2); - handle_trans2(conn, req, state); DLIST_REMOVE(conn->pending_trans, state); diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 8998f6a371..045de6f2d3 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -32,7 +32,7 @@ bool change_to_guest(void) if (!pass) { /* Don't need to free() this as its stored in a static */ - pass = getpwnam_alloc(NULL, lp_guestaccount()); + pass = getpwnam_alloc(talloc_autofree_context(), lp_guestaccount()); if (!pass) return(False); } |