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