r21460: Fix for server-side processing of SPNEGO auth
[Samba/bb.git] / source / smbd / sesssetup.c
blob9b9ae4c3533cee9db6ec8aacdc1c34b3bb2d32ec
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
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 extern struct auth_context *negprot_global_auth_context;
27 extern BOOL global_encrypted_passwords_negotiated;
28 extern BOOL global_spnego_negotiated;
29 extern enum protocol_types Protocol;
30 extern int max_send;
32 uint32 global_client_caps = 0;
35 on a logon error possibly map the error to success if "map to guest"
36 is set approriately
38 static NTSTATUS do_map_to_guest(NTSTATUS status, auth_serversupplied_info **server_info,
39 const char *user, const char *domain)
41 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
42 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
43 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
44 DEBUG(3,("No such user %s [%s] - using guest account\n",
45 user, domain));
46 status = make_server_info_guest(server_info);
50 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
51 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
52 DEBUG(3,("Registered username %s for guest access\n",user));
53 status = make_server_info_guest(server_info);
57 return status;
60 /****************************************************************************
61 Add the standard 'Samba' signature to the end of the session setup.
62 ****************************************************************************/
64 static int add_signature(char *outbuf, char *p)
66 char *start = p;
67 fstring lanman;
69 fstr_sprintf( lanman, "Samba %s", SAMBA_VERSION_STRING);
71 p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
72 p += srvstr_push(outbuf, p, lanman, -1, STR_TERMINATE);
73 p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
75 return PTR_DIFF(p, start);
78 /****************************************************************************
79 Start the signing engine if needed. Don't fail signing here.
80 ****************************************************************************/
82 static void sessionsetup_start_signing_engine(const auth_serversupplied_info *server_info, char *inbuf)
84 if (!server_info->guest && !srv_signing_started()) {
85 /* We need to start the signing engine
86 * here but a W2K client sends the old
87 * "BSRSPYL " signature instead of the
88 * correct one. Subsequent packets will
89 * be correct.
91 srv_check_sign_mac(inbuf, False);
95 /****************************************************************************
96 Send a security blob via a session setup reply.
97 ****************************************************************************/
99 static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
100 DATA_BLOB blob, NTSTATUS nt_status)
102 char *p;
104 if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
105 ERROR_NT(nt_status_squash(nt_status));
106 } else {
107 set_message(outbuf,4,0,True);
109 nt_status = nt_status_squash(nt_status);
110 SIVAL(outbuf, smb_rcls, NT_STATUS_V(nt_status));
111 SSVAL(outbuf, smb_vwv0, 0xFF); /* no chaining possible */
112 SSVAL(outbuf, smb_vwv3, blob.length);
113 p = smb_buf(outbuf);
115 /* should we cap this? */
116 memcpy(p, blob.data, blob.length);
117 p += blob.length;
119 p += add_signature( outbuf, p );
121 set_message_end(outbuf,p);
124 show_msg(outbuf);
125 return send_smb(smbd_server_fd(),outbuf);
128 /****************************************************************************
129 Do a 'guest' logon, getting back the
130 ****************************************************************************/
132 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
134 struct auth_context *auth_context;
135 auth_usersupplied_info *user_info = NULL;
137 NTSTATUS nt_status;
138 unsigned char chal[8];
140 ZERO_STRUCT(chal);
142 DEBUG(3,("Got anonymous request\n"));
144 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context, chal))) {
145 return nt_status;
148 if (!make_user_info_guest(&user_info)) {
149 (auth_context->free)(&auth_context);
150 return NT_STATUS_NO_MEMORY;
153 nt_status = auth_context->check_ntlm_password(auth_context, user_info, server_info);
154 (auth_context->free)(&auth_context);
155 free_user_info(&user_info);
156 return nt_status;
160 #ifdef HAVE_KRB5
161 /****************************************************************************
162 reply to a session setup spnego negotiate packet for kerberos
163 ****************************************************************************/
164 static int reply_spnego_kerberos(connection_struct *conn,
165 char *inbuf, char *outbuf,
166 int length, int bufsize,
167 DATA_BLOB *secblob)
169 TALLOC_CTX *mem_ctx;
170 DATA_BLOB ticket;
171 char *client, *p, *domain;
172 fstring netbios_domain_name;
173 struct passwd *pw;
174 fstring user;
175 int sess_vuid;
176 NTSTATUS ret;
177 PAC_DATA *pac_data;
178 DATA_BLOB ap_rep, ap_rep_wrapped, response;
179 auth_serversupplied_info *server_info = NULL;
180 DATA_BLOB session_key = data_blob(NULL, 0);
181 uint8 tok_id[2];
182 DATA_BLOB nullblob = data_blob(NULL, 0);
183 fstring real_username;
184 BOOL map_domainuser_to_guest = False;
185 BOOL username_was_mapped;
186 PAC_LOGON_INFO *logon_info = NULL;
188 ZERO_STRUCT(ticket);
189 ZERO_STRUCT(pac_data);
190 ZERO_STRUCT(ap_rep);
191 ZERO_STRUCT(ap_rep_wrapped);
192 ZERO_STRUCT(response);
194 mem_ctx = talloc_init("reply_spnego_kerberos");
195 if (mem_ctx == NULL)
196 return ERROR_NT(nt_status_squash(NT_STATUS_NO_MEMORY));
198 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
199 talloc_destroy(mem_ctx);
200 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
203 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket, &client, &pac_data, &ap_rep, &session_key);
205 data_blob_free(&ticket);
207 if (!NT_STATUS_IS_OK(ret)) {
208 DEBUG(1,("Failed to verify incoming ticket!\n"));
209 talloc_destroy(mem_ctx);
210 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
213 DEBUG(3,("Ticket name is [%s]\n", client));
215 p = strchr_m(client, '@');
216 if (!p) {
217 DEBUG(3,("Doesn't look like a valid principal\n"));
218 data_blob_free(&ap_rep);
219 data_blob_free(&session_key);
220 SAFE_FREE(client);
221 talloc_destroy(mem_ctx);
222 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
225 *p = 0;
227 /* save the PAC data if we have it */
229 if (pac_data) {
230 logon_info = get_logon_info_from_pac(pac_data);
231 if (logon_info) {
232 netsamlogon_cache_store( client, &logon_info->info3 );
236 if (!strequal(p+1, lp_realm())) {
237 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
238 if (!lp_allow_trusted_domains()) {
239 data_blob_free(&ap_rep);
240 data_blob_free(&session_key);
241 SAFE_FREE(client);
242 talloc_destroy(mem_ctx);
243 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
247 /* this gives a fully qualified user name (ie. with full realm).
248 that leads to very long usernames, but what else can we do? */
250 domain = p+1;
252 if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) {
254 unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1);
255 domain = netbios_domain_name;
256 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
258 } else {
260 /* If we have winbind running, we can (and must) shorten the
261 username by using the short netbios name. Otherwise we will
262 have inconsistent user names. With Kerberos, we get the
263 fully qualified realm, with ntlmssp we get the short
264 name. And even w2k3 does use ntlmssp if you for example
265 connect to an ip address. */
267 struct winbindd_request wb_request;
268 struct winbindd_response wb_response;
269 NSS_STATUS wb_result;
271 ZERO_STRUCT(wb_request);
272 ZERO_STRUCT(wb_response);
274 DEBUG(10, ("Mapping [%s] to short name\n", domain));
276 fstrcpy(wb_request.domain_name, domain);
278 wb_result = winbindd_request_response(WINBINDD_DOMAIN_INFO,
279 &wb_request, &wb_response);
281 if (wb_result == NSS_STATUS_SUCCESS) {
283 fstrcpy(netbios_domain_name,
284 wb_response.data.domain_info.name);
285 domain = netbios_domain_name;
287 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
288 } else {
289 DEBUG(3, ("Could not find short name -- winbind "
290 "not running?\n"));
294 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
296 /* lookup the passwd struct, create a new user if necessary */
298 username_was_mapped = map_username( user );
300 pw = smb_getpwnam( mem_ctx, user, real_username, True );
302 if (pw) {
303 /* if a real user check pam account restrictions */
304 /* only really perfomed if "obey pam restriction" is true */
305 /* do this before an eventual mappign to guest occurs */
306 ret = smb_pam_accountcheck(pw->pw_name);
307 if ( !NT_STATUS_IS_OK(ret)) {
308 DEBUG(1, ("PAM account restriction prevents user login\n"));
309 data_blob_free(&ap_rep);
310 data_blob_free(&session_key);
311 TALLOC_FREE(mem_ctx);
312 return ERROR_NT(nt_status_squash(ret));
316 if (!pw) {
318 /* this was originally the behavior of Samba 2.2, if a user
319 did not have a local uid but has been authenticated, then
320 map them to a guest account */
322 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
323 map_domainuser_to_guest = True;
324 fstrcpy(user,lp_guestaccount());
325 pw = smb_getpwnam( mem_ctx, user, real_username, True );
328 /* extra sanity check that the guest account is valid */
330 if ( !pw ) {
331 DEBUG(1,("Username %s is invalid on this system\n", user));
332 SAFE_FREE(client);
333 data_blob_free(&ap_rep);
334 data_blob_free(&session_key);
335 TALLOC_FREE(mem_ctx);
336 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
340 /* setup the string used by %U */
342 sub_set_smb_name( real_username );
343 reload_services(True);
345 if ( map_domainuser_to_guest ) {
346 make_server_info_guest(&server_info);
347 } else if (logon_info) {
348 /* pass the unmapped username here since map_username()
349 will be called again from inside make_server_info_info3() */
351 ret = make_server_info_info3(mem_ctx, client, domain,
352 &server_info, &logon_info->info3);
353 if ( !NT_STATUS_IS_OK(ret) ) {
354 DEBUG(1,("make_server_info_info3 failed: %s!\n",
355 nt_errstr(ret)));
356 SAFE_FREE(client);
357 data_blob_free(&ap_rep);
358 data_blob_free(&session_key);
359 TALLOC_FREE(mem_ctx);
360 return ERROR_NT(nt_status_squash(ret));
363 } else {
364 ret = make_server_info_pw(&server_info, real_username, pw);
366 if ( !NT_STATUS_IS_OK(ret) ) {
367 DEBUG(1,("make_server_info_pw failed: %s!\n",
368 nt_errstr(ret)));
369 SAFE_FREE(client);
370 data_blob_free(&ap_rep);
371 data_blob_free(&session_key);
372 TALLOC_FREE(mem_ctx);
373 return ERROR_NT(nt_status_squash(ret));
376 /* make_server_info_pw does not set the domain. Without this
377 * we end up with the local netbios name in substitutions for
378 * %D. */
380 if (server_info->sam_account != NULL) {
381 pdb_set_domain(server_info->sam_account, domain, PDB_SET);
385 server_info->was_mapped |= username_was_mapped;
387 /* we need to build the token for the user. make_server_info_guest()
388 already does this */
390 if ( !server_info->ptok ) {
391 ret = create_local_token( server_info );
392 if ( !NT_STATUS_IS_OK(ret) ) {
393 SAFE_FREE(client);
394 data_blob_free(&ap_rep);
395 data_blob_free(&session_key);
396 TALLOC_FREE( mem_ctx );
397 TALLOC_FREE( server_info );
398 return ERROR_NT(nt_status_squash(ret));
402 /* register_vuid keeps the server info */
403 /* register_vuid takes ownership of session_key, no need to free after this.
404 A better interface would copy it.... */
405 sess_vuid = register_vuid(server_info, session_key, nullblob, client);
407 SAFE_FREE(client);
409 if (sess_vuid == UID_FIELD_INVALID ) {
410 ret = NT_STATUS_LOGON_FAILURE;
411 } else {
412 /* current_user_info is changed on new vuid */
413 reload_services( True );
415 set_message(outbuf,4,0,True);
416 SSVAL(outbuf, smb_vwv3, 0);
418 if (server_info->guest) {
419 SSVAL(outbuf,smb_vwv2,1);
422 SSVAL(outbuf, smb_uid, sess_vuid);
424 sessionsetup_start_signing_engine(server_info, inbuf);
427 /* wrap that up in a nice GSS-API wrapping */
428 if (NT_STATUS_IS_OK(ret)) {
429 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
430 } else {
431 ap_rep_wrapped = data_blob(NULL, 0);
433 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
434 reply_sesssetup_blob(conn, outbuf, response, ret);
436 data_blob_free(&ap_rep);
437 data_blob_free(&ap_rep_wrapped);
438 data_blob_free(&response);
439 TALLOC_FREE(mem_ctx);
441 return -1; /* already replied */
443 #endif
445 /****************************************************************************
446 Send a session setup reply, wrapped in SPNEGO.
447 Get vuid and check first.
448 End the NTLMSSP exchange context if we are OK/complete fail
449 This should be split into two functions, one to handle each
450 leg of the NTLM auth steps.
451 ***************************************************************************/
453 static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
454 uint16 vuid,
455 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
456 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
457 BOOL wrap)
459 BOOL ret;
460 DATA_BLOB response;
461 struct auth_serversupplied_info *server_info = NULL;
463 if (NT_STATUS_IS_OK(nt_status)) {
464 server_info = (*auth_ntlmssp_state)->server_info;
465 } else {
466 nt_status = do_map_to_guest(nt_status,
467 &server_info,
468 (*auth_ntlmssp_state)->ntlmssp_state->user,
469 (*auth_ntlmssp_state)->ntlmssp_state->domain);
472 if (NT_STATUS_IS_OK(nt_status)) {
473 int sess_vuid;
474 DATA_BLOB nullblob = data_blob(NULL, 0);
475 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
477 /* register_vuid keeps the server info */
478 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
479 (*auth_ntlmssp_state)->server_info = NULL;
481 if (sess_vuid == UID_FIELD_INVALID ) {
482 nt_status = NT_STATUS_LOGON_FAILURE;
483 } else {
485 /* current_user_info is changed on new vuid */
486 reload_services( True );
488 set_message(outbuf,4,0,True);
489 SSVAL(outbuf, smb_vwv3, 0);
491 if (server_info->guest) {
492 SSVAL(outbuf,smb_vwv2,1);
495 SSVAL(outbuf,smb_uid,sess_vuid);
497 sessionsetup_start_signing_engine(server_info, inbuf);
501 if (wrap) {
502 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
503 } else {
504 response = *ntlmssp_blob;
507 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
508 if (wrap) {
509 data_blob_free(&response);
512 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
513 and the other end, that we are not finished yet. */
515 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
516 /* NB. This is *NOT* an error case. JRA */
517 auth_ntlmssp_end(auth_ntlmssp_state);
518 /* Kill the intermediate vuid */
519 invalidate_vuid(vuid);
522 return ret;
525 /****************************************************************************
526 Reply to a session setup spnego negotiate packet.
527 ****************************************************************************/
529 static int reply_spnego_negotiate(connection_struct *conn,
530 char *inbuf,
531 char *outbuf,
532 uint16 vuid,
533 int length, int bufsize,
534 DATA_BLOB blob1,
535 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
537 char *OIDs[ASN1_MAX_OIDS];
538 DATA_BLOB secblob;
539 int i;
540 DATA_BLOB chal;
541 #ifdef HAVE_KRB5
542 BOOL got_kerberos_mechanism = False;
543 #endif
544 NTSTATUS nt_status;
546 /* parse out the OIDs and the first sec blob */
547 if (!parse_negTokenTarg(blob1, OIDs, &secblob)) {
548 /* Kill the intermediate vuid */
549 invalidate_vuid(vuid);
551 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
554 /* only look at the first OID for determining the mechToken --
555 accoirding to RFC2478, we should choose the one we want
556 and renegotiate, but i smell a client bug here..
558 Problem observed when connecting to a member (samba box)
559 of an AD domain as a user in a Samba domain. Samba member
560 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
561 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
562 NTLMSSP mechtoken. --jerry */
564 #ifdef HAVE_KRB5
565 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
566 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
567 got_kerberos_mechanism = True;
569 #endif
571 for (i=0;OIDs[i];i++) {
572 DEBUG(3,("Got OID %s\n", OIDs[i]));
573 free(OIDs[i]);
575 DEBUG(3,("Got secblob of size %lu\n", (unsigned long)secblob.length));
577 #ifdef HAVE_KRB5
578 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
579 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
580 length, bufsize, &secblob);
581 data_blob_free(&secblob);
582 /* Kill the intermediate vuid */
583 invalidate_vuid(vuid);
585 return ret;
587 #endif
589 if (*auth_ntlmssp_state) {
590 auth_ntlmssp_end(auth_ntlmssp_state);
593 nt_status = auth_ntlmssp_start(auth_ntlmssp_state);
594 if (!NT_STATUS_IS_OK(nt_status)) {
595 /* Kill the intermediate vuid */
596 invalidate_vuid(vuid);
598 return ERROR_NT(nt_status_squash(nt_status));
601 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
602 secblob, &chal);
604 data_blob_free(&secblob);
606 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
607 &chal, nt_status, True);
609 data_blob_free(&chal);
611 /* already replied */
612 return -1;
615 /****************************************************************************
616 Reply to a session setup spnego auth packet.
617 ****************************************************************************/
619 static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
620 uint16 vuid,
621 int length, int bufsize,
622 DATA_BLOB blob1,
623 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
625 DATA_BLOB auth, auth_reply;
626 NTSTATUS nt_status = NT_STATUS_INVALID_PARAMETER;
628 if (!spnego_parse_auth(blob1, &auth)) {
629 #if 0
630 file_save("auth.dat", blob1.data, blob1.length);
631 #endif
632 /* Kill the intermediate vuid */
633 invalidate_vuid(vuid);
635 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
638 if (!*auth_ntlmssp_state) {
639 /* Kill the intermediate vuid */
640 invalidate_vuid(vuid);
642 /* auth before negotiatiate? */
643 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
646 nt_status = auth_ntlmssp_update(*auth_ntlmssp_state,
647 auth, &auth_reply);
649 data_blob_free(&auth);
651 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
652 auth_ntlmssp_state,
653 &auth_reply, nt_status, True);
655 data_blob_free(&auth_reply);
657 /* and tell smbd that we have already replied to this packet */
658 return -1;
661 /****************************************************************************
662 List to store partial SPNEGO auth fragments.
663 ****************************************************************************/
665 static struct pending_auth_data *pd_list;
667 /****************************************************************************
668 Delete an entry on the list.
669 ****************************************************************************/
671 static void delete_partial_auth(struct pending_auth_data *pad)
673 DLIST_REMOVE(pd_list, pad);
674 data_blob_free(&pad->partial_data);
675 SAFE_FREE(pad);
678 /****************************************************************************
679 Search for a partial SPNEGO auth fragment matching an smbpid.
680 ****************************************************************************/
682 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
684 struct pending_auth_data *pad;
686 for (pad = pd_list; pad; pad = pad->next) {
687 if (pad->smbpid == smbpid) {
688 break;
691 return pad;
694 /****************************************************************************
695 Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
696 else return NT_STATUS_OK.
697 ****************************************************************************/
699 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob)
701 struct pending_auth_data *pad;
702 ASN1_DATA data;
703 size_t needed_len = 0;
705 /* Ensure we have some data. */
706 if (pblob->length == 0) {
707 /* Caller can cope. */
708 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
709 delete_partial_auth(pad);
710 return NT_STATUS_OK;
713 pad = get_pending_auth_data(smbpid);
715 /* Were we waiting for more data ? */
716 if (pad) {
717 DATA_BLOB tmp_blob;
719 /* Integer wrap paranoia.... */
721 if (pad->partial_data.length + pblob->length < pad->partial_data.length ||
722 pad->partial_data.length + pblob->length < pblob->length) {
724 DEBUG(2,("check_spnego_blob_complete: integer wrap "
725 "pad->partial_data.length = %u, "
726 "pblob->length = %u\n",
727 (unsigned int)pad->partial_data.length,
728 (unsigned int)pblob->length ));
730 delete_partial_auth(pad);
731 return NT_STATUS_INVALID_PARAMETER;
734 DEBUG(10,("check_spnego_blob_complete: "
735 "pad->partial_data.length = %u, "
736 "pad->needed_len = %u, "
737 "pblob->length = %u,\n",
738 (unsigned int)pad->partial_data.length,
739 (unsigned int)pad->needed_len,
740 (unsigned int)pblob->length ));
742 tmp_blob = data_blob(NULL,
743 pad->partial_data.length + pblob->length);
745 /* Concatenate the two. */
746 memcpy(tmp_blob.data,
747 pad->partial_data.data,
748 pad->partial_data.length);
749 memcpy(tmp_blob.data + pad->partial_data.length,
750 pblob->data,
751 pblob->length);
753 /* Replace the partial data. */
754 data_blob_free(&pad->partial_data);
755 pad->partial_data = tmp_blob;
756 ZERO_STRUCT(tmp_blob);
758 /* Are we done ? */
759 if (pblob->length >= pad->needed_len) {
760 /* Yes, replace pblob. */
761 data_blob_free(pblob);
762 *pblob = pad->partial_data;
763 ZERO_STRUCT(pad->partial_data);
764 delete_partial_auth(pad);
765 return NT_STATUS_OK;
768 /* Still need more data. */
769 pad->needed_len -= pblob->length;
770 return NT_STATUS_MORE_PROCESSING_REQUIRED;
773 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
774 (pblob->data[0] != ASN1_CONTEXT(1))) {
775 /* Not something we can determine the
776 * length of.
778 return NT_STATUS_OK;
781 /* This is a new SPNEGO sessionsetup - see if
782 * the data given in this blob is enough.
785 asn1_load(&data, *pblob);
786 asn1_start_tag(&data, pblob->data[0]);
787 if (data.has_error || data.nesting == NULL) {
788 asn1_free(&data);
789 /* Let caller catch. */
790 return NT_STATUS_OK;
793 /* Integer wrap paranoia.... */
795 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
796 data.nesting->taglen + data.nesting->start < data.nesting->start) {
798 DEBUG(2,("check_spnego_blob_complete: integer wrap "
799 "data.nesting->taglen = %u, "
800 "data.nesting->start = %u\n",
801 (unsigned int)data.nesting->taglen,
802 (unsigned int)data.nesting->start ));
804 asn1_free(&data);
805 return NT_STATUS_INVALID_PARAMETER;
808 /* Total length of the needed asn1 is the tag length
809 * plus the current offset. */
811 needed_len = data.nesting->taglen + data.nesting->start;
812 asn1_free(&data);
814 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
815 "pblob->length = %u\n",
816 (unsigned int)needed_len,
817 (unsigned int)pblob->length ));
819 if (needed_len <= pblob->length) {
820 /* Nothing to do - blob is complete. */
821 return NT_STATUS_OK;
824 /* We must store this blob until complete. */
825 pad = SMB_MALLOC(sizeof(struct pending_auth_data));
826 if (!pad) {
827 return NT_STATUS_NO_MEMORY;
829 pad->needed_len = needed_len - pblob->length;
830 pad->partial_data = data_blob(pblob->data, pblob->length);
831 pad->smbpid = smbpid;
832 pad->vuid = vuid;
833 DLIST_ADD(pd_list, pad);
835 return NT_STATUS_MORE_PROCESSING_REQUIRED;
838 /****************************************************************************
839 Reply to a session setup command.
840 conn POINTER CAN BE NULL HERE !
841 ****************************************************************************/
843 static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
844 char *outbuf,
845 int length,int bufsize)
847 uint8 *p;
848 DATA_BLOB blob1;
849 int ret;
850 size_t bufrem;
851 fstring native_os, native_lanman, primary_domain;
852 char *p2;
853 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
854 enum remote_arch_types ra_type = get_remote_arch();
855 int vuid = SVAL(inbuf,smb_uid);
856 user_struct *vuser = NULL;
857 NTSTATUS status = NT_STATUS_OK;
858 uint16 smbpid = SVAL(inbuf,smb_pid);
860 DEBUG(3,("Doing spnego session setup\n"));
862 if (global_client_caps == 0) {
863 global_client_caps = IVAL(inbuf,smb_vwv10);
865 if (!(global_client_caps & CAP_STATUS32)) {
866 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
871 p = (uint8 *)smb_buf(inbuf);
873 if (data_blob_len == 0) {
874 /* an invalid request */
875 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
878 bufrem = smb_bufrem(inbuf, p);
879 /* pull the spnego blob */
880 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
882 #if 0
883 file_save("negotiate.dat", blob1.data, blob1.length);
884 #endif
886 p2 = inbuf + smb_vwv13 + data_blob_len;
887 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
888 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
889 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
890 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
891 native_os, native_lanman, primary_domain));
893 if ( ra_type == RA_WIN2K ) {
894 /* Windows 2003 doesn't set the native lanman string,
895 but does set primary domain which is a bug I think */
897 if ( !strlen(native_lanman) ) {
898 ra_lanman_string( primary_domain );
899 } else {
900 ra_lanman_string( native_lanman );
904 vuser = get_partial_auth_user_struct(vuid);
905 if (!vuser) {
906 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
907 if (pad) {
908 DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
909 (unsigned int)pad->vuid ));
910 vuid = pad->vuid;
911 vuser = get_partial_auth_user_struct(vuid);
915 if (!vuser) {
916 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
917 if (vuid == UID_FIELD_INVALID ) {
918 data_blob_free(&blob1);
919 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
922 vuser = get_partial_auth_user_struct(vuid);
925 if (!vuser) {
926 data_blob_free(&blob1);
927 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
930 SSVAL(outbuf,smb_uid,vuid);
932 /* Large (greater than 4k) SPNEGO blobs are split into multiple
933 * sessionsetup requests as the Windows limit on the security blob
934 * field is 4k. Bug #4400. JRA.
937 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
938 if (!NT_STATUS_IS_OK(status)) {
939 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
940 /* Real error - kill the intermediate vuid */
941 invalidate_vuid(vuid);
943 data_blob_free(&blob1);
944 return ERROR_NT(nt_status_squash(status));
947 if (blob1.data[0] == ASN1_APPLICATION(0)) {
948 /* its a negTokenTarg packet */
949 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
950 &vuser->auth_ntlmssp_state);
951 data_blob_free(&blob1);
952 return ret;
955 if (blob1.data[0] == ASN1_CONTEXT(1)) {
956 /* its a auth packet */
957 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
958 &vuser->auth_ntlmssp_state);
959 data_blob_free(&blob1);
960 return ret;
963 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
964 DATA_BLOB chal;
965 if (!vuser->auth_ntlmssp_state) {
966 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
967 if (!NT_STATUS_IS_OK(status)) {
968 /* Kill the intermediate vuid */
969 invalidate_vuid(vuid);
970 data_blob_free(&blob1);
971 return ERROR_NT(nt_status_squash(status));
975 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
976 blob1, &chal);
978 data_blob_free(&blob1);
980 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
981 &vuser->auth_ntlmssp_state,
982 &chal, status, False);
983 data_blob_free(&chal);
984 return -1;
987 /* what sort of packet is this? */
988 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
990 data_blob_free(&blob1);
992 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
995 /****************************************************************************
996 On new VC == 0, shutdown *all* old connections and users.
997 It seems that only NT4.x does this. At W2K and above (XP etc.).
998 a new session setup with VC==0 is ignored.
999 ****************************************************************************/
1001 static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
1002 void *p)
1004 struct sessionid *sessionid = (struct sessionid *)dbuf.dptr;
1005 const char *ip = (const char *)p;
1007 if (!process_exists(pid_to_procid(sessionid->pid))) {
1008 return 0;
1011 if (sessionid->pid == sys_getpid()) {
1012 return 0;
1015 if (strcmp(ip, sessionid->ip_addr) != 0) {
1016 return 0;
1019 message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
1020 NULL, 0, True);
1021 return 0;
1024 static void setup_new_vc_session(void)
1026 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1027 #if 0
1028 conn_close_all();
1029 invalidate_all_vuids();
1030 #endif
1031 if (lp_reset_on_zero_vc()) {
1032 session_traverse(shutdown_other_smbds, client_addr());
1036 /****************************************************************************
1037 Reply to a session setup command.
1038 ****************************************************************************/
1040 int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
1041 int length,int bufsize)
1043 int sess_vuid;
1044 int smb_bufsize;
1045 DATA_BLOB lm_resp;
1046 DATA_BLOB nt_resp;
1047 DATA_BLOB plaintext_password;
1048 fstring user;
1049 fstring sub_user; /* Sainitised username for substituion */
1050 fstring domain;
1051 fstring native_os;
1052 fstring native_lanman;
1053 fstring primary_domain;
1054 static BOOL done_sesssetup = False;
1055 auth_usersupplied_info *user_info = NULL;
1056 auth_serversupplied_info *server_info = NULL;
1058 NTSTATUS nt_status;
1060 BOOL doencrypt = global_encrypted_passwords_negotiated;
1062 DATA_BLOB session_key;
1064 START_PROFILE(SMBsesssetupX);
1066 ZERO_STRUCT(lm_resp);
1067 ZERO_STRUCT(nt_resp);
1068 ZERO_STRUCT(plaintext_password);
1070 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
1072 /* a SPNEGO session setup has 12 command words, whereas a normal
1073 NT1 session setup has 13. See the cifs spec. */
1074 if (CVAL(inbuf, smb_wct) == 12 &&
1075 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
1076 if (!global_spnego_negotiated) {
1077 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1078 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1081 if (SVAL(inbuf,smb_vwv4) == 0) {
1082 setup_new_vc_session();
1084 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
1087 smb_bufsize = SVAL(inbuf,smb_vwv2);
1089 if (Protocol < PROTOCOL_NT1) {
1090 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1092 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1093 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1095 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
1096 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1099 if (doencrypt) {
1100 lm_resp = data_blob(smb_buf(inbuf), passlen1);
1101 } else {
1102 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
1103 /* Ensure null termination */
1104 plaintext_password.data[passlen1] = 0;
1107 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
1108 *domain = 0;
1110 } else {
1111 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1112 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
1113 enum remote_arch_types ra_type = get_remote_arch();
1114 char *p = smb_buf(inbuf);
1115 char *save_p = smb_buf(inbuf);
1116 uint16 byte_count;
1119 if(global_client_caps == 0) {
1120 global_client_caps = IVAL(inbuf,smb_vwv11);
1122 if (!(global_client_caps & CAP_STATUS32)) {
1123 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1126 /* client_caps is used as final determination if client is NT or Win95.
1127 This is needed to return the correct error codes in some
1128 circumstances.
1131 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
1132 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
1133 set_remote_arch( RA_WIN95);
1138 if (!doencrypt) {
1139 /* both Win95 and WinNT stuff up the password lengths for
1140 non-encrypting systems. Uggh.
1142 if passlen1==24 its a win95 system, and its setting the
1143 password length incorrectly. Luckily it still works with the
1144 default code because Win95 will null terminate the password
1145 anyway
1147 if passlen1>0 and passlen2>0 then maybe its a NT box and its
1148 setting passlen2 to some random value which really stuffs
1149 things up. we need to fix that one. */
1151 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
1152 passlen2 = 0;
1155 /* check for nasty tricks */
1156 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
1157 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1160 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
1161 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1164 /* Save the lanman2 password and the NT md4 password. */
1166 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1167 doencrypt = False;
1170 if (doencrypt) {
1171 lm_resp = data_blob(p, passlen1);
1172 nt_resp = data_blob(p+passlen1, passlen2);
1173 } else {
1174 pstring pass;
1175 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
1177 #if 0
1178 /* This was the previous fix. Not sure if it's still valid. JRA. */
1179 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
1180 /* NT4.0 stuffs up plaintext unicode password lengths... */
1181 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
1182 sizeof(pass), passlen1, STR_TERMINATE);
1183 #endif
1185 if (unic && (passlen2 == 0) && passlen1) {
1186 /* Only a ascii plaintext password was sent. */
1187 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
1188 passlen1, STR_TERMINATE|STR_ASCII);
1189 } else {
1190 srvstr_pull(inbuf, pass, smb_buf(inbuf),
1191 sizeof(pass), unic ? passlen2 : passlen1,
1192 STR_TERMINATE);
1194 plaintext_password = data_blob(pass, strlen(pass)+1);
1197 p += passlen1 + passlen2;
1198 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
1199 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
1200 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
1201 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
1203 /* not documented or decoded by Ethereal but there is one more string
1204 in the extra bytes which is the same as the PrimaryDomain when using
1205 extended security. Windows NT 4 and 2003 use this string to store
1206 the native lanman string. Windows 9x does not include a string here
1207 at all so we have to check if we have any extra bytes left */
1209 byte_count = SVAL(inbuf, smb_vwv13);
1210 if ( PTR_DIFF(p, save_p) < byte_count)
1211 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
1212 else
1213 fstrcpy( primary_domain, "null" );
1215 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1216 domain, native_os, native_lanman, primary_domain));
1218 if ( ra_type == RA_WIN2K ) {
1219 if ( strlen(native_lanman) == 0 )
1220 ra_lanman_string( primary_domain );
1221 else
1222 ra_lanman_string( native_lanman );
1227 if (SVAL(inbuf,smb_vwv4) == 0) {
1228 setup_new_vc_session();
1231 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1233 if (*user) {
1234 if (global_spnego_negotiated) {
1236 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1238 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1239 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1241 fstrcpy(sub_user, user);
1242 } else {
1243 fstrcpy(sub_user, lp_guestaccount());
1246 sub_set_smb_name(sub_user);
1248 reload_services(True);
1250 if (lp_security() == SEC_SHARE) {
1251 /* in share level we should ignore any passwords */
1253 data_blob_free(&lm_resp);
1254 data_blob_free(&nt_resp);
1255 data_blob_clear_free(&plaintext_password);
1257 map_username(sub_user);
1258 add_session_user(sub_user);
1259 add_session_workgroup(domain);
1260 /* Then force it to null for the benfit of the code below */
1261 *user = 0;
1264 if (!*user) {
1266 nt_status = check_guest_password(&server_info);
1268 } else if (doencrypt) {
1269 if (!negprot_global_auth_context) {
1270 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1271 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1273 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1274 lm_resp, nt_resp);
1275 if (NT_STATUS_IS_OK(nt_status)) {
1276 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1277 user_info,
1278 &server_info);
1280 } else {
1281 struct auth_context *plaintext_auth_context = NULL;
1282 const uint8 *chal;
1284 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1286 if (NT_STATUS_IS_OK(nt_status)) {
1287 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1289 if (!make_user_info_for_reply(&user_info,
1290 user, domain, chal,
1291 plaintext_password)) {
1292 nt_status = NT_STATUS_NO_MEMORY;
1295 if (NT_STATUS_IS_OK(nt_status)) {
1296 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1297 user_info,
1298 &server_info);
1300 (plaintext_auth_context->free)(&plaintext_auth_context);
1305 free_user_info(&user_info);
1307 if (!NT_STATUS_IS_OK(nt_status)) {
1308 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1311 if (!NT_STATUS_IS_OK(nt_status)) {
1312 data_blob_free(&nt_resp);
1313 data_blob_free(&lm_resp);
1314 data_blob_clear_free(&plaintext_password);
1315 return ERROR_NT(nt_status_squash(nt_status));
1318 /* Ensure we can't possible take a code path leading to a null defref. */
1319 if (!server_info) {
1320 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1323 nt_status = create_local_token(server_info);
1324 if (!NT_STATUS_IS_OK(nt_status)) {
1325 DEBUG(10, ("create_local_token failed: %s\n",
1326 nt_errstr(nt_status)));
1327 data_blob_free(&nt_resp);
1328 data_blob_free(&lm_resp);
1329 data_blob_clear_free(&plaintext_password);
1330 return ERROR_NT(nt_status_squash(nt_status));
1333 if (server_info->user_session_key.data) {
1334 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1335 } else {
1336 session_key = data_blob(NULL, 0);
1339 data_blob_clear_free(&plaintext_password);
1341 /* it's ok - setup a reply */
1342 set_message(outbuf,3,0,True);
1343 if (Protocol >= PROTOCOL_NT1) {
1344 char *p = smb_buf( outbuf );
1345 p += add_signature( outbuf, p );
1346 set_message_end( outbuf, p );
1347 /* perhaps grab OS version here?? */
1350 if (server_info->guest) {
1351 SSVAL(outbuf,smb_vwv2,1);
1354 /* register the name and uid as being validated, so further connections
1355 to a uid can get through without a password, on the same VC */
1357 if (lp_security() == SEC_SHARE) {
1358 sess_vuid = UID_FIELD_INVALID;
1359 data_blob_free(&session_key);
1360 TALLOC_FREE(server_info);
1361 } else {
1362 /* register_vuid keeps the server info */
1363 sess_vuid = register_vuid(server_info, session_key,
1364 nt_resp.data ? nt_resp : lm_resp,
1365 sub_user);
1366 if (sess_vuid == UID_FIELD_INVALID) {
1367 data_blob_free(&nt_resp);
1368 data_blob_free(&lm_resp);
1369 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1372 /* current_user_info is changed on new vuid */
1373 reload_services( True );
1375 sessionsetup_start_signing_engine(server_info, inbuf);
1378 data_blob_free(&nt_resp);
1379 data_blob_free(&lm_resp);
1381 SSVAL(outbuf,smb_uid,sess_vuid);
1382 SSVAL(inbuf,smb_uid,sess_vuid);
1384 if (!done_sesssetup)
1385 max_send = MIN(max_send,smb_bufsize);
1387 done_sesssetup = True;
1389 END_PROFILE(SMBsesssetupX);
1390 return chain_reply(inbuf,outbuf,length,bufsize);