s3:util: rename procid_equal() to serverid_equal()
[Samba/wip.git] / source3 / smbd / sesssetup.c
blob81e56eb2084788c3069bec28a8669bff165a86cb
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 uint64_t 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 uint64_t 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;
336 struct server_id self_pid = messaging_server_id(state->msg_ctx);
338 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
339 server_id_str(talloc_tos(), &crec->pid), crec->addr));
341 if (!process_exists(crec->pid)) {
342 DEBUG(10, ("process does not exist\n"));
343 return 0;
346 if (serverid_equal(&crec->pid, &self_pid)) {
347 DEBUG(10, ("It's me\n"));
348 return 0;
351 if (strcmp(state->ip, crec->addr) != 0) {
352 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
353 return 0;
356 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
357 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
358 state->ip));
360 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
361 &data_blob_null);
362 return 0;
365 static void setup_new_vc_session(struct smbd_server_connection *sconn)
367 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
368 "compatible we would close all old resources.\n"));
369 #if 0
370 conn_close_all();
371 invalidate_all_vuids();
372 #endif
373 if (lp_reset_on_zero_vc()) {
374 char *addr;
375 struct shutdown_state state;
377 addr = tsocket_address_inet_addr_string(
378 sconn->remote_address, talloc_tos());
379 if (addr == NULL) {
380 return;
382 state.ip = addr;
383 state.msg_ctx = sconn->msg_ctx;
384 connections_forall_read(shutdown_other_smbds, &state);
385 TALLOC_FREE(addr);
389 /****************************************************************************
390 Reply to a session setup command.
391 ****************************************************************************/
393 void reply_sesssetup_and_X(struct smb_request *req)
395 uint64_t sess_vuid;
396 int smb_bufsize;
397 DATA_BLOB lm_resp;
398 DATA_BLOB nt_resp;
399 DATA_BLOB plaintext_password;
400 char *tmp;
401 const char *user;
402 fstring sub_user; /* Sanitised username for substituion */
403 const char *domain;
404 const char *native_os;
405 const char *native_lanman;
406 const char *primary_domain;
407 struct auth_usersupplied_info *user_info = NULL;
408 struct auth_session_info *session_info = NULL;
409 uint16 smb_flag2 = req->flags2;
410 uint16_t action = 0;
412 NTSTATUS nt_status;
413 struct smbd_server_connection *sconn = req->sconn;
415 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
416 bool signing_allowed = false;
417 bool signing_mandatory = false;
419 START_PROFILE(SMBsesssetupX);
421 ZERO_STRUCT(lm_resp);
422 ZERO_STRUCT(nt_resp);
423 ZERO_STRUCT(plaintext_password);
425 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
427 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
428 signing_allowed = true;
430 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
431 signing_mandatory = true;
435 * We can call srv_set_signing_negotiated() each time.
436 * It finds out when it needs to turn into a noop
437 * itself.
439 srv_set_signing_negotiated(req->sconn,
440 signing_allowed,
441 signing_mandatory);
443 /* a SPNEGO session setup has 12 command words, whereas a normal
444 NT1 session setup has 13. See the cifs spec. */
445 if (req->wct == 12 &&
446 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
448 if (!sconn->smb1.negprot.spnego) {
449 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
450 "at SPNEGO session setup when it was not "
451 "negotiated.\n"));
452 reply_nterror(req, nt_status_squash(
453 NT_STATUS_LOGON_FAILURE));
454 END_PROFILE(SMBsesssetupX);
455 return;
458 if (SVAL(req->vwv+4, 0) == 0) {
459 setup_new_vc_session(req->sconn);
462 reply_sesssetup_and_X_spnego(req);
463 END_PROFILE(SMBsesssetupX);
464 return;
467 smb_bufsize = SVAL(req->vwv+2, 0);
469 if (get_Protocol() < PROTOCOL_NT1) {
470 uint16 passlen1 = SVAL(req->vwv+7, 0);
472 /* Never do NT status codes with protocols before NT1 as we
473 * don't get client caps. */
474 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
476 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
477 reply_nterror(req, nt_status_squash(
478 NT_STATUS_INVALID_PARAMETER));
479 END_PROFILE(SMBsesssetupX);
480 return;
483 if (doencrypt) {
484 lm_resp = data_blob(req->buf, passlen1);
485 } else {
486 plaintext_password = data_blob(req->buf, passlen1+1);
487 /* Ensure null termination */
488 plaintext_password.data[passlen1] = 0;
491 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
492 req->buf + passlen1, STR_TERMINATE);
493 user = tmp ? tmp : "";
495 domain = "";
497 } else {
498 uint16 passlen1 = SVAL(req->vwv+7, 0);
499 uint16 passlen2 = SVAL(req->vwv+8, 0);
500 enum remote_arch_types ra_type = get_remote_arch();
501 const uint8_t *p = req->buf;
502 const uint8_t *save_p = req->buf;
503 uint16 byte_count;
506 if(global_client_caps == 0) {
507 global_client_caps = IVAL(req->vwv+11, 0);
509 if (!(global_client_caps & CAP_STATUS32)) {
510 remove_from_common_flags2(
511 FLAGS2_32_BIT_ERROR_CODES);
514 /* client_caps is used as final determination if
515 * client is NT or Win95. This is needed to return
516 * the correct error codes in some circumstances.
519 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
520 ra_type == RA_WIN95) {
521 if(!(global_client_caps & (CAP_NT_SMBS|
522 CAP_STATUS32))) {
523 set_remote_arch( RA_WIN95);
528 if (!doencrypt) {
529 /* both Win95 and WinNT stuff up the password
530 * lengths for non-encrypting systems. Uggh.
532 if passlen1==24 its a win95 system, and its setting
533 the password length incorrectly. Luckily it still
534 works with the default code because Win95 will null
535 terminate the password anyway
537 if passlen1>0 and passlen2>0 then maybe its a NT box
538 and its setting passlen2 to some random value which
539 really stuffs things up. we need to fix that one. */
541 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
542 passlen2 != 1) {
543 passlen2 = 0;
547 /* check for nasty tricks */
548 if (passlen1 > MAX_PASS_LEN
549 || passlen1 > smbreq_bufrem(req, p)) {
550 reply_nterror(req, nt_status_squash(
551 NT_STATUS_INVALID_PARAMETER));
552 END_PROFILE(SMBsesssetupX);
553 return;
556 if (passlen2 > MAX_PASS_LEN
557 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
558 reply_nterror(req, nt_status_squash(
559 NT_STATUS_INVALID_PARAMETER));
560 END_PROFILE(SMBsesssetupX);
561 return;
564 /* Save the lanman2 password and the NT md4 password. */
566 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
567 doencrypt = False;
570 if (doencrypt) {
571 lm_resp = data_blob(p, passlen1);
572 nt_resp = data_blob(p+passlen1, passlen2);
573 } else {
574 char *pass = NULL;
575 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
577 if (unic && (passlen2 == 0) && passlen1) {
578 /* Only a ascii plaintext password was sent. */
579 (void)srvstr_pull_talloc(talloc_tos(),
580 req->inbuf,
581 req->flags2,
582 &pass,
583 req->buf,
584 passlen1,
585 STR_TERMINATE|STR_ASCII);
586 } else {
587 (void)srvstr_pull_talloc(talloc_tos(),
588 req->inbuf,
589 req->flags2,
590 &pass,
591 req->buf,
592 unic ? passlen2 : passlen1,
593 STR_TERMINATE);
595 if (!pass) {
596 reply_nterror(req, nt_status_squash(
597 NT_STATUS_INVALID_PARAMETER));
598 END_PROFILE(SMBsesssetupX);
599 return;
601 plaintext_password = data_blob(pass, strlen(pass)+1);
604 p += passlen1 + passlen2;
606 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
607 STR_TERMINATE);
608 user = tmp ? tmp : "";
610 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
611 STR_TERMINATE);
612 domain = tmp ? tmp : "";
614 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
615 STR_TERMINATE);
616 native_os = tmp ? tmp : "";
618 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
619 STR_TERMINATE);
620 native_lanman = tmp ? tmp : "";
622 /* not documented or decoded by Ethereal but there is one more
623 * string in the extra bytes which is the same as the
624 * PrimaryDomain when using extended security. Windows NT 4
625 * and 2003 use this string to store the native lanman string.
626 * Windows 9x does not include a string here at all so we have
627 * to check if we have any extra bytes left */
629 byte_count = SVAL(req->vwv+13, 0);
630 if ( PTR_DIFF(p, save_p) < byte_count) {
631 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
632 STR_TERMINATE);
633 primary_domain = tmp ? tmp : "";
634 } else {
635 primary_domain = talloc_strdup(talloc_tos(), "null");
638 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
639 "PrimaryDomain=[%s]\n",
640 domain, native_os, native_lanman, primary_domain));
642 if ( ra_type == RA_WIN2K ) {
643 if ( strlen(native_lanman) == 0 )
644 ra_lanman_string( primary_domain );
645 else
646 ra_lanman_string( native_lanman );
651 if (SVAL(req->vwv+4, 0) == 0) {
652 setup_new_vc_session(req->sconn);
655 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
656 domain, user, get_remote_machine_name()));
658 if (*user) {
659 if (sconn->smb1.negprot.spnego) {
661 /* This has to be here, because this is a perfectly
662 * valid behaviour for guest logons :-( */
664 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
665 "at 'normal' session setup after "
666 "negotiating spnego.\n"));
667 reply_nterror(req, nt_status_squash(
668 NT_STATUS_LOGON_FAILURE));
669 END_PROFILE(SMBsesssetupX);
670 return;
672 fstrcpy(sub_user, user);
673 } else {
674 fstrcpy(sub_user, "");
677 sub_set_smb_name(sub_user);
679 reload_services(sconn, conn_snum_used, true);
681 if (!*user) {
683 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
685 } else if (doencrypt) {
686 struct auth4_context *negprot_auth_context = NULL;
687 negprot_auth_context = sconn->smb1.negprot.auth_context;
688 if (!negprot_auth_context) {
689 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
690 "session setup without negprot denied!\n"));
691 reply_nterror(req, nt_status_squash(
692 NT_STATUS_LOGON_FAILURE));
693 END_PROFILE(SMBsesssetupX);
694 return;
696 nt_status = make_user_info_for_reply_enc(&user_info, user,
697 domain,
698 sconn->remote_address,
699 lm_resp, nt_resp);
700 if (NT_STATUS_IS_OK(nt_status)) {
701 nt_status = auth_check_password_session_info(negprot_auth_context,
702 req, user_info, &session_info);
704 } else {
705 struct auth4_context *plaintext_auth_context = NULL;
707 nt_status = make_auth4_context(
708 talloc_tos(), &plaintext_auth_context);
710 if (NT_STATUS_IS_OK(nt_status)) {
711 uint8_t chal[8];
713 plaintext_auth_context->get_ntlm_challenge(
714 plaintext_auth_context, chal);
716 if (!make_user_info_for_reply(&user_info,
717 user, domain,
718 sconn->remote_address,
719 chal,
720 plaintext_password)) {
721 nt_status = NT_STATUS_NO_MEMORY;
724 if (NT_STATUS_IS_OK(nt_status)) {
725 nt_status = auth_check_password_session_info(plaintext_auth_context,
726 req, user_info, &session_info);
728 TALLOC_FREE(plaintext_auth_context);
732 free_user_info(&user_info);
734 if (!NT_STATUS_IS_OK(nt_status)) {
735 data_blob_free(&nt_resp);
736 data_blob_free(&lm_resp);
737 data_blob_clear_free(&plaintext_password);
738 reply_nterror(req, nt_status_squash(nt_status));
739 END_PROFILE(SMBsesssetupX);
740 return;
743 data_blob_clear_free(&plaintext_password);
745 /* it's ok - setup a reply */
746 reply_outbuf(req, 3, 0);
747 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
748 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
750 if (get_Protocol() >= PROTOCOL_NT1) {
751 push_signature(&req->outbuf);
752 /* perhaps grab OS version here?? */
755 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
756 action = 1;
759 /* register the name and uid as being validated, so further connections
760 to a uid can get through without a password, on the same VC */
762 /* Ignore the initial vuid. */
763 sess_vuid = register_initial_vuid(sconn);
764 if (sess_vuid == UID_FIELD_INVALID) {
765 data_blob_free(&nt_resp);
766 data_blob_free(&lm_resp);
767 reply_nterror(req, nt_status_squash(
768 NT_STATUS_LOGON_FAILURE));
769 END_PROFILE(SMBsesssetupX);
770 return;
772 /* register_existing_vuid keeps the session_info */
773 sess_vuid = register_existing_vuid(sconn, sess_vuid,
774 session_info,
775 nt_resp.data ? nt_resp : lm_resp);
776 if (sess_vuid == UID_FIELD_INVALID) {
777 data_blob_free(&nt_resp);
778 data_blob_free(&lm_resp);
779 reply_nterror(req, nt_status_squash(
780 NT_STATUS_LOGON_FAILURE));
781 END_PROFILE(SMBsesssetupX);
782 return;
785 /* current_user_info is changed on new vuid */
786 reload_services(sconn, conn_snum_used, true);
788 data_blob_free(&nt_resp);
789 data_blob_free(&lm_resp);
791 SSVAL(req->outbuf,smb_vwv2,action);
792 SSVAL(req->outbuf,smb_uid,sess_vuid);
793 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
794 req->vuid = sess_vuid;
796 if (!sconn->smb1.sessions.done_sesssetup) {
797 sconn->smb1.sessions.max_send =
798 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
800 sconn->smb1.sessions.done_sesssetup = true;
802 END_PROFILE(SMBsesssetupX);