s3:libsmb/cliconnect: make use of ntlmssp_is_anonymous()
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blob7d1535af5ac35104c52d2e4c20419eca423bd0a8
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 /* No, start a new authentication setup. */
206 vuid = register_initial_vuid(sconn);
207 if (vuid == UID_FIELD_INVALID) {
208 reply_nterror(req, nt_status_squash(
209 NT_STATUS_INVALID_PARAMETER));
210 return;
214 vuser = get_partial_auth_user_struct(sconn, vuid);
215 /* This MUST be valid. */
216 if (!vuser) {
217 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
220 if (!vuser->gensec_security) {
221 status = auth_generic_prepare(vuser, sconn->remote_address,
222 &vuser->gensec_security);
223 if (!NT_STATUS_IS_OK(status)) {
224 /* Kill the intermediate vuid */
225 invalidate_vuid(sconn, vuid);
226 reply_nterror(req, nt_status_squash(status));
227 return;
230 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_SESSION_KEY);
231 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
233 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_SPNEGO);
234 if (!NT_STATUS_IS_OK(status)) {
235 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
236 /* Kill the intermediate vuid */
237 invalidate_vuid(sconn, vuid);
238 reply_nterror(req, nt_status_squash(status));
239 return;
243 status = gensec_update(vuser->gensec_security,
244 talloc_tos(), NULL,
245 in_blob, &out_blob);
246 if (!NT_STATUS_IS_OK(status) &&
247 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
248 /* Kill the intermediate vuid */
249 invalidate_vuid(sconn, vuid);
250 reply_nterror(req, nt_status_squash(status));
251 return;
254 if (NT_STATUS_IS_OK(status)) {
255 struct auth_session_info *session_info = NULL;
256 int tmp_vuid;
258 status = gensec_session_info(vuser->gensec_security,
259 talloc_tos(),
260 &session_info);
261 if (!NT_STATUS_IS_OK(status)) {
262 DEBUG(1,("Failed to generate session_info "
263 "(user and group token) for session setup: %s\n",
264 nt_errstr(status)));
265 /* Kill the intermediate vuid */
266 data_blob_free(&out_blob);
267 invalidate_vuid(sconn, vuid);
268 reply_nterror(req, nt_status_squash(status));
269 return;
272 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
273 action = 1;
276 /* register_existing_vuid keeps the server info */
277 tmp_vuid = register_existing_vuid(sconn, vuid,
278 session_info,
279 data_blob_null);
280 if (tmp_vuid != vuid) {
281 data_blob_free(&out_blob);
282 invalidate_vuid(sconn, vuid);
283 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
284 return;
287 /* current_user_info is changed on new vuid */
288 reload_services(sconn, conn_snum_used, true);
291 reply_outbuf(req, 4, 0);
293 SSVAL(req->outbuf, smb_uid, vuid);
294 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
295 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
296 SSVAL(req->outbuf, smb_vwv2, action);
297 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
299 if (message_push_blob(&req->outbuf, out_blob) == -1) {
300 data_blob_free(&out_blob);
301 invalidate_vuid(sconn, vuid);
302 reply_nterror(req, NT_STATUS_NO_MEMORY);
303 return;
305 data_blob_free(&out_blob);
307 if (push_signature(&req->outbuf) == -1) {
308 invalidate_vuid(sconn, vuid);
309 reply_nterror(req, NT_STATUS_NO_MEMORY);
310 return;
314 /****************************************************************************
315 On new VC == 0, shutdown *all* old connections and users.
316 It seems that only NT4.x does this. At W2K and above (XP etc.).
317 a new session setup with VC==0 is ignored.
318 ****************************************************************************/
320 struct shutdown_state {
321 const char *ip;
322 struct messaging_context *msg_ctx;
325 static int shutdown_other_smbds(const struct connections_key *key,
326 const struct connections_data *crec,
327 void *private_data)
329 struct shutdown_state *state = (struct shutdown_state *)private_data;
331 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
332 server_id_str(talloc_tos(), &crec->pid), crec->addr));
334 if (!process_exists(crec->pid)) {
335 DEBUG(10, ("process does not exist\n"));
336 return 0;
339 if (procid_is_me(&crec->pid)) {
340 DEBUG(10, ("It's me\n"));
341 return 0;
344 if (strcmp(state->ip, crec->addr) != 0) {
345 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
346 return 0;
349 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
350 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
351 state->ip));
353 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
354 &data_blob_null);
355 return 0;
358 static void setup_new_vc_session(struct smbd_server_connection *sconn)
360 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
361 "compatible we would close all old resources.\n"));
362 #if 0
363 conn_close_all();
364 invalidate_all_vuids();
365 #endif
366 if (lp_reset_on_zero_vc()) {
367 char *addr;
368 struct shutdown_state state;
370 addr = tsocket_address_inet_addr_string(
371 sconn->remote_address, talloc_tos());
372 if (addr == NULL) {
373 return;
375 state.ip = addr;
376 state.msg_ctx = sconn->msg_ctx;
377 connections_forall_read(shutdown_other_smbds, &state);
378 TALLOC_FREE(addr);
382 /****************************************************************************
383 Reply to a session setup command.
384 ****************************************************************************/
386 void reply_sesssetup_and_X(struct smb_request *req)
388 int sess_vuid;
389 int smb_bufsize;
390 DATA_BLOB lm_resp;
391 DATA_BLOB nt_resp;
392 DATA_BLOB plaintext_password;
393 char *tmp;
394 const char *user;
395 fstring sub_user; /* Sanitised username for substituion */
396 const char *domain;
397 const char *native_os;
398 const char *native_lanman;
399 const char *primary_domain;
400 struct auth_usersupplied_info *user_info = NULL;
401 struct auth_session_info *session_info = NULL;
402 uint16 smb_flag2 = req->flags2;
403 uint16_t action = 0;
405 NTSTATUS nt_status;
406 struct smbd_server_connection *sconn = req->sconn;
408 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
409 bool signing_allowed = false;
410 bool signing_mandatory = false;
412 START_PROFILE(SMBsesssetupX);
414 ZERO_STRUCT(lm_resp);
415 ZERO_STRUCT(nt_resp);
416 ZERO_STRUCT(plaintext_password);
418 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
420 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
421 signing_allowed = true;
423 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
424 signing_mandatory = true;
428 * We can call srv_set_signing_negotiated() each time.
429 * It finds out when it needs to turn into a noop
430 * itself.
432 srv_set_signing_negotiated(req->sconn,
433 signing_allowed,
434 signing_mandatory);
436 /* a SPNEGO session setup has 12 command words, whereas a normal
437 NT1 session setup has 13. See the cifs spec. */
438 if (req->wct == 12 &&
439 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
441 if (!sconn->smb1.negprot.spnego) {
442 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
443 "at SPNEGO session setup when it was not "
444 "negotiated.\n"));
445 reply_nterror(req, nt_status_squash(
446 NT_STATUS_LOGON_FAILURE));
447 END_PROFILE(SMBsesssetupX);
448 return;
451 if (SVAL(req->vwv+4, 0) == 0) {
452 setup_new_vc_session(req->sconn);
455 reply_sesssetup_and_X_spnego(req);
456 END_PROFILE(SMBsesssetupX);
457 return;
460 smb_bufsize = SVAL(req->vwv+2, 0);
462 if (get_Protocol() < PROTOCOL_NT1) {
463 uint16 passlen1 = SVAL(req->vwv+7, 0);
465 /* Never do NT status codes with protocols before NT1 as we
466 * don't get client caps. */
467 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
469 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
470 reply_nterror(req, nt_status_squash(
471 NT_STATUS_INVALID_PARAMETER));
472 END_PROFILE(SMBsesssetupX);
473 return;
476 if (doencrypt) {
477 lm_resp = data_blob(req->buf, passlen1);
478 } else {
479 plaintext_password = data_blob(req->buf, passlen1+1);
480 /* Ensure null termination */
481 plaintext_password.data[passlen1] = 0;
484 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
485 req->buf + passlen1, STR_TERMINATE);
486 user = tmp ? tmp : "";
488 domain = "";
490 } else {
491 uint16 passlen1 = SVAL(req->vwv+7, 0);
492 uint16 passlen2 = SVAL(req->vwv+8, 0);
493 enum remote_arch_types ra_type = get_remote_arch();
494 const uint8_t *p = req->buf;
495 const uint8_t *save_p = req->buf;
496 uint16 byte_count;
499 if(global_client_caps == 0) {
500 global_client_caps = IVAL(req->vwv+11, 0);
502 if (!(global_client_caps & CAP_STATUS32)) {
503 remove_from_common_flags2(
504 FLAGS2_32_BIT_ERROR_CODES);
507 /* client_caps is used as final determination if
508 * client is NT or Win95. This is needed to return
509 * the correct error codes in some circumstances.
512 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
513 ra_type == RA_WIN95) {
514 if(!(global_client_caps & (CAP_NT_SMBS|
515 CAP_STATUS32))) {
516 set_remote_arch( RA_WIN95);
521 if (!doencrypt) {
522 /* both Win95 and WinNT stuff up the password
523 * lengths for non-encrypting systems. Uggh.
525 if passlen1==24 its a win95 system, and its setting
526 the password length incorrectly. Luckily it still
527 works with the default code because Win95 will null
528 terminate the password anyway
530 if passlen1>0 and passlen2>0 then maybe its a NT box
531 and its setting passlen2 to some random value which
532 really stuffs things up. we need to fix that one. */
534 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
535 passlen2 != 1) {
536 passlen2 = 0;
540 /* check for nasty tricks */
541 if (passlen1 > MAX_PASS_LEN
542 || passlen1 > smbreq_bufrem(req, p)) {
543 reply_nterror(req, nt_status_squash(
544 NT_STATUS_INVALID_PARAMETER));
545 END_PROFILE(SMBsesssetupX);
546 return;
549 if (passlen2 > MAX_PASS_LEN
550 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
551 reply_nterror(req, nt_status_squash(
552 NT_STATUS_INVALID_PARAMETER));
553 END_PROFILE(SMBsesssetupX);
554 return;
557 /* Save the lanman2 password and the NT md4 password. */
559 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
560 doencrypt = False;
563 if (doencrypt) {
564 lm_resp = data_blob(p, passlen1);
565 nt_resp = data_blob(p+passlen1, passlen2);
566 } else {
567 char *pass = NULL;
568 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
570 if (unic && (passlen2 == 0) && passlen1) {
571 /* Only a ascii plaintext password was sent. */
572 (void)srvstr_pull_talloc(talloc_tos(),
573 req->inbuf,
574 req->flags2,
575 &pass,
576 req->buf,
577 passlen1,
578 STR_TERMINATE|STR_ASCII);
579 } else {
580 (void)srvstr_pull_talloc(talloc_tos(),
581 req->inbuf,
582 req->flags2,
583 &pass,
584 req->buf,
585 unic ? passlen2 : passlen1,
586 STR_TERMINATE);
588 if (!pass) {
589 reply_nterror(req, nt_status_squash(
590 NT_STATUS_INVALID_PARAMETER));
591 END_PROFILE(SMBsesssetupX);
592 return;
594 plaintext_password = data_blob(pass, strlen(pass)+1);
597 p += passlen1 + passlen2;
599 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
600 STR_TERMINATE);
601 user = tmp ? tmp : "";
603 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
604 STR_TERMINATE);
605 domain = tmp ? tmp : "";
607 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
608 STR_TERMINATE);
609 native_os = tmp ? tmp : "";
611 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
612 STR_TERMINATE);
613 native_lanman = tmp ? tmp : "";
615 /* not documented or decoded by Ethereal but there is one more
616 * string in the extra bytes which is the same as the
617 * PrimaryDomain when using extended security. Windows NT 4
618 * and 2003 use this string to store the native lanman string.
619 * Windows 9x does not include a string here at all so we have
620 * to check if we have any extra bytes left */
622 byte_count = SVAL(req->vwv+13, 0);
623 if ( PTR_DIFF(p, save_p) < byte_count) {
624 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
625 STR_TERMINATE);
626 primary_domain = tmp ? tmp : "";
627 } else {
628 primary_domain = talloc_strdup(talloc_tos(), "null");
631 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
632 "PrimaryDomain=[%s]\n",
633 domain, native_os, native_lanman, primary_domain));
635 if ( ra_type == RA_WIN2K ) {
636 if ( strlen(native_lanman) == 0 )
637 ra_lanman_string( primary_domain );
638 else
639 ra_lanman_string( native_lanman );
644 if (SVAL(req->vwv+4, 0) == 0) {
645 setup_new_vc_session(req->sconn);
648 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
649 domain, user, get_remote_machine_name()));
651 if (*user) {
652 if (sconn->smb1.negprot.spnego) {
654 /* This has to be here, because this is a perfectly
655 * valid behaviour for guest logons :-( */
657 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
658 "at 'normal' session setup after "
659 "negotiating spnego.\n"));
660 reply_nterror(req, nt_status_squash(
661 NT_STATUS_LOGON_FAILURE));
662 END_PROFILE(SMBsesssetupX);
663 return;
665 fstrcpy(sub_user, user);
666 } else {
667 fstrcpy(sub_user, "");
670 sub_set_smb_name(sub_user);
672 reload_services(sconn, conn_snum_used, true);
674 if (!*user) {
676 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
678 } else if (doencrypt) {
679 struct auth4_context *negprot_auth_context = NULL;
680 negprot_auth_context = sconn->smb1.negprot.auth_context;
681 if (!negprot_auth_context) {
682 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
683 "session setup without negprot denied!\n"));
684 reply_nterror(req, nt_status_squash(
685 NT_STATUS_LOGON_FAILURE));
686 END_PROFILE(SMBsesssetupX);
687 return;
689 nt_status = make_user_info_for_reply_enc(&user_info, user,
690 domain,
691 sconn->remote_address,
692 lm_resp, nt_resp);
693 if (NT_STATUS_IS_OK(nt_status)) {
694 nt_status = auth_check_password_session_info(negprot_auth_context,
695 req, user_info, &session_info);
697 } else {
698 struct auth4_context *plaintext_auth_context = NULL;
700 nt_status = make_auth4_context(
701 talloc_tos(), &plaintext_auth_context);
703 if (NT_STATUS_IS_OK(nt_status)) {
704 uint8_t chal[8];
706 plaintext_auth_context->get_ntlm_challenge(
707 plaintext_auth_context, chal);
709 if (!make_user_info_for_reply(&user_info,
710 user, domain,
711 sconn->remote_address,
712 chal,
713 plaintext_password)) {
714 nt_status = NT_STATUS_NO_MEMORY;
717 if (NT_STATUS_IS_OK(nt_status)) {
718 nt_status = auth_check_password_session_info(plaintext_auth_context,
719 req, user_info, &session_info);
721 TALLOC_FREE(plaintext_auth_context);
725 free_user_info(&user_info);
727 if (!NT_STATUS_IS_OK(nt_status)) {
728 data_blob_free(&nt_resp);
729 data_blob_free(&lm_resp);
730 data_blob_clear_free(&plaintext_password);
731 reply_nterror(req, nt_status_squash(nt_status));
732 END_PROFILE(SMBsesssetupX);
733 return;
736 data_blob_clear_free(&plaintext_password);
738 /* it's ok - setup a reply */
739 reply_outbuf(req, 3, 0);
740 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
741 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
743 if (get_Protocol() >= PROTOCOL_NT1) {
744 push_signature(&req->outbuf);
745 /* perhaps grab OS version here?? */
748 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
749 action = 1;
752 /* register the name and uid as being validated, so further connections
753 to a uid can get through without a password, on the same VC */
755 /* Ignore the initial vuid. */
756 sess_vuid = register_initial_vuid(sconn);
757 if (sess_vuid == UID_FIELD_INVALID) {
758 data_blob_free(&nt_resp);
759 data_blob_free(&lm_resp);
760 reply_nterror(req, nt_status_squash(
761 NT_STATUS_LOGON_FAILURE));
762 END_PROFILE(SMBsesssetupX);
763 return;
765 /* register_existing_vuid keeps the session_info */
766 sess_vuid = register_existing_vuid(sconn, sess_vuid,
767 session_info,
768 nt_resp.data ? nt_resp : lm_resp);
769 if (sess_vuid == UID_FIELD_INVALID) {
770 data_blob_free(&nt_resp);
771 data_blob_free(&lm_resp);
772 reply_nterror(req, nt_status_squash(
773 NT_STATUS_LOGON_FAILURE));
774 END_PROFILE(SMBsesssetupX);
775 return;
778 /* current_user_info is changed on new vuid */
779 reload_services(sconn, conn_snum_used, true);
781 data_blob_free(&nt_resp);
782 data_blob_free(&lm_resp);
784 SSVAL(req->outbuf,smb_vwv2,action);
785 SSVAL(req->outbuf,smb_uid,sess_vuid);
786 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
787 req->vuid = sess_vuid;
789 if (!sconn->smb1.sessions.done_sesssetup) {
790 sconn->smb1.sessions.max_send =
791 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
793 sconn->smb1.sessions.done_sesssetup = true;
795 END_PROFILE(SMBsesssetupX);