nfs4acls: Use talloc_realloc()
[Samba.git] / source3 / smbd / sesssetup.c
blob6c31958e448a615fd897058931c99ad0ba9013fa
1 /*
2 Unix SMB/CIFS implementation.
3 handle SMBsessionsetup
4 Copyright (C) Andrew Tridgell 1998-2001
5 Copyright (C) Andrew Bartlett 2001
6 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7 Copyright (C) Luke Howard 2003
8 Copyright (C) Volker Lendecke 2007
9 Copyright (C) Jeremy Allison 2007
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "includes.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/spnego.h"
30 #include "../auth/ntlmssp/ntlmssp.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "libads/kerberos_proto.h"
33 #include "../lib/util/asn1.h"
34 #include "auth.h"
35 #include "messages.h"
36 #include "smbprofile.h"
37 #include "../libcli/security/security.h"
38 #include "auth/gensec/gensec.h"
39 #include "lib/conn_tdb.h"
41 /****************************************************************************
42 Add the standard 'Samba' signature to the end of the session setup.
43 ****************************************************************************/
45 static int push_signature(uint8_t **outbuf)
47 char *lanman;
48 int result, tmp;
49 fstring native_os;
51 result = 0;
53 fstr_sprintf(native_os, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION,
54 SAMBA_MINOR_NBT_ANNOUNCE_VERSION);
56 tmp = message_push_string(outbuf, native_os, STR_TERMINATE);
58 if (tmp == -1) return -1;
59 result += tmp;
61 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
62 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
63 SAFE_FREE(lanman);
65 else {
66 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
69 if (tmp == -1) return -1;
70 result += tmp;
72 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
74 if (tmp == -1) return -1;
75 result += tmp;
77 return result;
80 /****************************************************************************
81 Do a 'guest' logon, getting back the
82 ****************************************************************************/
84 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
85 TALLOC_CTX *mem_ctx,
86 struct auth_session_info **session_info)
88 struct auth4_context *auth_context;
89 struct auth_usersupplied_info *user_info = NULL;
90 uint8_t chal[8];
91 NTSTATUS nt_status;
93 DEBUG(3,("Got anonymous request\n"));
95 nt_status = make_auth4_context(talloc_tos(), &auth_context);
96 if (!NT_STATUS_IS_OK(nt_status)) {
97 return nt_status;
100 auth_context->get_ntlm_challenge(auth_context,
101 chal);
103 if (!make_user_info_guest(talloc_tos(), remote_address, &user_info)) {
104 TALLOC_FREE(auth_context);
105 return NT_STATUS_NO_MEMORY;
108 nt_status = auth_check_password_session_info(auth_context,
109 mem_ctx, user_info, session_info);
110 TALLOC_FREE(user_info);
111 TALLOC_FREE(auth_context);
112 return nt_status;
115 /****************************************************************************
116 Reply to a session setup command.
117 conn POINTER CAN BE NULL HERE !
118 ****************************************************************************/
120 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
122 const uint8_t *p;
123 DATA_BLOB in_blob;
124 DATA_BLOB out_blob = data_blob_null;
125 size_t bufrem;
126 char *tmp;
127 const char *native_os;
128 const char *native_lanman;
129 const char *primary_domain;
130 uint16_t data_blob_len = SVAL(req->vwv+7, 0);
131 enum remote_arch_types ra_type = get_remote_arch();
132 uint64_t vuid = req->vuid;
133 NTSTATUS status = NT_STATUS_OK;
134 struct smbXsrv_connection *xconn = req->xconn;
135 struct smbd_server_connection *sconn = req->sconn;
136 uint16_t action = 0;
137 NTTIME now = timeval_to_nttime(&req->request_time);
138 struct smbXsrv_session *session = NULL;
139 uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
140 uint32_t client_caps = IVAL(req->vwv+10, 0);
141 struct smbXsrv_session_auth0 *auth;
143 DEBUG(3,("Doing spnego session setup\n"));
145 if (!xconn->smb1.sessions.done_sesssetup) {
146 global_client_caps = client_caps;
148 if (!(global_client_caps & CAP_STATUS32)) {
149 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
153 p = req->buf;
155 if (data_blob_len == 0) {
156 /* an invalid request */
157 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
158 return;
161 bufrem = smbreq_bufrem(req, p);
162 /* pull the spnego blob */
163 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
165 #if 0
166 file_save("negotiate.dat", in_blob.data, in_blob.length);
167 #endif
169 p = req->buf + in_blob.length;
171 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
172 STR_TERMINATE);
173 native_os = tmp ? tmp : "";
175 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
176 STR_TERMINATE);
177 native_lanman = tmp ? tmp : "";
179 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
180 STR_TERMINATE);
181 primary_domain = tmp ? tmp : "";
183 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
184 native_os, native_lanman, primary_domain));
186 if ( ra_type == RA_WIN2K ) {
187 /* Vista sets neither the OS or lanman strings */
189 if ( !strlen(native_os) && !strlen(native_lanman) )
190 set_remote_arch(RA_VISTA);
192 /* Windows 2003 doesn't set the native lanman string,
193 but does set primary domain which is a bug I think */
195 if ( !strlen(native_lanman) ) {
196 ra_lanman_string( primary_domain );
197 } else {
198 ra_lanman_string( native_lanman );
200 } else if ( ra_type == RA_VISTA ) {
201 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
202 set_remote_arch(RA_OSX);
206 if (vuid != 0) {
207 status = smb1srv_session_lookup(xconn,
208 vuid, now,
209 &session);
210 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
211 reply_force_doserror(req, ERRSRV, ERRbaduid);
212 return;
214 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
215 status = NT_STATUS_OK;
217 if (NT_STATUS_IS_OK(status)) {
218 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
219 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
220 TALLOC_FREE(session->pending_auth);
222 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
223 reply_nterror(req, nt_status_squash(status));
224 return;
228 if (session == NULL) {
229 /* create a new session */
230 status = smbXsrv_session_create(xconn,
231 now, &session);
232 if (!NT_STATUS_IS_OK(status)) {
233 reply_nterror(req, nt_status_squash(status));
234 return;
238 status = smbXsrv_session_find_auth(session, xconn, now, &auth);
239 if (!NT_STATUS_IS_OK(status)) {
240 status = smbXsrv_session_create_auth(session, xconn, now,
241 0, /* flags */
242 0, /* security */
243 &auth);
244 if (!NT_STATUS_IS_OK(status)) {
245 reply_nterror(req, nt_status_squash(status));
246 return;
250 if (auth->gensec == NULL) {
251 status = auth_generic_prepare(session, xconn->remote_address,
252 &auth->gensec);
253 if (!NT_STATUS_IS_OK(status)) {
254 TALLOC_FREE(session);
255 reply_nterror(req, nt_status_squash(status));
256 return;
259 gensec_want_feature(auth->gensec, GENSEC_FEATURE_SESSION_KEY);
260 gensec_want_feature(auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
262 status = gensec_start_mech_by_oid(auth->gensec,
263 GENSEC_OID_SPNEGO);
264 if (!NT_STATUS_IS_OK(status)) {
265 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
266 TALLOC_FREE(session);;
267 reply_nterror(req, nt_status_squash(status));
268 return;
272 become_root();
273 status = gensec_update(auth->gensec,
274 talloc_tos(),
275 in_blob, &out_blob);
276 unbecome_root();
277 if (!NT_STATUS_IS_OK(status) &&
278 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
279 TALLOC_FREE(session);
280 reply_nterror(req, nt_status_squash(status));
281 return;
284 if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
285 struct auth_session_info *session_info = NULL;
287 status = gensec_session_info(auth->gensec,
288 session,
289 &session_info);
290 if (!NT_STATUS_IS_OK(status)) {
291 DEBUG(1,("Failed to generate session_info "
292 "(user and group token) for session setup: %s\n",
293 nt_errstr(status)));
294 data_blob_free(&out_blob);
295 TALLOC_FREE(session);
296 reply_nterror(req, nt_status_squash(status));
297 return;
300 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
301 action = 1;
304 if (session_info->session_key.length > 0) {
305 struct smbXsrv_session *x = session;
308 * Note: the SMB1 signing key is not truncated to 16 byte!
310 x->global->signing_key =
311 data_blob_dup_talloc(x->global,
312 session_info->session_key);
313 if (x->global->signing_key.data == NULL) {
314 data_blob_free(&out_blob);
315 TALLOC_FREE(session);
316 reply_nterror(req, NT_STATUS_NO_MEMORY);
317 return;
321 * clear the session key
322 * the first tcon will add setup the application key
324 data_blob_clear_free(&session_info->session_key);
327 session->compat = talloc_zero(session, struct user_struct);
328 if (session->compat == NULL) {
329 data_blob_free(&out_blob);
330 TALLOC_FREE(session);
331 reply_nterror(req, NT_STATUS_NO_MEMORY);
332 return;
334 session->compat->session = session;
335 session->compat->homes_snum = -1;
336 session->compat->session_info = session_info;
337 session->compat->session_keystr = NULL;
338 session->compat->vuid = session->global->session_wire_id;
339 DLIST_ADD(sconn->users, session->compat);
340 sconn->num_users++;
342 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
343 session->compat->homes_snum =
344 register_homes_share(session_info->unix_info->unix_name);
347 if (srv_is_signing_negotiated(xconn) &&
348 action == 0 &&
349 session->global->signing_key.length > 0)
352 * Try and turn on server signing on the first non-guest
353 * sessionsetup.
355 srv_set_signing(xconn,
356 session->global->signing_key,
357 data_blob_null);
360 set_current_user_info(session_info->unix_info->sanitized_username,
361 session_info->unix_info->unix_name,
362 session_info->info->domain_name);
364 session->status = NT_STATUS_OK;
365 session->global->auth_session_info = talloc_move(session->global,
366 &session_info);
367 session->global->auth_session_info_seqnum += 1;
368 session->global->channels[0].auth_session_info_seqnum =
369 session->global->auth_session_info_seqnum;
370 session->global->auth_time = now;
371 if (client_caps & CAP_DYNAMIC_REAUTH) {
372 session->global->expiration_time =
373 gensec_expire_time(auth->gensec);
374 } else {
375 session->global->expiration_time =
376 GENSEC_EXPIRE_TIME_INFINITY;
379 if (!session_claim(session)) {
380 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
381 (unsigned long long)session->compat->vuid));
382 data_blob_free(&out_blob);
383 TALLOC_FREE(session);
384 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
385 return;
388 status = smbXsrv_session_update(session);
389 if (!NT_STATUS_IS_OK(status)) {
390 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
391 (unsigned long long)session->compat->vuid,
392 nt_errstr(status)));
393 data_blob_free(&out_blob);
394 TALLOC_FREE(session);
395 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
396 return;
399 if (!xconn->smb1.sessions.done_sesssetup) {
400 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
401 reply_force_doserror(req, ERRSRV, ERRerror);
402 return;
404 xconn->smb1.sessions.max_send = smb_bufsize;
405 xconn->smb1.sessions.done_sesssetup = true;
408 /* current_user_info is changed on new vuid */
409 reload_services(sconn, conn_snum_used, true);
410 } else if (NT_STATUS_IS_OK(status)) {
411 struct auth_session_info *session_info = NULL;
413 status = gensec_session_info(auth->gensec,
414 session,
415 &session_info);
416 if (!NT_STATUS_IS_OK(status)) {
417 DEBUG(1,("Failed to generate session_info "
418 "(user and group token) for session setup: %s\n",
419 nt_errstr(status)));
420 data_blob_free(&out_blob);
421 TALLOC_FREE(session);
422 reply_nterror(req, nt_status_squash(status));
423 return;
426 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
427 action = 1;
431 * Keep the application key
433 data_blob_clear_free(&session_info->session_key);
434 session_info->session_key =
435 session->global->auth_session_info->session_key;
436 talloc_steal(session_info, session_info->session_key.data);
437 TALLOC_FREE(session->global->auth_session_info);
439 session->compat->session_info = session_info;
441 session->compat->vuid = session->global->session_wire_id;
443 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
444 session->compat->homes_snum =
445 register_homes_share(session_info->unix_info->unix_name);
448 set_current_user_info(session_info->unix_info->sanitized_username,
449 session_info->unix_info->unix_name,
450 session_info->info->domain_name);
452 session->status = NT_STATUS_OK;
453 session->global->auth_session_info = talloc_move(session->global,
454 &session_info);
455 session->global->auth_session_info_seqnum += 1;
456 session->global->channels[0].auth_session_info_seqnum =
457 session->global->auth_session_info_seqnum;
458 session->global->auth_time = now;
459 if (client_caps & CAP_DYNAMIC_REAUTH) {
460 session->global->expiration_time =
461 gensec_expire_time(auth->gensec);
462 } else {
463 session->global->expiration_time =
464 GENSEC_EXPIRE_TIME_INFINITY;
467 status = smbXsrv_session_update(session);
468 if (!NT_STATUS_IS_OK(status)) {
469 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
470 (unsigned long long)session->compat->vuid,
471 nt_errstr(status)));
472 data_blob_free(&out_blob);
473 TALLOC_FREE(session);
474 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
475 return;
478 conn_clear_vuid_caches(sconn, session->compat->vuid);
480 /* current_user_info is changed on new vuid */
481 reload_services(sconn, conn_snum_used, true);
484 vuid = session->global->session_wire_id;
486 reply_outbuf(req, 4, 0);
488 SSVAL(req->outbuf, smb_uid, vuid);
489 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
490 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
491 SSVAL(req->outbuf, smb_vwv2, action);
492 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
494 if (message_push_blob(&req->outbuf, out_blob) == -1) {
495 data_blob_free(&out_blob);
496 TALLOC_FREE(session);
497 reply_nterror(req, NT_STATUS_NO_MEMORY);
498 return;
500 data_blob_free(&out_blob);
502 if (push_signature(&req->outbuf) == -1) {
503 TALLOC_FREE(session);
504 reply_nterror(req, NT_STATUS_NO_MEMORY);
505 return;
509 /****************************************************************************
510 On new VC == 0, shutdown *all* old connections and users.
511 It seems that only NT4.x does this. At W2K and above (XP etc.).
512 a new session setup with VC==0 is ignored.
513 ****************************************************************************/
515 struct shutdown_state {
516 const char *ip;
517 struct messaging_context *msg_ctx;
520 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
521 void *private_data)
523 struct shutdown_state *state = (struct shutdown_state *)private_data;
524 struct server_id self_pid = messaging_server_id(state->msg_ctx);
525 struct server_id pid = session->channels[0].server_id;
526 const char *addr = session->channels[0].remote_address;
527 struct server_id_buf tmp;
529 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
530 server_id_str_buf(pid, &tmp), addr));
532 if (!process_exists(pid)) {
533 DEBUG(10, ("process does not exist\n"));
534 return 0;
537 if (serverid_equal(&pid, &self_pid)) {
538 DEBUG(10, ("It's me\n"));
539 return 0;
543 * here we use strstr() because 'addr'
544 * (session->channels[0].remote_address)
545 * contains a string like:
546 * 'ipv4:127.0.0.1:48163'
548 if (strstr(addr, state->ip) == NULL) {
549 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
550 return 0;
553 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
554 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
555 state->ip));
557 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
558 &data_blob_null);
559 return 0;
562 static void setup_new_vc_session(struct smbd_server_connection *sconn)
564 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
565 "compatible we would close all old resources.\n"));
566 #if 0
567 conn_close_all();
568 invalidate_all_vuids();
569 #endif
570 if (lp_reset_on_zero_vc()) {
571 char *addr;
572 struct shutdown_state state;
574 addr = tsocket_address_inet_addr_string(
575 sconn->remote_address, talloc_tos());
576 if (addr == NULL) {
577 return;
579 state.ip = addr;
580 state.msg_ctx = sconn->msg_ctx;
581 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
582 TALLOC_FREE(addr);
586 /****************************************************************************
587 Reply to a session setup command.
588 ****************************************************************************/
590 void reply_sesssetup_and_X(struct smb_request *req)
592 uint64_t sess_vuid;
593 uint16_t smb_bufsize;
594 DATA_BLOB lm_resp;
595 DATA_BLOB nt_resp;
596 DATA_BLOB plaintext_password;
597 char *tmp;
598 const char *user;
599 fstring sub_user; /* Sanitised username for substituion */
600 const char *domain;
601 const char *native_os;
602 const char *native_lanman;
603 const char *primary_domain;
604 struct auth_usersupplied_info *user_info = NULL;
605 struct auth_session_info *session_info = NULL;
606 uint16_t smb_flag2 = req->flags2;
607 uint16_t action = 0;
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 = false;
617 START_PROFILE(SMBsesssetupX);
619 ZERO_STRUCT(lm_resp);
620 ZERO_STRUCT(nt_resp);
621 ZERO_STRUCT(plaintext_password);
623 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
625 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
626 signing_allowed = true;
628 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
629 signing_mandatory = true;
633 * We can call srv_set_signing_negotiated() each time.
634 * It finds out when it needs to turn into a noop
635 * itself.
637 srv_set_signing_negotiated(xconn,
638 signing_allowed,
639 signing_mandatory);
641 /* a SPNEGO session setup has 12 command words, whereas a normal
642 NT1 session setup has 13. See the cifs spec. */
643 if (req->wct == 12 &&
644 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
646 if (!xconn->smb1.negprot.spnego) {
647 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
648 "at SPNEGO session setup when it was not "
649 "negotiated.\n"));
650 reply_nterror(req, nt_status_squash(
651 NT_STATUS_LOGON_FAILURE));
652 END_PROFILE(SMBsesssetupX);
653 return;
656 if (SVAL(req->vwv+4, 0) == 0) {
657 setup_new_vc_session(req->sconn);
660 reply_sesssetup_and_X_spnego(req);
661 END_PROFILE(SMBsesssetupX);
662 return;
665 smb_bufsize = SVAL(req->vwv+2, 0);
667 if (get_Protocol() < PROTOCOL_NT1) {
668 uint16_t passlen1 = SVAL(req->vwv+7, 0);
670 /* Never do NT status codes with protocols before NT1 as we
671 * don't get client caps. */
672 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
674 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
675 reply_nterror(req, nt_status_squash(
676 NT_STATUS_INVALID_PARAMETER));
677 END_PROFILE(SMBsesssetupX);
678 return;
681 if (doencrypt) {
682 lm_resp = data_blob(req->buf, passlen1);
683 } else {
684 plaintext_password = data_blob(req->buf, passlen1+1);
685 /* Ensure null termination */
686 plaintext_password.data[passlen1] = 0;
689 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
690 req->buf + passlen1, STR_TERMINATE);
691 user = tmp ? tmp : "";
693 domain = "";
695 } else {
696 uint16_t passlen1 = SVAL(req->vwv+7, 0);
697 uint16_t passlen2 = SVAL(req->vwv+8, 0);
698 enum remote_arch_types ra_type = get_remote_arch();
699 const uint8_t *p = req->buf;
700 const uint8_t *save_p = req->buf;
701 uint16_t byte_count;
703 if (!xconn->smb1.sessions.done_sesssetup) {
704 global_client_caps = IVAL(req->vwv+11, 0);
706 if (!(global_client_caps & CAP_STATUS32)) {
707 remove_from_common_flags2(
708 FLAGS2_32_BIT_ERROR_CODES);
711 /* client_caps is used as final determination if
712 * client is NT or Win95. This is needed to return
713 * the correct error codes in some circumstances.
716 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
717 ra_type == RA_WIN95) {
718 if(!(global_client_caps & (CAP_NT_SMBS|
719 CAP_STATUS32))) {
720 set_remote_arch( RA_WIN95);
725 if (!doencrypt) {
726 /* both Win95 and WinNT stuff up the password
727 * lengths for non-encrypting systems. Uggh.
729 if passlen1==24 its a win95 system, and its setting
730 the password length incorrectly. Luckily it still
731 works with the default code because Win95 will null
732 terminate the password anyway
734 if passlen1>0 and passlen2>0 then maybe its a NT box
735 and its setting passlen2 to some random value which
736 really stuffs things up. we need to fix that one. */
738 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
739 passlen2 != 1) {
740 passlen2 = 0;
744 /* check for nasty tricks */
745 if (passlen1 > MAX_PASS_LEN
746 || passlen1 > smbreq_bufrem(req, p)) {
747 reply_nterror(req, nt_status_squash(
748 NT_STATUS_INVALID_PARAMETER));
749 END_PROFILE(SMBsesssetupX);
750 return;
753 if (passlen2 > MAX_PASS_LEN
754 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
755 reply_nterror(req, nt_status_squash(
756 NT_STATUS_INVALID_PARAMETER));
757 END_PROFILE(SMBsesssetupX);
758 return;
761 /* Save the lanman2 password and the NT md4 password. */
763 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
764 doencrypt = False;
767 if (doencrypt) {
768 lm_resp = data_blob(p, passlen1);
769 nt_resp = data_blob(p+passlen1, passlen2);
770 } else {
771 char *pass = NULL;
772 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
774 if (unic && (passlen2 == 0) && passlen1) {
775 /* Only a ascii plaintext password was sent. */
776 (void)srvstr_pull_talloc(talloc_tos(),
777 req->inbuf,
778 req->flags2,
779 &pass,
780 req->buf,
781 passlen1,
782 STR_TERMINATE|STR_ASCII);
783 } else {
784 (void)srvstr_pull_talloc(talloc_tos(),
785 req->inbuf,
786 req->flags2,
787 &pass,
788 req->buf,
789 unic ? passlen2 : passlen1,
790 STR_TERMINATE);
792 if (!pass) {
793 reply_nterror(req, nt_status_squash(
794 NT_STATUS_INVALID_PARAMETER));
795 END_PROFILE(SMBsesssetupX);
796 return;
798 plaintext_password = data_blob(pass, strlen(pass)+1);
801 p += passlen1 + passlen2;
803 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
804 STR_TERMINATE);
805 user = tmp ? tmp : "";
807 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
808 STR_TERMINATE);
809 domain = tmp ? tmp : "";
811 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
812 STR_TERMINATE);
813 native_os = tmp ? tmp : "";
815 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
816 STR_TERMINATE);
817 native_lanman = tmp ? tmp : "";
819 /* not documented or decoded by Ethereal but there is one more
820 * string in the extra bytes which is the same as the
821 * PrimaryDomain when using extended security. Windows NT 4
822 * and 2003 use this string to store the native lanman string.
823 * Windows 9x does not include a string here at all so we have
824 * to check if we have any extra bytes left */
826 byte_count = SVAL(req->vwv+13, 0);
827 if ( PTR_DIFF(p, save_p) < byte_count) {
828 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
829 STR_TERMINATE);
830 primary_domain = tmp ? tmp : "";
831 } else {
832 primary_domain = talloc_strdup(talloc_tos(), "null");
835 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
836 "PrimaryDomain=[%s]\n",
837 domain, native_os, native_lanman, primary_domain));
839 if ( ra_type == RA_WIN2K ) {
840 if ( strlen(native_lanman) == 0 )
841 ra_lanman_string( primary_domain );
842 else
843 ra_lanman_string( native_lanman );
848 if (SVAL(req->vwv+4, 0) == 0) {
849 setup_new_vc_session(req->sconn);
852 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
853 domain, user, get_remote_machine_name()));
855 if (*user) {
856 if (xconn->smb1.negprot.spnego) {
858 /* This has to be here, because this is a perfectly
859 * valid behaviour for guest logons :-( */
861 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
862 "at 'normal' session setup after "
863 "negotiating spnego.\n"));
864 reply_nterror(req, nt_status_squash(
865 NT_STATUS_LOGON_FAILURE));
866 END_PROFILE(SMBsesssetupX);
867 return;
869 fstrcpy(sub_user, user);
870 } else {
871 fstrcpy(sub_user, "");
874 sub_set_smb_name(sub_user);
876 reload_services(sconn, conn_snum_used, true);
878 if (!*user) {
880 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
882 } else if (doencrypt) {
883 struct auth4_context *negprot_auth_context = NULL;
884 negprot_auth_context = xconn->smb1.negprot.auth_context;
885 if (!negprot_auth_context) {
886 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
887 "session setup without negprot denied!\n"));
888 reply_nterror(req, nt_status_squash(
889 NT_STATUS_LOGON_FAILURE));
890 END_PROFILE(SMBsesssetupX);
891 return;
893 nt_status = make_user_info_for_reply_enc(talloc_tos(),
894 &user_info, user,
895 domain,
896 sconn->remote_address,
897 lm_resp, nt_resp);
898 if (NT_STATUS_IS_OK(nt_status)) {
899 nt_status = auth_check_password_session_info(negprot_auth_context,
900 req, user_info, &session_info);
902 } else {
903 struct auth4_context *plaintext_auth_context = NULL;
905 nt_status = make_auth4_context(
906 talloc_tos(), &plaintext_auth_context);
908 if (NT_STATUS_IS_OK(nt_status)) {
909 uint8_t chal[8];
911 plaintext_auth_context->get_ntlm_challenge(
912 plaintext_auth_context, chal);
914 if (!make_user_info_for_reply(talloc_tos(),
915 &user_info,
916 user, domain,
917 sconn->remote_address,
918 chal,
919 plaintext_password)) {
920 nt_status = NT_STATUS_NO_MEMORY;
923 if (NT_STATUS_IS_OK(nt_status)) {
924 nt_status = auth_check_password_session_info(plaintext_auth_context,
925 req, user_info, &session_info);
927 TALLOC_FREE(plaintext_auth_context);
931 TALLOC_FREE(user_info);
933 if (!NT_STATUS_IS_OK(nt_status)) {
934 data_blob_free(&nt_resp);
935 data_blob_free(&lm_resp);
936 data_blob_clear_free(&plaintext_password);
937 reply_nterror(req, nt_status_squash(nt_status));
938 END_PROFILE(SMBsesssetupX);
939 return;
942 data_blob_clear_free(&plaintext_password);
944 /* it's ok - setup a reply */
945 reply_outbuf(req, 3, 0);
946 SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
947 SSVAL(req->outbuf, smb_vwv1, 0); /* no andx offset */
949 if (get_Protocol() >= PROTOCOL_NT1) {
950 push_signature(&req->outbuf);
951 /* perhaps grab OS version here?? */
954 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
955 action = 1;
958 /* register the name and uid as being validated, so further connections
959 to a uid can get through without a password, on the same VC */
961 nt_status = smbXsrv_session_create(xconn,
962 now, &session);
963 if (!NT_STATUS_IS_OK(nt_status)) {
964 data_blob_free(&nt_resp);
965 data_blob_free(&lm_resp);
966 reply_nterror(req, nt_status_squash(nt_status));
967 END_PROFILE(SMBsesssetupX);
968 return;
971 if (session_info->session_key.length > 0) {
972 uint8_t session_key[16];
975 * Note: the SMB1 signing key is not truncated to 16 byte!
977 session->global->signing_key =
978 data_blob_dup_talloc(session->global,
979 session_info->session_key);
980 if (session->global->signing_key.data == NULL) {
981 data_blob_free(&nt_resp);
982 data_blob_free(&lm_resp);
983 TALLOC_FREE(session);
984 reply_nterror(req, NT_STATUS_NO_MEMORY);
985 END_PROFILE(SMBsesssetupX);
986 return;
990 * The application key is truncated/padded to 16 bytes
992 ZERO_STRUCT(session_key);
993 memcpy(session_key, session->global->signing_key.data,
994 MIN(session->global->signing_key.length,
995 sizeof(session_key)));
996 session->global->application_key =
997 data_blob_talloc(session->global,
998 session_key,
999 sizeof(session_key));
1000 ZERO_STRUCT(session_key);
1001 if (session->global->application_key.data == NULL) {
1002 data_blob_free(&nt_resp);
1003 data_blob_free(&lm_resp);
1004 TALLOC_FREE(session);
1005 reply_nterror(req, NT_STATUS_NO_MEMORY);
1006 END_PROFILE(SMBsesssetupX);
1007 return;
1011 * Place the application key into the session_info
1013 data_blob_clear_free(&session_info->session_key);
1014 session_info->session_key = data_blob_dup_talloc(session_info,
1015 session->global->application_key);
1016 if (session_info->session_key.data == NULL) {
1017 data_blob_free(&nt_resp);
1018 data_blob_free(&lm_resp);
1019 TALLOC_FREE(session);
1020 reply_nterror(req, NT_STATUS_NO_MEMORY);
1021 END_PROFILE(SMBsesssetupX);
1022 return;
1026 session->compat = talloc_zero(session, struct user_struct);
1027 if (session->compat == NULL) {
1028 data_blob_free(&nt_resp);
1029 data_blob_free(&lm_resp);
1030 TALLOC_FREE(session);
1031 reply_nterror(req, NT_STATUS_NO_MEMORY);
1032 END_PROFILE(SMBsesssetupX);
1033 return;
1035 session->compat->session = session;
1036 session->compat->homes_snum = -1;
1037 session->compat->session_info = session_info;
1038 session->compat->session_keystr = NULL;
1039 session->compat->vuid = session->global->session_wire_id;
1040 DLIST_ADD(sconn->users, session->compat);
1041 sconn->num_users++;
1043 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1044 session->compat->homes_snum =
1045 register_homes_share(session_info->unix_info->unix_name);
1048 if (srv_is_signing_negotiated(xconn) &&
1049 action == 0 &&
1050 session->global->signing_key.length > 0)
1053 * Try and turn on server signing on the first non-guest
1054 * sessionsetup.
1056 srv_set_signing(xconn,
1057 session->global->signing_key,
1058 nt_resp.data ? nt_resp : lm_resp);
1061 set_current_user_info(session_info->unix_info->sanitized_username,
1062 session_info->unix_info->unix_name,
1063 session_info->info->domain_name);
1065 session->status = NT_STATUS_OK;
1066 session->global->auth_session_info = talloc_move(session->global,
1067 &session_info);
1068 session->global->auth_session_info_seqnum += 1;
1069 session->global->channels[0].auth_session_info_seqnum =
1070 session->global->auth_session_info_seqnum;
1071 session->global->auth_time = now;
1072 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1074 nt_status = smbXsrv_session_update(session);
1075 if (!NT_STATUS_IS_OK(nt_status)) {
1076 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1077 (unsigned long long)session->compat->vuid,
1078 nt_errstr(nt_status)));
1079 data_blob_free(&nt_resp);
1080 data_blob_free(&lm_resp);
1081 TALLOC_FREE(session);
1082 reply_nterror(req, nt_status_squash(nt_status));
1083 END_PROFILE(SMBsesssetupX);
1084 return;
1087 if (!session_claim(session)) {
1088 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1089 (unsigned long long)session->compat->vuid));
1090 data_blob_free(&nt_resp);
1091 data_blob_free(&lm_resp);
1092 TALLOC_FREE(session);
1093 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1094 END_PROFILE(SMBsesssetupX);
1095 return;
1098 /* current_user_info is changed on new vuid */
1099 reload_services(sconn, conn_snum_used, true);
1101 sess_vuid = session->global->session_wire_id;
1103 data_blob_free(&nt_resp);
1104 data_blob_free(&lm_resp);
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 END_PROFILE(SMBsesssetupX);