ctdb-tests: Add explicit wait to the fork_helper()
[Samba.git] / source3 / smbd / sesssetup.c
blobc058eac33630af119c8d931924df2a1df1d7366f
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 "auth.h"
30 #include "messages.h"
31 #include "smbprofile.h"
32 #include "../libcli/security/security.h"
33 #include "auth/gensec/gensec.h"
34 #include "lib/conn_tdb.h"
35 #include "../libcli/smb/smb_signing.h"
37 /****************************************************************************
38 Add the standard 'Samba' signature to the end of the session setup.
39 ****************************************************************************/
41 static int push_signature(uint8_t **outbuf)
43 char *lanman;
44 int result, tmp;
45 fstring native_os;
47 result = 0;
49 fstr_sprintf(native_os, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION,
50 SAMBA_MINOR_NBT_ANNOUNCE_VERSION);
52 tmp = message_push_string(outbuf, native_os, STR_TERMINATE);
54 if (tmp == -1) return -1;
55 result += tmp;
57 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
58 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
59 SAFE_FREE(lanman);
61 else {
62 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
65 if (tmp == -1) return -1;
66 result += tmp;
68 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
70 if (tmp == -1) return -1;
71 result += tmp;
73 return result;
76 /****************************************************************************
77 Do a 'guest' logon, getting back the
78 ****************************************************************************/
80 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
81 TALLOC_CTX *mem_ctx,
82 struct auth_session_info **session_info)
84 struct auth4_context *auth_context;
85 struct auth_usersupplied_info *user_info = NULL;
86 uint8_t chal[8];
87 NTSTATUS nt_status;
89 DEBUG(3,("Got anonymous request\n"));
91 nt_status = make_auth4_context(talloc_tos(), &auth_context);
92 if (!NT_STATUS_IS_OK(nt_status)) {
93 return nt_status;
96 auth_context->get_ntlm_challenge(auth_context,
97 chal);
99 if (!make_user_info_guest(talloc_tos(), remote_address, &user_info)) {
100 TALLOC_FREE(auth_context);
101 return NT_STATUS_NO_MEMORY;
104 nt_status = auth_check_password_session_info(auth_context,
105 mem_ctx, user_info, session_info);
106 TALLOC_FREE(user_info);
107 TALLOC_FREE(auth_context);
108 return nt_status;
111 /****************************************************************************
112 Reply to a session setup command.
113 conn POINTER CAN BE NULL HERE !
114 ****************************************************************************/
116 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
118 const uint8_t *p;
119 DATA_BLOB in_blob;
120 DATA_BLOB out_blob = data_blob_null;
121 size_t bufrem;
122 char *tmp;
123 const char *native_os;
124 const char *native_lanman;
125 const char *primary_domain;
126 uint16_t data_blob_len = SVAL(req->vwv+7, 0);
127 enum remote_arch_types ra_type = get_remote_arch();
128 uint64_t vuid = req->vuid;
129 NTSTATUS status = NT_STATUS_OK;
130 struct smbXsrv_connection *xconn = req->xconn;
131 struct smbd_server_connection *sconn = req->sconn;
132 uint16_t action = 0;
133 bool is_authenticated = false;
134 NTTIME now = timeval_to_nttime(&req->request_time);
135 struct smbXsrv_session *session = NULL;
136 uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
137 uint32_t client_caps = IVAL(req->vwv+10, 0);
138 struct smbXsrv_session_auth0 *auth;
140 DEBUG(3,("Doing spnego session setup\n"));
142 if (!xconn->smb1.sessions.done_sesssetup) {
143 global_client_caps = client_caps;
145 if (!(global_client_caps & CAP_STATUS32)) {
146 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
150 p = req->buf;
152 if (data_blob_len == 0) {
153 /* an invalid request */
154 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
155 return;
158 bufrem = smbreq_bufrem(req, p);
159 /* pull the spnego blob */
160 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
162 #if 0
163 file_save("negotiate.dat", in_blob.data, in_blob.length);
164 #endif
166 p = req->buf + in_blob.length;
168 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
169 STR_TERMINATE);
170 native_os = tmp ? tmp : "";
172 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
173 STR_TERMINATE);
174 native_lanman = tmp ? tmp : "";
176 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
177 STR_TERMINATE);
178 primary_domain = tmp ? tmp : "";
180 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
181 native_os, native_lanman, primary_domain));
183 if ( ra_type == RA_WIN2K ) {
184 /* Vista sets neither the OS or lanman strings */
186 if ( !strlen(native_os) && !strlen(native_lanman) )
187 set_remote_arch(RA_VISTA);
189 /* Windows 2003 doesn't set the native lanman string,
190 but does set primary domain which is a bug I think */
192 if ( !strlen(native_lanman) ) {
193 ra_lanman_string( primary_domain );
194 } else {
195 ra_lanman_string( native_lanman );
197 } else if ( ra_type == RA_VISTA ) {
198 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
199 set_remote_arch(RA_OSX);
203 if (vuid != 0) {
204 status = smb1srv_session_lookup(xconn,
205 vuid, now,
206 &session);
207 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
208 reply_force_doserror(req, ERRSRV, ERRbaduid);
209 return;
211 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
212 status = NT_STATUS_OK;
214 if (NT_STATUS_IS_OK(status)) {
215 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
216 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
217 TALLOC_FREE(session->pending_auth);
219 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
220 reply_nterror(req, nt_status_squash(status));
221 return;
225 if (session == NULL) {
226 /* create a new session */
227 status = smbXsrv_session_create(xconn,
228 now, &session);
229 if (!NT_STATUS_IS_OK(status)) {
230 reply_nterror(req, nt_status_squash(status));
231 return;
235 status = smbXsrv_session_find_auth(session, xconn, now, &auth);
236 if (!NT_STATUS_IS_OK(status)) {
237 status = smbXsrv_session_create_auth(session, xconn, now,
238 0, /* flags */
239 0, /* security */
240 &auth);
241 if (!NT_STATUS_IS_OK(status)) {
242 reply_nterror(req, nt_status_squash(status));
243 return;
247 if (auth->gensec == NULL) {
248 status = auth_generic_prepare(session, xconn->remote_address,
249 &auth->gensec);
250 if (!NT_STATUS_IS_OK(status)) {
251 TALLOC_FREE(session);
252 reply_nterror(req, nt_status_squash(status));
253 return;
256 gensec_want_feature(auth->gensec, GENSEC_FEATURE_SESSION_KEY);
257 gensec_want_feature(auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
259 status = gensec_start_mech_by_oid(auth->gensec,
260 GENSEC_OID_SPNEGO);
261 if (!NT_STATUS_IS_OK(status)) {
262 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
263 TALLOC_FREE(session);;
264 reply_nterror(req, nt_status_squash(status));
265 return;
269 become_root();
270 status = gensec_update(auth->gensec,
271 talloc_tos(),
272 in_blob, &out_blob);
273 unbecome_root();
274 if (!NT_STATUS_IS_OK(status) &&
275 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
276 TALLOC_FREE(session);
277 reply_nterror(req, nt_status_squash(status));
278 return;
281 if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
282 struct auth_session_info *session_info = NULL;
284 status = gensec_session_info(auth->gensec,
285 session,
286 &session_info);
287 if (!NT_STATUS_IS_OK(status)) {
288 DEBUG(1,("Failed to generate session_info "
289 "(user and group token) for session setup: %s\n",
290 nt_errstr(status)));
291 data_blob_free(&out_blob);
292 TALLOC_FREE(session);
293 reply_nterror(req, nt_status_squash(status));
294 return;
297 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
298 action |= SMB_SETUP_GUEST;
301 if (session_info->session_key.length > 0) {
302 struct smbXsrv_session *x = session;
305 * Note: the SMB1 signing key is not truncated to 16 byte!
307 x->global->signing_key =
308 data_blob_dup_talloc(x->global,
309 session_info->session_key);
310 if (x->global->signing_key.data == NULL) {
311 data_blob_free(&out_blob);
312 TALLOC_FREE(session);
313 reply_nterror(req, NT_STATUS_NO_MEMORY);
314 return;
318 * clear the session key
319 * the first tcon will add setup the application key
321 data_blob_clear_free(&session_info->session_key);
324 session->compat = talloc_zero(session, struct user_struct);
325 if (session->compat == NULL) {
326 data_blob_free(&out_blob);
327 TALLOC_FREE(session);
328 reply_nterror(req, NT_STATUS_NO_MEMORY);
329 return;
331 session->compat->session = session;
332 session->compat->homes_snum = -1;
333 session->compat->session_info = session_info;
334 session->compat->session_keystr = NULL;
335 session->compat->vuid = session->global->session_wire_id;
336 DLIST_ADD(sconn->users, session->compat);
337 sconn->num_users++;
339 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
340 is_authenticated = true;
341 session->compat->homes_snum =
342 register_homes_share(session_info->unix_info->unix_name);
345 if (srv_is_signing_negotiated(xconn) &&
346 is_authenticated &&
347 session->global->signing_key.length > 0)
350 * Try and turn on server signing on the first non-guest
351 * sessionsetup.
353 srv_set_signing(xconn,
354 session->global->signing_key,
355 data_blob_null);
358 set_current_user_info(session_info->unix_info->sanitized_username,
359 session_info->unix_info->unix_name,
360 session_info->info->domain_name);
362 session->status = NT_STATUS_OK;
363 session->global->auth_session_info = talloc_move(session->global,
364 &session_info);
365 session->global->auth_session_info_seqnum += 1;
366 session->global->channels[0].auth_session_info_seqnum =
367 session->global->auth_session_info_seqnum;
368 session->global->auth_time = now;
369 if (client_caps & CAP_DYNAMIC_REAUTH) {
370 session->global->expiration_time =
371 gensec_expire_time(auth->gensec);
372 } else {
373 session->global->expiration_time =
374 GENSEC_EXPIRE_TIME_INFINITY;
377 if (!session_claim(session)) {
378 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
379 (unsigned long long)session->compat->vuid));
380 data_blob_free(&out_blob);
381 TALLOC_FREE(session);
382 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
383 return;
386 status = smbXsrv_session_update(session);
387 if (!NT_STATUS_IS_OK(status)) {
388 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
389 (unsigned long long)session->compat->vuid,
390 nt_errstr(status)));
391 data_blob_free(&out_blob);
392 TALLOC_FREE(session);
393 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
394 return;
397 if (!xconn->smb1.sessions.done_sesssetup) {
398 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
399 reply_force_doserror(req, ERRSRV, ERRerror);
400 return;
402 xconn->smb1.sessions.max_send = smb_bufsize;
403 xconn->smb1.sessions.done_sesssetup = true;
406 /* current_user_info is changed on new vuid */
407 reload_services(sconn, conn_snum_used, true);
408 } else if (NT_STATUS_IS_OK(status)) {
409 struct auth_session_info *session_info = NULL;
411 status = gensec_session_info(auth->gensec,
412 session,
413 &session_info);
414 if (!NT_STATUS_IS_OK(status)) {
415 DEBUG(1,("Failed to generate session_info "
416 "(user and group token) for session setup: %s\n",
417 nt_errstr(status)));
418 data_blob_free(&out_blob);
419 TALLOC_FREE(session);
420 reply_nterror(req, nt_status_squash(status));
421 return;
424 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
425 action |= SMB_SETUP_GUEST;
429 * Keep the application key
431 data_blob_clear_free(&session_info->session_key);
432 session_info->session_key =
433 session->global->auth_session_info->session_key;
434 talloc_steal(session_info, session_info->session_key.data);
435 TALLOC_FREE(session->global->auth_session_info);
437 session->compat->session_info = session_info;
439 session->compat->vuid = session->global->session_wire_id;
441 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
442 session->compat->homes_snum =
443 register_homes_share(session_info->unix_info->unix_name);
446 set_current_user_info(session_info->unix_info->sanitized_username,
447 session_info->unix_info->unix_name,
448 session_info->info->domain_name);
450 session->status = NT_STATUS_OK;
451 session->global->auth_session_info = talloc_move(session->global,
452 &session_info);
453 session->global->auth_session_info_seqnum += 1;
454 session->global->channels[0].auth_session_info_seqnum =
455 session->global->auth_session_info_seqnum;
456 session->global->auth_time = now;
457 if (client_caps & CAP_DYNAMIC_REAUTH) {
458 session->global->expiration_time =
459 gensec_expire_time(auth->gensec);
460 } else {
461 session->global->expiration_time =
462 GENSEC_EXPIRE_TIME_INFINITY;
465 status = smbXsrv_session_update(session);
466 if (!NT_STATUS_IS_OK(status)) {
467 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
468 (unsigned long long)session->compat->vuid,
469 nt_errstr(status)));
470 data_blob_free(&out_blob);
471 TALLOC_FREE(session);
472 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
473 return;
476 conn_clear_vuid_caches(sconn, session->compat->vuid);
478 /* current_user_info is changed on new vuid */
479 reload_services(sconn, conn_snum_used, true);
482 vuid = session->global->session_wire_id;
484 reply_outbuf(req, 4, 0);
486 SSVAL(req->outbuf, smb_uid, vuid);
487 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
488 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
489 SSVAL(req->outbuf, smb_vwv2, action);
490 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
492 if (message_push_blob(&req->outbuf, out_blob) == -1) {
493 data_blob_free(&out_blob);
494 TALLOC_FREE(session);
495 reply_nterror(req, NT_STATUS_NO_MEMORY);
496 return;
498 data_blob_free(&out_blob);
500 if (push_signature(&req->outbuf) == -1) {
501 TALLOC_FREE(session);
502 reply_nterror(req, NT_STATUS_NO_MEMORY);
503 return;
507 /****************************************************************************
508 On new VC == 0, shutdown *all* old connections and users.
509 It seems that only NT4.x does this. At W2K and above (XP etc.).
510 a new session setup with VC==0 is ignored.
511 ****************************************************************************/
513 struct shutdown_state {
514 const char *ip;
515 struct messaging_context *msg_ctx;
518 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
519 void *private_data)
521 struct shutdown_state *state = (struct shutdown_state *)private_data;
522 struct server_id self_pid = messaging_server_id(state->msg_ctx);
523 struct server_id pid = session->channels[0].server_id;
524 const char *addr = session->channels[0].remote_address;
525 struct server_id_buf tmp;
527 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
528 server_id_str_buf(pid, &tmp), addr));
530 if (!process_exists(pid)) {
531 DEBUG(10, ("process does not exist\n"));
532 return 0;
535 if (serverid_equal(&pid, &self_pid)) {
536 DEBUG(10, ("It's me\n"));
537 return 0;
541 * here we use strstr() because 'addr'
542 * (session->channels[0].remote_address)
543 * contains a string like:
544 * 'ipv4:127.0.0.1:48163'
546 if (strstr(addr, state->ip) == NULL) {
547 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
548 return 0;
551 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
552 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
553 state->ip));
555 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
556 &data_blob_null);
557 return 0;
560 static void setup_new_vc_session(struct smbd_server_connection *sconn)
562 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
563 "compatible we would close all old resources.\n"));
564 #if 0
565 conn_close_all();
566 invalidate_all_vuids();
567 #endif
568 if (lp_reset_on_zero_vc()) {
569 char *addr;
570 struct shutdown_state state;
572 addr = tsocket_address_inet_addr_string(
573 sconn->remote_address, talloc_tos());
574 if (addr == NULL) {
575 return;
577 state.ip = addr;
578 state.msg_ctx = sconn->msg_ctx;
579 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
580 TALLOC_FREE(addr);
584 /****************************************************************************
585 Reply to a session setup command.
586 ****************************************************************************/
588 void reply_sesssetup_and_X(struct smb_request *req)
590 uint64_t sess_vuid;
591 uint16_t smb_bufsize;
592 DATA_BLOB lm_resp;
593 DATA_BLOB nt_resp;
594 DATA_BLOB plaintext_password;
595 char *tmp;
596 const char *user;
597 fstring sub_user; /* Sanitised username for substituion */
598 const char *domain;
599 const char *native_os;
600 const char *native_lanman;
601 const char *primary_domain;
602 struct auth_usersupplied_info *user_info = NULL;
603 struct auth_session_info *session_info = NULL;
604 uint16_t smb_flag2 = req->flags2;
605 uint16_t action = 0;
606 bool is_authenticated = false;
607 NTTIME now = timeval_to_nttime(&req->request_time);
608 struct smbXsrv_session *session = NULL;
609 NTSTATUS nt_status;
610 struct smbXsrv_connection *xconn = req->xconn;
611 struct smbd_server_connection *sconn = req->sconn;
612 bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
613 bool signing_allowed = false;
614 bool signing_mandatory = smb_signing_is_mandatory(
615 xconn->smb1.signing_state);
617 START_PROFILE(SMBsesssetupX);
619 ZERO_STRUCT(lm_resp);
620 ZERO_STRUCT(nt_resp);
621 ZERO_STRUCT(plaintext_password);
623 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
625 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
626 signing_allowed = true;
628 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
629 signing_mandatory = true;
633 * We can call srv_set_signing_negotiated() each time.
634 * It finds out when it needs to turn into a noop
635 * itself.
637 srv_set_signing_negotiated(xconn,
638 signing_allowed,
639 signing_mandatory);
641 /* a SPNEGO session setup has 12 command words, whereas a normal
642 NT1 session setup has 13. See the cifs spec. */
643 if (req->wct == 12 &&
644 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
646 if (!xconn->smb1.negprot.spnego) {
647 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
648 "at SPNEGO session setup when it was not "
649 "negotiated.\n"));
650 reply_nterror(req, nt_status_squash(
651 NT_STATUS_LOGON_FAILURE));
652 END_PROFILE(SMBsesssetupX);
653 return;
656 if (SVAL(req->vwv+4, 0) == 0) {
657 setup_new_vc_session(req->sconn);
660 reply_sesssetup_and_X_spnego(req);
661 END_PROFILE(SMBsesssetupX);
662 return;
665 smb_bufsize = SVAL(req->vwv+2, 0);
667 if (get_Protocol() < PROTOCOL_NT1) {
668 uint16_t passlen1 = SVAL(req->vwv+7, 0);
670 /* Never do NT status codes with protocols before NT1 as we
671 * don't get client caps. */
672 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
674 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
675 reply_nterror(req, nt_status_squash(
676 NT_STATUS_INVALID_PARAMETER));
677 END_PROFILE(SMBsesssetupX);
678 return;
681 if (doencrypt) {
682 lm_resp = data_blob(req->buf, passlen1);
683 } else {
684 plaintext_password = data_blob(req->buf, passlen1+1);
685 /* Ensure null termination */
686 plaintext_password.data[passlen1] = 0;
689 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
690 req->buf + passlen1, STR_TERMINATE);
691 user = tmp ? tmp : "";
693 domain = "";
695 } else {
696 uint16_t passlen1 = SVAL(req->vwv+7, 0);
697 uint16_t passlen2 = SVAL(req->vwv+8, 0);
698 enum remote_arch_types ra_type = get_remote_arch();
699 const uint8_t *p = req->buf;
700 const uint8_t *save_p = req->buf;
701 uint16_t byte_count;
703 if (!xconn->smb1.sessions.done_sesssetup) {
704 global_client_caps = IVAL(req->vwv+11, 0);
706 if (!(global_client_caps & CAP_STATUS32)) {
707 remove_from_common_flags2(
708 FLAGS2_32_BIT_ERROR_CODES);
711 /* client_caps is used as final determination if
712 * client is NT or Win95. This is needed to return
713 * the correct error codes in some circumstances.
716 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
717 ra_type == RA_WIN95) {
718 if(!(global_client_caps & (CAP_NT_SMBS|
719 CAP_STATUS32))) {
720 set_remote_arch( RA_WIN95);
725 if (!doencrypt) {
726 /* both Win95 and WinNT stuff up the password
727 * lengths for non-encrypting systems. Uggh.
729 if passlen1==24 its a win95 system, and its setting
730 the password length incorrectly. Luckily it still
731 works with the default code because Win95 will null
732 terminate the password anyway
734 if passlen1>0 and passlen2>0 then maybe its a NT box
735 and its setting passlen2 to some random value which
736 really stuffs things up. we need to fix that one. */
738 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
739 passlen2 != 1) {
740 passlen2 = 0;
744 /* check for nasty tricks */
745 if (passlen1 > MAX_PASS_LEN
746 || passlen1 > smbreq_bufrem(req, p)) {
747 reply_nterror(req, nt_status_squash(
748 NT_STATUS_INVALID_PARAMETER));
749 END_PROFILE(SMBsesssetupX);
750 return;
753 if (passlen2 > MAX_PASS_LEN
754 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
755 reply_nterror(req, nt_status_squash(
756 NT_STATUS_INVALID_PARAMETER));
757 END_PROFILE(SMBsesssetupX);
758 return;
761 /* Save the lanman2 password and the NT md4 password. */
763 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
764 doencrypt = False;
767 if (doencrypt) {
768 lm_resp = data_blob(p, passlen1);
769 nt_resp = data_blob(p+passlen1, passlen2);
770 } else {
771 char *pass = NULL;
772 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
774 if (unic && (passlen2 == 0) && passlen1) {
775 /* Only a ascii plaintext password was sent. */
776 (void)srvstr_pull_talloc(talloc_tos(),
777 req->inbuf,
778 req->flags2,
779 &pass,
780 req->buf,
781 passlen1,
782 STR_TERMINATE|STR_ASCII);
783 } else {
784 (void)srvstr_pull_talloc(talloc_tos(),
785 req->inbuf,
786 req->flags2,
787 &pass,
788 req->buf,
789 unic ? passlen2 : passlen1,
790 STR_TERMINATE);
792 if (!pass) {
793 reply_nterror(req, nt_status_squash(
794 NT_STATUS_INVALID_PARAMETER));
795 END_PROFILE(SMBsesssetupX);
796 return;
798 plaintext_password = data_blob(pass, strlen(pass)+1);
801 p += passlen1 + passlen2;
803 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
804 STR_TERMINATE);
805 user = tmp ? tmp : "";
807 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
808 STR_TERMINATE);
809 domain = tmp ? tmp : "";
811 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
812 STR_TERMINATE);
813 native_os = tmp ? tmp : "";
815 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
816 STR_TERMINATE);
817 native_lanman = tmp ? tmp : "";
819 /* not documented or decoded by Ethereal but there is one more
820 * string in the extra bytes which is the same as the
821 * PrimaryDomain when using extended security. Windows NT 4
822 * and 2003 use this string to store the native lanman string.
823 * Windows 9x does not include a string here at all so we have
824 * to check if we have any extra bytes left */
826 byte_count = SVAL(req->vwv+13, 0);
827 if ( PTR_DIFF(p, save_p) < byte_count) {
828 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
829 STR_TERMINATE);
830 primary_domain = tmp ? tmp : "";
831 } else {
832 primary_domain = talloc_strdup(talloc_tos(), "null");
835 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
836 "PrimaryDomain=[%s]\n",
837 domain, native_os, native_lanman, primary_domain));
839 if ( ra_type == RA_WIN2K ) {
840 if ( strlen(native_lanman) == 0 )
841 ra_lanman_string( primary_domain );
842 else
843 ra_lanman_string( native_lanman );
848 if (SVAL(req->vwv+4, 0) == 0) {
849 setup_new_vc_session(req->sconn);
852 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
853 domain, user, get_remote_machine_name()));
855 if (*user) {
856 if (xconn->smb1.negprot.spnego) {
858 /* This has to be here, because this is a perfectly
859 * valid behaviour for guest logons :-( */
861 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
862 "at 'normal' session setup after "
863 "negotiating spnego.\n"));
864 reply_nterror(req, nt_status_squash(
865 NT_STATUS_LOGON_FAILURE));
866 END_PROFILE(SMBsesssetupX);
867 return;
869 fstrcpy(sub_user, user);
870 } else {
871 fstrcpy(sub_user, "");
874 sub_set_smb_name(sub_user);
876 reload_services(sconn, conn_snum_used, true);
878 if (!*user) {
880 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
882 } else if (doencrypt) {
883 struct auth4_context *negprot_auth_context = NULL;
884 negprot_auth_context = xconn->smb1.negprot.auth_context;
885 if (!negprot_auth_context) {
886 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
887 "session setup without negprot denied!\n"));
888 reply_nterror(req, nt_status_squash(
889 NT_STATUS_LOGON_FAILURE));
890 END_PROFILE(SMBsesssetupX);
891 return;
893 nt_status = make_user_info_for_reply_enc(talloc_tos(),
894 &user_info, user,
895 domain,
896 sconn->remote_address,
897 lm_resp, nt_resp);
898 if (NT_STATUS_IS_OK(nt_status)) {
899 nt_status = auth_check_password_session_info(negprot_auth_context,
900 req, user_info, &session_info);
902 } else {
903 struct auth4_context *plaintext_auth_context = NULL;
905 nt_status = make_auth4_context(
906 talloc_tos(), &plaintext_auth_context);
908 if (NT_STATUS_IS_OK(nt_status)) {
909 uint8_t chal[8];
911 plaintext_auth_context->get_ntlm_challenge(
912 plaintext_auth_context, chal);
914 if (!make_user_info_for_reply(talloc_tos(),
915 &user_info,
916 user, domain,
917 sconn->remote_address,
918 chal,
919 plaintext_password)) {
920 nt_status = NT_STATUS_NO_MEMORY;
923 if (NT_STATUS_IS_OK(nt_status)) {
924 nt_status = auth_check_password_session_info(plaintext_auth_context,
925 req, user_info, &session_info);
927 TALLOC_FREE(plaintext_auth_context);
931 TALLOC_FREE(user_info);
933 if (!NT_STATUS_IS_OK(nt_status)) {
934 data_blob_free(&nt_resp);
935 data_blob_free(&lm_resp);
936 data_blob_clear_free(&plaintext_password);
937 reply_nterror(req, nt_status_squash(nt_status));
938 END_PROFILE(SMBsesssetupX);
939 return;
942 data_blob_clear_free(&plaintext_password);
944 /* it's ok - setup a reply */
945 reply_outbuf(req, 3, 0);
946 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
947 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
949 if (get_Protocol() >= PROTOCOL_NT1) {
950 push_signature(&req->outbuf);
951 /* perhaps grab OS version here?? */
954 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
955 action |= SMB_SETUP_GUEST;
958 /* register the name and uid as being validated, so further connections
959 to a uid can get through without a password, on the same VC */
961 nt_status = smbXsrv_session_create(xconn,
962 now, &session);
963 if (!NT_STATUS_IS_OK(nt_status)) {
964 data_blob_free(&nt_resp);
965 data_blob_free(&lm_resp);
966 reply_nterror(req, nt_status_squash(nt_status));
967 END_PROFILE(SMBsesssetupX);
968 return;
971 if (session_info->session_key.length > 0) {
972 uint8_t session_key[16];
975 * Note: the SMB1 signing key is not truncated to 16 byte!
977 session->global->signing_key =
978 data_blob_dup_talloc(session->global,
979 session_info->session_key);
980 if (session->global->signing_key.data == NULL) {
981 data_blob_free(&nt_resp);
982 data_blob_free(&lm_resp);
983 TALLOC_FREE(session);
984 reply_nterror(req, NT_STATUS_NO_MEMORY);
985 END_PROFILE(SMBsesssetupX);
986 return;
990 * The application key is truncated/padded to 16 bytes
992 ZERO_STRUCT(session_key);
993 memcpy(session_key, session->global->signing_key.data,
994 MIN(session->global->signing_key.length,
995 sizeof(session_key)));
996 session->global->application_key =
997 data_blob_talloc(session->global,
998 session_key,
999 sizeof(session_key));
1000 ZERO_STRUCT(session_key);
1001 if (session->global->application_key.data == NULL) {
1002 data_blob_free(&nt_resp);
1003 data_blob_free(&lm_resp);
1004 TALLOC_FREE(session);
1005 reply_nterror(req, NT_STATUS_NO_MEMORY);
1006 END_PROFILE(SMBsesssetupX);
1007 return;
1011 * Place the application key into the session_info
1013 data_blob_clear_free(&session_info->session_key);
1014 session_info->session_key = data_blob_dup_talloc(session_info,
1015 session->global->application_key);
1016 if (session_info->session_key.data == NULL) {
1017 data_blob_free(&nt_resp);
1018 data_blob_free(&lm_resp);
1019 TALLOC_FREE(session);
1020 reply_nterror(req, NT_STATUS_NO_MEMORY);
1021 END_PROFILE(SMBsesssetupX);
1022 return;
1026 session->compat = talloc_zero(session, struct user_struct);
1027 if (session->compat == NULL) {
1028 data_blob_free(&nt_resp);
1029 data_blob_free(&lm_resp);
1030 TALLOC_FREE(session);
1031 reply_nterror(req, NT_STATUS_NO_MEMORY);
1032 END_PROFILE(SMBsesssetupX);
1033 return;
1035 session->compat->session = session;
1036 session->compat->homes_snum = -1;
1037 session->compat->session_info = session_info;
1038 session->compat->session_keystr = NULL;
1039 session->compat->vuid = session->global->session_wire_id;
1040 DLIST_ADD(sconn->users, session->compat);
1041 sconn->num_users++;
1043 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1044 is_authenticated = true;
1045 session->compat->homes_snum =
1046 register_homes_share(session_info->unix_info->unix_name);
1049 if (srv_is_signing_negotiated(xconn) &&
1050 is_authenticated &&
1051 session->global->signing_key.length > 0)
1054 * Try and turn on server signing on the first non-guest
1055 * sessionsetup.
1057 srv_set_signing(xconn,
1058 session->global->signing_key,
1059 nt_resp.data ? nt_resp : lm_resp);
1062 set_current_user_info(session_info->unix_info->sanitized_username,
1063 session_info->unix_info->unix_name,
1064 session_info->info->domain_name);
1066 session->status = NT_STATUS_OK;
1067 session->global->auth_session_info = talloc_move(session->global,
1068 &session_info);
1069 session->global->auth_session_info_seqnum += 1;
1070 session->global->channels[0].auth_session_info_seqnum =
1071 session->global->auth_session_info_seqnum;
1072 session->global->auth_time = now;
1073 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1075 nt_status = smbXsrv_session_update(session);
1076 if (!NT_STATUS_IS_OK(nt_status)) {
1077 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1078 (unsigned long long)session->compat->vuid,
1079 nt_errstr(nt_status)));
1080 data_blob_free(&nt_resp);
1081 data_blob_free(&lm_resp);
1082 TALLOC_FREE(session);
1083 reply_nterror(req, nt_status_squash(nt_status));
1084 END_PROFILE(SMBsesssetupX);
1085 return;
1088 if (!session_claim(session)) {
1089 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1090 (unsigned long long)session->compat->vuid));
1091 data_blob_free(&nt_resp);
1092 data_blob_free(&lm_resp);
1093 TALLOC_FREE(session);
1094 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1095 END_PROFILE(SMBsesssetupX);
1096 return;
1099 /* current_user_info is changed on new vuid */
1100 reload_services(sconn, conn_snum_used, true);
1102 sess_vuid = session->global->session_wire_id;
1104 data_blob_free(&nt_resp);
1105 data_blob_free(&lm_resp);
1107 SSVAL(req->outbuf,smb_vwv2,action);
1108 SSVAL(req->outbuf,smb_uid,sess_vuid);
1109 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1110 req->vuid = sess_vuid;
1112 if (!xconn->smb1.sessions.done_sesssetup) {
1113 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1114 reply_force_doserror(req, ERRSRV, ERRerror);
1115 END_PROFILE(SMBsesssetupX);
1116 return;
1118 xconn->smb1.sessions.max_send = smb_bufsize;
1119 xconn->smb1.sessions.done_sesssetup = true;
1122 END_PROFILE(SMBsesssetupX);