/* Unix SMB/CIFS implementation. SMB client negotiate context management functions Copyright (C) Andrew Tridgell 1994-2005 Copyright (C) James Myers 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "includes.h" #include #include "system/time.h" #include "libcli/raw/libcliraw.h" #include "libcli/raw/raw_proto.h" #include "../libcli/smb/smbXcli_base.h" #include "../lib/util/tevent_ntstatus.h" NTSTATUS smb_raw_negotiate_fill_transport(struct smbcli_transport *transport) { struct smbcli_negotiate *n = &transport->negotiate; struct smbXcli_conn *c = transport->conn; NTTIME ntt; n->protocol = smbXcli_conn_protocol(c); if (n->protocol > PROTOCOL_NT1) { return NT_STATUS_REVISION_MISMATCH; } 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);; /* 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 (n->capabilities & CAP_EXTENDED_SECURITY) { const DATA_BLOB *b = smbXcli_conn_server_gss_blob(c); if (b) { n->secblob = *b; } } else { const uint8_t *p = smb1cli_conn_server_challenge(c); if (p) { n->secblob = data_blob_const(p, 8); } } n->readbraw_supported = smb1cli_conn_server_readbraw(c); n->readbraw_supported = smb1cli_conn_server_writebraw(c); n->lockread_supported = smb1cli_conn_server_lockread(c); return NT_STATUS_OK; } struct smb_raw_negotiate_state { struct smbcli_transport *transport; }; static void smb_raw_negotiate_done(struct tevent_req *subreq); struct tevent_req *smb_raw_negotiate_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbcli_transport *transport, int minprotocol, 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; } state->transport = transport; if (maxprotocol > PROTOCOL_NT1) { maxprotocol = PROTOCOL_NT1; } if (minprotocol > maxprotocol) { minprotocol = maxprotocol; } subreq = smbXcli_negprot_send(state, ev, transport->conn, timeout_msec, minprotocol, maxprotocol, transport->options.max_credits, NULL); if (tevent_req_nomem(subreq, req)) { return tevent_req_post(req, ev); } tevent_req_set_callback(subreq, smb_raw_negotiate_done, req); return req; } static void smb_raw_negotiate_done(struct tevent_req *subreq) { 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); NTSTATUS status; status = smbXcli_negprot_recv(subreq, NULL, NULL); TALLOC_FREE(subreq); if (tevent_req_nterror(req, status)) { return; } status = smb_raw_negotiate_fill_transport(state->transport); if (tevent_req_nterror(req, status)) { return; } tevent_req_done(req); } /* Send a negprot command. */ NTSTATUS smb_raw_negotiate_recv(struct tevent_req *req) { return tevent_req_simple_recv_ntstatus(req); } /* Send a negprot command (sync interface) */ NTSTATUS smb_raw_negotiate(struct smbcli_transport *transport, bool unicode, int minprotocol, int maxprotocol) { NTSTATUS status; struct tevent_req *subreq = NULL; bool ok; subreq = smb_raw_negotiate_send(transport, transport->ev, transport, minprotocol, maxprotocol); if (subreq == NULL) { status = NT_STATUS_NO_MEMORY; goto failed; } 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; }