diff options
Diffstat (limited to 'source3/libsmb/cliconnect.c')
-rw-r--r-- | source3/libsmb/cliconnect.c | 450 |
1 files changed, 7 insertions, 443 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index c2fa9239ef..8197e0ac18 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -33,22 +33,7 @@ #include "async_smb.h" #include "libsmb/nmblib.h" #include "librpc/ndr/libndr.h" - -static const struct { - int prot; - const char name[24]; -} prots[10] = { - {PROTOCOL_CORE, "PC NETWORK PROGRAM 1.0"}, - {PROTOCOL_COREPLUS, "MICROSOFT NETWORKS 1.03"}, - {PROTOCOL_LANMAN1, "MICROSOFT NETWORKS 3.0"}, - {PROTOCOL_LANMAN1, "LANMAN1.0"}, - {PROTOCOL_LANMAN2, "LM1.2X002"}, - {PROTOCOL_LANMAN2, "DOS LANMAN2.1"}, - {PROTOCOL_LANMAN2, "LANMAN2.1"}, - {PROTOCOL_LANMAN2, "Samba"}, - {PROTOCOL_NT1, "NT LANMAN 1.0"}, - {PROTOCOL_NT1, "NT LM 0.12"}, -}; +#include "../libcli/smb/smbXcli_base.h" #define STAR_SMBSERVER "*SMBSERVER" @@ -2513,446 +2498,25 @@ fail: return status; } -/**************************************************************************** - Send a negprot command. -****************************************************************************/ - -struct cli_negprot_state { - struct cli_state *cli; - enum protocol_types max_protocol; -}; - -static void cli_negprot_done(struct tevent_req *subreq); - struct tevent_req *cli_negprot_send(TALLOC_CTX *mem_ctx, struct event_context *ev, struct cli_state *cli, enum protocol_types max_protocol) { - struct tevent_req *req, *subreq; - struct cli_negprot_state *state; - uint8_t *bytes = NULL; - int numprots; - enum protocol_types tmp_protocol; - - req = tevent_req_create(mem_ctx, &state, struct cli_negprot_state); - if (req == NULL) { - return NULL; - } - state->cli = cli; - state->max_protocol = max_protocol; - - /* setup the protocol strings */ - for (numprots=0; numprots < ARRAY_SIZE(prots); numprots++) { - uint8_t c = 2; - if (prots[numprots].prot > state->max_protocol) { - break; - } - bytes = (uint8_t *)talloc_append_blob( - state, bytes, data_blob_const(&c, sizeof(c))); - if (tevent_req_nomem(bytes, req)) { - return tevent_req_post(req, ev); - } - bytes = smb_bytes_push_str(bytes, false, - prots[numprots].name, - strlen(prots[numprots].name)+1, - NULL); - if (tevent_req_nomem(bytes, req)) { - return tevent_req_post(req, ev); - } - } - - tmp_protocol = cli->conn.protocol; - cli->conn.protocol = state->max_protocol; - subreq = cli_smb_send(state, ev, cli, SMBnegprot, 0, 0, NULL, - talloc_get_size(bytes), bytes); - cli->conn.protocol = tmp_protocol; - if (tevent_req_nomem(subreq, req)) { - return tevent_req_post(req, ev); - } - tevent_req_set_callback(subreq, cli_negprot_done, req); - return req; -} - -static void cli_negprot_done(struct tevent_req *subreq) -{ - struct tevent_req *req = tevent_req_callback_data( - subreq, struct tevent_req); - struct cli_negprot_state *state = tevent_req_data( - req, struct cli_negprot_state); - struct cli_state *cli = state->cli; - uint8_t flags; - uint8_t wct; - uint16_t *vwv; - uint32_t num_bytes; - uint8_t *bytes; - NTSTATUS status; - uint16_t protnum; - uint8_t *inbuf; - uint32_t client_capabilities = cli->conn.smb1.client.capabilities; - uint32_t both_capabilities; - uint32_t server_capabilities = 0; - uint32_t capabilities; - uint32_t client_max_xmit = cli->conn.smb1.client.max_xmit; - uint32_t server_max_xmit = 0; - uint32_t max_xmit; - uint32_t server_max_mux = 0; - uint16_t server_security_mode = 0; - uint32_t server_session_key = 0; - bool server_readbraw = false; - bool server_writebraw = false; - bool server_lockread = false; - bool server_writeunlock = false; - struct GUID server_guid = GUID_zero(); - DATA_BLOB server_gss_blob = data_blob_null; - uint8_t server_challenge[8]; - char *server_workgroup = NULL; - char *server_name = NULL; - int server_time_zone = 0; - time_t server_system_time = 0; - enum protocol_types protocol; - - ZERO_STRUCT(server_challenge); - - status = cli_smb_recv(subreq, state, &inbuf, 1, &wct, &vwv, - &num_bytes, &bytes); - TALLOC_FREE(subreq); - if (!NT_STATUS_IS_OK(status)) { - tevent_req_nterror(req, status); - return; - } - - flags = CVAL(inbuf, smb_flg); - - protnum = SVAL(vwv, 0); - - if ((protnum >= ARRAY_SIZE(prots)) - || (prots[protnum].prot > state->max_protocol)) { - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - protocol = prots[protnum].prot; - - if ((protocol < PROTOCOL_NT1) && - client_is_signing_mandatory(cli)) { - DEBUG(0,("cli_negprot: SMB signing is mandatory and the selected protocol level doesn't support it.\n")); - tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); - return; - } - - if (flags & FLAG_SUPPORT_LOCKREAD) { - server_lockread = true; - server_writeunlock = true; - } - - if (protocol >= PROTOCOL_NT1) { - struct timespec ts; - const char *client_signing = NULL; - bool server_mandatory; - bool server_allowed; - const char *server_signing = NULL; - bool ok; - uint8_t key_len; - - if (wct != 0x11) { - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - /* NT protocol */ - server_security_mode = CVAL(vwv + 1, 0); - server_max_mux = SVAL(vwv + 1, 1); - server_max_xmit = IVAL(vwv + 3, 1); - server_session_key = IVAL(vwv + 7, 1); - server_time_zone = SVALS(vwv + 15, 1); - server_time_zone *= 60; - /* this time arrives in real GMT */ - ts = interpret_long_date(((char *)(vwv+11))+1); - server_system_time = ts.tv_sec; - server_capabilities = IVAL(vwv + 9, 1); - - key_len = CVAL(vwv + 16, 1); - - if (server_capabilities & CAP_RAW_MODE) { - server_readbraw = true; - server_writebraw = true; - } - if (server_capabilities & CAP_LOCK_AND_READ) { - server_lockread = true; - } - - if (server_capabilities & CAP_EXTENDED_SECURITY) { - DATA_BLOB blob1, blob2; - - if (num_bytes < 16) { - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - blob1 = data_blob_const(bytes, 16); - GUID_from_data_blob(&blob1, &server_guid); - - blob1 = data_blob_const(bytes+16, num_bytes-16); - blob2 = data_blob_dup_talloc(state, blob1); - if (blob1.length > 0 && - tevent_req_nomem(blob2.data, req)) { - return; - } - server_gss_blob = blob2; - } else { - DATA_BLOB blob1, blob2; - ssize_t ret = 0; - - if (num_bytes < key_len) { - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - if (key_len != 0 && key_len != 8) { - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - if (key_len == 8) { - memcpy(server_challenge, bytes, 8); - } - - blob1 = data_blob_const(bytes+key_len, num_bytes-key_len); - blob2 = data_blob_const(bytes+key_len, num_bytes-key_len); - if (blob1.length > 0) { - ret = pull_string_talloc(state, - (char *)inbuf, - SVAL(inbuf, smb_flg2), - &server_workgroup, - blob1.data, - blob1.length, - STR_TERMINATE| - STR_UNICODE| - STR_NOALIGN); - if (ret == -1) { - tevent_req_oom(req); - return; - } - } - - blob2.data += ret; - blob2.length -= ret; - if (blob2.length > 0) { - ret = pull_string_talloc(state, - (char *)inbuf, - SVAL(inbuf, smb_flg2), - &server_name, - blob2.data, - blob2.length, - STR_TERMINATE| - STR_UNICODE| - STR_NOALIGN); - if (ret == -1) { - tevent_req_oom(req); - return; - } - } - } - - client_signing = "disabled"; - if (client_is_signing_allowed(cli)) { - client_signing = "allowed"; - } - if (client_is_signing_mandatory(cli)) { - client_signing = "required"; - } - - server_signing = "not supported"; - - server_allowed = false; - if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) { - server_signing = "supported"; - server_allowed = true; - } - - server_mandatory = false; - if (server_security_mode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED) { - server_signing = "required"; - server_mandatory = true; - } - - ok = cli_set_signing_negotiated(cli, - server_allowed, - server_mandatory); - if (!ok) { - DEBUG(1,("cli_negprot: SMB signing is required, " - "but client[%s] and server[%s] mismatch\n", - client_signing, server_signing)); - tevent_req_nterror(req, NT_STATUS_ACCESS_DENIED); - return; - } - - } else if (protocol >= PROTOCOL_LANMAN1) { - DATA_BLOB blob1; - ssize_t ret = 0; - uint16_t key_len; - - if (wct != 0x0D) { - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - server_security_mode = SVAL(vwv + 1, 0); - server_max_xmit = SVAL(vwv + 2, 0); - server_max_mux = SVAL(vwv + 3, 0); - server_readbraw = ((SVAL(vwv + 5, 0) & 0x1) != 0); - server_writebraw = ((SVAL(vwv + 5, 0) & 0x2) != 0); - server_session_key = IVAL(vwv + 6, 0); - server_time_zone = SVALS(vwv + 10, 0); - server_time_zone *= 60; - /* this time is converted to GMT by make_unix_date */ - server_system_time = make_unix_date( - (char *)(vwv + 8), server_time_zone); - key_len = SVAL(vwv + 11, 0); - - if (num_bytes < key_len) { - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - if (key_len != 0 && key_len != 8) { - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - if (key_len == 8) { - memcpy(server_challenge, bytes, 8); - } - - blob1 = data_blob_const(bytes+key_len, num_bytes-key_len); - if (blob1.length > 0) { - ret = pull_string_talloc(state, - (char *)inbuf, - SVAL(inbuf, smb_flg2), - &server_workgroup, - blob1.data, - blob1.length, - STR_TERMINATE| - STR_ASCII); - if (ret == -1) { - tevent_req_oom(req); - return; - } - } - } else { - /* the old core protocol */ - server_time_zone = get_time_zone(time(NULL)); - server_system_time = 0; - server_max_xmit = 1024; - server_max_mux = 1; - server_security_mode = 0; - } - - if (server_max_xmit < 1024) { - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - if (server_max_mux < 1) { - tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE); - return; - } - - /* - * Now calculate the negotiated capabilities - * based on the mask for: - * - client only flags - * - flags used in both directions - * - server only flags - */ - both_capabilities = client_capabilities & server_capabilities; - capabilities = client_capabilities & SMB_CAP_CLIENT_MASK; - capabilities |= both_capabilities & SMB_CAP_BOTH_MASK; - capabilities |= server_capabilities & SMB_CAP_SERVER_MASK; - - max_xmit = MIN(client_max_xmit, server_max_xmit); - - if (server_workgroup) { - cli->server_domain = talloc_strdup(cli, server_workgroup); - if (tevent_req_nomem(cli->server_domain, req)) { - return; - } - } - - cli->conn.protocol = protocol; - - cli->conn.smb1.server.capabilities = server_capabilities; - cli->conn.smb1.capabilities = capabilities; - - cli->conn.smb1.server.max_xmit = server_max_xmit; - cli->conn.smb1.max_xmit = max_xmit; - - cli->conn.smb1.server.max_mux = server_max_mux; - - cli->conn.smb1.server.security_mode = server_security_mode; - - cli->conn.smb1.server.readbraw = server_readbraw; - cli->conn.smb1.server.writebraw = server_writebraw; - cli->conn.smb1.server.lockread = server_lockread; - cli->conn.smb1.server.writeunlock = server_writeunlock; - - cli->conn.smb1.server.session_key = server_session_key; - - talloc_steal(cli, server_gss_blob.data); - cli->conn.smb1.server.gss_blob = server_gss_blob; - cli->conn.smb1.server.guid = server_guid; - memcpy(cli->conn.smb1.server.challenge, server_challenge, 8); - cli->conn.smb1.server.workgroup = talloc_move(cli, &server_workgroup); - cli->conn.smb1.server.name = talloc_move(cli, &server_name); - - cli->conn.smb1.server.time_zone = server_time_zone; - cli->conn.smb1.server.system_time = server_system_time; - - tevent_req_done(req); + return smbXcli_negprot_send(mem_ctx, ev, + cli->conn, cli->timeout, + PROTOCOL_CORE, max_protocol); } NTSTATUS cli_negprot_recv(struct tevent_req *req) { - return tevent_req_simple_recv_ntstatus(req); + return smbXcli_negprot_recv(req); } NTSTATUS cli_negprot(struct cli_state *cli, enum protocol_types max_protocol) { - TALLOC_CTX *frame = talloc_stackframe(); - struct event_context *ev; - struct tevent_req *req; - NTSTATUS status = NT_STATUS_OK; - - if (cli_has_async_calls(cli)) { - /* - * Can't use sync call while an async call is in flight - */ - status = NT_STATUS_INVALID_PARAMETER; - goto fail; - } - - ev = event_context_init(frame); - if (ev == NULL) { - status = NT_STATUS_NO_MEMORY; - goto fail; - } - - req = cli_negprot_send(frame, ev, cli, max_protocol); - if (req == NULL) { - status = NT_STATUS_NO_MEMORY; - goto fail; - } - - if (!tevent_req_poll(req, ev)) { - status = map_nt_error_from_unix(errno); - goto fail; - } - - status = cli_negprot_recv(req); - fail: - TALLOC_FREE(frame); - return status; + return smbXcli_negprot(cli->conn, cli->timeout, + PROTOCOL_CORE, max_protocol); } static NTSTATUS cli_connect_sock(const char *host, int name_type, |