librpc: Shorten dcerpc_binding_handle_call a bit
[Samba/vl.git] / source3 / smbd / sesssetup.c
blob4728759c6ccf61c213663198d2ac4c62e4b7aabc
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 uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
136 uint32_t client_caps = IVAL(req->vwv+10, 0);
138 DEBUG(3,("Doing spnego session setup\n"));
140 if (!sconn->smb1.sessions.done_sesssetup) {
141 global_client_caps = client_caps;
143 if (!(global_client_caps & CAP_STATUS32)) {
144 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
148 p = req->buf;
150 if (data_blob_len == 0) {
151 /* an invalid request */
152 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
153 return;
156 bufrem = smbreq_bufrem(req, p);
157 /* pull the spnego blob */
158 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
160 #if 0
161 file_save("negotiate.dat", in_blob.data, in_blob.length);
162 #endif
164 p2 = (const char *)req->buf + in_blob.length;
166 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
167 STR_TERMINATE);
168 native_os = tmp ? tmp : "";
170 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
171 STR_TERMINATE);
172 native_lanman = tmp ? tmp : "";
174 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
175 STR_TERMINATE);
176 primary_domain = tmp ? tmp : "";
178 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
179 native_os, native_lanman, primary_domain));
181 if ( ra_type == RA_WIN2K ) {
182 /* Vista sets neither the OS or lanman strings */
184 if ( !strlen(native_os) && !strlen(native_lanman) )
185 set_remote_arch(RA_VISTA);
187 /* Windows 2003 doesn't set the native lanman string,
188 but does set primary domain which is a bug I think */
190 if ( !strlen(native_lanman) ) {
191 ra_lanman_string( primary_domain );
192 } else {
193 ra_lanman_string( native_lanman );
195 } else if ( ra_type == RA_VISTA ) {
196 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
197 set_remote_arch(RA_OSX);
201 if (vuid != 0) {
202 status = smb1srv_session_lookup(sconn->conn,
203 vuid, now,
204 &session);
205 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
206 reply_force_doserror(req, ERRSRV, ERRbaduid);
207 return;
209 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
210 status = NT_STATUS_OK;
212 if (NT_STATUS_IS_OK(status)) {
213 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
214 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
215 TALLOC_FREE(session->gensec);
217 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
218 reply_nterror(req, nt_status_squash(status));
219 return;
223 if (session == NULL) {
224 /* create a new session */
225 status = smbXsrv_session_create(sconn->conn,
226 now, &session);
227 if (!NT_STATUS_IS_OK(status)) {
228 reply_nterror(req, nt_status_squash(status));
229 return;
233 if (!session->gensec) {
234 status = auth_generic_prepare(session, sconn->remote_address,
235 &session->gensec);
236 if (!NT_STATUS_IS_OK(status)) {
237 TALLOC_FREE(session);
238 reply_nterror(req, nt_status_squash(status));
239 return;
242 gensec_want_feature(session->gensec, GENSEC_FEATURE_SESSION_KEY);
243 gensec_want_feature(session->gensec, GENSEC_FEATURE_UNIX_TOKEN);
245 status = gensec_start_mech_by_oid(session->gensec,
246 GENSEC_OID_SPNEGO);
247 if (!NT_STATUS_IS_OK(status)) {
248 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
249 TALLOC_FREE(session);;
250 reply_nterror(req, nt_status_squash(status));
251 return;
255 become_root();
256 status = gensec_update(session->gensec,
257 talloc_tos(), NULL,
258 in_blob, &out_blob);
259 unbecome_root();
260 if (!NT_STATUS_IS_OK(status) &&
261 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
262 TALLOC_FREE(session);
263 reply_nterror(req, nt_status_squash(status));
264 return;
267 if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
268 struct auth_session_info *session_info = NULL;
270 status = gensec_session_info(session->gensec,
271 session,
272 &session_info);
273 if (!NT_STATUS_IS_OK(status)) {
274 DEBUG(1,("Failed to generate session_info "
275 "(user and group token) for session setup: %s\n",
276 nt_errstr(status)));
277 data_blob_free(&out_blob);
278 TALLOC_FREE(session);
279 reply_nterror(req, nt_status_squash(status));
280 return;
283 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
284 action = 1;
287 if (session_info->session_key.length > 0) {
288 struct smbXsrv_session *x = session;
291 * Note: the SMB1 signing key is not truncated to 16 byte!
293 x->global->signing_key =
294 data_blob_dup_talloc(x->global,
295 session_info->session_key);
296 if (x->global->signing_key.data == NULL) {
297 data_blob_free(&out_blob);
298 TALLOC_FREE(session);
299 reply_nterror(req, NT_STATUS_NO_MEMORY);
300 return;
304 * clear the session key
305 * the first tcon will add setup the application key
307 data_blob_clear_free(&session_info->session_key);
310 session->compat = talloc_zero(session, struct user_struct);
311 if (session->compat == NULL) {
312 data_blob_free(&out_blob);
313 TALLOC_FREE(session);
314 reply_nterror(req, NT_STATUS_NO_MEMORY);
315 return;
317 session->compat->session = session;
318 session->compat->homes_snum = -1;
319 session->compat->session_info = session_info;
320 session->compat->session_keystr = NULL;
321 session->compat->vuid = session->global->session_wire_id;
322 DLIST_ADD(sconn->users, session->compat);
323 sconn->num_users++;
325 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
326 session->compat->homes_snum =
327 register_homes_share(session_info->unix_info->unix_name);
330 if (srv_is_signing_negotiated(sconn) &&
331 action == 0 &&
332 session->global->signing_key.length > 0)
335 * Try and turn on server signing on the first non-guest
336 * sessionsetup.
338 srv_set_signing(sconn,
339 session->global->signing_key,
340 data_blob_null);
343 set_current_user_info(session_info->unix_info->sanitized_username,
344 session_info->unix_info->unix_name,
345 session_info->info->domain_name);
347 session->status = NT_STATUS_OK;
348 session->global->auth_session_info = talloc_move(session->global,
349 &session_info);
350 session->global->auth_session_info_seqnum += 1;
351 session->global->channels[0].auth_session_info_seqnum =
352 session->global->auth_session_info_seqnum;
353 if (client_caps & CAP_DYNAMIC_REAUTH) {
354 session->global->expiration_time =
355 gensec_expire_time(session->gensec);
356 } else {
357 session->global->expiration_time =
358 GENSEC_EXPIRE_TIME_INFINITY;
361 if (!session_claim(session)) {
362 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
363 (unsigned long long)session->compat->vuid));
364 data_blob_free(&out_blob);
365 TALLOC_FREE(session);
366 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
367 return;
370 status = smbXsrv_session_update(session);
371 if (!NT_STATUS_IS_OK(status)) {
372 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
373 (unsigned long long)session->compat->vuid,
374 nt_errstr(status)));
375 data_blob_free(&out_blob);
376 TALLOC_FREE(session);
377 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
378 return;
381 if (!sconn->smb1.sessions.done_sesssetup) {
382 sconn->smb1.sessions.max_send =
383 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
385 sconn->smb1.sessions.done_sesssetup = true;
387 /* current_user_info is changed on new vuid */
388 reload_services(sconn, conn_snum_used, true);
389 } else if (NT_STATUS_IS_OK(status)) {
390 struct auth_session_info *session_info = NULL;
392 status = gensec_session_info(session->gensec,
393 session,
394 &session_info);
395 if (!NT_STATUS_IS_OK(status)) {
396 DEBUG(1,("Failed to generate session_info "
397 "(user and group token) for session setup: %s\n",
398 nt_errstr(status)));
399 data_blob_free(&out_blob);
400 TALLOC_FREE(session);
401 reply_nterror(req, nt_status_squash(status));
402 return;
405 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
406 action = 1;
410 * Keep the application key
412 data_blob_clear_free(&session_info->session_key);
413 session_info->session_key =
414 session->global->auth_session_info->session_key;
415 talloc_steal(session_info, session_info->session_key.data);
416 TALLOC_FREE(session->global->auth_session_info);
418 session->compat->session_info = session_info;
420 session->compat->vuid = session->global->session_wire_id;
422 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
423 session->compat->homes_snum =
424 register_homes_share(session_info->unix_info->unix_name);
427 set_current_user_info(session_info->unix_info->sanitized_username,
428 session_info->unix_info->unix_name,
429 session_info->info->domain_name);
431 session->status = NT_STATUS_OK;
432 session->global->auth_session_info = talloc_move(session->global,
433 &session_info);
434 session->global->auth_session_info_seqnum += 1;
435 session->global->channels[0].auth_session_info_seqnum =
436 session->global->auth_session_info_seqnum;
437 if (client_caps & CAP_DYNAMIC_REAUTH) {
438 session->global->expiration_time =
439 gensec_expire_time(session->gensec);
440 } else {
441 session->global->expiration_time =
442 GENSEC_EXPIRE_TIME_INFINITY;
445 status = smbXsrv_session_update(session);
446 if (!NT_STATUS_IS_OK(status)) {
447 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
448 (unsigned long long)session->compat->vuid,
449 nt_errstr(status)));
450 data_blob_free(&out_blob);
451 TALLOC_FREE(session);
452 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
453 return;
456 conn_clear_vuid_caches(sconn, session->compat->vuid);
458 /* current_user_info is changed on new vuid */
459 reload_services(sconn, conn_snum_used, true);
462 vuid = session->global->session_wire_id;
464 reply_outbuf(req, 4, 0);
466 SSVAL(req->outbuf, smb_uid, vuid);
467 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
468 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
469 SSVAL(req->outbuf, smb_vwv2, action);
470 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
472 if (message_push_blob(&req->outbuf, out_blob) == -1) {
473 data_blob_free(&out_blob);
474 TALLOC_FREE(session);
475 reply_nterror(req, NT_STATUS_NO_MEMORY);
476 return;
478 data_blob_free(&out_blob);
480 if (push_signature(&req->outbuf) == -1) {
481 TALLOC_FREE(session);
482 reply_nterror(req, NT_STATUS_NO_MEMORY);
483 return;
487 /****************************************************************************
488 On new VC == 0, shutdown *all* old connections and users.
489 It seems that only NT4.x does this. At W2K and above (XP etc.).
490 a new session setup with VC==0 is ignored.
491 ****************************************************************************/
493 struct shutdown_state {
494 const char *ip;
495 struct messaging_context *msg_ctx;
498 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
499 void *private_data)
501 struct shutdown_state *state = (struct shutdown_state *)private_data;
502 struct server_id self_pid = messaging_server_id(state->msg_ctx);
503 struct server_id pid = session->channels[0].server_id;
504 const char *addr = session->channels[0].remote_address;
506 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
507 server_id_str(talloc_tos(), &pid), addr));
509 if (!process_exists(pid)) {
510 DEBUG(10, ("process does not exist\n"));
511 return 0;
514 if (serverid_equal(&pid, &self_pid)) {
515 DEBUG(10, ("It's me\n"));
516 return 0;
520 * here we use strstr() because 'addr'
521 * (session->channels[0].remote_address)
522 * contains a string like:
523 * 'ipv4:127.0.0.1:48163'
525 if (strstr(addr, state->ip) == NULL) {
526 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
527 return 0;
530 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
531 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
532 state->ip));
534 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
535 &data_blob_null);
536 return 0;
539 static void setup_new_vc_session(struct smbd_server_connection *sconn)
541 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
542 "compatible we would close all old resources.\n"));
543 #if 0
544 conn_close_all();
545 invalidate_all_vuids();
546 #endif
547 if (lp_reset_on_zero_vc()) {
548 char *addr;
549 struct shutdown_state state;
551 addr = tsocket_address_inet_addr_string(
552 sconn->remote_address, talloc_tos());
553 if (addr == NULL) {
554 return;
556 state.ip = addr;
557 state.msg_ctx = sconn->msg_ctx;
558 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
559 TALLOC_FREE(addr);
563 /****************************************************************************
564 Reply to a session setup command.
565 ****************************************************************************/
567 void reply_sesssetup_and_X(struct smb_request *req)
569 uint64_t sess_vuid;
570 uint16_t smb_bufsize;
571 DATA_BLOB lm_resp;
572 DATA_BLOB nt_resp;
573 DATA_BLOB plaintext_password;
574 char *tmp;
575 const char *user;
576 fstring sub_user; /* Sanitised username for substituion */
577 const char *domain;
578 const char *native_os;
579 const char *native_lanman;
580 const char *primary_domain;
581 struct auth_usersupplied_info *user_info = NULL;
582 struct auth_session_info *session_info = NULL;
583 uint16 smb_flag2 = req->flags2;
584 uint16_t action = 0;
585 NTTIME now = timeval_to_nttime(&req->request_time);
586 struct smbXsrv_session *session = NULL;
588 NTSTATUS nt_status;
589 struct smbd_server_connection *sconn = req->sconn;
591 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
592 bool signing_allowed = false;
593 bool signing_mandatory = false;
595 START_PROFILE(SMBsesssetupX);
597 ZERO_STRUCT(lm_resp);
598 ZERO_STRUCT(nt_resp);
599 ZERO_STRUCT(plaintext_password);
601 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
603 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
604 signing_allowed = true;
606 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
607 signing_mandatory = true;
611 * We can call srv_set_signing_negotiated() each time.
612 * It finds out when it needs to turn into a noop
613 * itself.
615 srv_set_signing_negotiated(req->sconn,
616 signing_allowed,
617 signing_mandatory);
619 /* a SPNEGO session setup has 12 command words, whereas a normal
620 NT1 session setup has 13. See the cifs spec. */
621 if (req->wct == 12 &&
622 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
624 if (!sconn->smb1.negprot.spnego) {
625 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
626 "at SPNEGO session setup when it was not "
627 "negotiated.\n"));
628 reply_nterror(req, nt_status_squash(
629 NT_STATUS_LOGON_FAILURE));
630 END_PROFILE(SMBsesssetupX);
631 return;
634 if (SVAL(req->vwv+4, 0) == 0) {
635 setup_new_vc_session(req->sconn);
638 reply_sesssetup_and_X_spnego(req);
639 END_PROFILE(SMBsesssetupX);
640 return;
643 smb_bufsize = SVAL(req->vwv+2, 0);
645 if (get_Protocol() < PROTOCOL_NT1) {
646 uint16 passlen1 = SVAL(req->vwv+7, 0);
648 /* Never do NT status codes with protocols before NT1 as we
649 * don't get client caps. */
650 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
652 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
653 reply_nterror(req, nt_status_squash(
654 NT_STATUS_INVALID_PARAMETER));
655 END_PROFILE(SMBsesssetupX);
656 return;
659 if (doencrypt) {
660 lm_resp = data_blob(req->buf, passlen1);
661 } else {
662 plaintext_password = data_blob(req->buf, passlen1+1);
663 /* Ensure null termination */
664 plaintext_password.data[passlen1] = 0;
667 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
668 req->buf + passlen1, STR_TERMINATE);
669 user = tmp ? tmp : "";
671 domain = "";
673 } else {
674 uint16 passlen1 = SVAL(req->vwv+7, 0);
675 uint16 passlen2 = SVAL(req->vwv+8, 0);
676 enum remote_arch_types ra_type = get_remote_arch();
677 const uint8_t *p = req->buf;
678 const uint8_t *save_p = req->buf;
679 uint16 byte_count;
681 if (!sconn->smb1.sessions.done_sesssetup) {
682 global_client_caps = IVAL(req->vwv+11, 0);
684 if (!(global_client_caps & CAP_STATUS32)) {
685 remove_from_common_flags2(
686 FLAGS2_32_BIT_ERROR_CODES);
689 /* client_caps is used as final determination if
690 * client is NT or Win95. This is needed to return
691 * the correct error codes in some circumstances.
694 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
695 ra_type == RA_WIN95) {
696 if(!(global_client_caps & (CAP_NT_SMBS|
697 CAP_STATUS32))) {
698 set_remote_arch( RA_WIN95);
703 if (!doencrypt) {
704 /* both Win95 and WinNT stuff up the password
705 * lengths for non-encrypting systems. Uggh.
707 if passlen1==24 its a win95 system, and its setting
708 the password length incorrectly. Luckily it still
709 works with the default code because Win95 will null
710 terminate the password anyway
712 if passlen1>0 and passlen2>0 then maybe its a NT box
713 and its setting passlen2 to some random value which
714 really stuffs things up. we need to fix that one. */
716 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
717 passlen2 != 1) {
718 passlen2 = 0;
722 /* check for nasty tricks */
723 if (passlen1 > MAX_PASS_LEN
724 || passlen1 > smbreq_bufrem(req, p)) {
725 reply_nterror(req, nt_status_squash(
726 NT_STATUS_INVALID_PARAMETER));
727 END_PROFILE(SMBsesssetupX);
728 return;
731 if (passlen2 > MAX_PASS_LEN
732 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
733 reply_nterror(req, nt_status_squash(
734 NT_STATUS_INVALID_PARAMETER));
735 END_PROFILE(SMBsesssetupX);
736 return;
739 /* Save the lanman2 password and the NT md4 password. */
741 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
742 doencrypt = False;
745 if (doencrypt) {
746 lm_resp = data_blob(p, passlen1);
747 nt_resp = data_blob(p+passlen1, passlen2);
748 } else {
749 char *pass = NULL;
750 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
752 if (unic && (passlen2 == 0) && passlen1) {
753 /* Only a ascii plaintext password was sent. */
754 (void)srvstr_pull_talloc(talloc_tos(),
755 req->inbuf,
756 req->flags2,
757 &pass,
758 req->buf,
759 passlen1,
760 STR_TERMINATE|STR_ASCII);
761 } else {
762 (void)srvstr_pull_talloc(talloc_tos(),
763 req->inbuf,
764 req->flags2,
765 &pass,
766 req->buf,
767 unic ? passlen2 : passlen1,
768 STR_TERMINATE);
770 if (!pass) {
771 reply_nterror(req, nt_status_squash(
772 NT_STATUS_INVALID_PARAMETER));
773 END_PROFILE(SMBsesssetupX);
774 return;
776 plaintext_password = data_blob(pass, strlen(pass)+1);
779 p += passlen1 + passlen2;
781 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
782 STR_TERMINATE);
783 user = tmp ? tmp : "";
785 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
786 STR_TERMINATE);
787 domain = tmp ? tmp : "";
789 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
790 STR_TERMINATE);
791 native_os = tmp ? tmp : "";
793 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
794 STR_TERMINATE);
795 native_lanman = tmp ? tmp : "";
797 /* not documented or decoded by Ethereal but there is one more
798 * string in the extra bytes which is the same as the
799 * PrimaryDomain when using extended security. Windows NT 4
800 * and 2003 use this string to store the native lanman string.
801 * Windows 9x does not include a string here at all so we have
802 * to check if we have any extra bytes left */
804 byte_count = SVAL(req->vwv+13, 0);
805 if ( PTR_DIFF(p, save_p) < byte_count) {
806 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
807 STR_TERMINATE);
808 primary_domain = tmp ? tmp : "";
809 } else {
810 primary_domain = talloc_strdup(talloc_tos(), "null");
813 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
814 "PrimaryDomain=[%s]\n",
815 domain, native_os, native_lanman, primary_domain));
817 if ( ra_type == RA_WIN2K ) {
818 if ( strlen(native_lanman) == 0 )
819 ra_lanman_string( primary_domain );
820 else
821 ra_lanman_string( native_lanman );
826 if (SVAL(req->vwv+4, 0) == 0) {
827 setup_new_vc_session(req->sconn);
830 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
831 domain, user, get_remote_machine_name()));
833 if (*user) {
834 if (sconn->smb1.negprot.spnego) {
836 /* This has to be here, because this is a perfectly
837 * valid behaviour for guest logons :-( */
839 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
840 "at 'normal' session setup after "
841 "negotiating spnego.\n"));
842 reply_nterror(req, nt_status_squash(
843 NT_STATUS_LOGON_FAILURE));
844 END_PROFILE(SMBsesssetupX);
845 return;
847 fstrcpy(sub_user, user);
848 } else {
849 fstrcpy(sub_user, "");
852 sub_set_smb_name(sub_user);
854 reload_services(sconn, conn_snum_used, true);
856 if (!*user) {
858 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
860 } else if (doencrypt) {
861 struct auth4_context *negprot_auth_context = NULL;
862 negprot_auth_context = sconn->smb1.negprot.auth_context;
863 if (!negprot_auth_context) {
864 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
865 "session setup without negprot denied!\n"));
866 reply_nterror(req, nt_status_squash(
867 NT_STATUS_LOGON_FAILURE));
868 END_PROFILE(SMBsesssetupX);
869 return;
871 nt_status = make_user_info_for_reply_enc(&user_info, user,
872 domain,
873 sconn->remote_address,
874 lm_resp, nt_resp);
875 if (NT_STATUS_IS_OK(nt_status)) {
876 nt_status = auth_check_password_session_info(negprot_auth_context,
877 req, user_info, &session_info);
879 } else {
880 struct auth4_context *plaintext_auth_context = NULL;
882 nt_status = make_auth4_context(
883 talloc_tos(), &plaintext_auth_context);
885 if (NT_STATUS_IS_OK(nt_status)) {
886 uint8_t chal[8];
888 plaintext_auth_context->get_ntlm_challenge(
889 plaintext_auth_context, chal);
891 if (!make_user_info_for_reply(&user_info,
892 user, domain,
893 sconn->remote_address,
894 chal,
895 plaintext_password)) {
896 nt_status = NT_STATUS_NO_MEMORY;
899 if (NT_STATUS_IS_OK(nt_status)) {
900 nt_status = auth_check_password_session_info(plaintext_auth_context,
901 req, user_info, &session_info);
903 TALLOC_FREE(plaintext_auth_context);
907 free_user_info(&user_info);
909 if (!NT_STATUS_IS_OK(nt_status)) {
910 data_blob_free(&nt_resp);
911 data_blob_free(&lm_resp);
912 data_blob_clear_free(&plaintext_password);
913 reply_nterror(req, nt_status_squash(nt_status));
914 END_PROFILE(SMBsesssetupX);
915 return;
918 data_blob_clear_free(&plaintext_password);
920 /* it's ok - setup a reply */
921 reply_outbuf(req, 3, 0);
922 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
923 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
925 if (get_Protocol() >= PROTOCOL_NT1) {
926 push_signature(&req->outbuf);
927 /* perhaps grab OS version here?? */
930 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
931 action = 1;
934 /* register the name and uid as being validated, so further connections
935 to a uid can get through without a password, on the same VC */
937 nt_status = smbXsrv_session_create(sconn->conn,
938 now, &session);
939 if (!NT_STATUS_IS_OK(nt_status)) {
940 data_blob_free(&nt_resp);
941 data_blob_free(&lm_resp);
942 reply_nterror(req, nt_status_squash(nt_status));
943 END_PROFILE(SMBsesssetupX);
944 return;
947 if (session_info->session_key.length > 0) {
948 uint8_t session_key[16];
951 * Note: the SMB1 signing key is not truncated to 16 byte!
953 session->global->signing_key =
954 data_blob_dup_talloc(session->global,
955 session_info->session_key);
956 if (session->global->signing_key.data == NULL) {
957 data_blob_free(&nt_resp);
958 data_blob_free(&lm_resp);
959 TALLOC_FREE(session);
960 reply_nterror(req, NT_STATUS_NO_MEMORY);
961 END_PROFILE(SMBsesssetupX);
962 return;
966 * The application key is truncated/padded to 16 bytes
968 ZERO_STRUCT(session_key);
969 memcpy(session_key, session->global->signing_key.data,
970 MIN(session->global->signing_key.length,
971 sizeof(session_key)));
972 session->global->application_key =
973 data_blob_talloc(session->global,
974 session_key,
975 sizeof(session_key));
976 ZERO_STRUCT(session_key);
977 if (session->global->application_key.data == NULL) {
978 data_blob_free(&nt_resp);
979 data_blob_free(&lm_resp);
980 TALLOC_FREE(session);
981 reply_nterror(req, NT_STATUS_NO_MEMORY);
982 END_PROFILE(SMBsesssetupX);
983 return;
987 * Place the application key into the session_info
989 data_blob_clear_free(&session_info->session_key);
990 session_info->session_key = data_blob_dup_talloc(session_info,
991 session->global->application_key);
992 if (session_info->session_key.data == NULL) {
993 data_blob_free(&nt_resp);
994 data_blob_free(&lm_resp);
995 TALLOC_FREE(session);
996 reply_nterror(req, NT_STATUS_NO_MEMORY);
997 END_PROFILE(SMBsesssetupX);
998 return;
1002 session->compat = talloc_zero(session, struct user_struct);
1003 if (session->compat == NULL) {
1004 data_blob_free(&nt_resp);
1005 data_blob_free(&lm_resp);
1006 TALLOC_FREE(session);
1007 reply_nterror(req, NT_STATUS_NO_MEMORY);
1008 END_PROFILE(SMBsesssetupX);
1009 return;
1011 session->compat->session = session;
1012 session->compat->homes_snum = -1;
1013 session->compat->session_info = session_info;
1014 session->compat->session_keystr = NULL;
1015 session->compat->vuid = session->global->session_wire_id;
1016 DLIST_ADD(sconn->users, session->compat);
1017 sconn->num_users++;
1019 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1020 session->compat->homes_snum =
1021 register_homes_share(session_info->unix_info->unix_name);
1024 if (srv_is_signing_negotiated(sconn) &&
1025 action == 0 &&
1026 session->global->signing_key.length > 0)
1029 * Try and turn on server signing on the first non-guest
1030 * sessionsetup.
1032 srv_set_signing(sconn,
1033 session->global->signing_key,
1034 nt_resp.data ? nt_resp : lm_resp);
1037 set_current_user_info(session_info->unix_info->sanitized_username,
1038 session_info->unix_info->unix_name,
1039 session_info->info->domain_name);
1041 session->status = NT_STATUS_OK;
1042 session->global->auth_session_info = talloc_move(session->global,
1043 &session_info);
1044 session->global->auth_session_info_seqnum += 1;
1045 session->global->channels[0].auth_session_info_seqnum =
1046 session->global->auth_session_info_seqnum;
1047 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1049 nt_status = smbXsrv_session_update(session);
1050 if (!NT_STATUS_IS_OK(nt_status)) {
1051 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1052 (unsigned long long)session->compat->vuid,
1053 nt_errstr(nt_status)));
1054 data_blob_free(&nt_resp);
1055 data_blob_free(&lm_resp);
1056 TALLOC_FREE(session);
1057 reply_nterror(req, nt_status_squash(nt_status));
1058 END_PROFILE(SMBsesssetupX);
1059 return;
1062 if (!session_claim(session)) {
1063 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1064 (unsigned long long)session->compat->vuid));
1065 data_blob_free(&nt_resp);
1066 data_blob_free(&lm_resp);
1067 TALLOC_FREE(session);
1068 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1069 END_PROFILE(SMBsesssetupX);
1070 return;
1073 /* current_user_info is changed on new vuid */
1074 reload_services(sconn, conn_snum_used, true);
1076 sess_vuid = session->global->session_wire_id;
1078 data_blob_free(&nt_resp);
1079 data_blob_free(&lm_resp);
1081 SSVAL(req->outbuf,smb_vwv2,action);
1082 SSVAL(req->outbuf,smb_uid,sess_vuid);
1083 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1084 req->vuid = sess_vuid;
1086 if (!sconn->smb1.sessions.done_sesssetup) {
1087 sconn->smb1.sessions.max_send =
1088 MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1090 sconn->smb1.sessions.done_sesssetup = true;
1092 END_PROFILE(SMBsesssetupX);