buildtools: Rename perl vendorarch configure option.
[Samba.git] / source3 / smbd / sesssetup.c
blob4b86a99522fc152843186d66fd1ae0dbfdc15f09
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 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
387 reply_force_doserror(req, ERRSRV, ERRerror);
388 return;
390 sconn->smb1.sessions.max_send = smb_bufsize;
391 sconn->smb1.sessions.done_sesssetup = true;
394 /* current_user_info is changed on new vuid */
395 reload_services(sconn, conn_snum_used, true);
396 } else if (NT_STATUS_IS_OK(status)) {
397 struct auth_session_info *session_info = NULL;
399 status = gensec_session_info(session->gensec,
400 session,
401 &session_info);
402 if (!NT_STATUS_IS_OK(status)) {
403 DEBUG(1,("Failed to generate session_info "
404 "(user and group token) for session setup: %s\n",
405 nt_errstr(status)));
406 data_blob_free(&out_blob);
407 TALLOC_FREE(session);
408 reply_nterror(req, nt_status_squash(status));
409 return;
412 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
413 action = 1;
417 * Keep the application key
419 data_blob_clear_free(&session_info->session_key);
420 session_info->session_key =
421 session->global->auth_session_info->session_key;
422 talloc_steal(session_info, session_info->session_key.data);
423 TALLOC_FREE(session->global->auth_session_info);
425 session->compat->session_info = session_info;
427 session->compat->vuid = session->global->session_wire_id;
429 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
430 session->compat->homes_snum =
431 register_homes_share(session_info->unix_info->unix_name);
434 set_current_user_info(session_info->unix_info->sanitized_username,
435 session_info->unix_info->unix_name,
436 session_info->info->domain_name);
438 session->status = NT_STATUS_OK;
439 session->global->auth_session_info = talloc_move(session->global,
440 &session_info);
441 session->global->auth_session_info_seqnum += 1;
442 session->global->channels[0].auth_session_info_seqnum =
443 session->global->auth_session_info_seqnum;
444 if (client_caps & CAP_DYNAMIC_REAUTH) {
445 session->global->expiration_time =
446 gensec_expire_time(session->gensec);
447 } else {
448 session->global->expiration_time =
449 GENSEC_EXPIRE_TIME_INFINITY;
452 status = smbXsrv_session_update(session);
453 if (!NT_STATUS_IS_OK(status)) {
454 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
455 (unsigned long long)session->compat->vuid,
456 nt_errstr(status)));
457 data_blob_free(&out_blob);
458 TALLOC_FREE(session);
459 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
460 return;
463 conn_clear_vuid_caches(sconn, session->compat->vuid);
465 /* current_user_info is changed on new vuid */
466 reload_services(sconn, conn_snum_used, true);
469 vuid = session->global->session_wire_id;
471 reply_outbuf(req, 4, 0);
473 SSVAL(req->outbuf, smb_uid, vuid);
474 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
475 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
476 SSVAL(req->outbuf, smb_vwv2, action);
477 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
479 if (message_push_blob(&req->outbuf, out_blob) == -1) {
480 data_blob_free(&out_blob);
481 TALLOC_FREE(session);
482 reply_nterror(req, NT_STATUS_NO_MEMORY);
483 return;
485 data_blob_free(&out_blob);
487 if (push_signature(&req->outbuf) == -1) {
488 TALLOC_FREE(session);
489 reply_nterror(req, NT_STATUS_NO_MEMORY);
490 return;
494 /****************************************************************************
495 On new VC == 0, shutdown *all* old connections and users.
496 It seems that only NT4.x does this. At W2K and above (XP etc.).
497 a new session setup with VC==0 is ignored.
498 ****************************************************************************/
500 struct shutdown_state {
501 const char *ip;
502 struct messaging_context *msg_ctx;
505 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
506 void *private_data)
508 struct shutdown_state *state = (struct shutdown_state *)private_data;
509 struct server_id self_pid = messaging_server_id(state->msg_ctx);
510 struct server_id pid = session->channels[0].server_id;
511 const char *addr = session->channels[0].remote_address;
513 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
514 server_id_str(talloc_tos(), &pid), addr));
516 if (!process_exists(pid)) {
517 DEBUG(10, ("process does not exist\n"));
518 return 0;
521 if (serverid_equal(&pid, &self_pid)) {
522 DEBUG(10, ("It's me\n"));
523 return 0;
527 * here we use strstr() because 'addr'
528 * (session->channels[0].remote_address)
529 * contains a string like:
530 * 'ipv4:127.0.0.1:48163'
532 if (strstr(addr, state->ip) == NULL) {
533 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
534 return 0;
537 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
538 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
539 state->ip));
541 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
542 &data_blob_null);
543 return 0;
546 static void setup_new_vc_session(struct smbd_server_connection *sconn)
548 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
549 "compatible we would close all old resources.\n"));
550 #if 0
551 conn_close_all();
552 invalidate_all_vuids();
553 #endif
554 if (lp_reset_on_zero_vc()) {
555 char *addr;
556 struct shutdown_state state;
558 addr = tsocket_address_inet_addr_string(
559 sconn->remote_address, talloc_tos());
560 if (addr == NULL) {
561 return;
563 state.ip = addr;
564 state.msg_ctx = sconn->msg_ctx;
565 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
566 TALLOC_FREE(addr);
570 /****************************************************************************
571 Reply to a session setup command.
572 ****************************************************************************/
574 void reply_sesssetup_and_X(struct smb_request *req)
576 uint64_t sess_vuid;
577 uint16_t smb_bufsize;
578 DATA_BLOB lm_resp;
579 DATA_BLOB nt_resp;
580 DATA_BLOB plaintext_password;
581 char *tmp;
582 const char *user;
583 fstring sub_user; /* Sanitised username for substituion */
584 const char *domain;
585 const char *native_os;
586 const char *native_lanman;
587 const char *primary_domain;
588 struct auth_usersupplied_info *user_info = NULL;
589 struct auth_session_info *session_info = NULL;
590 uint16 smb_flag2 = req->flags2;
591 uint16_t action = 0;
592 NTTIME now = timeval_to_nttime(&req->request_time);
593 struct smbXsrv_session *session = NULL;
595 NTSTATUS nt_status;
596 struct smbd_server_connection *sconn = req->sconn;
598 bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
599 bool signing_allowed = false;
600 bool signing_mandatory = false;
602 START_PROFILE(SMBsesssetupX);
604 ZERO_STRUCT(lm_resp);
605 ZERO_STRUCT(nt_resp);
606 ZERO_STRUCT(plaintext_password);
608 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
610 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
611 signing_allowed = true;
613 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
614 signing_mandatory = true;
618 * We can call srv_set_signing_negotiated() each time.
619 * It finds out when it needs to turn into a noop
620 * itself.
622 srv_set_signing_negotiated(req->sconn,
623 signing_allowed,
624 signing_mandatory);
626 /* a SPNEGO session setup has 12 command words, whereas a normal
627 NT1 session setup has 13. See the cifs spec. */
628 if (req->wct == 12 &&
629 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
631 if (!sconn->smb1.negprot.spnego) {
632 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
633 "at SPNEGO session setup when it was not "
634 "negotiated.\n"));
635 reply_nterror(req, nt_status_squash(
636 NT_STATUS_LOGON_FAILURE));
637 END_PROFILE(SMBsesssetupX);
638 return;
641 if (SVAL(req->vwv+4, 0) == 0) {
642 setup_new_vc_session(req->sconn);
645 reply_sesssetup_and_X_spnego(req);
646 END_PROFILE(SMBsesssetupX);
647 return;
650 smb_bufsize = SVAL(req->vwv+2, 0);
652 if (get_Protocol() < PROTOCOL_NT1) {
653 uint16 passlen1 = SVAL(req->vwv+7, 0);
655 /* Never do NT status codes with protocols before NT1 as we
656 * don't get client caps. */
657 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
659 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
660 reply_nterror(req, nt_status_squash(
661 NT_STATUS_INVALID_PARAMETER));
662 END_PROFILE(SMBsesssetupX);
663 return;
666 if (doencrypt) {
667 lm_resp = data_blob(req->buf, passlen1);
668 } else {
669 plaintext_password = data_blob(req->buf, passlen1+1);
670 /* Ensure null termination */
671 plaintext_password.data[passlen1] = 0;
674 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
675 req->buf + passlen1, STR_TERMINATE);
676 user = tmp ? tmp : "";
678 domain = "";
680 } else {
681 uint16 passlen1 = SVAL(req->vwv+7, 0);
682 uint16 passlen2 = SVAL(req->vwv+8, 0);
683 enum remote_arch_types ra_type = get_remote_arch();
684 const uint8_t *p = req->buf;
685 const uint8_t *save_p = req->buf;
686 uint16 byte_count;
688 if (!sconn->smb1.sessions.done_sesssetup) {
689 global_client_caps = IVAL(req->vwv+11, 0);
691 if (!(global_client_caps & CAP_STATUS32)) {
692 remove_from_common_flags2(
693 FLAGS2_32_BIT_ERROR_CODES);
696 /* client_caps is used as final determination if
697 * client is NT or Win95. This is needed to return
698 * the correct error codes in some circumstances.
701 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
702 ra_type == RA_WIN95) {
703 if(!(global_client_caps & (CAP_NT_SMBS|
704 CAP_STATUS32))) {
705 set_remote_arch( RA_WIN95);
710 if (!doencrypt) {
711 /* both Win95 and WinNT stuff up the password
712 * lengths for non-encrypting systems. Uggh.
714 if passlen1==24 its a win95 system, and its setting
715 the password length incorrectly. Luckily it still
716 works with the default code because Win95 will null
717 terminate the password anyway
719 if passlen1>0 and passlen2>0 then maybe its a NT box
720 and its setting passlen2 to some random value which
721 really stuffs things up. we need to fix that one. */
723 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
724 passlen2 != 1) {
725 passlen2 = 0;
729 /* check for nasty tricks */
730 if (passlen1 > MAX_PASS_LEN
731 || passlen1 > smbreq_bufrem(req, p)) {
732 reply_nterror(req, nt_status_squash(
733 NT_STATUS_INVALID_PARAMETER));
734 END_PROFILE(SMBsesssetupX);
735 return;
738 if (passlen2 > MAX_PASS_LEN
739 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
740 reply_nterror(req, nt_status_squash(
741 NT_STATUS_INVALID_PARAMETER));
742 END_PROFILE(SMBsesssetupX);
743 return;
746 /* Save the lanman2 password and the NT md4 password. */
748 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
749 doencrypt = False;
752 if (doencrypt) {
753 lm_resp = data_blob(p, passlen1);
754 nt_resp = data_blob(p+passlen1, passlen2);
755 } else {
756 char *pass = NULL;
757 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
759 if (unic && (passlen2 == 0) && passlen1) {
760 /* Only a ascii plaintext password was sent. */
761 (void)srvstr_pull_talloc(talloc_tos(),
762 req->inbuf,
763 req->flags2,
764 &pass,
765 req->buf,
766 passlen1,
767 STR_TERMINATE|STR_ASCII);
768 } else {
769 (void)srvstr_pull_talloc(talloc_tos(),
770 req->inbuf,
771 req->flags2,
772 &pass,
773 req->buf,
774 unic ? passlen2 : passlen1,
775 STR_TERMINATE);
777 if (!pass) {
778 reply_nterror(req, nt_status_squash(
779 NT_STATUS_INVALID_PARAMETER));
780 END_PROFILE(SMBsesssetupX);
781 return;
783 plaintext_password = data_blob(pass, strlen(pass)+1);
786 p += passlen1 + passlen2;
788 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
789 STR_TERMINATE);
790 user = tmp ? tmp : "";
792 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
793 STR_TERMINATE);
794 domain = tmp ? tmp : "";
796 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
797 STR_TERMINATE);
798 native_os = tmp ? tmp : "";
800 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
801 STR_TERMINATE);
802 native_lanman = tmp ? tmp : "";
804 /* not documented or decoded by Ethereal but there is one more
805 * string in the extra bytes which is the same as the
806 * PrimaryDomain when using extended security. Windows NT 4
807 * and 2003 use this string to store the native lanman string.
808 * Windows 9x does not include a string here at all so we have
809 * to check if we have any extra bytes left */
811 byte_count = SVAL(req->vwv+13, 0);
812 if ( PTR_DIFF(p, save_p) < byte_count) {
813 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
814 STR_TERMINATE);
815 primary_domain = tmp ? tmp : "";
816 } else {
817 primary_domain = talloc_strdup(talloc_tos(), "null");
820 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
821 "PrimaryDomain=[%s]\n",
822 domain, native_os, native_lanman, primary_domain));
824 if ( ra_type == RA_WIN2K ) {
825 if ( strlen(native_lanman) == 0 )
826 ra_lanman_string( primary_domain );
827 else
828 ra_lanman_string( native_lanman );
833 if (SVAL(req->vwv+4, 0) == 0) {
834 setup_new_vc_session(req->sconn);
837 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
838 domain, user, get_remote_machine_name()));
840 if (*user) {
841 if (sconn->smb1.negprot.spnego) {
843 /* This has to be here, because this is a perfectly
844 * valid behaviour for guest logons :-( */
846 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
847 "at 'normal' session setup after "
848 "negotiating spnego.\n"));
849 reply_nterror(req, nt_status_squash(
850 NT_STATUS_LOGON_FAILURE));
851 END_PROFILE(SMBsesssetupX);
852 return;
854 fstrcpy(sub_user, user);
855 } else {
856 fstrcpy(sub_user, "");
859 sub_set_smb_name(sub_user);
861 reload_services(sconn, conn_snum_used, true);
863 if (!*user) {
865 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
867 } else if (doencrypt) {
868 struct auth4_context *negprot_auth_context = NULL;
869 negprot_auth_context = sconn->smb1.negprot.auth_context;
870 if (!negprot_auth_context) {
871 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
872 "session setup without negprot denied!\n"));
873 reply_nterror(req, nt_status_squash(
874 NT_STATUS_LOGON_FAILURE));
875 END_PROFILE(SMBsesssetupX);
876 return;
878 nt_status = make_user_info_for_reply_enc(&user_info, user,
879 domain,
880 sconn->remote_address,
881 lm_resp, nt_resp);
882 if (NT_STATUS_IS_OK(nt_status)) {
883 nt_status = auth_check_password_session_info(negprot_auth_context,
884 req, user_info, &session_info);
886 } else {
887 struct auth4_context *plaintext_auth_context = NULL;
889 nt_status = make_auth4_context(
890 talloc_tos(), &plaintext_auth_context);
892 if (NT_STATUS_IS_OK(nt_status)) {
893 uint8_t chal[8];
895 plaintext_auth_context->get_ntlm_challenge(
896 plaintext_auth_context, chal);
898 if (!make_user_info_for_reply(&user_info,
899 user, domain,
900 sconn->remote_address,
901 chal,
902 plaintext_password)) {
903 nt_status = NT_STATUS_NO_MEMORY;
906 if (NT_STATUS_IS_OK(nt_status)) {
907 nt_status = auth_check_password_session_info(plaintext_auth_context,
908 req, user_info, &session_info);
910 TALLOC_FREE(plaintext_auth_context);
914 free_user_info(&user_info);
916 if (!NT_STATUS_IS_OK(nt_status)) {
917 data_blob_free(&nt_resp);
918 data_blob_free(&lm_resp);
919 data_blob_clear_free(&plaintext_password);
920 reply_nterror(req, nt_status_squash(nt_status));
921 END_PROFILE(SMBsesssetupX);
922 return;
925 data_blob_clear_free(&plaintext_password);
927 /* it's ok - setup a reply */
928 reply_outbuf(req, 3, 0);
929 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
930 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
932 if (get_Protocol() >= PROTOCOL_NT1) {
933 push_signature(&req->outbuf);
934 /* perhaps grab OS version here?? */
937 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
938 action = 1;
941 /* register the name and uid as being validated, so further connections
942 to a uid can get through without a password, on the same VC */
944 nt_status = smbXsrv_session_create(sconn->conn,
945 now, &session);
946 if (!NT_STATUS_IS_OK(nt_status)) {
947 data_blob_free(&nt_resp);
948 data_blob_free(&lm_resp);
949 reply_nterror(req, nt_status_squash(nt_status));
950 END_PROFILE(SMBsesssetupX);
951 return;
954 if (session_info->session_key.length > 0) {
955 uint8_t session_key[16];
958 * Note: the SMB1 signing key is not truncated to 16 byte!
960 session->global->signing_key =
961 data_blob_dup_talloc(session->global,
962 session_info->session_key);
963 if (session->global->signing_key.data == NULL) {
964 data_blob_free(&nt_resp);
965 data_blob_free(&lm_resp);
966 TALLOC_FREE(session);
967 reply_nterror(req, NT_STATUS_NO_MEMORY);
968 END_PROFILE(SMBsesssetupX);
969 return;
973 * The application key is truncated/padded to 16 bytes
975 ZERO_STRUCT(session_key);
976 memcpy(session_key, session->global->signing_key.data,
977 MIN(session->global->signing_key.length,
978 sizeof(session_key)));
979 session->global->application_key =
980 data_blob_talloc(session->global,
981 session_key,
982 sizeof(session_key));
983 ZERO_STRUCT(session_key);
984 if (session->global->application_key.data == NULL) {
985 data_blob_free(&nt_resp);
986 data_blob_free(&lm_resp);
987 TALLOC_FREE(session);
988 reply_nterror(req, NT_STATUS_NO_MEMORY);
989 END_PROFILE(SMBsesssetupX);
990 return;
994 * Place the application key into the session_info
996 data_blob_clear_free(&session_info->session_key);
997 session_info->session_key = data_blob_dup_talloc(session_info,
998 session->global->application_key);
999 if (session_info->session_key.data == NULL) {
1000 data_blob_free(&nt_resp);
1001 data_blob_free(&lm_resp);
1002 TALLOC_FREE(session);
1003 reply_nterror(req, NT_STATUS_NO_MEMORY);
1004 END_PROFILE(SMBsesssetupX);
1005 return;
1009 session->compat = talloc_zero(session, struct user_struct);
1010 if (session->compat == NULL) {
1011 data_blob_free(&nt_resp);
1012 data_blob_free(&lm_resp);
1013 TALLOC_FREE(session);
1014 reply_nterror(req, NT_STATUS_NO_MEMORY);
1015 END_PROFILE(SMBsesssetupX);
1016 return;
1018 session->compat->session = session;
1019 session->compat->homes_snum = -1;
1020 session->compat->session_info = session_info;
1021 session->compat->session_keystr = NULL;
1022 session->compat->vuid = session->global->session_wire_id;
1023 DLIST_ADD(sconn->users, session->compat);
1024 sconn->num_users++;
1026 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1027 session->compat->homes_snum =
1028 register_homes_share(session_info->unix_info->unix_name);
1031 if (srv_is_signing_negotiated(sconn) &&
1032 action == 0 &&
1033 session->global->signing_key.length > 0)
1036 * Try and turn on server signing on the first non-guest
1037 * sessionsetup.
1039 srv_set_signing(sconn,
1040 session->global->signing_key,
1041 nt_resp.data ? nt_resp : lm_resp);
1044 set_current_user_info(session_info->unix_info->sanitized_username,
1045 session_info->unix_info->unix_name,
1046 session_info->info->domain_name);
1048 session->status = NT_STATUS_OK;
1049 session->global->auth_session_info = talloc_move(session->global,
1050 &session_info);
1051 session->global->auth_session_info_seqnum += 1;
1052 session->global->channels[0].auth_session_info_seqnum =
1053 session->global->auth_session_info_seqnum;
1054 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1056 nt_status = smbXsrv_session_update(session);
1057 if (!NT_STATUS_IS_OK(nt_status)) {
1058 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1059 (unsigned long long)session->compat->vuid,
1060 nt_errstr(nt_status)));
1061 data_blob_free(&nt_resp);
1062 data_blob_free(&lm_resp);
1063 TALLOC_FREE(session);
1064 reply_nterror(req, nt_status_squash(nt_status));
1065 END_PROFILE(SMBsesssetupX);
1066 return;
1069 if (!session_claim(session)) {
1070 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1071 (unsigned long long)session->compat->vuid));
1072 data_blob_free(&nt_resp);
1073 data_blob_free(&lm_resp);
1074 TALLOC_FREE(session);
1075 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1076 END_PROFILE(SMBsesssetupX);
1077 return;
1080 /* current_user_info is changed on new vuid */
1081 reload_services(sconn, conn_snum_used, true);
1083 sess_vuid = session->global->session_wire_id;
1085 data_blob_free(&nt_resp);
1086 data_blob_free(&lm_resp);
1088 SSVAL(req->outbuf,smb_vwv2,action);
1089 SSVAL(req->outbuf,smb_uid,sess_vuid);
1090 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1091 req->vuid = sess_vuid;
1093 if (!sconn->smb1.sessions.done_sesssetup) {
1094 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1095 reply_force_doserror(req, ERRSRV, ERRerror);
1096 END_PROFILE(SMBsesssetupX);
1097 return;
1099 sconn->smb1.sessions.max_send = smb_bufsize;
1100 sconn->smb1.sessions.done_sesssetup = true;
1103 END_PROFILE(SMBsesssetupX);