diff options
Diffstat (limited to 'source4/libcli/raw/rawnegotiate.c')
-rw-r--r-- | source4/libcli/raw/rawnegotiate.c | 253 |
1 files changed, 98 insertions, 155 deletions
diff --git a/source4/libcli/raw/rawnegotiate.c b/source4/libcli/raw/rawnegotiate.c index 9d6c9ffaf2..9b0ed38cf0 100644 --- a/source4/libcli/raw/rawnegotiate.c +++ b/source4/libcli/raw/rawnegotiate.c @@ -21,184 +21,106 @@ */ #include "includes.h" +#include <tevent.h> +#include "system/time.h" #include "libcli/raw/libcliraw.h" #include "libcli/raw/raw_proto.h" -#include "system/time.h" +#include "../libcli/smb/smbXcli_base.h" +#include "../lib/util/tevent_ntstatus.h" -static const struct { - enum protocol_types prot; - const char *name; -} prots[] = { - {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"}, - {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"}, - {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"}, - {PROTOCOL_LANMAN1,"LANMAN1.0"}, - {PROTOCOL_LANMAN1,"Windows for Workgroups 3.1a"}, - {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"}, -#if 0 - /* we don't yet handle chaining a SMB transport onto SMB2 */ - {PROTOCOL_SMB2_02,"SMB 2.002"}, -#endif +struct smb_raw_negotiate_state { + struct smbcli_transport *transport; }; -/* - Send a negprot command. -*/ -struct smbcli_request *smb_raw_negotiate_send(struct smbcli_transport *transport, - bool unicode, - int maxprotocol) -{ - struct smbcli_request *req; - int i; - uint16_t flags2 = 0; +static void smb_raw_negotiate_done(struct tevent_req *subreq); - req = smbcli_request_setup_transport(transport, SMBnegprot, 0, 0); - if (!req) { +struct tevent_req *smb_raw_negotiate_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + struct smbcli_transport *transport, + int maxprotocol) +{ + struct tevent_req *req; + struct smb_raw_negotiate_state *state; + struct tevent_req *subreq; + uint32_t timeout_msec = transport->options.request_timeout * 1000; + + req = tevent_req_create(mem_ctx, &state, + struct smb_raw_negotiate_state);; + if (req == NULL) { return NULL; } - - if (transport->options.ntstatus_support) { - flags2 |= FLAGS2_32_BIT_ERROR_CODES; - } - - if (unicode) { - flags2 |= FLAGS2_UNICODE_STRINGS; - } - flags2 |= FLAGS2_EXTENDED_ATTRIBUTES; - flags2 |= FLAGS2_LONG_PATH_COMPONENTS; - flags2 |= FLAGS2_IS_LONG_NAME; - - if (transport->options.use_spnego) { - flags2 |= FLAGS2_EXTENDED_SECURITY; - } - - SSVAL(req->out.hdr,HDR_FLG2, flags2); - - /* setup the protocol strings */ - for (i=0; i < ARRAY_SIZE(prots) && prots[i].prot <= maxprotocol; i++) { - smbcli_req_append_bytes(req, (const uint8_t *)"\2", 1); - smbcli_req_append_string(req, prots[i].name, STR_TERMINATE | STR_ASCII); - } - - if (!smbcli_request_send(req)) { - smbcli_request_destroy(req); - return NULL; + state->transport = transport; + + subreq = smbXcli_negprot_send(state, ev, + transport->conn, + timeout_msec, + PROTOCOL_CORE, + maxprotocol); + if (tevent_req_nomem(subreq, req)) { + return tevent_req_post(req, ev); } + tevent_req_set_callback(subreq, smb_raw_negotiate_done, req); return req; } -/* - Send a negprot command. -*/ -NTSTATUS smb_raw_negotiate_recv(struct smbcli_request *req) +static void smb_raw_negotiate_done(struct tevent_req *subreq) { - struct smbcli_transport *transport = req->transport; - int protocol; - - if (!smbcli_request_receive(req) || - smbcli_request_is_error(req)) { - return smbcli_request_destroy(req); + struct tevent_req *req = + tevent_req_callback_data(subreq, + struct tevent_req); + struct smb_raw_negotiate_state *state = + tevent_req_data(req, + struct smb_raw_negotiate_state); + struct smbcli_negotiate *n = &state->transport->negotiate; + struct smbXcli_conn *c = state->transport->conn; + NTSTATUS status; + NTTIME ntt; + + status = smbXcli_negprot_recv(subreq); + TALLOC_FREE(subreq); + if (tevent_req_nterror(req, status)) { + return; } - SMBCLI_CHECK_MIN_WCT(req, 1); - - protocol = SVALS(req->in.vwv, VWV(0)); + n->protocol = smbXcli_conn_protocol(c); - if (protocol >= ARRAY_SIZE(prots) || protocol < 0) { - req->status = NT_STATUS_UNSUCCESSFUL; - return smbcli_request_destroy(req); - } - - transport->negotiate.protocol = prots[protocol].prot; - - if (transport->negotiate.protocol >= PROTOCOL_NT1) { - NTTIME ntt; - - /* NT protocol */ - SMBCLI_CHECK_WCT(req, 17); - transport->negotiate.sec_mode = CVAL(req->in.vwv,VWV(1)); - transport->negotiate.max_mux = SVAL(req->in.vwv,VWV(1)+1); - transport->negotiate.max_xmit = IVAL(req->in.vwv,VWV(3)+1); - transport->negotiate.sesskey = IVAL(req->in.vwv,VWV(7)+1); - transport->negotiate.capabilities = IVAL(req->in.vwv,VWV(9)+1); - - /* this time arrives in real GMT */ - ntt = smbcli_pull_nttime(req->in.vwv, VWV(11)+1); - transport->negotiate.server_time = nt_time_to_unix(ntt); - transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(15)+1) * 60; - transport->negotiate.key_len = CVAL(req->in.vwv,VWV(16)+1); - - if (transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) { - if (req->in.data_size < 16) { - goto failed; - } - transport->negotiate.server_guid = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, 16); - transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data + 16, req->in.data_size - 16); - } else { - if (req->in.data_size < (transport->negotiate.key_len)) { - goto failed; - } - transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, transport->negotiate.key_len); - smbcli_req_pull_string(&req->in.bufinfo, transport, &transport->negotiate.server_domain, - req->in.data+transport->negotiate.key_len, - req->in.data_size-transport->negotiate.key_len, STR_UNICODE|STR_NOALIGN); - /* here comes the server name */ - } + n->sec_mode = smb1cli_conn_server_security_mode(c); + n->max_mux = smbXcli_conn_max_requests(c); + n->max_xmit = smb1cli_conn_max_xmit(c); + n->sesskey = smb1cli_conn_server_session_key(c); + n->capabilities = smb1cli_conn_capabilities(c);; - if (transport->negotiate.capabilities & CAP_RAW_MODE) { - transport->negotiate.readbraw_supported = true; - transport->negotiate.writebraw_supported = true; - } + /* this time arrives in real GMT */ + ntt = smbXcli_conn_server_system_time(c); + n->server_time = nt_time_to_unix(ntt); + n->server_zone = smb1cli_conn_server_time_zone(c); - if (transport->negotiate.capabilities & CAP_LOCK_AND_READ) - transport->negotiate.lockread_supported = true; - } else if (transport->negotiate.protocol >= PROTOCOL_LANMAN1) { - SMBCLI_CHECK_WCT(req, 13); - transport->negotiate.sec_mode = SVAL(req->in.vwv,VWV(1)); - transport->negotiate.max_xmit = SVAL(req->in.vwv,VWV(2)); - transport->negotiate.sesskey = IVAL(req->in.vwv,VWV(6)); - transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(10)) * 60; - - /* this time is converted to GMT by raw_pull_dos_date */ - transport->negotiate.server_time = raw_pull_dos_date(transport, - req->in.vwv+VWV(8)); - if ((SVAL(req->in.vwv,VWV(5)) & 0x1)) { - transport->negotiate.readbraw_supported = 1; - } - if ((SVAL(req->in.vwv,VWV(5)) & 0x2)) { - transport->negotiate.writebraw_supported = 1; + if (n->capabilities & CAP_EXTENDED_SECURITY) { + const DATA_BLOB *b = smbXcli_conn_server_gss_blob(c); + if (b) { + n->secblob = *b; } - transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, - req->in.data, req->in.data_size); } else { - /* the old core protocol */ - transport->negotiate.sec_mode = 0; - transport->negotiate.server_time = time(NULL); - transport->negotiate.max_xmit = transport->options.max_xmit; - transport->negotiate.server_zone = get_time_zone(transport->negotiate.server_time); - } - - /* a way to force ascii SMB */ - if (!transport->options.unicode) { - transport->negotiate.capabilities &= ~CAP_UNICODE; + const uint8_t *p = smb1cli_conn_server_challenge(c); + if (p) { + n->secblob = data_blob_const(p, 8); + } } - if (!transport->options.ntstatus_support) { - transport->negotiate.capabilities &= ~CAP_STATUS32; - } + n->readbraw_supported = smb1cli_conn_server_readbraw(c); + n->readbraw_supported = smb1cli_conn_server_writebraw(c); + n->lockread_supported = smb1cli_conn_server_lockread(c); - if (!transport->options.use_level2_oplocks) { - transport->negotiate.capabilities &= ~CAP_LEVEL_II_OPLOCKS; - } + tevent_req_done(req); +} -failed: - return smbcli_request_destroy(req); +/* + Send a negprot command. +*/ +NTSTATUS smb_raw_negotiate_recv(struct tevent_req *req) +{ + return tevent_req_simple_recv_ntstatus(req); } @@ -207,6 +129,27 @@ failed: */ NTSTATUS smb_raw_negotiate(struct smbcli_transport *transport, bool unicode, int maxprotocol) { - struct smbcli_request *req = smb_raw_negotiate_send(transport, unicode, maxprotocol); - return smb_raw_negotiate_recv(req); + NTSTATUS status = NT_STATUS_INTERNAL_ERROR; + struct tevent_req *subreq = NULL; + bool ok; + + subreq = smb_raw_negotiate_send(transport, + transport->ev, + transport, + maxprotocol); + if (subreq == NULL) { + return NT_STATUS_NO_MEMORY; + } + + ok = tevent_req_poll(subreq, transport->ev); + if (!ok) { + status = map_nt_error_from_unix_common(errno); + goto failed; + } + + status = smb_raw_negotiate_recv(subreq); + +failed: + TALLOC_FREE(subreq); + return status; } |