s4:libcli/raw: implement on top of smbXcli_conn/req
[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 struct smb_raw_negotiate_state {
32         struct smbcli_transport *transport;
33 };
34
35 static void smb_raw_negotiate_done(struct tevent_req *subreq);
36
37 struct tevent_req *smb_raw_negotiate_send(TALLOC_CTX *mem_ctx,
38                                           struct tevent_context *ev,
39                                           struct smbcli_transport *transport,
40                                           int maxprotocol)
41 {
42         struct tevent_req *req;
43         struct smb_raw_negotiate_state *state;
44         struct tevent_req *subreq;
45         uint32_t timeout_msec = transport->options.request_timeout * 1000;
46
47         req = tevent_req_create(mem_ctx, &state,
48                                 struct smb_raw_negotiate_state);;
49         if (req == NULL) {
50                 return NULL;
51         }
52         state->transport = transport;
53
54         subreq = smbXcli_negprot_send(state, ev,
55                                       transport->conn,
56                                       timeout_msec,
57                                       PROTOCOL_CORE,
58                                       maxprotocol);
59         if (tevent_req_nomem(subreq, req)) {
60                 return tevent_req_post(req, ev);
61         }
62         tevent_req_set_callback(subreq, smb_raw_negotiate_done, req);
63
64         return req;
65 }
66
67 static void smb_raw_negotiate_done(struct tevent_req *subreq)
68 {
69         struct tevent_req *req =
70                 tevent_req_callback_data(subreq,
71                 struct tevent_req);
72         struct smb_raw_negotiate_state *state =
73                 tevent_req_data(req,
74                 struct smb_raw_negotiate_state);
75         struct smbcli_negotiate *n = &state->transport->negotiate;
76         struct smbXcli_conn *c = state->transport->conn;
77         NTSTATUS status;
78         NTTIME ntt;
79
80         status = smbXcli_negprot_recv(subreq);
81         TALLOC_FREE(subreq);
82         if (tevent_req_nterror(req, status)) {
83                 return;
84         }
85
86         n->protocol = smbXcli_conn_protocol(c);
87
88         n->sec_mode = smb1cli_conn_server_security_mode(c);
89         n->max_mux  = smbXcli_conn_max_requests(c);
90         n->max_xmit = smb1cli_conn_max_xmit(c);
91         n->sesskey  = smb1cli_conn_server_session_key(c);
92         n->capabilities = smb1cli_conn_capabilities(c);;
93
94         /* this time arrives in real GMT */
95         ntt = smbXcli_conn_server_system_time(c);
96         n->server_time = nt_time_to_unix(ntt);
97         n->server_zone = smb1cli_conn_server_time_zone(c);
98
99         if (n->capabilities & CAP_EXTENDED_SECURITY) {
100                 const DATA_BLOB *b = smbXcli_conn_server_gss_blob(c);
101                 if (b) {
102                         n->secblob = *b;
103                 }
104         } else {
105                 const uint8_t *p = smb1cli_conn_server_challenge(c);
106                 if (p) {
107                         n->secblob = data_blob_const(p, 8);
108                 }
109         }
110
111         n->readbraw_supported = smb1cli_conn_server_readbraw(c);
112         n->readbraw_supported = smb1cli_conn_server_writebraw(c);
113         n->lockread_supported = smb1cli_conn_server_lockread(c);
114
115         tevent_req_done(req);
116 }
117
118 /*
119  Send a negprot command.
120 */
121 NTSTATUS smb_raw_negotiate_recv(struct tevent_req *req)
122 {
123         return tevent_req_simple_recv_ntstatus(req);
124 }
125
126
127 /*
128  Send a negprot command (sync interface)
129 */
130 NTSTATUS smb_raw_negotiate(struct smbcli_transport *transport, bool unicode, int maxprotocol)
131 {
132         NTSTATUS status = NT_STATUS_INTERNAL_ERROR;
133         struct tevent_req *subreq = NULL;
134         bool ok;
135
136         subreq = smb_raw_negotiate_send(transport,
137                                         transport->ev,
138                                         transport,
139                                         maxprotocol);
140         if (subreq == NULL) {
141                 return NT_STATUS_NO_MEMORY;
142         }
143
144         ok = tevent_req_poll(subreq, transport->ev);
145         if (!ok) {
146                 status = map_nt_error_from_unix_common(errno);
147                 goto failed;
148         }
149
150         status = smb_raw_negotiate_recv(subreq);
151
152 failed:
153         TALLOC_FREE(subreq);
154         return status;
155 }