torture: Add a check to verify MS-SMB2 3.3.5.14.2
[Samba.git] / source3 / smbd / sesssetup.c
blob1a0cb5e29d53104b91d390aad0d5ef00d43a77ec
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;
49 fstring native_os;
51 result = 0;
53 fstr_sprintf(native_os, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION,
54 SAMBA_MINOR_NBT_ANNOUNCE_VERSION);
56 tmp = message_push_string(outbuf, native_os, STR_TERMINATE);
58 if (tmp == -1) return -1;
59 result += tmp;
61 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
62 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
63 SAFE_FREE(lanman);
65 else {
66 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
69 if (tmp == -1) return -1;
70 result += tmp;
72 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
74 if (tmp == -1) return -1;
75 result += tmp;
77 return result;
80 /****************************************************************************
81 Do a 'guest' logon, getting back the
82 ****************************************************************************/
84 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
85 TALLOC_CTX *mem_ctx,
86 struct auth_session_info **session_info)
88 struct auth4_context *auth_context;
89 struct auth_usersupplied_info *user_info = NULL;
90 uint8_t chal[8];
91 NTSTATUS nt_status;
93 DEBUG(3,("Got anonymous request\n"));
95 nt_status = make_auth4_context(talloc_tos(), &auth_context);
96 if (!NT_STATUS_IS_OK(nt_status)) {
97 return nt_status;
100 auth_context->get_ntlm_challenge(auth_context,
101 chal);
103 if (!make_user_info_guest(talloc_tos(), remote_address, &user_info)) {
104 TALLOC_FREE(auth_context);
105 return NT_STATUS_NO_MEMORY;
108 nt_status = auth_check_password_session_info(auth_context,
109 mem_ctx, user_info, session_info);
110 TALLOC_FREE(user_info);
111 TALLOC_FREE(auth_context);
112 return nt_status;
115 /****************************************************************************
116 Reply to a session setup command.
117 conn POINTER CAN BE NULL HERE !
118 ****************************************************************************/
120 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
122 const uint8 *p;
123 DATA_BLOB in_blob;
124 DATA_BLOB out_blob = data_blob_null;
125 size_t bufrem;
126 char *tmp;
127 const char *native_os;
128 const char *native_lanman;
129 const char *primary_domain;
130 uint16 data_blob_len = SVAL(req->vwv+7, 0);
131 enum remote_arch_types ra_type = get_remote_arch();
132 uint64_t vuid = req->vuid;
133 NTSTATUS status = NT_STATUS_OK;
134 struct smbd_server_connection *sconn = req->sconn;
135 uint16_t action = 0;
136 NTTIME now = timeval_to_nttime(&req->request_time);
137 struct smbXsrv_session *session = NULL;
138 uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
139 uint32_t client_caps = IVAL(req->vwv+10, 0);
141 DEBUG(3,("Doing spnego session setup\n"));
143 if (!sconn->smb1.sessions.done_sesssetup) {
144 global_client_caps = client_caps;
146 if (!(global_client_caps & CAP_STATUS32)) {
147 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
151 p = req->buf;
153 if (data_blob_len == 0) {
154 /* an invalid request */
155 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
156 return;
159 bufrem = smbreq_bufrem(req, p);
160 /* pull the spnego blob */
161 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
163 #if 0
164 file_save("negotiate.dat", in_blob.data, in_blob.length);
165 #endif
167 p = req->buf + in_blob.length;
169 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
170 STR_TERMINATE);
171 native_os = tmp ? tmp : "";
173 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
174 STR_TERMINATE);
175 native_lanman = tmp ? tmp : "";
177 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
178 STR_TERMINATE);
179 primary_domain = tmp ? tmp : "";
181 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
182 native_os, native_lanman, primary_domain));
184 if ( ra_type == RA_WIN2K ) {
185 /* Vista sets neither the OS or lanman strings */
187 if ( !strlen(native_os) && !strlen(native_lanman) )
188 set_remote_arch(RA_VISTA);
190 /* Windows 2003 doesn't set the native lanman string,
191 but does set primary domain which is a bug I think */
193 if ( !strlen(native_lanman) ) {
194 ra_lanman_string( primary_domain );
195 } else {
196 ra_lanman_string( native_lanman );
198 } else if ( ra_type == RA_VISTA ) {
199 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
200 set_remote_arch(RA_OSX);
204 if (vuid != 0) {
205 status = smb1srv_session_lookup(sconn->conn,
206 vuid, now,
207 &session);
208 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
209 reply_force_doserror(req, ERRSRV, ERRbaduid);
210 return;
212 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
213 status = NT_STATUS_OK;
215 if (NT_STATUS_IS_OK(status)) {
216 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
217 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
218 TALLOC_FREE(session->gensec);
220 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
221 reply_nterror(req, nt_status_squash(status));
222 return;
226 if (session == NULL) {
227 /* create a new session */
228 status = smbXsrv_session_create(sconn->conn,
229 now, &session);
230 if (!NT_STATUS_IS_OK(status)) {
231 reply_nterror(req, nt_status_squash(status));
232 return;
236 if (!session->gensec) {
237 status = auth_generic_prepare(session, sconn->remote_address,
238 &session->gensec);
239 if (!NT_STATUS_IS_OK(status)) {
240 TALLOC_FREE(session);
241 reply_nterror(req, nt_status_squash(status));
242 return;
245 gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY);
246 gensec_want_feature(session->gensec, GENSEC_FEATURE_UNIX_TOKEN);
248 status = gensec_start_mech_by_oid(session->gensec,
249 GENSEC_OID_SPNEGO);
250 if (!NT_STATUS_IS_OK(status)) {
251 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
252 TALLOC_FREE(session);;
253 reply_nterror(req, nt_status_squash(status));
254 return;
258 become_root();
259 status = gensec_update(session->gensec,
260 talloc_tos(),
261 in_blob, &out_blob);
262 unbecome_root();
263 if (!NT_STATUS_IS_OK(status) &&
264 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
265 TALLOC_FREE(session);
266 reply_nterror(req, nt_status_squash(status));
267 return;
270 if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
271 struct auth_session_info *session_info = NULL;
273 status = gensec_session_info(session->gensec,
274 session,
275 &session_info);
276 if (!NT_STATUS_IS_OK(status)) {
277 DEBUG(1,("Failed to generate session_info "
278 "(user and group token) for session setup: %s\n",
279 nt_errstr(status)));
280 data_blob_free(&out_blob);
281 TALLOC_FREE(session);
282 reply_nterror(req, nt_status_squash(status));
283 return;
286 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
287 action = 1;
290 if (session_info->session_key.length > 0) {
291 struct smbXsrv_session *x = session;
294 * Note: the SMB1 signing key is not truncated to 16 byte!
296 x->global->signing_key =
297 data_blob_dup_talloc(x->global,
298 session_info->session_key);
299 if (x->global->signing_key.data == NULL) {
300 data_blob_free(&out_blob);
301 TALLOC_FREE(session);
302 reply_nterror(req, NT_STATUS_NO_MEMORY);
303 return;
307 * clear the session key
308 * the first tcon will add setup the application key
310 data_blob_clear_free(&session_info->session_key);
313 session->compat = talloc_zero(session, struct user_struct);
314 if (session->compat == NULL) {
315 data_blob_free(&out_blob);
316 TALLOC_FREE(session);
317 reply_nterror(req, NT_STATUS_NO_MEMORY);
318 return;
320 session->compat->session = session;
321 session->compat->homes_snum = -1;
322 session->compat->session_info = session_info;
323 session->compat->session_keystr = NULL;
324 session->compat->vuid = session->global->session_wire_id;
325 DLIST_ADD(sconn->users, session->compat);
326 sconn->num_users++;
328 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
329 session->compat->homes_snum =
330 register_homes_share(session_info->unix_info->unix_name);
333 if (srv_is_signing_negotiated(sconn) &&
334 action == 0 &&
335 session->global->signing_key.length > 0)
338 * Try and turn on server signing on the first non-guest
339 * sessionsetup.
341 srv_set_signing(sconn,
342 session->global->signing_key,
343 data_blob_null);
346 set_current_user_info(session_info->unix_info->sanitized_username,
347 session_info->unix_info->unix_name,
348 session_info->info->domain_name);
350 session->status = NT_STATUS_OK;
351 session->global->auth_session_info = talloc_move(session->global,
352 &session_info);
353 session->global->auth_session_info_seqnum += 1;
354 session->global->channels[0].auth_session_info_seqnum =
355 session->global->auth_session_info_seqnum;
356 if (client_caps & CAP_DYNAMIC_REAUTH) {
357 session->global->expiration_time =
358 gensec_expire_time(session->gensec);
359 } else {
360 session->global->expiration_time =
361 GENSEC_EXPIRE_TIME_INFINITY;
364 if (!session_claim(session)) {
365 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
366 (unsigned long long)session->compat->vuid));
367 data_blob_free(&out_blob);
368 TALLOC_FREE(session);
369 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
370 return;
373 status = smbXsrv_session_update(session);
374 if (!NT_STATUS_IS_OK(status)) {
375 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
376 (unsigned long long)session->compat->vuid,
377 nt_errstr(status)));
378 data_blob_free(&out_blob);
379 TALLOC_FREE(session);
380 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
381 return;
384 if (!sconn->smb1.sessions.done_sesssetup) {
385 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
386 reply_force_doserror(req, ERRSRV, ERRerror);
387 return;
389 sconn->smb1.sessions.max_send = smb_bufsize;
390 sconn->smb1.sessions.done_sesssetup = true;
393 /* current_user_info is changed on new vuid */
394 reload_services(sconn, conn_snum_used, true);
395 } else if (NT_STATUS_IS_OK(status)) {
396 struct auth_session_info *session_info = NULL;
398 status = gensec_session_info(session->gensec,
399 session,
400 &session_info);
401 if (!NT_STATUS_IS_OK(status)) {
402 DEBUG(1,("Failed to generate session_info "
403 "(user and group token) for session setup: %s\n",
404 nt_errstr(status)));
405 data_blob_free(&out_blob);
406 TALLOC_FREE(session);
407 reply_nterror(req, nt_status_squash(status));
408 return;
411 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
412 action = 1;
416 * Keep the application key
418 data_blob_clear_free(&session_info->session_key);
419 session_info->session_key =
420 session->global->auth_session_info->session_key;
421 talloc_steal(session_info, session_info->session_key.data);
422 TALLOC_FREE(session->global->auth_session_info);
424 session->compat->session_info = session_info;
426 session->compat->vuid = session->global->session_wire_id;
428 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
429 session->compat->homes_snum =
430 register_homes_share(session_info->unix_info->unix_name);
433 set_current_user_info(session_info->unix_info->sanitized_username,
434 session_info->unix_info->unix_name,
435 session_info->info->domain_name);
437 session->status = NT_STATUS_OK;
438 session->global->auth_session_info = talloc_move(session->global,
439 &session_info);
440 session->global->auth_session_info_seqnum += 1;
441 session->global->channels[0].auth_session_info_seqnum =
442 session->global->auth_session_info_seqnum;
443 if (client_caps & CAP_DYNAMIC_REAUTH) {
444 session->global->expiration_time =
445 gensec_expire_time(session->gensec);
446 } else {
447 session->global->expiration_time =
448 GENSEC_EXPIRE_TIME_INFINITY;
451 status = smbXsrv_session_update(session);
452 if (!NT_STATUS_IS_OK(status)) {
453 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
454 (unsigned long long)session->compat->vuid,
455 nt_errstr(status)));
456 data_blob_free(&out_blob);
457 TALLOC_FREE(session);
458 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
459 return;
462 conn_clear_vuid_caches(sconn, session->compat->vuid);
464 /* current_user_info is changed on new vuid */
465 reload_services(sconn, conn_snum_used, true);
468 vuid = session->global->session_wire_id;
470 reply_outbuf(req, 4, 0);
472 SSVAL(req->outbuf, smb_uid, vuid);
473 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
474 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
475 SSVAL(req->outbuf, smb_vwv2, action);
476 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
478 if (message_push_blob(&req->outbuf, out_blob) == -1) {
479 data_blob_free(&out_blob);
480 TALLOC_FREE(session);
481 reply_nterror(req, NT_STATUS_NO_MEMORY);
482 return;
484 data_blob_free(&out_blob);
486 if (push_signature(&req->outbuf) == -1) {
487 TALLOC_FREE(session);
488 reply_nterror(req, NT_STATUS_NO_MEMORY);
489 return;
493 /****************************************************************************
494 On new VC == 0, shutdown *all* old connections and users.
495 It seems that only NT4.x does this. At W2K and above (XP etc.).
496 a new session setup with VC==0 is ignored.
497 ****************************************************************************/
499 struct shutdown_state {
500 const char *ip;
501 struct messaging_context *msg_ctx;
504 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
505 void *private_data)
507 struct shutdown_state *state = (struct shutdown_state *)private_data;
508 struct server_id self_pid = messaging_server_id(state->msg_ctx);
509 struct server_id pid = session->channels[0].server_id;
510 const char *addr = session->channels[0].remote_address;
512 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
513 server_id_str(talloc_tos(), &pid), addr));
515 if (!process_exists(pid)) {
516 DEBUG(10, ("process does not exist\n"));
517 return 0;
520 if (serverid_equal(&pid, &self_pid)) {
521 DEBUG(10, ("It's me\n"));
522 return 0;
526 * here we use strstr() because 'addr'
527 * (session->channels[0].remote_address)
528 * contains a string like:
529 * 'ipv4:127.0.0.1:48163'
531 if (strstr(addr, state->ip) == NULL) {
532 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
533 return 0;
536 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
537 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
538 state->ip));
540 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
541 &data_blob_null);
542 return 0;
545 static void setup_new_vc_session(struct smbd_server_connection *sconn)
547 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
548 "compatible we would close all old resources.\n"));
549 #if 0
550 conn_close_all();
551 invalidate_all_vuids();
552 #endif
553 if (lp_reset_on_zero_vc()) {
554 char *addr;
555 struct shutdown_state state;
557 addr = tsocket_address_inet_addr_string(
558 sconn->remote_address, talloc_tos());
559 if (addr == NULL) {
560 return;
562 state.ip = addr;
563 state.msg_ctx = sconn->msg_ctx;
564 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
565 TALLOC_FREE(addr);
569 /****************************************************************************
570 Reply to a session setup command.
571 ****************************************************************************/
573 void reply_sesssetup_and_X(struct smb_request *req)
575 uint64_t sess_vuid;
576 uint16_t smb_bufsize;
577 DATA_BLOB lm_resp;
578 DATA_BLOB nt_resp;
579 DATA_BLOB plaintext_password;
580 char *tmp;
581 const char *user;
582 fstring sub_user; /* Sanitised username for substituion */
583 const char *domain;
584 const char *native_os;
585 const char *native_lanman;
586 const char *primary_domain;
587 struct auth_usersupplied_info *user_info = NULL;
588 struct auth_session_info *session_info = NULL;
589 uint16 smb_flag2 = req->flags2;
590 uint16_t action = 0;
591 NTTIME now = timeval_to_nttime(&req->request_time);
592 struct smbXsrv_session *session = NULL;
594 NTSTATUS nt_status;
595 struct smbd_server_connection *sconn = req->sconn;
597 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
598 bool signing_allowed = false;
599 bool signing_mandatory = false;
601 START_PROFILE(SMBsesssetupX);
603 ZERO_STRUCT(lm_resp);
604 ZERO_STRUCT(nt_resp);
605 ZERO_STRUCT(plaintext_password);
607 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
609 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
610 signing_allowed = true;
612 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
613 signing_mandatory = true;
617 * We can call srv_set_signing_negotiated() each time.
618 * It finds out when it needs to turn into a noop
619 * itself.
621 srv_set_signing_negotiated(req->sconn,
622 signing_allowed,
623 signing_mandatory);
625 /* a SPNEGO session setup has 12 command words, whereas a normal
626 NT1 session setup has 13. See the cifs spec. */
627 if (req->wct == 12 &&
628 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
630 if (!sconn->smb1.negprot.spnego) {
631 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
632 "at SPNEGO session setup when it was not "
633 "negotiated.\n"));
634 reply_nterror(req, nt_status_squash(
635 NT_STATUS_LOGON_FAILURE));
636 END_PROFILE(SMBsesssetupX);
637 return;
640 if (SVAL(req->vwv+4, 0) == 0) {
641 setup_new_vc_session(req->sconn);
644 reply_sesssetup_and_X_spnego(req);
645 END_PROFILE(SMBsesssetupX);
646 return;
649 smb_bufsize = SVAL(req->vwv+2, 0);
651 if (get_Protocol() < PROTOCOL_NT1) {
652 uint16 passlen1 = SVAL(req->vwv+7, 0);
654 /* Never do NT status codes with protocols before NT1 as we
655 * don't get client caps. */
656 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
658 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
659 reply_nterror(req, nt_status_squash(
660 NT_STATUS_INVALID_PARAMETER));
661 END_PROFILE(SMBsesssetupX);
662 return;
665 if (doencrypt) {
666 lm_resp = data_blob(req->buf, passlen1);
667 } else {
668 plaintext_password = data_blob(req->buf, passlen1+1);
669 /* Ensure null termination */
670 plaintext_password.data[passlen1] = 0;
673 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
674 req->buf + passlen1, STR_TERMINATE);
675 user = tmp ? tmp : "";
677 domain = "";
679 } else {
680 uint16 passlen1 = SVAL(req->vwv+7, 0);
681 uint16 passlen2 = SVAL(req->vwv+8, 0);
682 enum remote_arch_types ra_type = get_remote_arch();
683 const uint8_t *p = req->buf;
684 const uint8_t *save_p = req->buf;
685 uint16 byte_count;
687 if (!sconn->smb1.sessions.done_sesssetup) {
688 global_client_caps = IVAL(req->vwv+11, 0);
690 if (!(global_client_caps & CAP_STATUS32)) {
691 remove_from_common_flags2(
692 FLAGS2_32_BIT_ERROR_CODES);
695 /* client_caps is used as final determination if
696 * client is NT or Win95. This is needed to return
697 * the correct error codes in some circumstances.
700 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
701 ra_type == RA_WIN95) {
702 if(!(global_client_caps & (CAP_NT_SMBS|
703 CAP_STATUS32))) {
704 set_remote_arch( RA_WIN95);
709 if (!doencrypt) {
710 /* both Win95 and WinNT stuff up the password
711 * lengths for non-encrypting systems. Uggh.
713 if passlen1==24 its a win95 system, and its setting
714 the password length incorrectly. Luckily it still
715 works with the default code because Win95 will null
716 terminate the password anyway
718 if passlen1>0 and passlen2>0 then maybe its a NT box
719 and its setting passlen2 to some random value which
720 really stuffs things up. we need to fix that one. */
722 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
723 passlen2 != 1) {
724 passlen2 = 0;
728 /* check for nasty tricks */
729 if (passlen1 > MAX_PASS_LEN
730 || passlen1 > smbreq_bufrem(req, p)) {
731 reply_nterror(req, nt_status_squash(
732 NT_STATUS_INVALID_PARAMETER));
733 END_PROFILE(SMBsesssetupX);
734 return;
737 if (passlen2 > MAX_PASS_LEN
738 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
739 reply_nterror(req, nt_status_squash(
740 NT_STATUS_INVALID_PARAMETER));
741 END_PROFILE(SMBsesssetupX);
742 return;
745 /* Save the lanman2 password and the NT md4 password. */
747 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
748 doencrypt = False;
751 if (doencrypt) {
752 lm_resp = data_blob(p, passlen1);
753 nt_resp = data_blob(p+passlen1, passlen2);
754 } else {
755 char *pass = NULL;
756 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
758 if (unic && (passlen2 == 0) && passlen1) {
759 /* Only a ascii plaintext password was sent. */
760 (void)srvstr_pull_talloc(talloc_tos(),
761 req->inbuf,
762 req->flags2,
763 &pass,
764 req->buf,
765 passlen1,
766 STR_TERMINATE|STR_ASCII);
767 } else {
768 (void)srvstr_pull_talloc(talloc_tos(),
769 req->inbuf,
770 req->flags2,
771 &pass,
772 req->buf,
773 unic ? passlen2 : passlen1,
774 STR_TERMINATE);
776 if (!pass) {
777 reply_nterror(req, nt_status_squash(
778 NT_STATUS_INVALID_PARAMETER));
779 END_PROFILE(SMBsesssetupX);
780 return;
782 plaintext_password = data_blob(pass, strlen(pass)+1);
785 p += passlen1 + passlen2;
787 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
788 STR_TERMINATE);
789 user = tmp ? tmp : "";
791 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
792 STR_TERMINATE);
793 domain = tmp ? tmp : "";
795 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
796 STR_TERMINATE);
797 native_os = tmp ? tmp : "";
799 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
800 STR_TERMINATE);
801 native_lanman = tmp ? tmp : "";
803 /* not documented or decoded by Ethereal but there is one more
804 * string in the extra bytes which is the same as the
805 * PrimaryDomain when using extended security. Windows NT 4
806 * and 2003 use this string to store the native lanman string.
807 * Windows 9x does not include a string here at all so we have
808 * to check if we have any extra bytes left */
810 byte_count = SVAL(req->vwv+13, 0);
811 if ( PTR_DIFF(p, save_p) < byte_count) {
812 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
813 STR_TERMINATE);
814 primary_domain = tmp ? tmp : "";
815 } else {
816 primary_domain = talloc_strdup(talloc_tos(), "null");
819 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
820 "PrimaryDomain=[%s]\n",
821 domain, native_os, native_lanman, primary_domain));
823 if ( ra_type == RA_WIN2K ) {
824 if ( strlen(native_lanman) == 0 )
825 ra_lanman_string( primary_domain );
826 else
827 ra_lanman_string( native_lanman );
832 if (SVAL(req->vwv+4, 0) == 0) {
833 setup_new_vc_session(req->sconn);
836 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
837 domain, user, get_remote_machine_name()));
839 if (*user) {
840 if (sconn->smb1.negprot.spnego) {
842 /* This has to be here, because this is a perfectly
843 * valid behaviour for guest logons :-( */
845 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
846 "at 'normal' session setup after "
847 "negotiating spnego.\n"));
848 reply_nterror(req, nt_status_squash(
849 NT_STATUS_LOGON_FAILURE));
850 END_PROFILE(SMBsesssetupX);
851 return;
853 fstrcpy(sub_user, user);
854 } else {
855 fstrcpy(sub_user, "");
858 sub_set_smb_name(sub_user);
860 reload_services(sconn, conn_snum_used, true);
862 if (!*user) {
864 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
866 } else if (doencrypt) {
867 struct auth4_context *negprot_auth_context = NULL;
868 negprot_auth_context = sconn->smb1.negprot.auth_context;
869 if (!negprot_auth_context) {
870 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
871 "session setup without negprot denied!\n"));
872 reply_nterror(req, nt_status_squash(
873 NT_STATUS_LOGON_FAILURE));
874 END_PROFILE(SMBsesssetupX);
875 return;
877 nt_status = make_user_info_for_reply_enc(talloc_tos(),
878 &user_info, user,
879 domain,
880 sconn->remote_address,
881 lm_resp, nt_resp);
882 if (NT_STATUS_IS_OK(nt_status)) {
883 nt_status = auth_check_password_session_info(negprot_auth_context,
884 req, user_info, &session_info);
886 } else {
887 struct auth4_context *plaintext_auth_context = NULL;
889 nt_status = make_auth4_context(
890 talloc_tos(), &plaintext_auth_context);
892 if (NT_STATUS_IS_OK(nt_status)) {
893 uint8_t chal[8];
895 plaintext_auth_context->get_ntlm_challenge(
896 plaintext_auth_context, chal);
898 if (!make_user_info_for_reply(talloc_tos(),
899 &user_info,
900 user, domain,
901 sconn->remote_address,
902 chal,
903 plaintext_password)) {
904 nt_status = NT_STATUS_NO_MEMORY;
907 if (NT_STATUS_IS_OK(nt_status)) {
908 nt_status = auth_check_password_session_info(plaintext_auth_context,
909 req, user_info, &session_info);
911 TALLOC_FREE(plaintext_auth_context);
915 TALLOC_FREE(user_info);
917 if (!NT_STATUS_IS_OK(nt_status)) {
918 data_blob_free(&nt_resp);
919 data_blob_free(&lm_resp);
920 data_blob_clear_free(&plaintext_password);
921 reply_nterror(req, nt_status_squash(nt_status));
922 END_PROFILE(SMBsesssetupX);
923 return;
926 data_blob_clear_free(&plaintext_password);
928 /* it's ok - setup a reply */
929 reply_outbuf(req, 3, 0);
930 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
931 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
933 if (get_Protocol() >= PROTOCOL_NT1) {
934 push_signature(&req->outbuf);
935 /* perhaps grab OS version here?? */
938 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
939 action = 1;
942 /* register the name and uid as being validated, so further connections
943 to a uid can get through without a password, on the same VC */
945 nt_status = smbXsrv_session_create(sconn->conn,
946 now, &session);
947 if (!NT_STATUS_IS_OK(nt_status)) {
948 data_blob_free(&nt_resp);
949 data_blob_free(&lm_resp);
950 reply_nterror(req, nt_status_squash(nt_status));
951 END_PROFILE(SMBsesssetupX);
952 return;
955 if (session_info->session_key.length > 0) {
956 uint8_t session_key[16];
959 * Note: the SMB1 signing key is not truncated to 16 byte!
961 session->global->signing_key =
962 data_blob_dup_talloc(session->global,
963 session_info->session_key);
964 if (session->global->signing_key.data == NULL) {
965 data_blob_free(&nt_resp);
966 data_blob_free(&lm_resp);
967 TALLOC_FREE(session);
968 reply_nterror(req, NT_STATUS_NO_MEMORY);
969 END_PROFILE(SMBsesssetupX);
970 return;
974 * The application key is truncated/padded to 16 bytes
976 ZERO_STRUCT(session_key);
977 memcpy(session_key, session->global->signing_key.data,
978 MIN(session->global->signing_key.length,
979 sizeof(session_key)));
980 session->global->application_key =
981 data_blob_talloc(session->global,
982 session_key,
983 sizeof(session_key));
984 ZERO_STRUCT(session_key);
985 if (session->global->application_key.data == NULL) {
986 data_blob_free(&nt_resp);
987 data_blob_free(&lm_resp);
988 TALLOC_FREE(session);
989 reply_nterror(req, NT_STATUS_NO_MEMORY);
990 END_PROFILE(SMBsesssetupX);
991 return;
995 * Place the application key into the session_info
997 data_blob_clear_free(&session_info->session_key);
998 session_info->session_key = data_blob_dup_talloc(session_info,
999 session->global->application_key);
1000 if (session_info->session_key.data == NULL) {
1001 data_blob_free(&nt_resp);
1002 data_blob_free(&lm_resp);
1003 TALLOC_FREE(session);
1004 reply_nterror(req, NT_STATUS_NO_MEMORY);
1005 END_PROFILE(SMBsesssetupX);
1006 return;
1010 session->compat = talloc_zero(session, struct user_struct);
1011 if (session->compat == NULL) {
1012 data_blob_free(&nt_resp);
1013 data_blob_free(&lm_resp);
1014 TALLOC_FREE(session);
1015 reply_nterror(req, NT_STATUS_NO_MEMORY);
1016 END_PROFILE(SMBsesssetupX);
1017 return;
1019 session->compat->session = session;
1020 session->compat->homes_snum = -1;
1021 session->compat->session_info = session_info;
1022 session->compat->session_keystr = NULL;
1023 session->compat->vuid = session->global->session_wire_id;
1024 DLIST_ADD(sconn->users, session->compat);
1025 sconn->num_users++;
1027 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1028 session->compat->homes_snum =
1029 register_homes_share(session_info->unix_info->unix_name);
1032 if (srv_is_signing_negotiated(sconn) &&
1033 action == 0 &&
1034 session->global->signing_key.length > 0)
1037 * Try and turn on server signing on the first non-guest
1038 * sessionsetup.
1040 srv_set_signing(sconn,
1041 session->global->signing_key,
1042 nt_resp.data ? nt_resp : lm_resp);
1045 set_current_user_info(session_info->unix_info->sanitized_username,
1046 session_info->unix_info->unix_name,
1047 session_info->info->domain_name);
1049 session->status = NT_STATUS_OK;
1050 session->global->auth_session_info = talloc_move(session->global,
1051 &session_info);
1052 session->global->auth_session_info_seqnum += 1;
1053 session->global->channels[0].auth_session_info_seqnum =
1054 session->global->auth_session_info_seqnum;
1055 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1057 nt_status = smbXsrv_session_update(session);
1058 if (!NT_STATUS_IS_OK(nt_status)) {
1059 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1060 (unsigned long long)session->compat->vuid,
1061 nt_errstr(nt_status)));
1062 data_blob_free(&nt_resp);
1063 data_blob_free(&lm_resp);
1064 TALLOC_FREE(session);
1065 reply_nterror(req, nt_status_squash(nt_status));
1066 END_PROFILE(SMBsesssetupX);
1067 return;
1070 if (!session_claim(session)) {
1071 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1072 (unsigned long long)session->compat->vuid));
1073 data_blob_free(&nt_resp);
1074 data_blob_free(&lm_resp);
1075 TALLOC_FREE(session);
1076 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1077 END_PROFILE(SMBsesssetupX);
1078 return;
1081 /* current_user_info is changed on new vuid */
1082 reload_services(sconn, conn_snum_used, true);
1084 sess_vuid = session->global->session_wire_id;
1086 data_blob_free(&nt_resp);
1087 data_blob_free(&lm_resp);
1089 SSVAL(req->outbuf,smb_vwv2,action);
1090 SSVAL(req->outbuf,smb_uid,sess_vuid);
1091 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1092 req->vuid = sess_vuid;
1094 if (!sconn->smb1.sessions.done_sesssetup) {
1095 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1096 reply_force_doserror(req, ERRSRV, ERRerror);
1097 END_PROFILE(SMBsesssetupX);
1098 return;
1100 sconn->smb1.sessions.max_send = smb_bufsize;
1101 sconn->smb1.sessions.done_sesssetup = true;
1104 END_PROFILE(SMBsesssetupX);