s3:smbd: allow creating new spnego sessions only with a 0 vuid
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blobf9ba9769b59a3aa5968e4840ea3f9ba3857e8da8
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 Do a 'guest' logon, getting back the
77 ****************************************************************************/
79 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
80 TALLOC_CTX *mem_ctx,
81 struct auth_session_info **session_info)
83 struct auth4_context *auth_context;
84 struct auth_usersupplied_info *user_info = NULL;
85 uint8_t chal[8];
86 NTSTATUS nt_status;
88 DEBUG(3,("Got anonymous request\n"));
90 nt_status = make_auth4_context(talloc_tos(), &auth_context);
91 if (!NT_STATUS_IS_OK(nt_status)) {
92 return nt_status;
95 auth_context->get_ntlm_challenge(auth_context,
96 chal);
98 if (!make_user_info_guest(remote_address, &user_info)) {
99 TALLOC_FREE(auth_context);
100 return NT_STATUS_NO_MEMORY;
103 nt_status = auth_check_password_session_info(auth_context,
104 mem_ctx, user_info, session_info);
105 free_user_info(&user_info);
106 TALLOC_FREE(auth_context);
107 return nt_status;
110 /****************************************************************************
111 Reply to a session setup command.
112 conn POINTER CAN BE NULL HERE !
113 ****************************************************************************/
115 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
117 const uint8 *p;
118 DATA_BLOB in_blob;
119 DATA_BLOB out_blob = data_blob_null;
120 size_t bufrem;
121 char *tmp;
122 const char *native_os;
123 const char *native_lanman;
124 const char *primary_domain;
125 const char *p2;
126 uint16 data_blob_len = SVAL(req->vwv+7, 0);
127 enum remote_arch_types ra_type = get_remote_arch();
128 int vuid = req->vuid;
129 user_struct *vuser = NULL;
130 NTSTATUS status = NT_STATUS_OK;
131 struct smbd_server_connection *sconn = req->sconn;
132 uint16_t action = 0;
134 DEBUG(3,("Doing spnego session setup\n"));
136 if (global_client_caps == 0) {
137 global_client_caps = IVAL(req->vwv+10, 0);
139 if (!(global_client_caps & CAP_STATUS32)) {
140 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
144 p = req->buf;
146 if (data_blob_len == 0) {
147 /* an invalid request */
148 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
149 return;
152 bufrem = smbreq_bufrem(req, p);
153 /* pull the spnego blob */
154 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
156 #if 0
157 file_save("negotiate.dat", in_blob.data, in_blob.length);
158 #endif
160 p2 = (const char *)req->buf + in_blob.length;
162 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
163 STR_TERMINATE);
164 native_os = tmp ? tmp : "";
166 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
167 STR_TERMINATE);
168 native_lanman = tmp ? tmp : "";
170 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
171 STR_TERMINATE);
172 primary_domain = tmp ? tmp : "";
174 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
175 native_os, native_lanman, primary_domain));
177 if ( ra_type == RA_WIN2K ) {
178 /* Vista sets neither the OS or lanman strings */
180 if ( !strlen(native_os) && !strlen(native_lanman) )
181 set_remote_arch(RA_VISTA);
183 /* Windows 2003 doesn't set the native lanman string,
184 but does set primary domain which is a bug I think */
186 if ( !strlen(native_lanman) ) {
187 ra_lanman_string( primary_domain );
188 } else {
189 ra_lanman_string( native_lanman );
191 } else if ( ra_type == RA_VISTA ) {
192 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
193 set_remote_arch(RA_OSX);
197 vuser = get_valid_user_struct(sconn, vuid);
198 if (vuser != NULL) {
199 reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
200 return;
203 /* Do we have a valid vuid now ? */
204 if (!is_partial_auth_vuid(sconn, vuid)) {
205 if (vuid != 0) {
206 reply_force_doserror(req, ERRSRV, ERRbaduid);
207 return;
210 /* No, start a new authentication setup. */
211 vuid = register_initial_vuid(sconn);
212 if (vuid == UID_FIELD_INVALID) {
213 reply_nterror(req, nt_status_squash(
214 NT_STATUS_INVALID_PARAMETER));
215 return;
219 vuser = get_partial_auth_user_struct(sconn, vuid);
220 /* This MUST be valid. */
221 if (!vuser) {
222 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
225 if (!vuser->gensec_security) {
226 status = auth_generic_prepare(vuser, sconn->remote_address,
227 &vuser->gensec_security);
228 if (!NT_STATUS_IS_OK(status)) {
229 /* Kill the intermediate vuid */
230 invalidate_vuid(sconn, vuid);
231 reply_nterror(req, nt_status_squash(status));
232 return;
235 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_SESSION_KEY);
236 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
238 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_SPNEGO);
239 if (!NT_STATUS_IS_OK(status)) {
240 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
241 /* Kill the intermediate vuid */
242 invalidate_vuid(sconn, vuid);
243 reply_nterror(req, nt_status_squash(status));
244 return;
248 status = gensec_update(vuser->gensec_security,
249 talloc_tos(), NULL,
250 in_blob, &out_blob);
251 if (!NT_STATUS_IS_OK(status) &&
252 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
253 /* Kill the intermediate vuid */
254 invalidate_vuid(sconn, vuid);
255 reply_nterror(req, nt_status_squash(status));
256 return;
259 if (NT_STATUS_IS_OK(status)) {
260 struct auth_session_info *session_info = NULL;
261 int tmp_vuid;
263 status = gensec_session_info(vuser->gensec_security,
264 talloc_tos(),
265 &session_info);
266 if (!NT_STATUS_IS_OK(status)) {
267 DEBUG(1,("Failed to generate session_info "
268 "(user and group token) for session setup: %s\n",
269 nt_errstr(status)));
270 /* Kill the intermediate vuid */
271 data_blob_free(&out_blob);
272 invalidate_vuid(sconn, vuid);
273 reply_nterror(req, nt_status_squash(status));
274 return;
277 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
278 action = 1;
281 /* register_existing_vuid keeps the server info */
282 tmp_vuid = register_existing_vuid(sconn, vuid,
283 session_info,
284 data_blob_null);
285 if (tmp_vuid != vuid) {
286 data_blob_free(&out_blob);
287 invalidate_vuid(sconn, vuid);
288 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
289 return;
292 /* current_user_info is changed on new vuid */
293 reload_services(sconn, conn_snum_used, true);
296 reply_outbuf(req, 4, 0);
298 SSVAL(req->outbuf, smb_uid, vuid);
299 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
300 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
301 SSVAL(req->outbuf, smb_vwv2, action);
302 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
304 if (message_push_blob(&req->outbuf, out_blob) == -1) {
305 data_blob_free(&out_blob);
306 invalidate_vuid(sconn, vuid);
307 reply_nterror(req, NT_STATUS_NO_MEMORY);
308 return;
310 data_blob_free(&out_blob);
312 if (push_signature(&req->outbuf) == -1) {
313 invalidate_vuid(sconn, vuid);
314 reply_nterror(req, NT_STATUS_NO_MEMORY);
315 return;
319 /****************************************************************************
320 On new VC == 0, shutdown *all* old connections and users.
321 It seems that only NT4.x does this. At W2K and above (XP etc.).
322 a new session setup with VC==0 is ignored.
323 ****************************************************************************/
325 struct shutdown_state {
326 const char *ip;
327 struct messaging_context *msg_ctx;
330 static int shutdown_other_smbds(const struct connections_key *key,
331 const struct connections_data *crec,
332 void *private_data)
334 struct shutdown_state *state = (struct shutdown_state *)private_data;
336 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
337 server_id_str(talloc_tos(), &crec->pid), crec->addr));
339 if (!process_exists(crec->pid)) {
340 DEBUG(10, ("process does not exist\n"));
341 return 0;
344 if (procid_is_me(&crec->pid)) {
345 DEBUG(10, ("It's me\n"));
346 return 0;
349 if (strcmp(state->ip, crec->addr) != 0) {
350 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
351 return 0;
354 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
355 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
356 state->ip));
358 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
359 &data_blob_null);
360 return 0;
363 static void setup_new_vc_session(struct smbd_server_connection *sconn)
365 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
366 "compatible we would close all old resources.\n"));
367 #if 0
368 conn_close_all();
369 invalidate_all_vuids();
370 #endif
371 if (lp_reset_on_zero_vc()) {
372 char *addr;
373 struct shutdown_state state;
375 addr = tsocket_address_inet_addr_string(
376 sconn->remote_address, talloc_tos());
377 if (addr == NULL) {
378 return;
380 state.ip = addr;
381 state.msg_ctx = sconn->msg_ctx;
382 connections_forall_read(shutdown_other_smbds, &state);
383 TALLOC_FREE(addr);
387 /****************************************************************************
388 Reply to a session setup command.
389 ****************************************************************************/
391 void reply_sesssetup_and_X(struct smb_request *req)
393 int sess_vuid;
394 int smb_bufsize;
395 DATA_BLOB lm_resp;
396 DATA_BLOB nt_resp;
397 DATA_BLOB plaintext_password;
398 char *tmp;
399 const char *user;
400 fstring sub_user; /* Sanitised username for substituion */
401 const char *domain;
402 const char *native_os;
403 const char *native_lanman;
404 const char *primary_domain;
405 struct auth_usersupplied_info *user_info = NULL;
406 struct auth_session_info *session_info = NULL;
407 uint16 smb_flag2 = req->flags2;
408 uint16_t action = 0;
410 NTSTATUS nt_status;
411 struct smbd_server_connection *sconn = req->sconn;
413 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
414 bool signing_allowed = false;
415 bool signing_mandatory = false;
417 START_PROFILE(SMBsesssetupX);
419 ZERO_STRUCT(lm_resp);
420 ZERO_STRUCT(nt_resp);
421 ZERO_STRUCT(plaintext_password);
423 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
425 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
426 signing_allowed = true;
428 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
429 signing_mandatory = true;
433 * We can call srv_set_signing_negotiated() each time.
434 * It finds out when it needs to turn into a noop
435 * itself.
437 srv_set_signing_negotiated(req->sconn,
438 signing_allowed,
439 signing_mandatory);
441 /* a SPNEGO session setup has 12 command words, whereas a normal
442 NT1 session setup has 13. See the cifs spec. */
443 if (req->wct == 12 &&
444 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
446 if (!sconn->smb1.negprot.spnego) {
447 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
448 "at SPNEGO session setup when it was not "
449 "negotiated.\n"));
450 reply_nterror(req, nt_status_squash(
451 NT_STATUS_LOGON_FAILURE));
452 END_PROFILE(SMBsesssetupX);
453 return;
456 if (SVAL(req->vwv+4, 0) == 0) {
457 setup_new_vc_session(req->sconn);
460 reply_sesssetup_and_X_spnego(req);
461 END_PROFILE(SMBsesssetupX);
462 return;
465 smb_bufsize = SVAL(req->vwv+2, 0);
467 if (get_Protocol() < PROTOCOL_NT1) {
468 uint16 passlen1 = SVAL(req->vwv+7, 0);
470 /* Never do NT status codes with protocols before NT1 as we
471 * don't get client caps. */
472 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
474 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
475 reply_nterror(req, nt_status_squash(
476 NT_STATUS_INVALID_PARAMETER));
477 END_PROFILE(SMBsesssetupX);
478 return;
481 if (doencrypt) {
482 lm_resp = data_blob(req->buf, passlen1);
483 } else {
484 plaintext_password = data_blob(req->buf, passlen1+1);
485 /* Ensure null termination */
486 plaintext_password.data[passlen1] = 0;
489 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
490 req->buf + passlen1, STR_TERMINATE);
491 user = tmp ? tmp : "";
493 domain = "";
495 } else {
496 uint16 passlen1 = SVAL(req->vwv+7, 0);
497 uint16 passlen2 = SVAL(req->vwv+8, 0);
498 enum remote_arch_types ra_type = get_remote_arch();
499 const uint8_t *p = req->buf;
500 const uint8_t *save_p = req->buf;
501 uint16 byte_count;
504 if(global_client_caps == 0) {
505 global_client_caps = IVAL(req->vwv+11, 0);
507 if (!(global_client_caps & CAP_STATUS32)) {
508 remove_from_common_flags2(
509 FLAGS2_32_BIT_ERROR_CODES);
512 /* client_caps is used as final determination if
513 * client is NT or Win95. This is needed to return
514 * the correct error codes in some circumstances.
517 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
518 ra_type == RA_WIN95) {
519 if(!(global_client_caps & (CAP_NT_SMBS|
520 CAP_STATUS32))) {
521 set_remote_arch( RA_WIN95);
526 if (!doencrypt) {
527 /* both Win95 and WinNT stuff up the password
528 * lengths for non-encrypting systems. Uggh.
530 if passlen1==24 its a win95 system, and its setting
531 the password length incorrectly. Luckily it still
532 works with the default code because Win95 will null
533 terminate the password anyway
535 if passlen1>0 and passlen2>0 then maybe its a NT box
536 and its setting passlen2 to some random value which
537 really stuffs things up. we need to fix that one. */
539 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
540 passlen2 != 1) {
541 passlen2 = 0;
545 /* check for nasty tricks */
546 if (passlen1 > MAX_PASS_LEN
547 || passlen1 > smbreq_bufrem(req, p)) {
548 reply_nterror(req, nt_status_squash(
549 NT_STATUS_INVALID_PARAMETER));
550 END_PROFILE(SMBsesssetupX);
551 return;
554 if (passlen2 > MAX_PASS_LEN
555 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
556 reply_nterror(req, nt_status_squash(
557 NT_STATUS_INVALID_PARAMETER));
558 END_PROFILE(SMBsesssetupX);
559 return;
562 /* Save the lanman2 password and the NT md4 password. */
564 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
565 doencrypt = False;
568 if (doencrypt) {
569 lm_resp = data_blob(p, passlen1);
570 nt_resp = data_blob(p+passlen1, passlen2);
571 } else {
572 char *pass = NULL;
573 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
575 if (unic && (passlen2 == 0) && passlen1) {
576 /* Only a ascii plaintext password was sent. */
577 (void)srvstr_pull_talloc(talloc_tos(),
578 req->inbuf,
579 req->flags2,
580 &pass,
581 req->buf,
582 passlen1,
583 STR_TERMINATE|STR_ASCII);
584 } else {
585 (void)srvstr_pull_talloc(talloc_tos(),
586 req->inbuf,
587 req->flags2,
588 &pass,
589 req->buf,
590 unic ? passlen2 : passlen1,
591 STR_TERMINATE);
593 if (!pass) {
594 reply_nterror(req, nt_status_squash(
595 NT_STATUS_INVALID_PARAMETER));
596 END_PROFILE(SMBsesssetupX);
597 return;
599 plaintext_password = data_blob(pass, strlen(pass)+1);
602 p += passlen1 + passlen2;
604 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
605 STR_TERMINATE);
606 user = tmp ? tmp : "";
608 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
609 STR_TERMINATE);
610 domain = tmp ? tmp : "";
612 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
613 STR_TERMINATE);
614 native_os = tmp ? tmp : "";
616 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
617 STR_TERMINATE);
618 native_lanman = tmp ? tmp : "";
620 /* not documented or decoded by Ethereal but there is one more
621 * string in the extra bytes which is the same as the
622 * PrimaryDomain when using extended security. Windows NT 4
623 * and 2003 use this string to store the native lanman string.
624 * Windows 9x does not include a string here at all so we have
625 * to check if we have any extra bytes left */
627 byte_count = SVAL(req->vwv+13, 0);
628 if ( PTR_DIFF(p, save_p) < byte_count) {
629 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
630 STR_TERMINATE);
631 primary_domain = tmp ? tmp : "";
632 } else {
633 primary_domain = talloc_strdup(talloc_tos(), "null");
636 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
637 "PrimaryDomain=[%s]\n",
638 domain, native_os, native_lanman, primary_domain));
640 if ( ra_type == RA_WIN2K ) {
641 if ( strlen(native_lanman) == 0 )
642 ra_lanman_string( primary_domain );
643 else
644 ra_lanman_string( native_lanman );
649 if (SVAL(req->vwv+4, 0) == 0) {
650 setup_new_vc_session(req->sconn);
653 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
654 domain, user, get_remote_machine_name()));
656 if (*user) {
657 if (sconn->smb1.negprot.spnego) {
659 /* This has to be here, because this is a perfectly
660 * valid behaviour for guest logons :-( */
662 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
663 "at 'normal' session setup after "
664 "negotiating spnego.\n"));
665 reply_nterror(req, nt_status_squash(
666 NT_STATUS_LOGON_FAILURE));
667 END_PROFILE(SMBsesssetupX);
668 return;
670 fstrcpy(sub_user, user);
671 } else {
672 fstrcpy(sub_user, "");
675 sub_set_smb_name(sub_user);
677 reload_services(sconn, conn_snum_used, true);
679 if (!*user) {
681 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
683 } else if (doencrypt) {
684 struct auth4_context *negprot_auth_context = NULL;
685 negprot_auth_context = sconn->smb1.negprot.auth_context;
686 if (!negprot_auth_context) {
687 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
688 "session setup without negprot denied!\n"));
689 reply_nterror(req, nt_status_squash(
690 NT_STATUS_LOGON_FAILURE));
691 END_PROFILE(SMBsesssetupX);
692 return;
694 nt_status = make_user_info_for_reply_enc(&user_info, user,
695 domain,
696 sconn->remote_address,
697 lm_resp, nt_resp);
698 if (NT_STATUS_IS_OK(nt_status)) {
699 nt_status = auth_check_password_session_info(negprot_auth_context,
700 req, user_info, &session_info);
702 } else {
703 struct auth4_context *plaintext_auth_context = NULL;
705 nt_status = make_auth4_context(
706 talloc_tos(), &plaintext_auth_context);
708 if (NT_STATUS_IS_OK(nt_status)) {
709 uint8_t chal[8];
711 plaintext_auth_context->get_ntlm_challenge(
712 plaintext_auth_context, chal);
714 if (!make_user_info_for_reply(&user_info,
715 user, domain,
716 sconn->remote_address,
717 chal,
718 plaintext_password)) {
719 nt_status = NT_STATUS_NO_MEMORY;
722 if (NT_STATUS_IS_OK(nt_status)) {
723 nt_status = auth_check_password_session_info(plaintext_auth_context,
724 req, user_info, &session_info);
726 TALLOC_FREE(plaintext_auth_context);
730 free_user_info(&user_info);
732 if (!NT_STATUS_IS_OK(nt_status)) {
733 data_blob_free(&nt_resp);
734 data_blob_free(&lm_resp);
735 data_blob_clear_free(&plaintext_password);
736 reply_nterror(req, nt_status_squash(nt_status));
737 END_PROFILE(SMBsesssetupX);
738 return;
741 data_blob_clear_free(&plaintext_password);
743 /* it's ok - setup a reply */
744 reply_outbuf(req, 3, 0);
745 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
746 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
748 if (get_Protocol() >= PROTOCOL_NT1) {
749 push_signature(&req->outbuf);
750 /* perhaps grab OS version here?? */
753 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
754 action = 1;
757 /* register the name and uid as being validated, so further connections
758 to a uid can get through without a password, on the same VC */
760 /* Ignore the initial vuid. */
761 sess_vuid = register_initial_vuid(sconn);
762 if (sess_vuid == UID_FIELD_INVALID) {
763 data_blob_free(&nt_resp);
764 data_blob_free(&lm_resp);
765 reply_nterror(req, nt_status_squash(
766 NT_STATUS_LOGON_FAILURE));
767 END_PROFILE(SMBsesssetupX);
768 return;
770 /* register_existing_vuid keeps the session_info */
771 sess_vuid = register_existing_vuid(sconn, sess_vuid,
772 session_info,
773 nt_resp.data ? nt_resp : lm_resp);
774 if (sess_vuid == UID_FIELD_INVALID) {
775 data_blob_free(&nt_resp);
776 data_blob_free(&lm_resp);
777 reply_nterror(req, nt_status_squash(
778 NT_STATUS_LOGON_FAILURE));
779 END_PROFILE(SMBsesssetupX);
780 return;
783 /* current_user_info is changed on new vuid */
784 reload_services(sconn, conn_snum_used, true);
786 data_blob_free(&nt_resp);
787 data_blob_free(&lm_resp);
789 SSVAL(req->outbuf,smb_vwv2,action);
790 SSVAL(req->outbuf,smb_uid,sess_vuid);
791 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
792 req->vuid = sess_vuid;
794 if (!sconn->smb1.sessions.done_sesssetup) {
795 sconn->smb1.sessions.max_send =
796 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
798 sconn->smb1.sessions.done_sesssetup = true;
800 END_PROFILE(SMBsesssetupX);