s4:torture: Remove unused header file
[Samba.git] / source3 / smbd / sesssetup.c
bloba607abb50100f7899c2283bcfb1bf9da40a7b01a
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 "auth.h"
31 #include "messages.h"
32 #include "smbprofile.h"
33 #include "../libcli/security/security.h"
34 #include "auth/gensec/gensec.h"
35 #include "lib/conn_tdb.h"
36 #include "../libcli/smb/smb_signing.h"
38 /****************************************************************************
39 Add the standard 'Samba' signature to the end of the session setup.
40 ****************************************************************************/
42 static int push_signature(uint8_t **outbuf)
44 char *lanman;
45 int result, tmp;
46 fstring native_os;
48 result = 0;
50 fstr_sprintf(native_os, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION,
51 SAMBA_MINOR_NBT_ANNOUNCE_VERSION);
53 tmp = message_push_string(outbuf, native_os, STR_TERMINATE);
55 if (tmp == -1) return -1;
56 result += tmp;
58 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
59 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
60 SAFE_FREE(lanman);
62 else {
63 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
66 if (tmp == -1) return -1;
67 result += tmp;
69 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
71 if (tmp == -1) return -1;
72 result += tmp;
74 return result;
77 /****************************************************************************
78 Reply to a session setup command.
79 conn POINTER CAN BE NULL HERE !
80 ****************************************************************************/
82 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
84 const uint8_t *p;
85 DATA_BLOB in_blob;
86 DATA_BLOB out_blob = data_blob_null;
87 size_t bufrem;
88 char *tmp;
89 const char *native_os;
90 const char *native_lanman;
91 const char *primary_domain;
92 uint16_t data_blob_len = SVAL(req->vwv+7, 0);
93 enum remote_arch_types ra_type = get_remote_arch();
94 uint64_t vuid = req->vuid;
95 NTSTATUS status = NT_STATUS_OK;
96 struct smbXsrv_connection *xconn = req->xconn;
97 struct smbd_server_connection *sconn = req->sconn;
98 uint16_t action = 0;
99 bool is_authenticated = false;
100 NTTIME now = timeval_to_nttime(&req->request_time);
101 struct smbXsrv_session *session = NULL;
102 uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
103 uint32_t client_caps = IVAL(req->vwv+10, 0);
104 struct smbXsrv_session_auth0 *auth;
106 DEBUG(3,("Doing spnego session setup\n"));
108 if (!xconn->smb1.sessions.done_sesssetup) {
109 global_client_caps = client_caps;
111 if (!(global_client_caps & CAP_STATUS32)) {
112 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
116 p = req->buf;
118 if (data_blob_len == 0) {
119 /* an invalid request */
120 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
121 return;
124 bufrem = smbreq_bufrem(req, p);
125 /* pull the spnego blob */
126 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
128 #if 0
129 file_save("negotiate.dat", in_blob.data, in_blob.length);
130 #endif
132 p = req->buf + in_blob.length;
134 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
135 STR_TERMINATE);
136 native_os = tmp ? tmp : "";
138 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
139 STR_TERMINATE);
140 native_lanman = tmp ? tmp : "";
142 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
143 STR_TERMINATE);
144 primary_domain = tmp ? tmp : "";
146 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
147 native_os, native_lanman, primary_domain));
149 if ( ra_type == RA_WIN2K ) {
150 /* Vista sets neither the OS or lanman strings */
152 if ( !strlen(native_os) && !strlen(native_lanman) )
153 set_remote_arch(RA_VISTA);
155 /* Windows 2003 doesn't set the native lanman string,
156 but does set primary domain which is a bug I think */
158 if ( !strlen(native_lanman) ) {
159 ra_lanman_string( primary_domain );
160 } else {
161 ra_lanman_string( native_lanman );
163 } else if ( ra_type == RA_VISTA ) {
164 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
165 set_remote_arch(RA_OSX);
169 if (vuid != 0) {
170 status = smb1srv_session_lookup(xconn,
171 vuid, now,
172 &session);
173 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
174 reply_force_doserror(req, ERRSRV, ERRbaduid);
175 return;
177 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
178 status = NT_STATUS_OK;
180 if (NT_STATUS_IS_OK(status)) {
181 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
182 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
183 TALLOC_FREE(session->pending_auth);
185 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
186 reply_nterror(req, nt_status_squash(status));
187 return;
191 if (session == NULL) {
192 /* create a new session */
193 status = smbXsrv_session_create(xconn,
194 now, &session);
195 if (!NT_STATUS_IS_OK(status)) {
196 reply_nterror(req, nt_status_squash(status));
197 return;
201 status = smbXsrv_session_find_auth(session, xconn, now, &auth);
202 if (!NT_STATUS_IS_OK(status)) {
203 status = smbXsrv_session_create_auth(session, xconn, now,
204 0, /* flags */
205 0, /* security */
206 &auth);
207 if (!NT_STATUS_IS_OK(status)) {
208 reply_nterror(req, nt_status_squash(status));
209 return;
213 if (auth->gensec == NULL) {
214 status = auth_generic_prepare(session,
215 xconn->remote_address,
216 xconn->local_address,
217 "SMB",
218 &auth->gensec);
219 if (!NT_STATUS_IS_OK(status)) {
220 TALLOC_FREE(session);
221 reply_nterror(req, nt_status_squash(status));
222 return;
225 gensec_want_feature(auth->gensec, GENSEC_FEATURE_SESSION_KEY);
226 gensec_want_feature(auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
227 gensec_want_feature(auth->gensec, GENSEC_FEATURE_SMB_TRANSPORT);
229 status = gensec_start_mech_by_oid(auth->gensec,
230 GENSEC_OID_SPNEGO);
231 if (!NT_STATUS_IS_OK(status)) {
232 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
233 TALLOC_FREE(session);;
234 reply_nterror(req, nt_status_squash(status));
235 return;
239 become_root();
240 status = gensec_update(auth->gensec,
241 talloc_tos(),
242 in_blob, &out_blob);
243 unbecome_root();
244 if (!NT_STATUS_IS_OK(status) &&
245 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
246 TALLOC_FREE(session);
247 reply_nterror(req, nt_status_squash(status));
248 return;
251 if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
252 struct auth_session_info *session_info = NULL;
254 status = gensec_session_info(auth->gensec,
255 session,
256 &session_info);
257 if (!NT_STATUS_IS_OK(status)) {
258 DEBUG(1,("Failed to generate session_info "
259 "(user and group token) for session setup: %s\n",
260 nt_errstr(status)));
261 data_blob_free(&out_blob);
262 TALLOC_FREE(session);
263 reply_nterror(req, nt_status_squash(status));
264 return;
267 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
268 action |= SMB_SETUP_GUEST;
271 if (session_info->session_key.length > 0) {
272 struct smbXsrv_session *x = session;
275 * Note: the SMB1 signing key is not truncated to 16 byte!
277 x->global->signing_key =
278 data_blob_dup_talloc(x->global,
279 session_info->session_key);
280 if (x->global->signing_key.data == NULL) {
281 data_blob_free(&out_blob);
282 TALLOC_FREE(session);
283 reply_nterror(req, NT_STATUS_NO_MEMORY);
284 return;
288 * clear the session key
289 * the first tcon will add setup the application key
291 data_blob_clear_free(&session_info->session_key);
294 session->compat = talloc_zero(session, struct user_struct);
295 if (session->compat == NULL) {
296 data_blob_free(&out_blob);
297 TALLOC_FREE(session);
298 reply_nterror(req, NT_STATUS_NO_MEMORY);
299 return;
301 session->compat->session = session;
302 session->compat->homes_snum = -1;
303 session->compat->session_info = session_info;
304 session->compat->session_keystr = NULL;
305 session->compat->vuid = session->global->session_wire_id;
306 DLIST_ADD(sconn->users, session->compat);
307 sconn->num_users++;
309 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
310 is_authenticated = true;
311 session->compat->homes_snum =
312 register_homes_share(session_info->unix_info->unix_name);
315 if (srv_is_signing_negotiated(xconn) &&
316 is_authenticated &&
317 session->global->signing_key.length > 0)
320 * Try and turn on server signing on the first non-guest
321 * sessionsetup.
323 srv_set_signing(xconn,
324 session->global->signing_key,
325 data_blob_null);
328 set_current_user_info(session_info->unix_info->sanitized_username,
329 session_info->unix_info->unix_name,
330 session_info->info->domain_name);
332 session->status = NT_STATUS_OK;
333 session->global->auth_session_info = talloc_move(session->global,
334 &session_info);
335 session->global->auth_session_info_seqnum += 1;
336 session->global->channels[0].auth_session_info_seqnum =
337 session->global->auth_session_info_seqnum;
338 session->global->auth_time = now;
339 if (client_caps & CAP_DYNAMIC_REAUTH) {
340 session->global->expiration_time =
341 gensec_expire_time(auth->gensec);
342 } else {
343 session->global->expiration_time =
344 GENSEC_EXPIRE_TIME_INFINITY;
347 if (!session_claim(session)) {
348 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
349 (unsigned long long)session->compat->vuid));
350 data_blob_free(&out_blob);
351 TALLOC_FREE(session);
352 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
353 return;
356 status = smbXsrv_session_update(session);
357 if (!NT_STATUS_IS_OK(status)) {
358 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
359 (unsigned long long)session->compat->vuid,
360 nt_errstr(status)));
361 data_blob_free(&out_blob);
362 TALLOC_FREE(session);
363 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
364 return;
367 if (!xconn->smb1.sessions.done_sesssetup) {
368 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
369 reply_force_doserror(req, ERRSRV, ERRerror);
370 return;
372 xconn->smb1.sessions.max_send = smb_bufsize;
373 xconn->smb1.sessions.done_sesssetup = true;
376 /* current_user_info is changed on new vuid */
377 reload_services(sconn, conn_snum_used, true);
378 } else if (NT_STATUS_IS_OK(status)) {
379 struct auth_session_info *session_info = NULL;
381 status = gensec_session_info(auth->gensec,
382 session,
383 &session_info);
384 if (!NT_STATUS_IS_OK(status)) {
385 DEBUG(1,("Failed to generate session_info "
386 "(user and group token) for session setup: %s\n",
387 nt_errstr(status)));
388 data_blob_free(&out_blob);
389 TALLOC_FREE(session);
390 reply_nterror(req, nt_status_squash(status));
391 return;
394 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
395 action |= SMB_SETUP_GUEST;
399 * Keep the application key
401 data_blob_clear_free(&session_info->session_key);
402 session_info->session_key =
403 session->global->auth_session_info->session_key;
404 talloc_steal(session_info, session_info->session_key.data);
405 TALLOC_FREE(session->global->auth_session_info);
407 session->compat->session_info = session_info;
409 session->compat->vuid = session->global->session_wire_id;
411 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
412 session->compat->homes_snum =
413 register_homes_share(session_info->unix_info->unix_name);
416 set_current_user_info(session_info->unix_info->sanitized_username,
417 session_info->unix_info->unix_name,
418 session_info->info->domain_name);
420 session->status = NT_STATUS_OK;
421 session->global->auth_session_info = talloc_move(session->global,
422 &session_info);
423 session->global->auth_session_info_seqnum += 1;
424 session->global->channels[0].auth_session_info_seqnum =
425 session->global->auth_session_info_seqnum;
426 session->global->auth_time = now;
427 if (client_caps & CAP_DYNAMIC_REAUTH) {
428 session->global->expiration_time =
429 gensec_expire_time(auth->gensec);
430 } else {
431 session->global->expiration_time =
432 GENSEC_EXPIRE_TIME_INFINITY;
435 status = smbXsrv_session_update(session);
436 if (!NT_STATUS_IS_OK(status)) {
437 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
438 (unsigned long long)session->compat->vuid,
439 nt_errstr(status)));
440 data_blob_free(&out_blob);
441 TALLOC_FREE(session);
442 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
443 return;
446 conn_clear_vuid_caches(sconn, session->compat->vuid);
448 /* current_user_info is changed on new vuid */
449 reload_services(sconn, conn_snum_used, true);
452 vuid = session->global->session_wire_id;
454 reply_outbuf(req, 4, 0);
456 SSVAL(req->outbuf, smb_uid, vuid);
457 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
458 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
459 SSVAL(req->outbuf, smb_vwv2, action);
460 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
462 if (message_push_blob(&req->outbuf, out_blob) == -1) {
463 data_blob_free(&out_blob);
464 TALLOC_FREE(session);
465 reply_nterror(req, NT_STATUS_NO_MEMORY);
466 return;
468 data_blob_free(&out_blob);
470 if (push_signature(&req->outbuf) == -1) {
471 TALLOC_FREE(session);
472 reply_nterror(req, NT_STATUS_NO_MEMORY);
473 return;
477 /****************************************************************************
478 On new VC == 0, shutdown *all* old connections and users.
479 It seems that only NT4.x does this. At W2K and above (XP etc.).
480 a new session setup with VC==0 is ignored.
481 ****************************************************************************/
483 struct shutdown_state {
484 const char *ip;
485 size_t ip_length;
486 struct messaging_context *msg_ctx;
489 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
490 void *private_data)
492 struct shutdown_state *state = (struct shutdown_state *)private_data;
493 struct server_id self_pid = messaging_server_id(state->msg_ctx);
494 struct server_id pid = session->channels[0].server_id;
495 const char *addr = session->channels[0].remote_address;
496 const char *port_colon;
497 size_t addr_len;
498 struct server_id_buf tmp;
500 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
501 server_id_str_buf(pid, &tmp), addr));
503 if (!process_exists(pid)) {
504 DEBUG(10, ("process does not exist\n"));
505 return 0;
508 if (serverid_equal(&pid, &self_pid)) {
509 DEBUG(10, ("It's me\n"));
510 return 0;
513 port_colon = strrchr(addr, ':');
514 if (port_colon == NULL) {
515 DBG_DEBUG("addr %s in contains no port\n", addr);
516 return 0;
518 addr_len = port_colon - addr;
520 if ((addr_len != state->ip_length) ||
521 (strncmp(addr, state->ip, state->ip_length) != 0)) {
522 DEBUG(10, ("%s (%zu) does not match %s (%zu)\n",
523 state->ip, state->ip_length, addr, addr_len));
524 return 0;
527 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
528 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
529 state->ip));
531 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
532 &data_blob_null);
533 return 0;
536 static void setup_new_vc_session(struct smbd_server_connection *sconn)
538 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
539 "compatible we would close all old resources.\n"));
541 if (lp_reset_on_zero_vc()) {
542 char *addr;
543 const char *port_colon;
544 struct shutdown_state state;
546 addr = tsocket_address_string(
547 sconn->remote_address, talloc_tos());
548 if (addr == NULL) {
549 return;
551 state.ip = addr;
553 port_colon = strrchr(addr, ':');
554 if (port_colon == NULL) {
555 return;
557 state.ip_length = port_colon - addr;
558 state.msg_ctx = sconn->msg_ctx;
559 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
560 TALLOC_FREE(addr);
564 /****************************************************************************
565 Reply to a session setup command.
566 ****************************************************************************/
568 struct reply_sesssetup_and_X_state {
569 struct smb_request *req;
570 struct auth4_context *auth_context;
571 struct auth_usersupplied_info *user_info;
572 const char *user;
573 const char *domain;
574 DATA_BLOB lm_resp;
575 DATA_BLOB nt_resp;
576 DATA_BLOB plaintext_password;
579 static int reply_sesssetup_and_X_state_destructor(
580 struct reply_sesssetup_and_X_state *state)
582 data_blob_clear_free(&state->nt_resp);
583 data_blob_clear_free(&state->lm_resp);
584 data_blob_clear_free(&state->plaintext_password);
585 return 0;
588 void reply_sesssetup_and_X(struct smb_request *req)
590 struct reply_sesssetup_and_X_state *state = NULL;
591 uint64_t sess_vuid;
592 uint16_t smb_bufsize;
593 char *tmp;
594 fstring sub_user; /* Sanitised username for substituion */
595 const char *native_os;
596 const char *native_lanman;
597 const char *primary_domain;
598 struct auth_session_info *session_info = NULL;
599 uint16_t smb_flag2 = req->flags2;
600 uint16_t action = 0;
601 bool is_authenticated = false;
602 NTTIME now = timeval_to_nttime(&req->request_time);
603 struct smbXsrv_session *session = NULL;
604 NTSTATUS nt_status;
605 struct smbXsrv_connection *xconn = req->xconn;
606 struct smbd_server_connection *sconn = req->sconn;
607 bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
608 bool signing_allowed = false;
609 bool signing_mandatory = smb_signing_is_mandatory(
610 xconn->smb1.signing_state);
612 START_PROFILE(SMBsesssetupX);
614 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
616 state = talloc_zero(req, struct reply_sesssetup_and_X_state);
617 if (state == NULL) {
618 reply_nterror(req, NT_STATUS_NO_MEMORY);
619 END_PROFILE(SMBsesssetupX);
620 return;
622 state->req = req;
623 talloc_set_destructor(state, reply_sesssetup_and_X_state_destructor);
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 state->lm_resp = data_blob_talloc(state,
683 req->buf,
684 passlen1);
685 } else {
686 state->plaintext_password = data_blob_talloc(state,
687 req->buf,
688 passlen1+1);
689 /* Ensure null termination */
690 state->plaintext_password.data[passlen1] = 0;
693 srvstr_pull_req_talloc(state, req, &tmp,
694 req->buf + passlen1, STR_TERMINATE);
695 state->user = tmp ? tmp : "";
697 state->domain = "";
699 } else {
700 uint16_t passlen1 = SVAL(req->vwv+7, 0);
701 uint16_t passlen2 = SVAL(req->vwv+8, 0);
702 enum remote_arch_types ra_type = get_remote_arch();
703 const uint8_t *p = req->buf;
704 const uint8_t *save_p = req->buf;
705 uint16_t byte_count;
707 if (!xconn->smb1.sessions.done_sesssetup) {
708 global_client_caps = IVAL(req->vwv+11, 0);
710 if (!(global_client_caps & CAP_STATUS32)) {
711 remove_from_common_flags2(
712 FLAGS2_32_BIT_ERROR_CODES);
715 /* client_caps is used as final determination if
716 * client is NT or Win95. This is needed to return
717 * the correct error codes in some circumstances.
720 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
721 ra_type == RA_WIN95) {
722 if(!(global_client_caps & (CAP_NT_SMBS|
723 CAP_STATUS32))) {
724 set_remote_arch( RA_WIN95);
729 if (!doencrypt) {
730 /* both Win95 and WinNT stuff up the password
731 * lengths for non-encrypting systems. Uggh.
733 if passlen1==24 its a win95 system, and its setting
734 the password length incorrectly. Luckily it still
735 works with the default code because Win95 will null
736 terminate the password anyway
738 if passlen1>0 and passlen2>0 then maybe its a NT box
739 and its setting passlen2 to some random value which
740 really stuffs things up. we need to fix that one. */
742 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
743 passlen2 != 1) {
744 passlen2 = 0;
748 /* check for nasty tricks */
749 if (passlen1 > MAX_PASS_LEN
750 || passlen1 > smbreq_bufrem(req, p)) {
751 reply_nterror(req, nt_status_squash(
752 NT_STATUS_INVALID_PARAMETER));
753 END_PROFILE(SMBsesssetupX);
754 return;
757 if (passlen2 > MAX_PASS_LEN
758 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
759 reply_nterror(req, nt_status_squash(
760 NT_STATUS_INVALID_PARAMETER));
761 END_PROFILE(SMBsesssetupX);
762 return;
765 /* Save the lanman2 password and the NT md4 password. */
767 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
768 doencrypt = False;
771 if (doencrypt) {
772 state->lm_resp = data_blob_talloc(state, p, passlen1);
773 state->nt_resp = data_blob_talloc(state, p+passlen1, passlen2);
774 } else {
775 char *pass = NULL;
776 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
778 if (unic && (passlen2 == 0) && passlen1) {
779 /* Only a ascii plaintext password was sent. */
780 (void)srvstr_pull_talloc(state,
781 req->inbuf,
782 req->flags2,
783 &pass,
784 req->buf,
785 passlen1,
786 STR_TERMINATE|STR_ASCII);
787 } else {
788 (void)srvstr_pull_talloc(state,
789 req->inbuf,
790 req->flags2,
791 &pass,
792 req->buf,
793 unic ? passlen2 : passlen1,
794 STR_TERMINATE);
796 if (!pass) {
797 reply_nterror(req, nt_status_squash(
798 NT_STATUS_INVALID_PARAMETER));
799 END_PROFILE(SMBsesssetupX);
800 return;
802 state->plaintext_password = data_blob_talloc(state,
803 pass,
804 strlen(pass)+1);
807 p += passlen1 + passlen2;
809 p += srvstr_pull_req_talloc(state, req, &tmp, p,
810 STR_TERMINATE);
811 state->user = tmp ? tmp : "";
813 p += srvstr_pull_req_talloc(state, req, &tmp, p,
814 STR_TERMINATE);
815 state->domain = tmp ? tmp : "";
817 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
818 STR_TERMINATE);
819 native_os = tmp ? tmp : "";
821 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
822 STR_TERMINATE);
823 native_lanman = tmp ? tmp : "";
825 /* not documented or decoded by Ethereal but there is one more
826 * string in the extra bytes which is the same as the
827 * PrimaryDomain when using extended security. Windows NT 4
828 * and 2003 use this string to store the native lanman string.
829 * Windows 9x does not include a string here at all so we have
830 * to check if we have any extra bytes left */
832 byte_count = SVAL(req->vwv+13, 0);
833 if ( PTR_DIFF(p, save_p) < byte_count) {
834 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
835 STR_TERMINATE);
836 primary_domain = tmp ? tmp : "";
837 } else {
838 primary_domain = talloc_strdup(talloc_tos(), "null");
841 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
842 "PrimaryDomain=[%s]\n",
843 state->domain, native_os, native_lanman, primary_domain));
845 if ( ra_type == RA_WIN2K ) {
846 if ( strlen(native_lanman) == 0 )
847 ra_lanman_string( primary_domain );
848 else
849 ra_lanman_string( native_lanman );
854 if (SVAL(req->vwv+4, 0) == 0) {
855 setup_new_vc_session(req->sconn);
858 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
859 state->domain, state->user, get_remote_machine_name()));
861 if (*state->user) {
862 if (xconn->smb1.negprot.spnego) {
864 /* This has to be here, because this is a perfectly
865 * valid behaviour for guest logons :-( */
867 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
868 "at 'normal' session setup after "
869 "negotiating spnego.\n"));
870 reply_nterror(req, nt_status_squash(
871 NT_STATUS_LOGON_FAILURE));
872 END_PROFILE(SMBsesssetupX);
873 return;
875 fstrcpy(sub_user, state->user);
876 } else {
877 fstrcpy(sub_user, "");
880 sub_set_smb_name(sub_user);
882 reload_services(sconn, conn_snum_used, true);
884 if (!*state->user) {
885 DEBUG(3,("Got anonymous request\n"));
887 nt_status = make_auth4_context(state, &state->auth_context);
888 if (NT_STATUS_IS_OK(nt_status)) {
889 uint8_t chal[8];
891 state->auth_context->get_ntlm_challenge(
892 state->auth_context, chal);
894 if (!make_user_info_guest(state,
895 sconn->remote_address,
896 sconn->local_address,
897 "SMB", &state->user_info)) {
898 nt_status = NT_STATUS_NO_MEMORY;
901 if (NT_STATUS_IS_OK(nt_status)) {
902 state->user_info->auth_description = "guest";
905 } else if (doencrypt) {
906 state->auth_context = xconn->smb1.negprot.auth_context;
907 if (state->auth_context == NULL) {
908 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
909 "session setup without negprot denied!\n"));
910 reply_nterror(req, nt_status_squash(
911 NT_STATUS_LOGON_FAILURE));
912 END_PROFILE(SMBsesssetupX);
913 return;
915 nt_status = make_user_info_for_reply_enc(state,
916 &state->user_info,
917 state->user,
918 state->domain,
919 sconn->remote_address,
920 sconn->local_address,
921 "SMB",
922 state->lm_resp,
923 state->nt_resp);
925 if (NT_STATUS_IS_OK(nt_status)) {
926 state->user_info->auth_description = "bare-NTLM";
928 } else {
929 nt_status = make_auth4_context(state, &state->auth_context);
930 if (NT_STATUS_IS_OK(nt_status)) {
931 uint8_t chal[8];
933 state->auth_context->get_ntlm_challenge(
934 state->auth_context, chal);
936 if (!make_user_info_for_reply(state,
937 &state->user_info,
938 state->user,
939 state->domain,
940 sconn->remote_address,
941 sconn->local_address,
942 "SMB",
943 chal,
944 state->plaintext_password)) {
945 nt_status = NT_STATUS_NO_MEMORY;
948 if (NT_STATUS_IS_OK(nt_status)) {
949 state->user_info->auth_description = "plaintext";
954 if (!NT_STATUS_IS_OK(nt_status)) {
955 reply_nterror(req, nt_status_squash(nt_status));
956 END_PROFILE(SMBsesssetupX);
957 return;
960 nt_status = auth_check_password_session_info(state->auth_context,
961 req, state->user_info,
962 &session_info);
963 TALLOC_FREE(state->user_info);
964 if (!NT_STATUS_IS_OK(nt_status)) {
965 reply_nterror(req, nt_status_squash(nt_status));
966 END_PROFILE(SMBsesssetupX);
967 return;
970 /* it's ok - setup a reply */
971 reply_outbuf(req, 3, 0);
972 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
973 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
975 if (get_Protocol() >= PROTOCOL_NT1) {
976 push_signature(&req->outbuf);
977 /* perhaps grab OS version here?? */
980 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
981 action |= SMB_SETUP_GUEST;
984 /* register the name and uid as being validated, so further connections
985 to a uid can get through without a password, on the same VC */
987 nt_status = smbXsrv_session_create(xconn,
988 now, &session);
989 if (!NT_STATUS_IS_OK(nt_status)) {
990 reply_nterror(req, nt_status_squash(nt_status));
991 END_PROFILE(SMBsesssetupX);
992 return;
995 if (session_info->session_key.length > 0) {
996 uint8_t session_key[16];
999 * Note: the SMB1 signing key is not truncated to 16 byte!
1001 session->global->signing_key =
1002 data_blob_dup_talloc(session->global,
1003 session_info->session_key);
1004 if (session->global->signing_key.data == NULL) {
1005 TALLOC_FREE(session);
1006 reply_nterror(req, NT_STATUS_NO_MEMORY);
1007 END_PROFILE(SMBsesssetupX);
1008 return;
1012 * The application key is truncated/padded to 16 bytes
1014 ZERO_STRUCT(session_key);
1015 memcpy(session_key, session->global->signing_key.data,
1016 MIN(session->global->signing_key.length,
1017 sizeof(session_key)));
1018 session->global->application_key =
1019 data_blob_talloc(session->global,
1020 session_key,
1021 sizeof(session_key));
1022 ZERO_STRUCT(session_key);
1023 if (session->global->application_key.data == NULL) {
1024 TALLOC_FREE(session);
1025 reply_nterror(req, NT_STATUS_NO_MEMORY);
1026 END_PROFILE(SMBsesssetupX);
1027 return;
1031 * Place the application key into the session_info
1033 data_blob_clear_free(&session_info->session_key);
1034 session_info->session_key = data_blob_dup_talloc(session_info,
1035 session->global->application_key);
1036 if (session_info->session_key.data == NULL) {
1037 TALLOC_FREE(session);
1038 reply_nterror(req, NT_STATUS_NO_MEMORY);
1039 END_PROFILE(SMBsesssetupX);
1040 return;
1044 session->compat = talloc_zero(session, struct user_struct);
1045 if (session->compat == NULL) {
1046 TALLOC_FREE(session);
1047 reply_nterror(req, NT_STATUS_NO_MEMORY);
1048 END_PROFILE(SMBsesssetupX);
1049 return;
1051 session->compat->session = session;
1052 session->compat->homes_snum = -1;
1053 session->compat->session_info = session_info;
1054 session->compat->session_keystr = NULL;
1055 session->compat->vuid = session->global->session_wire_id;
1056 DLIST_ADD(sconn->users, session->compat);
1057 sconn->num_users++;
1059 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1060 is_authenticated = true;
1061 session->compat->homes_snum =
1062 register_homes_share(session_info->unix_info->unix_name);
1065 if (srv_is_signing_negotiated(xconn) &&
1066 is_authenticated &&
1067 session->global->signing_key.length > 0)
1070 * Try and turn on server signing on the first non-guest
1071 * sessionsetup.
1073 srv_set_signing(xconn,
1074 session->global->signing_key,
1075 state->nt_resp.data ? state->nt_resp : state->lm_resp);
1078 set_current_user_info(session_info->unix_info->sanitized_username,
1079 session_info->unix_info->unix_name,
1080 session_info->info->domain_name);
1082 session->status = NT_STATUS_OK;
1083 session->global->auth_session_info = talloc_move(session->global,
1084 &session_info);
1085 session->global->auth_session_info_seqnum += 1;
1086 session->global->channels[0].auth_session_info_seqnum =
1087 session->global->auth_session_info_seqnum;
1088 session->global->auth_time = now;
1089 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1091 nt_status = smbXsrv_session_update(session);
1092 if (!NT_STATUS_IS_OK(nt_status)) {
1093 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1094 (unsigned long long)session->compat->vuid,
1095 nt_errstr(nt_status)));
1096 TALLOC_FREE(session);
1097 reply_nterror(req, nt_status_squash(nt_status));
1098 END_PROFILE(SMBsesssetupX);
1099 return;
1102 if (!session_claim(session)) {
1103 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1104 (unsigned long long)session->compat->vuid));
1105 TALLOC_FREE(session);
1106 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1107 END_PROFILE(SMBsesssetupX);
1108 return;
1111 /* current_user_info is changed on new vuid */
1112 reload_services(sconn, conn_snum_used, true);
1114 sess_vuid = session->global->session_wire_id;
1116 SSVAL(req->outbuf,smb_vwv2,action);
1117 SSVAL(req->outbuf,smb_uid,sess_vuid);
1118 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1119 req->vuid = sess_vuid;
1121 if (!xconn->smb1.sessions.done_sesssetup) {
1122 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1123 reply_force_doserror(req, ERRSRV, ERRerror);
1124 END_PROFILE(SMBsesssetupX);
1125 return;
1127 xconn->smb1.sessions.max_send = smb_bufsize;
1128 xconn->smb1.sessions.done_sesssetup = true;
1131 TALLOC_FREE(state);
1132 END_PROFILE(SMBsesssetupX);