param: Rename variable used for lp_netbios_scope szNetbiosScope
[Samba.git] / source3 / smbd / sesssetup.c
blob02cb4458f617ec43fc5d479de07c9f6133c66ee0
1 /*
2 Unix SMB/CIFS implementation.
3 handle SMBsessionsetup
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7 Copyright (C) Luke Howard 2003
8 Copyright (C) Volker Lendecke 2007
9 Copyright (C) Jeremy Allison 2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/spnego.h"
30 #include "../auth/ntlmssp/ntlmssp.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "libads/kerberos_proto.h"
33 #include "../lib/util/asn1.h"
34 #include "auth.h"
35 #include "messages.h"
36 #include "smbprofile.h"
37 #include "../libcli/security/security.h"
38 #include "auth/gensec/gensec.h"
39 #include "lib/conn_tdb.h"
41 /****************************************************************************
42 Add the standard 'Samba' signature to the end of the session setup.
43 ****************************************************************************/
45 static int push_signature(uint8 **outbuf)
47 char *lanman;
48 int result, tmp;
49 fstring native_os;
51 result = 0;
53 fstr_sprintf(native_os, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION,
54 SAMBA_MINOR_NBT_ANNOUNCE_VERSION);
56 tmp = message_push_string(outbuf, native_os, STR_TERMINATE);
58 if (tmp == -1) return -1;
59 result += tmp;
61 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
62 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
63 SAFE_FREE(lanman);
65 else {
66 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
69 if (tmp == -1) return -1;
70 result += tmp;
72 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
74 if (tmp == -1) return -1;
75 result += tmp;
77 return result;
80 /****************************************************************************
81 Do a 'guest' logon, getting back the
82 ****************************************************************************/
84 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
85 TALLOC_CTX *mem_ctx,
86 struct auth_session_info **session_info)
88 struct auth4_context *auth_context;
89 struct auth_usersupplied_info *user_info = NULL;
90 uint8_t chal[8];
91 NTSTATUS nt_status;
93 DEBUG(3,("Got anonymous request\n"));
95 nt_status = make_auth4_context(talloc_tos(), &auth_context);
96 if (!NT_STATUS_IS_OK(nt_status)) {
97 return nt_status;
100 auth_context->get_ntlm_challenge(auth_context,
101 chal);
103 if (!make_user_info_guest(remote_address, &user_info)) {
104 TALLOC_FREE(auth_context);
105 return NT_STATUS_NO_MEMORY;
108 nt_status = auth_check_password_session_info(auth_context,
109 mem_ctx, user_info, session_info);
110 free_user_info(&user_info);
111 TALLOC_FREE(auth_context);
112 return nt_status;
115 /****************************************************************************
116 Reply to a session setup command.
117 conn POINTER CAN BE NULL HERE !
118 ****************************************************************************/
120 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
122 const uint8 *p;
123 DATA_BLOB in_blob;
124 DATA_BLOB out_blob = data_blob_null;
125 size_t bufrem;
126 char *tmp;
127 const char *native_os;
128 const char *native_lanman;
129 const char *primary_domain;
130 const char *p2;
131 uint16 data_blob_len = SVAL(req->vwv+7, 0);
132 enum remote_arch_types ra_type = get_remote_arch();
133 uint64_t vuid = req->vuid;
134 NTSTATUS status = NT_STATUS_OK;
135 struct smbd_server_connection *sconn = req->sconn;
136 uint16_t action = 0;
137 NTTIME now = timeval_to_nttime(&req->request_time);
138 struct smbXsrv_session *session = NULL;
139 uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
140 uint32_t client_caps = IVAL(req->vwv+10, 0);
142 DEBUG(3,("Doing spnego session setup\n"));
144 if (!sconn->smb1.sessions.done_sesssetup) {
145 global_client_caps = client_caps;
147 if (!(global_client_caps & CAP_STATUS32)) {
148 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
152 p = req->buf;
154 if (data_blob_len == 0) {
155 /* an invalid request */
156 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
157 return;
160 bufrem = smbreq_bufrem(req, p);
161 /* pull the spnego blob */
162 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
164 #if 0
165 file_save("negotiate.dat", in_blob.data, in_blob.length);
166 #endif
168 p2 = (const char *)req->buf + in_blob.length;
170 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
171 STR_TERMINATE);
172 native_os = tmp ? tmp : "";
174 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
175 STR_TERMINATE);
176 native_lanman = tmp ? tmp : "";
178 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
179 STR_TERMINATE);
180 primary_domain = tmp ? tmp : "";
182 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
183 native_os, native_lanman, primary_domain));
185 if ( ra_type == RA_WIN2K ) {
186 /* Vista sets neither the OS or lanman strings */
188 if ( !strlen(native_os) && !strlen(native_lanman) )
189 set_remote_arch(RA_VISTA);
191 /* Windows 2003 doesn't set the native lanman string,
192 but does set primary domain which is a bug I think */
194 if ( !strlen(native_lanman) ) {
195 ra_lanman_string( primary_domain );
196 } else {
197 ra_lanman_string( native_lanman );
199 } else if ( ra_type == RA_VISTA ) {
200 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
201 set_remote_arch(RA_OSX);
205 if (vuid != 0) {
206 status = smb1srv_session_lookup(sconn->conn,
207 vuid, now,
208 &session);
209 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
210 reply_force_doserror(req, ERRSRV, ERRbaduid);
211 return;
213 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
214 status = NT_STATUS_OK;
216 if (NT_STATUS_IS_OK(status)) {
217 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
218 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
219 TALLOC_FREE(session->gensec);
221 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
222 reply_nterror(req, nt_status_squash(status));
223 return;
227 if (session == NULL) {
228 /* create a new session */
229 status = smbXsrv_session_create(sconn->conn,
230 now, &session);
231 if (!NT_STATUS_IS_OK(status)) {
232 reply_nterror(req, nt_status_squash(status));
233 return;
237 if (!session->gensec) {
238 status = auth_generic_prepare(session, sconn->remote_address,
239 &session->gensec);
240 if (!NT_STATUS_IS_OK(status)) {
241 TALLOC_FREE(session);
242 reply_nterror(req, nt_status_squash(status));
243 return;
246 gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY);
247 gensec_want_feature(session->gensec, GENSEC_FEATURE_UNIX_TOKEN);
249 status = gensec_start_mech_by_oid(session->gensec,
250 GENSEC_OID_SPNEGO);
251 if (!NT_STATUS_IS_OK(status)) {
252 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
253 TALLOC_FREE(session);;
254 reply_nterror(req, nt_status_squash(status));
255 return;
259 become_root();
260 status = gensec_update(session->gensec,
261 talloc_tos(), NULL,
262 in_blob, &out_blob);
263 unbecome_root();
264 if (!NT_STATUS_IS_OK(status) &&
265 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
266 TALLOC_FREE(session);
267 reply_nterror(req, nt_status_squash(status));
268 return;
271 if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
272 struct auth_session_info *session_info = NULL;
274 status = gensec_session_info(session->gensec,
275 session,
276 &session_info);
277 if (!NT_STATUS_IS_OK(status)) {
278 DEBUG(1,("Failed to generate session_info "
279 "(user and group token) for session setup: %s\n",
280 nt_errstr(status)));
281 data_blob_free(&out_blob);
282 TALLOC_FREE(session);
283 reply_nterror(req, nt_status_squash(status));
284 return;
287 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
288 action = 1;
291 if (session_info->session_key.length > 0) {
292 struct smbXsrv_session *x = session;
295 * Note: the SMB1 signing key is not truncated to 16 byte!
297 x->global->signing_key =
298 data_blob_dup_talloc(x->global,
299 session_info->session_key);
300 if (x->global->signing_key.data == NULL) {
301 data_blob_free(&out_blob);
302 TALLOC_FREE(session);
303 reply_nterror(req, NT_STATUS_NO_MEMORY);
304 return;
308 * clear the session key
309 * the first tcon will add setup the application key
311 data_blob_clear_free(&session_info->session_key);
314 session->compat = talloc_zero(session, struct user_struct);
315 if (session->compat == NULL) {
316 data_blob_free(&out_blob);
317 TALLOC_FREE(session);
318 reply_nterror(req, NT_STATUS_NO_MEMORY);
319 return;
321 session->compat->session = session;
322 session->compat->homes_snum = -1;
323 session->compat->session_info = session_info;
324 session->compat->session_keystr = NULL;
325 session->compat->vuid = session->global->session_wire_id;
326 DLIST_ADD(sconn->users, session->compat);
327 sconn->num_users++;
329 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
330 session->compat->homes_snum =
331 register_homes_share(session_info->unix_info->unix_name);
334 if (srv_is_signing_negotiated(sconn) &&
335 action == 0 &&
336 session->global->signing_key.length > 0)
339 * Try and turn on server signing on the first non-guest
340 * sessionsetup.
342 srv_set_signing(sconn,
343 session->global->signing_key,
344 data_blob_null);
347 set_current_user_info(session_info->unix_info->sanitized_username,
348 session_info->unix_info->unix_name,
349 session_info->info->domain_name);
351 session->status = NT_STATUS_OK;
352 session->global->auth_session_info = talloc_move(session->global,
353 &session_info);
354 session->global->auth_session_info_seqnum += 1;
355 session->global->channels[0].auth_session_info_seqnum =
356 session->global->auth_session_info_seqnum;
357 if (client_caps & CAP_DYNAMIC_REAUTH) {
358 session->global->expiration_time =
359 gensec_expire_time(session->gensec);
360 } else {
361 session->global->expiration_time =
362 GENSEC_EXPIRE_TIME_INFINITY;
365 if (!session_claim(session)) {
366 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
367 (unsigned long long)session->compat->vuid));
368 data_blob_free(&out_blob);
369 TALLOC_FREE(session);
370 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
371 return;
374 status = smbXsrv_session_update(session);
375 if (!NT_STATUS_IS_OK(status)) {
376 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
377 (unsigned long long)session->compat->vuid,
378 nt_errstr(status)));
379 data_blob_free(&out_blob);
380 TALLOC_FREE(session);
381 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
382 return;
385 if (!sconn->smb1.sessions.done_sesssetup) {
386 sconn->smb1.sessions.max_send =
387 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
389 sconn->smb1.sessions.done_sesssetup = true;
391 /* current_user_info is changed on new vuid */
392 reload_services(sconn, conn_snum_used, true);
393 } else if (NT_STATUS_IS_OK(status)) {
394 struct auth_session_info *session_info = NULL;
396 status = gensec_session_info(session->gensec,
397 session,
398 &session_info);
399 if (!NT_STATUS_IS_OK(status)) {
400 DEBUG(1,("Failed to generate session_info "
401 "(user and group token) for session setup: %s\n",
402 nt_errstr(status)));
403 data_blob_free(&out_blob);
404 TALLOC_FREE(session);
405 reply_nterror(req, nt_status_squash(status));
406 return;
409 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
410 action = 1;
414 * Keep the application key
416 data_blob_clear_free(&session_info->session_key);
417 session_info->session_key =
418 session->global->auth_session_info->session_key;
419 talloc_steal(session_info, session_info->session_key.data);
420 TALLOC_FREE(session->global->auth_session_info);
422 session->compat->session_info = session_info;
424 session->compat->vuid = session->global->session_wire_id;
426 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
427 session->compat->homes_snum =
428 register_homes_share(session_info->unix_info->unix_name);
431 set_current_user_info(session_info->unix_info->sanitized_username,
432 session_info->unix_info->unix_name,
433 session_info->info->domain_name);
435 session->status = NT_STATUS_OK;
436 session->global->auth_session_info = talloc_move(session->global,
437 &session_info);
438 session->global->auth_session_info_seqnum += 1;
439 session->global->channels[0].auth_session_info_seqnum =
440 session->global->auth_session_info_seqnum;
441 if (client_caps & CAP_DYNAMIC_REAUTH) {
442 session->global->expiration_time =
443 gensec_expire_time(session->gensec);
444 } else {
445 session->global->expiration_time =
446 GENSEC_EXPIRE_TIME_INFINITY;
449 status = smbXsrv_session_update(session);
450 if (!NT_STATUS_IS_OK(status)) {
451 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
452 (unsigned long long)session->compat->vuid,
453 nt_errstr(status)));
454 data_blob_free(&out_blob);
455 TALLOC_FREE(session);
456 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
457 return;
460 conn_clear_vuid_caches(sconn, session->compat->vuid);
462 /* current_user_info is changed on new vuid */
463 reload_services(sconn, conn_snum_used, true);
466 vuid = session->global->session_wire_id;
468 reply_outbuf(req, 4, 0);
470 SSVAL(req->outbuf, smb_uid, vuid);
471 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
472 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
473 SSVAL(req->outbuf, smb_vwv2, action);
474 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
476 if (message_push_blob(&req->outbuf, out_blob) == -1) {
477 data_blob_free(&out_blob);
478 TALLOC_FREE(session);
479 reply_nterror(req, NT_STATUS_NO_MEMORY);
480 return;
482 data_blob_free(&out_blob);
484 if (push_signature(&req->outbuf) == -1) {
485 TALLOC_FREE(session);
486 reply_nterror(req, NT_STATUS_NO_MEMORY);
487 return;
491 /****************************************************************************
492 On new VC == 0, shutdown *all* old connections and users.
493 It seems that only NT4.x does this. At W2K and above (XP etc.).
494 a new session setup with VC==0 is ignored.
495 ****************************************************************************/
497 struct shutdown_state {
498 const char *ip;
499 struct messaging_context *msg_ctx;
502 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
503 void *private_data)
505 struct shutdown_state *state = (struct shutdown_state *)private_data;
506 struct server_id self_pid = messaging_server_id(state->msg_ctx);
507 struct server_id pid = session->channels[0].server_id;
508 const char *addr = session->channels[0].remote_address;
510 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
511 server_id_str(talloc_tos(), &pid), addr));
513 if (!process_exists(pid)) {
514 DEBUG(10, ("process does not exist\n"));
515 return 0;
518 if (serverid_equal(&pid, &self_pid)) {
519 DEBUG(10, ("It's me\n"));
520 return 0;
524 * here we use strstr() because 'addr'
525 * (session->channels[0].remote_address)
526 * contains a string like:
527 * 'ipv4:127.0.0.1:48163'
529 if (strstr(addr, state->ip) == NULL) {
530 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
531 return 0;
534 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
535 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
536 state->ip));
538 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
539 &data_blob_null);
540 return 0;
543 static void setup_new_vc_session(struct smbd_server_connection *sconn)
545 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
546 "compatible we would close all old resources.\n"));
547 #if 0
548 conn_close_all();
549 invalidate_all_vuids();
550 #endif
551 if (lp_reset_on_zero_vc()) {
552 char *addr;
553 struct shutdown_state state;
555 addr = tsocket_address_inet_addr_string(
556 sconn->remote_address, talloc_tos());
557 if (addr == NULL) {
558 return;
560 state.ip = addr;
561 state.msg_ctx = sconn->msg_ctx;
562 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
563 TALLOC_FREE(addr);
567 /****************************************************************************
568 Reply to a session setup command.
569 ****************************************************************************/
571 void reply_sesssetup_and_X(struct smb_request *req)
573 uint64_t sess_vuid;
574 uint16_t smb_bufsize;
575 DATA_BLOB lm_resp;
576 DATA_BLOB nt_resp;
577 DATA_BLOB plaintext_password;
578 char *tmp;
579 const char *user;
580 fstring sub_user; /* Sanitised username for substituion */
581 const char *domain;
582 const char *native_os;
583 const char *native_lanman;
584 const char *primary_domain;
585 struct auth_usersupplied_info *user_info = NULL;
586 struct auth_session_info *session_info = NULL;
587 uint16 smb_flag2 = req->flags2;
588 uint16_t action = 0;
589 NTTIME now = timeval_to_nttime(&req->request_time);
590 struct smbXsrv_session *session = NULL;
592 NTSTATUS nt_status;
593 struct smbd_server_connection *sconn = req->sconn;
595 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
596 bool signing_allowed = false;
597 bool signing_mandatory = false;
599 START_PROFILE(SMBsesssetupX);
601 ZERO_STRUCT(lm_resp);
602 ZERO_STRUCT(nt_resp);
603 ZERO_STRUCT(plaintext_password);
605 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
607 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
608 signing_allowed = true;
610 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
611 signing_mandatory = true;
615 * We can call srv_set_signing_negotiated() each time.
616 * It finds out when it needs to turn into a noop
617 * itself.
619 srv_set_signing_negotiated(req->sconn,
620 signing_allowed,
621 signing_mandatory);
623 /* a SPNEGO session setup has 12 command words, whereas a normal
624 NT1 session setup has 13. See the cifs spec. */
625 if (req->wct == 12 &&
626 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
628 if (!sconn->smb1.negprot.spnego) {
629 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
630 "at SPNEGO session setup when it was not "
631 "negotiated.\n"));
632 reply_nterror(req, nt_status_squash(
633 NT_STATUS_LOGON_FAILURE));
634 END_PROFILE(SMBsesssetupX);
635 return;
638 if (SVAL(req->vwv+4, 0) == 0) {
639 setup_new_vc_session(req->sconn);
642 reply_sesssetup_and_X_spnego(req);
643 END_PROFILE(SMBsesssetupX);
644 return;
647 smb_bufsize = SVAL(req->vwv+2, 0);
649 if (get_Protocol() < PROTOCOL_NT1) {
650 uint16 passlen1 = SVAL(req->vwv+7, 0);
652 /* Never do NT status codes with protocols before NT1 as we
653 * don't get client caps. */
654 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
656 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
657 reply_nterror(req, nt_status_squash(
658 NT_STATUS_INVALID_PARAMETER));
659 END_PROFILE(SMBsesssetupX);
660 return;
663 if (doencrypt) {
664 lm_resp = data_blob(req->buf, passlen1);
665 } else {
666 plaintext_password = data_blob(req->buf, passlen1+1);
667 /* Ensure null termination */
668 plaintext_password.data[passlen1] = 0;
671 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
672 req->buf + passlen1, STR_TERMINATE);
673 user = tmp ? tmp : "";
675 domain = "";
677 } else {
678 uint16 passlen1 = SVAL(req->vwv+7, 0);
679 uint16 passlen2 = SVAL(req->vwv+8, 0);
680 enum remote_arch_types ra_type = get_remote_arch();
681 const uint8_t *p = req->buf;
682 const uint8_t *save_p = req->buf;
683 uint16 byte_count;
685 if (!sconn->smb1.sessions.done_sesssetup) {
686 global_client_caps = IVAL(req->vwv+11, 0);
688 if (!(global_client_caps & CAP_STATUS32)) {
689 remove_from_common_flags2(
690 FLAGS2_32_BIT_ERROR_CODES);
693 /* client_caps is used as final determination if
694 * client is NT or Win95. This is needed to return
695 * the correct error codes in some circumstances.
698 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
699 ra_type == RA_WIN95) {
700 if(!(global_client_caps & (CAP_NT_SMBS|
701 CAP_STATUS32))) {
702 set_remote_arch( RA_WIN95);
707 if (!doencrypt) {
708 /* both Win95 and WinNT stuff up the password
709 * lengths for non-encrypting systems. Uggh.
711 if passlen1==24 its a win95 system, and its setting
712 the password length incorrectly. Luckily it still
713 works with the default code because Win95 will null
714 terminate the password anyway
716 if passlen1>0 and passlen2>0 then maybe its a NT box
717 and its setting passlen2 to some random value which
718 really stuffs things up. we need to fix that one. */
720 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
721 passlen2 != 1) {
722 passlen2 = 0;
726 /* check for nasty tricks */
727 if (passlen1 > MAX_PASS_LEN
728 || passlen1 > smbreq_bufrem(req, p)) {
729 reply_nterror(req, nt_status_squash(
730 NT_STATUS_INVALID_PARAMETER));
731 END_PROFILE(SMBsesssetupX);
732 return;
735 if (passlen2 > MAX_PASS_LEN
736 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
737 reply_nterror(req, nt_status_squash(
738 NT_STATUS_INVALID_PARAMETER));
739 END_PROFILE(SMBsesssetupX);
740 return;
743 /* Save the lanman2 password and the NT md4 password. */
745 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
746 doencrypt = False;
749 if (doencrypt) {
750 lm_resp = data_blob(p, passlen1);
751 nt_resp = data_blob(p+passlen1, passlen2);
752 } else {
753 char *pass = NULL;
754 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
756 if (unic && (passlen2 == 0) && passlen1) {
757 /* Only a ascii plaintext password was sent. */
758 (void)srvstr_pull_talloc(talloc_tos(),
759 req->inbuf,
760 req->flags2,
761 &pass,
762 req->buf,
763 passlen1,
764 STR_TERMINATE|STR_ASCII);
765 } else {
766 (void)srvstr_pull_talloc(talloc_tos(),
767 req->inbuf,
768 req->flags2,
769 &pass,
770 req->buf,
771 unic ? passlen2 : passlen1,
772 STR_TERMINATE);
774 if (!pass) {
775 reply_nterror(req, nt_status_squash(
776 NT_STATUS_INVALID_PARAMETER));
777 END_PROFILE(SMBsesssetupX);
778 return;
780 plaintext_password = data_blob(pass, strlen(pass)+1);
783 p += passlen1 + passlen2;
785 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
786 STR_TERMINATE);
787 user = tmp ? tmp : "";
789 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
790 STR_TERMINATE);
791 domain = tmp ? tmp : "";
793 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
794 STR_TERMINATE);
795 native_os = tmp ? tmp : "";
797 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
798 STR_TERMINATE);
799 native_lanman = tmp ? tmp : "";
801 /* not documented or decoded by Ethereal but there is one more
802 * string in the extra bytes which is the same as the
803 * PrimaryDomain when using extended security. Windows NT 4
804 * and 2003 use this string to store the native lanman string.
805 * Windows 9x does not include a string here at all so we have
806 * to check if we have any extra bytes left */
808 byte_count = SVAL(req->vwv+13, 0);
809 if ( PTR_DIFF(p, save_p) < byte_count) {
810 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
811 STR_TERMINATE);
812 primary_domain = tmp ? tmp : "";
813 } else {
814 primary_domain = talloc_strdup(talloc_tos(), "null");
817 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
818 "PrimaryDomain=[%s]\n",
819 domain, native_os, native_lanman, primary_domain));
821 if ( ra_type == RA_WIN2K ) {
822 if ( strlen(native_lanman) == 0 )
823 ra_lanman_string( primary_domain );
824 else
825 ra_lanman_string( native_lanman );
830 if (SVAL(req->vwv+4, 0) == 0) {
831 setup_new_vc_session(req->sconn);
834 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
835 domain, user, get_remote_machine_name()));
837 if (*user) {
838 if (sconn->smb1.negprot.spnego) {
840 /* This has to be here, because this is a perfectly
841 * valid behaviour for guest logons :-( */
843 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
844 "at 'normal' session setup after "
845 "negotiating spnego.\n"));
846 reply_nterror(req, nt_status_squash(
847 NT_STATUS_LOGON_FAILURE));
848 END_PROFILE(SMBsesssetupX);
849 return;
851 fstrcpy(sub_user, user);
852 } else {
853 fstrcpy(sub_user, "");
856 sub_set_smb_name(sub_user);
858 reload_services(sconn, conn_snum_used, true);
860 if (!*user) {
862 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
864 } else if (doencrypt) {
865 struct auth4_context *negprot_auth_context = NULL;
866 negprot_auth_context = sconn->smb1.negprot.auth_context;
867 if (!negprot_auth_context) {
868 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
869 "session setup without negprot denied!\n"));
870 reply_nterror(req, nt_status_squash(
871 NT_STATUS_LOGON_FAILURE));
872 END_PROFILE(SMBsesssetupX);
873 return;
875 nt_status = make_user_info_for_reply_enc(&user_info, user,
876 domain,
877 sconn->remote_address,
878 lm_resp, nt_resp);
879 if (NT_STATUS_IS_OK(nt_status)) {
880 nt_status = auth_check_password_session_info(negprot_auth_context,
881 req, user_info, &session_info);
883 } else {
884 struct auth4_context *plaintext_auth_context = NULL;
886 nt_status = make_auth4_context(
887 talloc_tos(), &plaintext_auth_context);
889 if (NT_STATUS_IS_OK(nt_status)) {
890 uint8_t chal[8];
892 plaintext_auth_context->get_ntlm_challenge(
893 plaintext_auth_context, chal);
895 if (!make_user_info_for_reply(&user_info,
896 user, domain,
897 sconn->remote_address,
898 chal,
899 plaintext_password)) {
900 nt_status = NT_STATUS_NO_MEMORY;
903 if (NT_STATUS_IS_OK(nt_status)) {
904 nt_status = auth_check_password_session_info(plaintext_auth_context,
905 req, user_info, &session_info);
907 TALLOC_FREE(plaintext_auth_context);
911 free_user_info(&user_info);
913 if (!NT_STATUS_IS_OK(nt_status)) {
914 data_blob_free(&nt_resp);
915 data_blob_free(&lm_resp);
916 data_blob_clear_free(&plaintext_password);
917 reply_nterror(req, nt_status_squash(nt_status));
918 END_PROFILE(SMBsesssetupX);
919 return;
922 data_blob_clear_free(&plaintext_password);
924 /* it's ok - setup a reply */
925 reply_outbuf(req, 3, 0);
926 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
927 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
929 if (get_Protocol() >= PROTOCOL_NT1) {
930 push_signature(&req->outbuf);
931 /* perhaps grab OS version here?? */
934 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
935 action = 1;
938 /* register the name and uid as being validated, so further connections
939 to a uid can get through without a password, on the same VC */
941 nt_status = smbXsrv_session_create(sconn->conn,
942 now, &session);
943 if (!NT_STATUS_IS_OK(nt_status)) {
944 data_blob_free(&nt_resp);
945 data_blob_free(&lm_resp);
946 reply_nterror(req, nt_status_squash(nt_status));
947 END_PROFILE(SMBsesssetupX);
948 return;
951 if (session_info->session_key.length > 0) {
952 uint8_t session_key[16];
955 * Note: the SMB1 signing key is not truncated to 16 byte!
957 session->global->signing_key =
958 data_blob_dup_talloc(session->global,
959 session_info->session_key);
960 if (session->global->signing_key.data == NULL) {
961 data_blob_free(&nt_resp);
962 data_blob_free(&lm_resp);
963 TALLOC_FREE(session);
964 reply_nterror(req, NT_STATUS_NO_MEMORY);
965 END_PROFILE(SMBsesssetupX);
966 return;
970 * The application key is truncated/padded to 16 bytes
972 ZERO_STRUCT(session_key);
973 memcpy(session_key, session->global->signing_key.data,
974 MIN(session->global->signing_key.length,
975 sizeof(session_key)));
976 session->global->application_key =
977 data_blob_talloc(session->global,
978 session_key,
979 sizeof(session_key));
980 ZERO_STRUCT(session_key);
981 if (session->global->application_key.data == NULL) {
982 data_blob_free(&nt_resp);
983 data_blob_free(&lm_resp);
984 TALLOC_FREE(session);
985 reply_nterror(req, NT_STATUS_NO_MEMORY);
986 END_PROFILE(SMBsesssetupX);
987 return;
991 * Place the application key into the session_info
993 data_blob_clear_free(&session_info->session_key);
994 session_info->session_key = data_blob_dup_talloc(session_info,
995 session->global->application_key);
996 if (session_info->session_key.data == NULL) {
997 data_blob_free(&nt_resp);
998 data_blob_free(&lm_resp);
999 TALLOC_FREE(session);
1000 reply_nterror(req, NT_STATUS_NO_MEMORY);
1001 END_PROFILE(SMBsesssetupX);
1002 return;
1006 session->compat = talloc_zero(session, struct user_struct);
1007 if (session->compat == NULL) {
1008 data_blob_free(&nt_resp);
1009 data_blob_free(&lm_resp);
1010 TALLOC_FREE(session);
1011 reply_nterror(req, NT_STATUS_NO_MEMORY);
1012 END_PROFILE(SMBsesssetupX);
1013 return;
1015 session->compat->session = session;
1016 session->compat->homes_snum = -1;
1017 session->compat->session_info = session_info;
1018 session->compat->session_keystr = NULL;
1019 session->compat->vuid = session->global->session_wire_id;
1020 DLIST_ADD(sconn->users, session->compat);
1021 sconn->num_users++;
1023 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1024 session->compat->homes_snum =
1025 register_homes_share(session_info->unix_info->unix_name);
1028 if (srv_is_signing_negotiated(sconn) &&
1029 action == 0 &&
1030 session->global->signing_key.length > 0)
1033 * Try and turn on server signing on the first non-guest
1034 * sessionsetup.
1036 srv_set_signing(sconn,
1037 session->global->signing_key,
1038 nt_resp.data ? nt_resp : lm_resp);
1041 set_current_user_info(session_info->unix_info->sanitized_username,
1042 session_info->unix_info->unix_name,
1043 session_info->info->domain_name);
1045 session->status = NT_STATUS_OK;
1046 session->global->auth_session_info = talloc_move(session->global,
1047 &session_info);
1048 session->global->auth_session_info_seqnum += 1;
1049 session->global->channels[0].auth_session_info_seqnum =
1050 session->global->auth_session_info_seqnum;
1051 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1053 nt_status = smbXsrv_session_update(session);
1054 if (!NT_STATUS_IS_OK(nt_status)) {
1055 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1056 (unsigned long long)session->compat->vuid,
1057 nt_errstr(nt_status)));
1058 data_blob_free(&nt_resp);
1059 data_blob_free(&lm_resp);
1060 TALLOC_FREE(session);
1061 reply_nterror(req, nt_status_squash(nt_status));
1062 END_PROFILE(SMBsesssetupX);
1063 return;
1066 if (!session_claim(session)) {
1067 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1068 (unsigned long long)session->compat->vuid));
1069 data_blob_free(&nt_resp);
1070 data_blob_free(&lm_resp);
1071 TALLOC_FREE(session);
1072 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1073 END_PROFILE(SMBsesssetupX);
1074 return;
1077 /* current_user_info is changed on new vuid */
1078 reload_services(sconn, conn_snum_used, true);
1080 sess_vuid = session->global->session_wire_id;
1082 data_blob_free(&nt_resp);
1083 data_blob_free(&lm_resp);
1085 SSVAL(req->outbuf,smb_vwv2,action);
1086 SSVAL(req->outbuf,smb_uid,sess_vuid);
1087 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1088 req->vuid = sess_vuid;
1090 if (!sconn->smb1.sessions.done_sesssetup) {
1091 sconn->smb1.sessions.max_send =
1092 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1094 sconn->smb1.sessions.done_sesssetup = true;
1096 END_PROFILE(SMBsesssetupX);