s4:libcli/raw: setup a smbXcli_session for each smbcli_session
[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 "libcli/raw/raw_proto.h"
25 #include "system/filesys.h"
26 #include "../libcli/smb/smbXcli_base.h"
27
28 #define SETUP_REQUEST_SESSION(cmd, wct, buflen) do { \
29         req = smbcli_request_setup_session(session, cmd, wct, buflen); \
30         if (!req) return NULL; \
31 } while (0)
32
33
34 /****************************************************************************
35  Initialize the session context
36 ****************************************************************************/
37 struct smbcli_session *smbcli_session_init(struct smbcli_transport *transport, 
38                                            TALLOC_CTX *parent_ctx, bool primary,
39                                            struct smbcli_session_options options)
40 {
41         struct smbcli_session *session;
42         uint16_t flags2;
43         uint32_t capabilities;
44
45         session = talloc_zero(parent_ctx, struct smbcli_session);
46         if (!session) {
47                 return NULL;
48         }
49
50         if (primary) {
51                 session->transport = talloc_steal(session, transport);
52         } else {
53                 session->transport = talloc_reference(session, transport);
54         }
55         session->pid = (uint16_t)getpid();
56         session->vuid = UID_FIELD_INVALID;
57         session->options = options;
58
59         /*
60          * for now session->vuid is still used by the callers, but we call:
61          * smb1cli_session_set_id(session->smbXcli, session->vuid);
62          * before using session->smbXcli, in future we should remove
63          * session->vuid.
64          */
65         session->smbXcli = smbXcli_session_create(session, transport->conn);
66         if (session->smbXcli == NULL) {
67                 talloc_free(session);
68                 return NULL;
69         }
70
71         capabilities = transport->negotiate.capabilities;
72
73         flags2 = FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_EXTENDED_ATTRIBUTES;
74
75         if (capabilities & CAP_UNICODE) {
76                 flags2 |= FLAGS2_UNICODE_STRINGS;
77         }
78         if (capabilities & CAP_STATUS32) {
79                 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
80         }
81         if (capabilities & CAP_EXTENDED_SECURITY) {
82                 flags2 |= FLAGS2_EXTENDED_SECURITY;
83         }
84         if (smb1cli_conn_signing_is_active(session->transport->conn)) {
85                 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
86         }
87
88         session->flags2 = flags2;
89
90         return session;
91 }
92
93 /****************************************************************************
94  Perform a session setup (async send)
95 ****************************************************************************/
96 struct smbcli_request *smb_raw_sesssetup_send(struct smbcli_session *session, 
97                                               union smb_sesssetup *parms) 
98 {
99         struct smbcli_request *req = NULL;
100
101         switch (parms->old.level) {
102         case RAW_SESSSETUP_OLD:
103                 SETUP_REQUEST_SESSION(SMBsesssetupX, 10, 0);
104                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
105                 SSVAL(req->out.vwv, VWV(1), 0);
106                 SSVAL(req->out.vwv,VWV(2),parms->old.in.bufsize);
107                 SSVAL(req->out.vwv,VWV(3),parms->old.in.mpx_max);
108                 SSVAL(req->out.vwv,VWV(4),parms->old.in.vc_num);
109                 SIVAL(req->out.vwv,VWV(5),parms->old.in.sesskey);
110                 SSVAL(req->out.vwv,VWV(7),parms->old.in.password.length);
111                 SIVAL(req->out.vwv,VWV(8), 0); /* reserved */
112                 smbcli_req_append_blob(req, &parms->old.in.password);
113                 smbcli_req_append_string(req, parms->old.in.user, STR_TERMINATE);
114                 smbcli_req_append_string(req, parms->old.in.domain, STR_TERMINATE|STR_UPPER);
115                 smbcli_req_append_string(req, parms->old.in.os, STR_TERMINATE);
116                 smbcli_req_append_string(req, parms->old.in.lanman, STR_TERMINATE);
117                 break;
118
119         case RAW_SESSSETUP_NT1:
120                 SETUP_REQUEST_SESSION(SMBsesssetupX, 13, 0);
121                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
122                 SSVAL(req->out.vwv, VWV(1), 0);
123                 SSVAL(req->out.vwv, VWV(2), parms->nt1.in.bufsize);
124                 SSVAL(req->out.vwv, VWV(3), parms->nt1.in.mpx_max);
125                 SSVAL(req->out.vwv, VWV(4), parms->nt1.in.vc_num);
126                 SIVAL(req->out.vwv, VWV(5), parms->nt1.in.sesskey);
127                 SSVAL(req->out.vwv, VWV(7), parms->nt1.in.password1.length);
128                 SSVAL(req->out.vwv, VWV(8), parms->nt1.in.password2.length);
129                 SIVAL(req->out.vwv, VWV(9), 0); /* reserved */
130                 SIVAL(req->out.vwv, VWV(11), parms->nt1.in.capabilities);
131                 smbcli_req_append_blob(req, &parms->nt1.in.password1);
132                 smbcli_req_append_blob(req, &parms->nt1.in.password2);
133                 smbcli_req_append_string(req, parms->nt1.in.user, STR_TERMINATE);
134                 smbcli_req_append_string(req, parms->nt1.in.domain, STR_TERMINATE|STR_UPPER);
135                 smbcli_req_append_string(req, parms->nt1.in.os, STR_TERMINATE);
136                 smbcli_req_append_string(req, parms->nt1.in.lanman, STR_TERMINATE);
137                 break;
138
139         case RAW_SESSSETUP_SPNEGO:
140                 SETUP_REQUEST_SESSION(SMBsesssetupX, 12, 0);
141                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
142                 SSVAL(req->out.vwv, VWV(1), 0);
143                 SSVAL(req->out.vwv, VWV(2), parms->spnego.in.bufsize);
144                 SSVAL(req->out.vwv, VWV(3), parms->spnego.in.mpx_max);
145                 SSVAL(req->out.vwv, VWV(4), parms->spnego.in.vc_num);
146                 SIVAL(req->out.vwv, VWV(5), parms->spnego.in.sesskey);
147                 SSVAL(req->out.vwv, VWV(7), parms->spnego.in.secblob.length);
148                 SIVAL(req->out.vwv, VWV(8), 0); /* reserved */
149                 SIVAL(req->out.vwv, VWV(10), parms->spnego.in.capabilities);
150                 smbcli_req_append_blob(req, &parms->spnego.in.secblob);
151                 smbcli_req_append_string(req, parms->spnego.in.os, STR_TERMINATE);
152                 smbcli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE);
153                 smbcli_req_append_string(req, parms->spnego.in.workgroup, STR_TERMINATE);
154                 break;
155
156         case RAW_SESSSETUP_SMB2:
157                 return NULL;
158         }
159
160         if (!smbcli_request_send(req)) {
161                 smbcli_request_destroy(req);
162                 return NULL;
163         }
164
165         return req;
166 }
167
168
169 /****************************************************************************
170  Perform a session setup (async recv)
171 ****************************************************************************/
172 NTSTATUS smb_raw_sesssetup_recv(struct smbcli_request *req, 
173                                 TALLOC_CTX *mem_ctx, 
174                                 union smb_sesssetup *parms) 
175 {
176         uint16_t len;
177         uint8_t *p;
178
179         if (!smbcli_request_receive(req)) {
180                 return smbcli_request_destroy(req);
181         }
182         
183         if (!NT_STATUS_IS_OK(req->status) &&
184             !NT_STATUS_EQUAL(req->status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
185                 return smbcli_request_destroy(req);
186         }
187
188         switch (parms->old.level) {
189         case RAW_SESSSETUP_OLD:
190                 SMBCLI_CHECK_WCT(req, 3);
191                 ZERO_STRUCT(parms->old.out);
192                 parms->old.out.vuid = SVAL(req->in.hdr, HDR_UID);
193                 parms->old.out.action = SVAL(req->in.vwv, VWV(2));
194                 p = req->in.data;
195                 if (p) {
196                         p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
197                         p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
198                         p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE);
199                 }
200                 break;
201
202         case RAW_SESSSETUP_NT1:
203                 SMBCLI_CHECK_WCT(req, 3);
204                 ZERO_STRUCT(parms->nt1.out);
205                 parms->nt1.out.vuid   = SVAL(req->in.hdr, HDR_UID);
206                 parms->nt1.out.action = SVAL(req->in.vwv, VWV(2));
207                 p = req->in.data;
208                 if (p) {
209                         p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
210                         p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
211                         if (p < (req->in.data + req->in.data_size)) {
212                                 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE);
213                         }
214                 }
215                 break;
216
217         case RAW_SESSSETUP_SPNEGO:
218                 SMBCLI_CHECK_WCT(req, 4);
219                 ZERO_STRUCT(parms->spnego.out);
220                 parms->spnego.out.vuid   = SVAL(req->in.hdr, HDR_UID);
221                 parms->spnego.out.action = SVAL(req->in.vwv, VWV(2));
222                 len                      = SVAL(req->in.vwv, VWV(3));
223                 p = req->in.data;
224                 if (!p) {
225                         break;
226                 }
227
228                 parms->spnego.out.secblob = smbcli_req_pull_blob(&req->in.bufinfo, mem_ctx, p, len);
229                 p += parms->spnego.out.secblob.length;
230                 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
231                 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
232                 p += smbcli_req_pull_string(&req->in.bufinfo, mem_ctx, &parms->spnego.out.workgroup, p, -1, STR_TERMINATE);
233                 break;
234
235         case RAW_SESSSETUP_SMB2:
236                 req->status = NT_STATUS_INTERNAL_ERROR;
237                 break;
238         }
239
240 failed:
241         return smbcli_request_destroy(req);
242 }
243
244
245 /*
246  Perform a session setup (sync interface)
247 */
248 NTSTATUS smb_raw_sesssetup(struct smbcli_session *session, 
249                            TALLOC_CTX *mem_ctx, union smb_sesssetup *parms) 
250 {
251         struct smbcli_request *req = smb_raw_sesssetup_send(session, parms);
252         return smb_raw_sesssetup_recv(req, mem_ctx, parms);
253 }
254
255
256 /****************************************************************************
257  Send a ulogoff (async send)
258 *****************************************************************************/
259 struct smbcli_request *smb_raw_ulogoff_send(struct smbcli_session *session)
260 {
261         struct smbcli_request *req;
262
263         SETUP_REQUEST_SESSION(SMBulogoffX, 2, 0);
264
265         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
266         SSVAL(req->out.vwv, VWV(1), 0);
267
268         if (!smbcli_request_send(req)) {
269                 smbcli_request_destroy(req);
270                 return NULL;
271         }
272
273         return req;
274 }
275
276 /****************************************************************************
277  Send a ulogoff (sync interface)
278 *****************************************************************************/
279 NTSTATUS smb_raw_ulogoff(struct smbcli_session *session)
280 {
281         struct smbcli_request *req = smb_raw_ulogoff_send(session);
282         return smbcli_request_simple_recv(req);
283 }
284
285
286 /****************************************************************************
287  Send a exit (async send)
288 *****************************************************************************/
289 struct smbcli_request *smb_raw_exit_send(struct smbcli_session *session)
290 {
291         struct smbcli_request *req;
292
293         SETUP_REQUEST_SESSION(SMBexit, 0, 0);
294
295         if (!smbcli_request_send(req)) {
296                 smbcli_request_destroy(req);
297                 return NULL;
298         }
299
300         return req;
301 }
302
303 /****************************************************************************
304  Send a exit (sync interface)
305 *****************************************************************************/
306 _PUBLIC_ NTSTATUS smb_raw_exit(struct smbcli_session *session)
307 {
308         struct smbcli_request *req = smb_raw_exit_send(session);
309         return smbcli_request_simple_recv(req);
310 }