Install dcerpc/__init__.py for all Python environments
[Samba.git] / source3 / smbd / sesssetup.c
blobe1fc7fd92a4355c2761aa614385ca180724b3b2d
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 struct messaging_context *msg_ctx;
488 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
489 void *private_data)
491 struct shutdown_state *state = (struct shutdown_state *)private_data;
492 struct server_id self_pid = messaging_server_id(state->msg_ctx);
493 struct server_id pid = session->channels[0].server_id;
494 const char *addr = session->channels[0].remote_address;
495 struct server_id_buf tmp;
497 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
498 server_id_str_buf(pid, &tmp), addr));
500 if (!process_exists(pid)) {
501 DEBUG(10, ("process does not exist\n"));
502 return 0;
505 if (serverid_equal(&pid, &self_pid)) {
506 DEBUG(10, ("It's me\n"));
507 return 0;
511 * here we use strstr() because 'addr'
512 * (session->channels[0].remote_address)
513 * contains a string like:
514 * 'ipv4:127.0.0.1:48163'
516 if (strstr(addr, state->ip) == NULL) {
517 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
518 return 0;
521 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
522 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
523 state->ip));
525 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
526 &data_blob_null);
527 return 0;
530 static void setup_new_vc_session(struct smbd_server_connection *sconn)
532 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
533 "compatible we would close all old resources.\n"));
534 #if 0
535 conn_close_all();
536 invalidate_all_vuids();
537 #endif
538 if (lp_reset_on_zero_vc()) {
539 char *addr;
540 struct shutdown_state state;
542 addr = tsocket_address_inet_addr_string(
543 sconn->remote_address, talloc_tos());
544 if (addr == NULL) {
545 return;
547 state.ip = addr;
548 state.msg_ctx = sconn->msg_ctx;
549 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
550 TALLOC_FREE(addr);
554 /****************************************************************************
555 Reply to a session setup command.
556 ****************************************************************************/
558 struct reply_sesssetup_and_X_state {
559 struct smb_request *req;
560 struct auth4_context *auth_context;
561 struct auth_usersupplied_info *user_info;
562 const char *user;
563 const char *domain;
564 DATA_BLOB lm_resp;
565 DATA_BLOB nt_resp;
566 DATA_BLOB plaintext_password;
569 static int reply_sesssetup_and_X_state_destructor(
570 struct reply_sesssetup_and_X_state *state)
572 data_blob_clear_free(&state->nt_resp);
573 data_blob_clear_free(&state->lm_resp);
574 data_blob_clear_free(&state->plaintext_password);
575 return 0;
578 void reply_sesssetup_and_X(struct smb_request *req)
580 struct reply_sesssetup_and_X_state *state = NULL;
581 uint64_t sess_vuid;
582 uint16_t smb_bufsize;
583 char *tmp;
584 fstring sub_user; /* Sanitised username for substituion */
585 const char *native_os;
586 const char *native_lanman;
587 const char *primary_domain;
588 struct auth_session_info *session_info = NULL;
589 uint16_t smb_flag2 = req->flags2;
590 uint16_t action = 0;
591 bool is_authenticated = false;
592 NTTIME now = timeval_to_nttime(&req->request_time);
593 struct smbXsrv_session *session = NULL;
594 NTSTATUS nt_status;
595 struct smbXsrv_connection *xconn = req->xconn;
596 struct smbd_server_connection *sconn = req->sconn;
597 bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
598 bool signing_allowed = false;
599 bool signing_mandatory = smb_signing_is_mandatory(
600 xconn->smb1.signing_state);
602 START_PROFILE(SMBsesssetupX);
604 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
606 state = talloc_zero(req, struct reply_sesssetup_and_X_state);
607 if (state == NULL) {
608 reply_nterror(req, NT_STATUS_NO_MEMORY);
609 END_PROFILE(SMBsesssetupX);
610 return;
612 state->req = req;
613 talloc_set_destructor(state, reply_sesssetup_and_X_state_destructor);
615 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
616 signing_allowed = true;
618 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
619 signing_mandatory = true;
623 * We can call srv_set_signing_negotiated() each time.
624 * It finds out when it needs to turn into a noop
625 * itself.
627 srv_set_signing_negotiated(xconn,
628 signing_allowed,
629 signing_mandatory);
631 /* a SPNEGO session setup has 12 command words, whereas a normal
632 NT1 session setup has 13. See the cifs spec. */
633 if (req->wct == 12 &&
634 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
636 if (!xconn->smb1.negprot.spnego) {
637 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
638 "at SPNEGO session setup when it was not "
639 "negotiated.\n"));
640 reply_nterror(req, nt_status_squash(
641 NT_STATUS_LOGON_FAILURE));
642 END_PROFILE(SMBsesssetupX);
643 return;
646 if (SVAL(req->vwv+4, 0) == 0) {
647 setup_new_vc_session(req->sconn);
650 reply_sesssetup_and_X_spnego(req);
651 END_PROFILE(SMBsesssetupX);
652 return;
655 smb_bufsize = SVAL(req->vwv+2, 0);
657 if (get_Protocol() < PROTOCOL_NT1) {
658 uint16_t passlen1 = SVAL(req->vwv+7, 0);
660 /* Never do NT status codes with protocols before NT1 as we
661 * don't get client caps. */
662 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
664 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
665 reply_nterror(req, nt_status_squash(
666 NT_STATUS_INVALID_PARAMETER));
667 END_PROFILE(SMBsesssetupX);
668 return;
671 if (doencrypt) {
672 state->lm_resp = data_blob_talloc(state,
673 req->buf,
674 passlen1);
675 } else {
676 state->plaintext_password = data_blob_talloc(state,
677 req->buf,
678 passlen1+1);
679 /* Ensure null termination */
680 state->plaintext_password.data[passlen1] = 0;
683 srvstr_pull_req_talloc(state, req, &tmp,
684 req->buf + passlen1, STR_TERMINATE);
685 state->user = tmp ? tmp : "";
687 state->domain = "";
689 } else {
690 uint16_t passlen1 = SVAL(req->vwv+7, 0);
691 uint16_t passlen2 = SVAL(req->vwv+8, 0);
692 enum remote_arch_types ra_type = get_remote_arch();
693 const uint8_t *p = req->buf;
694 const uint8_t *save_p = req->buf;
695 uint16_t byte_count;
697 if (!xconn->smb1.sessions.done_sesssetup) {
698 global_client_caps = IVAL(req->vwv+11, 0);
700 if (!(global_client_caps & CAP_STATUS32)) {
701 remove_from_common_flags2(
702 FLAGS2_32_BIT_ERROR_CODES);
705 /* client_caps is used as final determination if
706 * client is NT or Win95. This is needed to return
707 * the correct error codes in some circumstances.
710 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
711 ra_type == RA_WIN95) {
712 if(!(global_client_caps & (CAP_NT_SMBS|
713 CAP_STATUS32))) {
714 set_remote_arch( RA_WIN95);
719 if (!doencrypt) {
720 /* both Win95 and WinNT stuff up the password
721 * lengths for non-encrypting systems. Uggh.
723 if passlen1==24 its a win95 system, and its setting
724 the password length incorrectly. Luckily it still
725 works with the default code because Win95 will null
726 terminate the password anyway
728 if passlen1>0 and passlen2>0 then maybe its a NT box
729 and its setting passlen2 to some random value which
730 really stuffs things up. we need to fix that one. */
732 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
733 passlen2 != 1) {
734 passlen2 = 0;
738 /* check for nasty tricks */
739 if (passlen1 > MAX_PASS_LEN
740 || passlen1 > smbreq_bufrem(req, p)) {
741 reply_nterror(req, nt_status_squash(
742 NT_STATUS_INVALID_PARAMETER));
743 END_PROFILE(SMBsesssetupX);
744 return;
747 if (passlen2 > MAX_PASS_LEN
748 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
749 reply_nterror(req, nt_status_squash(
750 NT_STATUS_INVALID_PARAMETER));
751 END_PROFILE(SMBsesssetupX);
752 return;
755 /* Save the lanman2 password and the NT md4 password. */
757 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
758 doencrypt = False;
761 if (doencrypt) {
762 state->lm_resp = data_blob_talloc(state, p, passlen1);
763 state->nt_resp = data_blob_talloc(state, p+passlen1, passlen2);
764 } else {
765 char *pass = NULL;
766 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
768 if (unic && (passlen2 == 0) && passlen1) {
769 /* Only a ascii plaintext password was sent. */
770 (void)srvstr_pull_talloc(state,
771 req->inbuf,
772 req->flags2,
773 &pass,
774 req->buf,
775 passlen1,
776 STR_TERMINATE|STR_ASCII);
777 } else {
778 (void)srvstr_pull_talloc(state,
779 req->inbuf,
780 req->flags2,
781 &pass,
782 req->buf,
783 unic ? passlen2 : passlen1,
784 STR_TERMINATE);
786 if (!pass) {
787 reply_nterror(req, nt_status_squash(
788 NT_STATUS_INVALID_PARAMETER));
789 END_PROFILE(SMBsesssetupX);
790 return;
792 state->plaintext_password = data_blob_talloc(state,
793 pass,
794 strlen(pass)+1);
797 p += passlen1 + passlen2;
799 p += srvstr_pull_req_talloc(state, req, &tmp, p,
800 STR_TERMINATE);
801 state->user = tmp ? tmp : "";
803 p += srvstr_pull_req_talloc(state, req, &tmp, p,
804 STR_TERMINATE);
805 state->domain = tmp ? tmp : "";
807 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
808 STR_TERMINATE);
809 native_os = tmp ? tmp : "";
811 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
812 STR_TERMINATE);
813 native_lanman = tmp ? tmp : "";
815 /* not documented or decoded by Ethereal but there is one more
816 * string in the extra bytes which is the same as the
817 * PrimaryDomain when using extended security. Windows NT 4
818 * and 2003 use this string to store the native lanman string.
819 * Windows 9x does not include a string here at all so we have
820 * to check if we have any extra bytes left */
822 byte_count = SVAL(req->vwv+13, 0);
823 if ( PTR_DIFF(p, save_p) < byte_count) {
824 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
825 STR_TERMINATE);
826 primary_domain = tmp ? tmp : "";
827 } else {
828 primary_domain = talloc_strdup(talloc_tos(), "null");
831 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
832 "PrimaryDomain=[%s]\n",
833 state->domain, native_os, native_lanman, primary_domain));
835 if ( ra_type == RA_WIN2K ) {
836 if ( strlen(native_lanman) == 0 )
837 ra_lanman_string( primary_domain );
838 else
839 ra_lanman_string( native_lanman );
844 if (SVAL(req->vwv+4, 0) == 0) {
845 setup_new_vc_session(req->sconn);
848 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
849 state->domain, state->user, get_remote_machine_name()));
851 if (*state->user) {
852 if (xconn->smb1.negprot.spnego) {
854 /* This has to be here, because this is a perfectly
855 * valid behaviour for guest logons :-( */
857 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
858 "at 'normal' session setup after "
859 "negotiating spnego.\n"));
860 reply_nterror(req, nt_status_squash(
861 NT_STATUS_LOGON_FAILURE));
862 END_PROFILE(SMBsesssetupX);
863 return;
865 fstrcpy(sub_user, state->user);
866 } else {
867 fstrcpy(sub_user, "");
870 sub_set_smb_name(sub_user);
872 reload_services(sconn, conn_snum_used, true);
874 if (!*state->user) {
875 DEBUG(3,("Got anonymous request\n"));
877 nt_status = make_auth4_context(state, &state->auth_context);
878 if (NT_STATUS_IS_OK(nt_status)) {
879 uint8_t chal[8];
881 state->auth_context->get_ntlm_challenge(
882 state->auth_context, chal);
884 if (!make_user_info_guest(state,
885 sconn->remote_address,
886 sconn->local_address,
887 "SMB", &state->user_info)) {
888 nt_status = NT_STATUS_NO_MEMORY;
891 if (NT_STATUS_IS_OK(nt_status)) {
892 state->user_info->auth_description = "guest";
895 } else if (doencrypt) {
896 state->auth_context = xconn->smb1.negprot.auth_context;
897 if (state->auth_context == NULL) {
898 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
899 "session setup without negprot denied!\n"));
900 reply_nterror(req, nt_status_squash(
901 NT_STATUS_LOGON_FAILURE));
902 END_PROFILE(SMBsesssetupX);
903 return;
905 nt_status = make_user_info_for_reply_enc(state,
906 &state->user_info,
907 state->user,
908 state->domain,
909 sconn->remote_address,
910 sconn->local_address,
911 "SMB",
912 state->lm_resp,
913 state->nt_resp);
915 if (NT_STATUS_IS_OK(nt_status)) {
916 state->user_info->auth_description = "bare-NTLM";
918 } else {
919 nt_status = make_auth4_context(state, &state->auth_context);
920 if (NT_STATUS_IS_OK(nt_status)) {
921 uint8_t chal[8];
923 state->auth_context->get_ntlm_challenge(
924 state->auth_context, chal);
926 if (!make_user_info_for_reply(state,
927 &state->user_info,
928 state->user,
929 state->domain,
930 sconn->remote_address,
931 sconn->local_address,
932 "SMB",
933 chal,
934 state->plaintext_password)) {
935 nt_status = NT_STATUS_NO_MEMORY;
938 if (NT_STATUS_IS_OK(nt_status)) {
939 state->user_info->auth_description = "plaintext";
944 if (!NT_STATUS_IS_OK(nt_status)) {
945 reply_nterror(req, nt_status_squash(nt_status));
946 END_PROFILE(SMBsesssetupX);
947 return;
950 nt_status = auth_check_password_session_info(state->auth_context,
951 req, state->user_info,
952 &session_info);
953 TALLOC_FREE(state->user_info);
954 if (!NT_STATUS_IS_OK(nt_status)) {
955 reply_nterror(req, nt_status_squash(nt_status));
956 END_PROFILE(SMBsesssetupX);
957 return;
960 /* it's ok - setup a reply */
961 reply_outbuf(req, 3, 0);
962 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
963 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
965 if (get_Protocol() >= PROTOCOL_NT1) {
966 push_signature(&req->outbuf);
967 /* perhaps grab OS version here?? */
970 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
971 action |= SMB_SETUP_GUEST;
974 /* register the name and uid as being validated, so further connections
975 to a uid can get through without a password, on the same VC */
977 nt_status = smbXsrv_session_create(xconn,
978 now, &session);
979 if (!NT_STATUS_IS_OK(nt_status)) {
980 reply_nterror(req, nt_status_squash(nt_status));
981 END_PROFILE(SMBsesssetupX);
982 return;
985 if (session_info->session_key.length > 0) {
986 uint8_t session_key[16];
989 * Note: the SMB1 signing key is not truncated to 16 byte!
991 session->global->signing_key =
992 data_blob_dup_talloc(session->global,
993 session_info->session_key);
994 if (session->global->signing_key.data == NULL) {
995 TALLOC_FREE(session);
996 reply_nterror(req, NT_STATUS_NO_MEMORY);
997 END_PROFILE(SMBsesssetupX);
998 return;
1002 * The application key is truncated/padded to 16 bytes
1004 ZERO_STRUCT(session_key);
1005 memcpy(session_key, session->global->signing_key.data,
1006 MIN(session->global->signing_key.length,
1007 sizeof(session_key)));
1008 session->global->application_key =
1009 data_blob_talloc(session->global,
1010 session_key,
1011 sizeof(session_key));
1012 ZERO_STRUCT(session_key);
1013 if (session->global->application_key.data == NULL) {
1014 TALLOC_FREE(session);
1015 reply_nterror(req, NT_STATUS_NO_MEMORY);
1016 END_PROFILE(SMBsesssetupX);
1017 return;
1021 * Place the application key into the session_info
1023 data_blob_clear_free(&session_info->session_key);
1024 session_info->session_key = data_blob_dup_talloc(session_info,
1025 session->global->application_key);
1026 if (session_info->session_key.data == NULL) {
1027 TALLOC_FREE(session);
1028 reply_nterror(req, NT_STATUS_NO_MEMORY);
1029 END_PROFILE(SMBsesssetupX);
1030 return;
1034 session->compat = talloc_zero(session, struct user_struct);
1035 if (session->compat == NULL) {
1036 TALLOC_FREE(session);
1037 reply_nterror(req, NT_STATUS_NO_MEMORY);
1038 END_PROFILE(SMBsesssetupX);
1039 return;
1041 session->compat->session = session;
1042 session->compat->homes_snum = -1;
1043 session->compat->session_info = session_info;
1044 session->compat->session_keystr = NULL;
1045 session->compat->vuid = session->global->session_wire_id;
1046 DLIST_ADD(sconn->users, session->compat);
1047 sconn->num_users++;
1049 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1050 is_authenticated = true;
1051 session->compat->homes_snum =
1052 register_homes_share(session_info->unix_info->unix_name);
1055 if (srv_is_signing_negotiated(xconn) &&
1056 is_authenticated &&
1057 session->global->signing_key.length > 0)
1060 * Try and turn on server signing on the first non-guest
1061 * sessionsetup.
1063 srv_set_signing(xconn,
1064 session->global->signing_key,
1065 state->nt_resp.data ? state->nt_resp : state->lm_resp);
1068 set_current_user_info(session_info->unix_info->sanitized_username,
1069 session_info->unix_info->unix_name,
1070 session_info->info->domain_name);
1072 session->status = NT_STATUS_OK;
1073 session->global->auth_session_info = talloc_move(session->global,
1074 &session_info);
1075 session->global->auth_session_info_seqnum += 1;
1076 session->global->channels[0].auth_session_info_seqnum =
1077 session->global->auth_session_info_seqnum;
1078 session->global->auth_time = now;
1079 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1081 nt_status = smbXsrv_session_update(session);
1082 if (!NT_STATUS_IS_OK(nt_status)) {
1083 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1084 (unsigned long long)session->compat->vuid,
1085 nt_errstr(nt_status)));
1086 TALLOC_FREE(session);
1087 reply_nterror(req, nt_status_squash(nt_status));
1088 END_PROFILE(SMBsesssetupX);
1089 return;
1092 if (!session_claim(session)) {
1093 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1094 (unsigned long long)session->compat->vuid));
1095 TALLOC_FREE(session);
1096 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1097 END_PROFILE(SMBsesssetupX);
1098 return;
1101 /* current_user_info is changed on new vuid */
1102 reload_services(sconn, conn_snum_used, true);
1104 sess_vuid = session->global->session_wire_id;
1106 SSVAL(req->outbuf,smb_vwv2,action);
1107 SSVAL(req->outbuf,smb_uid,sess_vuid);
1108 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1109 req->vuid = sess_vuid;
1111 if (!xconn->smb1.sessions.done_sesssetup) {
1112 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1113 reply_force_doserror(req, ERRSRV, ERRerror);
1114 END_PROFILE(SMBsesssetupX);
1115 return;
1117 xconn->smb1.sessions.max_send = smb_bufsize;
1118 xconn->smb1.sessions.done_sesssetup = true;
1121 TALLOC_FREE(state);
1122 END_PROFILE(SMBsesssetupX);