s4:libcli: split out smb_raw_negotiate_fill_transport()
[samba.git] / source4 / libcli / raw / rawnegotiate.c
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 NTSTATUS smb_raw_negotiate_fill_transport(struct smbcli_transport *transport)
32 {
33         struct smbcli_negotiate *n = &transport->negotiate;
34         struct smbXcli_conn *c = transport->conn;
35         NTTIME ntt;
36
37         n->protocol = smbXcli_conn_protocol(c);
38         if (n->protocol > PROTOCOL_NT1) {
39                 return NT_STATUS_REVISION_MISMATCH;
40         }
41
42         n->sec_mode = smb1cli_conn_server_security_mode(c);
43         n->max_mux  = smbXcli_conn_max_requests(c);
44         n->max_xmit = smb1cli_conn_max_xmit(c);
45         n->sesskey  = smb1cli_conn_server_session_key(c);
46         n->capabilities = smb1cli_conn_capabilities(c);;
47
48         /* this time arrives in real GMT */
49         ntt = smbXcli_conn_server_system_time(c);
50         n->server_time = nt_time_to_unix(ntt);
51         n->server_zone = smb1cli_conn_server_time_zone(c);
52
53         if (n->capabilities & CAP_EXTENDED_SECURITY) {
54                 const DATA_BLOB *b = smbXcli_conn_server_gss_blob(c);
55                 if (b) {
56                         n->secblob = *b;
57                 }
58         } else {
59                 const uint8_t *p = smb1cli_conn_server_challenge(c);
60                 if (p) {
61                         n->secblob = data_blob_const(p, 8);
62                 }
63         }
64
65         n->readbraw_supported = smb1cli_conn_server_readbraw(c);
66         n->readbraw_supported = smb1cli_conn_server_writebraw(c);
67         n->lockread_supported = smb1cli_conn_server_lockread(c);
68
69         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 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         struct tevent_req *req;
85         struct smb_raw_negotiate_state *state;
86         struct tevent_req *subreq;
87         uint32_t timeout_msec = transport->options.request_timeout * 1000;
88
89         req = tevent_req_create(mem_ctx, &state,
90                                 struct smb_raw_negotiate_state);;
91         if (req == NULL) {
92                 return NULL;
93         }
94         state->transport = transport;
95
96         if (maxprotocol > PROTOCOL_NT1) {
97                 maxprotocol = PROTOCOL_NT1;
98         }
99
100         if (minprotocol > maxprotocol) {
101                 minprotocol = maxprotocol;
102         }
103
104         subreq = smbXcli_negprot_send(state, ev,
105                                       transport->conn,
106                                       timeout_msec,
107                                       minprotocol,
108                                       maxprotocol,
109                                       transport->options.max_credits);
110         if (tevent_req_nomem(subreq, req)) {
111                 return tevent_req_post(req, ev);
112         }
113         tevent_req_set_callback(subreq, smb_raw_negotiate_done, req);
114
115         return req;
116 }
117
118 static void smb_raw_negotiate_done(struct tevent_req *subreq)
119 {
120         struct tevent_req *req =
121                 tevent_req_callback_data(subreq,
122                 struct tevent_req);
123         struct smb_raw_negotiate_state *state =
124                 tevent_req_data(req,
125                 struct smb_raw_negotiate_state);
126         NTSTATUS status;
127
128         status = smbXcli_negprot_recv(subreq);
129         TALLOC_FREE(subreq);
130         if (tevent_req_nterror(req, status)) {
131                 return;
132         }
133
134         status = smb_raw_negotiate_fill_transport(state->transport);
135         if (tevent_req_nterror(req, status)) {
136                 return;
137         }
138
139         tevent_req_done(req);
140 }
141
142 /*
143  Send a negprot command.
144 */
145 NTSTATUS smb_raw_negotiate_recv(struct tevent_req *req)
146 {
147         return tevent_req_simple_recv_ntstatus(req);
148 }
149
150
151 /*
152  Send a negprot command (sync interface)
153 */
154 NTSTATUS smb_raw_negotiate(struct smbcli_transport *transport, bool unicode,
155                            int minprotocol, int maxprotocol)
156 {
157         NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
158         struct tevent_req *subreq = NULL;
159         bool ok;
160
161         subreq = smb_raw_negotiate_send(transport,
162                                         transport->ev,
163                                         transport,
164                                         minprotocol,
165                                         maxprotocol);
166         if (subreq == NULL) {
167                 return NT_STATUS_NO_MEMORY;
168         }
169
170         ok = tevent_req_poll(subreq, transport->ev);
171         if (!ok) {
172                 status = map_nt_error_from_unix_common(errno);
173                 goto failed;
174         }
175
176         status = smb_raw_negotiate_recv(subreq);
177
178 failed:
179         TALLOC_FREE(subreq);
180         return status;
181 }