tevent: call epoll_panic() if EPOLL_CTL_DEL failed
[Samba/gebeck_regimport.git] / source3 / smbd / sesssetup.c
blob890189cb34373ce4a992cfdcd5d6f768d96ffef8
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 (srv_is_signing_negotiated(sconn) &&
330 action == 0 &&
331 session->global->signing_key.length > 0)
334 * Try and turn on server signing on the first non-guest
335 * sessionsetup.
337 srv_set_signing(sconn,
338 session->global->signing_key,
339 data_blob_null);
342 set_current_user_info(session_info->unix_info->sanitized_username,
343 session_info->unix_info->unix_name,
344 session_info->info->domain_name);
346 session->status = NT_STATUS_OK;
347 session->global->auth_session_info = talloc_move(session->global,
348 &session_info);
349 session->global->auth_session_info_seqnum += 1;
350 session->global->channels[0].auth_session_info_seqnum =
351 session->global->auth_session_info_seqnum;
352 if (client_caps & CAP_DYNAMIC_REAUTH) {
353 session->global->expiration_time =
354 gensec_expire_time(session->gensec);
355 } else {
356 session->global->expiration_time =
357 GENSEC_EXPIRE_TIME_INFINITY;
360 if (!session_claim(session)) {
361 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
362 (unsigned long long)session->compat->vuid));
363 data_blob_free(&out_blob);
364 TALLOC_FREE(session);
365 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
366 return;
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(struct smbXsrv_session_global0 *session,
492 void *private_data)
494 struct shutdown_state *state = (struct shutdown_state *)private_data;
495 struct server_id self_pid = messaging_server_id(state->msg_ctx);
496 struct server_id pid = session->channels[0].server_id;
497 const char *addr = session->channels[0].remote_address;
499 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
500 server_id_str(talloc_tos(), &pid), addr));
502 if (!process_exists(pid)) {
503 DEBUG(10, ("process does not exist\n"));
504 return 0;
507 if (serverid_equal(&pid, &self_pid)) {
508 DEBUG(10, ("It's me\n"));
509 return 0;
513 * here we use strstr() because 'addr'
514 * (session->channels[0].remote_address)
515 * contains a string like:
516 * 'ipv4:127.0.0.1:48163'
518 if (strstr(addr, state->ip) == NULL) {
519 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
520 return 0;
523 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
524 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
525 state->ip));
527 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
528 &data_blob_null);
529 return 0;
532 static void setup_new_vc_session(struct smbd_server_connection *sconn)
534 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
535 "compatible we would close all old resources.\n"));
536 #if 0
537 conn_close_all();
538 invalidate_all_vuids();
539 #endif
540 if (lp_reset_on_zero_vc()) {
541 char *addr;
542 struct shutdown_state state;
544 addr = tsocket_address_inet_addr_string(
545 sconn->remote_address, talloc_tos());
546 if (addr == NULL) {
547 return;
549 state.ip = addr;
550 state.msg_ctx = sconn->msg_ctx;
551 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
552 TALLOC_FREE(addr);
556 /****************************************************************************
557 Reply to a session setup command.
558 ****************************************************************************/
560 void reply_sesssetup_and_X(struct smb_request *req)
562 uint64_t sess_vuid;
563 int smb_bufsize;
564 DATA_BLOB lm_resp;
565 DATA_BLOB nt_resp;
566 DATA_BLOB plaintext_password;
567 char *tmp;
568 const char *user;
569 fstring sub_user; /* Sanitised username for substituion */
570 const char *domain;
571 const char *native_os;
572 const char *native_lanman;
573 const char *primary_domain;
574 struct auth_usersupplied_info *user_info = NULL;
575 struct auth_session_info *session_info = NULL;
576 uint16 smb_flag2 = req->flags2;
577 uint16_t action = 0;
578 NTTIME now = timeval_to_nttime(&req->request_time);
579 struct smbXsrv_session *session = NULL;
581 NTSTATUS nt_status;
582 struct smbd_server_connection *sconn = req->sconn;
584 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
585 bool signing_allowed = false;
586 bool signing_mandatory = false;
588 START_PROFILE(SMBsesssetupX);
590 ZERO_STRUCT(lm_resp);
591 ZERO_STRUCT(nt_resp);
592 ZERO_STRUCT(plaintext_password);
594 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
596 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
597 signing_allowed = true;
599 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
600 signing_mandatory = true;
604 * We can call srv_set_signing_negotiated() each time.
605 * It finds out when it needs to turn into a noop
606 * itself.
608 srv_set_signing_negotiated(req->sconn,
609 signing_allowed,
610 signing_mandatory);
612 /* a SPNEGO session setup has 12 command words, whereas a normal
613 NT1 session setup has 13. See the cifs spec. */
614 if (req->wct == 12 &&
615 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
617 if (!sconn->smb1.negprot.spnego) {
618 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
619 "at SPNEGO session setup when it was not "
620 "negotiated.\n"));
621 reply_nterror(req, nt_status_squash(
622 NT_STATUS_LOGON_FAILURE));
623 END_PROFILE(SMBsesssetupX);
624 return;
627 if (SVAL(req->vwv+4, 0) == 0) {
628 setup_new_vc_session(req->sconn);
631 reply_sesssetup_and_X_spnego(req);
632 END_PROFILE(SMBsesssetupX);
633 return;
636 smb_bufsize = SVAL(req->vwv+2, 0);
638 if (get_Protocol() < PROTOCOL_NT1) {
639 uint16 passlen1 = SVAL(req->vwv+7, 0);
641 /* Never do NT status codes with protocols before NT1 as we
642 * don't get client caps. */
643 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
645 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
646 reply_nterror(req, nt_status_squash(
647 NT_STATUS_INVALID_PARAMETER));
648 END_PROFILE(SMBsesssetupX);
649 return;
652 if (doencrypt) {
653 lm_resp = data_blob(req->buf, passlen1);
654 } else {
655 plaintext_password = data_blob(req->buf, passlen1+1);
656 /* Ensure null termination */
657 plaintext_password.data[passlen1] = 0;
660 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
661 req->buf + passlen1, STR_TERMINATE);
662 user = tmp ? tmp : "";
664 domain = "";
666 } else {
667 uint16 passlen1 = SVAL(req->vwv+7, 0);
668 uint16 passlen2 = SVAL(req->vwv+8, 0);
669 enum remote_arch_types ra_type = get_remote_arch();
670 const uint8_t *p = req->buf;
671 const uint8_t *save_p = req->buf;
672 uint16 byte_count;
675 if(global_client_caps == 0) {
676 global_client_caps = IVAL(req->vwv+11, 0);
678 if (!(global_client_caps & CAP_STATUS32)) {
679 remove_from_common_flags2(
680 FLAGS2_32_BIT_ERROR_CODES);
683 /* client_caps is used as final determination if
684 * client is NT or Win95. This is needed to return
685 * the correct error codes in some circumstances.
688 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
689 ra_type == RA_WIN95) {
690 if(!(global_client_caps & (CAP_NT_SMBS|
691 CAP_STATUS32))) {
692 set_remote_arch( RA_WIN95);
697 if (!doencrypt) {
698 /* both Win95 and WinNT stuff up the password
699 * lengths for non-encrypting systems. Uggh.
701 if passlen1==24 its a win95 system, and its setting
702 the password length incorrectly. Luckily it still
703 works with the default code because Win95 will null
704 terminate the password anyway
706 if passlen1>0 and passlen2>0 then maybe its a NT box
707 and its setting passlen2 to some random value which
708 really stuffs things up. we need to fix that one. */
710 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
711 passlen2 != 1) {
712 passlen2 = 0;
716 /* check for nasty tricks */
717 if (passlen1 > MAX_PASS_LEN
718 || passlen1 > smbreq_bufrem(req, p)) {
719 reply_nterror(req, nt_status_squash(
720 NT_STATUS_INVALID_PARAMETER));
721 END_PROFILE(SMBsesssetupX);
722 return;
725 if (passlen2 > MAX_PASS_LEN
726 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
727 reply_nterror(req, nt_status_squash(
728 NT_STATUS_INVALID_PARAMETER));
729 END_PROFILE(SMBsesssetupX);
730 return;
733 /* Save the lanman2 password and the NT md4 password. */
735 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
736 doencrypt = False;
739 if (doencrypt) {
740 lm_resp = data_blob(p, passlen1);
741 nt_resp = data_blob(p+passlen1, passlen2);
742 } else {
743 char *pass = NULL;
744 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
746 if (unic && (passlen2 == 0) && passlen1) {
747 /* Only a ascii plaintext password was sent. */
748 (void)srvstr_pull_talloc(talloc_tos(),
749 req->inbuf,
750 req->flags2,
751 &pass,
752 req->buf,
753 passlen1,
754 STR_TERMINATE|STR_ASCII);
755 } else {
756 (void)srvstr_pull_talloc(talloc_tos(),
757 req->inbuf,
758 req->flags2,
759 &pass,
760 req->buf,
761 unic ? passlen2 : passlen1,
762 STR_TERMINATE);
764 if (!pass) {
765 reply_nterror(req, nt_status_squash(
766 NT_STATUS_INVALID_PARAMETER));
767 END_PROFILE(SMBsesssetupX);
768 return;
770 plaintext_password = data_blob(pass, strlen(pass)+1);
773 p += passlen1 + passlen2;
775 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
776 STR_TERMINATE);
777 user = tmp ? tmp : "";
779 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
780 STR_TERMINATE);
781 domain = tmp ? tmp : "";
783 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
784 STR_TERMINATE);
785 native_os = tmp ? tmp : "";
787 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
788 STR_TERMINATE);
789 native_lanman = tmp ? tmp : "";
791 /* not documented or decoded by Ethereal but there is one more
792 * string in the extra bytes which is the same as the
793 * PrimaryDomain when using extended security. Windows NT 4
794 * and 2003 use this string to store the native lanman string.
795 * Windows 9x does not include a string here at all so we have
796 * to check if we have any extra bytes left */
798 byte_count = SVAL(req->vwv+13, 0);
799 if ( PTR_DIFF(p, save_p) < byte_count) {
800 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
801 STR_TERMINATE);
802 primary_domain = tmp ? tmp : "";
803 } else {
804 primary_domain = talloc_strdup(talloc_tos(), "null");
807 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
808 "PrimaryDomain=[%s]\n",
809 domain, native_os, native_lanman, primary_domain));
811 if ( ra_type == RA_WIN2K ) {
812 if ( strlen(native_lanman) == 0 )
813 ra_lanman_string( primary_domain );
814 else
815 ra_lanman_string( native_lanman );
820 if (SVAL(req->vwv+4, 0) == 0) {
821 setup_new_vc_session(req->sconn);
824 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
825 domain, user, get_remote_machine_name()));
827 if (*user) {
828 if (sconn->smb1.negprot.spnego) {
830 /* This has to be here, because this is a perfectly
831 * valid behaviour for guest logons :-( */
833 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
834 "at 'normal' session setup after "
835 "negotiating spnego.\n"));
836 reply_nterror(req, nt_status_squash(
837 NT_STATUS_LOGON_FAILURE));
838 END_PROFILE(SMBsesssetupX);
839 return;
841 fstrcpy(sub_user, user);
842 } else {
843 fstrcpy(sub_user, "");
846 sub_set_smb_name(sub_user);
848 reload_services(sconn, conn_snum_used, true);
850 if (!*user) {
852 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
854 } else if (doencrypt) {
855 struct auth4_context *negprot_auth_context = NULL;
856 negprot_auth_context = sconn->smb1.negprot.auth_context;
857 if (!negprot_auth_context) {
858 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
859 "session setup without negprot denied!\n"));
860 reply_nterror(req, nt_status_squash(
861 NT_STATUS_LOGON_FAILURE));
862 END_PROFILE(SMBsesssetupX);
863 return;
865 nt_status = make_user_info_for_reply_enc(&user_info, user,
866 domain,
867 sconn->remote_address,
868 lm_resp, nt_resp);
869 if (NT_STATUS_IS_OK(nt_status)) {
870 nt_status = auth_check_password_session_info(negprot_auth_context,
871 req, user_info, &session_info);
873 } else {
874 struct auth4_context *plaintext_auth_context = NULL;
876 nt_status = make_auth4_context(
877 talloc_tos(), &plaintext_auth_context);
879 if (NT_STATUS_IS_OK(nt_status)) {
880 uint8_t chal[8];
882 plaintext_auth_context->get_ntlm_challenge(
883 plaintext_auth_context, chal);
885 if (!make_user_info_for_reply(&user_info,
886 user, domain,
887 sconn->remote_address,
888 chal,
889 plaintext_password)) {
890 nt_status = NT_STATUS_NO_MEMORY;
893 if (NT_STATUS_IS_OK(nt_status)) {
894 nt_status = auth_check_password_session_info(plaintext_auth_context,
895 req, user_info, &session_info);
897 TALLOC_FREE(plaintext_auth_context);
901 free_user_info(&user_info);
903 if (!NT_STATUS_IS_OK(nt_status)) {
904 data_blob_free(&nt_resp);
905 data_blob_free(&lm_resp);
906 data_blob_clear_free(&plaintext_password);
907 reply_nterror(req, nt_status_squash(nt_status));
908 END_PROFILE(SMBsesssetupX);
909 return;
912 data_blob_clear_free(&plaintext_password);
914 /* it's ok - setup a reply */
915 reply_outbuf(req, 3, 0);
916 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
917 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
919 if (get_Protocol() >= PROTOCOL_NT1) {
920 push_signature(&req->outbuf);
921 /* perhaps grab OS version here?? */
924 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
925 action = 1;
928 /* register the name and uid as being validated, so further connections
929 to a uid can get through without a password, on the same VC */
931 nt_status = smbXsrv_session_create(sconn->conn,
932 now, &session);
933 if (!NT_STATUS_IS_OK(nt_status)) {
934 data_blob_free(&nt_resp);
935 data_blob_free(&lm_resp);
936 reply_nterror(req, nt_status_squash(nt_status));
937 END_PROFILE(SMBsesssetupX);
938 return;
941 if (session_info->session_key.length > 0) {
942 uint8_t session_key[16];
945 * Note: the SMB1 signing key is not truncated to 16 byte!
947 session->global->signing_key =
948 data_blob_dup_talloc(session->global,
949 session_info->session_key);
950 if (session->global->signing_key.data == NULL) {
951 data_blob_free(&nt_resp);
952 data_blob_free(&lm_resp);
953 TALLOC_FREE(session);
954 reply_nterror(req, NT_STATUS_NO_MEMORY);
955 END_PROFILE(SMBsesssetupX);
956 return;
960 * The application key is truncated/padded to 16 bytes
962 ZERO_STRUCT(session_key);
963 memcpy(session_key, session->global->signing_key.data,
964 MIN(session->global->signing_key.length,
965 sizeof(session_key)));
966 session->global->application_key =
967 data_blob_talloc(session->global,
968 session_key,
969 sizeof(session_key));
970 ZERO_STRUCT(session_key);
971 if (session->global->application_key.data == NULL) {
972 data_blob_free(&nt_resp);
973 data_blob_free(&lm_resp);
974 TALLOC_FREE(session);
975 reply_nterror(req, NT_STATUS_NO_MEMORY);
976 END_PROFILE(SMBsesssetupX);
977 return;
981 * Place the application key into the session_info
983 data_blob_clear_free(&session_info->session_key);
984 session_info->session_key = data_blob_dup_talloc(session_info,
985 session->global->application_key);
986 if (session_info->session_key.data == NULL) {
987 data_blob_free(&nt_resp);
988 data_blob_free(&lm_resp);
989 TALLOC_FREE(session);
990 reply_nterror(req, NT_STATUS_NO_MEMORY);
991 END_PROFILE(SMBsesssetupX);
992 return;
996 session->compat = talloc_zero(session, struct user_struct);
997 if (session->compat == NULL) {
998 data_blob_free(&nt_resp);
999 data_blob_free(&lm_resp);
1000 TALLOC_FREE(session);
1001 reply_nterror(req, NT_STATUS_NO_MEMORY);
1002 END_PROFILE(SMBsesssetupX);
1003 return;
1005 session->compat->session = session;
1006 session->compat->homes_snum = -1;
1007 session->compat->session_info = session_info;
1008 session->compat->session_keystr = NULL;
1009 session->compat->vuid = session->global->session_wire_id;
1010 DLIST_ADD(sconn->users, session->compat);
1011 sconn->num_users++;
1013 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1014 session->compat->homes_snum =
1015 register_homes_share(session_info->unix_info->unix_name);
1018 if (srv_is_signing_negotiated(sconn) &&
1019 action == 0 &&
1020 session->global->signing_key.length > 0)
1023 * Try and turn on server signing on the first non-guest
1024 * sessionsetup.
1026 srv_set_signing(sconn,
1027 session->global->signing_key,
1028 nt_resp.data ? nt_resp : lm_resp);
1031 set_current_user_info(session_info->unix_info->sanitized_username,
1032 session_info->unix_info->unix_name,
1033 session_info->info->domain_name);
1035 session->status = NT_STATUS_OK;
1036 session->global->auth_session_info = talloc_move(session->global,
1037 &session_info);
1038 session->global->auth_session_info_seqnum += 1;
1039 session->global->channels[0].auth_session_info_seqnum =
1040 session->global->auth_session_info_seqnum;
1041 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1043 nt_status = smbXsrv_session_update(session);
1044 if (!NT_STATUS_IS_OK(nt_status)) {
1045 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1046 (unsigned long long)session->compat->vuid,
1047 nt_errstr(nt_status)));
1048 data_blob_free(&nt_resp);
1049 data_blob_free(&lm_resp);
1050 TALLOC_FREE(session);
1051 reply_nterror(req, nt_status_squash(nt_status));
1052 END_PROFILE(SMBsesssetupX);
1053 return;
1056 if (!session_claim(session)) {
1057 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1058 (unsigned long long)session->compat->vuid));
1059 data_blob_free(&nt_resp);
1060 data_blob_free(&lm_resp);
1061 TALLOC_FREE(session);
1062 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1063 END_PROFILE(SMBsesssetupX);
1064 return;
1067 /* current_user_info is changed on new vuid */
1068 reload_services(sconn, conn_snum_used, true);
1070 sess_vuid = session->global->session_wire_id;
1072 data_blob_free(&nt_resp);
1073 data_blob_free(&lm_resp);
1075 SSVAL(req->outbuf,smb_vwv2,action);
1076 SSVAL(req->outbuf,smb_uid,sess_vuid);
1077 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1078 req->vuid = sess_vuid;
1080 if (!sconn->smb1.sessions.done_sesssetup) {
1081 sconn->smb1.sessions.max_send =
1082 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1084 sconn->smb1.sessions.done_sesssetup = true;
1086 END_PROFILE(SMBsesssetupX);