s3:smbd: move sconn->smb1.signing_state to xconn->smb1.signing_state
[Samba.git] / source3 / smbd / sesssetup.c
blob43be24a889d494aefbef374e63495241158ed3c9
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 smbd_server_connection *sconn = req->sconn;
135 struct smbXsrv_connection *xconn = sconn->conn;
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(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(),
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 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 (!xconn->smb1.sessions.done_sesssetup) {
386 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
387 reply_force_doserror(req, ERRSRV, ERRerror);
388 return;
390 xconn->smb1.sessions.max_send = smb_bufsize;
391 xconn->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;
594 NTSTATUS nt_status;
595 struct smbd_server_connection *sconn = req->sconn;
596 struct smbXsrv_connection *xconn = sconn->conn;
597 bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
598 bool signing_allowed = false;
599 bool signing_mandatory = false;
601 START_PROFILE(SMBsesssetupX);
603 ZERO_STRUCT(lm_resp);
604 ZERO_STRUCT(nt_resp);
605 ZERO_STRUCT(plaintext_password);
607 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
609 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
610 signing_allowed = true;
612 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
613 signing_mandatory = true;
617 * We can call srv_set_signing_negotiated() each time.
618 * It finds out when it needs to turn into a noop
619 * itself.
621 srv_set_signing_negotiated(xconn,
622 signing_allowed,
623 signing_mandatory);
625 /* a SPNEGO session setup has 12 command words, whereas a normal
626 NT1 session setup has 13. See the cifs spec. */
627 if (req->wct == 12 &&
628 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
630 if (!xconn->smb1.negprot.spnego) {
631 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
632 "at SPNEGO session setup when it was not "
633 "negotiated.\n"));
634 reply_nterror(req, nt_status_squash(
635 NT_STATUS_LOGON_FAILURE));
636 END_PROFILE(SMBsesssetupX);
637 return;
640 if (SVAL(req->vwv+4, 0) == 0) {
641 setup_new_vc_session(req->sconn);
644 reply_sesssetup_and_X_spnego(req);
645 END_PROFILE(SMBsesssetupX);
646 return;
649 smb_bufsize = SVAL(req->vwv+2, 0);
651 if (get_Protocol() < PROTOCOL_NT1) {
652 uint16 passlen1 = SVAL(req->vwv+7, 0);
654 /* Never do NT status codes with protocols before NT1 as we
655 * don't get client caps. */
656 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
658 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
659 reply_nterror(req, nt_status_squash(
660 NT_STATUS_INVALID_PARAMETER));
661 END_PROFILE(SMBsesssetupX);
662 return;
665 if (doencrypt) {
666 lm_resp = data_blob(req->buf, passlen1);
667 } else {
668 plaintext_password = data_blob(req->buf, passlen1+1);
669 /* Ensure null termination */
670 plaintext_password.data[passlen1] = 0;
673 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
674 req->buf + passlen1, STR_TERMINATE);
675 user = tmp ? tmp : "";
677 domain = "";
679 } else {
680 uint16 passlen1 = SVAL(req->vwv+7, 0);
681 uint16 passlen2 = SVAL(req->vwv+8, 0);
682 enum remote_arch_types ra_type = get_remote_arch();
683 const uint8_t *p = req->buf;
684 const uint8_t *save_p = req->buf;
685 uint16 byte_count;
687 if (!xconn->smb1.sessions.done_sesssetup) {
688 global_client_caps = IVAL(req->vwv+11, 0);
690 if (!(global_client_caps & CAP_STATUS32)) {
691 remove_from_common_flags2(
692 FLAGS2_32_BIT_ERROR_CODES);
695 /* client_caps is used as final determination if
696 * client is NT or Win95. This is needed to return
697 * the correct error codes in some circumstances.
700 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
701 ra_type == RA_WIN95) {
702 if(!(global_client_caps & (CAP_NT_SMBS|
703 CAP_STATUS32))) {
704 set_remote_arch( RA_WIN95);
709 if (!doencrypt) {
710 /* both Win95 and WinNT stuff up the password
711 * lengths for non-encrypting systems. Uggh.
713 if passlen1==24 its a win95 system, and its setting
714 the password length incorrectly. Luckily it still
715 works with the default code because Win95 will null
716 terminate the password anyway
718 if passlen1>0 and passlen2>0 then maybe its a NT box
719 and its setting passlen2 to some random value which
720 really stuffs things up. we need to fix that one. */
722 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
723 passlen2 != 1) {
724 passlen2 = 0;
728 /* check for nasty tricks */
729 if (passlen1 > MAX_PASS_LEN
730 || passlen1 > smbreq_bufrem(req, p)) {
731 reply_nterror(req, nt_status_squash(
732 NT_STATUS_INVALID_PARAMETER));
733 END_PROFILE(SMBsesssetupX);
734 return;
737 if (passlen2 > MAX_PASS_LEN
738 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
739 reply_nterror(req, nt_status_squash(
740 NT_STATUS_INVALID_PARAMETER));
741 END_PROFILE(SMBsesssetupX);
742 return;
745 /* Save the lanman2 password and the NT md4 password. */
747 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
748 doencrypt = False;
751 if (doencrypt) {
752 lm_resp = data_blob(p, passlen1);
753 nt_resp = data_blob(p+passlen1, passlen2);
754 } else {
755 char *pass = NULL;
756 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
758 if (unic && (passlen2 == 0) && passlen1) {
759 /* Only a ascii plaintext password was sent. */
760 (void)srvstr_pull_talloc(talloc_tos(),
761 req->inbuf,
762 req->flags2,
763 &pass,
764 req->buf,
765 passlen1,
766 STR_TERMINATE|STR_ASCII);
767 } else {
768 (void)srvstr_pull_talloc(talloc_tos(),
769 req->inbuf,
770 req->flags2,
771 &pass,
772 req->buf,
773 unic ? passlen2 : passlen1,
774 STR_TERMINATE);
776 if (!pass) {
777 reply_nterror(req, nt_status_squash(
778 NT_STATUS_INVALID_PARAMETER));
779 END_PROFILE(SMBsesssetupX);
780 return;
782 plaintext_password = data_blob(pass, strlen(pass)+1);
785 p += passlen1 + passlen2;
787 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
788 STR_TERMINATE);
789 user = tmp ? tmp : "";
791 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
792 STR_TERMINATE);
793 domain = tmp ? tmp : "";
795 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
796 STR_TERMINATE);
797 native_os = tmp ? tmp : "";
799 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
800 STR_TERMINATE);
801 native_lanman = tmp ? tmp : "";
803 /* not documented or decoded by Ethereal but there is one more
804 * string in the extra bytes which is the same as the
805 * PrimaryDomain when using extended security. Windows NT 4
806 * and 2003 use this string to store the native lanman string.
807 * Windows 9x does not include a string here at all so we have
808 * to check if we have any extra bytes left */
810 byte_count = SVAL(req->vwv+13, 0);
811 if ( PTR_DIFF(p, save_p) < byte_count) {
812 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
813 STR_TERMINATE);
814 primary_domain = tmp ? tmp : "";
815 } else {
816 primary_domain = talloc_strdup(talloc_tos(), "null");
819 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
820 "PrimaryDomain=[%s]\n",
821 domain, native_os, native_lanman, primary_domain));
823 if ( ra_type == RA_WIN2K ) {
824 if ( strlen(native_lanman) == 0 )
825 ra_lanman_string( primary_domain );
826 else
827 ra_lanman_string( native_lanman );
832 if (SVAL(req->vwv+4, 0) == 0) {
833 setup_new_vc_session(req->sconn);
836 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
837 domain, user, get_remote_machine_name()));
839 if (*user) {
840 if (xconn->smb1.negprot.spnego) {
842 /* This has to be here, because this is a perfectly
843 * valid behaviour for guest logons :-( */
845 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
846 "at 'normal' session setup after "
847 "negotiating spnego.\n"));
848 reply_nterror(req, nt_status_squash(
849 NT_STATUS_LOGON_FAILURE));
850 END_PROFILE(SMBsesssetupX);
851 return;
853 fstrcpy(sub_user, user);
854 } else {
855 fstrcpy(sub_user, "");
858 sub_set_smb_name(sub_user);
860 reload_services(sconn, conn_snum_used, true);
862 if (!*user) {
864 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
866 } else if (doencrypt) {
867 struct auth4_context *negprot_auth_context = NULL;
868 negprot_auth_context = xconn->smb1.negprot.auth_context;
869 if (!negprot_auth_context) {
870 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
871 "session setup without negprot denied!\n"));
872 reply_nterror(req, nt_status_squash(
873 NT_STATUS_LOGON_FAILURE));
874 END_PROFILE(SMBsesssetupX);
875 return;
877 nt_status = make_user_info_for_reply_enc(talloc_tos(),
878 &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(talloc_tos(),
899 &user_info,
900 user, domain,
901 sconn->remote_address,
902 chal,
903 plaintext_password)) {
904 nt_status = NT_STATUS_NO_MEMORY;
907 if (NT_STATUS_IS_OK(nt_status)) {
908 nt_status = auth_check_password_session_info(plaintext_auth_context,
909 req, user_info, &session_info);
911 TALLOC_FREE(plaintext_auth_context);
915 TALLOC_FREE(user_info);
917 if (!NT_STATUS_IS_OK(nt_status)) {
918 data_blob_free(&nt_resp);
919 data_blob_free(&lm_resp);
920 data_blob_clear_free(&plaintext_password);
921 reply_nterror(req, nt_status_squash(nt_status));
922 END_PROFILE(SMBsesssetupX);
923 return;
926 data_blob_clear_free(&plaintext_password);
928 /* it's ok - setup a reply */
929 reply_outbuf(req, 3, 0);
930 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
931 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
933 if (get_Protocol() >= PROTOCOL_NT1) {
934 push_signature(&req->outbuf);
935 /* perhaps grab OS version here?? */
938 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
939 action = 1;
942 /* register the name and uid as being validated, so further connections
943 to a uid can get through without a password, on the same VC */
945 nt_status = smbXsrv_session_create(sconn->conn,
946 now, &session);
947 if (!NT_STATUS_IS_OK(nt_status)) {
948 data_blob_free(&nt_resp);
949 data_blob_free(&lm_resp);
950 reply_nterror(req, nt_status_squash(nt_status));
951 END_PROFILE(SMBsesssetupX);
952 return;
955 if (session_info->session_key.length > 0) {
956 uint8_t session_key[16];
959 * Note: the SMB1 signing key is not truncated to 16 byte!
961 session->global->signing_key =
962 data_blob_dup_talloc(session->global,
963 session_info->session_key);
964 if (session->global->signing_key.data == NULL) {
965 data_blob_free(&nt_resp);
966 data_blob_free(&lm_resp);
967 TALLOC_FREE(session);
968 reply_nterror(req, NT_STATUS_NO_MEMORY);
969 END_PROFILE(SMBsesssetupX);
970 return;
974 * The application key is truncated/padded to 16 bytes
976 ZERO_STRUCT(session_key);
977 memcpy(session_key, session->global->signing_key.data,
978 MIN(session->global->signing_key.length,
979 sizeof(session_key)));
980 session->global->application_key =
981 data_blob_talloc(session->global,
982 session_key,
983 sizeof(session_key));
984 ZERO_STRUCT(session_key);
985 if (session->global->application_key.data == NULL) {
986 data_blob_free(&nt_resp);
987 data_blob_free(&lm_resp);
988 TALLOC_FREE(session);
989 reply_nterror(req, NT_STATUS_NO_MEMORY);
990 END_PROFILE(SMBsesssetupX);
991 return;
995 * Place the application key into the session_info
997 data_blob_clear_free(&session_info->session_key);
998 session_info->session_key = data_blob_dup_talloc(session_info,
999 session->global->application_key);
1000 if (session_info->session_key.data == NULL) {
1001 data_blob_free(&nt_resp);
1002 data_blob_free(&lm_resp);
1003 TALLOC_FREE(session);
1004 reply_nterror(req, NT_STATUS_NO_MEMORY);
1005 END_PROFILE(SMBsesssetupX);
1006 return;
1010 session->compat = talloc_zero(session, struct user_struct);
1011 if (session->compat == NULL) {
1012 data_blob_free(&nt_resp);
1013 data_blob_free(&lm_resp);
1014 TALLOC_FREE(session);
1015 reply_nterror(req, NT_STATUS_NO_MEMORY);
1016 END_PROFILE(SMBsesssetupX);
1017 return;
1019 session->compat->session = session;
1020 session->compat->homes_snum = -1;
1021 session->compat->session_info = session_info;
1022 session->compat->session_keystr = NULL;
1023 session->compat->vuid = session->global->session_wire_id;
1024 DLIST_ADD(sconn->users, session->compat);
1025 sconn->num_users++;
1027 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1028 session->compat->homes_snum =
1029 register_homes_share(session_info->unix_info->unix_name);
1032 if (srv_is_signing_negotiated(xconn) &&
1033 action == 0 &&
1034 session->global->signing_key.length > 0)
1037 * Try and turn on server signing on the first non-guest
1038 * sessionsetup.
1040 srv_set_signing(xconn,
1041 session->global->signing_key,
1042 nt_resp.data ? nt_resp : lm_resp);
1045 set_current_user_info(session_info->unix_info->sanitized_username,
1046 session_info->unix_info->unix_name,
1047 session_info->info->domain_name);
1049 session->status = NT_STATUS_OK;
1050 session->global->auth_session_info = talloc_move(session->global,
1051 &session_info);
1052 session->global->auth_session_info_seqnum += 1;
1053 session->global->channels[0].auth_session_info_seqnum =
1054 session->global->auth_session_info_seqnum;
1055 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1057 nt_status = smbXsrv_session_update(session);
1058 if (!NT_STATUS_IS_OK(nt_status)) {
1059 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1060 (unsigned long long)session->compat->vuid,
1061 nt_errstr(nt_status)));
1062 data_blob_free(&nt_resp);
1063 data_blob_free(&lm_resp);
1064 TALLOC_FREE(session);
1065 reply_nterror(req, nt_status_squash(nt_status));
1066 END_PROFILE(SMBsesssetupX);
1067 return;
1070 if (!session_claim(session)) {
1071 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1072 (unsigned long long)session->compat->vuid));
1073 data_blob_free(&nt_resp);
1074 data_blob_free(&lm_resp);
1075 TALLOC_FREE(session);
1076 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1077 END_PROFILE(SMBsesssetupX);
1078 return;
1081 /* current_user_info is changed on new vuid */
1082 reload_services(sconn, conn_snum_used, true);
1084 sess_vuid = session->global->session_wire_id;
1086 data_blob_free(&nt_resp);
1087 data_blob_free(&lm_resp);
1089 SSVAL(req->outbuf,smb_vwv2,action);
1090 SSVAL(req->outbuf,smb_uid,sess_vuid);
1091 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1092 req->vuid = sess_vuid;
1094 if (!xconn->smb1.sessions.done_sesssetup) {
1095 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1096 reply_force_doserror(req, ERRSRV, ERRerror);
1097 END_PROFILE(SMBsesssetupX);
1098 return;
1100 xconn->smb1.sessions.max_send = smb_bufsize;
1101 xconn->smb1.sessions.done_sesssetup = true;
1104 END_PROFILE(SMBsesssetupX);