s3:smbd: remove smbd_server_connection argument from session_claim()
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blobcd7928de505e3abf4747b86d9eb3e8a62a74ae90
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 if (session_info->session_key.length > 0) {
287 struct smbXsrv_session *x = session;
290 * Note: the SMB1 signing key is not truncated to 16 byte!
292 x->global->signing_key =
293 data_blob_dup_talloc(x->global,
294 session_info->session_key);
295 if (x->global->signing_key.data == NULL) {
296 data_blob_free(&out_blob);
297 TALLOC_FREE(session);
298 reply_nterror(req, NT_STATUS_NO_MEMORY);
299 return;
303 * clear the session key
304 * the first tcon will add setup the application key
306 data_blob_clear_free(&session_info->session_key);
309 session->compat = talloc_zero(session, struct user_struct);
310 if (session->compat == NULL) {
311 data_blob_free(&out_blob);
312 TALLOC_FREE(session);
313 reply_nterror(req, NT_STATUS_NO_MEMORY);
314 return;
316 session->compat->session = session;
317 session->compat->homes_snum = -1;
318 session->compat->session_info = session_info;
319 session->compat->session_keystr = NULL;
320 session->compat->vuid = session->global->session_wire_id;
321 DLIST_ADD(sconn->users, session->compat);
322 sconn->num_users++;
324 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
325 session->compat->homes_snum =
326 register_homes_share(session_info->unix_info->unix_name);
329 if (!session_claim(session)) {
330 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
331 (unsigned long long)session->compat->vuid));
332 data_blob_free(&out_blob);
333 TALLOC_FREE(session);
334 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
335 return;
338 if (srv_is_signing_negotiated(sconn) &&
339 action == 0 &&
340 session->global->signing_key.length > 0)
343 * Try and turn on server signing on the first non-guest
344 * sessionsetup.
346 srv_set_signing(sconn,
347 session->global->signing_key,
348 data_blob_null);
351 set_current_user_info(session_info->unix_info->sanitized_username,
352 session_info->unix_info->unix_name,
353 session_info->info->domain_name);
355 session->status = NT_STATUS_OK;
356 session->global->auth_session_info = talloc_move(session->global,
357 &session_info);
358 session->global->auth_session_info_seqnum += 1;
359 session->global->channels[0].auth_session_info_seqnum =
360 session->global->auth_session_info_seqnum;
361 if (client_caps & CAP_DYNAMIC_REAUTH) {
362 session->global->expiration_time =
363 gensec_expire_time(session->gensec);
364 } else {
365 session->global->expiration_time =
366 GENSEC_EXPIRE_TIME_INFINITY;
369 status = smbXsrv_session_update(session);
370 if (!NT_STATUS_IS_OK(status)) {
371 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
372 (unsigned long long)session->compat->vuid,
373 nt_errstr(status)));
374 data_blob_free(&out_blob);
375 TALLOC_FREE(session);
376 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
377 return;
380 /* current_user_info is changed on new vuid */
381 reload_services(sconn, conn_snum_used, true);
382 } else if (NT_STATUS_IS_OK(status)) {
383 struct auth_session_info *session_info = NULL;
385 status = gensec_session_info(session->gensec,
386 session,
387 &session_info);
388 if (!NT_STATUS_IS_OK(status)) {
389 DEBUG(1,("Failed to generate session_info "
390 "(user and group token) for session setup: %s\n",
391 nt_errstr(status)));
392 data_blob_free(&out_blob);
393 TALLOC_FREE(session);
394 reply_nterror(req, nt_status_squash(status));
395 return;
398 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
399 action = 1;
403 * Keep the application key
405 data_blob_clear_free(&session_info->session_key);
406 session_info->session_key =
407 session->global->auth_session_info->session_key;
408 talloc_steal(session_info, session_info->session_key.data);
409 TALLOC_FREE(session->global->auth_session_info);
411 session->compat->session_info = session_info;
413 session->compat->vuid = session->global->session_wire_id;
415 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
416 session->compat->homes_snum =
417 register_homes_share(session_info->unix_info->unix_name);
420 set_current_user_info(session_info->unix_info->sanitized_username,
421 session_info->unix_info->unix_name,
422 session_info->info->domain_name);
424 session->status = NT_STATUS_OK;
425 session->global->auth_session_info = talloc_move(session->global,
426 &session_info);
427 session->global->auth_session_info_seqnum += 1;
428 session->global->channels[0].auth_session_info_seqnum =
429 session->global->auth_session_info_seqnum;
430 if (client_caps & CAP_DYNAMIC_REAUTH) {
431 session->global->expiration_time =
432 gensec_expire_time(session->gensec);
433 } else {
434 session->global->expiration_time =
435 GENSEC_EXPIRE_TIME_INFINITY;
438 status = smbXsrv_session_update(session);
439 if (!NT_STATUS_IS_OK(status)) {
440 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
441 (unsigned long long)session->compat->vuid,
442 nt_errstr(status)));
443 data_blob_free(&out_blob);
444 TALLOC_FREE(session);
445 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
446 return;
449 conn_clear_vuid_caches(sconn, session->compat->vuid);
451 /* current_user_info is changed on new vuid */
452 reload_services(sconn, conn_snum_used, true);
455 vuid = session->global->session_wire_id;
457 reply_outbuf(req, 4, 0);
459 SSVAL(req->outbuf, smb_uid, vuid);
460 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
461 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
462 SSVAL(req->outbuf, smb_vwv2, action);
463 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
465 if (message_push_blob(&req->outbuf, out_blob) == -1) {
466 data_blob_free(&out_blob);
467 TALLOC_FREE(session);
468 reply_nterror(req, NT_STATUS_NO_MEMORY);
469 return;
471 data_blob_free(&out_blob);
473 if (push_signature(&req->outbuf) == -1) {
474 TALLOC_FREE(session);
475 reply_nterror(req, NT_STATUS_NO_MEMORY);
476 return;
480 /****************************************************************************
481 On new VC == 0, shutdown *all* old connections and users.
482 It seems that only NT4.x does this. At W2K and above (XP etc.).
483 a new session setup with VC==0 is ignored.
484 ****************************************************************************/
486 struct shutdown_state {
487 const char *ip;
488 struct messaging_context *msg_ctx;
491 static int shutdown_other_smbds(const struct connections_key *key,
492 const struct connections_data *crec,
493 void *private_data)
495 struct shutdown_state *state = (struct shutdown_state *)private_data;
496 struct server_id self_pid = messaging_server_id(state->msg_ctx);
498 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
499 server_id_str(talloc_tos(), &crec->pid), crec->addr));
501 if (!process_exists(crec->pid)) {
502 DEBUG(10, ("process does not exist\n"));
503 return 0;
506 if (serverid_equal(&crec->pid, &self_pid)) {
507 DEBUG(10, ("It's me\n"));
508 return 0;
511 if (strcmp(state->ip, crec->addr) != 0) {
512 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
513 return 0;
516 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
517 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
518 state->ip));
520 messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
521 &data_blob_null);
522 return 0;
525 static void setup_new_vc_session(struct smbd_server_connection *sconn)
527 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
528 "compatible we would close all old resources.\n"));
529 #if 0
530 conn_close_all();
531 invalidate_all_vuids();
532 #endif
533 if (lp_reset_on_zero_vc()) {
534 char *addr;
535 struct shutdown_state state;
537 addr = tsocket_address_inet_addr_string(
538 sconn->remote_address, talloc_tos());
539 if (addr == NULL) {
540 return;
542 state.ip = addr;
543 state.msg_ctx = sconn->msg_ctx;
544 connections_forall_read(shutdown_other_smbds, &state);
545 TALLOC_FREE(addr);
549 /****************************************************************************
550 Reply to a session setup command.
551 ****************************************************************************/
553 void reply_sesssetup_and_X(struct smb_request *req)
555 uint64_t sess_vuid;
556 int smb_bufsize;
557 DATA_BLOB lm_resp;
558 DATA_BLOB nt_resp;
559 DATA_BLOB plaintext_password;
560 char *tmp;
561 const char *user;
562 fstring sub_user; /* Sanitised username for substituion */
563 const char *domain;
564 const char *native_os;
565 const char *native_lanman;
566 const char *primary_domain;
567 struct auth_usersupplied_info *user_info = NULL;
568 struct auth_session_info *session_info = NULL;
569 uint16 smb_flag2 = req->flags2;
570 uint16_t action = 0;
571 NTTIME now = timeval_to_nttime(&req->request_time);
572 struct smbXsrv_session *session = NULL;
574 NTSTATUS nt_status;
575 struct smbd_server_connection *sconn = req->sconn;
577 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
578 bool signing_allowed = false;
579 bool signing_mandatory = false;
581 START_PROFILE(SMBsesssetupX);
583 ZERO_STRUCT(lm_resp);
584 ZERO_STRUCT(nt_resp);
585 ZERO_STRUCT(plaintext_password);
587 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
589 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
590 signing_allowed = true;
592 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
593 signing_mandatory = true;
597 * We can call srv_set_signing_negotiated() each time.
598 * It finds out when it needs to turn into a noop
599 * itself.
601 srv_set_signing_negotiated(req->sconn,
602 signing_allowed,
603 signing_mandatory);
605 /* a SPNEGO session setup has 12 command words, whereas a normal
606 NT1 session setup has 13. See the cifs spec. */
607 if (req->wct == 12 &&
608 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
610 if (!sconn->smb1.negprot.spnego) {
611 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
612 "at SPNEGO session setup when it was not "
613 "negotiated.\n"));
614 reply_nterror(req, nt_status_squash(
615 NT_STATUS_LOGON_FAILURE));
616 END_PROFILE(SMBsesssetupX);
617 return;
620 if (SVAL(req->vwv+4, 0) == 0) {
621 setup_new_vc_session(req->sconn);
624 reply_sesssetup_and_X_spnego(req);
625 END_PROFILE(SMBsesssetupX);
626 return;
629 smb_bufsize = SVAL(req->vwv+2, 0);
631 if (get_Protocol() < PROTOCOL_NT1) {
632 uint16 passlen1 = SVAL(req->vwv+7, 0);
634 /* Never do NT status codes with protocols before NT1 as we
635 * don't get client caps. */
636 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
638 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
639 reply_nterror(req, nt_status_squash(
640 NT_STATUS_INVALID_PARAMETER));
641 END_PROFILE(SMBsesssetupX);
642 return;
645 if (doencrypt) {
646 lm_resp = data_blob(req->buf, passlen1);
647 } else {
648 plaintext_password = data_blob(req->buf, passlen1+1);
649 /* Ensure null termination */
650 plaintext_password.data[passlen1] = 0;
653 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
654 req->buf + passlen1, STR_TERMINATE);
655 user = tmp ? tmp : "";
657 domain = "";
659 } else {
660 uint16 passlen1 = SVAL(req->vwv+7, 0);
661 uint16 passlen2 = SVAL(req->vwv+8, 0);
662 enum remote_arch_types ra_type = get_remote_arch();
663 const uint8_t *p = req->buf;
664 const uint8_t *save_p = req->buf;
665 uint16 byte_count;
668 if(global_client_caps == 0) {
669 global_client_caps = IVAL(req->vwv+11, 0);
671 if (!(global_client_caps & CAP_STATUS32)) {
672 remove_from_common_flags2(
673 FLAGS2_32_BIT_ERROR_CODES);
676 /* client_caps is used as final determination if
677 * client is NT or Win95. This is needed to return
678 * the correct error codes in some circumstances.
681 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
682 ra_type == RA_WIN95) {
683 if(!(global_client_caps & (CAP_NT_SMBS|
684 CAP_STATUS32))) {
685 set_remote_arch( RA_WIN95);
690 if (!doencrypt) {
691 /* both Win95 and WinNT stuff up the password
692 * lengths for non-encrypting systems. Uggh.
694 if passlen1==24 its a win95 system, and its setting
695 the password length incorrectly. Luckily it still
696 works with the default code because Win95 will null
697 terminate the password anyway
699 if passlen1>0 and passlen2>0 then maybe its a NT box
700 and its setting passlen2 to some random value which
701 really stuffs things up. we need to fix that one. */
703 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
704 passlen2 != 1) {
705 passlen2 = 0;
709 /* check for nasty tricks */
710 if (passlen1 > MAX_PASS_LEN
711 || passlen1 > smbreq_bufrem(req, p)) {
712 reply_nterror(req, nt_status_squash(
713 NT_STATUS_INVALID_PARAMETER));
714 END_PROFILE(SMBsesssetupX);
715 return;
718 if (passlen2 > MAX_PASS_LEN
719 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
720 reply_nterror(req, nt_status_squash(
721 NT_STATUS_INVALID_PARAMETER));
722 END_PROFILE(SMBsesssetupX);
723 return;
726 /* Save the lanman2 password and the NT md4 password. */
728 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
729 doencrypt = False;
732 if (doencrypt) {
733 lm_resp = data_blob(p, passlen1);
734 nt_resp = data_blob(p+passlen1, passlen2);
735 } else {
736 char *pass = NULL;
737 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
739 if (unic && (passlen2 == 0) && passlen1) {
740 /* Only a ascii plaintext password was sent. */
741 (void)srvstr_pull_talloc(talloc_tos(),
742 req->inbuf,
743 req->flags2,
744 &pass,
745 req->buf,
746 passlen1,
747 STR_TERMINATE|STR_ASCII);
748 } else {
749 (void)srvstr_pull_talloc(talloc_tos(),
750 req->inbuf,
751 req->flags2,
752 &pass,
753 req->buf,
754 unic ? passlen2 : passlen1,
755 STR_TERMINATE);
757 if (!pass) {
758 reply_nterror(req, nt_status_squash(
759 NT_STATUS_INVALID_PARAMETER));
760 END_PROFILE(SMBsesssetupX);
761 return;
763 plaintext_password = data_blob(pass, strlen(pass)+1);
766 p += passlen1 + passlen2;
768 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
769 STR_TERMINATE);
770 user = tmp ? tmp : "";
772 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
773 STR_TERMINATE);
774 domain = tmp ? tmp : "";
776 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
777 STR_TERMINATE);
778 native_os = tmp ? tmp : "";
780 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
781 STR_TERMINATE);
782 native_lanman = tmp ? tmp : "";
784 /* not documented or decoded by Ethereal but there is one more
785 * string in the extra bytes which is the same as the
786 * PrimaryDomain when using extended security. Windows NT 4
787 * and 2003 use this string to store the native lanman string.
788 * Windows 9x does not include a string here at all so we have
789 * to check if we have any extra bytes left */
791 byte_count = SVAL(req->vwv+13, 0);
792 if ( PTR_DIFF(p, save_p) < byte_count) {
793 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
794 STR_TERMINATE);
795 primary_domain = tmp ? tmp : "";
796 } else {
797 primary_domain = talloc_strdup(talloc_tos(), "null");
800 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
801 "PrimaryDomain=[%s]\n",
802 domain, native_os, native_lanman, primary_domain));
804 if ( ra_type == RA_WIN2K ) {
805 if ( strlen(native_lanman) == 0 )
806 ra_lanman_string( primary_domain );
807 else
808 ra_lanman_string( native_lanman );
813 if (SVAL(req->vwv+4, 0) == 0) {
814 setup_new_vc_session(req->sconn);
817 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
818 domain, user, get_remote_machine_name()));
820 if (*user) {
821 if (sconn->smb1.negprot.spnego) {
823 /* This has to be here, because this is a perfectly
824 * valid behaviour for guest logons :-( */
826 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
827 "at 'normal' session setup after "
828 "negotiating spnego.\n"));
829 reply_nterror(req, nt_status_squash(
830 NT_STATUS_LOGON_FAILURE));
831 END_PROFILE(SMBsesssetupX);
832 return;
834 fstrcpy(sub_user, user);
835 } else {
836 fstrcpy(sub_user, "");
839 sub_set_smb_name(sub_user);
841 reload_services(sconn, conn_snum_used, true);
843 if (!*user) {
845 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
847 } else if (doencrypt) {
848 struct auth4_context *negprot_auth_context = NULL;
849 negprot_auth_context = sconn->smb1.negprot.auth_context;
850 if (!negprot_auth_context) {
851 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
852 "session setup without negprot denied!\n"));
853 reply_nterror(req, nt_status_squash(
854 NT_STATUS_LOGON_FAILURE));
855 END_PROFILE(SMBsesssetupX);
856 return;
858 nt_status = make_user_info_for_reply_enc(&user_info, user,
859 domain,
860 sconn->remote_address,
861 lm_resp, nt_resp);
862 if (NT_STATUS_IS_OK(nt_status)) {
863 nt_status = auth_check_password_session_info(negprot_auth_context,
864 req, user_info, &session_info);
866 } else {
867 struct auth4_context *plaintext_auth_context = NULL;
869 nt_status = make_auth4_context(
870 talloc_tos(), &plaintext_auth_context);
872 if (NT_STATUS_IS_OK(nt_status)) {
873 uint8_t chal[8];
875 plaintext_auth_context->get_ntlm_challenge(
876 plaintext_auth_context, chal);
878 if (!make_user_info_for_reply(&user_info,
879 user, domain,
880 sconn->remote_address,
881 chal,
882 plaintext_password)) {
883 nt_status = NT_STATUS_NO_MEMORY;
886 if (NT_STATUS_IS_OK(nt_status)) {
887 nt_status = auth_check_password_session_info(plaintext_auth_context,
888 req, user_info, &session_info);
890 TALLOC_FREE(plaintext_auth_context);
894 free_user_info(&user_info);
896 if (!NT_STATUS_IS_OK(nt_status)) {
897 data_blob_free(&nt_resp);
898 data_blob_free(&lm_resp);
899 data_blob_clear_free(&plaintext_password);
900 reply_nterror(req, nt_status_squash(nt_status));
901 END_PROFILE(SMBsesssetupX);
902 return;
905 data_blob_clear_free(&plaintext_password);
907 /* it's ok - setup a reply */
908 reply_outbuf(req, 3, 0);
909 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
910 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
912 if (get_Protocol() >= PROTOCOL_NT1) {
913 push_signature(&req->outbuf);
914 /* perhaps grab OS version here?? */
917 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
918 action = 1;
921 /* register the name and uid as being validated, so further connections
922 to a uid can get through without a password, on the same VC */
924 nt_status = smbXsrv_session_create(sconn->conn,
925 now, &session);
926 if (!NT_STATUS_IS_OK(nt_status)) {
927 data_blob_free(&nt_resp);
928 data_blob_free(&lm_resp);
929 reply_nterror(req, nt_status_squash(nt_status));
930 END_PROFILE(SMBsesssetupX);
931 return;
934 if (session_info->session_key.length > 0) {
935 uint8_t session_key[16];
938 * Note: the SMB1 signing key is not truncated to 16 byte!
940 session->global->signing_key =
941 data_blob_dup_talloc(session->global,
942 session_info->session_key);
943 if (session->global->signing_key.data == NULL) {
944 data_blob_free(&nt_resp);
945 data_blob_free(&lm_resp);
946 TALLOC_FREE(session);
947 reply_nterror(req, NT_STATUS_NO_MEMORY);
948 END_PROFILE(SMBsesssetupX);
949 return;
953 * The application key is truncated/padded to 16 bytes
955 ZERO_STRUCT(session_key);
956 memcpy(session_key, session->global->signing_key.data,
957 MIN(session->global->signing_key.length,
958 sizeof(session_key)));
959 session->global->application_key =
960 data_blob_talloc(session->global,
961 session_key,
962 sizeof(session_key));
963 ZERO_STRUCT(session_key);
964 if (session->global->application_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 * Place the application key into the session_info
976 data_blob_clear_free(&session_info->session_key);
977 session_info->session_key = data_blob_dup_talloc(session_info,
978 session->global->application_key);
979 if (session_info->session_key.data == NULL) {
980 data_blob_free(&nt_resp);
981 data_blob_free(&lm_resp);
982 TALLOC_FREE(session);
983 reply_nterror(req, NT_STATUS_NO_MEMORY);
984 END_PROFILE(SMBsesssetupX);
985 return;
989 session->compat = talloc_zero(session, struct user_struct);
990 if (session->compat == NULL) {
991 data_blob_free(&nt_resp);
992 data_blob_free(&lm_resp);
993 TALLOC_FREE(session);
994 reply_nterror(req, NT_STATUS_NO_MEMORY);
995 END_PROFILE(SMBsesssetupX);
996 return;
998 session->compat->session = session;
999 session->compat->homes_snum = -1;
1000 session->compat->session_info = session_info;
1001 session->compat->session_keystr = NULL;
1002 session->compat->vuid = session->global->session_wire_id;
1003 DLIST_ADD(sconn->users, session->compat);
1004 sconn->num_users++;
1006 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1007 session->compat->homes_snum =
1008 register_homes_share(session_info->unix_info->unix_name);
1011 if (!session_claim(session)) {
1012 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1013 (unsigned long long)session->compat->vuid));
1014 data_blob_free(&nt_resp);
1015 data_blob_free(&lm_resp);
1016 TALLOC_FREE(session);
1017 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1018 END_PROFILE(SMBsesssetupX);
1019 return;
1022 if (srv_is_signing_negotiated(sconn) &&
1023 action == 0 &&
1024 session->global->signing_key.length > 0)
1027 * Try and turn on server signing on the first non-guest
1028 * sessionsetup.
1030 srv_set_signing(sconn,
1031 session->global->signing_key,
1032 nt_resp.data ? nt_resp : lm_resp);
1035 set_current_user_info(session_info->unix_info->sanitized_username,
1036 session_info->unix_info->unix_name,
1037 session_info->info->domain_name);
1039 session->status = NT_STATUS_OK;
1040 session->global->auth_session_info = talloc_move(session->global,
1041 &session_info);
1042 session->global->auth_session_info_seqnum += 1;
1043 session->global->channels[0].auth_session_info_seqnum =
1044 session->global->auth_session_info_seqnum;
1045 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1047 nt_status = smbXsrv_session_update(session);
1048 if (!NT_STATUS_IS_OK(nt_status)) {
1049 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1050 (unsigned long long)session->compat->vuid,
1051 nt_errstr(nt_status)));
1052 data_blob_free(&nt_resp);
1053 data_blob_free(&lm_resp);
1054 TALLOC_FREE(session);
1055 reply_nterror(req, nt_status_squash(nt_status));
1056 END_PROFILE(SMBsesssetupX);
1057 return;
1060 /* current_user_info is changed on new vuid */
1061 reload_services(sconn, conn_snum_used, true);
1063 sess_vuid = session->global->session_wire_id;
1065 data_blob_free(&nt_resp);
1066 data_blob_free(&lm_resp);
1068 SSVAL(req->outbuf,smb_vwv2,action);
1069 SSVAL(req->outbuf,smb_uid,sess_vuid);
1070 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1071 req->vuid = sess_vuid;
1073 if (!sconn->smb1.sessions.done_sesssetup) {
1074 sconn->smb1.sessions.max_send =
1075 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1077 sconn->smb1.sessions.done_sesssetup = true;
1079 END_PROFILE(SMBsesssetupX);