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