lib/util: Remove unused sys_select_signal()
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blob1741f4ff9069ca13406332565159952b3d3b5a54
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 struct auth_serversupplied_info **server_info)
82 struct auth_context *auth_context;
83 struct auth_usersupplied_info *user_info = NULL;
85 NTSTATUS nt_status;
86 static unsigned char chal[8] = { 0, };
88 DEBUG(3,("Got anonymous request\n"));
90 nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
91 if (!NT_STATUS_IS_OK(nt_status)) {
92 return nt_status;
95 if (!make_user_info_guest(remote_address, &user_info)) {
96 TALLOC_FREE(auth_context);
97 return NT_STATUS_NO_MEMORY;
100 nt_status = auth_context->check_ntlm_password(auth_context,
101 user_info,
102 server_info);
103 TALLOC_FREE(auth_context);
104 free_user_info(&user_info);
105 return nt_status;
108 /****************************************************************************
109 Reply to a session setup command.
110 conn POINTER CAN BE NULL HERE !
111 ****************************************************************************/
113 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
115 const uint8 *p;
116 DATA_BLOB in_blob;
117 DATA_BLOB out_blob = data_blob_null;
118 size_t bufrem;
119 char *tmp;
120 const char *native_os;
121 const char *native_lanman;
122 const char *primary_domain;
123 const char *p2;
124 uint16 data_blob_len = SVAL(req->vwv+7, 0);
125 enum remote_arch_types ra_type = get_remote_arch();
126 int vuid = req->vuid;
127 user_struct *vuser = NULL;
128 NTSTATUS status = NT_STATUS_OK;
129 struct smbd_server_connection *sconn = req->sconn;
130 uint16_t action = 0;
132 DEBUG(3,("Doing spnego session setup\n"));
134 if (global_client_caps == 0) {
135 global_client_caps = IVAL(req->vwv+10, 0);
137 if (!(global_client_caps & CAP_STATUS32)) {
138 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
142 p = req->buf;
144 if (data_blob_len == 0) {
145 /* an invalid request */
146 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
147 return;
150 bufrem = smbreq_bufrem(req, p);
151 /* pull the spnego blob */
152 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
154 #if 0
155 file_save("negotiate.dat", in_blob.data, in_blob.length);
156 #endif
158 p2 = (const char *)req->buf + in_blob.length;
160 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
161 STR_TERMINATE);
162 native_os = tmp ? tmp : "";
164 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
165 STR_TERMINATE);
166 native_lanman = tmp ? tmp : "";
168 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
169 STR_TERMINATE);
170 primary_domain = tmp ? tmp : "";
172 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
173 native_os, native_lanman, primary_domain));
175 if ( ra_type == RA_WIN2K ) {
176 /* Vista sets neither the OS or lanman strings */
178 if ( !strlen(native_os) && !strlen(native_lanman) )
179 set_remote_arch(RA_VISTA);
181 /* Windows 2003 doesn't set the native lanman string,
182 but does set primary domain which is a bug I think */
184 if ( !strlen(native_lanman) ) {
185 ra_lanman_string( primary_domain );
186 } else {
187 ra_lanman_string( native_lanman );
189 } else if ( ra_type == RA_VISTA ) {
190 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
191 set_remote_arch(RA_OSX);
195 vuser = get_valid_user_struct(sconn, vuid);
196 if (vuser != NULL) {
197 reply_nterror(req, NT_STATUS_REQUEST_NOT_ACCEPTED);
198 return;
201 /* Do we have a valid vuid now ? */
202 if (!is_partial_auth_vuid(sconn, vuid)) {
203 /* No, start a new authentication setup. */
204 vuid = register_initial_vuid(sconn);
205 if (vuid == UID_FIELD_INVALID) {
206 reply_nterror(req, nt_status_squash(
207 NT_STATUS_INVALID_PARAMETER));
208 return;
212 vuser = get_partial_auth_user_struct(sconn, vuid);
213 /* This MUST be valid. */
214 if (!vuser) {
215 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
218 if (!vuser->gensec_security) {
219 status = auth_generic_prepare(vuser, sconn->remote_address,
220 &vuser->gensec_security);
221 if (!NT_STATUS_IS_OK(status)) {
222 /* Kill the intermediate vuid */
223 invalidate_vuid(sconn, vuid);
224 reply_nterror(req, nt_status_squash(status));
225 return;
228 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_SESSION_KEY);
229 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
231 status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_SPNEGO);
232 if (!NT_STATUS_IS_OK(status)) {
233 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
234 /* Kill the intermediate vuid */
235 invalidate_vuid(sconn, vuid);
236 reply_nterror(req, nt_status_squash(status));
237 return;
241 status = gensec_update(vuser->gensec_security,
242 talloc_tos(), NULL,
243 in_blob, &out_blob);
244 if (!NT_STATUS_IS_OK(status) &&
245 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
246 /* Kill the intermediate vuid */
247 invalidate_vuid(sconn, vuid);
248 reply_nterror(req, nt_status_squash(status));
249 return;
252 if (NT_STATUS_IS_OK(status)) {
253 struct auth_session_info *session_info = NULL;
254 int tmp_vuid;
256 status = gensec_session_info(vuser->gensec_security,
257 talloc_tos(),
258 &session_info);
259 if (!NT_STATUS_IS_OK(status)) {
260 /* Kill the intermediate vuid */
261 data_blob_free(&out_blob);
262 invalidate_vuid(sconn, vuid);
263 reply_nterror(req, nt_status_squash(status));
264 return;
267 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
268 action = 1;
271 /* register_existing_vuid keeps the server info */
272 tmp_vuid = register_existing_vuid(sconn, vuid,
273 session_info,
274 data_blob_null);
275 if (tmp_vuid != vuid) {
276 data_blob_free(&out_blob);
277 invalidate_vuid(sconn, vuid);
278 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
279 return;
282 /* current_user_info is changed on new vuid */
283 reload_services(sconn, conn_snum_used, true);
286 reply_outbuf(req, 4, 0);
288 SSVAL(req->outbuf, smb_uid, vuid);
289 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
290 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
291 SSVAL(req->outbuf, smb_vwv2, action);
292 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
294 if (message_push_blob(&req->outbuf, out_blob) == -1) {
295 data_blob_free(&out_blob);
296 invalidate_vuid(sconn, vuid);
297 reply_nterror(req, NT_STATUS_NO_MEMORY);
298 return;
300 data_blob_free(&out_blob);
302 if (push_signature(&req->outbuf) == -1) {
303 invalidate_vuid(sconn, vuid);
304 reply_nterror(req, NT_STATUS_NO_MEMORY);
305 return;
309 /****************************************************************************
310 On new VC == 0, shutdown *all* old connections and users.
311 It seems that only NT4.x does this. At W2K and above (XP etc.).
312 a new session setup with VC==0 is ignored.
313 ****************************************************************************/
315 struct shutdown_state {
316 const char *ip;
317 struct messaging_context *msg_ctx;
320 static int shutdown_other_smbds(const struct connections_key *key,
321 const struct connections_data *crec,
322 void *private_data)
324 struct shutdown_state *state = (struct shutdown_state *)private_data;
326 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
327 server_id_str(talloc_tos(), &crec->pid), crec->addr));
329 if (!process_exists(crec->pid)) {
330 DEBUG(10, ("process does not exist\n"));
331 return 0;
334 if (procid_is_me(&crec->pid)) {
335 DEBUG(10, ("It's me\n"));
336 return 0;
339 if (strcmp(state->ip, crec->addr) != 0) {
340 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
341 return 0;
344 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
345 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
346 state->ip));
348 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
349 &data_blob_null);
350 return 0;
353 static void setup_new_vc_session(struct smbd_server_connection *sconn)
355 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
356 "compatible we would close all old resources.\n"));
357 #if 0
358 conn_close_all();
359 invalidate_all_vuids();
360 #endif
361 if (lp_reset_on_zero_vc()) {
362 char *addr;
363 struct shutdown_state state;
365 addr = tsocket_address_inet_addr_string(
366 sconn->remote_address, talloc_tos());
367 if (addr == NULL) {
368 return;
370 state.ip = addr;
371 state.msg_ctx = sconn->msg_ctx;
372 connections_forall_read(shutdown_other_smbds, &state);
373 TALLOC_FREE(addr);
377 /****************************************************************************
378 Reply to a session setup command.
379 ****************************************************************************/
381 void reply_sesssetup_and_X(struct smb_request *req)
383 int sess_vuid;
384 int smb_bufsize;
385 DATA_BLOB lm_resp;
386 DATA_BLOB nt_resp;
387 DATA_BLOB plaintext_password;
388 char *tmp;
389 const char *user;
390 fstring sub_user; /* Sanitised username for substituion */
391 const char *domain;
392 const char *native_os;
393 const char *native_lanman;
394 const char *primary_domain;
395 struct auth_usersupplied_info *user_info = NULL;
396 struct auth_serversupplied_info *server_info = NULL;
397 struct auth_session_info *session_info = NULL;
398 uint16 smb_flag2 = req->flags2;
400 NTSTATUS nt_status;
401 struct smbd_server_connection *sconn = req->sconn;
403 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
404 bool signing_allowed = false;
405 bool signing_mandatory = false;
407 START_PROFILE(SMBsesssetupX);
409 ZERO_STRUCT(lm_resp);
410 ZERO_STRUCT(nt_resp);
411 ZERO_STRUCT(plaintext_password);
413 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
415 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
416 signing_allowed = true;
418 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
419 signing_mandatory = true;
423 * We can call srv_set_signing_negotiated() each time.
424 * It finds out when it needs to turn into a noop
425 * itself.
427 srv_set_signing_negotiated(req->sconn,
428 signing_allowed,
429 signing_mandatory);
431 /* a SPNEGO session setup has 12 command words, whereas a normal
432 NT1 session setup has 13. See the cifs spec. */
433 if (req->wct == 12 &&
434 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
436 if (!sconn->smb1.negprot.spnego) {
437 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
438 "at SPNEGO session setup when it was not "
439 "negotiated.\n"));
440 reply_nterror(req, nt_status_squash(
441 NT_STATUS_LOGON_FAILURE));
442 END_PROFILE(SMBsesssetupX);
443 return;
446 if (SVAL(req->vwv+4, 0) == 0) {
447 setup_new_vc_session(req->sconn);
450 reply_sesssetup_and_X_spnego(req);
451 END_PROFILE(SMBsesssetupX);
452 return;
455 smb_bufsize = SVAL(req->vwv+2, 0);
457 if (get_Protocol() < PROTOCOL_NT1) {
458 uint16 passlen1 = SVAL(req->vwv+7, 0);
460 /* Never do NT status codes with protocols before NT1 as we
461 * don't get client caps. */
462 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
464 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
465 reply_nterror(req, nt_status_squash(
466 NT_STATUS_INVALID_PARAMETER));
467 END_PROFILE(SMBsesssetupX);
468 return;
471 if (doencrypt) {
472 lm_resp = data_blob(req->buf, passlen1);
473 } else {
474 plaintext_password = data_blob(req->buf, passlen1+1);
475 /* Ensure null termination */
476 plaintext_password.data[passlen1] = 0;
479 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
480 req->buf + passlen1, STR_TERMINATE);
481 user = tmp ? tmp : "";
483 domain = "";
485 } else {
486 uint16 passlen1 = SVAL(req->vwv+7, 0);
487 uint16 passlen2 = SVAL(req->vwv+8, 0);
488 enum remote_arch_types ra_type = get_remote_arch();
489 const uint8_t *p = req->buf;
490 const uint8_t *save_p = req->buf;
491 uint16 byte_count;
494 if(global_client_caps == 0) {
495 global_client_caps = IVAL(req->vwv+11, 0);
497 if (!(global_client_caps & CAP_STATUS32)) {
498 remove_from_common_flags2(
499 FLAGS2_32_BIT_ERROR_CODES);
502 /* client_caps is used as final determination if
503 * client is NT or Win95. This is needed to return
504 * the correct error codes in some circumstances.
507 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
508 ra_type == RA_WIN95) {
509 if(!(global_client_caps & (CAP_NT_SMBS|
510 CAP_STATUS32))) {
511 set_remote_arch( RA_WIN95);
516 if (!doencrypt) {
517 /* both Win95 and WinNT stuff up the password
518 * lengths for non-encrypting systems. Uggh.
520 if passlen1==24 its a win95 system, and its setting
521 the password length incorrectly. Luckily it still
522 works with the default code because Win95 will null
523 terminate the password anyway
525 if passlen1>0 and passlen2>0 then maybe its a NT box
526 and its setting passlen2 to some random value which
527 really stuffs things up. we need to fix that one. */
529 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
530 passlen2 != 1) {
531 passlen2 = 0;
535 /* check for nasty tricks */
536 if (passlen1 > MAX_PASS_LEN
537 || passlen1 > smbreq_bufrem(req, p)) {
538 reply_nterror(req, nt_status_squash(
539 NT_STATUS_INVALID_PARAMETER));
540 END_PROFILE(SMBsesssetupX);
541 return;
544 if (passlen2 > MAX_PASS_LEN
545 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
546 reply_nterror(req, nt_status_squash(
547 NT_STATUS_INVALID_PARAMETER));
548 END_PROFILE(SMBsesssetupX);
549 return;
552 /* Save the lanman2 password and the NT md4 password. */
554 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
555 doencrypt = False;
558 if (doencrypt) {
559 lm_resp = data_blob(p, passlen1);
560 nt_resp = data_blob(p+passlen1, passlen2);
561 } else if (lp_security() != SEC_SHARE) {
563 * In share level we should ignore any passwords, so
564 * only read them if we're not.
566 char *pass = NULL;
567 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
569 if (unic && (passlen2 == 0) && passlen1) {
570 /* Only a ascii plaintext password was sent. */
571 (void)srvstr_pull_talloc(talloc_tos(),
572 req->inbuf,
573 req->flags2,
574 &pass,
575 req->buf,
576 passlen1,
577 STR_TERMINATE|STR_ASCII);
578 } else {
579 (void)srvstr_pull_talloc(talloc_tos(),
580 req->inbuf,
581 req->flags2,
582 &pass,
583 req->buf,
584 unic ? passlen2 : passlen1,
585 STR_TERMINATE);
587 if (!pass) {
588 reply_nterror(req, nt_status_squash(
589 NT_STATUS_INVALID_PARAMETER));
590 END_PROFILE(SMBsesssetupX);
591 return;
593 plaintext_password = data_blob(pass, strlen(pass)+1);
596 p += passlen1 + passlen2;
598 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
599 STR_TERMINATE);
600 user = tmp ? tmp : "";
602 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
603 STR_TERMINATE);
604 domain = tmp ? tmp : "";
606 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
607 STR_TERMINATE);
608 native_os = tmp ? tmp : "";
610 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
611 STR_TERMINATE);
612 native_lanman = tmp ? tmp : "";
614 /* not documented or decoded by Ethereal but there is one more
615 * string in the extra bytes which is the same as the
616 * PrimaryDomain when using extended security. Windows NT 4
617 * and 2003 use this string to store the native lanman string.
618 * Windows 9x does not include a string here at all so we have
619 * to check if we have any extra bytes left */
621 byte_count = SVAL(req->vwv+13, 0);
622 if ( PTR_DIFF(p, save_p) < byte_count) {
623 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
624 STR_TERMINATE);
625 primary_domain = tmp ? tmp : "";
626 } else {
627 primary_domain = talloc_strdup(talloc_tos(), "null");
630 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
631 "PrimaryDomain=[%s]\n",
632 domain, native_os, native_lanman, primary_domain));
634 if ( ra_type == RA_WIN2K ) {
635 if ( strlen(native_lanman) == 0 )
636 ra_lanman_string( primary_domain );
637 else
638 ra_lanman_string( native_lanman );
643 if (SVAL(req->vwv+4, 0) == 0) {
644 setup_new_vc_session(req->sconn);
647 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
648 domain, user, get_remote_machine_name()));
650 if (*user) {
651 if (sconn->smb1.negprot.spnego) {
653 /* This has to be here, because this is a perfectly
654 * valid behaviour for guest logons :-( */
656 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
657 "at 'normal' session setup after "
658 "negotiating spnego.\n"));
659 reply_nterror(req, nt_status_squash(
660 NT_STATUS_LOGON_FAILURE));
661 END_PROFILE(SMBsesssetupX);
662 return;
664 fstrcpy(sub_user, user);
665 } else {
666 fstrcpy(sub_user, "");
669 sub_set_smb_name(sub_user);
671 reload_services(sconn, conn_snum_used, true);
673 if (lp_security() == SEC_SHARE) {
674 char *sub_user_mapped = NULL;
675 /* In share level we should ignore any passwords */
677 data_blob_free(&lm_resp);
678 data_blob_free(&nt_resp);
679 data_blob_clear_free(&plaintext_password);
681 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
682 if (!sub_user_mapped) {
683 reply_nterror(req, NT_STATUS_NO_MEMORY);
684 END_PROFILE(SMBsesssetupX);
685 return;
687 fstrcpy(sub_user, sub_user_mapped);
688 add_session_user(sconn, sub_user);
689 add_session_workgroup(sconn, domain);
690 /* Then force it to null for the benfit of the code below */
691 user = "";
694 if (!*user) {
696 nt_status = check_guest_password(sconn->remote_address, &server_info);
698 } else if (doencrypt) {
699 struct auth_context *negprot_auth_context = NULL;
700 negprot_auth_context = sconn->smb1.negprot.auth_context;
701 if (!negprot_auth_context) {
702 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
703 "session setup without negprot denied!\n"));
704 reply_nterror(req, nt_status_squash(
705 NT_STATUS_LOGON_FAILURE));
706 END_PROFILE(SMBsesssetupX);
707 return;
709 nt_status = make_user_info_for_reply_enc(&user_info, user,
710 domain,
711 sconn->remote_address,
712 lm_resp, nt_resp);
713 if (NT_STATUS_IS_OK(nt_status)) {
714 nt_status = negprot_auth_context->check_ntlm_password(
715 negprot_auth_context,
716 user_info,
717 &server_info);
719 } else {
720 struct auth_context *plaintext_auth_context = NULL;
722 nt_status = make_auth_context_subsystem(
723 talloc_tos(), &plaintext_auth_context);
725 if (NT_STATUS_IS_OK(nt_status)) {
726 uint8_t chal[8];
728 plaintext_auth_context->get_ntlm_challenge(
729 plaintext_auth_context, chal);
731 if (!make_user_info_for_reply(&user_info,
732 user, domain,
733 sconn->remote_address,
734 chal,
735 plaintext_password)) {
736 nt_status = NT_STATUS_NO_MEMORY;
739 if (NT_STATUS_IS_OK(nt_status)) {
740 nt_status = plaintext_auth_context->check_ntlm_password(
741 plaintext_auth_context,
742 user_info,
743 &server_info);
745 TALLOC_FREE(plaintext_auth_context);
750 free_user_info(&user_info);
752 if (!NT_STATUS_IS_OK(nt_status)) {
753 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
754 user, domain);
757 if (!NT_STATUS_IS_OK(nt_status)) {
758 data_blob_free(&nt_resp);
759 data_blob_free(&lm_resp);
760 data_blob_clear_free(&plaintext_password);
761 reply_nterror(req, nt_status_squash(nt_status));
762 END_PROFILE(SMBsesssetupX);
763 return;
766 nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
767 TALLOC_FREE(server_info);
769 if (!NT_STATUS_IS_OK(nt_status)) {
770 DEBUG(10, ("create_local_token failed: %s\n",
771 nt_errstr(nt_status)));
772 data_blob_free(&nt_resp);
773 data_blob_free(&lm_resp);
774 data_blob_clear_free(&plaintext_password);
775 reply_nterror(req, nt_status_squash(nt_status));
776 END_PROFILE(SMBsesssetupX);
777 return;
780 data_blob_clear_free(&plaintext_password);
782 /* it's ok - setup a reply */
783 reply_outbuf(req, 3, 0);
784 if (get_Protocol() >= PROTOCOL_NT1) {
785 push_signature(&req->outbuf);
786 /* perhaps grab OS version here?? */
789 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
790 SSVAL(req->outbuf,smb_vwv2,1);
793 /* register the name and uid as being validated, so further connections
794 to a uid can get through without a password, on the same VC */
796 if (lp_security() == SEC_SHARE) {
797 sess_vuid = UID_FIELD_INVALID;
798 TALLOC_FREE(session_info);
799 } else {
800 /* Ignore the initial vuid. */
801 sess_vuid = register_initial_vuid(sconn);
802 if (sess_vuid == UID_FIELD_INVALID) {
803 data_blob_free(&nt_resp);
804 data_blob_free(&lm_resp);
805 reply_nterror(req, nt_status_squash(
806 NT_STATUS_LOGON_FAILURE));
807 END_PROFILE(SMBsesssetupX);
808 return;
810 /* register_existing_vuid keeps the session_info */
811 sess_vuid = register_existing_vuid(sconn, sess_vuid,
812 session_info,
813 nt_resp.data ? nt_resp : lm_resp);
814 if (sess_vuid == UID_FIELD_INVALID) {
815 data_blob_free(&nt_resp);
816 data_blob_free(&lm_resp);
817 reply_nterror(req, nt_status_squash(
818 NT_STATUS_LOGON_FAILURE));
819 END_PROFILE(SMBsesssetupX);
820 return;
823 /* current_user_info is changed on new vuid */
824 reload_services(sconn, conn_snum_used, true);
827 data_blob_free(&nt_resp);
828 data_blob_free(&lm_resp);
830 SSVAL(req->outbuf,smb_uid,sess_vuid);
831 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
832 req->vuid = sess_vuid;
834 if (!sconn->smb1.sessions.done_sesssetup) {
835 sconn->smb1.sessions.max_send =
836 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
838 sconn->smb1.sessions.done_sesssetup = true;
840 END_PROFILE(SMBsesssetupX);
841 chain_reply(req);
842 return;