lib: replace: Add strsep function (missing on Solaris).
[Samba.git] / source3 / smbd / sesssetup.c
blobd68bcb68cc62eeb5562863d520442b9e2429bcd1
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_t **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_t *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_t 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 = 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 (!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;
514 struct server_id_buf tmp;
516 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
517 server_id_str_buf(pid, &tmp), addr));
519 if (!process_exists(pid)) {
520 DEBUG(10, ("process does not exist\n"));
521 return 0;
524 if (serverid_equal(&pid, &self_pid)) {
525 DEBUG(10, ("It's me\n"));
526 return 0;
530 * here we use strstr() because 'addr'
531 * (session->channels[0].remote_address)
532 * contains a string like:
533 * 'ipv4:127.0.0.1:48163'
535 if (strstr(addr, state->ip) == NULL) {
536 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
537 return 0;
540 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
541 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
542 state->ip));
544 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
545 &data_blob_null);
546 return 0;
549 static void setup_new_vc_session(struct smbd_server_connection *sconn)
551 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
552 "compatible we would close all old resources.\n"));
553 #if 0
554 conn_close_all();
555 invalidate_all_vuids();
556 #endif
557 if (lp_reset_on_zero_vc()) {
558 char *addr;
559 struct shutdown_state state;
561 addr = tsocket_address_inet_addr_string(
562 sconn->remote_address, talloc_tos());
563 if (addr == NULL) {
564 return;
566 state.ip = addr;
567 state.msg_ctx = sconn->msg_ctx;
568 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
569 TALLOC_FREE(addr);
573 /****************************************************************************
574 Reply to a session setup command.
575 ****************************************************************************/
577 void reply_sesssetup_and_X(struct smb_request *req)
579 uint64_t sess_vuid;
580 uint16_t smb_bufsize;
581 DATA_BLOB lm_resp;
582 DATA_BLOB nt_resp;
583 DATA_BLOB plaintext_password;
584 char *tmp;
585 const char *user;
586 fstring sub_user; /* Sanitised username for substituion */
587 const char *domain;
588 const char *native_os;
589 const char *native_lanman;
590 const char *primary_domain;
591 struct auth_usersupplied_info *user_info = NULL;
592 struct auth_session_info *session_info = NULL;
593 uint16_t smb_flag2 = req->flags2;
594 uint16_t action = 0;
595 NTTIME now = timeval_to_nttime(&req->request_time);
596 struct smbXsrv_session *session = NULL;
597 NTSTATUS nt_status;
598 struct smbXsrv_connection *xconn = req->xconn;
599 struct smbd_server_connection *sconn = req->sconn;
600 bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
601 bool signing_allowed = false;
602 bool signing_mandatory = false;
604 START_PROFILE(SMBsesssetupX);
606 ZERO_STRUCT(lm_resp);
607 ZERO_STRUCT(nt_resp);
608 ZERO_STRUCT(plaintext_password);
610 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
612 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
613 signing_allowed = true;
615 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
616 signing_mandatory = true;
620 * We can call srv_set_signing_negotiated() each time.
621 * It finds out when it needs to turn into a noop
622 * itself.
624 srv_set_signing_negotiated(xconn,
625 signing_allowed,
626 signing_mandatory);
628 /* a SPNEGO session setup has 12 command words, whereas a normal
629 NT1 session setup has 13. See the cifs spec. */
630 if (req->wct == 12 &&
631 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
633 if (!xconn->smb1.negprot.spnego) {
634 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
635 "at SPNEGO session setup when it was not "
636 "negotiated.\n"));
637 reply_nterror(req, nt_status_squash(
638 NT_STATUS_LOGON_FAILURE));
639 END_PROFILE(SMBsesssetupX);
640 return;
643 if (SVAL(req->vwv+4, 0) == 0) {
644 setup_new_vc_session(req->sconn);
647 reply_sesssetup_and_X_spnego(req);
648 END_PROFILE(SMBsesssetupX);
649 return;
652 smb_bufsize = SVAL(req->vwv+2, 0);
654 if (get_Protocol() < PROTOCOL_NT1) {
655 uint16_t passlen1 = SVAL(req->vwv+7, 0);
657 /* Never do NT status codes with protocols before NT1 as we
658 * don't get client caps. */
659 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
661 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
662 reply_nterror(req, nt_status_squash(
663 NT_STATUS_INVALID_PARAMETER));
664 END_PROFILE(SMBsesssetupX);
665 return;
668 if (doencrypt) {
669 lm_resp = data_blob(req->buf, passlen1);
670 } else {
671 plaintext_password = data_blob(req->buf, passlen1+1);
672 /* Ensure null termination */
673 plaintext_password.data[passlen1] = 0;
676 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
677 req->buf + passlen1, STR_TERMINATE);
678 user = tmp ? tmp : "";
680 domain = "";
682 } else {
683 uint16_t passlen1 = SVAL(req->vwv+7, 0);
684 uint16_t passlen2 = SVAL(req->vwv+8, 0);
685 enum remote_arch_types ra_type = get_remote_arch();
686 const uint8_t *p = req->buf;
687 const uint8_t *save_p = req->buf;
688 uint16_t byte_count;
690 if (!xconn->smb1.sessions.done_sesssetup) {
691 global_client_caps = IVAL(req->vwv+11, 0);
693 if (!(global_client_caps & CAP_STATUS32)) {
694 remove_from_common_flags2(
695 FLAGS2_32_BIT_ERROR_CODES);
698 /* client_caps is used as final determination if
699 * client is NT or Win95. This is needed to return
700 * the correct error codes in some circumstances.
703 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
704 ra_type == RA_WIN95) {
705 if(!(global_client_caps & (CAP_NT_SMBS|
706 CAP_STATUS32))) {
707 set_remote_arch( RA_WIN95);
712 if (!doencrypt) {
713 /* both Win95 and WinNT stuff up the password
714 * lengths for non-encrypting systems. Uggh.
716 if passlen1==24 its a win95 system, and its setting
717 the password length incorrectly. Luckily it still
718 works with the default code because Win95 will null
719 terminate the password anyway
721 if passlen1>0 and passlen2>0 then maybe its a NT box
722 and its setting passlen2 to some random value which
723 really stuffs things up. we need to fix that one. */
725 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
726 passlen2 != 1) {
727 passlen2 = 0;
731 /* check for nasty tricks */
732 if (passlen1 > MAX_PASS_LEN
733 || passlen1 > smbreq_bufrem(req, p)) {
734 reply_nterror(req, nt_status_squash(
735 NT_STATUS_INVALID_PARAMETER));
736 END_PROFILE(SMBsesssetupX);
737 return;
740 if (passlen2 > MAX_PASS_LEN
741 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
742 reply_nterror(req, nt_status_squash(
743 NT_STATUS_INVALID_PARAMETER));
744 END_PROFILE(SMBsesssetupX);
745 return;
748 /* Save the lanman2 password and the NT md4 password. */
750 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
751 doencrypt = False;
754 if (doencrypt) {
755 lm_resp = data_blob(p, passlen1);
756 nt_resp = data_blob(p+passlen1, passlen2);
757 } else {
758 char *pass = NULL;
759 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
761 if (unic && (passlen2 == 0) && passlen1) {
762 /* Only a ascii plaintext password was sent. */
763 (void)srvstr_pull_talloc(talloc_tos(),
764 req->inbuf,
765 req->flags2,
766 &pass,
767 req->buf,
768 passlen1,
769 STR_TERMINATE|STR_ASCII);
770 } else {
771 (void)srvstr_pull_talloc(talloc_tos(),
772 req->inbuf,
773 req->flags2,
774 &pass,
775 req->buf,
776 unic ? passlen2 : passlen1,
777 STR_TERMINATE);
779 if (!pass) {
780 reply_nterror(req, nt_status_squash(
781 NT_STATUS_INVALID_PARAMETER));
782 END_PROFILE(SMBsesssetupX);
783 return;
785 plaintext_password = data_blob(pass, strlen(pass)+1);
788 p += passlen1 + passlen2;
790 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
791 STR_TERMINATE);
792 user = tmp ? tmp : "";
794 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
795 STR_TERMINATE);
796 domain = tmp ? tmp : "";
798 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
799 STR_TERMINATE);
800 native_os = tmp ? tmp : "";
802 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
803 STR_TERMINATE);
804 native_lanman = tmp ? tmp : "";
806 /* not documented or decoded by Ethereal but there is one more
807 * string in the extra bytes which is the same as the
808 * PrimaryDomain when using extended security. Windows NT 4
809 * and 2003 use this string to store the native lanman string.
810 * Windows 9x does not include a string here at all so we have
811 * to check if we have any extra bytes left */
813 byte_count = SVAL(req->vwv+13, 0);
814 if ( PTR_DIFF(p, save_p) < byte_count) {
815 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
816 STR_TERMINATE);
817 primary_domain = tmp ? tmp : "";
818 } else {
819 primary_domain = talloc_strdup(talloc_tos(), "null");
822 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
823 "PrimaryDomain=[%s]\n",
824 domain, native_os, native_lanman, primary_domain));
826 if ( ra_type == RA_WIN2K ) {
827 if ( strlen(native_lanman) == 0 )
828 ra_lanman_string( primary_domain );
829 else
830 ra_lanman_string( native_lanman );
835 if (SVAL(req->vwv+4, 0) == 0) {
836 setup_new_vc_session(req->sconn);
839 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
840 domain, user, get_remote_machine_name()));
842 if (*user) {
843 if (xconn->smb1.negprot.spnego) {
845 /* This has to be here, because this is a perfectly
846 * valid behaviour for guest logons :-( */
848 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
849 "at 'normal' session setup after "
850 "negotiating spnego.\n"));
851 reply_nterror(req, nt_status_squash(
852 NT_STATUS_LOGON_FAILURE));
853 END_PROFILE(SMBsesssetupX);
854 return;
856 fstrcpy(sub_user, user);
857 } else {
858 fstrcpy(sub_user, "");
861 sub_set_smb_name(sub_user);
863 reload_services(sconn, conn_snum_used, true);
865 if (!*user) {
867 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
869 } else if (doencrypt) {
870 struct auth4_context *negprot_auth_context = NULL;
871 negprot_auth_context = xconn->smb1.negprot.auth_context;
872 if (!negprot_auth_context) {
873 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
874 "session setup without negprot denied!\n"));
875 reply_nterror(req, nt_status_squash(
876 NT_STATUS_LOGON_FAILURE));
877 END_PROFILE(SMBsesssetupX);
878 return;
880 nt_status = make_user_info_for_reply_enc(talloc_tos(),
881 &user_info, user,
882 domain,
883 sconn->remote_address,
884 lm_resp, nt_resp);
885 if (NT_STATUS_IS_OK(nt_status)) {
886 nt_status = auth_check_password_session_info(negprot_auth_context,
887 req, user_info, &session_info);
889 } else {
890 struct auth4_context *plaintext_auth_context = NULL;
892 nt_status = make_auth4_context(
893 talloc_tos(), &plaintext_auth_context);
895 if (NT_STATUS_IS_OK(nt_status)) {
896 uint8_t chal[8];
898 plaintext_auth_context->get_ntlm_challenge(
899 plaintext_auth_context, chal);
901 if (!make_user_info_for_reply(talloc_tos(),
902 &user_info,
903 user, domain,
904 sconn->remote_address,
905 chal,
906 plaintext_password)) {
907 nt_status = NT_STATUS_NO_MEMORY;
910 if (NT_STATUS_IS_OK(nt_status)) {
911 nt_status = auth_check_password_session_info(plaintext_auth_context,
912 req, user_info, &session_info);
914 TALLOC_FREE(plaintext_auth_context);
918 TALLOC_FREE(user_info);
920 if (!NT_STATUS_IS_OK(nt_status)) {
921 data_blob_free(&nt_resp);
922 data_blob_free(&lm_resp);
923 data_blob_clear_free(&plaintext_password);
924 reply_nterror(req, nt_status_squash(nt_status));
925 END_PROFILE(SMBsesssetupX);
926 return;
929 data_blob_clear_free(&plaintext_password);
931 /* it's ok - setup a reply */
932 reply_outbuf(req, 3, 0);
933 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
934 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
936 if (get_Protocol() >= PROTOCOL_NT1) {
937 push_signature(&req->outbuf);
938 /* perhaps grab OS version here?? */
941 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
942 action = 1;
945 /* register the name and uid as being validated, so further connections
946 to a uid can get through without a password, on the same VC */
948 nt_status = smbXsrv_session_create(xconn,
949 now, &session);
950 if (!NT_STATUS_IS_OK(nt_status)) {
951 data_blob_free(&nt_resp);
952 data_blob_free(&lm_resp);
953 reply_nterror(req, nt_status_squash(nt_status));
954 END_PROFILE(SMBsesssetupX);
955 return;
958 if (session_info->session_key.length > 0) {
959 uint8_t session_key[16];
962 * Note: the SMB1 signing key is not truncated to 16 byte!
964 session->global->signing_key =
965 data_blob_dup_talloc(session->global,
966 session_info->session_key);
967 if (session->global->signing_key.data == NULL) {
968 data_blob_free(&nt_resp);
969 data_blob_free(&lm_resp);
970 TALLOC_FREE(session);
971 reply_nterror(req, NT_STATUS_NO_MEMORY);
972 END_PROFILE(SMBsesssetupX);
973 return;
977 * The application key is truncated/padded to 16 bytes
979 ZERO_STRUCT(session_key);
980 memcpy(session_key, session->global->signing_key.data,
981 MIN(session->global->signing_key.length,
982 sizeof(session_key)));
983 session->global->application_key =
984 data_blob_talloc(session->global,
985 session_key,
986 sizeof(session_key));
987 ZERO_STRUCT(session_key);
988 if (session->global->application_key.data == NULL) {
989 data_blob_free(&nt_resp);
990 data_blob_free(&lm_resp);
991 TALLOC_FREE(session);
992 reply_nterror(req, NT_STATUS_NO_MEMORY);
993 END_PROFILE(SMBsesssetupX);
994 return;
998 * Place the application key into the session_info
1000 data_blob_clear_free(&session_info->session_key);
1001 session_info->session_key = data_blob_dup_talloc(session_info,
1002 session->global->application_key);
1003 if (session_info->session_key.data == NULL) {
1004 data_blob_free(&nt_resp);
1005 data_blob_free(&lm_resp);
1006 TALLOC_FREE(session);
1007 reply_nterror(req, NT_STATUS_NO_MEMORY);
1008 END_PROFILE(SMBsesssetupX);
1009 return;
1013 session->compat = talloc_zero(session, struct user_struct);
1014 if (session->compat == NULL) {
1015 data_blob_free(&nt_resp);
1016 data_blob_free(&lm_resp);
1017 TALLOC_FREE(session);
1018 reply_nterror(req, NT_STATUS_NO_MEMORY);
1019 END_PROFILE(SMBsesssetupX);
1020 return;
1022 session->compat->session = session;
1023 session->compat->homes_snum = -1;
1024 session->compat->session_info = session_info;
1025 session->compat->session_keystr = NULL;
1026 session->compat->vuid = session->global->session_wire_id;
1027 DLIST_ADD(sconn->users, session->compat);
1028 sconn->num_users++;
1030 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1031 session->compat->homes_snum =
1032 register_homes_share(session_info->unix_info->unix_name);
1035 if (srv_is_signing_negotiated(xconn) &&
1036 action == 0 &&
1037 session->global->signing_key.length > 0)
1040 * Try and turn on server signing on the first non-guest
1041 * sessionsetup.
1043 srv_set_signing(xconn,
1044 session->global->signing_key,
1045 nt_resp.data ? nt_resp : lm_resp);
1048 set_current_user_info(session_info->unix_info->sanitized_username,
1049 session_info->unix_info->unix_name,
1050 session_info->info->domain_name);
1052 session->status = NT_STATUS_OK;
1053 session->global->auth_session_info = talloc_move(session->global,
1054 &session_info);
1055 session->global->auth_session_info_seqnum += 1;
1056 session->global->channels[0].auth_session_info_seqnum =
1057 session->global->auth_session_info_seqnum;
1058 session->global->auth_time = now;
1059 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1061 nt_status = smbXsrv_session_update(session);
1062 if (!NT_STATUS_IS_OK(nt_status)) {
1063 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1064 (unsigned long long)session->compat->vuid,
1065 nt_errstr(nt_status)));
1066 data_blob_free(&nt_resp);
1067 data_blob_free(&lm_resp);
1068 TALLOC_FREE(session);
1069 reply_nterror(req, nt_status_squash(nt_status));
1070 END_PROFILE(SMBsesssetupX);
1071 return;
1074 if (!session_claim(session)) {
1075 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1076 (unsigned long long)session->compat->vuid));
1077 data_blob_free(&nt_resp);
1078 data_blob_free(&lm_resp);
1079 TALLOC_FREE(session);
1080 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1081 END_PROFILE(SMBsesssetupX);
1082 return;
1085 /* current_user_info is changed on new vuid */
1086 reload_services(sconn, conn_snum_used, true);
1088 sess_vuid = session->global->session_wire_id;
1090 data_blob_free(&nt_resp);
1091 data_blob_free(&lm_resp);
1093 SSVAL(req->outbuf,smb_vwv2,action);
1094 SSVAL(req->outbuf,smb_uid,sess_vuid);
1095 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1096 req->vuid = sess_vuid;
1098 if (!xconn->smb1.sessions.done_sesssetup) {
1099 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1100 reply_force_doserror(req, ERRSRV, ERRerror);
1101 END_PROFILE(SMBsesssetupX);
1102 return;
1104 xconn->smb1.sessions.max_send = smb_bufsize;
1105 xconn->smb1.sessions.done_sesssetup = true;
1108 END_PROFILE(SMBsesssetupX);