auth: Make sure that creds_out is initialized with NULL.
[Samba.git] / source3 / smbd / sesssetup.c
blob512832847cc3863717ae3c40ab41f72a2a4a3f7f
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 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
383 reply_force_doserror(req, ERRSRV, ERRerror);
384 return;
386 sconn->smb1.sessions.max_send = smb_bufsize;
387 sconn->smb1.sessions.done_sesssetup = true;
390 /* current_user_info is changed on new vuid */
391 reload_services(sconn, conn_snum_used, true);
392 } else if (NT_STATUS_IS_OK(status)) {
393 struct auth_session_info *session_info = NULL;
395 status = gensec_session_info(session->gensec,
396 session,
397 &session_info);
398 if (!NT_STATUS_IS_OK(status)) {
399 DEBUG(1,("Failed to generate session_info "
400 "(user and group token) for session setup: %s\n",
401 nt_errstr(status)));
402 data_blob_free(&out_blob);
403 TALLOC_FREE(session);
404 reply_nterror(req, nt_status_squash(status));
405 return;
408 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
409 action = 1;
413 * Keep the application key
415 data_blob_clear_free(&session_info->session_key);
416 session_info->session_key =
417 session->global->auth_session_info->session_key;
418 talloc_steal(session_info, session_info->session_key.data);
419 TALLOC_FREE(session->global->auth_session_info);
421 session->compat->session_info = session_info;
423 session->compat->vuid = session->global->session_wire_id;
425 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
426 session->compat->homes_snum =
427 register_homes_share(session_info->unix_info->unix_name);
430 set_current_user_info(session_info->unix_info->sanitized_username,
431 session_info->unix_info->unix_name,
432 session_info->info->domain_name);
434 session->status = NT_STATUS_OK;
435 session->global->auth_session_info = talloc_move(session->global,
436 &session_info);
437 session->global->auth_session_info_seqnum += 1;
438 session->global->channels[0].auth_session_info_seqnum =
439 session->global->auth_session_info_seqnum;
440 if (client_caps & CAP_DYNAMIC_REAUTH) {
441 session->global->expiration_time =
442 gensec_expire_time(session->gensec);
443 } else {
444 session->global->expiration_time =
445 GENSEC_EXPIRE_TIME_INFINITY;
448 status = smbXsrv_session_update(session);
449 if (!NT_STATUS_IS_OK(status)) {
450 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
451 (unsigned long long)session->compat->vuid,
452 nt_errstr(status)));
453 data_blob_free(&out_blob);
454 TALLOC_FREE(session);
455 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
456 return;
459 conn_clear_vuid_caches(sconn, session->compat->vuid);
461 /* current_user_info is changed on new vuid */
462 reload_services(sconn, conn_snum_used, true);
465 vuid = session->global->session_wire_id;
467 reply_outbuf(req, 4, 0);
469 SSVAL(req->outbuf, smb_uid, vuid);
470 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
471 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
472 SSVAL(req->outbuf, smb_vwv2, action);
473 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
475 if (message_push_blob(&req->outbuf, out_blob) == -1) {
476 data_blob_free(&out_blob);
477 TALLOC_FREE(session);
478 reply_nterror(req, NT_STATUS_NO_MEMORY);
479 return;
481 data_blob_free(&out_blob);
483 if (push_signature(&req->outbuf) == -1) {
484 TALLOC_FREE(session);
485 reply_nterror(req, NT_STATUS_NO_MEMORY);
486 return;
490 /****************************************************************************
491 On new VC == 0, shutdown *all* old connections and users.
492 It seems that only NT4.x does this. At W2K and above (XP etc.).
493 a new session setup with VC==0 is ignored.
494 ****************************************************************************/
496 struct shutdown_state {
497 const char *ip;
498 struct messaging_context *msg_ctx;
501 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
502 void *private_data)
504 struct shutdown_state *state = (struct shutdown_state *)private_data;
505 struct server_id self_pid = messaging_server_id(state->msg_ctx);
506 struct server_id pid = session->channels[0].server_id;
507 const char *addr = session->channels[0].remote_address;
509 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
510 server_id_str(talloc_tos(), &pid), addr));
512 if (!process_exists(pid)) {
513 DEBUG(10, ("process does not exist\n"));
514 return 0;
517 if (serverid_equal(&pid, &self_pid)) {
518 DEBUG(10, ("It's me\n"));
519 return 0;
523 * here we use strstr() because 'addr'
524 * (session->channels[0].remote_address)
525 * contains a string like:
526 * 'ipv4:127.0.0.1:48163'
528 if (strstr(addr, state->ip) == NULL) {
529 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
530 return 0;
533 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
534 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
535 state->ip));
537 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
538 &data_blob_null);
539 return 0;
542 static void setup_new_vc_session(struct smbd_server_connection *sconn)
544 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
545 "compatible we would close all old resources.\n"));
546 #if 0
547 conn_close_all();
548 invalidate_all_vuids();
549 #endif
550 if (lp_reset_on_zero_vc()) {
551 char *addr;
552 struct shutdown_state state;
554 addr = tsocket_address_inet_addr_string(
555 sconn->remote_address, talloc_tos());
556 if (addr == NULL) {
557 return;
559 state.ip = addr;
560 state.msg_ctx = sconn->msg_ctx;
561 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
562 TALLOC_FREE(addr);
566 /****************************************************************************
567 Reply to a session setup command.
568 ****************************************************************************/
570 void reply_sesssetup_and_X(struct smb_request *req)
572 uint64_t sess_vuid;
573 uint16_t smb_bufsize;
574 DATA_BLOB lm_resp;
575 DATA_BLOB nt_resp;
576 DATA_BLOB plaintext_password;
577 char *tmp;
578 const char *user;
579 fstring sub_user; /* Sanitised username for substituion */
580 const char *domain;
581 const char *native_os;
582 const char *native_lanman;
583 const char *primary_domain;
584 struct auth_usersupplied_info *user_info = NULL;
585 struct auth_session_info *session_info = NULL;
586 uint16 smb_flag2 = req->flags2;
587 uint16_t action = 0;
588 NTTIME now = timeval_to_nttime(&req->request_time);
589 struct smbXsrv_session *session = NULL;
591 NTSTATUS nt_status;
592 struct smbd_server_connection *sconn = req->sconn;
594 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
595 bool signing_allowed = false;
596 bool signing_mandatory = false;
598 START_PROFILE(SMBsesssetupX);
600 ZERO_STRUCT(lm_resp);
601 ZERO_STRUCT(nt_resp);
602 ZERO_STRUCT(plaintext_password);
604 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
606 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
607 signing_allowed = true;
609 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
610 signing_mandatory = true;
614 * We can call srv_set_signing_negotiated() each time.
615 * It finds out when it needs to turn into a noop
616 * itself.
618 srv_set_signing_negotiated(req->sconn,
619 signing_allowed,
620 signing_mandatory);
622 /* a SPNEGO session setup has 12 command words, whereas a normal
623 NT1 session setup has 13. See the cifs spec. */
624 if (req->wct == 12 &&
625 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
627 if (!sconn->smb1.negprot.spnego) {
628 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
629 "at SPNEGO session setup when it was not "
630 "negotiated.\n"));
631 reply_nterror(req, nt_status_squash(
632 NT_STATUS_LOGON_FAILURE));
633 END_PROFILE(SMBsesssetupX);
634 return;
637 if (SVAL(req->vwv+4, 0) == 0) {
638 setup_new_vc_session(req->sconn);
641 reply_sesssetup_and_X_spnego(req);
642 END_PROFILE(SMBsesssetupX);
643 return;
646 smb_bufsize = SVAL(req->vwv+2, 0);
648 if (get_Protocol() < PROTOCOL_NT1) {
649 uint16 passlen1 = SVAL(req->vwv+7, 0);
651 /* Never do NT status codes with protocols before NT1 as we
652 * don't get client caps. */
653 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
655 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
656 reply_nterror(req, nt_status_squash(
657 NT_STATUS_INVALID_PARAMETER));
658 END_PROFILE(SMBsesssetupX);
659 return;
662 if (doencrypt) {
663 lm_resp = data_blob(req->buf, passlen1);
664 } else {
665 plaintext_password = data_blob(req->buf, passlen1+1);
666 /* Ensure null termination */
667 plaintext_password.data[passlen1] = 0;
670 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
671 req->buf + passlen1, STR_TERMINATE);
672 user = tmp ? tmp : "";
674 domain = "";
676 } else {
677 uint16 passlen1 = SVAL(req->vwv+7, 0);
678 uint16 passlen2 = SVAL(req->vwv+8, 0);
679 enum remote_arch_types ra_type = get_remote_arch();
680 const uint8_t *p = req->buf;
681 const uint8_t *save_p = req->buf;
682 uint16 byte_count;
684 if (!sconn->smb1.sessions.done_sesssetup) {
685 global_client_caps = IVAL(req->vwv+11, 0);
687 if (!(global_client_caps & CAP_STATUS32)) {
688 remove_from_common_flags2(
689 FLAGS2_32_BIT_ERROR_CODES);
692 /* client_caps is used as final determination if
693 * client is NT or Win95. This is needed to return
694 * the correct error codes in some circumstances.
697 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
698 ra_type == RA_WIN95) {
699 if(!(global_client_caps & (CAP_NT_SMBS|
700 CAP_STATUS32))) {
701 set_remote_arch( RA_WIN95);
706 if (!doencrypt) {
707 /* both Win95 and WinNT stuff up the password
708 * lengths for non-encrypting systems. Uggh.
710 if passlen1==24 its a win95 system, and its setting
711 the password length incorrectly. Luckily it still
712 works with the default code because Win95 will null
713 terminate the password anyway
715 if passlen1>0 and passlen2>0 then maybe its a NT box
716 and its setting passlen2 to some random value which
717 really stuffs things up. we need to fix that one. */
719 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
720 passlen2 != 1) {
721 passlen2 = 0;
725 /* check for nasty tricks */
726 if (passlen1 > MAX_PASS_LEN
727 || passlen1 > smbreq_bufrem(req, p)) {
728 reply_nterror(req, nt_status_squash(
729 NT_STATUS_INVALID_PARAMETER));
730 END_PROFILE(SMBsesssetupX);
731 return;
734 if (passlen2 > MAX_PASS_LEN
735 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
736 reply_nterror(req, nt_status_squash(
737 NT_STATUS_INVALID_PARAMETER));
738 END_PROFILE(SMBsesssetupX);
739 return;
742 /* Save the lanman2 password and the NT md4 password. */
744 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
745 doencrypt = False;
748 if (doencrypt) {
749 lm_resp = data_blob(p, passlen1);
750 nt_resp = data_blob(p+passlen1, passlen2);
751 } else {
752 char *pass = NULL;
753 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
755 if (unic && (passlen2 == 0) && passlen1) {
756 /* Only a ascii plaintext password was sent. */
757 (void)srvstr_pull_talloc(talloc_tos(),
758 req->inbuf,
759 req->flags2,
760 &pass,
761 req->buf,
762 passlen1,
763 STR_TERMINATE|STR_ASCII);
764 } else {
765 (void)srvstr_pull_talloc(talloc_tos(),
766 req->inbuf,
767 req->flags2,
768 &pass,
769 req->buf,
770 unic ? passlen2 : passlen1,
771 STR_TERMINATE);
773 if (!pass) {
774 reply_nterror(req, nt_status_squash(
775 NT_STATUS_INVALID_PARAMETER));
776 END_PROFILE(SMBsesssetupX);
777 return;
779 plaintext_password = data_blob(pass, strlen(pass)+1);
782 p += passlen1 + passlen2;
784 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
785 STR_TERMINATE);
786 user = tmp ? tmp : "";
788 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
789 STR_TERMINATE);
790 domain = tmp ? tmp : "";
792 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
793 STR_TERMINATE);
794 native_os = tmp ? tmp : "";
796 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
797 STR_TERMINATE);
798 native_lanman = tmp ? tmp : "";
800 /* not documented or decoded by Ethereal but there is one more
801 * string in the extra bytes which is the same as the
802 * PrimaryDomain when using extended security. Windows NT 4
803 * and 2003 use this string to store the native lanman string.
804 * Windows 9x does not include a string here at all so we have
805 * to check if we have any extra bytes left */
807 byte_count = SVAL(req->vwv+13, 0);
808 if ( PTR_DIFF(p, save_p) < byte_count) {
809 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
810 STR_TERMINATE);
811 primary_domain = tmp ? tmp : "";
812 } else {
813 primary_domain = talloc_strdup(talloc_tos(), "null");
816 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
817 "PrimaryDomain=[%s]\n",
818 domain, native_os, native_lanman, primary_domain));
820 if ( ra_type == RA_WIN2K ) {
821 if ( strlen(native_lanman) == 0 )
822 ra_lanman_string( primary_domain );
823 else
824 ra_lanman_string( native_lanman );
829 if (SVAL(req->vwv+4, 0) == 0) {
830 setup_new_vc_session(req->sconn);
833 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
834 domain, user, get_remote_machine_name()));
836 if (*user) {
837 if (sconn->smb1.negprot.spnego) {
839 /* This has to be here, because this is a perfectly
840 * valid behaviour for guest logons :-( */
842 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
843 "at 'normal' session setup after "
844 "negotiating spnego.\n"));
845 reply_nterror(req, nt_status_squash(
846 NT_STATUS_LOGON_FAILURE));
847 END_PROFILE(SMBsesssetupX);
848 return;
850 fstrcpy(sub_user, user);
851 } else {
852 fstrcpy(sub_user, "");
855 sub_set_smb_name(sub_user);
857 reload_services(sconn, conn_snum_used, true);
859 if (!*user) {
861 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
863 } else if (doencrypt) {
864 struct auth4_context *negprot_auth_context = NULL;
865 negprot_auth_context = sconn->smb1.negprot.auth_context;
866 if (!negprot_auth_context) {
867 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
868 "session setup without negprot denied!\n"));
869 reply_nterror(req, nt_status_squash(
870 NT_STATUS_LOGON_FAILURE));
871 END_PROFILE(SMBsesssetupX);
872 return;
874 nt_status = make_user_info_for_reply_enc(&user_info, user,
875 domain,
876 sconn->remote_address,
877 lm_resp, nt_resp);
878 if (NT_STATUS_IS_OK(nt_status)) {
879 nt_status = auth_check_password_session_info(negprot_auth_context,
880 req, user_info, &session_info);
882 } else {
883 struct auth4_context *plaintext_auth_context = NULL;
885 nt_status = make_auth4_context(
886 talloc_tos(), &plaintext_auth_context);
888 if (NT_STATUS_IS_OK(nt_status)) {
889 uint8_t chal[8];
891 plaintext_auth_context->get_ntlm_challenge(
892 plaintext_auth_context, chal);
894 if (!make_user_info_for_reply(&user_info,
895 user, domain,
896 sconn->remote_address,
897 chal,
898 plaintext_password)) {
899 nt_status = NT_STATUS_NO_MEMORY;
902 if (NT_STATUS_IS_OK(nt_status)) {
903 nt_status = auth_check_password_session_info(plaintext_auth_context,
904 req, user_info, &session_info);
906 TALLOC_FREE(plaintext_auth_context);
910 free_user_info(&user_info);
912 if (!NT_STATUS_IS_OK(nt_status)) {
913 data_blob_free(&nt_resp);
914 data_blob_free(&lm_resp);
915 data_blob_clear_free(&plaintext_password);
916 reply_nterror(req, nt_status_squash(nt_status));
917 END_PROFILE(SMBsesssetupX);
918 return;
921 data_blob_clear_free(&plaintext_password);
923 /* it's ok - setup a reply */
924 reply_outbuf(req, 3, 0);
925 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
926 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
928 if (get_Protocol() >= PROTOCOL_NT1) {
929 push_signature(&req->outbuf);
930 /* perhaps grab OS version here?? */
933 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
934 action = 1;
937 /* register the name and uid as being validated, so further connections
938 to a uid can get through without a password, on the same VC */
940 nt_status = smbXsrv_session_create(sconn->conn,
941 now, &session);
942 if (!NT_STATUS_IS_OK(nt_status)) {
943 data_blob_free(&nt_resp);
944 data_blob_free(&lm_resp);
945 reply_nterror(req, nt_status_squash(nt_status));
946 END_PROFILE(SMBsesssetupX);
947 return;
950 if (session_info->session_key.length > 0) {
951 uint8_t session_key[16];
954 * Note: the SMB1 signing key is not truncated to 16 byte!
956 session->global->signing_key =
957 data_blob_dup_talloc(session->global,
958 session_info->session_key);
959 if (session->global->signing_key.data == NULL) {
960 data_blob_free(&nt_resp);
961 data_blob_free(&lm_resp);
962 TALLOC_FREE(session);
963 reply_nterror(req, NT_STATUS_NO_MEMORY);
964 END_PROFILE(SMBsesssetupX);
965 return;
969 * The application key is truncated/padded to 16 bytes
971 ZERO_STRUCT(session_key);
972 memcpy(session_key, session->global->signing_key.data,
973 MIN(session->global->signing_key.length,
974 sizeof(session_key)));
975 session->global->application_key =
976 data_blob_talloc(session->global,
977 session_key,
978 sizeof(session_key));
979 ZERO_STRUCT(session_key);
980 if (session->global->application_key.data == NULL) {
981 data_blob_free(&nt_resp);
982 data_blob_free(&lm_resp);
983 TALLOC_FREE(session);
984 reply_nterror(req, NT_STATUS_NO_MEMORY);
985 END_PROFILE(SMBsesssetupX);
986 return;
990 * Place the application key into the session_info
992 data_blob_clear_free(&session_info->session_key);
993 session_info->session_key = data_blob_dup_talloc(session_info,
994 session->global->application_key);
995 if (session_info->session_key.data == NULL) {
996 data_blob_free(&nt_resp);
997 data_blob_free(&lm_resp);
998 TALLOC_FREE(session);
999 reply_nterror(req, NT_STATUS_NO_MEMORY);
1000 END_PROFILE(SMBsesssetupX);
1001 return;
1005 session->compat = talloc_zero(session, struct user_struct);
1006 if (session->compat == NULL) {
1007 data_blob_free(&nt_resp);
1008 data_blob_free(&lm_resp);
1009 TALLOC_FREE(session);
1010 reply_nterror(req, NT_STATUS_NO_MEMORY);
1011 END_PROFILE(SMBsesssetupX);
1012 return;
1014 session->compat->session = session;
1015 session->compat->homes_snum = -1;
1016 session->compat->session_info = session_info;
1017 session->compat->session_keystr = NULL;
1018 session->compat->vuid = session->global->session_wire_id;
1019 DLIST_ADD(sconn->users, session->compat);
1020 sconn->num_users++;
1022 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1023 session->compat->homes_snum =
1024 register_homes_share(session_info->unix_info->unix_name);
1027 if (srv_is_signing_negotiated(sconn) &&
1028 action == 0 &&
1029 session->global->signing_key.length > 0)
1032 * Try and turn on server signing on the first non-guest
1033 * sessionsetup.
1035 srv_set_signing(sconn,
1036 session->global->signing_key,
1037 nt_resp.data ? nt_resp : lm_resp);
1040 set_current_user_info(session_info->unix_info->sanitized_username,
1041 session_info->unix_info->unix_name,
1042 session_info->info->domain_name);
1044 session->status = NT_STATUS_OK;
1045 session->global->auth_session_info = talloc_move(session->global,
1046 &session_info);
1047 session->global->auth_session_info_seqnum += 1;
1048 session->global->channels[0].auth_session_info_seqnum =
1049 session->global->auth_session_info_seqnum;
1050 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1052 nt_status = smbXsrv_session_update(session);
1053 if (!NT_STATUS_IS_OK(nt_status)) {
1054 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1055 (unsigned long long)session->compat->vuid,
1056 nt_errstr(nt_status)));
1057 data_blob_free(&nt_resp);
1058 data_blob_free(&lm_resp);
1059 TALLOC_FREE(session);
1060 reply_nterror(req, nt_status_squash(nt_status));
1061 END_PROFILE(SMBsesssetupX);
1062 return;
1065 if (!session_claim(session)) {
1066 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1067 (unsigned long long)session->compat->vuid));
1068 data_blob_free(&nt_resp);
1069 data_blob_free(&lm_resp);
1070 TALLOC_FREE(session);
1071 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1072 END_PROFILE(SMBsesssetupX);
1073 return;
1076 /* current_user_info is changed on new vuid */
1077 reload_services(sconn, conn_snum_used, true);
1079 sess_vuid = session->global->session_wire_id;
1081 data_blob_free(&nt_resp);
1082 data_blob_free(&lm_resp);
1084 SSVAL(req->outbuf,smb_vwv2,action);
1085 SSVAL(req->outbuf,smb_uid,sess_vuid);
1086 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1087 req->vuid = sess_vuid;
1089 if (!sconn->smb1.sessions.done_sesssetup) {
1090 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1091 reply_force_doserror(req, ERRSRV, ERRerror);
1092 END_PROFILE(SMBsesssetupX);
1093 return;
1095 sconn->smb1.sessions.max_send = smb_bufsize;
1096 sconn->smb1.sessions.done_sesssetup = true;
1099 END_PROFILE(SMBsesssetupX);