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