diff options
Diffstat (limited to '')
-rw-r--r-- | source4/libcli/raw/rawnegotiate.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/source4/libcli/raw/rawnegotiate.c b/source4/libcli/raw/rawnegotiate.c new file mode 100644 index 0000000..6d1b736 --- /dev/null +++ b/source4/libcli/raw/rawnegotiate.c @@ -0,0 +1,183 @@ +/* + Unix SMB/CIFS implementation. + + SMB client negotiate context management functions + + Copyright (C) Andrew Tridgell 1994-2005 + Copyright (C) James Myers 2003 <myersjj@samba.org> + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include <tevent.h> +#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; +} |