Use new common function.
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blobdc3e2540f45e6a4ab417fb8655f786ee10f2444d
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 NTSTATUS status = NT_STATUS_OK;
131 struct smbd_server_connection *sconn = req->sconn;
132 uint16_t action = 0;
133 NTTIME now = timeval_to_nttime(&req->request_time);
134 struct smbXsrv_session *session = NULL;
135 uint32_t client_caps = IVAL(req->vwv+10, 0);
137 DEBUG(3,("Doing spnego session setup\n"));
139 if (global_client_caps == 0) {
140 global_client_caps = client_caps;
142 if (!(global_client_caps & CAP_STATUS32)) {
143 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
147 p = req->buf;
149 if (data_blob_len == 0) {
150 /* an invalid request */
151 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
152 return;
155 bufrem = smbreq_bufrem(req, p);
156 /* pull the spnego blob */
157 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
159 #if 0
160 file_save("negotiate.dat", in_blob.data, in_blob.length);
161 #endif
163 p2 = (const char *)req->buf + in_blob.length;
165 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
166 STR_TERMINATE);
167 native_os = tmp ? tmp : "";
169 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
170 STR_TERMINATE);
171 native_lanman = tmp ? tmp : "";
173 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
174 STR_TERMINATE);
175 primary_domain = tmp ? tmp : "";
177 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
178 native_os, native_lanman, primary_domain));
180 if ( ra_type == RA_WIN2K ) {
181 /* Vista sets neither the OS or lanman strings */
183 if ( !strlen(native_os) && !strlen(native_lanman) )
184 set_remote_arch(RA_VISTA);
186 /* Windows 2003 doesn't set the native lanman string,
187 but does set primary domain which is a bug I think */
189 if ( !strlen(native_lanman) ) {
190 ra_lanman_string( primary_domain );
191 } else {
192 ra_lanman_string( native_lanman );
194 } else if ( ra_type == RA_VISTA ) {
195 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
196 set_remote_arch(RA_OSX);
200 if (vuid != 0) {
201 status = smb1srv_session_lookup(sconn->conn,
202 vuid, now,
203 &session);
204 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
205 reply_force_doserror(req, ERRSRV, ERRbaduid);
206 return;
208 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
209 status = NT_STATUS_OK;
211 if (NT_STATUS_IS_OK(status)) {
212 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
213 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
214 TALLOC_FREE(session->gensec);
216 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
217 reply_nterror(req, nt_status_squash(status));
218 return;
222 if (session == NULL) {
223 /* create a new session */
224 status = smbXsrv_session_create(sconn->conn,
225 now, &session);
226 if (!NT_STATUS_IS_OK(status)) {
227 reply_nterror(req, nt_status_squash(status));
228 return;
232 if (!session->gensec) {
233 status = auth_generic_prepare(session, sconn->remote_address,
234 &session->gensec);
235 if (!NT_STATUS_IS_OK(status)) {
236 TALLOC_FREE(session);
237 reply_nterror(req, nt_status_squash(status));
238 return;
241 gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY);
242 gensec_want_feature(session->gensec, GENSEC_FEATURE_UNIX_TOKEN);
244 status = gensec_start_mech_by_oid(session->gensec,
245 GENSEC_OID_SPNEGO);
246 if (!NT_STATUS_IS_OK(status)) {
247 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
248 TALLOC_FREE(session);;
249 reply_nterror(req, nt_status_squash(status));
250 return;
254 become_root();
255 status = gensec_update(session->gensec,
256 talloc_tos(), NULL,
257 in_blob, &out_blob);
258 unbecome_root();
259 if (!NT_STATUS_IS_OK(status) &&
260 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
261 TALLOC_FREE(session);
262 reply_nterror(req, nt_status_squash(status));
263 return;
266 if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
267 struct auth_session_info *session_info = NULL;
269 status = gensec_session_info(session->gensec,
270 session,
271 &session_info);
272 if (!NT_STATUS_IS_OK(status)) {
273 DEBUG(1,("Failed to generate session_info "
274 "(user and group token) for session setup: %s\n",
275 nt_errstr(status)));
276 data_blob_free(&out_blob);
277 TALLOC_FREE(session);
278 reply_nterror(req, nt_status_squash(status));
279 return;
282 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
283 action = 1;
286 session->compat = talloc_zero(session, struct user_struct);
287 if (session->compat == NULL) {
288 data_blob_free(&out_blob);
289 TALLOC_FREE(session);
290 reply_nterror(req, NT_STATUS_NO_MEMORY);
291 return;
293 session->compat->session = session;
294 session->compat->homes_snum = -1;
295 session->compat->session_info = session_info;
296 session->compat->session_keystr = NULL;
297 session->compat->vuid = session->global->session_wire_id;
298 DLIST_ADD(sconn->users, session->compat);
299 sconn->num_users++;
301 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
302 session->compat->homes_snum =
303 register_homes_share(session_info->unix_info->unix_name);
306 if (!session_claim(sconn, session->compat)) {
307 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
308 (unsigned long long)session->compat->vuid));
309 data_blob_free(&out_blob);
310 TALLOC_FREE(session);
311 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
312 return;
315 if (srv_is_signing_negotiated(sconn) && action == 0) {
317 * Try and turn on server signing on the first non-guest
318 * sessionsetup.
320 srv_set_signing(sconn,
321 session_info->session_key,
322 data_blob_null);
325 set_current_user_info(session_info->unix_info->sanitized_username,
326 session_info->unix_info->unix_name,
327 session_info->info->domain_name);
329 session->status = NT_STATUS_OK;
330 session->global->auth_session_info = talloc_move(session->global,
331 &session_info);
332 session->global->auth_session_info_seqnum += 1;
333 session->global->channels[0].auth_session_info_seqnum =
334 session->global->auth_session_info_seqnum;
335 if (client_caps & CAP_DYNAMIC_REAUTH) {
336 session->global->expiration_time =
337 gensec_expire_time(session->gensec);
338 } else {
339 session->global->expiration_time =
340 GENSEC_EXPIRE_TIME_INFINITY;
343 status = smbXsrv_session_update(session);
344 if (!NT_STATUS_IS_OK(status)) {
345 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
346 (unsigned long long)session->compat->vuid,
347 nt_errstr(status)));
348 data_blob_free(&out_blob);
349 TALLOC_FREE(session);
350 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
351 return;
354 /* current_user_info is changed on new vuid */
355 reload_services(sconn, conn_snum_used, true);
356 } else if (NT_STATUS_IS_OK(status)) {
357 struct auth_session_info *session_info = NULL;
359 status = gensec_session_info(session->gensec,
360 session,
361 &session_info);
362 if (!NT_STATUS_IS_OK(status)) {
363 DEBUG(1,("Failed to generate session_info "
364 "(user and group token) for session setup: %s\n",
365 nt_errstr(status)));
366 data_blob_free(&out_blob);
367 TALLOC_FREE(session);
368 reply_nterror(req, nt_status_squash(status));
369 return;
372 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
373 action = 1;
376 session->compat->session_info = session_info;
377 session->compat->vuid = session->global->session_wire_id;
379 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
380 session->compat->homes_snum =
381 register_homes_share(session_info->unix_info->unix_name);
384 set_current_user_info(session_info->unix_info->sanitized_username,
385 session_info->unix_info->unix_name,
386 session_info->info->domain_name);
388 session->status = NT_STATUS_OK;
389 TALLOC_FREE(session->global->auth_session_info);
390 session->global->auth_session_info = session_info;
391 session->global->auth_session_info_seqnum += 1;
392 session->global->channels[0].auth_session_info_seqnum =
393 session->global->auth_session_info_seqnum;
394 if (client_caps & CAP_DYNAMIC_REAUTH) {
395 session->global->expiration_time =
396 gensec_expire_time(session->gensec);
397 } else {
398 session->global->expiration_time =
399 GENSEC_EXPIRE_TIME_INFINITY;
402 status = smbXsrv_session_update(session);
403 if (!NT_STATUS_IS_OK(status)) {
404 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
405 (unsigned long long)session->compat->vuid,
406 nt_errstr(status)));
407 data_blob_free(&out_blob);
408 TALLOC_FREE(session);
409 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
410 return;
413 conn_clear_vuid_caches(sconn, session->compat->vuid);
415 /* current_user_info is changed on new vuid */
416 reload_services(sconn, conn_snum_used, true);
419 vuid = session->global->session_wire_id;
421 reply_outbuf(req, 4, 0);
423 SSVAL(req->outbuf, smb_uid, vuid);
424 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
425 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
426 SSVAL(req->outbuf, smb_vwv2, action);
427 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
429 if (message_push_blob(&req->outbuf, out_blob) == -1) {
430 data_blob_free(&out_blob);
431 TALLOC_FREE(session);
432 reply_nterror(req, NT_STATUS_NO_MEMORY);
433 return;
435 data_blob_free(&out_blob);
437 if (push_signature(&req->outbuf) == -1) {
438 TALLOC_FREE(session);
439 reply_nterror(req, NT_STATUS_NO_MEMORY);
440 return;
444 /****************************************************************************
445 On new VC == 0, shutdown *all* old connections and users.
446 It seems that only NT4.x does this. At W2K and above (XP etc.).
447 a new session setup with VC==0 is ignored.
448 ****************************************************************************/
450 struct shutdown_state {
451 const char *ip;
452 struct messaging_context *msg_ctx;
455 static int shutdown_other_smbds(const struct connections_key *key,
456 const struct connections_data *crec,
457 void *private_data)
459 struct shutdown_state *state = (struct shutdown_state *)private_data;
460 struct server_id self_pid = messaging_server_id(state->msg_ctx);
462 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
463 server_id_str(talloc_tos(), &crec->pid), crec->addr));
465 if (!process_exists(crec->pid)) {
466 DEBUG(10, ("process does not exist\n"));
467 return 0;
470 if (serverid_equal(&crec->pid, &self_pid)) {
471 DEBUG(10, ("It's me\n"));
472 return 0;
475 if (strcmp(state->ip, crec->addr) != 0) {
476 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
477 return 0;
480 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
481 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
482 state->ip));
484 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
485 &data_blob_null);
486 return 0;
489 static void setup_new_vc_session(struct smbd_server_connection *sconn)
491 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
492 "compatible we would close all old resources.\n"));
493 #if 0
494 conn_close_all();
495 invalidate_all_vuids();
496 #endif
497 if (lp_reset_on_zero_vc()) {
498 char *addr;
499 struct shutdown_state state;
501 addr = tsocket_address_inet_addr_string(
502 sconn->remote_address, talloc_tos());
503 if (addr == NULL) {
504 return;
506 state.ip = addr;
507 state.msg_ctx = sconn->msg_ctx;
508 connections_forall_read(shutdown_other_smbds, &state);
509 TALLOC_FREE(addr);
513 /****************************************************************************
514 Reply to a session setup command.
515 ****************************************************************************/
517 void reply_sesssetup_and_X(struct smb_request *req)
519 uint64_t sess_vuid;
520 int smb_bufsize;
521 DATA_BLOB lm_resp;
522 DATA_BLOB nt_resp;
523 DATA_BLOB plaintext_password;
524 char *tmp;
525 const char *user;
526 fstring sub_user; /* Sanitised username for substituion */
527 const char *domain;
528 const char *native_os;
529 const char *native_lanman;
530 const char *primary_domain;
531 struct auth_usersupplied_info *user_info = NULL;
532 struct auth_session_info *session_info = NULL;
533 uint16 smb_flag2 = req->flags2;
534 uint16_t action = 0;
535 NTTIME now = timeval_to_nttime(&req->request_time);
536 struct smbXsrv_session *session = NULL;
538 NTSTATUS nt_status;
539 struct smbd_server_connection *sconn = req->sconn;
541 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
542 bool signing_allowed = false;
543 bool signing_mandatory = false;
545 START_PROFILE(SMBsesssetupX);
547 ZERO_STRUCT(lm_resp);
548 ZERO_STRUCT(nt_resp);
549 ZERO_STRUCT(plaintext_password);
551 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
553 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
554 signing_allowed = true;
556 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
557 signing_mandatory = true;
561 * We can call srv_set_signing_negotiated() each time.
562 * It finds out when it needs to turn into a noop
563 * itself.
565 srv_set_signing_negotiated(req->sconn,
566 signing_allowed,
567 signing_mandatory);
569 /* a SPNEGO session setup has 12 command words, whereas a normal
570 NT1 session setup has 13. See the cifs spec. */
571 if (req->wct == 12 &&
572 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
574 if (!sconn->smb1.negprot.spnego) {
575 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
576 "at SPNEGO session setup when it was not "
577 "negotiated.\n"));
578 reply_nterror(req, nt_status_squash(
579 NT_STATUS_LOGON_FAILURE));
580 END_PROFILE(SMBsesssetupX);
581 return;
584 if (SVAL(req->vwv+4, 0) == 0) {
585 setup_new_vc_session(req->sconn);
588 reply_sesssetup_and_X_spnego(req);
589 END_PROFILE(SMBsesssetupX);
590 return;
593 smb_bufsize = SVAL(req->vwv+2, 0);
595 if (get_Protocol() < PROTOCOL_NT1) {
596 uint16 passlen1 = SVAL(req->vwv+7, 0);
598 /* Never do NT status codes with protocols before NT1 as we
599 * don't get client caps. */
600 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
602 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
603 reply_nterror(req, nt_status_squash(
604 NT_STATUS_INVALID_PARAMETER));
605 END_PROFILE(SMBsesssetupX);
606 return;
609 if (doencrypt) {
610 lm_resp = data_blob(req->buf, passlen1);
611 } else {
612 plaintext_password = data_blob(req->buf, passlen1+1);
613 /* Ensure null termination */
614 plaintext_password.data[passlen1] = 0;
617 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
618 req->buf + passlen1, STR_TERMINATE);
619 user = tmp ? tmp : "";
621 domain = "";
623 } else {
624 uint16 passlen1 = SVAL(req->vwv+7, 0);
625 uint16 passlen2 = SVAL(req->vwv+8, 0);
626 enum remote_arch_types ra_type = get_remote_arch();
627 const uint8_t *p = req->buf;
628 const uint8_t *save_p = req->buf;
629 uint16 byte_count;
632 if(global_client_caps == 0) {
633 global_client_caps = IVAL(req->vwv+11, 0);
635 if (!(global_client_caps & CAP_STATUS32)) {
636 remove_from_common_flags2(
637 FLAGS2_32_BIT_ERROR_CODES);
640 /* client_caps is used as final determination if
641 * client is NT or Win95. This is needed to return
642 * the correct error codes in some circumstances.
645 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
646 ra_type == RA_WIN95) {
647 if(!(global_client_caps & (CAP_NT_SMBS|
648 CAP_STATUS32))) {
649 set_remote_arch( RA_WIN95);
654 if (!doencrypt) {
655 /* both Win95 and WinNT stuff up the password
656 * lengths for non-encrypting systems. Uggh.
658 if passlen1==24 its a win95 system, and its setting
659 the password length incorrectly. Luckily it still
660 works with the default code because Win95 will null
661 terminate the password anyway
663 if passlen1>0 and passlen2>0 then maybe its a NT box
664 and its setting passlen2 to some random value which
665 really stuffs things up. we need to fix that one. */
667 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
668 passlen2 != 1) {
669 passlen2 = 0;
673 /* check for nasty tricks */
674 if (passlen1 > MAX_PASS_LEN
675 || passlen1 > smbreq_bufrem(req, p)) {
676 reply_nterror(req, nt_status_squash(
677 NT_STATUS_INVALID_PARAMETER));
678 END_PROFILE(SMBsesssetupX);
679 return;
682 if (passlen2 > MAX_PASS_LEN
683 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
684 reply_nterror(req, nt_status_squash(
685 NT_STATUS_INVALID_PARAMETER));
686 END_PROFILE(SMBsesssetupX);
687 return;
690 /* Save the lanman2 password and the NT md4 password. */
692 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
693 doencrypt = False;
696 if (doencrypt) {
697 lm_resp = data_blob(p, passlen1);
698 nt_resp = data_blob(p+passlen1, passlen2);
699 } else {
700 char *pass = NULL;
701 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
703 if (unic && (passlen2 == 0) && passlen1) {
704 /* Only a ascii plaintext password was sent. */
705 (void)srvstr_pull_talloc(talloc_tos(),
706 req->inbuf,
707 req->flags2,
708 &pass,
709 req->buf,
710 passlen1,
711 STR_TERMINATE|STR_ASCII);
712 } else {
713 (void)srvstr_pull_talloc(talloc_tos(),
714 req->inbuf,
715 req->flags2,
716 &pass,
717 req->buf,
718 unic ? passlen2 : passlen1,
719 STR_TERMINATE);
721 if (!pass) {
722 reply_nterror(req, nt_status_squash(
723 NT_STATUS_INVALID_PARAMETER));
724 END_PROFILE(SMBsesssetupX);
725 return;
727 plaintext_password = data_blob(pass, strlen(pass)+1);
730 p += passlen1 + passlen2;
732 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
733 STR_TERMINATE);
734 user = tmp ? tmp : "";
736 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
737 STR_TERMINATE);
738 domain = tmp ? tmp : "";
740 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
741 STR_TERMINATE);
742 native_os = tmp ? tmp : "";
744 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
745 STR_TERMINATE);
746 native_lanman = tmp ? tmp : "";
748 /* not documented or decoded by Ethereal but there is one more
749 * string in the extra bytes which is the same as the
750 * PrimaryDomain when using extended security. Windows NT 4
751 * and 2003 use this string to store the native lanman string.
752 * Windows 9x does not include a string here at all so we have
753 * to check if we have any extra bytes left */
755 byte_count = SVAL(req->vwv+13, 0);
756 if ( PTR_DIFF(p, save_p) < byte_count) {
757 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
758 STR_TERMINATE);
759 primary_domain = tmp ? tmp : "";
760 } else {
761 primary_domain = talloc_strdup(talloc_tos(), "null");
764 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
765 "PrimaryDomain=[%s]\n",
766 domain, native_os, native_lanman, primary_domain));
768 if ( ra_type == RA_WIN2K ) {
769 if ( strlen(native_lanman) == 0 )
770 ra_lanman_string( primary_domain );
771 else
772 ra_lanman_string( native_lanman );
777 if (SVAL(req->vwv+4, 0) == 0) {
778 setup_new_vc_session(req->sconn);
781 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
782 domain, user, get_remote_machine_name()));
784 if (*user) {
785 if (sconn->smb1.negprot.spnego) {
787 /* This has to be here, because this is a perfectly
788 * valid behaviour for guest logons :-( */
790 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
791 "at 'normal' session setup after "
792 "negotiating spnego.\n"));
793 reply_nterror(req, nt_status_squash(
794 NT_STATUS_LOGON_FAILURE));
795 END_PROFILE(SMBsesssetupX);
796 return;
798 fstrcpy(sub_user, user);
799 } else {
800 fstrcpy(sub_user, "");
803 sub_set_smb_name(sub_user);
805 reload_services(sconn, conn_snum_used, true);
807 if (!*user) {
809 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
811 } else if (doencrypt) {
812 struct auth4_context *negprot_auth_context = NULL;
813 negprot_auth_context = sconn->smb1.negprot.auth_context;
814 if (!negprot_auth_context) {
815 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
816 "session setup without negprot denied!\n"));
817 reply_nterror(req, nt_status_squash(
818 NT_STATUS_LOGON_FAILURE));
819 END_PROFILE(SMBsesssetupX);
820 return;
822 nt_status = make_user_info_for_reply_enc(&user_info, user,
823 domain,
824 sconn->remote_address,
825 lm_resp, nt_resp);
826 if (NT_STATUS_IS_OK(nt_status)) {
827 nt_status = auth_check_password_session_info(negprot_auth_context,
828 req, user_info, &session_info);
830 } else {
831 struct auth4_context *plaintext_auth_context = NULL;
833 nt_status = make_auth4_context(
834 talloc_tos(), &plaintext_auth_context);
836 if (NT_STATUS_IS_OK(nt_status)) {
837 uint8_t chal[8];
839 plaintext_auth_context->get_ntlm_challenge(
840 plaintext_auth_context, chal);
842 if (!make_user_info_for_reply(&user_info,
843 user, domain,
844 sconn->remote_address,
845 chal,
846 plaintext_password)) {
847 nt_status = NT_STATUS_NO_MEMORY;
850 if (NT_STATUS_IS_OK(nt_status)) {
851 nt_status = auth_check_password_session_info(plaintext_auth_context,
852 req, user_info, &session_info);
854 TALLOC_FREE(plaintext_auth_context);
858 free_user_info(&user_info);
860 if (!NT_STATUS_IS_OK(nt_status)) {
861 data_blob_free(&nt_resp);
862 data_blob_free(&lm_resp);
863 data_blob_clear_free(&plaintext_password);
864 reply_nterror(req, nt_status_squash(nt_status));
865 END_PROFILE(SMBsesssetupX);
866 return;
869 data_blob_clear_free(&plaintext_password);
871 /* it's ok - setup a reply */
872 reply_outbuf(req, 3, 0);
873 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
874 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
876 if (get_Protocol() >= PROTOCOL_NT1) {
877 push_signature(&req->outbuf);
878 /* perhaps grab OS version here?? */
881 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
882 action = 1;
885 /* register the name and uid as being validated, so further connections
886 to a uid can get through without a password, on the same VC */
888 nt_status = smbXsrv_session_create(sconn->conn,
889 now, &session);
890 if (!NT_STATUS_IS_OK(nt_status)) {
891 data_blob_free(&nt_resp);
892 data_blob_free(&lm_resp);
893 reply_nterror(req, nt_status_squash(nt_status));
894 END_PROFILE(SMBsesssetupX);
895 return;
898 session->compat = talloc_zero(session, struct user_struct);
899 if (session->compat == NULL) {
900 data_blob_free(&nt_resp);
901 data_blob_free(&lm_resp);
902 TALLOC_FREE(session);
903 reply_nterror(req, NT_STATUS_NO_MEMORY);
904 END_PROFILE(SMBsesssetupX);
905 return;
907 session->compat->session = session;
908 session->compat->homes_snum = -1;
909 session->compat->session_info = session_info;
910 session->compat->session_keystr = NULL;
911 session->compat->vuid = session->global->session_wire_id;
912 DLIST_ADD(sconn->users, session->compat);
913 sconn->num_users++;
915 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
916 session->compat->homes_snum =
917 register_homes_share(session_info->unix_info->unix_name);
920 if (!session_claim(sconn, session->compat)) {
921 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
922 (unsigned long long)session->compat->vuid));
923 data_blob_free(&nt_resp);
924 data_blob_free(&lm_resp);
925 TALLOC_FREE(session);
926 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
927 END_PROFILE(SMBsesssetupX);
928 return;
931 if (srv_is_signing_negotiated(sconn) && action == 0) {
933 * Try and turn on server signing on the first non-guest
934 * sessionsetup.
936 srv_set_signing(sconn,
937 session_info->session_key,
938 nt_resp.data ? nt_resp : lm_resp);
941 set_current_user_info(session_info->unix_info->sanitized_username,
942 session_info->unix_info->unix_name,
943 session_info->info->domain_name);
945 session->status = NT_STATUS_OK;
946 session->global->auth_session_info = talloc_move(session->global,
947 &session_info);
948 session->global->auth_session_info_seqnum += 1;
949 session->global->channels[0].auth_session_info_seqnum =
950 session->global->auth_session_info_seqnum;
951 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
953 nt_status = smbXsrv_session_update(session);
954 if (!NT_STATUS_IS_OK(nt_status)) {
955 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
956 (unsigned long long)session->compat->vuid,
957 nt_errstr(nt_status)));
958 data_blob_free(&nt_resp);
959 data_blob_free(&lm_resp);
960 TALLOC_FREE(session);
961 reply_nterror(req, nt_status_squash(nt_status));
962 END_PROFILE(SMBsesssetupX);
963 return;
966 /* current_user_info is changed on new vuid */
967 reload_services(sconn, conn_snum_used, true);
969 sess_vuid = session->global->session_wire_id;
971 data_blob_free(&nt_resp);
972 data_blob_free(&lm_resp);
974 SSVAL(req->outbuf,smb_vwv2,action);
975 SSVAL(req->outbuf,smb_uid,sess_vuid);
976 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
977 req->vuid = sess_vuid;
979 if (!sconn->smb1.sessions.done_sesssetup) {
980 sconn->smb1.sessions.max_send =
981 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
983 sconn->smb1.sessions.done_sesssetup = true;
985 END_PROFILE(SMBsesssetupX);