46236217ea543b03f613ca3025626c24f461bf0d
[gd/samba-autobuild/.git] / source4 / libcli / raw / clisession.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB client session context management functions
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) James Myers 2003 <myersjj@samba.org>
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "includes.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "auth/auth.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 {
37         struct smbcli_session *session;
38         uint16_t flags2;
39         uint32_t capabilities;
40
41         session = talloc_zero(transport, struct smbcli_session);
42         if (!session) {
43                 return NULL;
44         }
45
46         session->transport = talloc_reference(session, transport);
47         session->pid = (uint16_t)getpid();
48         session->vuid = UID_FIELD_INVALID;
49         
50         capabilities = transport->negotiate.capabilities;
51
52         flags2 = FLAGS2_LONG_PATH_COMPONENTS | FLAGS2_EXTENDED_ATTRIBUTES;
53
54         if (capabilities & CAP_UNICODE) {
55                 flags2 |= FLAGS2_UNICODE_STRINGS;
56         }
57         if (capabilities & CAP_STATUS32) {
58                 flags2 |= FLAGS2_32_BIT_ERROR_CODES;
59         }
60         if (capabilities & CAP_EXTENDED_SECURITY) {
61                 flags2 |= FLAGS2_EXTENDED_SECURITY;
62         }
63         if (session->transport->negotiate.sign_info.doing_signing) {
64                 flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
65         }
66
67         session->flags2 = flags2;
68
69         return session;
70 }
71
72 /****************************************************************************
73  Perform a session setup (async send)
74 ****************************************************************************/
75 struct smbcli_request *smb_raw_session_setup_send(struct smbcli_session *session, union smb_sesssetup *parms) 
76 {
77         struct smbcli_request *req = NULL;
78
79         switch (parms->generic.level) {
80         case RAW_SESSSETUP_GENERIC:
81                 /* handled elsewhere */
82                 return NULL;
83
84         case RAW_SESSSETUP_OLD:
85                 SETUP_REQUEST_SESSION(SMBsesssetupX, 10, 0);
86                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
87                 SSVAL(req->out.vwv, VWV(1), 0);
88                 SSVAL(req->out.vwv,VWV(2),parms->old.in.bufsize);
89                 SSVAL(req->out.vwv,VWV(3),parms->old.in.mpx_max);
90                 SSVAL(req->out.vwv,VWV(4),parms->old.in.vc_num);
91                 SIVAL(req->out.vwv,VWV(5),parms->old.in.sesskey);
92                 SSVAL(req->out.vwv,VWV(7),parms->old.in.password.length);
93                 SIVAL(req->out.vwv,VWV(8), 0); /* reserved */
94                 smbcli_req_append_blob(req, &parms->old.in.password);
95                 smbcli_req_append_string(req, parms->old.in.user, STR_TERMINATE);
96                 smbcli_req_append_string(req, parms->old.in.domain, STR_TERMINATE|STR_UPPER);
97                 smbcli_req_append_string(req, parms->old.in.os, STR_TERMINATE);
98                 smbcli_req_append_string(req, parms->old.in.lanman, STR_TERMINATE);
99                 break;
100
101         case RAW_SESSSETUP_NT1:
102                 SETUP_REQUEST_SESSION(SMBsesssetupX, 13, 0);
103                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
104                 SSVAL(req->out.vwv, VWV(1), 0);
105                 SSVAL(req->out.vwv, VWV(2), parms->nt1.in.bufsize);
106                 SSVAL(req->out.vwv, VWV(3), parms->nt1.in.mpx_max);
107                 SSVAL(req->out.vwv, VWV(4), parms->nt1.in.vc_num);
108                 SIVAL(req->out.vwv, VWV(5), parms->nt1.in.sesskey);
109                 SSVAL(req->out.vwv, VWV(7), parms->nt1.in.password1.length);
110                 SSVAL(req->out.vwv, VWV(8), parms->nt1.in.password2.length);
111                 SIVAL(req->out.vwv, VWV(9), 0); /* reserved */
112                 SIVAL(req->out.vwv, VWV(11), parms->nt1.in.capabilities);
113                 smbcli_req_append_blob(req, &parms->nt1.in.password1);
114                 smbcli_req_append_blob(req, &parms->nt1.in.password2);
115                 smbcli_req_append_string(req, parms->nt1.in.user, STR_TERMINATE);
116                 smbcli_req_append_string(req, parms->nt1.in.domain, STR_TERMINATE|STR_UPPER);
117                 smbcli_req_append_string(req, parms->nt1.in.os, STR_TERMINATE);
118                 smbcli_req_append_string(req, parms->nt1.in.lanman, STR_TERMINATE);
119                 break;
120
121         case RAW_SESSSETUP_SPNEGO:
122                 SETUP_REQUEST_SESSION(SMBsesssetupX, 12, 0);
123                 SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
124                 SSVAL(req->out.vwv, VWV(1), 0);
125                 SSVAL(req->out.vwv, VWV(2), parms->spnego.in.bufsize);
126                 SSVAL(req->out.vwv, VWV(3), parms->spnego.in.mpx_max);
127                 SSVAL(req->out.vwv, VWV(4), parms->spnego.in.vc_num);
128                 SIVAL(req->out.vwv, VWV(5), parms->spnego.in.sesskey);
129                 SSVAL(req->out.vwv, VWV(7), parms->spnego.in.secblob.length);
130                 SIVAL(req->out.vwv, VWV(8), 0); /* reserved */
131                 SIVAL(req->out.vwv, VWV(10), parms->spnego.in.capabilities);
132                 smbcli_req_append_blob(req, &parms->spnego.in.secblob);
133                 smbcli_req_append_string(req, parms->spnego.in.os, STR_TERMINATE);
134                 smbcli_req_append_string(req, parms->spnego.in.lanman, STR_TERMINATE);
135                 smbcli_req_append_string(req, parms->spnego.in.domain, STR_TERMINATE);
136                 break;
137         }
138
139         if (!smbcli_request_send(req)) {
140                 smbcli_request_destroy(req);
141                 return NULL;
142         }
143
144         return req;
145 }
146
147
148 /****************************************************************************
149  Perform a session setup (async recv)
150 ****************************************************************************/
151 NTSTATUS smb_raw_session_setup_recv(struct smbcli_request *req, 
152                                     TALLOC_CTX *mem_ctx, 
153                                     union smb_sesssetup *parms) 
154 {
155         uint16_t len;
156         uint8_t *p;
157
158         if (!smbcli_request_receive(req)) {
159                 return smbcli_request_destroy(req);
160         }
161         
162         if (!NT_STATUS_IS_OK(req->status) &&
163             !NT_STATUS_EQUAL(req->status,NT_STATUS_MORE_PROCESSING_REQUIRED)) {
164                 return smbcli_request_destroy(req);
165         }
166
167         switch (parms->generic.level) {
168         case RAW_SESSSETUP_GENERIC:
169                 /* handled elsewhere */
170                 return NT_STATUS_INVALID_LEVEL;
171
172         case RAW_SESSSETUP_OLD:
173                 SMBCLI_CHECK_WCT(req, 3);
174                 ZERO_STRUCT(parms->old.out);
175                 parms->old.out.vuid = SVAL(req->in.hdr, HDR_UID);
176                 parms->old.out.action = SVAL(req->in.vwv, VWV(2));
177                 p = req->in.data;
178                 if (p) {
179                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.os, p, -1, STR_TERMINATE);
180                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.lanman, p, -1, STR_TERMINATE);
181                         p += smbcli_req_pull_string(req, mem_ctx, &parms->old.out.domain, p, -1, STR_TERMINATE);
182                 }
183                 break;
184
185         case RAW_SESSSETUP_NT1:
186                 SMBCLI_CHECK_WCT(req, 3);
187                 ZERO_STRUCT(parms->nt1.out);
188                 parms->nt1.out.vuid   = SVAL(req->in.hdr, HDR_UID);
189                 parms->nt1.out.action = SVAL(req->in.vwv, VWV(2));
190                 p = req->in.data;
191                 if (p) {
192                         p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.os, p, -1, STR_TERMINATE);
193                         p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.lanman, p, -1, STR_TERMINATE);
194                         if (p < (req->in.data + req->in.data_size)) {
195                                 p += smbcli_req_pull_string(req, mem_ctx, &parms->nt1.out.domain, p, -1, STR_TERMINATE);
196                         }
197                 }
198                 break;
199
200         case RAW_SESSSETUP_SPNEGO:
201                 SMBCLI_CHECK_WCT(req, 4);
202                 ZERO_STRUCT(parms->spnego.out);
203                 parms->spnego.out.vuid   = SVAL(req->in.hdr, HDR_UID);
204                 parms->spnego.out.action = SVAL(req->in.vwv, VWV(2));
205                 len                      = SVAL(req->in.vwv, VWV(3));
206                 p = req->in.data;
207                 if (!p) {
208                         break;
209                 }
210
211                 parms->spnego.out.secblob = smbcli_req_pull_blob(req, mem_ctx, p, len);
212                 p += parms->spnego.out.secblob.length;
213                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.os, p, -1, STR_TERMINATE);
214                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.lanman, p, -1, STR_TERMINATE);
215                 p += smbcli_req_pull_string(req, mem_ctx, &parms->spnego.out.domain, p, -1, STR_TERMINATE);
216                 break;
217         }
218
219 failed:
220         return smbcli_request_destroy(req);
221 }
222
223 /*
224   form an encrypted lanman password from a plaintext password
225   and the server supplied challenge
226 */
227 static DATA_BLOB lanman_blob(const char *pass, DATA_BLOB challenge)
228 {
229         DATA_BLOB blob = data_blob(NULL, 24);
230         SMBencrypt(pass, challenge.data, blob.data);
231         return blob;
232 }
233
234 /*
235   form an encrypted NT password from a plaintext password
236   and the server supplied challenge
237 */
238 static DATA_BLOB nt_blob(const char *pass, DATA_BLOB challenge)
239 {
240         DATA_BLOB blob = data_blob(NULL, 24);
241         SMBNTencrypt(pass, challenge.data, blob.data);
242         return blob;
243 }
244
245 /*
246   store the user session key for a transport
247 */
248 void smbcli_session_set_user_session_key(struct smbcli_session *session,
249                                    const DATA_BLOB *session_key)
250 {
251         session->user_session_key = data_blob_talloc(session, 
252                                                      session_key->data, 
253                                                      session_key->length);
254 }
255
256 /*
257   setup signing for a NT1 style session setup
258 */
259 void smb_session_use_nt1_session_keys(struct smbcli_session *session, 
260                                       const char *password, const DATA_BLOB *nt_response)
261 {
262         struct smbcli_transport *transport = session->transport; 
263         uint8_t nt_hash[16];
264         DATA_BLOB session_key = data_blob(NULL, 16);
265
266         E_md4hash(password, nt_hash);
267         SMBsesskeygen_ntv1(nt_hash, session_key.data);
268
269         smbcli_transport_simple_set_signing(transport, session_key, *nt_response);
270
271         smbcli_session_set_user_session_key(session, &session_key);
272         data_blob_free(&session_key);
273 }
274
275 /****************************************************************************
276  Perform a session setup (sync interface) using generic interface and the old
277  style sesssetup call
278 ****************************************************************************/
279 static NTSTATUS smb_raw_session_setup_generic_old(struct smbcli_session *session, 
280                                                   TALLOC_CTX *mem_ctx, 
281                                                   union smb_sesssetup *parms) 
282 {
283         NTSTATUS status;
284         union smb_sesssetup s2;
285
286         /* use the old interface */
287         s2.generic.level = RAW_SESSSETUP_OLD;
288         s2.old.in.bufsize = session->transport->options.max_xmit;
289         s2.old.in.mpx_max = session->transport->options.max_mux;
290         s2.old.in.vc_num = 1;
291         s2.old.in.sesskey = parms->generic.in.sesskey;
292         s2.old.in.domain = parms->generic.in.domain;
293         s2.old.in.user = parms->generic.in.user;
294         s2.old.in.os = "Unix";
295         s2.old.in.lanman = "Samba";
296         
297         if (!parms->generic.in.password) {
298                 s2.old.in.password = data_blob(NULL, 0);
299         } else if (session->transport->negotiate.sec_mode & 
300                    NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
301                 s2.old.in.password = lanman_blob(parms->generic.in.password, 
302                                                  session->transport->negotiate.secblob);
303         } else {
304                 s2.old.in.password = data_blob(parms->generic.in.password, 
305                                                strlen(parms->generic.in.password));
306         }
307         
308         status = smb_raw_session_setup(session, mem_ctx, &s2);
309         
310         data_blob_free(&s2.old.in.password);
311         
312         if (!NT_STATUS_IS_OK(status)) {
313                 return status;
314         }
315         
316         parms->generic.out.vuid = s2.old.out.vuid;
317         parms->generic.out.os = s2.old.out.os;
318         parms->generic.out.lanman = s2.old.out.lanman;
319         parms->generic.out.domain = s2.old.out.domain;
320         
321         return NT_STATUS_OK;
322 }
323
324 /****************************************************************************
325  Perform a session setup (sync interface) using generic interface and the NT1
326  style sesssetup call
327 ****************************************************************************/
328 static NTSTATUS smb_raw_session_setup_generic_nt1(struct smbcli_session *session, 
329                                                   TALLOC_CTX *mem_ctx,
330                                                   union smb_sesssetup *parms) 
331 {
332         NTSTATUS status;
333         union smb_sesssetup s2;
334
335         s2.generic.level = RAW_SESSSETUP_NT1;
336         s2.nt1.in.bufsize = session->transport->options.max_xmit;
337         s2.nt1.in.mpx_max = session->transport->options.max_mux;
338         s2.nt1.in.vc_num = 1;
339         s2.nt1.in.sesskey = parms->generic.in.sesskey;
340         s2.nt1.in.capabilities = parms->generic.in.capabilities;
341         s2.nt1.in.domain = parms->generic.in.domain;
342         s2.nt1.in.user = parms->generic.in.user;
343         s2.nt1.in.os = "Unix";
344         s2.nt1.in.lanman = "Samba";
345
346         if (!parms->generic.in.password) {
347                 s2.nt1.in.password1 = data_blob(NULL, 0);
348                 s2.nt1.in.password2 = data_blob(NULL, 0);
349         } else if (session->transport->negotiate.sec_mode & 
350                    NEGOTIATE_SECURITY_CHALLENGE_RESPONSE) {
351                 s2.nt1.in.password1 = lanman_blob(parms->generic.in.password, 
352                                                   session->transport->negotiate.secblob);
353                 s2.nt1.in.password2 = nt_blob(parms->generic.in.password, 
354                                               session->transport->negotiate.secblob);
355                 smb_session_use_nt1_session_keys(session, parms->generic.in.password, &s2.nt1.in.password2);
356
357         } else {
358                 s2.nt1.in.password1 = data_blob(parms->generic.in.password, 
359                                                 strlen(parms->generic.in.password));
360                 s2.nt1.in.password2 = data_blob(NULL, 0);
361         }
362
363         status = smb_raw_session_setup(session, mem_ctx, &s2);
364                 
365         data_blob_free(&s2.nt1.in.password1);
366         data_blob_free(&s2.nt1.in.password2);
367                 
368         if (!NT_STATUS_IS_OK(status)) {
369                 return status;
370         }
371
372         parms->generic.out.vuid = s2.nt1.out.vuid;
373         parms->generic.out.os = s2.nt1.out.os;
374         parms->generic.out.lanman = s2.nt1.out.lanman;
375         parms->generic.out.domain = s2.nt1.out.domain;
376
377         return NT_STATUS_OK;
378 }
379
380 /****************************************************************************
381  Perform a session setup (sync interface) using generic interface and the SPNEGO
382  style sesssetup call
383 ****************************************************************************/
384 static NTSTATUS smb_raw_session_setup_generic_spnego(struct smbcli_session *session, 
385                                                   TALLOC_CTX *mem_ctx,
386                                                   union smb_sesssetup *parms) 
387 {
388         NTSTATUS status;
389         NTSTATUS session_key_err = NT_STATUS_NO_USER_SESSION_KEY;
390         union smb_sesssetup s2;
391         DATA_BLOB session_key = data_blob(NULL, 0);
392         DATA_BLOB null_data_blob = data_blob(NULL, 0);
393         const char *chosen_oid = NULL;
394
395         s2.generic.level = RAW_SESSSETUP_SPNEGO;
396         s2.spnego.in.bufsize = session->transport->options.max_xmit;
397         s2.spnego.in.mpx_max = session->transport->options.max_mux;
398         s2.spnego.in.vc_num = 1;
399         s2.spnego.in.sesskey = parms->generic.in.sesskey;
400         s2.spnego.in.capabilities = parms->generic.in.capabilities;
401         s2.spnego.in.domain = parms->generic.in.domain;
402         s2.spnego.in.os = "Unix";
403         s2.spnego.in.lanman = "Samba";
404         s2.spnego.out.vuid = session->vuid;
405
406         smbcli_temp_set_signing(session->transport);
407
408         status = gensec_client_start(session, &session->gensec);
409         if (!NT_STATUS_IS_OK(status)) {
410                 DEBUG(1, ("Failed to start GENSEC client mode: %s\n", nt_errstr(status)));
411                 return status;
412         }
413
414         gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY);
415
416         status = gensec_set_domain(session->gensec, parms->generic.in.domain);
417         if (!NT_STATUS_IS_OK(status)) {
418                 DEBUG(1, ("Failed to start set GENSEC client domain to %s: %s\n", 
419                           parms->generic.in.domain, nt_errstr(status)));
420                 goto done;
421         }
422
423         status = gensec_set_username(session->gensec, parms->generic.in.user);
424         if (!NT_STATUS_IS_OK(status)) {
425                 DEBUG(1, ("Failed to start set GENSEC client username to %s: %s\n", 
426                           parms->generic.in.user, nt_errstr(status)));
427                 goto done;
428         }
429
430         status = gensec_set_password(session->gensec, parms->generic.in.password);
431         if (!NT_STATUS_IS_OK(status)) {
432                 DEBUG(1, ("Failed to start set GENSEC client password: %s\n", 
433                           nt_errstr(status)));
434                 goto done;
435         }
436
437         status = gensec_set_target_hostname(session->gensec, session->transport->socket->hostname);
438         if (!NT_STATUS_IS_OK(status)) {
439                 DEBUG(1, ("Failed to start set GENSEC target hostname: %s\n", 
440                           nt_errstr(status)));
441                 goto done;
442         }
443
444         if (session->transport->negotiate.secblob.length) {
445                 chosen_oid = GENSEC_OID_SPNEGO;
446         } else {
447                 /* without a sec blob, means raw NTLMSSP */
448                 chosen_oid = GENSEC_OID_NTLMSSP;
449         }
450
451         status = gensec_start_mech_by_oid(session->gensec, chosen_oid);
452         if (!NT_STATUS_IS_OK(status)) {
453                 DEBUG(1, ("Failed to start set GENSEC client SPNEGO mechanism %s: %s\n",
454                           gensec_get_name_by_oid(chosen_oid), nt_errstr(status)));
455                 goto done;
456         }
457         
458         status = gensec_update(session->gensec, mem_ctx,
459                                session->transport->negotiate.secblob,
460                                &s2.spnego.in.secblob);
461
462         while(1) {
463                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) && !NT_STATUS_IS_OK(status)) {
464                         break;
465                 }
466
467                 if (!NT_STATUS_IS_OK(session_key_err)) {
468                         session_key_err = gensec_session_key(session->gensec, &session_key);
469                 }
470                 if (NT_STATUS_IS_OK(session_key_err)) {
471                         smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob);
472                 }
473                 
474                 if (NT_STATUS_IS_OK(status) && s2.spnego.in.secblob.length == 0) {
475                         break;
476                 }
477
478                 session->vuid = s2.spnego.out.vuid;
479                 status = smb_raw_session_setup(session, mem_ctx, &s2);
480                 session->vuid = UID_FIELD_INVALID;
481                 if (!NT_STATUS_IS_OK(status) &&
482                     !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
483                         break;
484                 }
485
486                 status = gensec_update(session->gensec, mem_ctx,
487                                        s2.spnego.out.secblob,
488                                        &s2.spnego.in.secblob);
489
490         }
491
492 done:
493         if (NT_STATUS_IS_OK(status)) {
494                 if (!NT_STATUS_IS_OK(session_key_err)) {
495                         DEBUG(1, ("Failed to get user session key: %s\n", nt_errstr(session_key_err)));
496                         return session_key_err;
497                 }
498
499                 smbcli_session_set_user_session_key(session, &session_key);
500
501                 parms->generic.out.vuid = s2.spnego.out.vuid;
502                 parms->generic.out.os = s2.spnego.out.os;
503                 parms->generic.out.lanman = s2.spnego.out.lanman;
504                 parms->generic.out.domain = s2.spnego.out.domain;
505         } else {
506                 talloc_free(session->gensec);
507                 session->gensec = NULL;
508                 DEBUG(1, ("Failed to login with %s: %s\n", gensec_get_name_by_oid(chosen_oid), nt_errstr(status)));
509                 return status;
510         }
511
512         return status;
513 }
514
515 /****************************************************************************
516  Perform a session setup (sync interface) using generic interface
517 ****************************************************************************/
518 static NTSTATUS smb_raw_session_setup_generic(struct smbcli_session *session, 
519                                               TALLOC_CTX *mem_ctx,
520                                               union smb_sesssetup *parms) 
521 {
522         if (session->transport->negotiate.protocol < PROTOCOL_LANMAN1) {
523                 /* no session setup at all in earliest protocols */
524                 ZERO_STRUCT(parms->generic.out);
525                 return NT_STATUS_OK;
526         }
527
528         /* see if we need to use the original session setup interface */
529         if (session->transport->negotiate.protocol < PROTOCOL_NT1) {
530                 return smb_raw_session_setup_generic_old(session, mem_ctx, parms);
531         }
532
533         /* see if we should use the NT1 interface */
534         if (!session->transport->options.use_spnego ||
535             !(parms->generic.in.capabilities & CAP_EXTENDED_SECURITY)) {
536                 return smb_raw_session_setup_generic_nt1(session, mem_ctx, parms);
537         }
538
539         /* default to using SPNEGO/NTLMSSP */
540         return smb_raw_session_setup_generic_spnego(session, mem_ctx, parms);
541 }
542
543
544 /****************************************************************************
545  Perform a session setup (sync interface)
546 this interface allows for RAW_SESSSETUP_GENERIC to auto-select session
547 setup variant based on negotiated protocol options
548 ****************************************************************************/
549 NTSTATUS smb_raw_session_setup(struct smbcli_session *session, TALLOC_CTX *mem_ctx, 
550                                union smb_sesssetup *parms) 
551 {
552         struct smbcli_request *req;
553
554         if (parms->generic.level == RAW_SESSSETUP_GENERIC) {
555                 NTSTATUS ret = smb_raw_session_setup_generic(session, mem_ctx, parms);
556
557                 if (NT_STATUS_IS_OK(ret) 
558                     && parms->generic.in.user 
559                     && *parms->generic.in.user) {
560                         if (!session->transport->negotiate.sign_info.doing_signing 
561                             && session->transport->negotiate.sign_info.mandatory_signing) {
562                                 DEBUG(0, ("SMB signing required, but server does not support it\n"));
563                                 return NT_STATUS_ACCESS_DENIED;
564                         }
565                 }
566                 return ret;
567         }
568
569         req = smb_raw_session_setup_send(session, parms);
570         return smb_raw_session_setup_recv(req, mem_ctx, parms);
571 }
572
573
574 /****************************************************************************
575  Send a uloggoff (async send)
576 *****************************************************************************/
577 struct smbcli_request *smb_raw_ulogoff_send(struct smbcli_session *session)
578 {
579         struct smbcli_request *req;
580
581         SETUP_REQUEST_SESSION(SMBulogoffX, 2, 0);
582
583         SSVAL(req->out.vwv, VWV(0), SMB_CHAIN_NONE);
584         SSVAL(req->out.vwv, VWV(1), 0);
585
586         if (!smbcli_request_send(req)) {
587                 smbcli_request_destroy(req);
588                 return NULL;
589         }
590
591         return req;
592 }
593
594 /****************************************************************************
595  Send a uloggoff (sync interface)
596 *****************************************************************************/
597 NTSTATUS smb_raw_ulogoff(struct smbcli_session *session)
598 {
599         struct smbcli_request *req = smb_raw_ulogoff_send(session);
600         return smbcli_request_simple_recv(req);
601 }
602
603
604 /****************************************************************************
605  Send a exit (async send)
606 *****************************************************************************/
607 struct smbcli_request *smb_raw_exit_send(struct smbcli_session *session)
608 {
609         struct smbcli_request *req;
610
611         SETUP_REQUEST_SESSION(SMBexit, 0, 0);
612
613         if (!smbcli_request_send(req)) {
614                 smbcli_request_destroy(req);
615                 return NULL;
616         }
617
618         return req;
619 }
620
621 /****************************************************************************
622  Send a exit (sync interface)
623 *****************************************************************************/
624 NTSTATUS smb_raw_exit(struct smbcli_session *session)
625 {
626         struct smbcli_request *req = smb_raw_exit_send(session);
627         return smbcli_request_simple_recv(req);
628 }