diff options
-rw-r--r-- | source3/smbd/globals.h | 37 | ||||
-rw-r--r-- | source3/smbd/negprot.c | 11 | ||||
-rw-r--r-- | source3/smbd/process.c | 25 | ||||
-rw-r--r-- | source3/smbd/smb2_negprot.c | 56 |
4 files changed, 122 insertions, 7 deletions
diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 56ee251483..0a57013a68 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -326,6 +326,41 @@ bool push_deferred_open_message_smb2(struct smbd_smb2_request *smb2req, char *private_data, size_t priv_len); +struct smbXsrv_connection { + struct smbd_server_connection *sconn; + + const struct tsocket_address *local_address; + const struct tsocket_address *remote_address; + const char *remote_hostname; + + struct tevent_context *ev_ctx; + struct messaging_context *msg_ctx; + + enum protocol_types protocol; + + struct { + struct { + uint32_t capabilities; + struct GUID guid; + uint16_t security_mode; + uint16_t num_dialects; + uint16_t *dialects; + } client; + struct { + uint32_t capabilities; + struct GUID guid; + uint16_t security_mode; + uint16_t dialect; + uint32_t max_trans; + uint32_t max_read; + uint32_t max_write; + } server; + } smb2; +}; + +NTSTATUS smbXsrv_connection_init_tables(struct smbXsrv_connection *conn, + enum protocol_types protocol); + struct smbd_smb2_request { struct smbd_smb2_request *prev, *next; @@ -599,6 +634,8 @@ struct smbd_server_connection { struct bitmap *credits_bitmap; bool compound_related_in_progress; } smb2; + + struct smbXsrv_connection *conn; }; extern struct smbd_server_connection *smbd_server_conn; diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c index 9ddafee657..a55a7c336c 100644 --- a/source3/smbd/negprot.c +++ b/source3/smbd/negprot.c @@ -65,7 +65,7 @@ static void reply_corep(struct smb_request *req, uint16 choice) reply_outbuf(req, 1, 0); SSVAL(req->outbuf, smb_vwv0, choice); - set_Protocol(PROTOCOL_CORE); + smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_CORE); } /**************************************************************************** @@ -85,7 +85,8 @@ static void reply_coreplus(struct smb_request *req, uint16 choice) SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); SSVAL(req->outbuf,smb_vwv1,0x1); /* user level security, don't * encrypt */ - set_Protocol(PROTOCOL_COREPLUS); + + smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_COREPLUS); } /**************************************************************************** @@ -118,7 +119,7 @@ static void reply_lanman1(struct smb_request *req, uint16 choice) SSVAL(req->outbuf,smb_vwv11, 8); } - set_Protocol(PROTOCOL_LANMAN1); + smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_LANMAN1); /* Reply, SMBlockread, SMBwritelock supported. */ SCVAL(req->outbuf,smb_flg, FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); @@ -167,7 +168,7 @@ static void reply_lanman2(struct smb_request *req, uint16 choice) SSVAL(req->outbuf,smb_vwv11, 8); } - set_Protocol(PROTOCOL_LANMAN2); + smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_LANMAN2); /* Reply, SMBlockread, SMBwritelock supported. */ SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD); @@ -360,7 +361,7 @@ static void reply_nt1(struct smb_request *req, uint16 choice) SSVAL(req->outbuf,smb_vwv0,choice); SCVAL(req->outbuf,smb_vwv1,secword); - set_Protocol(PROTOCOL_NT1); + smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_NT1); SSVAL(req->outbuf,smb_vwv1+1, lp_maxmux()); /* maxmpx */ SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */ diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 7b12315fc3..087326205c 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -3149,6 +3149,17 @@ static void smbd_id_cache_kill(struct messaging_context *msg_ctx, id_cache_delete_from_cache(&id); } +NTSTATUS smbXsrv_connection_init_tables(struct smbXsrv_connection *conn, + enum protocol_types protocol) +{ + NTSTATUS status; + + set_Protocol(protocol); + conn->protocol = protocol; + + return NT_STATUS_OK; +} + /**************************************************************************** Process commands from the client ****************************************************************************/ @@ -3167,6 +3178,12 @@ void smbd_process(struct tevent_context *ev_ctx, char *rhost; int ret; + sconn->conn = talloc_zero(sconn, struct smbXsrv_connection); + if (sconn->conn == NULL) { + DEBUG(0,("talloc_zero(struct smbXsrv_connection)\n")); + exit_server_cleanly("talloc_zero(struct smbXsrv_connection).\n"); + } + if (lp_srv_maxprotocol() >= PROTOCOL_SMB2_02) { /* * We're not making the decision here, @@ -3430,6 +3447,14 @@ void smbd_process(struct tevent_context *ev_ctx, exit_server("failed to create smbd_server_connection fde"); } + sconn->conn->sconn = sconn; + sconn->conn->ev_ctx = sconn->ev_ctx; + sconn->conn->msg_ctx = sconn->msg_ctx; + sconn->conn->local_address = sconn->local_address; + sconn->conn->remote_address = sconn->remote_address; + sconn->conn->remote_hostname = sconn->remote_hostname; + sconn->conn->protocol = PROTOCOL_NONE; + TALLOC_FREE(frame); while (True) { diff --git a/source3/smbd/smb2_negprot.c b/source3/smbd/smb2_negprot.c index 6d60117710..cfb5dcb777 100644 --- a/source3/smbd/smb2_negprot.c +++ b/source3/smbd/smb2_negprot.c @@ -23,6 +23,7 @@ #include "smbd/globals.h" #include "../libcli/smb/smb_common.h" #include "../lib/tsocket/tsocket.h" +#include "../librpc/ndr/libndr.h" /* * this is the entry point if SMB2 is selected via @@ -94,8 +95,15 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) size_t c; uint16_t security_mode; uint16_t dialect_count; + uint16_t in_security_mode; + uint32_t in_capabilities; + DATA_BLOB in_guid_blob; + struct GUID in_guid; + NTTIME in_start_time; uint16_t dialect = 0; uint32_t capabilities; + DATA_BLOB out_guid_blob; + struct GUID out_guid; enum protocol_types protocol = PROTOCOL_NONE; uint32_t max_limit; uint32_t max_trans = lp_smb2_max_trans(); @@ -109,10 +117,21 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) inbody = (const uint8_t *)req->in.vector[i+1].iov_base; dialect_count = SVAL(inbody, 0x02); + + in_security_mode = SVAL(inbody, 0x04); + in_capabilities = IVAL(inbody, 0x08); + in_guid_blob = data_blob_const(inbody + 0x0C, 16); + in_start_time = BVAL(inbody, 0x1C); + if (dialect_count == 0) { return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); } + status = GUID_from_ndr_blob(&in_guid_blob, &in_guid); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } + expected_dyn_size = dialect_count * 2; if (req->in.vector[i+2].iov_len < expected_dyn_size) { return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER); @@ -280,6 +299,12 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) security_buffer = data_blob_const(NULL, 0); #endif + out_guid_blob = data_blob_const(negprot_spnego_blob.data, 16); + status = GUID_from_ndr_blob(&out_guid_blob, &out_guid); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } + outbody = data_blob_talloc(req->out.vector, NULL, 0x40); if (outbody.data == NULL) { return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); @@ -291,7 +316,7 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) SSVAL(outbody.data, 0x04, dialect); /* dialect revision */ SSVAL(outbody.data, 0x06, 0); /* reserved */ memcpy(outbody.data + 0x08, - negprot_spnego_blob.data, 16); /* server guid */ + out_guid_blob.data, 16); /* server guid */ SIVAL(outbody.data, 0x18, capabilities); /* capabilities */ SIVAL(outbody.data, 0x1C, max_trans); /* max transact size */ @@ -310,7 +335,34 @@ NTSTATUS smbd_smb2_request_process_negprot(struct smbd_smb2_request *req) req->sconn->using_smb2 = true; if (dialect != SMB2_DIALECT_REVISION_2FF) { - set_Protocol(protocol); + struct smbXsrv_connection *conn = req->sconn->conn; + + status = smbXsrv_connection_init_tables(conn, protocol); + if (!NT_STATUS_IS_OK(status)) { + return smbd_smb2_request_error(req, status); + } + + conn->smb2.client.capabilities = in_capabilities; + conn->smb2.client.security_mode = in_security_mode; + conn->smb2.client.guid = in_guid; + conn->smb2.client.num_dialects = dialect_count; + conn->smb2.client.dialects = talloc_array(conn, + uint16_t, + dialect_count); + if (conn->smb2.client.dialects == NULL) { + return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY); + } + for (c=0; c < dialect_count; c++) { + conn->smb2.client.dialects[c] = SVAL(indyn, c*2); + } + + conn->smb2.server.capabilities = capabilities; + conn->smb2.server.security_mode = security_mode; + conn->smb2.server.guid = out_guid; + conn->smb2.server.dialect = dialect; + conn->smb2.server.max_trans = max_trans; + conn->smb2.server.max_read = max_read; + conn->smb2.server.max_write = max_write; req->sconn->smb2.max_trans = max_trans; req->sconn->smb2.max_read = max_read; |