diff options
author | Volker Lendecke <vlendec@samba.org> | 2007-07-23 09:36:09 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:28:53 -0500 |
commit | cc6a41017c577742af73b4bc60993d8d415ea580 (patch) | |
tree | a1705a0b1dedc300c7c728fd4fad6fe53192bf10 /source3/smbd | |
parent | 041204d1a4ec9b19287ca92fa5b291a8eb5ff10b (diff) | |
download | samba-cc6a41017c577742af73b4bc60993d8d415ea580.tar.gz samba-cc6a41017c577742af73b4bc60993d8d415ea580.tar.bz2 samba-cc6a41017c577742af73b4bc60993d8d415ea580.zip |
r23997: Check in the infrastructure for getting rid of the global InBuffer/OutBuffer
The complete history of this patch can be found under
http://www.samba.org/~vlendec/inbuf-checkin/.
Jeremy, Jerry: If possible I would like to see this in 3.2.0. I'm only
checking into 3_2 at the moment, as it currently will slow down operations for
all non-converted (i.e. all at this moment) operations, as it will copy the
talloc'ed inbuf over the global InBuffer. It will need quite a bit of effort
to convert everything necessary for the normal operations an XP box does.
I have patches for negprot, session setup, tcon_and_X, open_and_X, close. More
to come, but I would appreciate some help here.
Volker
(This used to be commit 5594af2b208c860d3f4b453af6a649d9e4295d1c)
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/blocking.c | 2 | ||||
-rw-r--r-- | source3/smbd/error.c | 26 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 6 | ||||
-rw-r--r-- | source3/smbd/pipes.c | 6 | ||||
-rw-r--r-- | source3/smbd/process.c | 968 | ||||
-rw-r--r-- | source3/smbd/reply.c | 43 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 2 |
7 files changed, 658 insertions, 395 deletions
diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index ed1977e3be..09d16337cd 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -286,7 +286,7 @@ static void reply_lockingX_success(blocking_lock_record *blr) * that here and must set up the chain info manually. */ - outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); + outsize = chain_reply(inbuf,&outbuf,blr->length,bufsize); outsize += chain_size; diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 12b57d5ab4..d00c61487a 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -131,3 +131,29 @@ int error_packet(const char *inbuf, char *outbuf, uint8 eclass, uint32 ecode, NT error_packet_set(outbuf, eclass, ecode, ntstatus, line, file); return outsize; } + +void reply_nt_error(struct smb_request *req, NTSTATUS ntstatus, + int line, const char *file) +{ + TALLOC_FREE(req->outbuf); + reply_outbuf(req, 0, 0); + error_packet_set((char *)req->outbuf, 0, 0, ntstatus, line, file); +} + +void reply_dos_error(struct smb_request *req, uint8 eclass, uint32 ecode, + int line, const char *file) +{ + TALLOC_FREE(req->outbuf); + reply_outbuf(req, 0, 0); + error_packet_set((char *)req->outbuf, eclass, ecode, NT_STATUS_OK, line, + file); +} + +void reply_both_error(struct smb_request *req, uint8 eclass, uint32 ecode, + NTSTATUS status, int line, const char *file) +{ + TALLOC_FREE(req->outbuf); + reply_outbuf(req, 0, 0); + error_packet_set((char *)req->outbuf, eclass, ecode, status, + line, file); +} diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 64b6d33eee..e435e1b6fb 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -433,7 +433,7 @@ static int do_ntcreate_pipe_open(connection_struct *conn, DEBUG(5,("do_ntcreate_pipe_open: open pipe = %s\n", fname)); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -471,7 +471,7 @@ int reply_ntcreate_and_X_quota(connection_struct *conn, DEBUG(5,("reply_ntcreate_and_X_quota: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); - result = chain_reply(inbuf,outbuf,length,bufsize); + result = chain_reply(inbuf,&outbuf,length,bufsize); return result; } @@ -987,7 +987,7 @@ int reply_ntcreate_and_X(connection_struct *conn, DEBUG(5,("reply_ntcreate_and_X: fnum = %d, open name = %s\n", fsp->fnum, fsp->fsp_name)); - result = chain_reply(inbuf,outbuf,length,bufsize); + result = chain_reply(inbuf,&outbuf,length,bufsize); END_PROFILE(SMBntcreateX); return result; } diff --git a/source3/smbd/pipes.c b/source3/smbd/pipes.c index 1ea3e052b2..a6cdc3a989 100644 --- a/source3/smbd/pipes.c +++ b/source3/smbd/pipes.c @@ -126,7 +126,7 @@ int reply_open_pipe_and_X(connection_struct *conn, SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,0x0001); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -231,7 +231,7 @@ int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten)); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -278,7 +278,7 @@ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) /* Ensure we set up the message length to include the data length read. */ set_message_bcc(inbuf,outbuf,nread); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 558d403948..4a846e9708 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -23,9 +23,14 @@ extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; +const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); + static char *InBuffer = NULL; static char *OutBuffer = NULL; -static char *current_inbuf = NULL; +static const char *current_inbuf = NULL; + +static char *NewInBuffer(char **old_inbuf); +static char *NewOutBuffer(char **old_outbuf); /* * Size of data we can send to client. Set @@ -56,6 +61,10 @@ void init_smb_request(struct smb_request *req, const uint8 *inbuf) 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->inbuf = inbuf; + req->outbuf = NULL; } /**************************************************************************** @@ -70,7 +79,7 @@ static struct pending_message_list *deferred_open_queue; ready for processing. ****************************************************************************/ -static BOOL push_queued_message(char *buf, int msg_len, +static BOOL push_queued_message(const char *buf, int msg_len, struct timeval request_time, struct timeval end_time, char *private_data, size_t private_len) @@ -357,12 +366,14 @@ static int select_on_fd(int fd, int maxfd, fd_set *fds) The timeout is in milliseconds ****************************************************************************/ -static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) +static BOOL receive_message_or_smb(TALLOC_CTX *mem_ctx, char **buffer, + size_t *buffer_len, int timeout) { fd_set r_fds, w_fds; int selrtn; struct timeval to; int maxfd = 0; + ssize_t len; smb_read_error = 0; @@ -413,8 +424,16 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) } if (pop_message) { - memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length)); - + + *buffer = (char *)talloc_memdup(mem_ctx, msg->buf.data, + msg->buf.length); + if (*buffer == NULL) { + DEBUG(0, ("talloc failed\n")); + smb_read_error = READ_ERROR; + return False; + } + *buffer_len = msg->buf.length; + /* We leave this message on the queue so the open code can know this is a retry. */ DEBUG(5,("receive_message_or_smb: returning deferred open smb message.\n")); @@ -530,7 +549,15 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) goto again; } - return receive_smb(smbd_server_fd(), buffer, 0); + len = receive_smb_talloc(mem_ctx, smbd_server_fd(), buffer, 0); + + if (len == -1) { + return False; + } + + *buffer_len = (size_t)len; + + return True; } /* @@ -603,273 +630,301 @@ force write permissions on print services. static const struct smb_message_struct { const char *name; int (*fn)(connection_struct *conn, char *, char *, int, int); + void (*fn_new)(connection_struct *conn, struct smb_request *req); int flags; } smb_messages[256] = { -/* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, -/* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, -/* 0x02 */ { "SMBopen",reply_open,AS_USER }, -/* 0x03 */ { "SMBcreate",reply_mknew,AS_USER}, -/* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC }, -/* 0x05 */ { "SMBflush",reply_flush,AS_USER}, -/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE }, -/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE }, -/* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER}, -/* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, -/* 0x0a */ { "SMBread",reply_read,AS_USER}, -/* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC }, -/* 0x0c */ { "SMBlock",reply_lock,AS_USER}, -/* 0x0d */ { "SMBunlock",reply_unlock,AS_USER}, -/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER }, -/* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, -/* 0x10 */ { "SMBcheckpath",reply_checkpath,AS_USER}, -/* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR}, -/* 0x12 */ { "SMBlseek",reply_lseek,AS_USER}, -/* 0x13 */ { "SMBlockread",reply_lockread,AS_USER}, -/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,AS_USER}, -/* 0x15 */ { NULL, NULL, 0 }, -/* 0x16 */ { NULL, NULL, 0 }, -/* 0x17 */ { NULL, NULL, 0 }, -/* 0x18 */ { NULL, NULL, 0 }, -/* 0x19 */ { NULL, NULL, 0 }, -/* 0x1a */ { "SMBreadbraw",reply_readbraw,AS_USER}, -/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,AS_USER}, -/* 0x1c */ { "SMBreadBs",NULL,0 }, -/* 0x1d */ { "SMBwritebraw",reply_writebraw,AS_USER}, -/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,AS_USER}, -/* 0x1f */ { "SMBwriteBs",reply_writebs,AS_USER}, -/* 0x20 */ { "SMBwritec",NULL,0}, -/* 0x21 */ { NULL, NULL, 0 }, -/* 0x22 */ { "SMBsetattrE",reply_setattrE,AS_USER | NEED_WRITE }, -/* 0x23 */ { "SMBgetattrE",reply_getattrE,AS_USER }, -/* 0x24 */ { "SMBlockingX",reply_lockingX,AS_USER }, -/* 0x25 */ { "SMBtrans",reply_trans,AS_USER | CAN_IPC }, -/* 0x26 */ { "SMBtranss",reply_transs,AS_USER | CAN_IPC}, -/* 0x27 */ { "SMBioctl",reply_ioctl,0}, -/* 0x28 */ { "SMBioctls",NULL,AS_USER}, -/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE }, -/* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE }, -/* 0x2b */ { "SMBecho",reply_echo,0}, -/* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER}, -/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC }, -/* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, -/* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC }, -/* 0x30 */ { NULL, NULL, 0 }, -/* 0x31 */ { NULL, NULL, 0 }, -/* 0x32 */ { "SMBtrans2", reply_trans2, AS_USER | CAN_IPC }, -/* 0x33 */ { "SMBtranss2", reply_transs2, AS_USER}, -/* 0x34 */ { "SMBfindclose", reply_findclose,AS_USER}, -/* 0x35 */ { "SMBfindnclose", reply_findnclose, AS_USER}, -/* 0x36 */ { NULL, NULL, 0 }, -/* 0x37 */ { NULL, NULL, 0 }, -/* 0x38 */ { NULL, NULL, 0 }, -/* 0x39 */ { NULL, NULL, 0 }, -/* 0x3a */ { NULL, NULL, 0 }, -/* 0x3b */ { NULL, NULL, 0 }, -/* 0x3c */ { NULL, NULL, 0 }, -/* 0x3d */ { NULL, NULL, 0 }, -/* 0x3e */ { NULL, NULL, 0 }, -/* 0x3f */ { NULL, NULL, 0 }, -/* 0x40 */ { NULL, NULL, 0 }, -/* 0x41 */ { NULL, NULL, 0 }, -/* 0x42 */ { NULL, NULL, 0 }, -/* 0x43 */ { NULL, NULL, 0 }, -/* 0x44 */ { NULL, NULL, 0 }, -/* 0x45 */ { NULL, NULL, 0 }, -/* 0x46 */ { NULL, NULL, 0 }, -/* 0x47 */ { NULL, NULL, 0 }, -/* 0x48 */ { NULL, NULL, 0 }, -/* 0x49 */ { NULL, NULL, 0 }, -/* 0x4a */ { NULL, NULL, 0 }, -/* 0x4b */ { NULL, NULL, 0 }, -/* 0x4c */ { NULL, NULL, 0 }, -/* 0x4d */ { NULL, NULL, 0 }, -/* 0x4e */ { NULL, NULL, 0 }, -/* 0x4f */ { NULL, NULL, 0 }, -/* 0x50 */ { NULL, NULL, 0 }, -/* 0x51 */ { NULL, NULL, 0 }, -/* 0x52 */ { NULL, NULL, 0 }, -/* 0x53 */ { NULL, NULL, 0 }, -/* 0x54 */ { NULL, NULL, 0 }, -/* 0x55 */ { NULL, NULL, 0 }, -/* 0x56 */ { NULL, NULL, 0 }, -/* 0x57 */ { NULL, NULL, 0 }, -/* 0x58 */ { NULL, NULL, 0 }, -/* 0x59 */ { NULL, NULL, 0 }, -/* 0x5a */ { NULL, NULL, 0 }, -/* 0x5b */ { NULL, NULL, 0 }, -/* 0x5c */ { NULL, NULL, 0 }, -/* 0x5d */ { NULL, NULL, 0 }, -/* 0x5e */ { NULL, NULL, 0 }, -/* 0x5f */ { NULL, NULL, 0 }, -/* 0x60 */ { NULL, NULL, 0 }, -/* 0x61 */ { NULL, NULL, 0 }, -/* 0x62 */ { NULL, NULL, 0 }, -/* 0x63 */ { NULL, NULL, 0 }, -/* 0x64 */ { NULL, NULL, 0 }, -/* 0x65 */ { NULL, NULL, 0 }, -/* 0x66 */ { NULL, NULL, 0 }, -/* 0x67 */ { NULL, NULL, 0 }, -/* 0x68 */ { NULL, NULL, 0 }, -/* 0x69 */ { NULL, NULL, 0 }, -/* 0x6a */ { NULL, NULL, 0 }, -/* 0x6b */ { NULL, NULL, 0 }, -/* 0x6c */ { NULL, NULL, 0 }, -/* 0x6d */ { NULL, NULL, 0 }, -/* 0x6e */ { NULL, NULL, 0 }, -/* 0x6f */ { NULL, NULL, 0 }, -/* 0x70 */ { "SMBtcon",reply_tcon,0}, -/* 0x71 */ { "SMBtdis",reply_tdis,DO_CHDIR}, -/* 0x72 */ { "SMBnegprot",reply_negprot,0}, -/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,0}, -/* 0x74 */ { "SMBulogoffX", reply_ulogoffX, 0}, /* ulogoff doesn't give a valid TID */ -/* 0x75 */ { "SMBtconX",reply_tcon_and_X,0}, -/* 0x76 */ { NULL, NULL, 0 }, -/* 0x77 */ { NULL, NULL, 0 }, -/* 0x78 */ { NULL, NULL, 0 }, -/* 0x79 */ { NULL, NULL, 0 }, -/* 0x7a */ { NULL, NULL, 0 }, -/* 0x7b */ { NULL, NULL, 0 }, -/* 0x7c */ { NULL, NULL, 0 }, -/* 0x7d */ { NULL, NULL, 0 }, -/* 0x7e */ { NULL, NULL, 0 }, -/* 0x7f */ { NULL, NULL, 0 }, -/* 0x80 */ { "SMBdskattr",reply_dskattr,AS_USER}, -/* 0x81 */ { "SMBsearch",reply_search,AS_USER}, -/* 0x82 */ { "SMBffirst",reply_search,AS_USER}, -/* 0x83 */ { "SMBfunique",reply_search,AS_USER}, -/* 0x84 */ { "SMBfclose",reply_fclose,AS_USER}, -/* 0x85 */ { NULL, NULL, 0 }, -/* 0x86 */ { NULL, NULL, 0 }, -/* 0x87 */ { NULL, NULL, 0 }, -/* 0x88 */ { NULL, NULL, 0 }, -/* 0x89 */ { NULL, NULL, 0 }, -/* 0x8a */ { NULL, NULL, 0 }, -/* 0x8b */ { NULL, NULL, 0 }, -/* 0x8c */ { NULL, NULL, 0 }, -/* 0x8d */ { NULL, NULL, 0 }, -/* 0x8e */ { NULL, NULL, 0 }, -/* 0x8f */ { NULL, NULL, 0 }, -/* 0x90 */ { NULL, NULL, 0 }, -/* 0x91 */ { NULL, NULL, 0 }, -/* 0x92 */ { NULL, NULL, 0 }, -/* 0x93 */ { NULL, NULL, 0 }, -/* 0x94 */ { NULL, NULL, 0 }, -/* 0x95 */ { NULL, NULL, 0 }, -/* 0x96 */ { NULL, NULL, 0 }, -/* 0x97 */ { NULL, NULL, 0 }, -/* 0x98 */ { NULL, NULL, 0 }, -/* 0x99 */ { NULL, NULL, 0 }, -/* 0x9a */ { NULL, NULL, 0 }, -/* 0x9b */ { NULL, NULL, 0 }, -/* 0x9c */ { NULL, NULL, 0 }, -/* 0x9d */ { NULL, NULL, 0 }, -/* 0x9e */ { NULL, NULL, 0 }, -/* 0x9f */ { NULL, NULL, 0 }, -/* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC }, -/* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC }, -/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC }, -/* 0xa3 */ { NULL, NULL, 0 }, -/* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 }, -/* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE }, -/* 0xa6 */ { NULL, NULL, 0 }, -/* 0xa7 */ { NULL, NULL, 0 }, -/* 0xa8 */ { NULL, NULL, 0 }, -/* 0xa9 */ { NULL, NULL, 0 }, -/* 0xaa */ { NULL, NULL, 0 }, -/* 0xab */ { NULL, NULL, 0 }, -/* 0xac */ { NULL, NULL, 0 }, -/* 0xad */ { NULL, NULL, 0 }, -/* 0xae */ { NULL, NULL, 0 }, -/* 0xaf */ { NULL, NULL, 0 }, -/* 0xb0 */ { NULL, NULL, 0 }, -/* 0xb1 */ { NULL, NULL, 0 }, -/* 0xb2 */ { NULL, NULL, 0 }, -/* 0xb3 */ { NULL, NULL, 0 }, -/* 0xb4 */ { NULL, NULL, 0 }, -/* 0xb5 */ { NULL, NULL, 0 }, -/* 0xb6 */ { NULL, NULL, 0 }, -/* 0xb7 */ { NULL, NULL, 0 }, -/* 0xb8 */ { NULL, NULL, 0 }, -/* 0xb9 */ { NULL, NULL, 0 }, -/* 0xba */ { NULL, NULL, 0 }, -/* 0xbb */ { NULL, NULL, 0 }, -/* 0xbc */ { NULL, NULL, 0 }, -/* 0xbd */ { NULL, NULL, 0 }, -/* 0xbe */ { NULL, NULL, 0 }, -/* 0xbf */ { NULL, NULL, 0 }, -/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER}, -/* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER}, -/* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER}, -/* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER}, -/* 0xc4 */ { NULL, NULL, 0 }, -/* 0xc5 */ { NULL, NULL, 0 }, -/* 0xc6 */ { NULL, NULL, 0 }, -/* 0xc7 */ { NULL, NULL, 0 }, -/* 0xc8 */ { NULL, NULL, 0 }, -/* 0xc9 */ { NULL, NULL, 0 }, -/* 0xca */ { NULL, NULL, 0 }, -/* 0xcb */ { NULL, NULL, 0 }, -/* 0xcc */ { NULL, NULL, 0 }, -/* 0xcd */ { NULL, NULL, 0 }, -/* 0xce */ { NULL, NULL, 0 }, -/* 0xcf */ { NULL, NULL, 0 }, -/* 0xd0 */ { "SMBsends",reply_sends,AS_GUEST}, -/* 0xd1 */ { "SMBsendb",NULL,AS_GUEST}, -/* 0xd2 */ { "SMBfwdname",NULL,AS_GUEST}, -/* 0xd3 */ { "SMBcancelf",NULL,AS_GUEST}, -/* 0xd4 */ { "SMBgetmac",NULL,AS_GUEST}, -/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,AS_GUEST}, -/* 0xd6 */ { "SMBsendend",reply_sendend,AS_GUEST}, -/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,AS_GUEST}, -/* 0xd8 */ { NULL, NULL, 0 }, -/* 0xd9 */ { NULL, NULL, 0 }, -/* 0xda */ { NULL, NULL, 0 }, -/* 0xdb */ { NULL, NULL, 0 }, -/* 0xdc */ { NULL, NULL, 0 }, -/* 0xdd */ { NULL, NULL, 0 }, -/* 0xde */ { NULL, NULL, 0 }, -/* 0xdf */ { NULL, NULL, 0 }, -/* 0xe0 */ { NULL, NULL, 0 }, -/* 0xe1 */ { NULL, NULL, 0 }, -/* 0xe2 */ { NULL, NULL, 0 }, -/* 0xe3 */ { NULL, NULL, 0 }, -/* 0xe4 */ { NULL, NULL, 0 }, -/* 0xe5 */ { NULL, NULL, 0 }, -/* 0xe6 */ { NULL, NULL, 0 }, -/* 0xe7 */ { NULL, NULL, 0 }, -/* 0xe8 */ { NULL, NULL, 0 }, -/* 0xe9 */ { NULL, NULL, 0 }, -/* 0xea */ { NULL, NULL, 0 }, -/* 0xeb */ { NULL, NULL, 0 }, -/* 0xec */ { NULL, NULL, 0 }, -/* 0xed */ { NULL, NULL, 0 }, -/* 0xee */ { NULL, NULL, 0 }, -/* 0xef */ { NULL, NULL, 0 }, -/* 0xf0 */ { NULL, NULL, 0 }, -/* 0xf1 */ { NULL, NULL, 0 }, -/* 0xf2 */ { NULL, NULL, 0 }, -/* 0xf3 */ { NULL, NULL, 0 }, -/* 0xf4 */ { NULL, NULL, 0 }, -/* 0xf5 */ { NULL, NULL, 0 }, -/* 0xf6 */ { NULL, NULL, 0 }, -/* 0xf7 */ { NULL, NULL, 0 }, -/* 0xf8 */ { NULL, NULL, 0 }, -/* 0xf9 */ { NULL, NULL, 0 }, -/* 0xfa */ { NULL, NULL, 0 }, -/* 0xfb */ { NULL, NULL, 0 }, -/* 0xfc */ { NULL, NULL, 0 }, -/* 0xfd */ { NULL, NULL, 0 }, -/* 0xfe */ { NULL, NULL, 0 }, -/* 0xff */ { NULL, NULL, 0 } +/* 0x00 */ { "SMBmkdir",reply_mkdir,NULL,AS_USER | NEED_WRITE}, +/* 0x01 */ { "SMBrmdir",reply_rmdir,NULL,AS_USER | NEED_WRITE}, +/* 0x02 */ { "SMBopen",reply_open,NULL,AS_USER }, +/* 0x03 */ { "SMBcreate",reply_mknew,NULL,AS_USER}, +/* 0x04 */ { "SMBclose",reply_close,NULL,AS_USER | CAN_IPC }, +/* 0x05 */ { "SMBflush",reply_flush,NULL,AS_USER}, +/* 0x06 */ { "SMBunlink",reply_unlink,NULL,AS_USER | NEED_WRITE }, +/* 0x07 */ { "SMBmv",reply_mv,NULL,AS_USER | NEED_WRITE }, +/* 0x08 */ { "SMBgetatr",reply_getatr,NULL,AS_USER}, +/* 0x09 */ { "SMBsetatr",reply_setatr,NULL,AS_USER | NEED_WRITE}, +/* 0x0a */ { "SMBread",reply_read,NULL,AS_USER}, +/* 0x0b */ { "SMBwrite",reply_write,NULL,AS_USER | CAN_IPC }, +/* 0x0c */ { "SMBlock",reply_lock,NULL,AS_USER}, +/* 0x0d */ { "SMBunlock",reply_unlock,NULL,AS_USER}, +/* 0x0e */ { "SMBctemp",reply_ctemp,NULL,AS_USER }, +/* 0x0f */ { "SMBmknew",reply_mknew,NULL,AS_USER}, +/* 0x10 */ { "SMBcheckpath",reply_checkpath,NULL,AS_USER}, +/* 0x11 */ { "SMBexit",reply_exit,NULL,DO_CHDIR}, +/* 0x12 */ { "SMBlseek",reply_lseek,NULL,AS_USER}, +/* 0x13 */ { "SMBlockread",reply_lockread,NULL,AS_USER}, +/* 0x14 */ { "SMBwriteunlock",reply_writeunlock,NULL,AS_USER}, +/* 0x15 */ { NULL, NULL, NULL, 0 }, +/* 0x16 */ { NULL, NULL, NULL, 0 }, +/* 0x17 */ { NULL, NULL, NULL, 0 }, +/* 0x18 */ { NULL, NULL, NULL, 0 }, +/* 0x19 */ { NULL, NULL, NULL, 0 }, +/* 0x1a */ { "SMBreadbraw",reply_readbraw,NULL,AS_USER}, +/* 0x1b */ { "SMBreadBmpx",reply_readbmpx,NULL,AS_USER}, +/* 0x1c */ { "SMBreadBs",NULL, NULL,0 }, +/* 0x1d */ { "SMBwritebraw",reply_writebraw,NULL,AS_USER}, +/* 0x1e */ { "SMBwriteBmpx",reply_writebmpx,NULL,AS_USER}, +/* 0x1f */ { "SMBwriteBs",reply_writebs,NULL,AS_USER}, +/* 0x20 */ { "SMBwritec",NULL, NULL,0}, +/* 0x21 */ { NULL, NULL, NULL, 0 }, +/* 0x22 */ { "SMBsetattrE",reply_setattrE,NULL,AS_USER | NEED_WRITE }, +/* 0x23 */ { "SMBgetattrE",reply_getattrE,NULL,AS_USER }, +/* 0x24 */ { "SMBlockingX",reply_lockingX,NULL,AS_USER }, +/* 0x25 */ { "SMBtrans",reply_trans,NULL,AS_USER | CAN_IPC }, +/* 0x26 */ { "SMBtranss",reply_transs,NULL,AS_USER | CAN_IPC}, +/* 0x27 */ { "SMBioctl",reply_ioctl,NULL,0}, +/* 0x28 */ { "SMBioctls",NULL, NULL,AS_USER}, +/* 0x29 */ { "SMBcopy",reply_copy,NULL,AS_USER | NEED_WRITE }, +/* 0x2a */ { "SMBmove",NULL, NULL,AS_USER | NEED_WRITE }, +/* 0x2b */ { "SMBecho",reply_echo,NULL,0}, +/* 0x2c */ { "SMBwriteclose",reply_writeclose,NULL,AS_USER}, +/* 0x2d */ { "SMBopenX",reply_open_and_X,NULL,AS_USER | CAN_IPC }, +/* 0x2e */ { "SMBreadX",reply_read_and_X,NULL,AS_USER | CAN_IPC }, +/* 0x2f */ { "SMBwriteX",reply_write_and_X,NULL,AS_USER | CAN_IPC }, +/* 0x30 */ { NULL, NULL, NULL, 0 }, +/* 0x31 */ { NULL, NULL, NULL, 0 }, +/* 0x32 */ { "SMBtrans2", reply_trans2,NULL, AS_USER | CAN_IPC }, +/* 0x33 */ { "SMBtranss2", reply_transs2,NULL, AS_USER}, +/* 0x34 */ { "SMBfindclose", reply_findclose,NULL,AS_USER}, +/* 0x35 */ { "SMBfindnclose", reply_findnclose,NULL, AS_USER}, +/* 0x36 */ { NULL, NULL, NULL, 0 }, +/* 0x37 */ { NULL, NULL, NULL, 0 }, +/* 0x38 */ { NULL, NULL, NULL, 0 }, +/* 0x39 */ { NULL, NULL, NULL, 0 }, +/* 0x3a */ { NULL, NULL, NULL, 0 }, +/* 0x3b */ { NULL, NULL, NULL, 0 }, +/* 0x3c */ { NULL, NULL, NULL, 0 }, +/* 0x3d */ { NULL, NULL, NULL, 0 }, +/* 0x3e */ { NULL, NULL, NULL, 0 }, +/* 0x3f */ { NULL, NULL, NULL, 0 }, +/* 0x40 */ { NULL, NULL, NULL, 0 }, +/* 0x41 */ { NULL, NULL, NULL, 0 }, +/* 0x42 */ { NULL, NULL, NULL, 0 }, +/* 0x43 */ { NULL, NULL, NULL, 0 }, +/* 0x44 */ { NULL, NULL, NULL, 0 }, +/* 0x45 */ { NULL, NULL, NULL, 0 }, +/* 0x46 */ { NULL, NULL, NULL, 0 }, +/* 0x47 */ { NULL, NULL, NULL, 0 }, +/* 0x48 */ { NULL, NULL, NULL, 0 }, +/* 0x49 */ { NULL, NULL, NULL, 0 }, +/* 0x4a */ { NULL, NULL, NULL, 0 }, +/* 0x4b */ { NULL, NULL, NULL, 0 }, +/* 0x4c */ { NULL, NULL, NULL, 0 }, +/* 0x4d */ { NULL, NULL, NULL, 0 }, +/* 0x4e */ { NULL, NULL, NULL, 0 }, +/* 0x4f */ { NULL, NULL, NULL, 0 }, +/* 0x50 */ { NULL, NULL, NULL, 0 }, +/* 0x51 */ { NULL, NULL, NULL, 0 }, +/* 0x52 */ { NULL, NULL, NULL, 0 }, +/* 0x53 */ { NULL, NULL, NULL, 0 }, +/* 0x54 */ { NULL, NULL, NULL, 0 }, +/* 0x55 */ { NULL, NULL, NULL, 0 }, +/* 0x56 */ { NULL, NULL, NULL, 0 }, +/* 0x57 */ { NULL, NULL, NULL, 0 }, +/* 0x58 */ { NULL, NULL, NULL, 0 }, +/* 0x59 */ { NULL, NULL, NULL, 0 }, +/* 0x5a */ { NULL, NULL, NULL, 0 }, +/* 0x5b */ { NULL, NULL, NULL, 0 }, +/* 0x5c */ { NULL, NULL, NULL, 0 }, +/* 0x5d */ { NULL, NULL, NULL, 0 }, +/* 0x5e */ { NULL, NULL, NULL, 0 }, +/* 0x5f */ { NULL, NULL, NULL, 0 }, +/* 0x60 */ { NULL, NULL, NULL, 0 }, +/* 0x61 */ { NULL, NULL, NULL, 0 }, +/* 0x62 */ { NULL, NULL, NULL, 0 }, +/* 0x63 */ { NULL, NULL, NULL, 0 }, +/* 0x64 */ { NULL, NULL, NULL, 0 }, +/* 0x65 */ { NULL, NULL, NULL, 0 }, +/* 0x66 */ { NULL, NULL, NULL, 0 }, +/* 0x67 */ { NULL, NULL, NULL, 0 }, +/* 0x68 */ { NULL, NULL, NULL, 0 }, +/* 0x69 */ { NULL, NULL, NULL, 0 }, +/* 0x6a */ { NULL, NULL, NULL, 0 }, +/* 0x6b */ { NULL, NULL, NULL, 0 }, +/* 0x6c */ { NULL, NULL, NULL, 0 }, +/* 0x6d */ { NULL, NULL, NULL, 0 }, +/* 0x6e */ { NULL, NULL, NULL, 0 }, +/* 0x6f */ { NULL, NULL, NULL, 0 }, +/* 0x70 */ { "SMBtcon",reply_tcon,NULL,0}, +/* 0x71 */ { "SMBtdis",reply_tdis,NULL,DO_CHDIR}, +/* 0x72 */ { "SMBnegprot",reply_negprot,NULL,0}, +/* 0x73 */ { "SMBsesssetupX",reply_sesssetup_and_X,NULL,0}, +/* 0x74 */ { "SMBulogoffX", reply_ulogoffX,NULL, 0}, /* ulogoff doesn't give a valid TID */ +/* 0x75 */ { "SMBtconX",reply_tcon_and_X,NULL,0}, +/* 0x76 */ { NULL, NULL, NULL, 0 }, +/* 0x77 */ { NULL, NULL, NULL, 0 }, +/* 0x78 */ { NULL, NULL, NULL, 0 }, +/* 0x79 */ { NULL, NULL, NULL, 0 }, +/* 0x7a */ { NULL, NULL, NULL, 0 }, +/* 0x7b */ { NULL, NULL, NULL, 0 }, +/* 0x7c */ { NULL, NULL, NULL, 0 }, +/* 0x7d */ { NULL, NULL, NULL, 0 }, +/* 0x7e */ { NULL, NULL, NULL, 0 }, +/* 0x7f */ { NULL, NULL, NULL, 0 }, +/* 0x80 */ { "SMBdskattr",reply_dskattr,NULL,AS_USER}, +/* 0x81 */ { "SMBsearch",reply_search,NULL,AS_USER}, +/* 0x82 */ { "SMBffirst",reply_search,NULL,AS_USER}, +/* 0x83 */ { "SMBfunique",reply_search,NULL,AS_USER}, +/* 0x84 */ { "SMBfclose",reply_fclose,NULL,AS_USER}, +/* 0x85 */ { NULL, NULL, NULL, 0 }, +/* 0x86 */ { NULL, NULL, NULL, 0 }, +/* 0x87 */ { NULL, NULL, NULL, 0 }, +/* 0x88 */ { NULL, NULL, NULL, 0 }, +/* 0x89 */ { NULL, NULL, NULL, 0 }, +/* 0x8a */ { NULL, NULL, NULL, 0 }, +/* 0x8b */ { NULL, NULL, NULL, 0 }, +/* 0x8c */ { NULL, NULL, NULL, 0 }, +/* 0x8d */ { NULL, NULL, NULL, 0 }, +/* 0x8e */ { NULL, NULL, NULL, 0 }, +/* 0x8f */ { NULL, NULL, NULL, 0 }, +/* 0x90 */ { NULL, NULL, NULL, 0 }, +/* 0x91 */ { NULL, NULL, NULL, 0 }, +/* 0x92 */ { NULL, NULL, NULL, 0 }, +/* 0x93 */ { NULL, NULL, NULL, 0 }, +/* 0x94 */ { NULL, NULL, NULL, 0 }, +/* 0x95 */ { NULL, NULL, NULL, 0 }, +/* 0x96 */ { NULL, NULL, NULL, 0 }, +/* 0x97 */ { NULL, NULL, NULL, 0 }, +/* 0x98 */ { NULL, NULL, NULL, 0 }, +/* 0x99 */ { NULL, NULL, NULL, 0 }, +/* 0x9a */ { NULL, NULL, NULL, 0 }, +/* 0x9b */ { NULL, NULL, NULL, 0 }, +/* 0x9c */ { NULL, NULL, NULL, 0 }, +/* 0x9d */ { NULL, NULL, NULL, 0 }, +/* 0x9e */ { NULL, NULL, NULL, 0 }, +/* 0x9f */ { NULL, NULL, NULL, 0 }, +/* 0xa0 */ { "SMBnttrans", reply_nttrans,NULL, AS_USER | CAN_IPC }, +/* 0xa1 */ { "SMBnttranss", reply_nttranss,NULL, AS_USER | CAN_IPC }, +/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X,NULL, AS_USER | CAN_IPC }, +/* 0xa3 */ { NULL, NULL, NULL, 0 }, +/* 0xa4 */ { "SMBntcancel", reply_ntcancel,NULL, 0 }, +/* 0xa5 */ { "SMBntrename", reply_ntrename,NULL, AS_USER | NEED_WRITE }, +/* 0xa6 */ { NULL, NULL, NULL, 0 }, +/* 0xa7 */ { NULL, NULL, NULL, 0 }, +/* 0xa8 */ { NULL, NULL, NULL, 0 }, +/* 0xa9 */ { NULL, NULL, NULL, 0 }, +/* 0xaa */ { NULL, NULL, NULL, 0 }, +/* 0xab */ { NULL, NULL, NULL, 0 }, +/* 0xac */ { NULL, NULL, NULL, 0 }, +/* 0xad */ { NULL, NULL, NULL, 0 }, +/* 0xae */ { NULL, NULL, NULL, 0 }, +/* 0xaf */ { NULL, NULL, NULL, 0 }, +/* 0xb0 */ { NULL, NULL, NULL, 0 }, +/* 0xb1 */ { NULL, NULL, NULL, 0 }, +/* 0xb2 */ { NULL, NULL, NULL, 0 }, +/* 0xb3 */ { NULL, NULL, NULL, 0 }, +/* 0xb4 */ { NULL, NULL, NULL, 0 }, +/* 0xb5 */ { NULL, NULL, NULL, 0 }, +/* 0xb6 */ { NULL, NULL, NULL, 0 }, +/* 0xb7 */ { NULL, NULL, NULL, 0 }, +/* 0xb8 */ { NULL, NULL, NULL, 0 }, +/* 0xb9 */ { NULL, NULL, NULL, 0 }, +/* 0xba */ { NULL, NULL, NULL, 0 }, +/* 0xbb */ { NULL, NULL, NULL, 0 }, +/* 0xbc */ { NULL, NULL, NULL, 0 }, +/* 0xbd */ { NULL, NULL, NULL, 0 }, +/* 0xbe */ { NULL, NULL, NULL, 0 }, +/* 0xbf */ { NULL, NULL, NULL, 0 }, +/* 0xc0 */ { "SMBsplopen",reply_printopen,NULL,AS_USER}, +/* 0xc1 */ { "SMBsplwr",reply_printwrite,NULL,AS_USER}, +/* 0xc2 */ { "SMBsplclose",reply_printclose,NULL,AS_USER}, +/* 0xc3 */ { "SMBsplretq",reply_printqueue,NULL,AS_USER}, +/* 0xc4 */ { NULL, NULL, NULL, 0 }, +/* 0xc5 */ { NULL, NULL, NULL, 0 }, +/* 0xc6 */ { NULL, NULL, NULL, 0 }, +/* 0xc7 */ { NULL, NULL, NULL, 0 }, +/* 0xc8 */ { NULL, NULL, NULL, 0 }, +/* 0xc9 */ { NULL, NULL, NULL, 0 }, +/* 0xca */ { NULL, NULL, NULL, 0 }, +/* 0xcb */ { NULL, NULL, NULL, 0 }, +/* 0xcc */ { NULL, NULL, NULL, 0 }, +/* 0xcd */ { NULL, NULL, NULL, 0 }, +/* 0xce */ { NULL, NULL, NULL, 0 }, +/* 0xcf */ { NULL, NULL, NULL, 0 }, +/* 0xd0 */ { "SMBsends",reply_sends,NULL,AS_GUEST}, +/* 0xd1 */ { "SMBsendb",NULL, NULL,AS_GUEST}, +/* 0xd2 */ { "SMBfwdname",NULL, NULL,AS_GUEST}, +/* 0xd3 */ { "SMBcancelf",NULL, NULL,AS_GUEST}, +/* 0xd4 */ { "SMBgetmac",NULL, NULL,AS_GUEST}, +/* 0xd5 */ { "SMBsendstrt",reply_sendstrt,NULL,AS_GUEST}, +/* 0xd6 */ { "SMBsendend",reply_sendend,NULL,AS_GUEST}, +/* 0xd7 */ { "SMBsendtxt",reply_sendtxt,NULL,AS_GUEST}, +/* 0xd8 */ { NULL, NULL, NULL, 0 }, +/* 0xd9 */ { NULL, NULL, NULL, 0 }, +/* 0xda */ { NULL, NULL, NULL, 0 }, +/* 0xdb */ { NULL, NULL, NULL, 0 }, +/* 0xdc */ { NULL, NULL, NULL, 0 }, +/* 0xdd */ { NULL, NULL, NULL, 0 }, +/* 0xde */ { NULL, NULL, NULL, 0 }, +/* 0xdf */ { NULL, NULL, NULL, 0 }, +/* 0xe0 */ { NULL, NULL, NULL, 0 }, +/* 0xe1 */ { NULL, NULL, NULL, 0 }, +/* 0xe2 */ { NULL, NULL, NULL, 0 }, +/* 0xe3 */ { NULL, NULL, NULL, 0 }, +/* 0xe4 */ { NULL, NULL, NULL, 0 }, +/* 0xe5 */ { NULL, NULL, NULL, 0 }, +/* 0xe6 */ { NULL, NULL, NULL, 0 }, +/* 0xe7 */ { NULL, NULL, NULL, 0 }, +/* 0xe8 */ { NULL, NULL, NULL, 0 }, +/* 0xe9 */ { NULL, NULL, NULL, 0 }, +/* 0xea */ { NULL, NULL, NULL, 0 }, +/* 0xeb */ { NULL, NULL, NULL, 0 }, +/* 0xec */ { NULL, NULL, NULL, 0 }, +/* 0xed */ { NULL, NULL, NULL, 0 }, +/* 0xee */ { NULL, NULL, NULL, 0 }, +/* 0xef */ { NULL, NULL, NULL, 0 }, +/* 0xf0 */ { NULL, NULL, NULL, 0 }, +/* 0xf1 */ { NULL, NULL, NULL, 0 }, +/* 0xf2 */ { NULL, NULL, NULL, 0 }, +/* 0xf3 */ { NULL, NULL, NULL, 0 }, +/* 0xf4 */ { NULL, NULL, NULL, 0 }, +/* 0xf5 */ { NULL, NULL, NULL, 0 }, +/* 0xf6 */ { NULL, NULL, NULL, 0 }, +/* 0xf7 */ { NULL, NULL, NULL, 0 }, +/* 0xf8 */ { NULL, NULL, NULL, 0 }, +/* 0xf9 */ { NULL, NULL, NULL, 0 }, +/* 0xfa */ { NULL, NULL, NULL, 0 }, +/* 0xfb */ { NULL, NULL, NULL, 0 }, +/* 0xfc */ { NULL, NULL, NULL, 0 }, +/* 0xfd */ { NULL, NULL, NULL, 0 }, +/* 0xfe */ { NULL, NULL, NULL, 0 }, +/* 0xff */ { NULL, NULL, NULL, 0 } }; /******************************************************************* + allocate and initialize a reply packet +********************************************************************/ + +void reply_outbuf(struct smb_request *req, uint8 num_words, uint16 num_bytes) +{ + if (!(req->outbuf = TALLOC_ARRAY( + req, uint8, + smb_size + num_words*2 + num_bytes))) { + smb_panic("could not allocate output buffer\n"); + } + + construct_reply_common((char *)req->inbuf, (char *)req->outbuf); + set_message((char *)req->inbuf, (char *)req->outbuf, + num_words, num_bytes, False); + /* + * Zero out the word area, the caller has to take care of the bcc area + * himself + */ + if (num_words != 0) { + memset(req->outbuf + smb_vwv0, 0, num_words*2); + } + + return; +} + + +/******************************************************************* Dump a packet to a file. ********************************************************************/ -static void smb_dump(const char *name, int type, char *data, ssize_t len) +static void smb_dump(const char *name, int type, const char *data, ssize_t len) { int fd, i; pstring fname; @@ -891,37 +946,47 @@ static void smb_dump(const char *name, int type, char *data, ssize_t len) } } - /**************************************************************************** - Do a switch on the message type, and return the response size + Prepare everything for calling the actual request function, and potentially + call the request function via the "new" interface. + + Return False if the "legacy" function needs to be called, everything is + prepared. + + Return True if we're done. + + I know this API sucks, but it is the one with the least code change I could + find. ****************************************************************************/ -static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize) +static BOOL switch_message_new(uint8 type, struct smb_request *req, int size, + connection_struct **pconn) { - int outsize = 0; int flags; uint16 session_tag; connection_struct *conn; static uint16 last_session_tag = UID_FIELD_INVALID; - type &= 0xff; - errno = 0; last_message = type; - /* Make sure this is an SMB packet. smb_size contains NetBIOS header so subtract 4 from it. */ - if ((strncmp(smb_base(inbuf),"\377SMB",4) != 0) || (size < (smb_size - 4))) { - DEBUG(2,("Non-SMB packet of length %d. Terminating server\n",smb_len(inbuf))); + /* Make sure this is an SMB packet. smb_size contains NetBIOS header + * so subtract 4 from it. */ + if ((strncmp(smb_base(req->inbuf),"\377SMB",4) != 0) + || (size < (smb_size - 4))) { + DEBUG(2,("Non-SMB packet of length %d. Terminating server\n", + smb_len(req->inbuf))); exit_server_cleanly("Non-SMB packet"); - return(-1); + return True; } - if (smb_messages[type].fn == NULL) { + if ((smb_messages[type].fn == NULL) + && (smb_messages[type].fn_new == NULL)) { DEBUG(0,("Unknown message type %d!\n",type)); - smb_dump("Unknown", 1, inbuf, size); - outsize = reply_unknown(inbuf,outbuf); + smb_dump("Unknown", 1, (char *)req->inbuf, size); + reply_unknown_new(req, type); goto done; } @@ -929,16 +994,16 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* In share mode security we must ignore the vuid. */ session_tag = (lp_security() == SEC_SHARE) - ? UID_FIELD_INVALID : SVAL(inbuf,smb_uid); - conn = conn_find(SVAL(inbuf,smb_tid)); + ? UID_FIELD_INVALID : req->vuid; + conn = conn_find(req->tid); DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n", smb_fn_name(type), (int)sys_getpid(), (unsigned long)conn)); - smb_dump(smb_fn_name(type), 1, inbuf, size); + smb_dump(smb_fn_name(type), 1, (char *)req->inbuf, size); /* Ensure this value is replaced in the incoming packet. */ - SSVAL(inbuf,smb_uid,session_tag); + SSVAL(req->inbuf,smb_uid,session_tag); /* * Ensure the correct username is in current_user_info. This is a @@ -971,26 +1036,30 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize * (from Samba4). */ if (type == SMBntcreateX) { - return ERROR_NT(NT_STATUS_INVALID_HANDLE); + reply_nterror(req, NT_STATUS_INVALID_HANDLE); } else { - return ERROR_DOS(ERRSRV, ERRinvnid); + reply_doserror(req, ERRSRV, ERRinvnid); } + goto done; } if (!change_to_user(conn,session_tag)) { - return(ERROR_NT(NT_STATUS_DOS(ERRSRV,ERRbaduid))); + reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid)); + goto done; } /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */ /* Does it need write permission? */ if ((flags & NEED_WRITE) && !CAN_WRITE(conn)) { - return ERROR_NT(NT_STATUS_MEDIA_WRITE_PROTECTED); + reply_nterror(req, NT_STATUS_MEDIA_WRITE_PROTECTED); + goto done; } /* IPC services are limited */ if (IS_IPC(conn) && !(flags & CAN_IPC)) { - return(ERROR_DOS(ERRSRV,ERRaccess)); + reply_doserror(req, ERRSRV,ERRaccess); + goto done; } } else { /* This call needs to be run as root */ @@ -999,10 +1068,11 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize /* load service specific parameters */ if (conn) { - if (!set_current_service(conn,SVAL(inbuf,smb_flg), + if (!set_current_service(conn,SVAL(req->inbuf,smb_flg), (flags & (AS_USER|DO_CHDIR) ?True:False))) { - return(ERROR_DOS(ERRSRV,ERRaccess)); + reply_doserror(req, ERRSRV, ERRaccess); + goto done; } conn->num_smb_operations++; } @@ -1012,15 +1082,72 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize && (!change_to_guest() || !check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) { - return(ERROR_DOS(ERRSRV,ERRaccess)); + reply_doserror(req, ERRSRV, ERRaccess); + goto done; } - current_inbuf = inbuf; /* In case we need to defer this message in - * open... */ - outsize = smb_messages[type].fn(conn, inbuf,outbuf,size,bufsize); + current_inbuf = (char *)req->inbuf; /* In case we need to defer this + * message in open... */ + + if (smb_messages[type].fn_new != NULL) { + smb_messages[type].fn_new(conn, req); + goto done; + } + + /* + * Indicate the upper layer that there's still work. + */ + *pconn = conn; + return False; done: - smb_dump(smb_fn_name(type), 0, outbuf, outsize); + return True; +} + + +/**************************************************************************** + Do a switch on the message type, and return the response size +****************************************************************************/ + +static int switch_message(uint8 type, struct smb_request *req, char **outbuf, + int size, int bufsize) +{ + int outsize = 0; + connection_struct *conn = NULL; + + if (switch_message_new(type, req, size, &conn)) { + if (req->outbuf != NULL) { + *outbuf = (char *)req->outbuf; + return smb_len(req->outbuf)+4; + } + return -1; + } + + if (InBuffer == NULL) { + DEBUG(1, ("have to alloc InBuffer for %s\n", + smb_fn_name(type))); + if (NewInBuffer(NULL) == NULL) { + smb_panic("Could not allocate InBuffer"); + } + } + + if ((OutBuffer == NULL) && (NewOutBuffer(NULL) == NULL)) { + smb_panic("Could not allocate OutBuffer"); + } + + clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, + total_buffer_size); + + memcpy(InBuffer, req->inbuf, MIN(size, total_buffer_size)); + + construct_reply_common(InBuffer, OutBuffer); + + outsize = smb_messages[type].fn(conn, InBuffer, OutBuffer, size, + bufsize); + + smb_dump(smb_fn_name(type), 0, OutBuffer, outsize); + + *outbuf = OutBuffer; return(outsize); } @@ -1029,41 +1156,54 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize Construct a reply to the incoming packet. ****************************************************************************/ -static int construct_reply(char *inbuf,char *outbuf,int size,int bufsize) +static void construct_reply(char *inbuf, int size) { - int type = CVAL(inbuf,smb_com); + uint8 type = CVAL(inbuf,smb_com); int outsize = 0; - int msg_type = CVAL(inbuf,0); + struct smb_request *req; + char *outbuf; chain_size = 0; file_chain_reset(); reset_chain_p(); - if (msg_type != 0) - return(reply_special(inbuf,outbuf)); + if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + smb_panic("could not allocate smb_request"); + } + init_smb_request(req, (uint8 *)inbuf); - construct_reply_common(inbuf, outbuf); + outsize = switch_message(type, req, &outbuf, size, max_send); - outsize = switch_message(type,inbuf,outbuf,size,bufsize); + if (outsize > 4) { + smb_setlen(inbuf,outbuf,outsize - 4); + } - outsize += chain_size; + if (outsize > 0) { + if (CVAL(outbuf,0) == 0) + show_msg(outbuf); - if(outsize > 4) { - smb_setlen(inbuf,outbuf,outsize - 4); + if (outsize != smb_len(outbuf) + 4) { + DEBUG(0,("ERROR: Invalid message response size! " + "%d %d\n", outsize, smb_len(outbuf))); + } else if (!send_smb(smbd_server_fd(),outbuf)) { + exit_server_cleanly("construct_reply: send_smb " + "failed."); + } } - return(outsize); + + TALLOC_FREE(req); + + return; } /**************************************************************************** Process an smb from the client ****************************************************************************/ -static void process_smb(char *inbuf, char *outbuf) +static void process_smb(char *inbuf, size_t nread) { static int trans_num; int msg_type = CVAL(inbuf,0); - int32 len = smb_len(inbuf); - int nread = len + 4; DO_PROFILE_INC(smb_count); @@ -1082,27 +1222,22 @@ static void process_smb(char *inbuf, char *outbuf) } } - DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, len ) ); + DEBUG( 6, ( "got message type 0x%x of len 0x%x\n", msg_type, + smb_len(inbuf) ) ); DEBUG( 3, ( "Transaction %d of length %d\n", trans_num, nread ) ); - if (msg_type == 0) - show_msg(inbuf); - else if(msg_type == SMBkeepalive) - return; /* Keepalive packet. */ + if (msg_type != 0) { + /* + * NetBIOS session request, keepalive, etc. + */ + reply_special(inbuf); + return; + } - nread = construct_reply(inbuf,outbuf,nread,max_send); + show_msg(inbuf); + + construct_reply(inbuf,nread); - if(nread > 0) { - if (CVAL(outbuf,0) == 0) - show_msg(outbuf); - - if (nread != smb_len(outbuf) + 4) { - DEBUG(0,("ERROR: Invalid message response size! %d %d\n", - nread, smb_len(outbuf))); - } else if (!send_smb(smbd_server_fd(),outbuf)) { - exit_server_cleanly("process_smb: send_smb failed."); - } - } trans_num++; } @@ -1158,18 +1293,23 @@ void construct_reply_common(const char *inbuf, char *outbuf) Construct a chained reply and add it to the already made reply ****************************************************************************/ -int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) +int chain_reply(char *inbuf,char **poutbuf,int size,int bufsize) { static char *orig_inbuf; - static char *orig_outbuf; int smb_com1, smb_com2 = CVAL(inbuf,smb_vwv0); unsigned smb_off2 = SVAL(inbuf,smb_vwv1); - char *inbuf2, *outbuf2; + char *inbuf2; int outsize2; int new_size; char inbuf_saved[smb_wct]; - char outbuf_saved[smb_wct]; - int outsize = smb_len(outbuf) + 4; + char *outbuf = *poutbuf; + size_t outsize = smb_len(outbuf) + 4; + size_t outsize_padded; + size_t ofs, to_move; + + struct smb_request *req; + size_t caller_outputlen; + char *caller_output; /* Maybe its not chained, or it's an error packet. */ if (smb_com2 == 0xFF || SVAL(outbuf,smb_rcls) != 0) { @@ -1180,7 +1320,20 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) if (chain_size == 0) { /* this is the first part of the chain */ orig_inbuf = inbuf; - orig_outbuf = outbuf; + } + + /* + * We need to save the output the caller added to the chain so that we + * can splice it into the final output buffer later. + */ + + caller_outputlen = outsize - smb_wct; + + caller_output = (char *)memdup(outbuf + smb_wct, caller_outputlen); + + if (caller_output == NULL) { + /* TODO: NT_STATUS_NO_MEMORY */ + smb_panic("could not dup outbuf"); } /* @@ -1189,27 +1342,25 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) * 4 byte aligned. JRA. */ - outsize = (outsize + 3) & ~3; + outsize_padded = (outsize + 3) & ~3; - /* we need to tell the client where the next part of the reply will be */ - SSVAL(outbuf,smb_vwv1,smb_offset(outbuf+outsize,outbuf)); - SCVAL(outbuf,smb_vwv0,smb_com2); - - /* remember how much the caller added to the chain, only counting stuff - after the parameter words */ - chain_size += outsize - smb_wct; + /* + * remember how much the caller added to the chain, only counting + * stuff after the parameter words + */ + chain_size += outsize_padded - smb_wct; - /* work out pointers into the original packets. The - headers on these need to be filled in */ + /* + * work out pointers into the original packets. The + * headers on these need to be filled in + */ inbuf2 = orig_inbuf + smb_off2 + 4 - smb_wct; - outbuf2 = orig_outbuf + SVAL(outbuf,smb_vwv1) + 4 - smb_wct; /* remember the original command type */ smb_com1 = CVAL(orig_inbuf,smb_com); /* save the data which will be overwritten by the new headers */ memcpy(inbuf_saved,inbuf2,smb_wct); - memcpy(outbuf_saved,outbuf2,smb_wct); /* give the new packet the same header as the last part of the SMB */ memmove(inbuf2,inbuf,smb_wct); @@ -1230,34 +1381,112 @@ int chain_reply(char *inbuf,char *outbuf,int size,int bufsize) /* And set it in the header. */ smb_setlen(inbuf, inbuf2, new_size); - /* create the out buffer */ - construct_reply_common(inbuf2, outbuf2); - DEBUG(3,("Chained message\n")); show_msg(inbuf2); + if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + smb_panic("could not allocate smb_request"); + } + init_smb_request(req, (uint8 *)inbuf2); + /* process the request */ - outsize2 = switch_message(smb_com2,inbuf2,outbuf2,new_size, - bufsize-chain_size); + outsize2 = switch_message(smb_com2, req, &outbuf, new_size, + bufsize-chain_size); - /* copy the new reply and request headers over the old ones, but - preserve the smb_com field */ - memmove(orig_outbuf,outbuf2,smb_wct); - SCVAL(orig_outbuf,smb_com,smb_com1); + /* + * We don't accept deferred operations in chained requests. + */ + SMB_ASSERT(outsize2 >= smb_wct); - /* restore the saved data, being careful not to overwrite any - data from the reply header */ - memcpy(inbuf2,inbuf_saved,smb_wct); + /* + * Move away the new command output so that caller_output fits in, + * copy in the caller_output saved above. + */ - { - int ofs = smb_wct - PTR_DIFF(outbuf2,orig_outbuf); - if (ofs < 0) { - ofs = 0; + SMB_ASSERT(outsize_padded >= smb_wct); + + /* + * "ofs" is the space we need for caller_output. Equal to + * caller_outputlen plus the padding. + */ + + ofs = outsize_padded - smb_wct; + + /* + * "to_move" is the amount of bytes the secondary routine gave us + */ + + to_move = outsize2 - smb_wct; + + if (to_move + ofs + smb_wct + chain_size > max_send) { + smb_panic("replies too large -- would have to cut"); + } + + /* + * In the "new" API "outbuf" is allocated via reply_outbuf, just for + * the first request in the chain. So we have to re-allocate it. In + * the "old" API the only outbuf ever used is the global OutBuffer + * which is always large enough. + */ + + if (outbuf != OutBuffer) { + outbuf = TALLOC_REALLOC_ARRAY(NULL, outbuf, char, + to_move + ofs + smb_wct); + if (outbuf == NULL) { + smb_panic("could not realloc outbuf"); } - memmove(outbuf2+ofs,outbuf_saved+ofs,smb_wct-ofs); } - return outsize2; + *poutbuf = outbuf; + + memmove(outbuf + smb_wct + ofs, outbuf + smb_wct, to_move); + memcpy(outbuf + smb_wct, caller_output, caller_outputlen); + + /* + * The secondary function has overwritten smb_com + */ + + SCVAL(outbuf, smb_com, smb_com1); + + /* + * We've just copied in the whole "wct" area from the secondary + * function. Fix up the chaining: com2 and the offset need to be + * readjusted. + */ + + SCVAL(outbuf, smb_vwv0, smb_com2); + SSVAL(outbuf, smb_vwv1, chain_size + smb_wct - 4); + + if (outsize_padded > outsize) { + + /* + * Due to padding we have some uninitialized bytes after the + * caller's output + */ + + memset(outbuf + outsize, 0, outsize_padded - outsize); + } + + smb_setlen(NULL, outbuf, outsize2 + chain_size - 4); + + /* + * restore the saved data, being careful not to overwrite any data + * from the reply header + */ + memcpy(inbuf2,inbuf_saved,smb_wct); + + SAFE_FREE(caller_output); + TALLOC_FREE(req); + + return outsize2 + chain_size; +} + +void chain_reply_new(struct smb_request *req) +{ + chain_reply(CONST_DISCARD(char *, req->inbuf), + (char **)(void *)&req->outbuf, + smb_len(req->inbuf)+4, + smb_len(req->outbuf)+4); } /**************************************************************************** @@ -1450,8 +1679,6 @@ char *get_OutBuffer(void) return OutBuffer; } -const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); - /**************************************************************************** Allocate a new InBuffer. Returns the new and old ones. ****************************************************************************/ @@ -1501,16 +1728,13 @@ void smbd_process(void) time_t last_timeout_processing_time = time(NULL); unsigned int num_smbs = 0; - /* Allocate the primary Inbut/Output buffers. */ - - if ((NewInBuffer(NULL) == NULL) || (NewOutBuffer(NULL) == NULL)) - return; - max_recv = MIN(lp_maxxmit(),BUFFER_SIZE); while (True) { int select_timeout = setup_select_timeout(); int num_echos; + char *inbuf; + size_t inbuf_len; errno = 0; @@ -1528,17 +1752,15 @@ void smbd_process(void) run_events(smbd_event_context(), 0, NULL, NULL); -#if defined(DEVELOPER) - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); -#endif - - while (!receive_message_or_smb(InBuffer,BUFFER_SIZE+LARGE_WRITEX_HDR_SIZE,select_timeout)) { + while (!receive_message_or_smb(NULL, &inbuf, &inbuf_len, + select_timeout)) { if(!timeout_processing(&select_timeout, &last_timeout_processing_time)) return; num_smbs = 0; /* Reset smb counter. */ } + /* * Ensure we do timeout processing if the SMB we just got was * only an echo request. This allows us to set the select @@ -1550,9 +1772,9 @@ void smbd_process(void) */ num_echos = smb_echo_count; - clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, OutBuffer, total_buffer_size); + process_smb(inbuf, inbuf_len); - process_smb(InBuffer, OutBuffer); + TALLOC_FREE(inbuf); if (smb_echo_count != num_echos) { if(!timeout_processing( &select_timeout, &last_timeout_processing_time)) diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index f8d3bb8c48..00e2bf5984 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -284,22 +284,28 @@ size_t srvstr_get_path(const char *inbuf, uint16 smb_flags2, char *dest, } /**************************************************************************** - Reply to a special message. + Reply to a (netbios-level) special message. ****************************************************************************/ -int reply_special(char *inbuf,char *outbuf) +void reply_special(char *inbuf) { - int outsize = 4; int msg_type = CVAL(inbuf,0); int msg_flags = CVAL(inbuf,1); fstring name1,name2; char name_type = 0; + + /* + * We only really use 4 bytes of the outbuf, but for the smb_setlen + * calculation & friends (send_smb uses that) we need the full smb + * header. + */ + char outbuf[smb_size]; static BOOL already_got_session = False; *name1 = *name2 = 0; - memset(outbuf,'\0',smb_size); + memset(outbuf, '\0', sizeof(outbuf)); smb_setlen(inbuf,outbuf,0); @@ -315,7 +321,7 @@ int reply_special(char *inbuf,char *outbuf) if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) { DEBUG(0,("Invalid name length in session request\n")); - return(0); + return; } name_extract(inbuf,4,name1); name_type = name_extract(inbuf,4 + name_len(inbuf + 4),name2); @@ -363,13 +369,14 @@ int reply_special(char *inbuf,char *outbuf) case SMBkeepalive: /* session keepalive */ default: - return(0); + return; } DEBUG(5,("init msg_type=0x%x msg_flags=0x%x\n", msg_type, msg_flags)); - - return(outsize); + + send_smb(smbd_server_fd(), outbuf); + return; } /**************************************************************************** @@ -613,7 +620,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt TALLOC_FREE(ctx); END_PROFILE(SMBtconX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -631,6 +638,14 @@ int reply_unknown(char *inbuf,char *outbuf) return(ERROR_DOS(ERRSRV,ERRunknownsmb)); } +void reply_unknown_new(struct smb_request *req, uint8 type) +{ + DEBUG(0, ("unknown command type (%s): type=%d (0x%X)\n", + smb_fn_name(type), type, type)); + reply_doserror(req, ERRSRV, ERRunknownsmb); + return; +} + /**************************************************************************** Reply to an ioctl. conn POINTER CAN BE NULL HERE ! @@ -1582,7 +1597,7 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt } END_PROFILE(SMBopenX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -1611,7 +1626,7 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length, DEBUG( 3, ( "ulogoffX vuid=%d\n", vuid ) ); END_PROFILE(SMBulogoffX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -2813,7 +2828,7 @@ int reply_read_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt nread = send_file_readX(conn, inbuf, outbuf, length, bufsize, fsp, startpos, smb_maxcnt); /* Only call chain_reply if not an error. */ if (nread != -1 && SVAL(outbuf,smb_rcls) == 0) { - nread = chain_reply(inbuf,outbuf,length,bufsize); + nread = chain_reply(inbuf,&outbuf,length,bufsize); } END_PROFILE(SMBreadX); @@ -3254,7 +3269,7 @@ int reply_write_and_X(connection_struct *conn, char *inbuf,char *outbuf,int leng } END_PROFILE(SMBwriteX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } /**************************************************************************** @@ -5722,7 +5737,7 @@ int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks)); END_PROFILE(SMBlockingX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } #undef DBGC_CLASS diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index 320d283575..eb0d7b3e12 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -1582,5 +1582,5 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, done_sesssetup = True; END_PROFILE(SMBsesssetupX); - return chain_reply(inbuf,outbuf,length,bufsize); + return chain_reply(inbuf,&outbuf,length,bufsize); } |