s3:smbd: remember the time of the session setup auth_time
[Samba.git] / source3 / smbd / sesssetup.c
blobf00a55c2dfaa5563cb96288006301a35217dd619
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(talloc_tos(), 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 TALLOC_FREE(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 uint16 data_blob_len = SVAL(req->vwv+7, 0);
131 enum remote_arch_types ra_type = get_remote_arch();
132 uint64_t vuid = req->vuid;
133 NTSTATUS status = NT_STATUS_OK;
134 struct smbXsrv_connection *xconn = req->xconn;
135 struct smbd_server_connection *sconn = xconn->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 (!xconn->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 p = req->buf + in_blob.length;
170 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
171 STR_TERMINATE);
172 native_os = tmp ? tmp : "";
174 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
175 STR_TERMINATE);
176 native_lanman = tmp ? tmp : "";
178 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
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(xconn,
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(xconn,
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, xconn->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(),
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(xconn) &&
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(xconn,
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 session->global->auth_time = now;
358 if (client_caps & CAP_DYNAMIC_REAUTH) {
359 session->global->expiration_time =
360 gensec_expire_time(session->gensec);
361 } else {
362 session->global->expiration_time =
363 GENSEC_EXPIRE_TIME_INFINITY;
366 if (!session_claim(session)) {
367 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
368 (unsigned long long)session->compat->vuid));
369 data_blob_free(&out_blob);
370 TALLOC_FREE(session);
371 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
372 return;
375 status = smbXsrv_session_update(session);
376 if (!NT_STATUS_IS_OK(status)) {
377 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
378 (unsigned long long)session->compat->vuid,
379 nt_errstr(status)));
380 data_blob_free(&out_blob);
381 TALLOC_FREE(session);
382 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
383 return;
386 if (!xconn->smb1.sessions.done_sesssetup) {
387 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
388 reply_force_doserror(req, ERRSRV, ERRerror);
389 return;
391 xconn->smb1.sessions.max_send = smb_bufsize;
392 xconn->smb1.sessions.done_sesssetup = true;
395 /* current_user_info is changed on new vuid */
396 reload_services(sconn, conn_snum_used, true);
397 } else if (NT_STATUS_IS_OK(status)) {
398 struct auth_session_info *session_info = NULL;
400 status = gensec_session_info(session->gensec,
401 session,
402 &session_info);
403 if (!NT_STATUS_IS_OK(status)) {
404 DEBUG(1,("Failed to generate session_info "
405 "(user and group token) for session setup: %s\n",
406 nt_errstr(status)));
407 data_blob_free(&out_blob);
408 TALLOC_FREE(session);
409 reply_nterror(req, nt_status_squash(status));
410 return;
413 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
414 action = 1;
418 * Keep the application key
420 data_blob_clear_free(&session_info->session_key);
421 session_info->session_key =
422 session->global->auth_session_info->session_key;
423 talloc_steal(session_info, session_info->session_key.data);
424 TALLOC_FREE(session->global->auth_session_info);
426 session->compat->session_info = session_info;
428 session->compat->vuid = session->global->session_wire_id;
430 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
431 session->compat->homes_snum =
432 register_homes_share(session_info->unix_info->unix_name);
435 set_current_user_info(session_info->unix_info->sanitized_username,
436 session_info->unix_info->unix_name,
437 session_info->info->domain_name);
439 session->status = NT_STATUS_OK;
440 session->global->auth_session_info = talloc_move(session->global,
441 &session_info);
442 session->global->auth_session_info_seqnum += 1;
443 session->global->channels[0].auth_session_info_seqnum =
444 session->global->auth_session_info_seqnum;
445 session->global->auth_time = now;
446 if (client_caps & CAP_DYNAMIC_REAUTH) {
447 session->global->expiration_time =
448 gensec_expire_time(session->gensec);
449 } else {
450 session->global->expiration_time =
451 GENSEC_EXPIRE_TIME_INFINITY;
454 status = smbXsrv_session_update(session);
455 if (!NT_STATUS_IS_OK(status)) {
456 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
457 (unsigned long long)session->compat->vuid,
458 nt_errstr(status)));
459 data_blob_free(&out_blob);
460 TALLOC_FREE(session);
461 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
462 return;
465 conn_clear_vuid_caches(sconn, session->compat->vuid);
467 /* current_user_info is changed on new vuid */
468 reload_services(sconn, conn_snum_used, true);
471 vuid = session->global->session_wire_id;
473 reply_outbuf(req, 4, 0);
475 SSVAL(req->outbuf, smb_uid, vuid);
476 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
477 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
478 SSVAL(req->outbuf, smb_vwv2, action);
479 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
481 if (message_push_blob(&req->outbuf, out_blob) == -1) {
482 data_blob_free(&out_blob);
483 TALLOC_FREE(session);
484 reply_nterror(req, NT_STATUS_NO_MEMORY);
485 return;
487 data_blob_free(&out_blob);
489 if (push_signature(&req->outbuf) == -1) {
490 TALLOC_FREE(session);
491 reply_nterror(req, NT_STATUS_NO_MEMORY);
492 return;
496 /****************************************************************************
497 On new VC == 0, shutdown *all* old connections and users.
498 It seems that only NT4.x does this. At W2K and above (XP etc.).
499 a new session setup with VC==0 is ignored.
500 ****************************************************************************/
502 struct shutdown_state {
503 const char *ip;
504 struct messaging_context *msg_ctx;
507 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
508 void *private_data)
510 struct shutdown_state *state = (struct shutdown_state *)private_data;
511 struct server_id self_pid = messaging_server_id(state->msg_ctx);
512 struct server_id pid = session->channels[0].server_id;
513 const char *addr = session->channels[0].remote_address;
515 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
516 server_id_str(talloc_tos(), &pid), addr));
518 if (!process_exists(pid)) {
519 DEBUG(10, ("process does not exist\n"));
520 return 0;
523 if (serverid_equal(&pid, &self_pid)) {
524 DEBUG(10, ("It's me\n"));
525 return 0;
529 * here we use strstr() because 'addr'
530 * (session->channels[0].remote_address)
531 * contains a string like:
532 * 'ipv4:127.0.0.1:48163'
534 if (strstr(addr, state->ip) == NULL) {
535 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
536 return 0;
539 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
540 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
541 state->ip));
543 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
544 &data_blob_null);
545 return 0;
548 static void setup_new_vc_session(struct smbd_server_connection *sconn)
550 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
551 "compatible we would close all old resources.\n"));
552 #if 0
553 conn_close_all();
554 invalidate_all_vuids();
555 #endif
556 if (lp_reset_on_zero_vc()) {
557 char *addr;
558 struct shutdown_state state;
560 addr = tsocket_address_inet_addr_string(
561 sconn->remote_address, talloc_tos());
562 if (addr == NULL) {
563 return;
565 state.ip = addr;
566 state.msg_ctx = sconn->msg_ctx;
567 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
568 TALLOC_FREE(addr);
572 /****************************************************************************
573 Reply to a session setup command.
574 ****************************************************************************/
576 void reply_sesssetup_and_X(struct smb_request *req)
578 uint64_t sess_vuid;
579 uint16_t smb_bufsize;
580 DATA_BLOB lm_resp;
581 DATA_BLOB nt_resp;
582 DATA_BLOB plaintext_password;
583 char *tmp;
584 const char *user;
585 fstring sub_user; /* Sanitised username for substituion */
586 const char *domain;
587 const char *native_os;
588 const char *native_lanman;
589 const char *primary_domain;
590 struct auth_usersupplied_info *user_info = NULL;
591 struct auth_session_info *session_info = NULL;
592 uint16 smb_flag2 = req->flags2;
593 uint16_t action = 0;
594 NTTIME now = timeval_to_nttime(&req->request_time);
595 struct smbXsrv_session *session = NULL;
596 NTSTATUS nt_status;
597 struct smbXsrv_connection *xconn = req->xconn;
598 struct smbd_server_connection *sconn = xconn->sconn;
599 bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
600 bool signing_allowed = false;
601 bool signing_mandatory = false;
603 START_PROFILE(SMBsesssetupX);
605 ZERO_STRUCT(lm_resp);
606 ZERO_STRUCT(nt_resp);
607 ZERO_STRUCT(plaintext_password);
609 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
611 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
612 signing_allowed = true;
614 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
615 signing_mandatory = true;
619 * We can call srv_set_signing_negotiated() each time.
620 * It finds out when it needs to turn into a noop
621 * itself.
623 srv_set_signing_negotiated(xconn,
624 signing_allowed,
625 signing_mandatory);
627 /* a SPNEGO session setup has 12 command words, whereas a normal
628 NT1 session setup has 13. See the cifs spec. */
629 if (req->wct == 12 &&
630 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
632 if (!xconn->smb1.negprot.spnego) {
633 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
634 "at SPNEGO session setup when it was not "
635 "negotiated.\n"));
636 reply_nterror(req, nt_status_squash(
637 NT_STATUS_LOGON_FAILURE));
638 END_PROFILE(SMBsesssetupX);
639 return;
642 if (SVAL(req->vwv+4, 0) == 0) {
643 setup_new_vc_session(req->sconn);
646 reply_sesssetup_and_X_spnego(req);
647 END_PROFILE(SMBsesssetupX);
648 return;
651 smb_bufsize = SVAL(req->vwv+2, 0);
653 if (get_Protocol() < PROTOCOL_NT1) {
654 uint16 passlen1 = SVAL(req->vwv+7, 0);
656 /* Never do NT status codes with protocols before NT1 as we
657 * don't get client caps. */
658 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
660 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
661 reply_nterror(req, nt_status_squash(
662 NT_STATUS_INVALID_PARAMETER));
663 END_PROFILE(SMBsesssetupX);
664 return;
667 if (doencrypt) {
668 lm_resp = data_blob(req->buf, passlen1);
669 } else {
670 plaintext_password = data_blob(req->buf, passlen1+1);
671 /* Ensure null termination */
672 plaintext_password.data[passlen1] = 0;
675 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
676 req->buf + passlen1, STR_TERMINATE);
677 user = tmp ? tmp : "";
679 domain = "";
681 } else {
682 uint16 passlen1 = SVAL(req->vwv+7, 0);
683 uint16 passlen2 = SVAL(req->vwv+8, 0);
684 enum remote_arch_types ra_type = get_remote_arch();
685 const uint8_t *p = req->buf;
686 const uint8_t *save_p = req->buf;
687 uint16 byte_count;
689 if (!xconn->smb1.sessions.done_sesssetup) {
690 global_client_caps = IVAL(req->vwv+11, 0);
692 if (!(global_client_caps & CAP_STATUS32)) {
693 remove_from_common_flags2(
694 FLAGS2_32_BIT_ERROR_CODES);
697 /* client_caps is used as final determination if
698 * client is NT or Win95. This is needed to return
699 * the correct error codes in some circumstances.
702 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
703 ra_type == RA_WIN95) {
704 if(!(global_client_caps & (CAP_NT_SMBS|
705 CAP_STATUS32))) {
706 set_remote_arch( RA_WIN95);
711 if (!doencrypt) {
712 /* both Win95 and WinNT stuff up the password
713 * lengths for non-encrypting systems. Uggh.
715 if passlen1==24 its a win95 system, and its setting
716 the password length incorrectly. Luckily it still
717 works with the default code because Win95 will null
718 terminate the password anyway
720 if passlen1>0 and passlen2>0 then maybe its a NT box
721 and its setting passlen2 to some random value which
722 really stuffs things up. we need to fix that one. */
724 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
725 passlen2 != 1) {
726 passlen2 = 0;
730 /* check for nasty tricks */
731 if (passlen1 > MAX_PASS_LEN
732 || passlen1 > smbreq_bufrem(req, p)) {
733 reply_nterror(req, nt_status_squash(
734 NT_STATUS_INVALID_PARAMETER));
735 END_PROFILE(SMBsesssetupX);
736 return;
739 if (passlen2 > MAX_PASS_LEN
740 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
741 reply_nterror(req, nt_status_squash(
742 NT_STATUS_INVALID_PARAMETER));
743 END_PROFILE(SMBsesssetupX);
744 return;
747 /* Save the lanman2 password and the NT md4 password. */
749 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
750 doencrypt = False;
753 if (doencrypt) {
754 lm_resp = data_blob(p, passlen1);
755 nt_resp = data_blob(p+passlen1, passlen2);
756 } else {
757 char *pass = NULL;
758 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
760 if (unic && (passlen2 == 0) && passlen1) {
761 /* Only a ascii plaintext password was sent. */
762 (void)srvstr_pull_talloc(talloc_tos(),
763 req->inbuf,
764 req->flags2,
765 &pass,
766 req->buf,
767 passlen1,
768 STR_TERMINATE|STR_ASCII);
769 } else {
770 (void)srvstr_pull_talloc(talloc_tos(),
771 req->inbuf,
772 req->flags2,
773 &pass,
774 req->buf,
775 unic ? passlen2 : passlen1,
776 STR_TERMINATE);
778 if (!pass) {
779 reply_nterror(req, nt_status_squash(
780 NT_STATUS_INVALID_PARAMETER));
781 END_PROFILE(SMBsesssetupX);
782 return;
784 plaintext_password = data_blob(pass, strlen(pass)+1);
787 p += passlen1 + passlen2;
789 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
790 STR_TERMINATE);
791 user = tmp ? tmp : "";
793 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
794 STR_TERMINATE);
795 domain = tmp ? tmp : "";
797 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
798 STR_TERMINATE);
799 native_os = tmp ? tmp : "";
801 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
802 STR_TERMINATE);
803 native_lanman = tmp ? tmp : "";
805 /* not documented or decoded by Ethereal but there is one more
806 * string in the extra bytes which is the same as the
807 * PrimaryDomain when using extended security. Windows NT 4
808 * and 2003 use this string to store the native lanman string.
809 * Windows 9x does not include a string here at all so we have
810 * to check if we have any extra bytes left */
812 byte_count = SVAL(req->vwv+13, 0);
813 if ( PTR_DIFF(p, save_p) < byte_count) {
814 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
815 STR_TERMINATE);
816 primary_domain = tmp ? tmp : "";
817 } else {
818 primary_domain = talloc_strdup(talloc_tos(), "null");
821 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
822 "PrimaryDomain=[%s]\n",
823 domain, native_os, native_lanman, primary_domain));
825 if ( ra_type == RA_WIN2K ) {
826 if ( strlen(native_lanman) == 0 )
827 ra_lanman_string( primary_domain );
828 else
829 ra_lanman_string( native_lanman );
834 if (SVAL(req->vwv+4, 0) == 0) {
835 setup_new_vc_session(req->sconn);
838 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
839 domain, user, get_remote_machine_name()));
841 if (*user) {
842 if (xconn->smb1.negprot.spnego) {
844 /* This has to be here, because this is a perfectly
845 * valid behaviour for guest logons :-( */
847 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
848 "at 'normal' session setup after "
849 "negotiating spnego.\n"));
850 reply_nterror(req, nt_status_squash(
851 NT_STATUS_LOGON_FAILURE));
852 END_PROFILE(SMBsesssetupX);
853 return;
855 fstrcpy(sub_user, user);
856 } else {
857 fstrcpy(sub_user, "");
860 sub_set_smb_name(sub_user);
862 reload_services(sconn, conn_snum_used, true);
864 if (!*user) {
866 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
868 } else if (doencrypt) {
869 struct auth4_context *negprot_auth_context = NULL;
870 negprot_auth_context = xconn->smb1.negprot.auth_context;
871 if (!negprot_auth_context) {
872 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
873 "session setup without negprot denied!\n"));
874 reply_nterror(req, nt_status_squash(
875 NT_STATUS_LOGON_FAILURE));
876 END_PROFILE(SMBsesssetupX);
877 return;
879 nt_status = make_user_info_for_reply_enc(talloc_tos(),
880 &user_info, user,
881 domain,
882 sconn->remote_address,
883 lm_resp, nt_resp);
884 if (NT_STATUS_IS_OK(nt_status)) {
885 nt_status = auth_check_password_session_info(negprot_auth_context,
886 req, user_info, &session_info);
888 } else {
889 struct auth4_context *plaintext_auth_context = NULL;
891 nt_status = make_auth4_context(
892 talloc_tos(), &plaintext_auth_context);
894 if (NT_STATUS_IS_OK(nt_status)) {
895 uint8_t chal[8];
897 plaintext_auth_context->get_ntlm_challenge(
898 plaintext_auth_context, chal);
900 if (!make_user_info_for_reply(talloc_tos(),
901 &user_info,
902 user, domain,
903 sconn->remote_address,
904 chal,
905 plaintext_password)) {
906 nt_status = NT_STATUS_NO_MEMORY;
909 if (NT_STATUS_IS_OK(nt_status)) {
910 nt_status = auth_check_password_session_info(plaintext_auth_context,
911 req, user_info, &session_info);
913 TALLOC_FREE(plaintext_auth_context);
917 TALLOC_FREE(user_info);
919 if (!NT_STATUS_IS_OK(nt_status)) {
920 data_blob_free(&nt_resp);
921 data_blob_free(&lm_resp);
922 data_blob_clear_free(&plaintext_password);
923 reply_nterror(req, nt_status_squash(nt_status));
924 END_PROFILE(SMBsesssetupX);
925 return;
928 data_blob_clear_free(&plaintext_password);
930 /* it's ok - setup a reply */
931 reply_outbuf(req, 3, 0);
932 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
933 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
935 if (get_Protocol() >= PROTOCOL_NT1) {
936 push_signature(&req->outbuf);
937 /* perhaps grab OS version here?? */
940 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
941 action = 1;
944 /* register the name and uid as being validated, so further connections
945 to a uid can get through without a password, on the same VC */
947 nt_status = smbXsrv_session_create(xconn,
948 now, &session);
949 if (!NT_STATUS_IS_OK(nt_status)) {
950 data_blob_free(&nt_resp);
951 data_blob_free(&lm_resp);
952 reply_nterror(req, nt_status_squash(nt_status));
953 END_PROFILE(SMBsesssetupX);
954 return;
957 if (session_info->session_key.length > 0) {
958 uint8_t session_key[16];
961 * Note: the SMB1 signing key is not truncated to 16 byte!
963 session->global->signing_key =
964 data_blob_dup_talloc(session->global,
965 session_info->session_key);
966 if (session->global->signing_key.data == NULL) {
967 data_blob_free(&nt_resp);
968 data_blob_free(&lm_resp);
969 TALLOC_FREE(session);
970 reply_nterror(req, NT_STATUS_NO_MEMORY);
971 END_PROFILE(SMBsesssetupX);
972 return;
976 * The application key is truncated/padded to 16 bytes
978 ZERO_STRUCT(session_key);
979 memcpy(session_key, session->global->signing_key.data,
980 MIN(session->global->signing_key.length,
981 sizeof(session_key)));
982 session->global->application_key =
983 data_blob_talloc(session->global,
984 session_key,
985 sizeof(session_key));
986 ZERO_STRUCT(session_key);
987 if (session->global->application_key.data == NULL) {
988 data_blob_free(&nt_resp);
989 data_blob_free(&lm_resp);
990 TALLOC_FREE(session);
991 reply_nterror(req, NT_STATUS_NO_MEMORY);
992 END_PROFILE(SMBsesssetupX);
993 return;
997 * Place the application key into the session_info
999 data_blob_clear_free(&session_info->session_key);
1000 session_info->session_key = data_blob_dup_talloc(session_info,
1001 session->global->application_key);
1002 if (session_info->session_key.data == NULL) {
1003 data_blob_free(&nt_resp);
1004 data_blob_free(&lm_resp);
1005 TALLOC_FREE(session);
1006 reply_nterror(req, NT_STATUS_NO_MEMORY);
1007 END_PROFILE(SMBsesssetupX);
1008 return;
1012 session->compat = talloc_zero(session, struct user_struct);
1013 if (session->compat == NULL) {
1014 data_blob_free(&nt_resp);
1015 data_blob_free(&lm_resp);
1016 TALLOC_FREE(session);
1017 reply_nterror(req, NT_STATUS_NO_MEMORY);
1018 END_PROFILE(SMBsesssetupX);
1019 return;
1021 session->compat->session = session;
1022 session->compat->homes_snum = -1;
1023 session->compat->session_info = session_info;
1024 session->compat->session_keystr = NULL;
1025 session->compat->vuid = session->global->session_wire_id;
1026 DLIST_ADD(sconn->users, session->compat);
1027 sconn->num_users++;
1029 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1030 session->compat->homes_snum =
1031 register_homes_share(session_info->unix_info->unix_name);
1034 if (srv_is_signing_negotiated(xconn) &&
1035 action == 0 &&
1036 session->global->signing_key.length > 0)
1039 * Try and turn on server signing on the first non-guest
1040 * sessionsetup.
1042 srv_set_signing(xconn,
1043 session->global->signing_key,
1044 nt_resp.data ? nt_resp : lm_resp);
1047 set_current_user_info(session_info->unix_info->sanitized_username,
1048 session_info->unix_info->unix_name,
1049 session_info->info->domain_name);
1051 session->status = NT_STATUS_OK;
1052 session->global->auth_session_info = talloc_move(session->global,
1053 &session_info);
1054 session->global->auth_session_info_seqnum += 1;
1055 session->global->channels[0].auth_session_info_seqnum =
1056 session->global->auth_session_info_seqnum;
1057 session->global->auth_time = now;
1058 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1060 nt_status = smbXsrv_session_update(session);
1061 if (!NT_STATUS_IS_OK(nt_status)) {
1062 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1063 (unsigned long long)session->compat->vuid,
1064 nt_errstr(nt_status)));
1065 data_blob_free(&nt_resp);
1066 data_blob_free(&lm_resp);
1067 TALLOC_FREE(session);
1068 reply_nterror(req, nt_status_squash(nt_status));
1069 END_PROFILE(SMBsesssetupX);
1070 return;
1073 if (!session_claim(session)) {
1074 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1075 (unsigned long long)session->compat->vuid));
1076 data_blob_free(&nt_resp);
1077 data_blob_free(&lm_resp);
1078 TALLOC_FREE(session);
1079 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1080 END_PROFILE(SMBsesssetupX);
1081 return;
1084 /* current_user_info is changed on new vuid */
1085 reload_services(sconn, conn_snum_used, true);
1087 sess_vuid = session->global->session_wire_id;
1089 data_blob_free(&nt_resp);
1090 data_blob_free(&lm_resp);
1092 SSVAL(req->outbuf,smb_vwv2,action);
1093 SSVAL(req->outbuf,smb_uid,sess_vuid);
1094 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1095 req->vuid = sess_vuid;
1097 if (!xconn->smb1.sessions.done_sesssetup) {
1098 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1099 reply_force_doserror(req, ERRSRV, ERRerror);
1100 END_PROFILE(SMBsesssetupX);
1101 return;
1103 xconn->smb1.sessions.max_send = smb_bufsize;
1104 xconn->smb1.sessions.done_sesssetup = true;
1107 END_PROFILE(SMBsesssetupX);