s3:smbd: remove pending_auth_data logic
[Samba.git] / source3 / smbd / sesssetup.c
blobc70ab17e3c872b7b2fded78a68c5e038432bcb18
1 /*
2 Unix SMB/CIFS implementation.
3 handle SMBsessionsetup
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7 Copyright (C) Luke Howard 2003
8 Copyright (C) Volker Lendecke 2007
9 Copyright (C) Jeremy Allison 2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/spnego.h"
30 #include "../auth/ntlmssp/ntlmssp.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "libads/kerberos_proto.h"
33 #include "../lib/util/asn1.h"
34 #include "auth.h"
35 #include "messages.h"
36 #include "smbprofile.h"
37 #include "../libcli/security/security.h"
38 #include "auth/gensec/gensec.h"
40 /****************************************************************************
41 Add the standard 'Samba' signature to the end of the session setup.
42 ****************************************************************************/
44 static int push_signature(uint8 **outbuf)
46 char *lanman;
47 int result, tmp;
49 result = 0;
51 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
53 if (tmp == -1) return -1;
54 result += tmp;
56 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
57 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
58 SAFE_FREE(lanman);
60 else {
61 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
64 if (tmp == -1) return -1;
65 result += tmp;
67 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
69 if (tmp == -1) return -1;
70 result += tmp;
72 return result;
75 /****************************************************************************
76 Send a security blob via a session setup reply.
77 ****************************************************************************/
79 static void reply_sesssetup_blob(struct smb_request *req,
80 DATA_BLOB blob,
81 NTSTATUS nt_status)
83 if (!NT_STATUS_IS_OK(nt_status) &&
84 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
85 reply_nterror(req, nt_status_squash(nt_status));
86 return;
89 nt_status = nt_status_squash(nt_status);
90 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
91 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
92 SSVAL(req->outbuf, smb_vwv3, blob.length);
94 if ((message_push_blob(&req->outbuf, blob) == -1)
95 || (push_signature(&req->outbuf) == -1)) {
96 reply_nterror(req, NT_STATUS_NO_MEMORY);
100 /****************************************************************************
101 Do a 'guest' logon, getting back the
102 ****************************************************************************/
104 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
105 struct auth_serversupplied_info **server_info)
107 struct auth_context *auth_context;
108 struct auth_usersupplied_info *user_info = NULL;
110 NTSTATUS nt_status;
111 static unsigned char chal[8] = { 0, };
113 DEBUG(3,("Got anonymous request\n"));
115 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
116 if (!NT_STATUS_IS_OK(nt_status)) {
117 return nt_status;
120 if (!make_user_info_guest(remote_address, &user_info)) {
121 TALLOC_FREE(auth_context);
122 return NT_STATUS_NO_MEMORY;
125 nt_status = auth_context->check_ntlm_password(auth_context,
126 user_info,
127 server_info);
128 TALLOC_FREE(auth_context);
129 free_user_info(&user_info);
130 return nt_status;
134 #ifdef HAVE_KRB5
136 #if 0
137 /* Experiment that failed. See "only happens with a KDC" comment below. */
138 /****************************************************************************
139 Cerate a clock skew error blob for a Windows client.
140 ****************************************************************************/
142 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
144 krb5_context context = NULL;
145 krb5_error_code kerr = 0;
146 krb5_data reply;
147 krb5_principal host_princ = NULL;
148 char *host_princ_s = NULL;
149 bool ret = False;
151 *pblob_out = data_blob_null;
153 initialize_krb5_error_table();
154 kerr = krb5_init_context(&context);
155 if (kerr) {
156 return False;
158 /* Create server principal. */
159 asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm());
160 if (!host_princ_s) {
161 goto out;
163 strlower_m(host_princ_s);
165 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
166 if (kerr) {
167 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
168 "for name %s: Error %s\n",
169 host_princ_s, error_message(kerr) ));
170 goto out;
173 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
174 host_princ, &reply);
175 if (kerr) {
176 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
177 "failed: Error %s\n",
178 error_message(kerr) ));
179 goto out;
182 *pblob_out = data_blob(reply.data, reply.length);
183 kerberos_free_data_contents(context,&reply);
184 ret = True;
186 out:
188 if (host_princ_s) {
189 SAFE_FREE(host_princ_s);
191 if (host_princ) {
192 krb5_free_principal(context, host_princ);
194 krb5_free_context(context);
195 return ret;
197 #endif
199 /****************************************************************************
200 Reply to a session setup spnego negotiate packet for kerberos.
201 ****************************************************************************/
203 static void reply_spnego_kerberos(struct smb_request *req,
204 DATA_BLOB *secblob,
205 const char *mechOID,
206 uint16 vuid,
207 bool *p_invalidate_vuid)
209 TALLOC_CTX *mem_ctx;
210 DATA_BLOB ticket;
211 struct passwd *pw;
212 int sess_vuid = req->vuid;
213 NTSTATUS ret = NT_STATUS_OK;
214 DATA_BLOB ap_rep, ap_rep_wrapped, response;
215 struct auth_session_info *session_info = NULL;
216 DATA_BLOB session_key = data_blob_null;
217 uint8 tok_id[2];
218 DATA_BLOB nullblob = data_blob_null;
219 bool map_domainuser_to_guest = False;
220 bool username_was_mapped;
221 struct PAC_LOGON_INFO *logon_info = NULL;
222 struct smbd_server_connection *sconn = req->sconn;
223 char *principal;
224 char *user;
225 char *domain;
226 char *real_username;
228 ZERO_STRUCT(ticket);
229 ZERO_STRUCT(ap_rep);
230 ZERO_STRUCT(ap_rep_wrapped);
231 ZERO_STRUCT(response);
233 /* Normally we will always invalidate the intermediate vuid. */
234 *p_invalidate_vuid = True;
236 mem_ctx = talloc_init("reply_spnego_kerberos");
237 if (mem_ctx == NULL) {
238 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
239 return;
242 if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
243 talloc_destroy(mem_ctx);
244 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
245 return;
248 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
249 &principal, &logon_info, &ap_rep,
250 &session_key, True);
252 data_blob_free(&ticket);
254 if (!NT_STATUS_IS_OK(ret)) {
255 #if 0
256 /* Experiment that failed.
257 * See "only happens with a KDC" comment below. */
259 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
262 * Windows in this case returns
263 * NT_STATUS_MORE_PROCESSING_REQUIRED
264 * with a negTokenTarg blob containing an krb5_error
265 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
266 * The client then fixes its clock and continues rather
267 * than giving an error. JRA.
268 * -- Looks like this only happens with a KDC. JRA.
271 bool ok = make_krb5_skew_error(&ap_rep);
272 if (!ok) {
273 talloc_destroy(mem_ctx);
274 return ERROR_NT(nt_status_squash(
275 NT_STATUS_LOGON_FAILURE));
277 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
278 TOK_ID_KRB_ERROR);
279 response = spnego_gen_auth_response(&ap_rep_wrapped,
280 ret, OID_KERBEROS5_OLD);
281 reply_sesssetup_blob(conn, inbuf, outbuf, response,
282 NT_STATUS_MORE_PROCESSING_REQUIRED);
285 * In this one case we don't invalidate the
286 * intermediate vuid as we're expecting the client
287 * to re-use it for the next sessionsetupX packet. JRA.
290 *p_invalidate_vuid = False;
292 data_blob_free(&ap_rep);
293 data_blob_free(&ap_rep_wrapped);
294 data_blob_free(&response);
295 talloc_destroy(mem_ctx);
296 return -1; /* already replied */
298 #else
299 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
300 ret = NT_STATUS_LOGON_FAILURE;
302 #endif
303 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
304 nt_errstr(ret)));
305 talloc_destroy(mem_ctx);
306 reply_nterror(req, nt_status_squash(ret));
307 return;
310 ret = get_user_from_kerberos_info(talloc_tos(),
311 sconn->remote_hostname,
312 principal, logon_info,
313 &username_was_mapped,
314 &map_domainuser_to_guest,
315 &user, &domain,
316 &real_username, &pw);
317 if (!NT_STATUS_IS_OK(ret)) {
318 data_blob_free(&ap_rep);
319 data_blob_free(&session_key);
320 talloc_destroy(mem_ctx);
321 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
322 return;
325 /* save the PAC data if we have it */
326 if (logon_info) {
327 netsamlogon_cache_store(user, &logon_info->info3);
330 /* setup the string used by %U */
331 sub_set_smb_name(real_username);
333 /* reload services so that the new %U is taken into account */
334 reload_services(sconn, conn_snum_used, true);
336 ret = make_session_info_krb5(mem_ctx,
337 user, domain, real_username, pw,
338 logon_info, map_domainuser_to_guest,
339 username_was_mapped,
340 &session_key,
341 &session_info);
342 data_blob_free(&session_key);
343 if (!NT_STATUS_IS_OK(ret)) {
344 DEBUG(1, ("make_server_info_krb5 failed!\n"));
345 data_blob_free(&ap_rep);
346 TALLOC_FREE(mem_ctx);
347 reply_nterror(req, nt_status_squash(ret));
348 return;
351 if (!is_partial_auth_vuid(sconn, sess_vuid)) {
352 sess_vuid = register_initial_vuid(sconn);
355 /* register_existing_vuid keeps the server info */
356 /* register_existing_vuid takes ownership of session_key on success,
357 * no need to free after this on success. A better interface would copy
358 * it.... */
360 sess_vuid = register_existing_vuid(sconn, sess_vuid,
361 session_info, nullblob);
363 reply_outbuf(req, 4, 0);
364 SSVAL(req->outbuf,smb_uid,sess_vuid);
366 if (sess_vuid == UID_FIELD_INVALID ) {
367 ret = NT_STATUS_LOGON_FAILURE;
368 } else {
369 /* current_user_info is changed on new vuid */
370 reload_services(sconn, conn_snum_used, true);
372 SSVAL(req->outbuf, smb_vwv3, 0);
374 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
375 SSVAL(req->outbuf,smb_vwv2,1);
378 SSVAL(req->outbuf, smb_uid, sess_vuid);
380 /* Successful logon. Keep this vuid. */
381 *p_invalidate_vuid = False;
384 /* wrap that up in a nice GSS-API wrapping */
385 if (NT_STATUS_IS_OK(ret)) {
386 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
387 TOK_ID_KRB_AP_REP);
388 } else {
389 ap_rep_wrapped = data_blob_null;
391 response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
392 mechOID);
393 reply_sesssetup_blob(req, response, ret);
395 data_blob_free(&ap_rep);
396 data_blob_free(&ap_rep_wrapped);
397 data_blob_free(&response);
398 TALLOC_FREE(mem_ctx);
401 #endif
403 /****************************************************************************
404 Send a session setup reply, wrapped in SPNEGO.
405 Get vuid and check first.
406 End the NTLMSSP exchange context if we are OK/complete fail
407 This should be split into two functions, one to handle each
408 leg of the NTLM auth steps.
409 ***************************************************************************/
411 static void reply_spnego_ntlmssp(struct smb_request *req,
412 uint16 vuid,
413 struct gensec_security **gensec_security,
414 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
415 const char *OID,
416 bool wrap)
418 bool do_invalidate = true;
419 DATA_BLOB response;
420 struct auth_session_info *session_info = NULL;
421 struct smbd_server_connection *sconn = req->sconn;
423 if (NT_STATUS_IS_OK(nt_status)) {
424 nt_status = gensec_session_info(*gensec_security,
425 talloc_tos(),
426 &session_info);
429 reply_outbuf(req, 4, 0);
431 SSVAL(req->outbuf, smb_uid, vuid);
433 if (NT_STATUS_IS_OK(nt_status)) {
434 DATA_BLOB nullblob = data_blob_null;
436 if (!is_partial_auth_vuid(sconn, vuid)) {
437 nt_status = NT_STATUS_LOGON_FAILURE;
438 goto out;
441 /* register_existing_vuid keeps the server info */
442 if (register_existing_vuid(sconn, vuid,
443 session_info, nullblob) !=
444 vuid) {
445 /* The problem is, *gensec_security points
446 * into the vuser this will have
447 * talloc_free()'ed in
448 * register_existing_vuid() */
449 do_invalidate = false;
450 nt_status = NT_STATUS_LOGON_FAILURE;
451 goto out;
454 /* current_user_info is changed on new vuid */
455 reload_services(sconn, conn_snum_used, true);
457 SSVAL(req->outbuf, smb_vwv3, 0);
459 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
460 SSVAL(req->outbuf,smb_vwv2,1);
464 out:
466 if (wrap) {
467 response = spnego_gen_auth_response(talloc_tos(),
468 ntlmssp_blob,
469 nt_status, OID);
470 } else {
471 response = *ntlmssp_blob;
474 reply_sesssetup_blob(req, response, nt_status);
475 if (wrap) {
476 data_blob_free(&response);
479 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
480 and the other end, that we are not finished yet. */
482 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
483 /* NB. This is *NOT* an error case. JRA */
484 if (do_invalidate) {
485 TALLOC_FREE(*gensec_security);
486 if (!NT_STATUS_IS_OK(nt_status)) {
487 /* Kill the intermediate vuid */
488 invalidate_vuid(sconn, vuid);
494 /****************************************************************************
495 Is this a krb5 mechanism ?
496 ****************************************************************************/
498 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
499 DATA_BLOB blob_in,
500 DATA_BLOB *pblob_out,
501 char **kerb_mechOID)
503 char *OIDs[ASN1_MAX_OIDS];
504 int i;
505 NTSTATUS ret = NT_STATUS_OK;
507 *kerb_mechOID = NULL;
509 /* parse out the OIDs and the first sec blob */
510 if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
511 (OIDs[0] == NULL)) {
512 return NT_STATUS_LOGON_FAILURE;
515 /* only look at the first OID for determining the mechToken --
516 according to RFC2478, we should choose the one we want
517 and renegotiate, but i smell a client bug here..
519 Problem observed when connecting to a member (samba box)
520 of an AD domain as a user in a Samba domain. Samba member
521 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
522 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
523 NTLMSSP mechtoken. --jerry */
525 #ifdef HAVE_KRB5
526 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
527 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
528 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
529 if (*kerb_mechOID == NULL) {
530 ret = NT_STATUS_NO_MEMORY;
533 #endif
535 for (i=0;OIDs[i];i++) {
536 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
537 talloc_free(OIDs[i]);
539 return ret;
542 /****************************************************************************
543 Fall back from krb5 to NTLMSSP.
544 ****************************************************************************/
546 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
547 uint16 vuid)
549 DATA_BLOB response;
551 reply_outbuf(req, 4, 0);
552 SSVAL(req->outbuf,smb_uid,vuid);
554 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
555 "but set to downgrade to NTLMSSP\n"));
557 response = spnego_gen_auth_response(talloc_tos(), NULL,
558 NT_STATUS_MORE_PROCESSING_REQUIRED,
559 OID_NTLMSSP);
560 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
561 data_blob_free(&response);
564 /****************************************************************************
565 Reply to a session setup spnego negotiate packet.
566 ****************************************************************************/
568 static void reply_spnego_negotiate(struct smb_request *req,
569 uint16 vuid,
570 DATA_BLOB blob1,
571 struct gensec_security **gensec_security)
573 DATA_BLOB secblob;
574 DATA_BLOB chal;
575 char *kerb_mech = NULL;
576 NTSTATUS status;
577 struct smbd_server_connection *sconn = req->sconn;
579 status = parse_spnego_mechanisms(talloc_tos(),
580 blob1, &secblob, &kerb_mech);
581 if (!NT_STATUS_IS_OK(status)) {
582 /* Kill the intermediate vuid */
583 invalidate_vuid(sconn, vuid);
584 reply_nterror(req, nt_status_squash(status));
585 return;
588 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
589 (unsigned long)secblob.length));
591 #ifdef HAVE_KRB5
592 if (kerb_mech && ((lp_security()==SEC_ADS) ||
593 USE_KERBEROS_KEYTAB) ) {
594 bool destroy_vuid = True;
595 reply_spnego_kerberos(req, &secblob, kerb_mech,
596 vuid, &destroy_vuid);
597 data_blob_free(&secblob);
598 if (destroy_vuid) {
599 /* Kill the intermediate vuid */
600 invalidate_vuid(sconn, vuid);
602 TALLOC_FREE(kerb_mech);
603 return;
605 #endif
607 TALLOC_FREE(*gensec_security);
609 if (kerb_mech) {
610 data_blob_free(&secblob);
611 /* The mechtoken is a krb5 ticket, but
612 * we need to fall back to NTLM. */
613 reply_spnego_downgrade_to_ntlmssp(req, vuid);
614 TALLOC_FREE(kerb_mech);
615 return;
618 status = auth_generic_prepare(NULL, sconn->remote_address,
619 gensec_security);
620 if (!NT_STATUS_IS_OK(status)) {
621 /* Kill the intermediate vuid */
622 invalidate_vuid(sconn, vuid);
623 reply_nterror(req, nt_status_squash(status));
624 return;
627 gensec_want_feature(*gensec_security, GENSEC_FEATURE_SESSION_KEY);
628 gensec_want_feature(*gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
630 status = gensec_start_mech_by_oid(*gensec_security, GENSEC_OID_NTLMSSP);
631 if (!NT_STATUS_IS_OK(status)) {
632 /* Kill the intermediate vuid */
633 invalidate_vuid(sconn, vuid);
634 reply_nterror(req, nt_status_squash(status));
635 return;
638 status = gensec_update(*gensec_security, talloc_tos(),
639 NULL, secblob, &chal);
641 data_blob_free(&secblob);
643 reply_spnego_ntlmssp(req, vuid, gensec_security,
644 &chal, status, OID_NTLMSSP, true);
646 data_blob_free(&chal);
648 /* already replied */
649 return;
652 /****************************************************************************
653 Reply to a session setup spnego auth packet.
654 ****************************************************************************/
656 static void reply_spnego_auth(struct smb_request *req,
657 uint16 vuid,
658 DATA_BLOB blob1,
659 struct gensec_security **gensec_security)
661 DATA_BLOB auth = data_blob_null;
662 DATA_BLOB auth_reply = data_blob_null;
663 DATA_BLOB secblob = data_blob_null;
664 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
665 struct smbd_server_connection *sconn = req->sconn;
667 if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
668 #if 0
669 file_save("auth.dat", blob1.data, blob1.length);
670 #endif
671 /* Kill the intermediate vuid */
672 invalidate_vuid(sconn, vuid);
674 reply_nterror(req, nt_status_squash(
675 NT_STATUS_LOGON_FAILURE));
676 return;
679 if (auth.data[0] == ASN1_APPLICATION(0)) {
680 /* Might be a second negTokenTarg packet */
681 char *kerb_mech = NULL;
683 status = parse_spnego_mechanisms(talloc_tos(),
684 auth, &secblob, &kerb_mech);
686 if (!NT_STATUS_IS_OK(status)) {
687 /* Kill the intermediate vuid */
688 invalidate_vuid(sconn, vuid);
689 reply_nterror(req, nt_status_squash(status));
690 return;
693 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
694 (unsigned long)secblob.length));
695 #ifdef HAVE_KRB5
696 if (kerb_mech && ((lp_security()==SEC_ADS) ||
697 USE_KERBEROS_KEYTAB)) {
698 bool destroy_vuid = True;
699 reply_spnego_kerberos(req, &secblob, kerb_mech,
700 vuid, &destroy_vuid);
701 data_blob_free(&secblob);
702 data_blob_free(&auth);
703 if (destroy_vuid) {
704 /* Kill the intermediate vuid */
705 invalidate_vuid(sconn, vuid);
707 TALLOC_FREE(kerb_mech);
708 return;
710 #endif
711 /* Can't blunder into NTLMSSP auth if we have
712 * a krb5 ticket. */
714 if (kerb_mech) {
715 /* Kill the intermediate vuid */
716 invalidate_vuid(sconn, vuid);
717 DEBUG(3,("reply_spnego_auth: network "
718 "misconfiguration, client sent us a "
719 "krb5 ticket and kerberos security "
720 "not enabled\n"));
721 reply_nterror(req, nt_status_squash(
722 NT_STATUS_LOGON_FAILURE));
723 TALLOC_FREE(kerb_mech);
727 /* If we get here it wasn't a negTokenTarg auth packet. */
728 data_blob_free(&secblob);
730 if (!*gensec_security) {
731 status = auth_generic_prepare(NULL, sconn->remote_address,
732 gensec_security);
733 if (!NT_STATUS_IS_OK(status)) {
734 /* Kill the intermediate vuid */
735 invalidate_vuid(sconn, vuid);
736 reply_nterror(req, nt_status_squash(status));
737 return;
740 gensec_want_feature(*gensec_security, GENSEC_FEATURE_SESSION_KEY);
741 gensec_want_feature(*gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
743 status = gensec_start_mech_by_oid(*gensec_security, GENSEC_OID_NTLMSSP);
744 if (!NT_STATUS_IS_OK(status)) {
745 /* Kill the intermediate vuid */
746 invalidate_vuid(sconn, vuid);
747 reply_nterror(req, nt_status_squash(status));
748 return;
752 status = gensec_update(*gensec_security, talloc_tos(),
753 NULL, auth, &auth_reply);
755 data_blob_free(&auth);
757 /* Don't send the mechid as we've already sent this (RFC4178). */
759 reply_spnego_ntlmssp(req, vuid,
760 gensec_security,
761 &auth_reply, status, NULL, true);
763 data_blob_free(&auth_reply);
765 /* and tell smbd that we have already replied to this packet */
766 return;
769 /****************************************************************************
770 Reply to a session setup command.
771 conn POINTER CAN BE NULL HERE !
772 ****************************************************************************/
774 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
776 const uint8 *p;
777 DATA_BLOB blob1;
778 size_t bufrem;
779 char *tmp;
780 const char *native_os;
781 const char *native_lanman;
782 const char *primary_domain;
783 const char *p2;
784 uint16 data_blob_len = SVAL(req->vwv+7, 0);
785 enum remote_arch_types ra_type = get_remote_arch();
786 int vuid = req->vuid;
787 user_struct *vuser = NULL;
788 NTSTATUS status = NT_STATUS_OK;
789 struct smbd_server_connection *sconn = req->sconn;
790 DATA_BLOB chal;
792 DEBUG(3,("Doing spnego session setup\n"));
794 if (global_client_caps == 0) {
795 global_client_caps = IVAL(req->vwv+10, 0);
797 if (!(global_client_caps & CAP_STATUS32)) {
798 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
803 p = req->buf;
805 if (data_blob_len == 0) {
806 /* an invalid request */
807 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
808 return;
811 bufrem = smbreq_bufrem(req, p);
812 /* pull the spnego blob */
813 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
815 #if 0
816 file_save("negotiate.dat", blob1.data, blob1.length);
817 #endif
819 p2 = (const char *)req->buf + blob1.length;
821 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
822 STR_TERMINATE);
823 native_os = tmp ? tmp : "";
825 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
826 STR_TERMINATE);
827 native_lanman = tmp ? tmp : "";
829 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
830 STR_TERMINATE);
831 primary_domain = tmp ? tmp : "";
833 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
834 native_os, native_lanman, primary_domain));
836 if ( ra_type == RA_WIN2K ) {
837 /* Vista sets neither the OS or lanman strings */
839 if ( !strlen(native_os) && !strlen(native_lanman) )
840 set_remote_arch(RA_VISTA);
842 /* Windows 2003 doesn't set the native lanman string,
843 but does set primary domain which is a bug I think */
845 if ( !strlen(native_lanman) ) {
846 ra_lanman_string( primary_domain );
847 } else {
848 ra_lanman_string( native_lanman );
850 } else if ( ra_type == RA_VISTA ) {
851 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
852 set_remote_arch(RA_OSX);
856 /* Do we have a valid vuid now ? */
857 if (!is_partial_auth_vuid(sconn, vuid)) {
858 /* No, start a new authentication setup. */
859 vuid = register_initial_vuid(sconn);
860 if (vuid == UID_FIELD_INVALID) {
861 data_blob_free(&blob1);
862 reply_nterror(req, nt_status_squash(
863 NT_STATUS_INVALID_PARAMETER));
864 return;
868 vuser = get_partial_auth_user_struct(sconn, vuid);
869 /* This MUST be valid. */
870 if (!vuser) {
871 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
874 if (!vuser->gensec_security) {
875 status = auth_generic_prepare(vuser, sconn->remote_address,
876 &vuser->gensec_security);
877 if (!NT_STATUS_IS_OK(status)) {
878 /* Kill the intermediate vuid */
879 invalidate_vuid(sconn, vuid);
880 data_blob_free(&blob1);
881 reply_nterror(req, nt_status_squash(status));
882 return;
885 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_SESSION_KEY);
886 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
888 if (sconn->use_gensec_hook) {
889 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_SPNEGO);
890 } else {
891 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_NTLMSSP);
893 if (!NT_STATUS_IS_OK(status)) {
894 /* Kill the intermediate vuid */
895 invalidate_vuid(sconn, vuid);
896 data_blob_free(&blob1);
897 reply_nterror(req, nt_status_squash(status));
898 return;
902 status = gensec_update(vuser->gensec_security,
903 talloc_tos(), NULL,
904 blob1, &chal);
906 data_blob_free(&blob1);
908 reply_spnego_ntlmssp(req, vuid,
909 &vuser->gensec_security,
910 &chal, status, NULL, false);
911 data_blob_free(&chal);
912 return;
915 /****************************************************************************
916 On new VC == 0, shutdown *all* old connections and users.
917 It seems that only NT4.x does this. At W2K and above (XP etc.).
918 a new session setup with VC==0 is ignored.
919 ****************************************************************************/
921 struct shutdown_state {
922 const char *ip;
923 struct messaging_context *msg_ctx;
926 static int shutdown_other_smbds(const struct connections_key *key,
927 const struct connections_data *crec,
928 void *private_data)
930 struct shutdown_state *state = (struct shutdown_state *)private_data;
932 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
933 server_id_str(talloc_tos(), &crec->pid), crec->addr));
935 if (!process_exists(crec->pid)) {
936 DEBUG(10, ("process does not exist\n"));
937 return 0;
940 if (procid_is_me(&crec->pid)) {
941 DEBUG(10, ("It's me\n"));
942 return 0;
945 if (strcmp(state->ip, crec->addr) != 0) {
946 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
947 return 0;
950 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
951 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
952 state->ip));
954 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
955 &data_blob_null);
956 return 0;
959 static void setup_new_vc_session(struct smbd_server_connection *sconn)
961 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
962 "compatible we would close all old resources.\n"));
963 #if 0
964 conn_close_all();
965 invalidate_all_vuids();
966 #endif
967 if (lp_reset_on_zero_vc()) {
968 char *addr;
969 struct shutdown_state state;
971 addr = tsocket_address_inet_addr_string(
972 sconn->remote_address, talloc_tos());
973 if (addr == NULL) {
974 return;
976 state.ip = addr;
977 state.msg_ctx = sconn->msg_ctx;
978 connections_forall_read(shutdown_other_smbds, &state);
979 TALLOC_FREE(addr);
983 /****************************************************************************
984 Reply to a session setup command.
985 ****************************************************************************/
987 void reply_sesssetup_and_X(struct smb_request *req)
989 int sess_vuid;
990 int smb_bufsize;
991 DATA_BLOB lm_resp;
992 DATA_BLOB nt_resp;
993 DATA_BLOB plaintext_password;
994 char *tmp;
995 const char *user;
996 fstring sub_user; /* Sanitised username for substituion */
997 const char *domain;
998 const char *native_os;
999 const char *native_lanman;
1000 const char *primary_domain;
1001 struct auth_usersupplied_info *user_info = NULL;
1002 struct auth_serversupplied_info *server_info = NULL;
1003 struct auth_session_info *session_info = NULL;
1004 uint16 smb_flag2 = req->flags2;
1006 NTSTATUS nt_status;
1007 struct smbd_server_connection *sconn = req->sconn;
1009 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1010 bool signing_allowed = false;
1011 bool signing_mandatory = false;
1013 START_PROFILE(SMBsesssetupX);
1015 ZERO_STRUCT(lm_resp);
1016 ZERO_STRUCT(nt_resp);
1017 ZERO_STRUCT(plaintext_password);
1019 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1021 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
1022 signing_allowed = true;
1024 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
1025 signing_mandatory = true;
1029 * We can call srv_set_signing_negotiated() each time.
1030 * It finds out when it needs to turn into a noop
1031 * itself.
1033 srv_set_signing_negotiated(req->sconn,
1034 signing_allowed,
1035 signing_mandatory);
1037 /* a SPNEGO session setup has 12 command words, whereas a normal
1038 NT1 session setup has 13. See the cifs spec. */
1039 if (req->wct == 12 &&
1040 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1042 if (!sconn->smb1.negprot.spnego) {
1043 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1044 "at SPNEGO session setup when it was not "
1045 "negotiated.\n"));
1046 reply_nterror(req, nt_status_squash(
1047 NT_STATUS_LOGON_FAILURE));
1048 END_PROFILE(SMBsesssetupX);
1049 return;
1052 if (SVAL(req->vwv+4, 0) == 0) {
1053 setup_new_vc_session(req->sconn);
1056 reply_sesssetup_and_X_spnego(req);
1057 END_PROFILE(SMBsesssetupX);
1058 return;
1061 smb_bufsize = SVAL(req->vwv+2, 0);
1063 if (get_Protocol() < PROTOCOL_NT1) {
1064 uint16 passlen1 = SVAL(req->vwv+7, 0);
1066 /* Never do NT status codes with protocols before NT1 as we
1067 * don't get client caps. */
1068 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1070 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1071 reply_nterror(req, nt_status_squash(
1072 NT_STATUS_INVALID_PARAMETER));
1073 END_PROFILE(SMBsesssetupX);
1074 return;
1077 if (doencrypt) {
1078 lm_resp = data_blob(req->buf, passlen1);
1079 } else {
1080 plaintext_password = data_blob(req->buf, passlen1+1);
1081 /* Ensure null termination */
1082 plaintext_password.data[passlen1] = 0;
1085 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1086 req->buf + passlen1, STR_TERMINATE);
1087 user = tmp ? tmp : "";
1089 domain = "";
1091 } else {
1092 uint16 passlen1 = SVAL(req->vwv+7, 0);
1093 uint16 passlen2 = SVAL(req->vwv+8, 0);
1094 enum remote_arch_types ra_type = get_remote_arch();
1095 const uint8_t *p = req->buf;
1096 const uint8_t *save_p = req->buf;
1097 uint16 byte_count;
1100 if(global_client_caps == 0) {
1101 global_client_caps = IVAL(req->vwv+11, 0);
1103 if (!(global_client_caps & CAP_STATUS32)) {
1104 remove_from_common_flags2(
1105 FLAGS2_32_BIT_ERROR_CODES);
1108 /* client_caps is used as final determination if
1109 * client is NT or Win95. This is needed to return
1110 * the correct error codes in some circumstances.
1113 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1114 ra_type == RA_WIN95) {
1115 if(!(global_client_caps & (CAP_NT_SMBS|
1116 CAP_STATUS32))) {
1117 set_remote_arch( RA_WIN95);
1122 if (!doencrypt) {
1123 /* both Win95 and WinNT stuff up the password
1124 * lengths for non-encrypting systems. Uggh.
1126 if passlen1==24 its a win95 system, and its setting
1127 the password length incorrectly. Luckily it still
1128 works with the default code because Win95 will null
1129 terminate the password anyway
1131 if passlen1>0 and passlen2>0 then maybe its a NT box
1132 and its setting passlen2 to some random value which
1133 really stuffs things up. we need to fix that one. */
1135 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1136 passlen2 != 1) {
1137 passlen2 = 0;
1141 /* check for nasty tricks */
1142 if (passlen1 > MAX_PASS_LEN
1143 || passlen1 > smbreq_bufrem(req, p)) {
1144 reply_nterror(req, nt_status_squash(
1145 NT_STATUS_INVALID_PARAMETER));
1146 END_PROFILE(SMBsesssetupX);
1147 return;
1150 if (passlen2 > MAX_PASS_LEN
1151 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1152 reply_nterror(req, nt_status_squash(
1153 NT_STATUS_INVALID_PARAMETER));
1154 END_PROFILE(SMBsesssetupX);
1155 return;
1158 /* Save the lanman2 password and the NT md4 password. */
1160 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1161 doencrypt = False;
1164 if (doencrypt) {
1165 lm_resp = data_blob(p, passlen1);
1166 nt_resp = data_blob(p+passlen1, passlen2);
1167 } else if (lp_security() != SEC_SHARE) {
1169 * In share level we should ignore any passwords, so
1170 * only read them if we're not.
1172 char *pass = NULL;
1173 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1175 if (unic && (passlen2 == 0) && passlen1) {
1176 /* Only a ascii plaintext password was sent. */
1177 (void)srvstr_pull_talloc(talloc_tos(),
1178 req->inbuf,
1179 req->flags2,
1180 &pass,
1181 req->buf,
1182 passlen1,
1183 STR_TERMINATE|STR_ASCII);
1184 } else {
1185 (void)srvstr_pull_talloc(talloc_tos(),
1186 req->inbuf,
1187 req->flags2,
1188 &pass,
1189 req->buf,
1190 unic ? passlen2 : passlen1,
1191 STR_TERMINATE);
1193 if (!pass) {
1194 reply_nterror(req, nt_status_squash(
1195 NT_STATUS_INVALID_PARAMETER));
1196 END_PROFILE(SMBsesssetupX);
1197 return;
1199 plaintext_password = data_blob(pass, strlen(pass)+1);
1202 p += passlen1 + passlen2;
1204 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1205 STR_TERMINATE);
1206 user = tmp ? tmp : "";
1208 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1209 STR_TERMINATE);
1210 domain = tmp ? tmp : "";
1212 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1213 STR_TERMINATE);
1214 native_os = tmp ? tmp : "";
1216 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1217 STR_TERMINATE);
1218 native_lanman = tmp ? tmp : "";
1220 /* not documented or decoded by Ethereal but there is one more
1221 * string in the extra bytes which is the same as the
1222 * PrimaryDomain when using extended security. Windows NT 4
1223 * and 2003 use this string to store the native lanman string.
1224 * Windows 9x does not include a string here at all so we have
1225 * to check if we have any extra bytes left */
1227 byte_count = SVAL(req->vwv+13, 0);
1228 if ( PTR_DIFF(p, save_p) < byte_count) {
1229 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1230 STR_TERMINATE);
1231 primary_domain = tmp ? tmp : "";
1232 } else {
1233 primary_domain = talloc_strdup(talloc_tos(), "null");
1236 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1237 "PrimaryDomain=[%s]\n",
1238 domain, native_os, native_lanman, primary_domain));
1240 if ( ra_type == RA_WIN2K ) {
1241 if ( strlen(native_lanman) == 0 )
1242 ra_lanman_string( primary_domain );
1243 else
1244 ra_lanman_string( native_lanman );
1249 if (SVAL(req->vwv+4, 0) == 0) {
1250 setup_new_vc_session(req->sconn);
1253 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1254 domain, user, get_remote_machine_name()));
1256 if (*user) {
1257 if (sconn->smb1.negprot.spnego) {
1259 /* This has to be here, because this is a perfectly
1260 * valid behaviour for guest logons :-( */
1262 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1263 "at 'normal' session setup after "
1264 "negotiating spnego.\n"));
1265 reply_nterror(req, nt_status_squash(
1266 NT_STATUS_LOGON_FAILURE));
1267 END_PROFILE(SMBsesssetupX);
1268 return;
1270 fstrcpy(sub_user, user);
1271 } else {
1272 fstrcpy(sub_user, "");
1275 sub_set_smb_name(sub_user);
1277 reload_services(sconn, conn_snum_used, true);
1279 if (lp_security() == SEC_SHARE) {
1280 char *sub_user_mapped = NULL;
1281 /* In share level we should ignore any passwords */
1283 data_blob_free(&lm_resp);
1284 data_blob_free(&nt_resp);
1285 data_blob_clear_free(&plaintext_password);
1287 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1288 if (!sub_user_mapped) {
1289 reply_nterror(req, NT_STATUS_NO_MEMORY);
1290 END_PROFILE(SMBsesssetupX);
1291 return;
1293 fstrcpy(sub_user, sub_user_mapped);
1294 add_session_user(sconn, sub_user);
1295 add_session_workgroup(sconn, domain);
1296 /* Then force it to null for the benfit of the code below */
1297 user = "";
1300 if (!*user) {
1302 nt_status = check_guest_password(sconn->remote_address, &server_info);
1304 } else if (doencrypt) {
1305 struct auth_context *negprot_auth_context = NULL;
1306 negprot_auth_context = sconn->smb1.negprot.auth_context;
1307 if (!negprot_auth_context) {
1308 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1309 "session setup without negprot denied!\n"));
1310 reply_nterror(req, nt_status_squash(
1311 NT_STATUS_LOGON_FAILURE));
1312 END_PROFILE(SMBsesssetupX);
1313 return;
1315 nt_status = make_user_info_for_reply_enc(&user_info, user,
1316 domain,
1317 sconn->remote_address,
1318 lm_resp, nt_resp);
1319 if (NT_STATUS_IS_OK(nt_status)) {
1320 nt_status = negprot_auth_context->check_ntlm_password(
1321 negprot_auth_context,
1322 user_info,
1323 &server_info);
1325 } else {
1326 struct auth_context *plaintext_auth_context = NULL;
1328 nt_status = make_auth_context_subsystem(
1329 talloc_tos(), &plaintext_auth_context);
1331 if (NT_STATUS_IS_OK(nt_status)) {
1332 uint8_t chal[8];
1334 plaintext_auth_context->get_ntlm_challenge(
1335 plaintext_auth_context, chal);
1337 if (!make_user_info_for_reply(&user_info,
1338 user, domain,
1339 sconn->remote_address,
1340 chal,
1341 plaintext_password)) {
1342 nt_status = NT_STATUS_NO_MEMORY;
1345 if (NT_STATUS_IS_OK(nt_status)) {
1346 nt_status = plaintext_auth_context->check_ntlm_password(
1347 plaintext_auth_context,
1348 user_info,
1349 &server_info);
1351 TALLOC_FREE(plaintext_auth_context);
1356 free_user_info(&user_info);
1358 if (!NT_STATUS_IS_OK(nt_status)) {
1359 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
1360 user, domain);
1363 if (!NT_STATUS_IS_OK(nt_status)) {
1364 data_blob_free(&nt_resp);
1365 data_blob_free(&lm_resp);
1366 data_blob_clear_free(&plaintext_password);
1367 reply_nterror(req, nt_status_squash(nt_status));
1368 END_PROFILE(SMBsesssetupX);
1369 return;
1372 nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
1373 TALLOC_FREE(server_info);
1375 if (!NT_STATUS_IS_OK(nt_status)) {
1376 DEBUG(10, ("create_local_token failed: %s\n",
1377 nt_errstr(nt_status)));
1378 data_blob_free(&nt_resp);
1379 data_blob_free(&lm_resp);
1380 data_blob_clear_free(&plaintext_password);
1381 reply_nterror(req, nt_status_squash(nt_status));
1382 END_PROFILE(SMBsesssetupX);
1383 return;
1386 data_blob_clear_free(&plaintext_password);
1388 /* it's ok - setup a reply */
1389 reply_outbuf(req, 3, 0);
1390 if (get_Protocol() >= PROTOCOL_NT1) {
1391 push_signature(&req->outbuf);
1392 /* perhaps grab OS version here?? */
1395 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
1396 SSVAL(req->outbuf,smb_vwv2,1);
1399 /* register the name and uid as being validated, so further connections
1400 to a uid can get through without a password, on the same VC */
1402 if (lp_security() == SEC_SHARE) {
1403 sess_vuid = UID_FIELD_INVALID;
1404 TALLOC_FREE(session_info);
1405 } else {
1406 /* Ignore the initial vuid. */
1407 sess_vuid = register_initial_vuid(sconn);
1408 if (sess_vuid == UID_FIELD_INVALID) {
1409 data_blob_free(&nt_resp);
1410 data_blob_free(&lm_resp);
1411 reply_nterror(req, nt_status_squash(
1412 NT_STATUS_LOGON_FAILURE));
1413 END_PROFILE(SMBsesssetupX);
1414 return;
1416 /* register_existing_vuid keeps the session_info */
1417 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1418 session_info,
1419 nt_resp.data ? nt_resp : lm_resp);
1420 if (sess_vuid == UID_FIELD_INVALID) {
1421 data_blob_free(&nt_resp);
1422 data_blob_free(&lm_resp);
1423 reply_nterror(req, nt_status_squash(
1424 NT_STATUS_LOGON_FAILURE));
1425 END_PROFILE(SMBsesssetupX);
1426 return;
1429 /* current_user_info is changed on new vuid */
1430 reload_services(sconn, conn_snum_used, true);
1433 data_blob_free(&nt_resp);
1434 data_blob_free(&lm_resp);
1436 SSVAL(req->outbuf,smb_uid,sess_vuid);
1437 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1438 req->vuid = sess_vuid;
1440 if (!sconn->smb1.sessions.done_sesssetup) {
1441 sconn->smb1.sessions.max_send =
1442 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1444 sconn->smb1.sessions.done_sesssetup = true;
1446 END_PROFILE(SMBsesssetupX);
1447 chain_reply(req);
1448 return;