Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : 4 : SMB client negotiate context management functions 5 : 6 : Copyright (C) Andrew Tridgell 1994-2005 7 : Copyright (C) James Myers 2003 <myersjj@samba.org> 8 : 9 : This program is free software; you can redistribute it and/or modify 10 : it under the terms of the GNU General Public License as published by 11 : the Free Software Foundation; either version 3 of the License, or 12 : (at your option) any later version. 13 : 14 : This program is distributed in the hope that it will be useful, 15 : but WITHOUT ANY WARRANTY; without even the implied warranty of 16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 : GNU General Public License for more details. 18 : 19 : You should have received a copy of the GNU General Public License 20 : along with this program. If not, see <http://www.gnu.org/licenses/>. 21 : */ 22 : 23 : #include "includes.h" 24 : #include <tevent.h> 25 : #include "system/time.h" 26 : #include "libcli/raw/libcliraw.h" 27 : #include "libcli/raw/raw_proto.h" 28 : #include "../libcli/smb/smbXcli_base.h" 29 : #include "../lib/util/tevent_ntstatus.h" 30 : 31 2755 : NTSTATUS smb_raw_negotiate_fill_transport(struct smbcli_transport *transport) 32 : { 33 2755 : struct smbcli_negotiate *n = &transport->negotiate; 34 2755 : struct smbXcli_conn *c = transport->conn; 35 133 : NTTIME ntt; 36 : 37 2755 : n->protocol = smbXcli_conn_protocol(c); 38 2755 : if (n->protocol > PROTOCOL_NT1) { 39 0 : return NT_STATUS_REVISION_MISMATCH; 40 : } 41 : 42 2755 : n->sec_mode = smb1cli_conn_server_security_mode(c); 43 2755 : n->max_mux = smbXcli_conn_max_requests(c); 44 2755 : n->max_xmit = smb1cli_conn_max_xmit(c); 45 2755 : n->sesskey = smb1cli_conn_server_session_key(c); 46 2755 : n->capabilities = smb1cli_conn_capabilities(c);; 47 : 48 : /* this time arrives in real GMT */ 49 2755 : ntt = smbXcli_conn_server_system_time(c); 50 2755 : n->server_time = nt_time_to_unix(ntt); 51 2755 : n->server_zone = smb1cli_conn_server_time_zone(c); 52 : 53 2755 : if (n->capabilities & CAP_EXTENDED_SECURITY) { 54 2735 : const DATA_BLOB *b = smbXcli_conn_server_gss_blob(c); 55 2735 : if (b) { 56 2735 : n->secblob = *b; 57 : } 58 : } else { 59 20 : const uint8_t *p = smb1cli_conn_server_challenge(c); 60 20 : if (p) { 61 20 : n->secblob = data_blob_const(p, 8); 62 : } 63 : } 64 : 65 2755 : n->readbraw_supported = smb1cli_conn_server_readbraw(c); 66 2755 : n->readbraw_supported = smb1cli_conn_server_writebraw(c); 67 2755 : n->lockread_supported = smb1cli_conn_server_lockread(c); 68 : 69 2755 : return NT_STATUS_OK; 70 : } 71 : 72 : struct smb_raw_negotiate_state { 73 : struct smbcli_transport *transport; 74 : }; 75 : 76 : static void smb_raw_negotiate_done(struct tevent_req *subreq); 77 : 78 3431 : struct tevent_req *smb_raw_negotiate_send(TALLOC_CTX *mem_ctx, 79 : struct tevent_context *ev, 80 : struct smbcli_transport *transport, 81 : int minprotocol, 82 : int maxprotocol) 83 : { 84 141 : struct tevent_req *req; 85 141 : struct smb_raw_negotiate_state *state; 86 141 : struct tevent_req *subreq; 87 3431 : uint32_t timeout_msec = transport->options.request_timeout * 1000; 88 : 89 3431 : req = tevent_req_create(mem_ctx, &state, 90 141 : struct smb_raw_negotiate_state);; 91 3431 : if (req == NULL) { 92 0 : return NULL; 93 : } 94 3431 : state->transport = transport; 95 : 96 3431 : if (maxprotocol > PROTOCOL_NT1) { 97 0 : maxprotocol = PROTOCOL_NT1; 98 : } 99 : 100 3431 : if (minprotocol > maxprotocol) { 101 16 : minprotocol = maxprotocol; 102 : } 103 : 104 3572 : subreq = smbXcli_negprot_send(state, ev, 105 : transport->conn, 106 : timeout_msec, 107 : minprotocol, 108 : maxprotocol, 109 3431 : transport->options.max_credits, 110 : NULL); 111 3431 : if (tevent_req_nomem(subreq, req)) { 112 0 : return tevent_req_post(req, ev); 113 : } 114 3431 : tevent_req_set_callback(subreq, smb_raw_negotiate_done, req); 115 : 116 3431 : return req; 117 : } 118 : 119 3431 : static void smb_raw_negotiate_done(struct tevent_req *subreq) 120 : { 121 141 : struct tevent_req *req = 122 3431 : tevent_req_callback_data(subreq, 123 : struct tevent_req); 124 141 : struct smb_raw_negotiate_state *state = 125 3431 : tevent_req_data(req, 126 : struct smb_raw_negotiate_state); 127 141 : NTSTATUS status; 128 : 129 3431 : status = smbXcli_negprot_recv(subreq, NULL, NULL); 130 3431 : TALLOC_FREE(subreq); 131 3431 : if (tevent_req_nterror(req, status)) { 132 702 : return; 133 : } 134 : 135 2729 : status = smb_raw_negotiate_fill_transport(state->transport); 136 2729 : if (tevent_req_nterror(req, status)) { 137 0 : return; 138 : } 139 : 140 2729 : tevent_req_done(req); 141 : } 142 : 143 : /* 144 : Send a negprot command. 145 : */ 146 2831 : NTSTATUS smb_raw_negotiate_recv(struct tevent_req *req) 147 : { 148 2831 : return tevent_req_simple_recv_ntstatus(req); 149 : } 150 : 151 : 152 : /* 153 : Send a negprot command (sync interface) 154 : */ 155 0 : NTSTATUS smb_raw_negotiate(struct smbcli_transport *transport, bool unicode, 156 : int minprotocol, int maxprotocol) 157 : { 158 0 : NTSTATUS status; 159 0 : struct tevent_req *subreq = NULL; 160 0 : bool ok; 161 : 162 0 : subreq = smb_raw_negotiate_send(transport, 163 : transport->ev, 164 : transport, 165 : minprotocol, 166 : maxprotocol); 167 0 : if (subreq == NULL) { 168 0 : status = NT_STATUS_NO_MEMORY; 169 0 : goto failed; 170 : } 171 : 172 0 : ok = tevent_req_poll(subreq, transport->ev); 173 0 : if (!ok) { 174 0 : status = map_nt_error_from_unix_common(errno); 175 0 : goto failed; 176 : } 177 : 178 0 : status = smb_raw_negotiate_recv(subreq); 179 : 180 0 : failed: 181 0 : TALLOC_FREE(subreq); 182 0 : return status; 183 : }