diff options
Diffstat (limited to 'source4/smb_server')
-rw-r--r-- | source4/smb_server/blob.c | 7 | ||||
-rw-r--r-- | source4/smb_server/config.mk | 24 | ||||
-rw-r--r-- | source4/smb_server/smb/config.mk | 16 | ||||
-rw-r--r-- | source4/smb_server/smb/receive.c | 230 | ||||
-rw-r--r-- | source4/smb_server/smb/request.c | 6 | ||||
-rw-r--r-- | source4/smb_server/smb/sesssetup.c | 5 | ||||
-rw-r--r-- | source4/smb_server/smb2/config.mk | 16 | ||||
-rw-r--r-- | source4/smb_server/smb2/fileio.c | 79 | ||||
-rw-r--r-- | source4/smb_server/smb2/find.c | 4 | ||||
-rw-r--r-- | source4/smb_server/smb2/negprot.c | 9 | ||||
-rw-r--r-- | source4/smb_server/smb2/smb2_server.h | 6 | ||||
-rw-r--r-- | source4/smb_server/smb_server.c | 3 |
12 files changed, 239 insertions, 166 deletions
diff --git a/source4/smb_server/blob.c b/source4/smb_server/blob.c index 8834c4483c..368b81d18e 100644 --- a/source4/smb_server/blob.c +++ b/source4/smb_server/blob.c @@ -476,12 +476,12 @@ NTSTATUS smbsrv_push_passthru_fileinfo(TALLOC_CTX *mem_ctx, } list_size = ea_list_size_chained(st->all_eas.out.num_eas, - st->all_eas.out.eas); + st->all_eas.out.eas, 4); BLOB_CHECK(smbsrv_blob_grow_data(mem_ctx, blob, list_size)); ea_put_list_chained(blob->data, st->all_eas.out.num_eas, - st->all_eas.out.eas); + st->all_eas.out.eas, 4); return NT_STATUS_OK; case RAW_FILEINFO_SMB2_ALL_INFORMATION: @@ -503,7 +503,8 @@ NTSTATUS smbsrv_push_passthru_fileinfo(TALLOC_CTX *mem_ctx, SIVAL(blob->data, 0x48, st->all_info2.out.ea_size); SIVAL(blob->data, 0x4C, st->all_info2.out.access_mask); SBVAL(blob->data, 0x50, st->all_info2.out.position); - SBVAL(blob->data, 0x58, st->all_info2.out.mode); + SIVAL(blob->data, 0x58, st->all_info2.out.mode); + SIVAL(blob->data, 0x5C, st->all_info2.out.alignment_requirement); BLOB_CHECK(smbsrv_blob_append_string(mem_ctx, blob, st->all_info2.out.fname.s, 0x60, default_str_flags, diff --git a/source4/smb_server/config.mk b/source4/smb_server/config.mk index 85c969df59..e11968a100 100644 --- a/source4/smb_server/config.mk +++ b/source4/smb_server/config.mk @@ -2,21 +2,16 @@ # [MODULE::SERVICE_SMB] INIT_FUNCTION = server_service_smb_init -SUBSYSTEM = service -OBJ_FILES = smb_server.o -PRIVATE_PROTO_HEADER = service_smb_proto.h +SUBSYSTEM = smbd PRIVATE_DEPENDENCIES = SMB_SERVER +SERVICE_SMB_OBJ_FILES = $(smb_serversrcdir)/smb_server.o + +$(eval $(call proto_header_template,$(smb_serversrcdir)/service_smb_proto.h,$(SERVICE_SMB_OBJ_FILES:.o=.c))) + ####################### # Start SUBSYSTEM SMB [SUBSYSTEM::SMB_SERVER] -OBJ_FILES = \ - handle.o \ - tcon.o \ - session.o \ - blob.o \ - management.o -PRIVATE_PROTO_HEADER = smb_server_proto.h PUBLIC_DEPENDENCIES = \ share \ LIBPACKET \ @@ -25,5 +20,14 @@ PUBLIC_DEPENDENCIES = \ # End SUBSYSTEM SMB ####################### +SMB_SERVER_OBJ_FILES = $(addprefix $(smb_serversrcdir)/, \ + handle.o \ + tcon.o \ + session.o \ + blob.o \ + management.o) + +$(eval $(call proto_header_template,$(smb_serversrcdir)/smb_server_proto.h,$(SMB_SERVER_OBJ_FILES:.o=.c))) + mkinclude smb/config.mk mkinclude smb2/config.mk diff --git a/source4/smb_server/smb/config.mk b/source4/smb_server/smb/config.mk index 7927f295b9..9adf334850 100644 --- a/source4/smb_server/smb/config.mk +++ b/source4/smb_server/smb/config.mk @@ -1,8 +1,12 @@ ####################### # Start SUBSYSTEM SMB_PROTOCOL [SUBSYSTEM::SMB_PROTOCOL] -PRIVATE_PROTO_HEADER = smb_proto.h -OBJ_FILES = \ +PUBLIC_DEPENDENCIES = \ + ntvfs LIBPACKET CREDENTIALS +# End SUBSYSTEM SMB_PROTOCOL +####################### + +SMB_PROTOCOL_OBJ_FILES = $(addprefix $(smb_serversrcdir)/smb/, \ receive.o \ negprot.o \ nttrans.o \ @@ -13,8 +17,6 @@ OBJ_FILES = \ sesssetup.o \ srvtime.o \ trans2.o \ - signing.o -PUBLIC_DEPENDENCIES = \ - ntvfs LIBPACKET CREDENTIALS -# End SUBSYSTEM SMB_PROTOCOL -####################### + signing.o) + +$(eval $(call proto_header_template,$(smb_serversrcdir)/smb/smb_proto.h,$(SMB_PROTOCOL_OBJ_FILES:.o=.c))) diff --git a/source4/smb_server/smb/receive.c b/source4/smb_server/smb/receive.c index e3d247cbc0..0afa3a652d 100644 --- a/source4/smb_server/smb/receive.c +++ b/source4/smb_server/smb/receive.c @@ -65,111 +65,16 @@ NTSTATUS smbsrv_send_oplock_break(void *p, struct ntvfs_handle *ntvfs, uint8_t l static void switch_message(int type, struct smbsrv_request *req); -/**************************************************************************** -receive a SMB request header from the wire, forming a request_context -from the result -****************************************************************************/ -NTSTATUS smbsrv_recv_smb_request(void *private, DATA_BLOB blob) -{ - struct smbsrv_connection *smb_conn = talloc_get_type(private, struct smbsrv_connection); - struct smbsrv_request *req; - struct timeval cur_time = timeval_current(); - uint8_t command; - - smb_conn->statistics.last_request_time = cur_time; - - /* see if its a special NBT packet */ - if (CVAL(blob.data, 0) != 0) { - req = smbsrv_init_request(smb_conn); - NT_STATUS_HAVE_NO_MEMORY(req); - - ZERO_STRUCT(req->in); - - req->in.buffer = talloc_steal(req, blob.data); - req->in.size = blob.length; - req->request_time = cur_time; - - smbsrv_reply_special(req); - return NT_STATUS_OK; - } - - if ((NBT_HDR_SIZE + MIN_SMB_SIZE) > blob.length) { - DEBUG(2,("Invalid SMB packet: length %ld\n", (long)blob.length)); - smbsrv_terminate_connection(smb_conn, "Invalid SMB packet"); - return NT_STATUS_OK; - } - - /* Make sure this is an SMB packet */ - if (IVAL(blob.data, NBT_HDR_SIZE) != SMB_MAGIC) { - DEBUG(2,("Non-SMB packet of length %ld. Terminating connection\n", - (long)blob.length)); - smbsrv_terminate_connection(smb_conn, "Non-SMB packet"); - return NT_STATUS_OK; - } - - req = smbsrv_init_request(smb_conn); - NT_STATUS_HAVE_NO_MEMORY(req); - - req->in.buffer = talloc_steal(req, blob.data); - req->in.size = blob.length; - req->request_time = cur_time; - req->chained_fnum = -1; - req->in.allocated = req->in.size; - req->in.hdr = req->in.buffer + NBT_HDR_SIZE; - req->in.vwv = req->in.hdr + HDR_VWV; - req->in.wct = CVAL(req->in.hdr, HDR_WCT); - if (req->in.vwv + VWV(req->in.wct) <= req->in.buffer + req->in.size) { - req->in.data = req->in.vwv + VWV(req->in.wct) + 2; - req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct)); - - /* the bcc length is only 16 bits, but some packets - (such as SMBwriteX) can be much larger than 64k. We - detect this by looking for a large non-chained NBT - packet (at least 64k bigger than what is - specified). If it is detected then the NBT size is - used instead of the bcc size */ - if (req->in.data_size + 0x10000 <= - req->in.size - PTR_DIFF(req->in.data, req->in.buffer) && - (req->in.wct < 1 || SVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE)) { - /* its an oversized packet! fun for all the family */ - req->in.data_size = req->in.size - PTR_DIFF(req->in.data,req->in.buffer); - } - } - - if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct > req->in.size) { - DEBUG(2,("Invalid SMB word count %d\n", req->in.wct)); - smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet"); - return NT_STATUS_OK; - } - - if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct + req->in.data_size > req->in.size) { - DEBUG(2,("Invalid SMB buffer length count %d\n", - (int)req->in.data_size)); - smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet"); - return NT_STATUS_OK; - } - - req->flags2 = SVAL(req->in.hdr, HDR_FLG2); - - /* fix the bufinfo */ - smbsrv_setup_bufinfo(req); - - if (!smbsrv_signing_check_incoming(req)) { - smbsrv_send_error(req, NT_STATUS_ACCESS_DENIED); - return NT_STATUS_OK; - } - - command = CVAL(req->in.hdr, HDR_COM); - switch_message(command, req); - return NT_STATUS_OK; -} - /* These flags determine some of the permissions required to do an operation */ #define NEED_SESS (1<<0) #define NEED_TCON (1<<1) #define SIGNING_NO_REPLY (1<<2) +/* does VWV(0) of the request hold chaining information */ +#define AND_X (1<<3) +/* The 64Kb question: are requests > 64K valid? */ +#define LARGE_REQUEST (1<<4) /* define a list of possible SMB messages and their corresponding @@ -180,6 +85,7 @@ static const struct smb_message_struct { const char *name; void (*fn)(struct smbsrv_request *); +#define message_flags(type) smb_messages[(type) & 0xff].flags int flags; } smb_messages[256] = { @@ -219,7 +125,7 @@ static const struct smb_message_struct /* 0x21 */ { NULL, NULL, 0 }, /* 0x22 */ { "SMBsetattrE", smbsrv_reply_setattrE, NEED_SESS|NEED_TCON }, /* 0x23 */ { "SMBgetattrE", smbsrv_reply_getattrE, NEED_SESS|NEED_TCON }, -/* 0x24 */ { "SMBlockingX", smbsrv_reply_lockingX, NEED_SESS|NEED_TCON }, +/* 0x24 */ { "SMBlockingX", smbsrv_reply_lockingX, NEED_SESS|NEED_TCON|AND_X }, /* 0x25 */ { "SMBtrans", smbsrv_reply_trans, NEED_SESS|NEED_TCON }, /* 0x26 */ { "SMBtranss", smbsrv_reply_transs, NEED_SESS|NEED_TCON }, /* 0x27 */ { "SMBioctl", smbsrv_reply_ioctl, NEED_SESS|NEED_TCON }, @@ -228,9 +134,9 @@ static const struct smb_message_struct /* 0x2a */ { "SMBmove", NULL, NEED_SESS|NEED_TCON }, /* 0x2b */ { "SMBecho", smbsrv_reply_echo, 0 }, /* 0x2c */ { "SMBwriteclose", smbsrv_reply_writeclose, NEED_SESS|NEED_TCON }, -/* 0x2d */ { "SMBopenX", smbsrv_reply_open_and_X, NEED_SESS|NEED_TCON }, -/* 0x2e */ { "SMBreadX", smbsrv_reply_read_and_X, NEED_SESS|NEED_TCON }, -/* 0x2f */ { "SMBwriteX", smbsrv_reply_write_and_X, NEED_SESS|NEED_TCON}, +/* 0x2d */ { "SMBopenX", smbsrv_reply_open_and_X, NEED_SESS|NEED_TCON|AND_X }, +/* 0x2e */ { "SMBreadX", smbsrv_reply_read_and_X, NEED_SESS|NEED_TCON|AND_X }, +/* 0x2f */ { "SMBwriteX", smbsrv_reply_write_and_X, NEED_SESS|NEED_TCON|AND_X|LARGE_REQUEST}, /* 0x30 */ { NULL, NULL, 0 }, /* 0x31 */ { NULL, NULL, 0 }, /* 0x32 */ { "SMBtrans2", smbsrv_reply_trans2, NEED_SESS|NEED_TCON }, @@ -298,9 +204,9 @@ static const struct smb_message_struct /* 0x70 */ { "SMBtcon", smbsrv_reply_tcon, NEED_SESS }, /* 0x71 */ { "SMBtdis", smbsrv_reply_tdis, NEED_TCON }, /* 0x72 */ { "SMBnegprot", smbsrv_reply_negprot, 0 }, -/* 0x73 */ { "SMBsesssetupX", smbsrv_reply_sesssetup, 0 }, -/* 0x74 */ { "SMBulogoffX", smbsrv_reply_ulogoffX, NEED_SESS }, /* ulogoff doesn't give a valid TID */ -/* 0x75 */ { "SMBtconX", smbsrv_reply_tcon_and_X, NEED_SESS }, +/* 0x73 */ { "SMBsesssetupX", smbsrv_reply_sesssetup, AND_X }, +/* 0x74 */ { "SMBulogoffX", smbsrv_reply_ulogoffX, NEED_SESS|AND_X }, /* ulogoff doesn't give a valid TID */ +/* 0x75 */ { "SMBtconX", smbsrv_reply_tcon_and_X, NEED_SESS|AND_X }, /* 0x76 */ { NULL, NULL, 0 }, /* 0x77 */ { NULL, NULL, 0 }, /* 0x78 */ { NULL, NULL, 0 }, @@ -343,9 +249,9 @@ static const struct smb_message_struct /* 0x9d */ { NULL, NULL, 0 }, /* 0x9e */ { NULL, NULL, 0 }, /* 0x9f */ { NULL, NULL, 0 }, -/* 0xa0 */ { "SMBnttrans", smbsrv_reply_nttrans, NEED_SESS|NEED_TCON }, +/* 0xa0 */ { "SMBnttrans", smbsrv_reply_nttrans, NEED_SESS|NEED_TCON|LARGE_REQUEST }, /* 0xa1 */ { "SMBnttranss", smbsrv_reply_nttranss, NEED_SESS|NEED_TCON }, -/* 0xa2 */ { "SMBntcreateX", smbsrv_reply_ntcreate_and_X, NEED_SESS|NEED_TCON }, +/* 0xa2 */ { "SMBntcreateX", smbsrv_reply_ntcreate_and_X, NEED_SESS|NEED_TCON|AND_X }, /* 0xa3 */ { NULL, NULL, 0 }, /* 0xa4 */ { "SMBntcancel", smbsrv_reply_ntcancel, NEED_SESS|NEED_TCON|SIGNING_NO_REPLY }, /* 0xa5 */ { "SMBntrename", smbsrv_reply_ntrename, NEED_SESS|NEED_TCON }, @@ -442,6 +348,111 @@ static const struct smb_message_struct }; /**************************************************************************** +receive a SMB request header from the wire, forming a request_context +from the result +****************************************************************************/ +NTSTATUS smbsrv_recv_smb_request(void *private, DATA_BLOB blob) +{ + struct smbsrv_connection *smb_conn = talloc_get_type(private, struct smbsrv_connection); + struct smbsrv_request *req; + struct timeval cur_time = timeval_current(); + uint8_t command; + + smb_conn->statistics.last_request_time = cur_time; + + /* see if its a special NBT packet */ + if (CVAL(blob.data, 0) != 0) { + req = smbsrv_init_request(smb_conn); + NT_STATUS_HAVE_NO_MEMORY(req); + + ZERO_STRUCT(req->in); + + req->in.buffer = talloc_steal(req, blob.data); + req->in.size = blob.length; + req->request_time = cur_time; + + smbsrv_reply_special(req); + return NT_STATUS_OK; + } + + if ((NBT_HDR_SIZE + MIN_SMB_SIZE) > blob.length) { + DEBUG(2,("Invalid SMB packet: length %ld\n", (long)blob.length)); + smbsrv_terminate_connection(smb_conn, "Invalid SMB packet"); + return NT_STATUS_OK; + } + + /* Make sure this is an SMB packet */ + if (IVAL(blob.data, NBT_HDR_SIZE) != SMB_MAGIC) { + DEBUG(2,("Non-SMB packet of length %ld. Terminating connection\n", + (long)blob.length)); + smbsrv_terminate_connection(smb_conn, "Non-SMB packet"); + return NT_STATUS_OK; + } + + req = smbsrv_init_request(smb_conn); + NT_STATUS_HAVE_NO_MEMORY(req); + + req->in.buffer = talloc_steal(req, blob.data); + req->in.size = blob.length; + req->request_time = cur_time; + req->chained_fnum = -1; + req->in.allocated = req->in.size; + req->in.hdr = req->in.buffer + NBT_HDR_SIZE; + req->in.vwv = req->in.hdr + HDR_VWV; + req->in.wct = CVAL(req->in.hdr, HDR_WCT); + + command = CVAL(req->in.hdr, HDR_COM); + + if (req->in.vwv + VWV(req->in.wct) <= req->in.buffer + req->in.size) { + req->in.data = req->in.vwv + VWV(req->in.wct) + 2; + req->in.data_size = SVAL(req->in.vwv, VWV(req->in.wct)); + + /* the bcc length is only 16 bits, but some packets + (such as SMBwriteX) can be much larger than 64k. We + detect this by looking for a large non-chained NBT + packet (at least 64k bigger than what is + specified). If it is detected then the NBT size is + used instead of the bcc size */ + if (req->in.data_size + 0x10000 <= + req->in.size - PTR_DIFF(req->in.data, req->in.buffer) && + ( message_flags(command) & LARGE_REQUEST) && + ( !(message_flags(command) & AND_X) || + (req->in.wct < 1 || SVAL(req->in.vwv, VWV(0)) == SMB_CHAIN_NONE) ) + ) { + /* its an oversized packet! fun for all the family */ + req->in.data_size = req->in.size - PTR_DIFF(req->in.data,req->in.buffer); + } + } + + if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct > req->in.size) { + DEBUG(2,("Invalid SMB word count %d\n", req->in.wct)); + smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet"); + return NT_STATUS_OK; + } + + if (NBT_HDR_SIZE + MIN_SMB_SIZE + 2*req->in.wct + req->in.data_size > req->in.size) { + DEBUG(2,("Invalid SMB buffer length count %d\n", + (int)req->in.data_size)); + smbsrv_terminate_connection(req->smb_conn, "Invalid SMB packet"); + return NT_STATUS_OK; + } + + req->flags2 = SVAL(req->in.hdr, HDR_FLG2); + + /* fix the bufinfo */ + smbsrv_setup_bufinfo(req); + + if (!smbsrv_signing_check_incoming(req)) { + smbsrv_send_error(req, NT_STATUS_ACCESS_DENIED); + return NT_STATUS_OK; + } + + command = CVAL(req->in.hdr, HDR_COM); + switch_message(command, req); + return NT_STATUS_OK; +} + +/**************************************************************************** return a string containing the function name of a SMB command ****************************************************************************/ static const char *smb_fn_name(uint8_t type) @@ -497,7 +508,8 @@ static void switch_message(int type, struct smbsrv_request *req) } } - DEBUG(5,("switch message %s (task_id %d)\n",smb_fn_name(type), req->smb_conn->connection->server_id.id)); + DEBUG(5,("switch message %s (task_id %u)\n", + smb_fn_name(type), (unsigned)req->smb_conn->connection->server_id.id)); /* this must be called before we do any reply */ if (flags & SIGNING_NO_REPLY) { diff --git a/source4/smb_server/smb/request.c b/source4/smb_server/smb/request.c index 87073517dd..c7fa2d7d8a 100644 --- a/source4/smb_server/smb/request.c +++ b/source4/smb_server/smb/request.c @@ -651,10 +651,10 @@ bool req_data_oob(struct request_bufinfo *bufinfo, const uint8_t *ptr, uint32_t } /* be careful with wraparound! */ - if (ptr < bufinfo->data || - ptr >= bufinfo->data + bufinfo->data_size || + if ((uintptr_t)ptr < (uintptr_t)bufinfo->data || + (uintptr_t)ptr >= (uintptr_t)bufinfo->data + bufinfo->data_size || count > bufinfo->data_size || - ptr + count > bufinfo->data + bufinfo->data_size) { + (uintptr_t)ptr + count > (uintptr_t)bufinfo->data + bufinfo->data_size) { return true; } return false; diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c index de2141b808..2c4068bda5 100644 --- a/source4/smb_server/smb/sesssetup.c +++ b/source4/smb_server/smb/sesssetup.c @@ -70,7 +70,7 @@ static void sesssetup_old_send(struct auth_check_password_request *areq, if (!NT_STATUS_IS_OK(status)) goto failed; /* This references server_info into session_info */ - status = auth_generate_session_info(req, req->smb_conn->lp_ctx, + status = auth_generate_session_info(req, req->smb_conn->connection->event.ctx, req->smb_conn->lp_ctx, server_info, &session_info); if (!NT_STATUS_IS_OK(status)) goto failed; @@ -166,7 +166,8 @@ static void sesssetup_nt1_send(struct auth_check_password_request *areq, if (!NT_STATUS_IS_OK(status)) goto failed; /* This references server_info into session_info */ - status = auth_generate_session_info(req, req->smb_conn->lp_ctx, + status = auth_generate_session_info(req, req->smb_conn->connection->event.ctx, + req->smb_conn->lp_ctx, server_info, &session_info); if (!NT_STATUS_IS_OK(status)) goto failed; diff --git a/source4/smb_server/smb2/config.mk b/source4/smb_server/smb2/config.mk index d5ba43b3a8..68ee6e58f6 100644 --- a/source4/smb_server/smb2/config.mk +++ b/source4/smb_server/smb2/config.mk @@ -1,8 +1,12 @@ ####################### # Start SUBSYSTEM SMB2_PROTOCOL [SUBSYSTEM::SMB2_PROTOCOL] -PRIVATE_PROTO_HEADER = smb2_proto.h -OBJ_FILES = \ +PUBLIC_DEPENDENCIES = \ + ntvfs LIBPACKET LIBCLI_SMB2 +# End SUBSYSTEM SMB2_PROTOCOL +####################### + +SMB2_PROTOCOL_OBJ_FILES = $(addprefix $(smb_serversrcdir)/smb2/, \ receive.o \ negprot.o \ sesssetup.o \ @@ -10,8 +14,6 @@ OBJ_FILES = \ fileio.o \ fileinfo.o \ find.o \ - keepalive.o -PUBLIC_DEPENDENCIES = \ - ntvfs LIBPACKET LIBCLI_SMB2 -# End SUBSYSTEM SMB2_PROTOCOL -####################### + keepalive.o) + +$(eval $(call proto_header_template,$(smb_serversrcdir)/smb2/smb2_proto.h,$(SMB2_PROTOCOL_OBJ_FILES:.o=.c))) diff --git a/source4/smb_server/smb2/fileio.c b/source4/smb_server/smb2/fileio.c index 0e3df56b42..5ab217bbfd 100644 --- a/source4/smb_server/smb2/fileio.c +++ b/source4/smb_server/smb2/fileio.c @@ -79,6 +79,7 @@ void smb2srv_create_recv(struct smb2srv_request *req) SMB2SRV_CHECK(smb2_pull_o32s32_blob(&req->in, io, req->in.body+0x30, &blob)); /* TODO: parse the blob */ ZERO_STRUCT(io->smb2.in.eas); + ZERO_STRUCT(io->smb2.in.blobs); /* the VFS backend does not yet handle NULL filenames */ if (io->smb2.in.fname == NULL) { @@ -134,7 +135,7 @@ static void smb2srv_flush_send(struct ntvfs_request *ntvfs) SMB2SRV_CHECK_ASYNC_STATUS(io, union smb_flush); SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x04, false, 0)); - SSVAL(req->out.body, 0x02, 0); + SSVAL(req->out.body, 0x02, io->smb2.out.reserved); smb2srv_send_reply(req); } @@ -142,15 +143,14 @@ static void smb2srv_flush_send(struct ntvfs_request *ntvfs) void smb2srv_flush_recv(struct smb2srv_request *req) { union smb_flush *io; - uint16_t _pad; SMB2SRV_CHECK_BODY_SIZE(req, 0x18, false); SMB2SRV_TALLOC_IO_PTR(io, union smb_flush); SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_flush_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->smb2.level = RAW_FLUSH_SMB2; - _pad = SVAL(req->in.body, 0x02); - io->smb2.in.unknown = IVAL(req->in.body, 0x04); + io->smb2.in.reserved1 = SVAL(req->in.body, 0x02); + io->smb2.in.reserved2 = IVAL(req->in.body, 0x04); io->smb2.in.file.ntvfs = smb2srv_pull_handle(req, req->in.body, 0x08); SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs); @@ -167,7 +167,8 @@ static void smb2srv_read_send(struct ntvfs_request *ntvfs) /* TODO: avoid the memcpy */ SMB2SRV_CHECK(smb2_push_o16s32_blob(&req->out, 0x02, io->smb2.out.data)); - SBVAL(req->out.body, 0x08, io->smb2.out.unknown1); + SIVAL(req->out.body, 0x08, io->smb2.out.remaining); + SIVAL(req->out.body, 0x0C, io->smb2.out.reserved); smb2srv_send_reply(req); } @@ -185,8 +186,11 @@ void smb2srv_read_recv(struct smb2srv_request *req) io->smb2.in.length = IVAL(req->in.body, 0x04); io->smb2.in.offset = BVAL(req->in.body, 0x08); io->smb2.in.file.ntvfs = smb2srv_pull_handle(req, req->in.body, 0x10); - io->smb2.in.unknown1 = BVAL(req->in.body, 0x20); - io->smb2.in.unknown2 = BVAL(req->in.body, 0x28); + io->smb2.in.min_count = IVAL(req->in.body, 0x20); + io->smb2.in.channel = IVAL(req->in.body, 0x24); + io->smb2.in.remaining = IVAL(req->in.body, 0x28); + io->smb2.in.channel_offset = SVAL(req->in.body, 0x2C); + io->smb2.in.channel_length = SVAL(req->in.body, 0x2E); SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs); @@ -242,7 +246,7 @@ static void smb2srv_lock_send(struct ntvfs_request *ntvfs) SMB2SRV_CHECK_ASYNC_STATUS_ERR(io, union smb_lock); SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x04, false, 0)); - SSVAL(req->out.body, 0x02, io->smb2.out.unknown1); + SSVAL(req->out.body, 0x02, io->smb2.out.reserved); smb2srv_send_reply(req); } @@ -250,20 +254,34 @@ static void smb2srv_lock_send(struct ntvfs_request *ntvfs) void smb2srv_lock_recv(struct smb2srv_request *req) { union smb_lock *io; + int i; SMB2SRV_CHECK_BODY_SIZE(req, 0x30, false); SMB2SRV_TALLOC_IO_PTR(io, union smb_lock); SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_lock_send, NTVFS_ASYNC_STATE_MAY_ASYNC); io->smb2.level = RAW_LOCK_SMB2; - - io->smb2.in.unknown1 = SVAL(req->in.body, 0x02); - io->smb2.in.unknown2 = IVAL(req->in.body, 0x04); + io->smb2.in.lock_count = SVAL(req->in.body, 0x02); + io->smb2.in.reserved = IVAL(req->in.body, 0x04); io->smb2.in.file.ntvfs = smb2srv_pull_handle(req, req->in.body, 0x08); - io->smb2.in.offset = BVAL(req->in.body, 0x18); - io->smb2.in.count = BVAL(req->in.body, 0x20); - io->smb2.in.unknown5 = IVAL(req->in.body, 0x24); - io->smb2.in.flags = IVAL(req->in.body, 0x28); + if (req->in.body_size < 24 + 24*(uint64_t)io->smb2.in.lock_count) { + DEBUG(0,("%s: lock buffer too small\n", __location__)); + smb2srv_send_error(req, NT_STATUS_FOOBAR); + return; + } + io->smb2.in.locks = talloc_array(io, struct smb2_lock_element, + io->smb2.in.lock_count); + if (io->smb2.in.locks == NULL) { + smb2srv_send_error(req, NT_STATUS_NO_MEMORY); + return; + } + + for (i=0;i<io->smb2.in.lock_count;i++) { + io->smb2.in.locks[i].offset = BVAL(req->in.body, 24 + i*24); + io->smb2.in.locks[i].length = BVAL(req->in.body, 32 + i*24); + io->smb2.in.locks[i].flags = IVAL(req->in.body, 40 + i*24); + io->smb2.in.locks[i].reserved = IVAL(req->in.body, 44 + i*24); + } SMB2SRV_CHECK_FILE_HANDLE(io->smb2.in.file.ntvfs); SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, io)); @@ -405,7 +423,36 @@ void smb2srv_notify_recv(struct smb2srv_request *req) SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_notify(req->ntvfs, io)); } +static void smb2srv_break_send(struct ntvfs_request *ntvfs) +{ + struct smb2srv_request *req; + union smb_lock *io; + + SMB2SRV_CHECK_ASYNC_STATUS_ERR(io, union smb_lock); + SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x18, false, 0)); + + SCVAL(req->out.body, 0x02, io->smb2_break.out.oplock_level); + SCVAL(req->out.body, 0x03, io->smb2_break.out.reserved); + SIVAL(req->out.body, 0x04, io->smb2_break.out.reserved2); + smb2srv_push_handle(req->out.body, 0x08,io->smb2_break.out.file.ntvfs); + + smb2srv_send_reply(req); +} + void smb2srv_break_recv(struct smb2srv_request *req) { - smb2srv_send_error(req, NT_STATUS_NOT_IMPLEMENTED); + union smb_lock *io; + + SMB2SRV_CHECK_BODY_SIZE(req, 0x18, false); + SMB2SRV_TALLOC_IO_PTR(io, union smb_lock); + SMB2SRV_SETUP_NTVFS_REQUEST(smb2srv_break_send, NTVFS_ASYNC_STATE_MAY_ASYNC); + + io->smb2_break.level = RAW_LOCK_SMB2_BREAK; + io->smb2_break.in.oplock_level = CVAL(req->in.body, 0x02); + io->smb2_break.in.reserved = CVAL(req->in.body, 0x03); + io->smb2_break.in.reserved2 = IVAL(req->in.body, 0x04); + io->smb2_break.in.file.ntvfs = smb2srv_pull_handle(req, req->in.body, 0x08); + + SMB2SRV_CHECK_FILE_HANDLE(io->smb2_break.in.file.ntvfs); + SMB2SRV_CALL_NTVFS_BACKEND(ntvfs_lock(req->ntvfs, io)); } diff --git a/source4/smb_server/smb2/find.c b/source4/smb_server/smb2/find.c index 6018f1958f..32b280c5c2 100644 --- a/source4/smb_server/smb2/find.c +++ b/source4/smb_server/smb2/find.c @@ -112,7 +112,7 @@ static NTSTATUS smb2srv_find_backend(struct smb2srv_find_state *state) return NT_STATUS_FOOBAR; } - if (info->in.continue_flags & SMB2_CONTINUE_FLAG_NEW) { + if (info->in.continue_flags & SMB2_CONTINUE_FLAG_REOPEN) { state->ff = talloc(state, union smb_search_first); NT_STATUS_HAVE_NO_MEMORY(state->ff); @@ -156,7 +156,7 @@ void smb2srv_find_recv(struct smb2srv_request *req) info->data_level = RAW_SEARCH_DATA_GENERIC;/* will be overwritten later */ info->in.level = CVAL(req->in.body, 0x02); info->in.continue_flags = CVAL(req->in.body, 0x03); - info->in.unknown = IVAL(req->in.body, 0x04); + info->in.file_index = IVAL(req->in.body, 0x04); info->in.file.ntvfs = smb2srv_pull_handle(req, req->in.body, 0x08); SMB2SRV_CHECK(smb2_pull_o16s16_string(&req->in, info, req->in.body+0x18, &info->in.pattern)); info->in.max_response_size = IVAL(req->in.body, 0x1C); diff --git a/source4/smb_server/smb2/negprot.c b/source4/smb_server/smb2/negprot.c index e7352f7c42..4479ae2da1 100644 --- a/source4/smb_server/smb2/negprot.c +++ b/source4/smb_server/smb2/negprot.c @@ -114,9 +114,12 @@ static NTSTATUS smb2srv_negprot_backend(struct smb2srv_request *req, struct smb2 io->out.security_mode = 0; /* no signing yet */ io->out.dialect_revision = SMB2_DIALECT_REVISION; io->out.capabilities = 0; - io->out.max_transact_size = 0x10000; - io->out.max_read_size = 0x10000; - io->out.max_write_size = 0x10000; + io->out.max_transact_size = lp_parm_ulong(req->smb_conn->lp_ctx, NULL, + "smb2", "max transaction size", 0x10000); + io->out.max_read_size = lp_parm_ulong(req->smb_conn->lp_ctx, NULL, + "smb2", "max read size", 0x10000); + io->out.max_write_size = lp_parm_ulong(req->smb_conn->lp_ctx, NULL, + "smb2", "max write size", 0x10000); io->out.system_time = timeval_to_nttime(¤t_time); io->out.server_start_time = timeval_to_nttime(&boot_time); io->out.reserved2 = 0; diff --git a/source4/smb_server/smb2/smb2_server.h b/source4/smb_server/smb2/smb2_server.h index 2f347d3876..ae4abbd71e 100644 --- a/source4/smb_server/smb2/smb2_server.h +++ b/source4/smb_server/smb2/smb2_server.h @@ -70,7 +70,7 @@ struct smbsrv_request; #include "smb_server/smb2/smb2_proto.h" -/* useful way of catching wct errors with file and line number */ +/* useful way of catching field size errors with file and line number */ #define SMB2SRV_CHECK_BODY_SIZE(req, size, dynamic) do { \ size_t is_size = req->in.body_size; \ uint16_t field_size = SVAL(req->in.body, 0); \ @@ -78,13 +78,13 @@ struct smbsrv_request; if (is_size < (size)) { \ DEBUG(0,("%s: buffer too small 0x%x. Expected 0x%x\n", \ __location__, (unsigned)is_size, (unsigned)want_size)); \ - smb2srv_send_error(req, NT_STATUS_FOOBAR); \ + smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER); \ return; \ }\ if (field_size != want_size) { \ DEBUG(0,("%s: unexpected fixed body size 0x%x. Expected 0x%x\n", \ __location__, (unsigned)field_size, (unsigned)want_size)); \ - smb2srv_send_error(req, NT_STATUS_FOOBAR); \ + smb2srv_send_error(req, NT_STATUS_INVALID_PARAMETER); \ return; \ } \ } while (0) diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c index 4f8e628f74..367557dbb7 100644 --- a/source4/smb_server/smb_server.c +++ b/source4/smb_server/smb_server.c @@ -157,6 +157,7 @@ static void smbsrv_accept(struct stream_connection *conn) smbsrv_management_init(smb_conn); if (!NT_STATUS_IS_OK(share_get_context_by_name(smb_conn, lp_share_backend(smb_conn->lp_ctx), + smb_conn->connection->event.ctx, smb_conn->lp_ctx, &(smb_conn->share_context)))) { smbsrv_terminate_connection(smb_conn, "share_init failed!"); return; @@ -206,7 +207,7 @@ static void smbsrv_preopen_ldb(struct task_server *task) /* yes, this looks strange. It is a hack to preload the schema. I'd like to share most of the ldb context with the child too. That will come later */ - talloc_free(samdb_connect(task, task->lp_ctx, NULL)); + talloc_free(samdb_connect(task, task->event_ctx, task->lp_ctx, NULL)); } /* |