idl: Remove unused KRB5_EDATA_NTSTATUS
[samba4-gss.git] / source3 / smbd / smb1_sesssetup.c
blob443791bcc0d9de99e53322342f13080b7c5d1564
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 "lib/util/server_id.h"
28 #include "smbd/smbd.h"
29 #include "smbd/globals.h"
30 #include "source3/smbd/smbXsrv_session.h"
31 #include "auth.h"
32 #include "messages.h"
33 #include "smbprofile.h"
34 #include "../libcli/security/security.h"
35 #include "auth/gensec/gensec.h"
36 #include "../libcli/smb/smb_signing.h"
37 #include "lib/util/string_wrappers.h"
38 #include "source3/lib/substitute.h"
40 /****************************************************************************
41 Add the standard 'Samba' signature to the end of the session setup.
42 ****************************************************************************/
44 static int push_signature(uint8_t **outbuf)
46 char *lanman;
47 int result, tmp;
48 fstring native_os;
50 result = 0;
52 fstr_sprintf(native_os, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION,
53 SAMBA_MINOR_NBT_ANNOUNCE_VERSION);
55 tmp = message_push_string(outbuf, native_os, STR_TERMINATE);
57 if (tmp == -1) return -1;
58 result += tmp;
60 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
61 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
62 SAFE_FREE(lanman);
64 else {
65 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
68 if (tmp == -1) return -1;
69 result += tmp;
71 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
73 if (tmp == -1) return -1;
74 result += tmp;
76 return result;
79 /****************************************************************************
80 Reply to a session setup command.
81 conn POINTER CAN BE NULL HERE !
82 ****************************************************************************/
84 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
86 const uint8_t *p;
87 DATA_BLOB in_blob;
88 DATA_BLOB out_blob = data_blob_null;
89 size_t bufrem;
90 char *tmp = NULL;
91 const char *native_os;
92 const char *native_lanman;
93 const char *primary_domain;
94 uint16_t data_blob_len = SVAL(req->vwv+7, 0);
95 enum remote_arch_types ra_type = get_remote_arch();
96 uint64_t vuid = req->vuid;
97 NTSTATUS status = NT_STATUS_OK;
98 struct smbXsrv_connection *xconn = req->xconn;
99 struct smbd_server_connection *sconn = req->sconn;
100 uint16_t action = 0;
101 bool is_authenticated = false;
102 NTTIME now = timeval_to_nttime(&req->request_time);
103 struct smbXsrv_session *session = NULL;
104 uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
105 uint32_t client_caps = IVAL(req->vwv+10, 0);
106 struct smbXsrv_session_auth0 *auth;
108 DEBUG(3,("Doing spnego session setup\n"));
110 if (!xconn->smb1.sessions.done_sesssetup) {
111 global_client_caps = client_caps;
113 if (!(global_client_caps & CAP_STATUS32)) {
114 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
118 p = req->buf;
120 if (data_blob_len == 0) {
121 /* an invalid request */
122 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
123 return;
126 bufrem = smbreq_bufrem(req, p);
127 /* pull the spnego blob */
128 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
130 #if 0
131 file_save("negotiate.dat", in_blob.data, in_blob.length);
132 #endif
134 p = req->buf + in_blob.length;
136 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
137 STR_TERMINATE);
138 native_os = tmp ? tmp : "";
140 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
141 STR_TERMINATE);
142 native_lanman = tmp ? tmp : "";
144 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
145 STR_TERMINATE);
146 primary_domain = tmp ? tmp : "";
148 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
149 native_os, native_lanman, primary_domain));
151 if ( ra_type == RA_WIN2K ) {
152 /* Vista sets neither the OS or lanman strings */
154 if ( !strlen(native_os) && !strlen(native_lanman) )
155 set_remote_arch(RA_VISTA);
157 /* Windows 2003 doesn't set the native lanman string,
158 but does set primary domain which is a bug I think */
160 if ( !strlen(native_lanman) ) {
161 ra_lanman_string( primary_domain );
162 } else {
163 ra_lanman_string( native_lanman );
165 } else if ( ra_type == RA_VISTA ) {
166 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
167 set_remote_arch(RA_OSX);
171 if (vuid != 0) {
172 status = smb1srv_session_lookup(xconn,
173 vuid, now,
174 &session);
175 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
176 reply_force_doserror(req, ERRSRV, ERRbaduid);
177 return;
179 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
180 status = NT_STATUS_OK;
182 if (NT_STATUS_IS_OK(status)) {
183 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
184 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
185 TALLOC_FREE(session->pending_auth);
187 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
188 reply_nterror(req, nt_status_squash(status));
189 return;
193 if (session == NULL) {
194 /* create a new session */
195 status = smbXsrv_session_create(xconn,
196 now, &session);
197 if (!NT_STATUS_IS_OK(status)) {
198 reply_nterror(req, nt_status_squash(status));
199 return;
203 status = smbXsrv_session_find_auth(session, xconn, now, &auth);
204 if (!NT_STATUS_IS_OK(status)) {
205 status = smbXsrv_session_create_auth(session, xconn, now,
206 0, /* flags */
207 0, /* security */
208 &auth);
209 if (!NT_STATUS_IS_OK(status)) {
210 reply_nterror(req, nt_status_squash(status));
211 return;
215 if (auth->gensec == NULL) {
216 status = auth_generic_prepare(session,
217 xconn->remote_address,
218 xconn->local_address,
219 "SMB",
220 &auth->gensec);
221 if (!NT_STATUS_IS_OK(status)) {
222 TALLOC_FREE(session);
223 reply_nterror(req, nt_status_squash(status));
224 return;
227 gensec_want_feature(auth->gensec, GENSEC_FEATURE_SESSION_KEY);
228 gensec_want_feature(auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
229 gensec_want_feature(auth->gensec, GENSEC_FEATURE_SMB_TRANSPORT);
231 status = gensec_start_mech_by_oid(auth->gensec,
232 GENSEC_OID_SPNEGO);
233 if (!NT_STATUS_IS_OK(status)) {
234 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
235 TALLOC_FREE(session);;
236 reply_nterror(req, nt_status_squash(status));
237 return;
241 become_root();
242 status = gensec_update(auth->gensec,
243 talloc_tos(),
244 in_blob, &out_blob);
245 unbecome_root();
246 if (!NT_STATUS_IS_OK(status) &&
247 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
248 TALLOC_FREE(session);
249 reply_nterror(req, nt_status_squash(status));
250 return;
253 if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
254 struct auth_session_info *session_info = NULL;
256 status = gensec_session_info(auth->gensec,
257 session,
258 &session_info);
259 if (!NT_STATUS_IS_OK(status)) {
260 DEBUG(1,("Failed to generate session_info "
261 "(user and group token) for session setup: %s\n",
262 nt_errstr(status)));
263 data_blob_free(&out_blob);
264 TALLOC_FREE(session);
265 reply_nterror(req, nt_status_squash(status));
266 return;
269 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
270 action |= SMB_SETUP_GUEST;
273 session->global->signing_algo = SMB2_SIGNING_MD5_SMB1;
274 session->global->encryption_cipher = 0;
275 session->global->channels[0].signing_algo =
276 session->global->signing_algo;
277 session->global->channels[0].encryption_cipher =
278 session->global->encryption_cipher;
280 if (session_info->session_key.length > 0) {
281 struct smbXsrv_session *x = session;
283 status = smb2_signing_key_sign_create(x->global,
284 x->global->signing_algo,
285 &session_info->session_key,
286 NULL, /* no derivation */
287 &x->global->signing_key);
288 if (!NT_STATUS_IS_OK(status)) {
289 data_blob_free(&out_blob);
290 TALLOC_FREE(session);
291 reply_nterror(req, status);
292 return;
294 x->global->signing_key_blob = x->global->signing_key->blob;
297 * clear the session key
298 * the first tcon will add setup the application key
300 data_blob_clear_free(&session_info->session_key);
303 sconn->num_users++;
305 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
306 is_authenticated = true;
307 session->homes_snum =
308 register_homes_share(session_info->unix_info->unix_name);
311 if (smb1_srv_is_signing_negotiated(xconn) &&
312 is_authenticated &&
313 smb2_signing_key_valid(session->global->signing_key))
316 * Try and turn on server signing on the first non-guest
317 * sessionsetup.
319 smb1_srv_set_signing(xconn,
320 session->global->signing_key->blob,
321 data_blob_null);
324 set_current_user_info(session_info->unix_info->sanitized_username,
325 session_info->unix_info->unix_name,
326 session_info->info->domain_name);
328 session->status = NT_STATUS_OK;
329 session->global->auth_session_info = talloc_move(session->global,
330 &session_info);
331 session->global->auth_session_info_seqnum += 1;
332 session->global->channels[0].auth_session_info_seqnum =
333 session->global->auth_session_info_seqnum;
334 session->global->auth_time = now;
335 if (client_caps & CAP_DYNAMIC_REAUTH) {
336 session->global->expiration_time =
337 gensec_expire_time(auth->gensec);
338 } else {
339 session->global->expiration_time =
340 GENSEC_EXPIRE_TIME_INFINITY;
343 if (!session_claim(session)) {
344 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
345 (unsigned long long)session->global->session_wire_id));
346 data_blob_free(&out_blob);
347 TALLOC_FREE(session);
348 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
349 return;
352 status = smbXsrv_session_update(session);
353 if (!NT_STATUS_IS_OK(status)) {
354 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
355 (unsigned long long)session->global->session_wire_id,
356 nt_errstr(status)));
357 data_blob_free(&out_blob);
358 TALLOC_FREE(session);
359 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
360 return;
363 if (!xconn->smb1.sessions.done_sesssetup) {
364 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
365 reply_force_doserror(req, ERRSRV, ERRerror);
366 return;
368 xconn->smb1.sessions.max_send = smb_bufsize;
369 xconn->smb1.sessions.done_sesssetup = true;
372 /* current_user_info is changed on new vuid */
373 reload_services(sconn, conn_snum_used, true);
374 } else if (NT_STATUS_IS_OK(status)) {
375 struct auth_session_info *session_info = NULL;
377 status = gensec_session_info(auth->gensec,
378 session,
379 &session_info);
380 if (!NT_STATUS_IS_OK(status)) {
381 DEBUG(1,("Failed to generate session_info "
382 "(user and group token) for session setup: %s\n",
383 nt_errstr(status)));
384 data_blob_free(&out_blob);
385 TALLOC_FREE(session);
386 reply_nterror(req, nt_status_squash(status));
387 return;
390 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
391 action |= SMB_SETUP_GUEST;
395 * Keep the application key
397 data_blob_clear_free(&session_info->session_key);
398 session_info->session_key =
399 session->global->auth_session_info->session_key;
400 talloc_steal(session_info, session_info->session_key.data);
401 TALLOC_FREE(session->global->auth_session_info);
403 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
404 session->homes_snum =
405 register_homes_share(session_info->unix_info->unix_name);
408 set_current_user_info(session_info->unix_info->sanitized_username,
409 session_info->unix_info->unix_name,
410 session_info->info->domain_name);
412 session->status = NT_STATUS_OK;
413 session->global->auth_session_info = talloc_move(session->global,
414 &session_info);
415 session->global->auth_session_info_seqnum += 1;
416 session->global->channels[0].auth_session_info_seqnum =
417 session->global->auth_session_info_seqnum;
418 session->global->auth_time = now;
419 if (client_caps & CAP_DYNAMIC_REAUTH) {
420 session->global->expiration_time =
421 gensec_expire_time(auth->gensec);
422 } else {
423 session->global->expiration_time =
424 GENSEC_EXPIRE_TIME_INFINITY;
427 status = smbXsrv_session_update(session);
428 if (!NT_STATUS_IS_OK(status)) {
429 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
430 (unsigned long long)session->global->session_wire_id,
431 nt_errstr(status)));
432 data_blob_free(&out_blob);
433 TALLOC_FREE(session);
434 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
435 return;
438 conn_clear_vuid_caches(sconn, session->global->session_wire_id);
440 /* current_user_info is changed on new vuid */
441 reload_services(sconn, conn_snum_used, true);
444 vuid = session->global->session_wire_id;
446 reply_smb1_outbuf(req, 4, 0);
448 SSVAL(req->outbuf, smb_uid, vuid);
449 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
450 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
451 SSVAL(req->outbuf, smb_vwv2, action);
452 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
454 if (message_push_blob(&req->outbuf, out_blob) == -1) {
455 data_blob_free(&out_blob);
456 TALLOC_FREE(session);
457 reply_nterror(req, NT_STATUS_NO_MEMORY);
458 return;
460 data_blob_free(&out_blob);
462 if (push_signature(&req->outbuf) == -1) {
463 TALLOC_FREE(session);
464 reply_nterror(req, NT_STATUS_NO_MEMORY);
465 return;
469 /****************************************************************************
470 On new VC == 0, shutdown *all* old connections and users.
471 It seems that only NT4.x does this. At W2K and above (XP etc.).
472 a new session setup with VC==0 is ignored.
473 ****************************************************************************/
475 struct shutdown_state {
476 const char *ip;
477 size_t ip_length;
478 struct messaging_context *msg_ctx;
481 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
482 void *private_data)
484 struct shutdown_state *state = (struct shutdown_state *)private_data;
485 struct server_id self_pid = messaging_server_id(state->msg_ctx);
486 struct server_id pid = session->channels[0].server_id;
487 const char *addr = session->channels[0].remote_address;
488 const char *port_colon;
489 size_t addr_len;
490 struct server_id_buf tmp;
492 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
493 server_id_str_buf(pid, &tmp), addr));
495 if (!process_exists(pid)) {
496 DEBUG(10, ("process does not exist\n"));
497 return 0;
500 if (server_id_equal(&pid, &self_pid)) {
501 DEBUG(10, ("It's me\n"));
502 return 0;
505 port_colon = strrchr(addr, ':');
506 if (port_colon == NULL) {
507 DBG_DEBUG("addr %s in contains no port\n", addr);
508 return 0;
510 addr_len = port_colon - addr;
512 if ((addr_len != state->ip_length) ||
513 (strncmp(addr, state->ip, state->ip_length) != 0)) {
514 DEBUG(10, ("%s (%zu) does not match %s (%zu)\n",
515 state->ip, state->ip_length, addr, addr_len));
516 return 0;
519 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
520 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
521 state->ip));
523 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
524 &data_blob_null);
525 return 0;
528 static void setup_new_vc_session(struct smbd_server_connection *sconn)
530 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
531 "compatible we would close all old resources.\n"));
533 if (lp_reset_on_zero_vc()) {
534 char *addr;
535 const char *port_colon;
536 struct shutdown_state state;
538 addr = tsocket_address_string(
539 sconn->remote_address, talloc_tos());
540 if (addr == NULL) {
541 return;
543 state.ip = addr;
545 port_colon = strrchr(addr, ':');
546 if (port_colon == NULL) {
547 return;
549 state.ip_length = port_colon - addr;
550 state.msg_ctx = sconn->msg_ctx;
551 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
552 TALLOC_FREE(addr);
556 /****************************************************************************
557 Reply to a session setup command.
558 ****************************************************************************/
560 struct reply_sesssetup_and_X_state {
561 struct smb_request *req;
562 struct auth4_context *auth_context;
563 struct auth_usersupplied_info *user_info;
564 const char *user;
565 const char *domain;
566 DATA_BLOB lm_resp;
567 DATA_BLOB nt_resp;
568 DATA_BLOB plaintext_password;
571 static int reply_sesssetup_and_X_state_destructor(
572 struct reply_sesssetup_and_X_state *state)
574 data_blob_clear_free(&state->nt_resp);
575 data_blob_clear_free(&state->lm_resp);
576 data_blob_clear_free(&state->plaintext_password);
577 return 0;
580 void reply_sesssetup_and_X(struct smb_request *req)
582 struct reply_sesssetup_and_X_state *state = NULL;
583 uint64_t sess_vuid;
584 uint16_t smb_bufsize;
585 char *tmp = NULL;
586 fstring sub_user; /* Sanitised username for substitution */
587 const char *native_os;
588 const char *native_lanman;
589 const char *primary_domain;
590 struct auth_session_info *session_info = NULL;
591 uint16_t smb_flag2 = req->flags2;
592 uint16_t action = 0;
593 bool is_authenticated = false;
594 NTTIME now = timeval_to_nttime(&req->request_time);
595 struct smbXsrv_session *session = NULL;
596 NTSTATUS nt_status;
597 struct smbXsrv_connection *xconn = req->xconn;
598 struct smbd_server_connection *sconn = req->sconn;
599 bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
600 bool signing_allowed = false;
601 bool signing_mandatory = smb1_signing_is_mandatory(
602 xconn->smb1.signing_state);
604 START_PROFILE(SMBsesssetupX);
606 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
608 state = talloc_zero(req, struct reply_sesssetup_and_X_state);
609 if (state == NULL) {
610 reply_nterror(req, NT_STATUS_NO_MEMORY);
611 END_PROFILE(SMBsesssetupX);
612 return;
614 state->req = req;
615 talloc_set_destructor(state, reply_sesssetup_and_X_state_destructor);
617 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
618 signing_allowed = true;
620 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
621 signing_mandatory = true;
625 * We can call smb1_srv_set_signing_negotiated() each time.
626 * It finds out when it needs to turn into a noop
627 * itself.
629 smb1_srv_set_signing_negotiated(xconn,
630 signing_allowed,
631 signing_mandatory);
633 /* a SPNEGO session setup has 12 command words, whereas a normal
634 NT1 session setup has 13. See the cifs spec. */
635 if (req->wct == 12 &&
636 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
638 if (!xconn->smb1.negprot.spnego) {
639 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
640 "at SPNEGO session setup when it was not "
641 "negotiated.\n"));
642 reply_nterror(req, nt_status_squash(
643 NT_STATUS_LOGON_FAILURE));
644 END_PROFILE(SMBsesssetupX);
645 return;
648 if (SVAL(req->vwv+4, 0) == 0) {
649 setup_new_vc_session(req->sconn);
652 reply_sesssetup_and_X_spnego(req);
653 END_PROFILE(SMBsesssetupX);
654 return;
657 smb_bufsize = SVAL(req->vwv+2, 0);
659 if (xconn->protocol < PROTOCOL_NT1) {
660 uint16_t passlen1 = SVAL(req->vwv+7, 0);
662 /* Never do NT status codes with protocols before NT1 as we
663 * don't get client caps. */
664 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
666 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
667 reply_nterror(req, nt_status_squash(
668 NT_STATUS_INVALID_PARAMETER));
669 END_PROFILE(SMBsesssetupX);
670 return;
673 if (doencrypt) {
674 state->lm_resp = data_blob_talloc(state,
675 req->buf,
676 passlen1);
677 } else {
678 state->plaintext_password = data_blob_talloc(state,
679 req->buf,
680 passlen1+1);
681 /* Ensure null termination */
682 state->plaintext_password.data[passlen1] = 0;
685 srvstr_pull_req_talloc(state, req, &tmp,
686 req->buf + passlen1, STR_TERMINATE);
687 state->user = tmp ? tmp : "";
689 state->domain = "";
691 } else {
692 uint16_t passlen1 = SVAL(req->vwv+7, 0);
693 uint16_t passlen2 = SVAL(req->vwv+8, 0);
694 enum remote_arch_types ra_type = get_remote_arch();
695 const uint8_t *p = req->buf;
696 const uint8_t *save_p = req->buf;
697 uint16_t byte_count;
699 if (!xconn->smb1.sessions.done_sesssetup) {
700 global_client_caps = IVAL(req->vwv+11, 0);
702 if (!(global_client_caps & CAP_STATUS32)) {
703 remove_from_common_flags2(
704 FLAGS2_32_BIT_ERROR_CODES);
707 /* client_caps is used as final determination if
708 * client is NT or Win95. This is needed to return
709 * the correct error codes in some circumstances.
712 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
713 ra_type == RA_WIN95) {
714 if(!(global_client_caps & (CAP_NT_SMBS|
715 CAP_STATUS32))) {
716 set_remote_arch( RA_WIN95);
721 if (!doencrypt) {
722 /* both Win95 and WinNT stuff up the password
723 * lengths for non-encrypting systems. Uggh.
725 if passlen1==24 its a win95 system, and its setting
726 the password length incorrectly. Luckily it still
727 works with the default code because Win95 will null
728 terminate the password anyway
730 if passlen1>0 and passlen2>0 then maybe its a NT box
731 and its setting passlen2 to some random value which
732 really stuffs things up. we need to fix that one. */
734 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
735 passlen2 != 1) {
736 passlen2 = 0;
740 /* check for nasty tricks */
741 if (passlen1 > MAX_PASS_LEN
742 || passlen1 > smbreq_bufrem(req, p)) {
743 reply_nterror(req, nt_status_squash(
744 NT_STATUS_INVALID_PARAMETER));
745 END_PROFILE(SMBsesssetupX);
746 return;
749 if (passlen2 > MAX_PASS_LEN
750 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
751 reply_nterror(req, nt_status_squash(
752 NT_STATUS_INVALID_PARAMETER));
753 END_PROFILE(SMBsesssetupX);
754 return;
757 /* Save the lanman2 password and the NT md4 password. */
759 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
760 doencrypt = False;
763 if (doencrypt) {
764 state->lm_resp = data_blob_talloc(state, p, passlen1);
765 state->nt_resp = data_blob_talloc(state, p+passlen1, passlen2);
766 } else {
767 char *pass = NULL;
768 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
770 if (unic && (passlen2 == 0) && passlen1) {
771 /* Only a ascii plaintext password was sent. */
772 (void)srvstr_pull_talloc(state,
773 req->inbuf,
774 req->flags2,
775 &pass,
776 req->buf,
777 passlen1,
778 STR_TERMINATE|STR_ASCII);
779 } else {
780 (void)srvstr_pull_talloc(state,
781 req->inbuf,
782 req->flags2,
783 &pass,
784 req->buf,
785 unic ? passlen2 : passlen1,
786 STR_TERMINATE);
788 if (!pass) {
789 reply_nterror(req, nt_status_squash(
790 NT_STATUS_INVALID_PARAMETER));
791 END_PROFILE(SMBsesssetupX);
792 return;
794 state->plaintext_password = data_blob_talloc(state,
795 pass,
796 strlen(pass)+1);
799 p += passlen1 + passlen2;
801 p += srvstr_pull_req_talloc(state, req, &tmp, p,
802 STR_TERMINATE);
803 state->user = tmp ? tmp : "";
805 p += srvstr_pull_req_talloc(state, req, &tmp, p,
806 STR_TERMINATE);
807 state->domain = tmp ? tmp : "";
809 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
810 STR_TERMINATE);
811 native_os = tmp ? tmp : "";
813 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
814 STR_TERMINATE);
815 native_lanman = tmp ? tmp : "";
817 /* not documented or decoded by Ethereal but there is one more
818 * string in the extra bytes which is the same as the
819 * PrimaryDomain when using extended security. Windows NT 4
820 * and 2003 use this string to store the native lanman string.
821 * Windows 9x does not include a string here at all so we have
822 * to check if we have any extra bytes left */
824 byte_count = SVAL(req->vwv+13, 0);
825 if ( PTR_DIFF(p, save_p) < byte_count) {
826 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
827 STR_TERMINATE);
828 primary_domain = tmp ? tmp : "";
829 } else {
830 primary_domain = talloc_strdup(talloc_tos(), "null");
833 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
834 "PrimaryDomain=[%s]\n",
835 state->domain, native_os, native_lanman, primary_domain));
837 if ( ra_type == RA_WIN2K ) {
838 if ( strlen(native_lanman) == 0 )
839 ra_lanman_string( primary_domain );
840 else
841 ra_lanman_string( native_lanman );
846 if (SVAL(req->vwv+4, 0) == 0) {
847 setup_new_vc_session(req->sconn);
850 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
851 state->domain, state->user, get_remote_machine_name()));
853 if (*state->user) {
854 if (xconn->smb1.negprot.spnego) {
856 /* This has to be here, because this is a perfectly
857 * valid behaviour for guest logons :-( */
859 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
860 "at 'normal' session setup after "
861 "negotiating spnego.\n"));
862 reply_nterror(req, nt_status_squash(
863 NT_STATUS_LOGON_FAILURE));
864 END_PROFILE(SMBsesssetupX);
865 return;
867 fstrcpy(sub_user, state->user);
868 } else {
869 fstrcpy(sub_user, "");
872 if (!*state->user) {
873 DEBUG(3,("Got anonymous request\n"));
875 nt_status = make_auth4_context(state, &state->auth_context);
876 if (NT_STATUS_IS_OK(nt_status)) {
877 uint8_t chal[8];
879 state->auth_context->get_ntlm_challenge(
880 state->auth_context, chal);
882 if (!make_user_info_guest(state,
883 sconn->remote_address,
884 sconn->local_address,
885 "SMB", &state->user_info)) {
886 nt_status = NT_STATUS_NO_MEMORY;
889 if (NT_STATUS_IS_OK(nt_status)) {
890 state->user_info->auth_description = "guest";
893 } else if (doencrypt) {
894 state->auth_context = xconn->smb1.negprot.auth_context;
895 if (state->auth_context == NULL) {
896 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
897 "session setup without negprot denied!\n"));
898 reply_nterror(req, nt_status_squash(
899 NT_STATUS_LOGON_FAILURE));
900 END_PROFILE(SMBsesssetupX);
901 return;
903 nt_status = make_user_info_for_reply_enc(state,
904 &state->user_info,
905 state->user,
906 state->domain,
907 sconn->remote_address,
908 sconn->local_address,
909 "SMB",
910 state->lm_resp,
911 state->nt_resp);
913 if (NT_STATUS_IS_OK(nt_status)) {
914 state->user_info->auth_description = "bare-NTLM";
916 } else {
917 nt_status = make_auth4_context(state, &state->auth_context);
918 if (NT_STATUS_IS_OK(nt_status)) {
919 uint8_t chal[8];
921 state->auth_context->get_ntlm_challenge(
922 state->auth_context, chal);
924 if (!make_user_info_for_reply(state,
925 &state->user_info,
926 state->user,
927 state->domain,
928 sconn->remote_address,
929 sconn->local_address,
930 "SMB",
931 chal,
932 state->plaintext_password)) {
933 nt_status = NT_STATUS_NO_MEMORY;
936 if (NT_STATUS_IS_OK(nt_status)) {
937 state->user_info->auth_description = "plaintext";
942 if (!NT_STATUS_IS_OK(nt_status)) {
943 reply_nterror(req, nt_status_squash(nt_status));
944 END_PROFILE(SMBsesssetupX);
945 return;
948 nt_status = auth_check_password_session_info(state->auth_context,
949 req, state->user_info,
950 &session_info);
951 TALLOC_FREE(state->user_info);
952 if (!NT_STATUS_IS_OK(nt_status)) {
953 reply_nterror(req, nt_status_squash(nt_status));
954 END_PROFILE(SMBsesssetupX);
955 return;
958 /* it's ok - setup a reply */
959 reply_smb1_outbuf(req, 3, 0);
960 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
961 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
963 if (xconn->protocol >= PROTOCOL_NT1) {
964 push_signature(&req->outbuf);
965 /* perhaps grab OS version here?? */
968 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
969 action |= SMB_SETUP_GUEST;
972 /* register the name and uid as being validated, so further connections
973 to a uid can get through without a password, on the same VC */
975 nt_status = smbXsrv_session_create(xconn,
976 now, &session);
977 if (!NT_STATUS_IS_OK(nt_status)) {
978 reply_nterror(req, nt_status_squash(nt_status));
979 END_PROFILE(SMBsesssetupX);
980 return;
983 session->global->signing_algo = SMB2_SIGNING_MD5_SMB1;
984 session->global->encryption_cipher = 0;
985 session->global->channels[0].signing_algo =
986 session->global->signing_algo;
987 session->global->channels[0].encryption_cipher =
988 session->global->encryption_cipher;
990 if (session_info->session_key.length > 0) {
991 struct smbXsrv_session *x = session;
992 uint8_t session_key[16];
993 NTSTATUS status;
995 status = smb2_signing_key_sign_create(x->global,
996 x->global->signing_algo,
997 &session_info->session_key,
998 NULL, /* no derivation */
999 &x->global->signing_key);
1000 if (!NT_STATUS_IS_OK(status)) {
1001 TALLOC_FREE(session);
1002 reply_nterror(req, status);
1003 END_PROFILE(SMBsesssetupX);
1004 return;
1006 x->global->signing_key_blob = x->global->signing_key->blob;
1009 * The application key is truncated/padded to 16 bytes
1011 ZERO_STRUCT(session_key);
1012 memcpy(session_key, session->global->signing_key_blob.data,
1013 MIN(session->global->signing_key_blob.length,
1014 sizeof(session_key)));
1015 session->global->application_key_blob =
1016 data_blob_talloc(session->global,
1017 session_key,
1018 sizeof(session_key));
1019 ZERO_STRUCT(session_key);
1020 if (session->global->application_key_blob.data == NULL) {
1021 TALLOC_FREE(session);
1022 reply_nterror(req, NT_STATUS_NO_MEMORY);
1023 END_PROFILE(SMBsesssetupX);
1024 return;
1026 talloc_keep_secret(session->global->application_key_blob.data);
1029 * Place the application key into the session_info
1031 data_blob_clear_free(&session_info->session_key);
1032 session_info->session_key = data_blob_dup_talloc(session_info,
1033 session->global->application_key_blob);
1034 if (session_info->session_key.data == NULL) {
1035 TALLOC_FREE(session);
1036 reply_nterror(req, NT_STATUS_NO_MEMORY);
1037 END_PROFILE(SMBsesssetupX);
1038 return;
1040 talloc_keep_secret(session_info->session_key.data);
1043 sconn->num_users++;
1045 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1046 is_authenticated = true;
1047 session->homes_snum =
1048 register_homes_share(session_info->unix_info->unix_name);
1051 if (smb1_srv_is_signing_negotiated(xconn) &&
1052 is_authenticated &&
1053 smb2_signing_key_valid(session->global->signing_key))
1056 * Try and turn on server signing on the first non-guest
1057 * sessionsetup.
1059 smb1_srv_set_signing(xconn,
1060 session->global->signing_key->blob,
1061 state->nt_resp.data ? state->nt_resp : state->lm_resp);
1064 set_current_user_info(session_info->unix_info->sanitized_username,
1065 session_info->unix_info->unix_name,
1066 session_info->info->domain_name);
1068 session->status = NT_STATUS_OK;
1069 session->global->auth_session_info = talloc_move(session->global,
1070 &session_info);
1071 session->global->auth_session_info_seqnum += 1;
1072 session->global->channels[0].auth_session_info_seqnum =
1073 session->global->auth_session_info_seqnum;
1074 session->global->auth_time = now;
1075 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1077 nt_status = smbXsrv_session_update(session);
1078 if (!NT_STATUS_IS_OK(nt_status)) {
1079 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1080 (unsigned long long)session->global->session_wire_id,
1081 nt_errstr(nt_status)));
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->global->session_wire_id));
1091 TALLOC_FREE(session);
1092 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1093 END_PROFILE(SMBsesssetupX);
1094 return;
1097 /* current_user_info is changed on new vuid */
1098 reload_services(sconn, conn_snum_used, true);
1100 sess_vuid = session->global->session_wire_id;
1102 SSVAL(req->outbuf,smb_vwv2,action);
1103 SSVAL(req->outbuf,smb_uid,sess_vuid);
1104 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1105 req->vuid = sess_vuid;
1107 if (!xconn->smb1.sessions.done_sesssetup) {
1108 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1109 reply_force_doserror(req, ERRSRV, ERRerror);
1110 END_PROFILE(SMBsesssetupX);
1111 return;
1113 xconn->smb1.sessions.max_send = smb_bufsize;
1114 xconn->smb1.sessions.done_sesssetup = true;
1117 TALLOC_FREE(state);
1118 END_PROFILE(SMBsesssetupX);