smbd: remove vuid from struct user_struct
[Samba.git] / source3 / smbd / sesssetup.c
blob94d1ac1e047cf4714fae2b48fc2eb82bda56d84b
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 "../libcli/smb/smb_signing.h"
37 /****************************************************************************
38 Add the standard 'Samba' signature to the end of the session setup.
39 ****************************************************************************/
41 static int push_signature(uint8_t **outbuf)
43 char *lanman;
44 int result, tmp;
45 fstring native_os;
47 result = 0;
49 fstr_sprintf(native_os, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION,
50 SAMBA_MINOR_NBT_ANNOUNCE_VERSION);
52 tmp = message_push_string(outbuf, native_os, STR_TERMINATE);
54 if (tmp == -1) return -1;
55 result += tmp;
57 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
58 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
59 SAFE_FREE(lanman);
61 else {
62 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
65 if (tmp == -1) return -1;
66 result += tmp;
68 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
70 if (tmp == -1) return -1;
71 result += tmp;
73 return result;
76 /****************************************************************************
77 Reply to a session setup command.
78 conn POINTER CAN BE NULL HERE !
79 ****************************************************************************/
81 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
83 const uint8_t *p;
84 DATA_BLOB in_blob;
85 DATA_BLOB out_blob = data_blob_null;
86 size_t bufrem;
87 char *tmp;
88 const char *native_os;
89 const char *native_lanman;
90 const char *primary_domain;
91 uint16_t data_blob_len = SVAL(req->vwv+7, 0);
92 enum remote_arch_types ra_type = get_remote_arch();
93 uint64_t vuid = req->vuid;
94 NTSTATUS status = NT_STATUS_OK;
95 struct smbXsrv_connection *xconn = req->xconn;
96 struct smbd_server_connection *sconn = req->sconn;
97 uint16_t action = 0;
98 bool is_authenticated = false;
99 NTTIME now = timeval_to_nttime(&req->request_time);
100 struct smbXsrv_session *session = NULL;
101 uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
102 uint32_t client_caps = IVAL(req->vwv+10, 0);
103 struct smbXsrv_session_auth0 *auth;
105 DEBUG(3,("Doing spnego session setup\n"));
107 if (!xconn->smb1.sessions.done_sesssetup) {
108 global_client_caps = client_caps;
110 if (!(global_client_caps & CAP_STATUS32)) {
111 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
115 p = req->buf;
117 if (data_blob_len == 0) {
118 /* an invalid request */
119 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
120 return;
123 bufrem = smbreq_bufrem(req, p);
124 /* pull the spnego blob */
125 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
127 #if 0
128 file_save("negotiate.dat", in_blob.data, in_blob.length);
129 #endif
131 p = req->buf + in_blob.length;
133 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
134 STR_TERMINATE);
135 native_os = tmp ? tmp : "";
137 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
138 STR_TERMINATE);
139 native_lanman = tmp ? tmp : "";
141 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
142 STR_TERMINATE);
143 primary_domain = tmp ? tmp : "";
145 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
146 native_os, native_lanman, primary_domain));
148 if ( ra_type == RA_WIN2K ) {
149 /* Vista sets neither the OS or lanman strings */
151 if ( !strlen(native_os) && !strlen(native_lanman) )
152 set_remote_arch(RA_VISTA);
154 /* Windows 2003 doesn't set the native lanman string,
155 but does set primary domain which is a bug I think */
157 if ( !strlen(native_lanman) ) {
158 ra_lanman_string( primary_domain );
159 } else {
160 ra_lanman_string( native_lanman );
162 } else if ( ra_type == RA_VISTA ) {
163 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
164 set_remote_arch(RA_OSX);
168 if (vuid != 0) {
169 status = smb1srv_session_lookup(xconn,
170 vuid, now,
171 &session);
172 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
173 reply_force_doserror(req, ERRSRV, ERRbaduid);
174 return;
176 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
177 status = NT_STATUS_OK;
179 if (NT_STATUS_IS_OK(status)) {
180 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
181 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
182 TALLOC_FREE(session->pending_auth);
184 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
185 reply_nterror(req, nt_status_squash(status));
186 return;
190 if (session == NULL) {
191 /* create a new session */
192 status = smbXsrv_session_create(xconn,
193 now, &session);
194 if (!NT_STATUS_IS_OK(status)) {
195 reply_nterror(req, nt_status_squash(status));
196 return;
200 status = smbXsrv_session_find_auth(session, xconn, now, &auth);
201 if (!NT_STATUS_IS_OK(status)) {
202 status = smbXsrv_session_create_auth(session, xconn, now,
203 0, /* flags */
204 0, /* security */
205 &auth);
206 if (!NT_STATUS_IS_OK(status)) {
207 reply_nterror(req, nt_status_squash(status));
208 return;
212 if (auth->gensec == NULL) {
213 status = auth_generic_prepare(session,
214 xconn->remote_address,
215 xconn->local_address,
216 "SMB",
217 &auth->gensec);
218 if (!NT_STATUS_IS_OK(status)) {
219 TALLOC_FREE(session);
220 reply_nterror(req, nt_status_squash(status));
221 return;
224 gensec_want_feature(auth->gensec, GENSEC_FEATURE_SESSION_KEY);
225 gensec_want_feature(auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
226 gensec_want_feature(auth->gensec, GENSEC_FEATURE_SMB_TRANSPORT);
228 status = gensec_start_mech_by_oid(auth->gensec,
229 GENSEC_OID_SPNEGO);
230 if (!NT_STATUS_IS_OK(status)) {
231 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
232 TALLOC_FREE(session);;
233 reply_nterror(req, nt_status_squash(status));
234 return;
238 become_root();
239 status = gensec_update(auth->gensec,
240 talloc_tos(),
241 in_blob, &out_blob);
242 unbecome_root();
243 if (!NT_STATUS_IS_OK(status) &&
244 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
245 TALLOC_FREE(session);
246 reply_nterror(req, nt_status_squash(status));
247 return;
250 if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
251 struct auth_session_info *session_info = NULL;
253 status = gensec_session_info(auth->gensec,
254 session,
255 &session_info);
256 if (!NT_STATUS_IS_OK(status)) {
257 DEBUG(1,("Failed to generate session_info "
258 "(user and group token) for session setup: %s\n",
259 nt_errstr(status)));
260 data_blob_free(&out_blob);
261 TALLOC_FREE(session);
262 reply_nterror(req, nt_status_squash(status));
263 return;
266 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
267 action |= SMB_SETUP_GUEST;
270 if (session_info->session_key.length > 0) {
271 struct smbXsrv_session *x = session;
274 * Note: the SMB1 signing key is not truncated to 16 byte!
276 x->global->signing_key =
277 talloc_zero(x->global, struct smb2_signing_key);
278 if (x->global->signing_key == NULL) {
279 data_blob_free(&out_blob);
280 TALLOC_FREE(session);
281 reply_nterror(req, NT_STATUS_NO_MEMORY);
282 return;
284 /* TODO: setup destructor once we cache the hmac handle */
286 x->global->signing_key->blob =
287 x->global->signing_key_blob =
288 data_blob_dup_talloc(x->global->signing_key,
289 session_info->session_key);
290 if (!smb2_signing_key_valid(x->global->signing_key)) {
291 data_blob_free(&out_blob);
292 TALLOC_FREE(session);
293 reply_nterror(req, NT_STATUS_NO_MEMORY);
294 return;
296 talloc_keep_secret(x->global->signing_key->blob.data);
299 * clear the session key
300 * the first tcon will add setup the application key
302 data_blob_clear_free(&session_info->session_key);
305 session->compat = talloc_zero(session, struct user_struct);
306 if (session->compat == NULL) {
307 data_blob_free(&out_blob);
308 TALLOC_FREE(session);
309 reply_nterror(req, NT_STATUS_NO_MEMORY);
310 return;
312 session->compat->session = session;
313 session->compat->session_info = session_info;
314 DLIST_ADD(sconn->users, session->compat);
315 sconn->num_users++;
317 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
318 is_authenticated = true;
319 session->homes_snum =
320 register_homes_share(session_info->unix_info->unix_name);
323 if (srv_is_signing_negotiated(xconn) &&
324 is_authenticated &&
325 smb2_signing_key_valid(session->global->signing_key))
328 * Try and turn on server signing on the first non-guest
329 * sessionsetup.
331 srv_set_signing(xconn,
332 session->global->signing_key->blob,
333 data_blob_null);
336 set_current_user_info(session_info->unix_info->sanitized_username,
337 session_info->unix_info->unix_name,
338 session_info->info->domain_name);
340 session->status = NT_STATUS_OK;
341 session->global->auth_session_info = talloc_move(session->global,
342 &session_info);
343 session->global->auth_session_info_seqnum += 1;
344 session->global->channels[0].auth_session_info_seqnum =
345 session->global->auth_session_info_seqnum;
346 session->global->auth_time = now;
347 if (client_caps & CAP_DYNAMIC_REAUTH) {
348 session->global->expiration_time =
349 gensec_expire_time(auth->gensec);
350 } else {
351 session->global->expiration_time =
352 GENSEC_EXPIRE_TIME_INFINITY;
355 if (!session_claim(session)) {
356 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
357 (unsigned long long)session->global->session_wire_id));
358 data_blob_free(&out_blob);
359 TALLOC_FREE(session);
360 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
361 return;
364 status = smbXsrv_session_update(session);
365 if (!NT_STATUS_IS_OK(status)) {
366 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
367 (unsigned long long)session->global->session_wire_id,
368 nt_errstr(status)));
369 data_blob_free(&out_blob);
370 TALLOC_FREE(session);
371 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
372 return;
375 if (!xconn->smb1.sessions.done_sesssetup) {
376 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
377 reply_force_doserror(req, ERRSRV, ERRerror);
378 return;
380 xconn->smb1.sessions.max_send = smb_bufsize;
381 xconn->smb1.sessions.done_sesssetup = true;
384 /* current_user_info is changed on new vuid */
385 reload_services(sconn, conn_snum_used, true);
386 } else if (NT_STATUS_IS_OK(status)) {
387 struct auth_session_info *session_info = NULL;
389 status = gensec_session_info(auth->gensec,
390 session,
391 &session_info);
392 if (!NT_STATUS_IS_OK(status)) {
393 DEBUG(1,("Failed to generate session_info "
394 "(user and group token) for session setup: %s\n",
395 nt_errstr(status)));
396 data_blob_free(&out_blob);
397 TALLOC_FREE(session);
398 reply_nterror(req, nt_status_squash(status));
399 return;
402 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
403 action |= SMB_SETUP_GUEST;
407 * Keep the application key
409 data_blob_clear_free(&session_info->session_key);
410 session_info->session_key =
411 session->global->auth_session_info->session_key;
412 talloc_steal(session_info, session_info->session_key.data);
413 TALLOC_FREE(session->global->auth_session_info);
415 session->compat->session_info = session_info;
417 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
418 session->homes_snum =
419 register_homes_share(session_info->unix_info->unix_name);
422 set_current_user_info(session_info->unix_info->sanitized_username,
423 session_info->unix_info->unix_name,
424 session_info->info->domain_name);
426 session->status = NT_STATUS_OK;
427 session->global->auth_session_info = talloc_move(session->global,
428 &session_info);
429 session->global->auth_session_info_seqnum += 1;
430 session->global->channels[0].auth_session_info_seqnum =
431 session->global->auth_session_info_seqnum;
432 session->global->auth_time = now;
433 if (client_caps & CAP_DYNAMIC_REAUTH) {
434 session->global->expiration_time =
435 gensec_expire_time(auth->gensec);
436 } else {
437 session->global->expiration_time =
438 GENSEC_EXPIRE_TIME_INFINITY;
441 status = smbXsrv_session_update(session);
442 if (!NT_STATUS_IS_OK(status)) {
443 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
444 (unsigned long long)session->global->session_wire_id,
445 nt_errstr(status)));
446 data_blob_free(&out_blob);
447 TALLOC_FREE(session);
448 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
449 return;
452 conn_clear_vuid_caches(sconn, session->global->session_wire_id);
454 /* current_user_info is changed on new vuid */
455 reload_services(sconn, conn_snum_used, true);
458 vuid = session->global->session_wire_id;
460 reply_outbuf(req, 4, 0);
462 SSVAL(req->outbuf, smb_uid, vuid);
463 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
464 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
465 SSVAL(req->outbuf, smb_vwv2, action);
466 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
468 if (message_push_blob(&req->outbuf, out_blob) == -1) {
469 data_blob_free(&out_blob);
470 TALLOC_FREE(session);
471 reply_nterror(req, NT_STATUS_NO_MEMORY);
472 return;
474 data_blob_free(&out_blob);
476 if (push_signature(&req->outbuf) == -1) {
477 TALLOC_FREE(session);
478 reply_nterror(req, NT_STATUS_NO_MEMORY);
479 return;
483 /****************************************************************************
484 On new VC == 0, shutdown *all* old connections and users.
485 It seems that only NT4.x does this. At W2K and above (XP etc.).
486 a new session setup with VC==0 is ignored.
487 ****************************************************************************/
489 struct shutdown_state {
490 const char *ip;
491 size_t ip_length;
492 struct messaging_context *msg_ctx;
495 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
496 void *private_data)
498 struct shutdown_state *state = (struct shutdown_state *)private_data;
499 struct server_id self_pid = messaging_server_id(state->msg_ctx);
500 struct server_id pid = session->channels[0].server_id;
501 const char *addr = session->channels[0].remote_address;
502 const char *port_colon;
503 size_t addr_len;
504 struct server_id_buf tmp;
506 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
507 server_id_str_buf(pid, &tmp), addr));
509 if (!process_exists(pid)) {
510 DEBUG(10, ("process does not exist\n"));
511 return 0;
514 if (server_id_equal(&pid, &self_pid)) {
515 DEBUG(10, ("It's me\n"));
516 return 0;
519 port_colon = strrchr(addr, ':');
520 if (port_colon == NULL) {
521 DBG_DEBUG("addr %s in contains no port\n", addr);
522 return 0;
524 addr_len = port_colon - addr;
526 if ((addr_len != state->ip_length) ||
527 (strncmp(addr, state->ip, state->ip_length) != 0)) {
528 DEBUG(10, ("%s (%zu) does not match %s (%zu)\n",
529 state->ip, state->ip_length, addr, addr_len));
530 return 0;
533 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
534 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
535 state->ip));
537 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
538 &data_blob_null);
539 return 0;
542 static void setup_new_vc_session(struct smbd_server_connection *sconn)
544 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
545 "compatible we would close all old resources.\n"));
547 if (lp_reset_on_zero_vc()) {
548 char *addr;
549 const char *port_colon;
550 struct shutdown_state state;
552 addr = tsocket_address_string(
553 sconn->remote_address, talloc_tos());
554 if (addr == NULL) {
555 return;
557 state.ip = addr;
559 port_colon = strrchr(addr, ':');
560 if (port_colon == NULL) {
561 return;
563 state.ip_length = port_colon - addr;
564 state.msg_ctx = sconn->msg_ctx;
565 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
566 TALLOC_FREE(addr);
570 /****************************************************************************
571 Reply to a session setup command.
572 ****************************************************************************/
574 struct reply_sesssetup_and_X_state {
575 struct smb_request *req;
576 struct auth4_context *auth_context;
577 struct auth_usersupplied_info *user_info;
578 const char *user;
579 const char *domain;
580 DATA_BLOB lm_resp;
581 DATA_BLOB nt_resp;
582 DATA_BLOB plaintext_password;
585 static int reply_sesssetup_and_X_state_destructor(
586 struct reply_sesssetup_and_X_state *state)
588 data_blob_clear_free(&state->nt_resp);
589 data_blob_clear_free(&state->lm_resp);
590 data_blob_clear_free(&state->plaintext_password);
591 return 0;
594 void reply_sesssetup_and_X(struct smb_request *req)
596 struct reply_sesssetup_and_X_state *state = NULL;
597 uint64_t sess_vuid;
598 uint16_t smb_bufsize;
599 char *tmp;
600 fstring sub_user; /* Sanitised username for substituion */
601 const char *native_os;
602 const char *native_lanman;
603 const char *primary_domain;
604 struct auth_session_info *session_info = NULL;
605 uint16_t smb_flag2 = req->flags2;
606 uint16_t action = 0;
607 bool is_authenticated = false;
608 NTTIME now = timeval_to_nttime(&req->request_time);
609 struct smbXsrv_session *session = NULL;
610 NTSTATUS nt_status;
611 struct smbXsrv_connection *xconn = req->xconn;
612 struct smbd_server_connection *sconn = req->sconn;
613 bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
614 bool signing_allowed = false;
615 bool signing_mandatory = smb_signing_is_mandatory(
616 xconn->smb1.signing_state);
618 START_PROFILE(SMBsesssetupX);
620 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
622 state = talloc_zero(req, struct reply_sesssetup_and_X_state);
623 if (state == NULL) {
624 reply_nterror(req, NT_STATUS_NO_MEMORY);
625 END_PROFILE(SMBsesssetupX);
626 return;
628 state->req = req;
629 talloc_set_destructor(state, reply_sesssetup_and_X_state_destructor);
631 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
632 signing_allowed = true;
634 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
635 signing_mandatory = true;
639 * We can call srv_set_signing_negotiated() each time.
640 * It finds out when it needs to turn into a noop
641 * itself.
643 srv_set_signing_negotiated(xconn,
644 signing_allowed,
645 signing_mandatory);
647 /* a SPNEGO session setup has 12 command words, whereas a normal
648 NT1 session setup has 13. See the cifs spec. */
649 if (req->wct == 12 &&
650 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
652 if (!xconn->smb1.negprot.spnego) {
653 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
654 "at SPNEGO session setup when it was not "
655 "negotiated.\n"));
656 reply_nterror(req, nt_status_squash(
657 NT_STATUS_LOGON_FAILURE));
658 END_PROFILE(SMBsesssetupX);
659 return;
662 if (SVAL(req->vwv+4, 0) == 0) {
663 setup_new_vc_session(req->sconn);
666 reply_sesssetup_and_X_spnego(req);
667 END_PROFILE(SMBsesssetupX);
668 return;
671 smb_bufsize = SVAL(req->vwv+2, 0);
673 if (get_Protocol() < PROTOCOL_NT1) {
674 uint16_t passlen1 = SVAL(req->vwv+7, 0);
676 /* Never do NT status codes with protocols before NT1 as we
677 * don't get client caps. */
678 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
680 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
681 reply_nterror(req, nt_status_squash(
682 NT_STATUS_INVALID_PARAMETER));
683 END_PROFILE(SMBsesssetupX);
684 return;
687 if (doencrypt) {
688 state->lm_resp = data_blob_talloc(state,
689 req->buf,
690 passlen1);
691 } else {
692 state->plaintext_password = data_blob_talloc(state,
693 req->buf,
694 passlen1+1);
695 /* Ensure null termination */
696 state->plaintext_password.data[passlen1] = 0;
699 srvstr_pull_req_talloc(state, req, &tmp,
700 req->buf + passlen1, STR_TERMINATE);
701 state->user = tmp ? tmp : "";
703 state->domain = "";
705 } else {
706 uint16_t passlen1 = SVAL(req->vwv+7, 0);
707 uint16_t passlen2 = SVAL(req->vwv+8, 0);
708 enum remote_arch_types ra_type = get_remote_arch();
709 const uint8_t *p = req->buf;
710 const uint8_t *save_p = req->buf;
711 uint16_t byte_count;
713 if (!xconn->smb1.sessions.done_sesssetup) {
714 global_client_caps = IVAL(req->vwv+11, 0);
716 if (!(global_client_caps & CAP_STATUS32)) {
717 remove_from_common_flags2(
718 FLAGS2_32_BIT_ERROR_CODES);
721 /* client_caps is used as final determination if
722 * client is NT or Win95. This is needed to return
723 * the correct error codes in some circumstances.
726 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
727 ra_type == RA_WIN95) {
728 if(!(global_client_caps & (CAP_NT_SMBS|
729 CAP_STATUS32))) {
730 set_remote_arch( RA_WIN95);
735 if (!doencrypt) {
736 /* both Win95 and WinNT stuff up the password
737 * lengths for non-encrypting systems. Uggh.
739 if passlen1==24 its a win95 system, and its setting
740 the password length incorrectly. Luckily it still
741 works with the default code because Win95 will null
742 terminate the password anyway
744 if passlen1>0 and passlen2>0 then maybe its a NT box
745 and its setting passlen2 to some random value which
746 really stuffs things up. we need to fix that one. */
748 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
749 passlen2 != 1) {
750 passlen2 = 0;
754 /* check for nasty tricks */
755 if (passlen1 > MAX_PASS_LEN
756 || passlen1 > smbreq_bufrem(req, p)) {
757 reply_nterror(req, nt_status_squash(
758 NT_STATUS_INVALID_PARAMETER));
759 END_PROFILE(SMBsesssetupX);
760 return;
763 if (passlen2 > MAX_PASS_LEN
764 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
765 reply_nterror(req, nt_status_squash(
766 NT_STATUS_INVALID_PARAMETER));
767 END_PROFILE(SMBsesssetupX);
768 return;
771 /* Save the lanman2 password and the NT md4 password. */
773 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
774 doencrypt = False;
777 if (doencrypt) {
778 state->lm_resp = data_blob_talloc(state, p, passlen1);
779 state->nt_resp = data_blob_talloc(state, p+passlen1, passlen2);
780 } else {
781 char *pass = NULL;
782 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
784 if (unic && (passlen2 == 0) && passlen1) {
785 /* Only a ascii plaintext password was sent. */
786 (void)srvstr_pull_talloc(state,
787 req->inbuf,
788 req->flags2,
789 &pass,
790 req->buf,
791 passlen1,
792 STR_TERMINATE|STR_ASCII);
793 } else {
794 (void)srvstr_pull_talloc(state,
795 req->inbuf,
796 req->flags2,
797 &pass,
798 req->buf,
799 unic ? passlen2 : passlen1,
800 STR_TERMINATE);
802 if (!pass) {
803 reply_nterror(req, nt_status_squash(
804 NT_STATUS_INVALID_PARAMETER));
805 END_PROFILE(SMBsesssetupX);
806 return;
808 state->plaintext_password = data_blob_talloc(state,
809 pass,
810 strlen(pass)+1);
813 p += passlen1 + passlen2;
815 p += srvstr_pull_req_talloc(state, req, &tmp, p,
816 STR_TERMINATE);
817 state->user = tmp ? tmp : "";
819 p += srvstr_pull_req_talloc(state, req, &tmp, p,
820 STR_TERMINATE);
821 state->domain = tmp ? tmp : "";
823 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
824 STR_TERMINATE);
825 native_os = tmp ? tmp : "";
827 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
828 STR_TERMINATE);
829 native_lanman = tmp ? tmp : "";
831 /* not documented or decoded by Ethereal but there is one more
832 * string in the extra bytes which is the same as the
833 * PrimaryDomain when using extended security. Windows NT 4
834 * and 2003 use this string to store the native lanman string.
835 * Windows 9x does not include a string here at all so we have
836 * to check if we have any extra bytes left */
838 byte_count = SVAL(req->vwv+13, 0);
839 if ( PTR_DIFF(p, save_p) < byte_count) {
840 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
841 STR_TERMINATE);
842 primary_domain = tmp ? tmp : "";
843 } else {
844 primary_domain = talloc_strdup(talloc_tos(), "null");
847 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
848 "PrimaryDomain=[%s]\n",
849 state->domain, native_os, native_lanman, primary_domain));
851 if ( ra_type == RA_WIN2K ) {
852 if ( strlen(native_lanman) == 0 )
853 ra_lanman_string( primary_domain );
854 else
855 ra_lanman_string( native_lanman );
860 if (SVAL(req->vwv+4, 0) == 0) {
861 setup_new_vc_session(req->sconn);
864 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
865 state->domain, state->user, get_remote_machine_name()));
867 if (*state->user) {
868 if (xconn->smb1.negprot.spnego) {
870 /* This has to be here, because this is a perfectly
871 * valid behaviour for guest logons :-( */
873 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
874 "at 'normal' session setup after "
875 "negotiating spnego.\n"));
876 reply_nterror(req, nt_status_squash(
877 NT_STATUS_LOGON_FAILURE));
878 END_PROFILE(SMBsesssetupX);
879 return;
881 fstrcpy(sub_user, state->user);
882 } else {
883 fstrcpy(sub_user, "");
886 sub_set_smb_name(sub_user);
888 reload_services(sconn, conn_snum_used, true);
890 if (!*state->user) {
891 DEBUG(3,("Got anonymous request\n"));
893 nt_status = make_auth4_context(state, &state->auth_context);
894 if (NT_STATUS_IS_OK(nt_status)) {
895 uint8_t chal[8];
897 state->auth_context->get_ntlm_challenge(
898 state->auth_context, chal);
900 if (!make_user_info_guest(state,
901 sconn->remote_address,
902 sconn->local_address,
903 "SMB", &state->user_info)) {
904 nt_status = NT_STATUS_NO_MEMORY;
907 if (NT_STATUS_IS_OK(nt_status)) {
908 state->user_info->auth_description = "guest";
911 } else if (doencrypt) {
912 state->auth_context = xconn->smb1.negprot.auth_context;
913 if (state->auth_context == NULL) {
914 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
915 "session setup without negprot denied!\n"));
916 reply_nterror(req, nt_status_squash(
917 NT_STATUS_LOGON_FAILURE));
918 END_PROFILE(SMBsesssetupX);
919 return;
921 nt_status = make_user_info_for_reply_enc(state,
922 &state->user_info,
923 state->user,
924 state->domain,
925 sconn->remote_address,
926 sconn->local_address,
927 "SMB",
928 state->lm_resp,
929 state->nt_resp);
931 if (NT_STATUS_IS_OK(nt_status)) {
932 state->user_info->auth_description = "bare-NTLM";
934 } else {
935 nt_status = make_auth4_context(state, &state->auth_context);
936 if (NT_STATUS_IS_OK(nt_status)) {
937 uint8_t chal[8];
939 state->auth_context->get_ntlm_challenge(
940 state->auth_context, chal);
942 if (!make_user_info_for_reply(state,
943 &state->user_info,
944 state->user,
945 state->domain,
946 sconn->remote_address,
947 sconn->local_address,
948 "SMB",
949 chal,
950 state->plaintext_password)) {
951 nt_status = NT_STATUS_NO_MEMORY;
954 if (NT_STATUS_IS_OK(nt_status)) {
955 state->user_info->auth_description = "plaintext";
960 if (!NT_STATUS_IS_OK(nt_status)) {
961 reply_nterror(req, nt_status_squash(nt_status));
962 END_PROFILE(SMBsesssetupX);
963 return;
966 nt_status = auth_check_password_session_info(state->auth_context,
967 req, state->user_info,
968 &session_info);
969 TALLOC_FREE(state->user_info);
970 if (!NT_STATUS_IS_OK(nt_status)) {
971 reply_nterror(req, nt_status_squash(nt_status));
972 END_PROFILE(SMBsesssetupX);
973 return;
976 /* it's ok - setup a reply */
977 reply_outbuf(req, 3, 0);
978 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
979 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
981 if (get_Protocol() >= PROTOCOL_NT1) {
982 push_signature(&req->outbuf);
983 /* perhaps grab OS version here?? */
986 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
987 action |= SMB_SETUP_GUEST;
990 /* register the name and uid as being validated, so further connections
991 to a uid can get through without a password, on the same VC */
993 nt_status = smbXsrv_session_create(xconn,
994 now, &session);
995 if (!NT_STATUS_IS_OK(nt_status)) {
996 reply_nterror(req, nt_status_squash(nt_status));
997 END_PROFILE(SMBsesssetupX);
998 return;
1001 if (session_info->session_key.length > 0) {
1002 uint8_t session_key[16];
1005 * Note: the SMB1 signing key is not truncated to 16 byte!
1007 session->global->signing_key =
1008 talloc_zero(session->global, struct smb2_signing_key);
1009 if (session->global->signing_key == NULL) {
1010 TALLOC_FREE(session);
1011 reply_nterror(req, NT_STATUS_NO_MEMORY);
1012 END_PROFILE(SMBsesssetupX);
1013 return;
1015 /* TODO: setup destructor once we cache the hmac handle */
1017 session->global->signing_key->blob =
1018 session->global->signing_key_blob =
1019 data_blob_dup_talloc(session->global->signing_key,
1020 session_info->session_key);
1021 if (!smb2_signing_key_valid(session->global->signing_key)) {
1022 TALLOC_FREE(session);
1023 reply_nterror(req, NT_STATUS_NO_MEMORY);
1024 END_PROFILE(SMBsesssetupX);
1025 return;
1027 talloc_keep_secret(session->global->signing_key->blob.data);
1030 * The application key is truncated/padded to 16 bytes
1032 ZERO_STRUCT(session_key);
1033 memcpy(session_key, session->global->signing_key->blob.data,
1034 MIN(session->global->signing_key->blob.length,
1035 sizeof(session_key)));
1036 session->global->application_key =
1037 data_blob_talloc(session->global,
1038 session_key,
1039 sizeof(session_key));
1040 ZERO_STRUCT(session_key);
1041 if (session->global->application_key.data == NULL) {
1042 TALLOC_FREE(session);
1043 reply_nterror(req, NT_STATUS_NO_MEMORY);
1044 END_PROFILE(SMBsesssetupX);
1045 return;
1049 * Place the application key into the session_info
1051 data_blob_clear_free(&session_info->session_key);
1052 session_info->session_key = data_blob_dup_talloc(session_info,
1053 session->global->application_key);
1054 if (session_info->session_key.data == NULL) {
1055 TALLOC_FREE(session);
1056 reply_nterror(req, NT_STATUS_NO_MEMORY);
1057 END_PROFILE(SMBsesssetupX);
1058 return;
1062 session->compat = talloc_zero(session, struct user_struct);
1063 if (session->compat == NULL) {
1064 TALLOC_FREE(session);
1065 reply_nterror(req, NT_STATUS_NO_MEMORY);
1066 END_PROFILE(SMBsesssetupX);
1067 return;
1069 session->compat->session = session;
1070 session->compat->session_info = session_info;
1071 DLIST_ADD(sconn->users, session->compat);
1072 sconn->num_users++;
1074 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1075 is_authenticated = true;
1076 session->homes_snum =
1077 register_homes_share(session_info->unix_info->unix_name);
1080 if (srv_is_signing_negotiated(xconn) &&
1081 is_authenticated &&
1082 smb2_signing_key_valid(session->global->signing_key))
1085 * Try and turn on server signing on the first non-guest
1086 * sessionsetup.
1088 srv_set_signing(xconn,
1089 session->global->signing_key->blob,
1090 state->nt_resp.data ? state->nt_resp : state->lm_resp);
1093 set_current_user_info(session_info->unix_info->sanitized_username,
1094 session_info->unix_info->unix_name,
1095 session_info->info->domain_name);
1097 session->status = NT_STATUS_OK;
1098 session->global->auth_session_info = talloc_move(session->global,
1099 &session_info);
1100 session->global->auth_session_info_seqnum += 1;
1101 session->global->channels[0].auth_session_info_seqnum =
1102 session->global->auth_session_info_seqnum;
1103 session->global->auth_time = now;
1104 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1106 nt_status = smbXsrv_session_update(session);
1107 if (!NT_STATUS_IS_OK(nt_status)) {
1108 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1109 (unsigned long long)session->global->session_wire_id,
1110 nt_errstr(nt_status)));
1111 TALLOC_FREE(session);
1112 reply_nterror(req, nt_status_squash(nt_status));
1113 END_PROFILE(SMBsesssetupX);
1114 return;
1117 if (!session_claim(session)) {
1118 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1119 (unsigned long long)session->global->session_wire_id));
1120 TALLOC_FREE(session);
1121 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1122 END_PROFILE(SMBsesssetupX);
1123 return;
1126 /* current_user_info is changed on new vuid */
1127 reload_services(sconn, conn_snum_used, true);
1129 sess_vuid = session->global->session_wire_id;
1131 SSVAL(req->outbuf,smb_vwv2,action);
1132 SSVAL(req->outbuf,smb_uid,sess_vuid);
1133 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1134 req->vuid = sess_vuid;
1136 if (!xconn->smb1.sessions.done_sesssetup) {
1137 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1138 reply_force_doserror(req, ERRSRV, ERRerror);
1139 END_PROFILE(SMBsesssetupX);
1140 return;
1142 xconn->smb1.sessions.max_send = smb_bufsize;
1143 xconn->smb1.sessions.done_sesssetup = true;
1146 TALLOC_FREE(state);
1147 END_PROFILE(SMBsesssetupX);