r4951: some of the code dealing with libcli was getting too complex trying to
[jelmer/samba4-debian.git] / source / 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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "libcli/raw/libcliraw.h"
25 #include "auth/auth.h"
26
27 #define SETUP_REQUEST_SESSION(cmd, wct, buflen) do { \
28         req = smbcli_request_setup_session(session, cmd, wct, buflen); \
29         if (!req) return NULL; \
30 } while (0)
31
32
33 /****************************************************************************
34  Initialize the session context
35 ****************************************************************************/
36 struct smbcli_session *smbcli_session_init(struct smbcli_transport *transport, 
37                                            TALLOC_CTX *parent_ctx, BOOL primary)
38 {
39         struct smbcli_session *session;
40         uint16_t flags2;
41         uint32_t capabilities;
42
43         session = talloc_zero(parent_ctx, struct smbcli_session);
44         if (!session) {
45                 return NULL;
46         }
47
48         if (primary) {
49                 session->transport = talloc_steal(session, transport);
50         } else {
51                 session->transport = talloc_reference(session, transport);
52         }
53         session->pid = (uint16_t)getpid();
54         session->vuid = UID_FIELD_INVALID;
55         
56         capabilities = transport->negotiate.capabilities;
57
58         flags2 = FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_EXTENDED_ATTRIBUTES;
59
60         if (capabilities & CAP_UNICODE) {
61                 flags2 |= FLAGS2_UNICODE_STRINGS;
62         }
63         if (capabilities & CAP_STATUS32) {
64                 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
65         }
66         if (capabilities & CAP_EXTENDED_SECURITY) {
67                 flags2 |= FLAGS2_EXTENDED_SECURITY;
68         }
69         if (session->transport->negotiate.sign_info.doing_signing) {
70                 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
71         }
72
73         session->flags2 = flags2;
74
75         return session;
76 }
77
78 /****************************************************************************
79  Perform a session setup (async send)
80 ****************************************************************************/
81 struct smbcli_request *smb_raw_session_setup_send(struct smbcli_session *session, 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.domain, STR_TERMINATE);
138                 break;
139         }
140
141         if (!smbcli_request_send(req)) {
142                 smbcli_request_destroy(req);
143                 return NULL;
144         }
145
146         return req;
147 }
148
149
150 /****************************************************************************
151  Perform a session setup (async recv)
152 ****************************************************************************/
153 NTSTATUS smb_raw_session_setup_recv(struct smbcli_request *req, 
154                                     TALLOC_CTX *mem_ctx, 
155                                     union smb_sesssetup *parms) 
156 {
157         uint16_t len;
158         uint8_t *p;
159
160         if (!smbcli_request_receive(req)) {
161                 return smbcli_request_destroy(req);
162         }
163         
164         if (!NT_STATUS_IS_OK(req->status) &&
165             !NT_STATUS_EQUAL(req->status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
166                 return smbcli_request_destroy(req);
167         }
168
169         switch (parms->old.level) {
170         case RAW_SESSSETUP_OLD:
171                 SMBCLI_CHECK_WCT(req, 3);
172                 ZERO_STRUCT(parms->old.out);
173                 parms->old.out.vuid = SVAL(req->in.hdr, HDR_UID);
174                 parms->old.out.action = SVAL(req->in.vwv, VWV(2));
175                 p = req->in.data;
176                 if (p) {
177                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
178                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
179                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE);
180                 }
181                 break;
182
183         case RAW_SESSSETUP_NT1:
184                 SMBCLI_CHECK_WCT(req, 3);
185                 ZERO_STRUCT(parms->nt1.out);
186                 parms->nt1.out.vuid   = SVAL(req->in.hdr, HDR_UID);
187                 parms->nt1.out.action = SVAL(req->in.vwv, VWV(2));
188                 p = req->in.data;
189                 if (p) {
190                         p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
191                         p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
192                         if (p < (req->in.data + req->in.data_size)) {
193                                 p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE);
194                         }
195                 }
196                 break;
197
198         case RAW_SESSSETUP_SPNEGO:
199                 SMBCLI_CHECK_WCT(req, 4);
200                 ZERO_STRUCT(parms->spnego.out);
201                 parms->spnego.out.vuid   = SVAL(req->in.hdr, HDR_UID);
202                 parms->spnego.out.action = SVAL(req->in.vwv, VWV(2));
203                 len                      = SVAL(req->in.vwv, VWV(3));
204                 p = req->in.data;
205                 if (!p) {
206                         break;
207                 }
208
209                 parms->spnego.out.secblob = smbcli_req_pull_blob(req, mem_ctx, p, len);
210                 p += parms->spnego.out.secblob.length;
211                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
212                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
213                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.domain, p, -1, STR_TERMINATE);
214                 break;
215         }
216
217 failed:
218         return smbcli_request_destroy(req);
219 }
220
221
222 /*
223  Perform a session setup (sync interface)
224 */
225 NTSTATUS smb_raw_session_setup(struct smbcli_session *session, TALLOC_CTX *mem_ctx, 
226                                union smb_sesssetup *parms) 
227 {
228         struct smbcli_request *req = smb_raw_session_setup_send(session, parms);
229         return smb_raw_session_setup_recv(req, mem_ctx, parms);
230 }
231
232
233 /****************************************************************************
234  Send a uloggoff (async send)
235 *****************************************************************************/
236 struct smbcli_request *smb_raw_ulogoff_send(struct smbcli_session *session)
237 {
238         struct smbcli_request *req;
239
240         SETUP_REQUEST_SESSION(SMBulogoffX, 2, 0);
241
242         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
243         SSVAL(req->out.vwv, VWV(1), 0);
244
245         if (!smbcli_request_send(req)) {
246                 smbcli_request_destroy(req);
247                 return NULL;
248         }
249
250         return req;
251 }
252
253 /****************************************************************************
254  Send a uloggoff (sync interface)
255 *****************************************************************************/
256 NTSTATUS smb_raw_ulogoff(struct smbcli_session *session)
257 {
258         struct smbcli_request *req = smb_raw_ulogoff_send(session);
259         return smbcli_request_simple_recv(req);
260 }
261
262
263 /****************************************************************************
264  Send a exit (async send)
265 *****************************************************************************/
266 struct smbcli_request *smb_raw_exit_send(struct smbcli_session *session)
267 {
268         struct smbcli_request *req;
269
270         SETUP_REQUEST_SESSION(SMBexit, 0, 0);
271
272         if (!smbcli_request_send(req)) {
273                 smbcli_request_destroy(req);
274                 return NULL;
275         }
276
277         return req;
278 }
279
280 /****************************************************************************
281  Send a exit (sync interface)
282 *****************************************************************************/
283 NTSTATUS smb_raw_exit(struct smbcli_session *session)
284 {
285         struct smbcli_request *req = smb_raw_exit_send(session);
286         return smbcli_request_simple_recv(req);
287 }