summaryrefslogtreecommitdiff
path: root/source3/libsmb/cliconnect.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libsmb/cliconnect.c')
-rw-r--r--source3/libsmb/cliconnect.c450
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,