Merge commit 'release-4-0-0alpha1' into v4-0-test
[kai/samba.git] / source4 / libcli / raw / clisession.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB client session context management functions
4
5    Copyright (C) Andrew Tridgell 1994-2005
6    Copyright (C) James Myers 2003 <myersjj@samba.org>
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "system/filesys.h"
25
26 #define SETUP_REQUEST_SESSION(cmd, wct, buflen) do { \
27         req = smbcli_request_setup_session(session, cmd, wct, buflen); \
28         if (!req) return NULL; \
29 } while (0)
30
31
32 /****************************************************************************
33  Initialize the session context
34 ****************************************************************************/
35 struct smbcli_session *smbcli_session_init(struct smbcli_transport *transport, 
36                                            TALLOC_CTX *parent_ctx, bool primary)
37 {
38         struct smbcli_session *session;
39         uint16_t flags2;
40         uint32_t capabilities;
41
42         session = talloc_zero(parent_ctx, struct smbcli_session);
43         if (!session) {
44                 return NULL;
45         }
46
47         if (primary) {
48                 session->transport = talloc_steal(session, transport);
49         } else {
50                 session->transport = talloc_reference(session, transport);
51         }
52         session->pid = (uint16_t)getpid();
53         session->vuid = UID_FIELD_INVALID;
54         
55         capabilities = transport->negotiate.capabilities;
56
57         flags2 = FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_EXTENDED_ATTRIBUTES;
58
59         if (capabilities & CAP_UNICODE) {
60                 flags2 |= FLAGS2_UNICODE_STRINGS;
61         }
62         if (capabilities & CAP_STATUS32) {
63                 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
64         }
65         if (capabilities & CAP_EXTENDED_SECURITY) {
66                 flags2 |= FLAGS2_EXTENDED_SECURITY;
67         }
68         if (session->transport->negotiate.sign_info.doing_signing) {
69                 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
70         }
71
72         session->flags2 = flags2;
73
74         return session;
75 }
76
77 /****************************************************************************
78  Perform a session setup (async send)
79 ****************************************************************************/
80 struct smbcli_request *smb_raw_sesssetup_send(struct smbcli_session *session, 
81                                               union smb_sesssetup *parms) 
82 {
83         struct smbcli_request *req = NULL;
84
85         switch (parms->old.level) {
86         case RAW_SESSSETUP_OLD:
87                 SETUP_REQUEST_SESSION(SMBsesssetupX, 10, 0);
88                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
89                 SSVAL(req->out.vwv, VWV(1), 0);
90                 SSVAL(req->out.vwv,VWV(2),parms->old.in.bufsize);
91                 SSVAL(req->out.vwv,VWV(3),parms->old.in.mpx_max);
92                 SSVAL(req->out.vwv,VWV(4),parms->old.in.vc_num);
93                 SIVAL(req->out.vwv,VWV(5),parms->old.in.sesskey);
94                 SSVAL(req->out.vwv,VWV(7),parms->old.in.password.length);
95                 SIVAL(req->out.vwv,VWV(8), 0); /* reserved */
96                 smbcli_req_append_blob(req, &parms->old.in.password);
97                 smbcli_req_append_string(req, parms->old.in.user, STR_TERMINATE);
98                 smbcli_req_append_string(req, parms->old.in.domain, STR_TERMINATE|STR_UPPER);
99                 smbcli_req_append_string(req, parms->old.in.os, STR_TERMINATE);
100                 smbcli_req_append_string(req, parms->old.in.lanman, STR_TERMINATE);
101                 break;
102
103         case RAW_SESSSETUP_NT1:
104                 SETUP_REQUEST_SESSION(SMBsesssetupX, 13, 0);
105                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
106                 SSVAL(req->out.vwv, VWV(1), 0);
107                 SSVAL(req->out.vwv, VWV(2), parms->nt1.in.bufsize);
108                 SSVAL(req->out.vwv, VWV(3), parms->nt1.in.mpx_max);
109                 SSVAL(req->out.vwv, VWV(4), parms->nt1.in.vc_num);
110                 SIVAL(req->out.vwv, VWV(5), parms->nt1.in.sesskey);
111                 SSVAL(req->out.vwv, VWV(7), parms->nt1.in.password1.length);
112                 SSVAL(req->out.vwv, VWV(8), parms->nt1.in.password2.length);
113                 SIVAL(req->out.vwv, VWV(9), 0); /* reserved */
114                 SIVAL(req->out.vwv, VWV(11), parms->nt1.in.capabilities);
115                 smbcli_req_append_blob(req, &parms->nt1.in.password1);
116                 smbcli_req_append_blob(req, &parms->nt1.in.password2);
117                 smbcli_req_append_string(req, parms->nt1.in.user, STR_TERMINATE);
118                 smbcli_req_append_string(req, parms->nt1.in.domain, STR_TERMINATE|STR_UPPER);
119                 smbcli_req_append_string(req, parms->nt1.in.os, STR_TERMINATE);
120                 smbcli_req_append_string(req, parms->nt1.in.lanman, STR_TERMINATE);
121                 break;
122
123         case RAW_SESSSETUP_SPNEGO:
124                 SETUP_REQUEST_SESSION(SMBsesssetupX, 12, 0);
125                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
126                 SSVAL(req->out.vwv, VWV(1), 0);
127                 SSVAL(req->out.vwv, VWV(2), parms->spnego.in.bufsize);
128                 SSVAL(req->out.vwv, VWV(3), parms->spnego.in.mpx_max);
129                 SSVAL(req->out.vwv, VWV(4), parms->spnego.in.vc_num);
130                 SIVAL(req->out.vwv, VWV(5), parms->spnego.in.sesskey);
131                 SSVAL(req->out.vwv, VWV(7), parms->spnego.in.secblob.length);
132                 SIVAL(req->out.vwv, VWV(8), 0); /* reserved */
133                 SIVAL(req->out.vwv, VWV(10), parms->spnego.in.capabilities);
134                 smbcli_req_append_blob(req, &parms->spnego.in.secblob);
135                 smbcli_req_append_string(req, parms->spnego.in.os, STR_TERMINATE);
136                 smbcli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE);
137                 smbcli_req_append_string(req, parms->spnego.in.workgroup, STR_TERMINATE);
138                 break;
139
140         case RAW_SESSSETUP_SMB2:
141                 return NULL;
142         }
143
144         if (!smbcli_request_send(req)) {
145                 smbcli_request_destroy(req);
146                 return NULL;
147         }
148
149         return req;
150 }
151
152
153 /****************************************************************************
154  Perform a session setup (async recv)
155 ****************************************************************************/
156 NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req, 
157                                 TALLOC_CTX *mem_ctx, 
158                                 union smb_sesssetup *parms) 
159 {
160         uint16_t len;
161         uint8_t *p;
162
163         if (!smbcli_request_receive(req)) {
164                 return smbcli_request_destroy(req);
165         }
166         
167         if (!NT_STATUS_IS_OK(req->status) &&
168             !NT_STATUS_EQUAL(req->status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
169                 return smbcli_request_destroy(req);
170         }
171
172         switch (parms->old.level) {
173         case RAW_SESSSETUP_OLD:
174                 SMBCLI_CHECK_WCT(req, 3);
175                 ZERO_STRUCT(parms->old.out);
176                 parms->old.out.vuid = SVAL(req->in.hdr, HDR_UID);
177                 parms->old.out.action = SVAL(req->in.vwv, VWV(2));
178                 p = req->in.data;
179                 if (p) {
180                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
181                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
182                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE);
183                 }
184                 break;
185
186         case RAW_SESSSETUP_NT1:
187                 SMBCLI_CHECK_WCT(req, 3);
188                 ZERO_STRUCT(parms->nt1.out);
189                 parms->nt1.out.vuid   = SVAL(req->in.hdr, HDR_UID);
190                 parms->nt1.out.action = SVAL(req->in.vwv, VWV(2));
191                 p = req->in.data;
192                 if (p) {
193                         p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
194                         p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
195                         if (p < (req->in.data + req->in.data_size)) {
196                                 p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE);
197                         }
198                 }
199                 break;
200
201         case RAW_SESSSETUP_SPNEGO:
202                 SMBCLI_CHECK_WCT(req, 4);
203                 ZERO_STRUCT(parms->spnego.out);
204                 parms->spnego.out.vuid   = SVAL(req->in.hdr, HDR_UID);
205                 parms->spnego.out.action = SVAL(req->in.vwv, VWV(2));
206                 len                      = SVAL(req->in.vwv, VWV(3));
207                 p = req->in.data;
208                 if (!p) {
209                         break;
210                 }
211
212                 parms->spnego.out.secblob = smbcli_req_pull_blob(req, mem_ctx, p, len);
213                 p += parms->spnego.out.secblob.length;
214                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
215                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
216                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE);
217                 break;
218
219         case RAW_SESSSETUP_SMB2:
220                 req->status = NT_STATUS_INTERNAL_ERROR;
221                 break;
222         }
223
224 failed:
225         return smbcli_request_destroy(req);
226 }
227
228
229 /*
230  Perform a session setup (sync interface)
231 */
232 NTSTATUS smb_raw_sesssetup(struct smbcli_session *session, 
233                            TALLOC_CTX *mem_ctx, union smb_sesssetup *parms) 
234 {
235         struct smbcli_request *req = smb_raw_sesssetup_send(session, parms);
236         return smb_raw_sesssetup_recv(req, mem_ctx, parms);
237 }
238
239
240 /****************************************************************************
241  Send a ulogoff (async send)
242 *****************************************************************************/
243 struct smbcli_request *smb_raw_ulogoff_send(struct smbcli_session *session)
244 {
245         struct smbcli_request *req;
246
247         SETUP_REQUEST_SESSION(SMBulogoffX, 2, 0);
248
249         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
250         SSVAL(req->out.vwv, VWV(1), 0);
251
252         if (!smbcli_request_send(req)) {
253                 smbcli_request_destroy(req);
254                 return NULL;
255         }
256
257         return req;
258 }
259
260 /****************************************************************************
261  Send a ulogoff (sync interface)
262 *****************************************************************************/
263 NTSTATUS smb_raw_ulogoff(struct smbcli_session *session)
264 {
265         struct smbcli_request *req = smb_raw_ulogoff_send(session);
266         return smbcli_request_simple_recv(req);
267 }
268
269
270 /****************************************************************************
271  Send a exit (async send)
272 *****************************************************************************/
273 struct smbcli_request *smb_raw_exit_send(struct smbcli_session *session)
274 {
275         struct smbcli_request *req;
276
277         SETUP_REQUEST_SESSION(SMBexit, 0, 0);
278
279         if (!smbcli_request_send(req)) {
280                 smbcli_request_destroy(req);
281                 return NULL;
282         }
283
284         return req;
285 }
286
287 /****************************************************************************
288  Send a exit (sync interface)
289 *****************************************************************************/
290 NTSTATUS smb_raw_exit(struct smbcli_session *session)
291 {
292         struct smbcli_request *req = smb_raw_exit_send(session);
293         return smbcli_request_simple_recv(req);
294 }