s3:smbd: use 'struct user_struct' instead of typedef'ed 'user_struct'
[Samba.git] / source3 / smbd / sesssetup.c
bloba3c6ede818bce3a3e85296a1a67c71ae3e453c7d
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"
39 #include "lib/conn_tdb.h"
41 /****************************************************************************
42 Add the standard 'Samba' signature to the end of the session setup.
43 ****************************************************************************/
45 static int push_signature(uint8 **outbuf)
47 char *lanman;
48 int result, tmp;
50 result = 0;
52 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
54 if (tmp == -1) return -1;
55 result += tmp;
57 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
58 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
59 SAFE_FREE(lanman);
61 else {
62 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
65 if (tmp == -1) return -1;
66 result += tmp;
68 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
70 if (tmp == -1) return -1;
71 result += tmp;
73 return result;
76 /****************************************************************************
77 Do a 'guest' logon, getting back the
78 ****************************************************************************/
80 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
81 TALLOC_CTX *mem_ctx,
82 struct auth_session_info **session_info)
84 struct auth4_context *auth_context;
85 struct auth_usersupplied_info *user_info = NULL;
86 uint8_t chal[8];
87 NTSTATUS nt_status;
89 DEBUG(3,("Got anonymous request\n"));
91 nt_status = make_auth4_context(talloc_tos(), &auth_context);
92 if (!NT_STATUS_IS_OK(nt_status)) {
93 return nt_status;
96 auth_context->get_ntlm_challenge(auth_context,
97 chal);
99 if (!make_user_info_guest(remote_address, &user_info)) {
100 TALLOC_FREE(auth_context);
101 return NT_STATUS_NO_MEMORY;
104 nt_status = auth_check_password_session_info(auth_context,
105 mem_ctx, user_info, session_info);
106 free_user_info(&user_info);
107 TALLOC_FREE(auth_context);
108 return nt_status;
111 /****************************************************************************
112 Reply to a session setup command.
113 conn POINTER CAN BE NULL HERE !
114 ****************************************************************************/
116 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
118 const uint8 *p;
119 DATA_BLOB in_blob;
120 DATA_BLOB out_blob = data_blob_null;
121 size_t bufrem;
122 char *tmp;
123 const char *native_os;
124 const char *native_lanman;
125 const char *primary_domain;
126 const char *p2;
127 uint16 data_blob_len = SVAL(req->vwv+7, 0);
128 enum remote_arch_types ra_type = get_remote_arch();
129 int vuid = req->vuid;
130 struct user_struct *vuser = NULL;
131 NTSTATUS status = NT_STATUS_OK;
132 struct smbd_server_connection *sconn = req->sconn;
133 uint16_t action = 0;
135 DEBUG(3,("Doing spnego session setup\n"));
137 if (global_client_caps == 0) {
138 global_client_caps = IVAL(req->vwv+10, 0);
140 if (!(global_client_caps & CAP_STATUS32)) {
141 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
145 p = req->buf;
147 if (data_blob_len == 0) {
148 /* an invalid request */
149 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
150 return;
153 bufrem = smbreq_bufrem(req, p);
154 /* pull the spnego blob */
155 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
157 #if 0
158 file_save("negotiate.dat", in_blob.data, in_blob.length);
159 #endif
161 p2 = (const char *)req->buf + in_blob.length;
163 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
164 STR_TERMINATE);
165 native_os = tmp ? tmp : "";
167 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
168 STR_TERMINATE);
169 native_lanman = tmp ? tmp : "";
171 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
172 STR_TERMINATE);
173 primary_domain = tmp ? tmp : "";
175 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
176 native_os, native_lanman, primary_domain));
178 if ( ra_type == RA_WIN2K ) {
179 /* Vista sets neither the OS or lanman strings */
181 if ( !strlen(native_os) && !strlen(native_lanman) )
182 set_remote_arch(RA_VISTA);
184 /* Windows 2003 doesn't set the native lanman string,
185 but does set primary domain which is a bug I think */
187 if ( !strlen(native_lanman) ) {
188 ra_lanman_string( primary_domain );
189 } else {
190 ra_lanman_string( native_lanman );
192 } else if ( ra_type == RA_VISTA ) {
193 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
194 set_remote_arch(RA_OSX);
198 vuser = get_valid_user_struct(sconn, vuid);
199 if (vuser != NULL) {
200 reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
201 return;
204 /* Do we have a valid vuid now ? */
205 if (!is_partial_auth_vuid(sconn, vuid)) {
206 if (vuid != 0) {
207 reply_force_doserror(req, ERRSRV, ERRbaduid);
208 return;
211 /* No, start a new authentication setup. */
212 vuid = register_initial_vuid(sconn);
213 if (vuid == UID_FIELD_INVALID) {
214 reply_nterror(req, nt_status_squash(
215 NT_STATUS_INVALID_PARAMETER));
216 return;
220 vuser = get_partial_auth_user_struct(sconn, vuid);
221 /* This MUST be valid. */
222 if (!vuser) {
223 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
226 if (!vuser->gensec_security) {
227 status = auth_generic_prepare(vuser, sconn->remote_address,
228 &vuser->gensec_security);
229 if (!NT_STATUS_IS_OK(status)) {
230 /* Kill the intermediate vuid */
231 invalidate_vuid(sconn, vuid);
232 reply_nterror(req, nt_status_squash(status));
233 return;
236 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_SESSION_KEY);
237 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
239 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_SPNEGO);
240 if (!NT_STATUS_IS_OK(status)) {
241 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
242 /* Kill the intermediate vuid */
243 invalidate_vuid(sconn, vuid);
244 reply_nterror(req, nt_status_squash(status));
245 return;
249 status = gensec_update(vuser->gensec_security,
250 talloc_tos(), NULL,
251 in_blob, &out_blob);
252 if (!NT_STATUS_IS_OK(status) &&
253 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
254 /* Kill the intermediate vuid */
255 invalidate_vuid(sconn, vuid);
256 reply_nterror(req, nt_status_squash(status));
257 return;
260 if (NT_STATUS_IS_OK(status)) {
261 struct auth_session_info *session_info = NULL;
262 int tmp_vuid;
264 status = gensec_session_info(vuser->gensec_security,
265 talloc_tos(),
266 &session_info);
267 if (!NT_STATUS_IS_OK(status)) {
268 DEBUG(1,("Failed to generate session_info "
269 "(user and group token) for session setup: %s\n",
270 nt_errstr(status)));
271 /* Kill the intermediate vuid */
272 data_blob_free(&out_blob);
273 invalidate_vuid(sconn, vuid);
274 reply_nterror(req, nt_status_squash(status));
275 return;
278 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
279 action = 1;
282 /* register_existing_vuid keeps the server info */
283 tmp_vuid = register_existing_vuid(sconn, vuid,
284 session_info,
285 data_blob_null);
286 if (tmp_vuid != vuid) {
287 data_blob_free(&out_blob);
288 invalidate_vuid(sconn, vuid);
289 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
290 return;
293 /* current_user_info is changed on new vuid */
294 reload_services(sconn, conn_snum_used, true);
297 reply_outbuf(req, 4, 0);
299 SSVAL(req->outbuf, smb_uid, vuid);
300 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
301 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
302 SSVAL(req->outbuf, smb_vwv2, action);
303 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
305 if (message_push_blob(&req->outbuf, out_blob) == -1) {
306 data_blob_free(&out_blob);
307 invalidate_vuid(sconn, vuid);
308 reply_nterror(req, NT_STATUS_NO_MEMORY);
309 return;
311 data_blob_free(&out_blob);
313 if (push_signature(&req->outbuf) == -1) {
314 invalidate_vuid(sconn, vuid);
315 reply_nterror(req, NT_STATUS_NO_MEMORY);
316 return;
320 /****************************************************************************
321 On new VC == 0, shutdown *all* old connections and users.
322 It seems that only NT4.x does this. At W2K and above (XP etc.).
323 a new session setup with VC==0 is ignored.
324 ****************************************************************************/
326 struct shutdown_state {
327 const char *ip;
328 struct messaging_context *msg_ctx;
331 static int shutdown_other_smbds(const struct connections_key *key,
332 const struct connections_data *crec,
333 void *private_data)
335 struct shutdown_state *state = (struct shutdown_state *)private_data;
337 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
338 server_id_str(talloc_tos(), &crec->pid), crec->addr));
340 if (!process_exists(crec->pid)) {
341 DEBUG(10, ("process does not exist\n"));
342 return 0;
345 if (procid_is_me(&crec->pid)) {
346 DEBUG(10, ("It's me\n"));
347 return 0;
350 if (strcmp(state->ip, crec->addr) != 0) {
351 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
352 return 0;
355 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
356 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
357 state->ip));
359 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
360 &data_blob_null);
361 return 0;
364 static void setup_new_vc_session(struct smbd_server_connection *sconn)
366 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
367 "compatible we would close all old resources.\n"));
368 #if 0
369 conn_close_all();
370 invalidate_all_vuids();
371 #endif
372 if (lp_reset_on_zero_vc()) {
373 char *addr;
374 struct shutdown_state state;
376 addr = tsocket_address_inet_addr_string(
377 sconn->remote_address, talloc_tos());
378 if (addr == NULL) {
379 return;
381 state.ip = addr;
382 state.msg_ctx = sconn->msg_ctx;
383 connections_forall_read(shutdown_other_smbds, &state);
384 TALLOC_FREE(addr);
388 /****************************************************************************
389 Reply to a session setup command.
390 ****************************************************************************/
392 void reply_sesssetup_and_X(struct smb_request *req)
394 int sess_vuid;
395 int smb_bufsize;
396 DATA_BLOB lm_resp;
397 DATA_BLOB nt_resp;
398 DATA_BLOB plaintext_password;
399 char *tmp;
400 const char *user;
401 fstring sub_user; /* Sanitised username for substituion */
402 const char *domain;
403 const char *native_os;
404 const char *native_lanman;
405 const char *primary_domain;
406 struct auth_usersupplied_info *user_info = NULL;
407 struct auth_session_info *session_info = NULL;
408 uint16 smb_flag2 = req->flags2;
409 uint16_t action = 0;
411 NTSTATUS nt_status;
412 struct smbd_server_connection *sconn = req->sconn;
414 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
415 bool signing_allowed = false;
416 bool signing_mandatory = false;
418 START_PROFILE(SMBsesssetupX);
420 ZERO_STRUCT(lm_resp);
421 ZERO_STRUCT(nt_resp);
422 ZERO_STRUCT(plaintext_password);
424 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
426 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
427 signing_allowed = true;
429 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
430 signing_mandatory = true;
434 * We can call srv_set_signing_negotiated() each time.
435 * It finds out when it needs to turn into a noop
436 * itself.
438 srv_set_signing_negotiated(req->sconn,
439 signing_allowed,
440 signing_mandatory);
442 /* a SPNEGO session setup has 12 command words, whereas a normal
443 NT1 session setup has 13. See the cifs spec. */
444 if (req->wct == 12 &&
445 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
447 if (!sconn->smb1.negprot.spnego) {
448 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
449 "at SPNEGO session setup when it was not "
450 "negotiated.\n"));
451 reply_nterror(req, nt_status_squash(
452 NT_STATUS_LOGON_FAILURE));
453 END_PROFILE(SMBsesssetupX);
454 return;
457 if (SVAL(req->vwv+4, 0) == 0) {
458 setup_new_vc_session(req->sconn);
461 reply_sesssetup_and_X_spnego(req);
462 END_PROFILE(SMBsesssetupX);
463 return;
466 smb_bufsize = SVAL(req->vwv+2, 0);
468 if (get_Protocol() < PROTOCOL_NT1) {
469 uint16 passlen1 = SVAL(req->vwv+7, 0);
471 /* Never do NT status codes with protocols before NT1 as we
472 * don't get client caps. */
473 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
475 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
476 reply_nterror(req, nt_status_squash(
477 NT_STATUS_INVALID_PARAMETER));
478 END_PROFILE(SMBsesssetupX);
479 return;
482 if (doencrypt) {
483 lm_resp = data_blob(req->buf, passlen1);
484 } else {
485 plaintext_password = data_blob(req->buf, passlen1+1);
486 /* Ensure null termination */
487 plaintext_password.data[passlen1] = 0;
490 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
491 req->buf + passlen1, STR_TERMINATE);
492 user = tmp ? tmp : "";
494 domain = "";
496 } else {
497 uint16 passlen1 = SVAL(req->vwv+7, 0);
498 uint16 passlen2 = SVAL(req->vwv+8, 0);
499 enum remote_arch_types ra_type = get_remote_arch();
500 const uint8_t *p = req->buf;
501 const uint8_t *save_p = req->buf;
502 uint16 byte_count;
505 if(global_client_caps == 0) {
506 global_client_caps = IVAL(req->vwv+11, 0);
508 if (!(global_client_caps & CAP_STATUS32)) {
509 remove_from_common_flags2(
510 FLAGS2_32_BIT_ERROR_CODES);
513 /* client_caps is used as final determination if
514 * client is NT or Win95. This is needed to return
515 * the correct error codes in some circumstances.
518 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
519 ra_type == RA_WIN95) {
520 if(!(global_client_caps & (CAP_NT_SMBS|
521 CAP_STATUS32))) {
522 set_remote_arch( RA_WIN95);
527 if (!doencrypt) {
528 /* both Win95 and WinNT stuff up the password
529 * lengths for non-encrypting systems. Uggh.
531 if passlen1==24 its a win95 system, and its setting
532 the password length incorrectly. Luckily it still
533 works with the default code because Win95 will null
534 terminate the password anyway
536 if passlen1>0 and passlen2>0 then maybe its a NT box
537 and its setting passlen2 to some random value which
538 really stuffs things up. we need to fix that one. */
540 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
541 passlen2 != 1) {
542 passlen2 = 0;
546 /* check for nasty tricks */
547 if (passlen1 > MAX_PASS_LEN
548 || passlen1 > smbreq_bufrem(req, p)) {
549 reply_nterror(req, nt_status_squash(
550 NT_STATUS_INVALID_PARAMETER));
551 END_PROFILE(SMBsesssetupX);
552 return;
555 if (passlen2 > MAX_PASS_LEN
556 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
557 reply_nterror(req, nt_status_squash(
558 NT_STATUS_INVALID_PARAMETER));
559 END_PROFILE(SMBsesssetupX);
560 return;
563 /* Save the lanman2 password and the NT md4 password. */
565 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
566 doencrypt = False;
569 if (doencrypt) {
570 lm_resp = data_blob(p, passlen1);
571 nt_resp = data_blob(p+passlen1, passlen2);
572 } else {
573 char *pass = NULL;
574 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
576 if (unic && (passlen2 == 0) && passlen1) {
577 /* Only a ascii plaintext password was sent. */
578 (void)srvstr_pull_talloc(talloc_tos(),
579 req->inbuf,
580 req->flags2,
581 &pass,
582 req->buf,
583 passlen1,
584 STR_TERMINATE|STR_ASCII);
585 } else {
586 (void)srvstr_pull_talloc(talloc_tos(),
587 req->inbuf,
588 req->flags2,
589 &pass,
590 req->buf,
591 unic ? passlen2 : passlen1,
592 STR_TERMINATE);
594 if (!pass) {
595 reply_nterror(req, nt_status_squash(
596 NT_STATUS_INVALID_PARAMETER));
597 END_PROFILE(SMBsesssetupX);
598 return;
600 plaintext_password = data_blob(pass, strlen(pass)+1);
603 p += passlen1 + passlen2;
605 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
606 STR_TERMINATE);
607 user = tmp ? tmp : "";
609 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
610 STR_TERMINATE);
611 domain = tmp ? tmp : "";
613 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
614 STR_TERMINATE);
615 native_os = tmp ? tmp : "";
617 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
618 STR_TERMINATE);
619 native_lanman = tmp ? tmp : "";
621 /* not documented or decoded by Ethereal but there is one more
622 * string in the extra bytes which is the same as the
623 * PrimaryDomain when using extended security. Windows NT 4
624 * and 2003 use this string to store the native lanman string.
625 * Windows 9x does not include a string here at all so we have
626 * to check if we have any extra bytes left */
628 byte_count = SVAL(req->vwv+13, 0);
629 if ( PTR_DIFF(p, save_p) < byte_count) {
630 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
631 STR_TERMINATE);
632 primary_domain = tmp ? tmp : "";
633 } else {
634 primary_domain = talloc_strdup(talloc_tos(), "null");
637 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
638 "PrimaryDomain=[%s]\n",
639 domain, native_os, native_lanman, primary_domain));
641 if ( ra_type == RA_WIN2K ) {
642 if ( strlen(native_lanman) == 0 )
643 ra_lanman_string( primary_domain );
644 else
645 ra_lanman_string( native_lanman );
650 if (SVAL(req->vwv+4, 0) == 0) {
651 setup_new_vc_session(req->sconn);
654 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
655 domain, user, get_remote_machine_name()));
657 if (*user) {
658 if (sconn->smb1.negprot.spnego) {
660 /* This has to be here, because this is a perfectly
661 * valid behaviour for guest logons :-( */
663 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
664 "at 'normal' session setup after "
665 "negotiating spnego.\n"));
666 reply_nterror(req, nt_status_squash(
667 NT_STATUS_LOGON_FAILURE));
668 END_PROFILE(SMBsesssetupX);
669 return;
671 fstrcpy(sub_user, user);
672 } else {
673 fstrcpy(sub_user, "");
676 sub_set_smb_name(sub_user);
678 reload_services(sconn, conn_snum_used, true);
680 if (!*user) {
682 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
684 } else if (doencrypt) {
685 struct auth4_context *negprot_auth_context = NULL;
686 negprot_auth_context = sconn->smb1.negprot.auth_context;
687 if (!negprot_auth_context) {
688 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
689 "session setup without negprot denied!\n"));
690 reply_nterror(req, nt_status_squash(
691 NT_STATUS_LOGON_FAILURE));
692 END_PROFILE(SMBsesssetupX);
693 return;
695 nt_status = make_user_info_for_reply_enc(&user_info, user,
696 domain,
697 sconn->remote_address,
698 lm_resp, nt_resp);
699 if (NT_STATUS_IS_OK(nt_status)) {
700 nt_status = auth_check_password_session_info(negprot_auth_context,
701 req, user_info, &session_info);
703 } else {
704 struct auth4_context *plaintext_auth_context = NULL;
706 nt_status = make_auth4_context(
707 talloc_tos(), &plaintext_auth_context);
709 if (NT_STATUS_IS_OK(nt_status)) {
710 uint8_t chal[8];
712 plaintext_auth_context->get_ntlm_challenge(
713 plaintext_auth_context, chal);
715 if (!make_user_info_for_reply(&user_info,
716 user, domain,
717 sconn->remote_address,
718 chal,
719 plaintext_password)) {
720 nt_status = NT_STATUS_NO_MEMORY;
723 if (NT_STATUS_IS_OK(nt_status)) {
724 nt_status = auth_check_password_session_info(plaintext_auth_context,
725 req, user_info, &session_info);
727 TALLOC_FREE(plaintext_auth_context);
731 free_user_info(&user_info);
733 if (!NT_STATUS_IS_OK(nt_status)) {
734 data_blob_free(&nt_resp);
735 data_blob_free(&lm_resp);
736 data_blob_clear_free(&plaintext_password);
737 reply_nterror(req, nt_status_squash(nt_status));
738 END_PROFILE(SMBsesssetupX);
739 return;
742 data_blob_clear_free(&plaintext_password);
744 /* it's ok - setup a reply */
745 reply_outbuf(req, 3, 0);
746 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
747 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
749 if (get_Protocol() >= PROTOCOL_NT1) {
750 push_signature(&req->outbuf);
751 /* perhaps grab OS version here?? */
754 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
755 action = 1;
758 /* register the name and uid as being validated, so further connections
759 to a uid can get through without a password, on the same VC */
761 /* Ignore the initial vuid. */
762 sess_vuid = register_initial_vuid(sconn);
763 if (sess_vuid == UID_FIELD_INVALID) {
764 data_blob_free(&nt_resp);
765 data_blob_free(&lm_resp);
766 reply_nterror(req, nt_status_squash(
767 NT_STATUS_LOGON_FAILURE));
768 END_PROFILE(SMBsesssetupX);
769 return;
771 /* register_existing_vuid keeps the session_info */
772 sess_vuid = register_existing_vuid(sconn, sess_vuid,
773 session_info,
774 nt_resp.data ? nt_resp : lm_resp);
775 if (sess_vuid == UID_FIELD_INVALID) {
776 data_blob_free(&nt_resp);
777 data_blob_free(&lm_resp);
778 reply_nterror(req, nt_status_squash(
779 NT_STATUS_LOGON_FAILURE));
780 END_PROFILE(SMBsesssetupX);
781 return;
784 /* current_user_info is changed on new vuid */
785 reload_services(sconn, conn_snum_used, true);
787 data_blob_free(&nt_resp);
788 data_blob_free(&lm_resp);
790 SSVAL(req->outbuf,smb_vwv2,action);
791 SSVAL(req->outbuf,smb_uid,sess_vuid);
792 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
793 req->vuid = sess_vuid;
795 if (!sconn->smb1.sessions.done_sesssetup) {
796 sconn->smb1.sessions.max_send =
797 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
799 sconn->smb1.sessions.done_sesssetup = true;
801 END_PROFILE(SMBsesssetupX);