s3:smbd: setup session->global->signing_/application_key during old SMB1 session...
[Samba.git] / source3 / smbd / sesssetup.c
blob003e4952f2d013defd815523e2bbcc69ff147c78
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;
377 * Keep the application key
379 data_blob_clear_free(&session_info->session_key);
380 session_info->session_key =
381 session->global->auth_session_info->session_key;
382 talloc_steal(session_info, session_info->session_key.data);
383 TALLOC_FREE(session->global->auth_session_info);
385 session->compat->session_info = session_info;
387 session->compat->vuid = session->global->session_wire_id;
389 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
390 session->compat->homes_snum =
391 register_homes_share(session_info->unix_info->unix_name);
394 set_current_user_info(session_info->unix_info->sanitized_username,
395 session_info->unix_info->unix_name,
396 session_info->info->domain_name);
398 session->status = NT_STATUS_OK;
399 session->global->auth_session_info = talloc_move(session->global,
400 &session_info);
401 session->global->auth_session_info_seqnum += 1;
402 session->global->channels[0].auth_session_info_seqnum =
403 session->global->auth_session_info_seqnum;
404 if (client_caps & CAP_DYNAMIC_REAUTH) {
405 session->global->expiration_time =
406 gensec_expire_time(session->gensec);
407 } else {
408 session->global->expiration_time =
409 GENSEC_EXPIRE_TIME_INFINITY;
412 status = smbXsrv_session_update(session);
413 if (!NT_STATUS_IS_OK(status)) {
414 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
415 (unsigned long long)session->compat->vuid,
416 nt_errstr(status)));
417 data_blob_free(&out_blob);
418 TALLOC_FREE(session);
419 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
420 return;
423 conn_clear_vuid_caches(sconn, session->compat->vuid);
425 /* current_user_info is changed on new vuid */
426 reload_services(sconn, conn_snum_used, true);
429 vuid = session->global->session_wire_id;
431 reply_outbuf(req, 4, 0);
433 SSVAL(req->outbuf, smb_uid, vuid);
434 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
435 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
436 SSVAL(req->outbuf, smb_vwv2, action);
437 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
439 if (message_push_blob(&req->outbuf, out_blob) == -1) {
440 data_blob_free(&out_blob);
441 TALLOC_FREE(session);
442 reply_nterror(req, NT_STATUS_NO_MEMORY);
443 return;
445 data_blob_free(&out_blob);
447 if (push_signature(&req->outbuf) == -1) {
448 TALLOC_FREE(session);
449 reply_nterror(req, NT_STATUS_NO_MEMORY);
450 return;
454 /****************************************************************************
455 On new VC == 0, shutdown *all* old connections and users.
456 It seems that only NT4.x does this. At W2K and above (XP etc.).
457 a new session setup with VC==0 is ignored.
458 ****************************************************************************/
460 struct shutdown_state {
461 const char *ip;
462 struct messaging_context *msg_ctx;
465 static int shutdown_other_smbds(const struct connections_key *key,
466 const struct connections_data *crec,
467 void *private_data)
469 struct shutdown_state *state = (struct shutdown_state *)private_data;
470 struct server_id self_pid = messaging_server_id(state->msg_ctx);
472 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
473 server_id_str(talloc_tos(), &crec->pid), crec->addr));
475 if (!process_exists(crec->pid)) {
476 DEBUG(10, ("process does not exist\n"));
477 return 0;
480 if (serverid_equal(&crec->pid, &self_pid)) {
481 DEBUG(10, ("It's me\n"));
482 return 0;
485 if (strcmp(state->ip, crec->addr) != 0) {
486 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
487 return 0;
490 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
491 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
492 state->ip));
494 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
495 &data_blob_null);
496 return 0;
499 static void setup_new_vc_session(struct smbd_server_connection *sconn)
501 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
502 "compatible we would close all old resources.\n"));
503 #if 0
504 conn_close_all();
505 invalidate_all_vuids();
506 #endif
507 if (lp_reset_on_zero_vc()) {
508 char *addr;
509 struct shutdown_state state;
511 addr = tsocket_address_inet_addr_string(
512 sconn->remote_address, talloc_tos());
513 if (addr == NULL) {
514 return;
516 state.ip = addr;
517 state.msg_ctx = sconn->msg_ctx;
518 connections_forall_read(shutdown_other_smbds, &state);
519 TALLOC_FREE(addr);
523 /****************************************************************************
524 Reply to a session setup command.
525 ****************************************************************************/
527 void reply_sesssetup_and_X(struct smb_request *req)
529 uint64_t sess_vuid;
530 int smb_bufsize;
531 DATA_BLOB lm_resp;
532 DATA_BLOB nt_resp;
533 DATA_BLOB plaintext_password;
534 char *tmp;
535 const char *user;
536 fstring sub_user; /* Sanitised username for substituion */
537 const char *domain;
538 const char *native_os;
539 const char *native_lanman;
540 const char *primary_domain;
541 struct auth_usersupplied_info *user_info = NULL;
542 struct auth_session_info *session_info = NULL;
543 uint16 smb_flag2 = req->flags2;
544 uint16_t action = 0;
545 NTTIME now = timeval_to_nttime(&req->request_time);
546 struct smbXsrv_session *session = NULL;
548 NTSTATUS nt_status;
549 struct smbd_server_connection *sconn = req->sconn;
551 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
552 bool signing_allowed = false;
553 bool signing_mandatory = false;
555 START_PROFILE(SMBsesssetupX);
557 ZERO_STRUCT(lm_resp);
558 ZERO_STRUCT(nt_resp);
559 ZERO_STRUCT(plaintext_password);
561 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
563 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
564 signing_allowed = true;
566 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
567 signing_mandatory = true;
571 * We can call srv_set_signing_negotiated() each time.
572 * It finds out when it needs to turn into a noop
573 * itself.
575 srv_set_signing_negotiated(req->sconn,
576 signing_allowed,
577 signing_mandatory);
579 /* a SPNEGO session setup has 12 command words, whereas a normal
580 NT1 session setup has 13. See the cifs spec. */
581 if (req->wct == 12 &&
582 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
584 if (!sconn->smb1.negprot.spnego) {
585 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
586 "at SPNEGO session setup when it was not "
587 "negotiated.\n"));
588 reply_nterror(req, nt_status_squash(
589 NT_STATUS_LOGON_FAILURE));
590 END_PROFILE(SMBsesssetupX);
591 return;
594 if (SVAL(req->vwv+4, 0) == 0) {
595 setup_new_vc_session(req->sconn);
598 reply_sesssetup_and_X_spnego(req);
599 END_PROFILE(SMBsesssetupX);
600 return;
603 smb_bufsize = SVAL(req->vwv+2, 0);
605 if (get_Protocol() < PROTOCOL_NT1) {
606 uint16 passlen1 = SVAL(req->vwv+7, 0);
608 /* Never do NT status codes with protocols before NT1 as we
609 * don't get client caps. */
610 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
612 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
613 reply_nterror(req, nt_status_squash(
614 NT_STATUS_INVALID_PARAMETER));
615 END_PROFILE(SMBsesssetupX);
616 return;
619 if (doencrypt) {
620 lm_resp = data_blob(req->buf, passlen1);
621 } else {
622 plaintext_password = data_blob(req->buf, passlen1+1);
623 /* Ensure null termination */
624 plaintext_password.data[passlen1] = 0;
627 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
628 req->buf + passlen1, STR_TERMINATE);
629 user = tmp ? tmp : "";
631 domain = "";
633 } else {
634 uint16 passlen1 = SVAL(req->vwv+7, 0);
635 uint16 passlen2 = SVAL(req->vwv+8, 0);
636 enum remote_arch_types ra_type = get_remote_arch();
637 const uint8_t *p = req->buf;
638 const uint8_t *save_p = req->buf;
639 uint16 byte_count;
642 if(global_client_caps == 0) {
643 global_client_caps = IVAL(req->vwv+11, 0);
645 if (!(global_client_caps & CAP_STATUS32)) {
646 remove_from_common_flags2(
647 FLAGS2_32_BIT_ERROR_CODES);
650 /* client_caps is used as final determination if
651 * client is NT or Win95. This is needed to return
652 * the correct error codes in some circumstances.
655 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
656 ra_type == RA_WIN95) {
657 if(!(global_client_caps & (CAP_NT_SMBS|
658 CAP_STATUS32))) {
659 set_remote_arch( RA_WIN95);
664 if (!doencrypt) {
665 /* both Win95 and WinNT stuff up the password
666 * lengths for non-encrypting systems. Uggh.
668 if passlen1==24 its a win95 system, and its setting
669 the password length incorrectly. Luckily it still
670 works with the default code because Win95 will null
671 terminate the password anyway
673 if passlen1>0 and passlen2>0 then maybe its a NT box
674 and its setting passlen2 to some random value which
675 really stuffs things up. we need to fix that one. */
677 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
678 passlen2 != 1) {
679 passlen2 = 0;
683 /* check for nasty tricks */
684 if (passlen1 > MAX_PASS_LEN
685 || passlen1 > smbreq_bufrem(req, p)) {
686 reply_nterror(req, nt_status_squash(
687 NT_STATUS_INVALID_PARAMETER));
688 END_PROFILE(SMBsesssetupX);
689 return;
692 if (passlen2 > MAX_PASS_LEN
693 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
694 reply_nterror(req, nt_status_squash(
695 NT_STATUS_INVALID_PARAMETER));
696 END_PROFILE(SMBsesssetupX);
697 return;
700 /* Save the lanman2 password and the NT md4 password. */
702 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
703 doencrypt = False;
706 if (doencrypt) {
707 lm_resp = data_blob(p, passlen1);
708 nt_resp = data_blob(p+passlen1, passlen2);
709 } else {
710 char *pass = NULL;
711 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
713 if (unic && (passlen2 == 0) && passlen1) {
714 /* Only a ascii plaintext password was sent. */
715 (void)srvstr_pull_talloc(talloc_tos(),
716 req->inbuf,
717 req->flags2,
718 &pass,
719 req->buf,
720 passlen1,
721 STR_TERMINATE|STR_ASCII);
722 } else {
723 (void)srvstr_pull_talloc(talloc_tos(),
724 req->inbuf,
725 req->flags2,
726 &pass,
727 req->buf,
728 unic ? passlen2 : passlen1,
729 STR_TERMINATE);
731 if (!pass) {
732 reply_nterror(req, nt_status_squash(
733 NT_STATUS_INVALID_PARAMETER));
734 END_PROFILE(SMBsesssetupX);
735 return;
737 plaintext_password = data_blob(pass, strlen(pass)+1);
740 p += passlen1 + passlen2;
742 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
743 STR_TERMINATE);
744 user = tmp ? tmp : "";
746 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
747 STR_TERMINATE);
748 domain = tmp ? tmp : "";
750 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
751 STR_TERMINATE);
752 native_os = tmp ? tmp : "";
754 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
755 STR_TERMINATE);
756 native_lanman = tmp ? tmp : "";
758 /* not documented or decoded by Ethereal but there is one more
759 * string in the extra bytes which is the same as the
760 * PrimaryDomain when using extended security. Windows NT 4
761 * and 2003 use this string to store the native lanman string.
762 * Windows 9x does not include a string here at all so we have
763 * to check if we have any extra bytes left */
765 byte_count = SVAL(req->vwv+13, 0);
766 if ( PTR_DIFF(p, save_p) < byte_count) {
767 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
768 STR_TERMINATE);
769 primary_domain = tmp ? tmp : "";
770 } else {
771 primary_domain = talloc_strdup(talloc_tos(), "null");
774 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
775 "PrimaryDomain=[%s]\n",
776 domain, native_os, native_lanman, primary_domain));
778 if ( ra_type == RA_WIN2K ) {
779 if ( strlen(native_lanman) == 0 )
780 ra_lanman_string( primary_domain );
781 else
782 ra_lanman_string( native_lanman );
787 if (SVAL(req->vwv+4, 0) == 0) {
788 setup_new_vc_session(req->sconn);
791 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
792 domain, user, get_remote_machine_name()));
794 if (*user) {
795 if (sconn->smb1.negprot.spnego) {
797 /* This has to be here, because this is a perfectly
798 * valid behaviour for guest logons :-( */
800 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
801 "at 'normal' session setup after "
802 "negotiating spnego.\n"));
803 reply_nterror(req, nt_status_squash(
804 NT_STATUS_LOGON_FAILURE));
805 END_PROFILE(SMBsesssetupX);
806 return;
808 fstrcpy(sub_user, user);
809 } else {
810 fstrcpy(sub_user, "");
813 sub_set_smb_name(sub_user);
815 reload_services(sconn, conn_snum_used, true);
817 if (!*user) {
819 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
821 } else if (doencrypt) {
822 struct auth4_context *negprot_auth_context = NULL;
823 negprot_auth_context = sconn->smb1.negprot.auth_context;
824 if (!negprot_auth_context) {
825 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
826 "session setup without negprot denied!\n"));
827 reply_nterror(req, nt_status_squash(
828 NT_STATUS_LOGON_FAILURE));
829 END_PROFILE(SMBsesssetupX);
830 return;
832 nt_status = make_user_info_for_reply_enc(&user_info, user,
833 domain,
834 sconn->remote_address,
835 lm_resp, nt_resp);
836 if (NT_STATUS_IS_OK(nt_status)) {
837 nt_status = auth_check_password_session_info(negprot_auth_context,
838 req, user_info, &session_info);
840 } else {
841 struct auth4_context *plaintext_auth_context = NULL;
843 nt_status = make_auth4_context(
844 talloc_tos(), &plaintext_auth_context);
846 if (NT_STATUS_IS_OK(nt_status)) {
847 uint8_t chal[8];
849 plaintext_auth_context->get_ntlm_challenge(
850 plaintext_auth_context, chal);
852 if (!make_user_info_for_reply(&user_info,
853 user, domain,
854 sconn->remote_address,
855 chal,
856 plaintext_password)) {
857 nt_status = NT_STATUS_NO_MEMORY;
860 if (NT_STATUS_IS_OK(nt_status)) {
861 nt_status = auth_check_password_session_info(plaintext_auth_context,
862 req, user_info, &session_info);
864 TALLOC_FREE(plaintext_auth_context);
868 free_user_info(&user_info);
870 if (!NT_STATUS_IS_OK(nt_status)) {
871 data_blob_free(&nt_resp);
872 data_blob_free(&lm_resp);
873 data_blob_clear_free(&plaintext_password);
874 reply_nterror(req, nt_status_squash(nt_status));
875 END_PROFILE(SMBsesssetupX);
876 return;
879 data_blob_clear_free(&plaintext_password);
881 /* it's ok - setup a reply */
882 reply_outbuf(req, 3, 0);
883 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
884 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
886 if (get_Protocol() >= PROTOCOL_NT1) {
887 push_signature(&req->outbuf);
888 /* perhaps grab OS version here?? */
891 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
892 action = 1;
895 /* register the name and uid as being validated, so further connections
896 to a uid can get through without a password, on the same VC */
898 nt_status = smbXsrv_session_create(sconn->conn,
899 now, &session);
900 if (!NT_STATUS_IS_OK(nt_status)) {
901 data_blob_free(&nt_resp);
902 data_blob_free(&lm_resp);
903 reply_nterror(req, nt_status_squash(nt_status));
904 END_PROFILE(SMBsesssetupX);
905 return;
908 if (session_info->session_key.length > 0) {
909 uint8_t session_key[16];
912 * Note: the SMB1 signing key is not truncated to 16 byte!
914 session->global->signing_key =
915 data_blob_dup_talloc(session->global,
916 session_info->session_key);
917 if (session->global->signing_key.data == NULL) {
918 data_blob_free(&nt_resp);
919 data_blob_free(&lm_resp);
920 TALLOC_FREE(session);
921 reply_nterror(req, NT_STATUS_NO_MEMORY);
922 END_PROFILE(SMBsesssetupX);
923 return;
927 * The application key is truncated/padded to 16 bytes
929 ZERO_STRUCT(session_key);
930 memcpy(session_key, session->global->signing_key.data,
931 MIN(session->global->signing_key.length,
932 sizeof(session_key)));
933 session->global->application_key =
934 data_blob_talloc(session->global,
935 session_key,
936 sizeof(session_key));
937 ZERO_STRUCT(session_key);
938 if (session->global->application_key.data == NULL) {
939 data_blob_free(&nt_resp);
940 data_blob_free(&lm_resp);
941 TALLOC_FREE(session);
942 reply_nterror(req, NT_STATUS_NO_MEMORY);
943 END_PROFILE(SMBsesssetupX);
944 return;
948 * Place the application key into the session_info
950 data_blob_clear_free(&session_info->session_key);
951 session_info->session_key = data_blob_dup_talloc(session_info,
952 session->global->application_key);
953 if (session_info->session_key.data == NULL) {
954 data_blob_free(&nt_resp);
955 data_blob_free(&lm_resp);
956 TALLOC_FREE(session);
957 reply_nterror(req, NT_STATUS_NO_MEMORY);
958 END_PROFILE(SMBsesssetupX);
959 return;
963 session->compat = talloc_zero(session, struct user_struct);
964 if (session->compat == 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;
972 session->compat->session = session;
973 session->compat->homes_snum = -1;
974 session->compat->session_info = session_info;
975 session->compat->session_keystr = NULL;
976 session->compat->vuid = session->global->session_wire_id;
977 DLIST_ADD(sconn->users, session->compat);
978 sconn->num_users++;
980 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
981 session->compat->homes_snum =
982 register_homes_share(session_info->unix_info->unix_name);
985 if (!session_claim(sconn, session->compat)) {
986 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
987 (unsigned long long)session->compat->vuid));
988 data_blob_free(&nt_resp);
989 data_blob_free(&lm_resp);
990 TALLOC_FREE(session);
991 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
992 END_PROFILE(SMBsesssetupX);
993 return;
996 if (srv_is_signing_negotiated(sconn) &&
997 action == 0 &&
998 session->global->signing_key.length > 0)
1001 * Try and turn on server signing on the first non-guest
1002 * sessionsetup.
1004 srv_set_signing(sconn,
1005 session->global->signing_key,
1006 nt_resp.data ? nt_resp : lm_resp);
1009 set_current_user_info(session_info->unix_info->sanitized_username,
1010 session_info->unix_info->unix_name,
1011 session_info->info->domain_name);
1013 session->status = NT_STATUS_OK;
1014 session->global->auth_session_info = talloc_move(session->global,
1015 &session_info);
1016 session->global->auth_session_info_seqnum += 1;
1017 session->global->channels[0].auth_session_info_seqnum =
1018 session->global->auth_session_info_seqnum;
1019 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1021 nt_status = smbXsrv_session_update(session);
1022 if (!NT_STATUS_IS_OK(nt_status)) {
1023 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1024 (unsigned long long)session->compat->vuid,
1025 nt_errstr(nt_status)));
1026 data_blob_free(&nt_resp);
1027 data_blob_free(&lm_resp);
1028 TALLOC_FREE(session);
1029 reply_nterror(req, nt_status_squash(nt_status));
1030 END_PROFILE(SMBsesssetupX);
1031 return;
1034 /* current_user_info is changed on new vuid */
1035 reload_services(sconn, conn_snum_used, true);
1037 sess_vuid = session->global->session_wire_id;
1039 data_blob_free(&nt_resp);
1040 data_blob_free(&lm_resp);
1042 SSVAL(req->outbuf,smb_vwv2,action);
1043 SSVAL(req->outbuf,smb_uid,sess_vuid);
1044 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1045 req->vuid = sess_vuid;
1047 if (!sconn->smb1.sessions.done_sesssetup) {
1048 sconn->smb1.sessions.max_send =
1049 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1051 sconn->smb1.sessions.done_sesssetup = true;
1053 END_PROFILE(SMBsesssetupX);