r5298: - got rid of pstring.h from includes.h. This at least makes it a bit
[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 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 "system/filesys.h"
26 #include "auth/auth.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 {
40         struct smbcli_session *session;
41         uint16_t flags2;
42         uint32_t capabilities;
43
44         session = talloc_zero(parent_ctx, struct smbcli_session);
45         if (!session) {
46                 return NULL;
47         }
48
49         if (primary) {
50                 session->transport = talloc_steal(session, transport);
51         } else {
52                 session->transport = talloc_reference(session, transport);
53         }
54         session->pid = (uint16_t)getpid();
55         session->vuid = UID_FIELD_INVALID;
56         
57         capabilities = transport->negotiate.capabilities;
58
59         flags2 = FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_EXTENDED_ATTRIBUTES;
60
61         if (capabilities & CAP_UNICODE) {
62                 flags2 |= FLAGS2_UNICODE_STRINGS;
63         }
64         if (capabilities & CAP_STATUS32) {
65                 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
66         }
67         if (capabilities & CAP_EXTENDED_SECURITY) {
68                 flags2 |= FLAGS2_EXTENDED_SECURITY;
69         }
70         if (session->transport->negotiate.sign_info.doing_signing) {
71                 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
72         }
73
74         session->flags2 = flags2;
75
76         return session;
77 }
78
79 /****************************************************************************
80  Perform a session setup (async send)
81 ****************************************************************************/
82 struct smbcli_request *smb_raw_session_setup_send(struct smbcli_session *session, union smb_sesssetup *parms) 
83 {
84         struct smbcli_request *req = NULL;
85
86         switch (parms->old.level) {
87         case RAW_SESSSETUP_OLD:
88                 SETUP_REQUEST_SESSION(SMBsesssetupX, 10, 0);
89                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
90                 SSVAL(req->out.vwv, VWV(1), 0);
91                 SSVAL(req->out.vwv,VWV(2),parms->old.in.bufsize);
92                 SSVAL(req->out.vwv,VWV(3),parms->old.in.mpx_max);
93                 SSVAL(req->out.vwv,VWV(4),parms->old.in.vc_num);
94                 SIVAL(req->out.vwv,VWV(5),parms->old.in.sesskey);
95                 SSVAL(req->out.vwv,VWV(7),parms->old.in.password.length);
96                 SIVAL(req->out.vwv,VWV(8), 0); /* reserved */
97                 smbcli_req_append_blob(req, &parms->old.in.password);
98                 smbcli_req_append_string(req, parms->old.in.user, STR_TERMINATE);
99                 smbcli_req_append_string(req, parms->old.in.domain, STR_TERMINATE|STR_UPPER);
100                 smbcli_req_append_string(req, parms->old.in.os, STR_TERMINATE);
101                 smbcli_req_append_string(req, parms->old.in.lanman, STR_TERMINATE);
102                 break;
103
104         case RAW_SESSSETUP_NT1:
105                 SETUP_REQUEST_SESSION(SMBsesssetupX, 13, 0);
106                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
107                 SSVAL(req->out.vwv, VWV(1), 0);
108                 SSVAL(req->out.vwv, VWV(2), parms->nt1.in.bufsize);
109                 SSVAL(req->out.vwv, VWV(3), parms->nt1.in.mpx_max);
110                 SSVAL(req->out.vwv, VWV(4), parms->nt1.in.vc_num);
111                 SIVAL(req->out.vwv, VWV(5), parms->nt1.in.sesskey);
112                 SSVAL(req->out.vwv, VWV(7), parms->nt1.in.password1.length);
113                 SSVAL(req->out.vwv, VWV(8), parms->nt1.in.password2.length);
114                 SIVAL(req->out.vwv, VWV(9), 0); /* reserved */
115                 SIVAL(req->out.vwv, VWV(11), parms->nt1.in.capabilities);
116                 smbcli_req_append_blob(req, &parms->nt1.in.password1);
117                 smbcli_req_append_blob(req, &parms->nt1.in.password2);
118                 smbcli_req_append_string(req, parms->nt1.in.user, STR_TERMINATE);
119                 smbcli_req_append_string(req, parms->nt1.in.domain, STR_TERMINATE|STR_UPPER);
120                 smbcli_req_append_string(req, parms->nt1.in.os, STR_TERMINATE);
121                 smbcli_req_append_string(req, parms->nt1.in.lanman, STR_TERMINATE);
122                 break;
123
124         case RAW_SESSSETUP_SPNEGO:
125                 SETUP_REQUEST_SESSION(SMBsesssetupX, 12, 0);
126                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
127                 SSVAL(req->out.vwv, VWV(1), 0);
128                 SSVAL(req->out.vwv, VWV(2), parms->spnego.in.bufsize);
129                 SSVAL(req->out.vwv, VWV(3), parms->spnego.in.mpx_max);
130                 SSVAL(req->out.vwv, VWV(4), parms->spnego.in.vc_num);
131                 SIVAL(req->out.vwv, VWV(5), parms->spnego.in.sesskey);
132                 SSVAL(req->out.vwv, VWV(7), parms->spnego.in.secblob.length);
133                 SIVAL(req->out.vwv, VWV(8), 0); /* reserved */
134                 SIVAL(req->out.vwv, VWV(10), parms->spnego.in.capabilities);
135                 smbcli_req_append_blob(req, &parms->spnego.in.secblob);
136                 smbcli_req_append_string(req, parms->spnego.in.os, STR_TERMINATE);
137                 smbcli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE);
138                 smbcli_req_append_string(req, parms->spnego.in.domain, STR_TERMINATE);
139                 break;
140         }
141
142         if (!smbcli_request_send(req)) {
143                 smbcli_request_destroy(req);
144                 return NULL;
145         }
146
147         return req;
148 }
149
150
151 /****************************************************************************
152  Perform a session setup (async recv)
153 ****************************************************************************/
154 NTSTATUS smb_raw_session_setup_recv(struct smbcli_request *req, 
155                                     TALLOC_CTX *mem_ctx, 
156                                     union smb_sesssetup *parms) 
157 {
158         uint16_t len;
159         uint8_t *p;
160
161         if (!smbcli_request_receive(req)) {
162                 return smbcli_request_destroy(req);
163         }
164         
165         if (!NT_STATUS_IS_OK(req->status) &&
166             !NT_STATUS_EQUAL(req->status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
167                 return smbcli_request_destroy(req);
168         }
169
170         switch (parms->old.level) {
171         case RAW_SESSSETUP_OLD:
172                 SMBCLI_CHECK_WCT(req, 3);
173                 ZERO_STRUCT(parms->old.out);
174                 parms->old.out.vuid = SVAL(req->in.hdr, HDR_UID);
175                 parms->old.out.action = SVAL(req->in.vwv, VWV(2));
176                 p = req->in.data;
177                 if (p) {
178                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
179                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
180                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE);
181                 }
182                 break;
183
184         case RAW_SESSSETUP_NT1:
185                 SMBCLI_CHECK_WCT(req, 3);
186                 ZERO_STRUCT(parms->nt1.out);
187                 parms->nt1.out.vuid   = SVAL(req->in.hdr, HDR_UID);
188                 parms->nt1.out.action = SVAL(req->in.vwv, VWV(2));
189                 p = req->in.data;
190                 if (p) {
191                         p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
192                         p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
193                         if (p < (req->in.data + req->in.data_size)) {
194                                 p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE);
195                         }
196                 }
197                 break;
198
199         case RAW_SESSSETUP_SPNEGO:
200                 SMBCLI_CHECK_WCT(req, 4);
201                 ZERO_STRUCT(parms->spnego.out);
202                 parms->spnego.out.vuid   = SVAL(req->in.hdr, HDR_UID);
203                 parms->spnego.out.action = SVAL(req->in.vwv, VWV(2));
204                 len                      = SVAL(req->in.vwv, VWV(3));
205                 p = req->in.data;
206                 if (!p) {
207                         break;
208                 }
209
210                 parms->spnego.out.secblob = smbcli_req_pull_blob(req, mem_ctx, p, len);
211                 p += parms->spnego.out.secblob.length;
212                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
213                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
214                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.domain, p, -1, STR_TERMINATE);
215                 break;
216         }
217
218 failed:
219         return smbcli_request_destroy(req);
220 }
221
222
223 /*
224  Perform a session setup (sync interface)
225 */
226 NTSTATUS smb_raw_session_setup(struct smbcli_session *session, TALLOC_CTX *mem_ctx, 
227                                union smb_sesssetup *parms) 
228 {
229         struct smbcli_request *req = smb_raw_session_setup_send(session, parms);
230         return smb_raw_session_setup_recv(req, mem_ctx, parms);
231 }
232
233
234 /****************************************************************************
235  Send a uloggoff (async send)
236 *****************************************************************************/
237 struct smbcli_request *smb_raw_ulogoff_send(struct smbcli_session *session)
238 {
239         struct smbcli_request *req;
240
241         SETUP_REQUEST_SESSION(SMBulogoffX, 2, 0);
242
243         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
244         SSVAL(req->out.vwv, VWV(1), 0);
245
246         if (!smbcli_request_send(req)) {
247                 smbcli_request_destroy(req);
248                 return NULL;
249         }
250
251         return req;
252 }
253
254 /****************************************************************************
255  Send a uloggoff (sync interface)
256 *****************************************************************************/
257 NTSTATUS smb_raw_ulogoff(struct smbcli_session *session)
258 {
259         struct smbcli_request *req = smb_raw_ulogoff_send(session);
260         return smbcli_request_simple_recv(req);
261 }
262
263
264 /****************************************************************************
265  Send a exit (async send)
266 *****************************************************************************/
267 struct smbcli_request *smb_raw_exit_send(struct smbcli_session *session)
268 {
269         struct smbcli_request *req;
270
271         SETUP_REQUEST_SESSION(SMBexit, 0, 0);
272
273         if (!smbcli_request_send(req)) {
274                 smbcli_request_destroy(req);
275                 return NULL;
276         }
277
278         return req;
279 }
280
281 /****************************************************************************
282  Send a exit (sync interface)
283 *****************************************************************************/
284 NTSTATUS smb_raw_exit(struct smbcli_session *session)
285 {
286         struct smbcli_request *req = smb_raw_exit_send(session);
287         return smbcli_request_simple_recv(req);
288 }