diff options
-rw-r--r-- | source4/smb_server/config.mk | 2 | ||||
-rw-r--r-- | source4/smb_server/smb_server.c | 129 | ||||
-rw-r--r-- | source4/smb_server/smb_server.h | 6 |
3 files changed, 36 insertions, 101 deletions
diff --git a/source4/smb_server/config.mk b/source4/smb_server/config.mk index 03a49d728a..c1eadf9397 100644 --- a/source4/smb_server/config.mk +++ b/source4/smb_server/config.mk @@ -20,6 +20,6 @@ ADD_OBJ_FILES = \ signing.o \ management.o REQUIRED_SUBSYSTEMS = \ - NTVFS + NTVFS LIBPACKET # End SUBSYSTEM SMB ####################### diff --git a/source4/smb_server/smb_server.c b/source4/smb_server/smb_server.c index ccfc6c9c7b..0cdc2dc7e4 100644 --- a/source4/smb_server/smb_server.c +++ b/source4/smb_server/smb_server.c @@ -27,6 +27,7 @@ #include "smbd/service_stream.h" #include "smb_server/smb_server.h" #include "lib/messaging/irpc.h" +#include "lib/stream/packet.h" /* @@ -68,85 +69,18 @@ static void construct_reply(struct smbsrv_request *req); receive a SMB request header from the wire, forming a request_context from the result ****************************************************************************/ -static NTSTATUS receive_smb_request(struct smbsrv_connection *smb_conn) +static NTSTATUS receive_smb_request(void *private, DATA_BLOB blob) { - NTSTATUS status; - ssize_t len; + struct smbsrv_connection *smb_conn = talloc_get_type(private, struct smbsrv_connection); struct smbsrv_request *req; - size_t nread; - - /* allocate the request if needed */ - if (smb_conn->partial_req == NULL) { - req = init_smb_request(smb_conn); - if (req == NULL) { - return NT_STATUS_NO_MEMORY; - } - - req->in.buffer = talloc_array(req, uint8_t, NBT_HDR_SIZE); - if (req->in.buffer == NULL) { - talloc_free(req); - return NT_STATUS_NO_MEMORY; - } - req->in.size = 0; - smb_conn->partial_req = req; - } - - req = smb_conn->partial_req; - - /* read in the header */ - if (req->in.size < NBT_HDR_SIZE) { - status = socket_recv(smb_conn->connection->socket, - req->in.buffer + req->in.size, - NBT_HDR_SIZE - req->in.size, - &nread, 0); - if (NT_STATUS_IS_ERR(status)) { - return status; - } - if (!NT_STATUS_IS_OK(status)) { - return NT_STATUS_OK; - } - if (nread == 0) { - return NT_STATUS_END_OF_FILE; - } - req->in.size += nread; - - /* when we have a full NBT header, then allocate the packet */ - if (req->in.size == NBT_HDR_SIZE) { - len = smb_len(req->in.buffer) + NBT_HDR_SIZE; - req->in.buffer = talloc_realloc(req, req->in.buffer, - uint8_t, len); - if (req->in.buffer == NULL) { - return NT_STATUS_NO_MEMORY; - } - } else { - return NT_STATUS_OK; - } - } - - /* read in the main packet */ - len = smb_len(req->in.buffer) + NBT_HDR_SIZE; - - status = socket_recv(smb_conn->connection->socket, - req->in.buffer + req->in.size, - len - req->in.size, - &nread, 0); - if (NT_STATUS_IS_ERR(status)) { - return status; - } - if (!NT_STATUS_IS_OK(status)) { - return NT_STATUS_OK; - } - if (nread == 0) { - return NT_STATUS_END_OF_FILE; - } - - req->in.size += nread; - if (req->in.size != len) { - return NT_STATUS_OK; + req = init_smb_request(smb_conn); + if (req == NULL) { + return NT_STATUS_NO_MEMORY; } - /* we have a full packet */ + req->in.buffer = talloc_steal(req, blob.data); + req->in.size = blob.length; req->request_time = timeval_current(); req->chained_fnum = -1; req->in.allocated = req->in.size; @@ -171,8 +105,6 @@ static NTSTATUS receive_smb_request(struct smbsrv_connection *smb_conn) } } - smb_conn->partial_req = NULL; - construct_reply(req); return NT_STATUS_OK; @@ -659,7 +591,7 @@ error: */ void smbsrv_terminate_connection(struct smbsrv_connection *smb_conn, const char *reason) { - smb_conn->terminate = True; + smb_conn->terminate = reason; } /* @@ -668,31 +600,17 @@ void smbsrv_terminate_connection(struct smbsrv_connection *smb_conn, const char static void smbsrv_recv(struct stream_connection *conn, uint16_t flags) { struct smbsrv_connection *smb_conn = talloc_get_type(conn->private, struct smbsrv_connection); - NTSTATUS status; DEBUG(10,("smbsrv_recv\n")); - /* our backends are designed to process one request at a time, - unless they deliberately mark the request as async and - process it later on a timer or other event. This enforces - that ordering. */ - if (smb_conn->processing) { - EVENT_FD_NOT_READABLE(conn->event.fde); - return; - } - - smb_conn->processing = True; - status = receive_smb_request(smb_conn); - smb_conn->processing = False; - if (NT_STATUS_IS_ERR(status) || smb_conn->terminate) { + packet_recv(smb_conn->packet); + if (smb_conn->terminate) { talloc_free(conn->event.fde); conn->event.fde = NULL; - stream_terminate_connection(smb_conn->connection, nt_errstr(status)); + stream_terminate_connection(smb_conn->connection, smb_conn->terminate); return; } - EVENT_FD_READABLE(conn->event.fde); - /* free up temporary memory */ lp_talloc_free(); } @@ -734,7 +652,7 @@ static void smbsrv_send(struct stream_connection *conn, uint16_t flags) } if (smb_conn->terminate) { - stream_terminate_connection(smb_conn->connection, "send termination"); + stream_terminate_connection(smb_conn->connection, smb_conn->terminate); return; } @@ -745,6 +663,17 @@ static void smbsrv_send(struct stream_connection *conn, uint16_t flags) } } + +/* + handle socket recv errors +*/ +static void smbsrv_recv_error(void *private, NTSTATUS status) +{ + struct smbsrv_connection *smb_conn = talloc_get_type(private, struct smbsrv_connection); + + smbsrv_terminate_connection(smb_conn, nt_errstr(status)); +} + /* initialise a server_context from a open socket and register a event handler for reading from that socket @@ -770,6 +699,15 @@ static void smbsrv_accept(struct stream_connection *conn) smb_conn->negotiate.called_name = NULL; smb_conn->negotiate.calling_name = NULL; + smb_conn->packet = packet_init(smb_conn); + packet_set_private(smb_conn->packet, smb_conn); + packet_set_socket(smb_conn->packet, conn->socket); + packet_set_callback(smb_conn->packet, receive_smb_request); + packet_set_full_request(smb_conn->packet, packet_full_request_nbt); + packet_set_error_handler(smb_conn->packet, smbsrv_recv_error); + packet_set_event_context(smb_conn->packet, conn->event.ctx); + packet_set_serialise(smb_conn->packet, conn->event.fde); + smbsrv_vuid_init(smb_conn); srv_init_signing(smb_conn); @@ -777,7 +715,6 @@ static void smbsrv_accept(struct stream_connection *conn) smbsrv_tcon_init(smb_conn); smb_conn->connection = conn; - smb_conn->processing = False; smb_conn->config.security = lp_security(); smb_conn->config.nt_status_support = lp_nt_status_support(); diff --git a/source4/smb_server/smb_server.h b/source4/smb_server/smb_server.h index 360ea7ddfb..b6c9d5f985 100644 --- a/source4/smb_server/smb_server.h +++ b/source4/smb_server/smb_server.h @@ -252,7 +252,7 @@ struct smbsrv_connection { struct stream_connection *connection; /* this holds a partially received request */ - struct smbsrv_request *partial_req; + struct packet_context *packet; /* this holds list of replies that are waiting to be sent to the client */ @@ -266,10 +266,8 @@ struct smbsrv_connection { uint8_t command; } *trans_partial; - BOOL processing; - /* mark a connection for termination */ - BOOL terminate; + const char *terminate; /* configuration parameters */ struct { |