source: vendor/current/source3/smbd/sesssetup.c

Last change on this file was 989, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.7

File size: 31.5 KB
Line 
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
10
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.
15
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.
20
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/>.
23*/
24
25#include "includes.h"
26#include "../lib/tsocket/tsocket.h"
27#include "smbd/smbd.h"
28#include "smbd/globals.h"
29#include "auth.h"
30#include "messages.h"
31#include "smbprofile.h"
32#include "../libcli/security/security.h"
33#include "auth/gensec/gensec.h"
34#include "lib/conn_tdb.h"
35#include "../libcli/smb/smb_signing.h"
36
37/****************************************************************************
38 Add the standard 'Samba' signature to the end of the session setup.
39****************************************************************************/
40
41static int push_signature(uint8_t **outbuf)
42{
43 char *lanman;
44 int result, tmp;
45 fstring native_os;
46
47 result = 0;
48
49 fstr_sprintf(native_os, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION,
50 SAMBA_MINOR_NBT_ANNOUNCE_VERSION);
51
52 tmp = message_push_string(outbuf, native_os, STR_TERMINATE);
53
54 if (tmp == -1) return -1;
55 result += tmp;
56
57 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
58 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
59 SAFE_FREE(lanman);
60 }
61 else {
62 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
63 }
64
65 if (tmp == -1) return -1;
66 result += tmp;
67
68 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
69
70 if (tmp == -1) return -1;
71 result += tmp;
72
73 return result;
74}
75
76/****************************************************************************
77 Do a 'guest' logon, getting back the
78****************************************************************************/
79
80static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
81 TALLOC_CTX *mem_ctx,
82 struct auth_session_info **session_info)
83{
84 struct auth4_context *auth_context;
85 struct auth_usersupplied_info *user_info = NULL;
86 uint8_t chal[8];
87 NTSTATUS nt_status;
88
89 DEBUG(3,("Got anonymous request\n"));
90
91 nt_status = make_auth4_context(talloc_tos(), &auth_context);
92 if (!NT_STATUS_IS_OK(nt_status)) {
93 return nt_status;
94 }
95
96 auth_context->get_ntlm_challenge(auth_context,
97 chal);
98
99 if (!make_user_info_guest(talloc_tos(), remote_address, &user_info)) {
100 TALLOC_FREE(auth_context);
101 return NT_STATUS_NO_MEMORY;
102 }
103
104 nt_status = auth_check_password_session_info(auth_context,
105 mem_ctx, user_info, session_info);
106 TALLOC_FREE(user_info);
107 TALLOC_FREE(auth_context);
108 return nt_status;
109}
110
111/****************************************************************************
112 Reply to a session setup command.
113 conn POINTER CAN BE NULL HERE !
114****************************************************************************/
115
116static void reply_sesssetup_and_X_spnego(struct smb_request *req)
117{
118 const uint8_t *p;
119 DATA_BLOB in_blob;
120 DATA_BLOB out_blob = data_blob_null;
121 size_t bufrem;
122 char *tmp;
123 const char *native_os;
124 const char *native_lanman;
125 const char *primary_domain;
126 uint16_t data_blob_len = SVAL(req->vwv+7, 0);
127 enum remote_arch_types ra_type = get_remote_arch();
128 uint64_t vuid = req->vuid;
129 NTSTATUS status = NT_STATUS_OK;
130 struct smbXsrv_connection *xconn = req->xconn;
131 struct smbd_server_connection *sconn = req->sconn;
132 uint16_t action = 0;
133 bool is_authenticated = false;
134 NTTIME now = timeval_to_nttime(&req->request_time);
135 struct smbXsrv_session *session = NULL;
136 uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
137 uint32_t client_caps = IVAL(req->vwv+10, 0);
138 struct smbXsrv_session_auth0 *auth;
139
140 DEBUG(3,("Doing spnego session setup\n"));
141
142 if (!xconn->smb1.sessions.done_sesssetup) {
143 global_client_caps = client_caps;
144
145 if (!(global_client_caps & CAP_STATUS32)) {
146 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
147 }
148 }
149
150 p = req->buf;
151
152 if (data_blob_len == 0) {
153 /* an invalid request */
154 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
155 return;
156 }
157
158 bufrem = smbreq_bufrem(req, p);
159 /* pull the spnego blob */
160 in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
161
162#if 0
163 file_save("negotiate.dat", in_blob.data, in_blob.length);
164#endif
165
166 p = req->buf + in_blob.length;
167
168 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
169 STR_TERMINATE);
170 native_os = tmp ? tmp : "";
171
172 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
173 STR_TERMINATE);
174 native_lanman = tmp ? tmp : "";
175
176 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
177 STR_TERMINATE);
178 primary_domain = tmp ? tmp : "";
179
180 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
181 native_os, native_lanman, primary_domain));
182
183 if ( ra_type == RA_WIN2K ) {
184 /* Vista sets neither the OS or lanman strings */
185
186 if ( !strlen(native_os) && !strlen(native_lanman) )
187 set_remote_arch(RA_VISTA);
188
189 /* Windows 2003 doesn't set the native lanman string,
190 but does set primary domain which is a bug I think */
191
192 if ( !strlen(native_lanman) ) {
193 ra_lanman_string( primary_domain );
194 } else {
195 ra_lanman_string( native_lanman );
196 }
197 } else if ( ra_type == RA_VISTA ) {
198 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
199 set_remote_arch(RA_OSX);
200 }
201 }
202
203 if (vuid != 0) {
204 status = smb1srv_session_lookup(xconn,
205 vuid, now,
206 &session);
207 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
208 reply_force_doserror(req, ERRSRV, ERRbaduid);
209 return;
210 }
211 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
212 status = NT_STATUS_OK;
213 }
214 if (NT_STATUS_IS_OK(status)) {
215 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
216 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
217 TALLOC_FREE(session->pending_auth);
218 }
219 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
220 reply_nterror(req, nt_status_squash(status));
221 return;
222 }
223 }
224
225 if (session == NULL) {
226 /* create a new session */
227 status = smbXsrv_session_create(xconn,
228 now, &session);
229 if (!NT_STATUS_IS_OK(status)) {
230 reply_nterror(req, nt_status_squash(status));
231 return;
232 }
233 }
234
235 status = smbXsrv_session_find_auth(session, xconn, now, &auth);
236 if (!NT_STATUS_IS_OK(status)) {
237 status = smbXsrv_session_create_auth(session, xconn, now,
238 0, /* flags */
239 0, /* security */
240 &auth);
241 if (!NT_STATUS_IS_OK(status)) {
242 reply_nterror(req, nt_status_squash(status));
243 return;
244 }
245 }
246
247 if (auth->gensec == NULL) {
248 status = auth_generic_prepare(session, xconn->remote_address,
249 &auth->gensec);
250 if (!NT_STATUS_IS_OK(status)) {
251 TALLOC_FREE(session);
252 reply_nterror(req, nt_status_squash(status));
253 return;
254 }
255
256 gensec_want_feature(auth->gensec, GENSEC_FEATURE_SESSION_KEY);
257 gensec_want_feature(auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
258
259 status = gensec_start_mech_by_oid(auth->gensec,
260 GENSEC_OID_SPNEGO);
261 if (!NT_STATUS_IS_OK(status)) {
262 DEBUG(0, ("Failed to start SPNEGO handler!\n"));
263 TALLOC_FREE(session);;
264 reply_nterror(req, nt_status_squash(status));
265 return;
266 }
267 }
268
269 become_root();
270 status = gensec_update(auth->gensec,
271 talloc_tos(),
272 in_blob, &out_blob);
273 unbecome_root();
274 if (!NT_STATUS_IS_OK(status) &&
275 !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
276 TALLOC_FREE(session);
277 reply_nterror(req, nt_status_squash(status));
278 return;
279 }
280
281 if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
282 struct auth_session_info *session_info = NULL;
283
284 status = gensec_session_info(auth->gensec,
285 session,
286 &session_info);
287 if (!NT_STATUS_IS_OK(status)) {
288 DEBUG(1,("Failed to generate session_info "
289 "(user and group token) for session setup: %s\n",
290 nt_errstr(status)));
291 data_blob_free(&out_blob);
292 TALLOC_FREE(session);
293 reply_nterror(req, nt_status_squash(status));
294 return;
295 }
296
297 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
298 action |= SMB_SETUP_GUEST;
299 }
300
301 if (session_info->session_key.length > 0) {
302 struct smbXsrv_session *x = session;
303
304 /*
305 * Note: the SMB1 signing key is not truncated to 16 byte!
306 */
307 x->global->signing_key =
308 data_blob_dup_talloc(x->global,
309 session_info->session_key);
310 if (x->global->signing_key.data == NULL) {
311 data_blob_free(&out_blob);
312 TALLOC_FREE(session);
313 reply_nterror(req, NT_STATUS_NO_MEMORY);
314 return;
315 }
316
317 /*
318 * clear the session key
319 * the first tcon will add setup the application key
320 */
321 data_blob_clear_free(&session_info->session_key);
322 }
323
324 session->compat = talloc_zero(session, struct user_struct);
325 if (session->compat == NULL) {
326 data_blob_free(&out_blob);
327 TALLOC_FREE(session);
328 reply_nterror(req, NT_STATUS_NO_MEMORY);
329 return;
330 }
331 session->compat->session = session;
332 session->compat->homes_snum = -1;
333 session->compat->session_info = session_info;
334 session->compat->session_keystr = NULL;
335 session->compat->vuid = session->global->session_wire_id;
336 DLIST_ADD(sconn->users, session->compat);
337 sconn->num_users++;
338
339 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
340 is_authenticated = true;
341 session->compat->homes_snum =
342 register_homes_share(session_info->unix_info->unix_name);
343 }
344
345 if (srv_is_signing_negotiated(xconn) &&
346 is_authenticated &&
347 session->global->signing_key.length > 0)
348 {
349 /*
350 * Try and turn on server signing on the first non-guest
351 * sessionsetup.
352 */
353 srv_set_signing(xconn,
354 session->global->signing_key,
355 data_blob_null);
356 }
357
358 set_current_user_info(session_info->unix_info->sanitized_username,
359 session_info->unix_info->unix_name,
360 session_info->info->domain_name);
361
362 session->status = NT_STATUS_OK;
363 session->global->auth_session_info = talloc_move(session->global,
364 &session_info);
365 session->global->auth_session_info_seqnum += 1;
366 session->global->channels[0].auth_session_info_seqnum =
367 session->global->auth_session_info_seqnum;
368 session->global->auth_time = now;
369 if (client_caps & CAP_DYNAMIC_REAUTH) {
370 session->global->expiration_time =
371 gensec_expire_time(auth->gensec);
372 } else {
373 session->global->expiration_time =
374 GENSEC_EXPIRE_TIME_INFINITY;
375 }
376
377 if (!session_claim(session)) {
378 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
379 (unsigned long long)session->compat->vuid));
380 data_blob_free(&out_blob);
381 TALLOC_FREE(session);
382 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
383 return;
384 }
385
386 status = smbXsrv_session_update(session);
387 if (!NT_STATUS_IS_OK(status)) {
388 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
389 (unsigned long long)session->compat->vuid,
390 nt_errstr(status)));
391 data_blob_free(&out_blob);
392 TALLOC_FREE(session);
393 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
394 return;
395 }
396
397 if (!xconn->smb1.sessions.done_sesssetup) {
398 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
399 reply_force_doserror(req, ERRSRV, ERRerror);
400 return;
401 }
402 xconn->smb1.sessions.max_send = smb_bufsize;
403 xconn->smb1.sessions.done_sesssetup = true;
404 }
405
406 /* current_user_info is changed on new vuid */
407 reload_services(sconn, conn_snum_used, true);
408 } else if (NT_STATUS_IS_OK(status)) {
409 struct auth_session_info *session_info = NULL;
410
411 status = gensec_session_info(auth->gensec,
412 session,
413 &session_info);
414 if (!NT_STATUS_IS_OK(status)) {
415 DEBUG(1,("Failed to generate session_info "
416 "(user and group token) for session setup: %s\n",
417 nt_errstr(status)));
418 data_blob_free(&out_blob);
419 TALLOC_FREE(session);
420 reply_nterror(req, nt_status_squash(status));
421 return;
422 }
423
424 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
425 action |= SMB_SETUP_GUEST;
426 }
427
428 /*
429 * Keep the application key
430 */
431 data_blob_clear_free(&session_info->session_key);
432 session_info->session_key =
433 session->global->auth_session_info->session_key;
434 talloc_steal(session_info, session_info->session_key.data);
435 TALLOC_FREE(session->global->auth_session_info);
436
437 session->compat->session_info = session_info;
438
439 session->compat->vuid = session->global->session_wire_id;
440
441 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
442 session->compat->homes_snum =
443 register_homes_share(session_info->unix_info->unix_name);
444 }
445
446 set_current_user_info(session_info->unix_info->sanitized_username,
447 session_info->unix_info->unix_name,
448 session_info->info->domain_name);
449
450 session->status = NT_STATUS_OK;
451 session->global->auth_session_info = talloc_move(session->global,
452 &session_info);
453 session->global->auth_session_info_seqnum += 1;
454 session->global->channels[0].auth_session_info_seqnum =
455 session->global->auth_session_info_seqnum;
456 session->global->auth_time = now;
457 if (client_caps & CAP_DYNAMIC_REAUTH) {
458 session->global->expiration_time =
459 gensec_expire_time(auth->gensec);
460 } else {
461 session->global->expiration_time =
462 GENSEC_EXPIRE_TIME_INFINITY;
463 }
464
465 status = smbXsrv_session_update(session);
466 if (!NT_STATUS_IS_OK(status)) {
467 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
468 (unsigned long long)session->compat->vuid,
469 nt_errstr(status)));
470 data_blob_free(&out_blob);
471 TALLOC_FREE(session);
472 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
473 return;
474 }
475
476 conn_clear_vuid_caches(sconn, session->compat->vuid);
477
478 /* current_user_info is changed on new vuid */
479 reload_services(sconn, conn_snum_used, true);
480 }
481
482 vuid = session->global->session_wire_id;
483
484 reply_outbuf(req, 4, 0);
485
486 SSVAL(req->outbuf, smb_uid, vuid);
487 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
488 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
489 SSVAL(req->outbuf, smb_vwv2, action);
490 SSVAL(req->outbuf, smb_vwv3, out_blob.length);
491
492 if (message_push_blob(&req->outbuf, out_blob) == -1) {
493 data_blob_free(&out_blob);
494 TALLOC_FREE(session);
495 reply_nterror(req, NT_STATUS_NO_MEMORY);
496 return;
497 }
498 data_blob_free(&out_blob);
499
500 if (push_signature(&req->outbuf) == -1) {
501 TALLOC_FREE(session);
502 reply_nterror(req, NT_STATUS_NO_MEMORY);
503 return;
504 }
505}
506
507/****************************************************************************
508 On new VC == 0, shutdown *all* old connections and users.
509 It seems that only NT4.x does this. At W2K and above (XP etc.).
510 a new session setup with VC==0 is ignored.
511****************************************************************************/
512
513struct shutdown_state {
514 const char *ip;
515 struct messaging_context *msg_ctx;
516};
517
518static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
519 void *private_data)
520{
521 struct shutdown_state *state = (struct shutdown_state *)private_data;
522 struct server_id self_pid = messaging_server_id(state->msg_ctx);
523 struct server_id pid = session->channels[0].server_id;
524 const char *addr = session->channels[0].remote_address;
525 struct server_id_buf tmp;
526
527 DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
528 server_id_str_buf(pid, &tmp), addr));
529
530 if (!process_exists(pid)) {
531 DEBUG(10, ("process does not exist\n"));
532 return 0;
533 }
534
535 if (serverid_equal(&pid, &self_pid)) {
536 DEBUG(10, ("It's me\n"));
537 return 0;
538 }
539
540 /*
541 * here we use strstr() because 'addr'
542 * (session->channels[0].remote_address)
543 * contains a string like:
544 * 'ipv4:127.0.0.1:48163'
545 */
546 if (strstr(addr, state->ip) == NULL) {
547 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
548 return 0;
549 }
550
551 DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
552 "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
553 state->ip));
554
555 messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
556 &data_blob_null);
557 return 0;
558}
559
560static void setup_new_vc_session(struct smbd_server_connection *sconn)
561{
562 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
563 "compatible we would close all old resources.\n"));
564#if 0
565 conn_close_all();
566 invalidate_all_vuids();
567#endif
568 if (lp_reset_on_zero_vc()) {
569 char *addr;
570 struct shutdown_state state;
571
572 addr = tsocket_address_inet_addr_string(
573 sconn->remote_address, talloc_tos());
574 if (addr == NULL) {
575 return;
576 }
577 state.ip = addr;
578 state.msg_ctx = sconn->msg_ctx;
579 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
580 TALLOC_FREE(addr);
581 }
582}
583
584/****************************************************************************
585 Reply to a session setup command.
586****************************************************************************/
587
588void reply_sesssetup_and_X(struct smb_request *req)
589{
590 uint64_t sess_vuid;
591 uint16_t smb_bufsize;
592 DATA_BLOB lm_resp;
593 DATA_BLOB nt_resp;
594 DATA_BLOB plaintext_password;
595 char *tmp;
596 const char *user;
597 fstring sub_user; /* Sanitised username for substituion */
598 const char *domain;
599 const char *native_os;
600 const char *native_lanman;
601 const char *primary_domain;
602 struct auth_usersupplied_info *user_info = NULL;
603 struct auth_session_info *session_info = NULL;
604 uint16_t smb_flag2 = req->flags2;
605 uint16_t action = 0;
606 bool is_authenticated = false;
607 NTTIME now = timeval_to_nttime(&req->request_time);
608 struct smbXsrv_session *session = NULL;
609 NTSTATUS nt_status;
610 struct smbXsrv_connection *xconn = req->xconn;
611 struct smbd_server_connection *sconn = req->sconn;
612 bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
613 bool signing_allowed = false;
614 bool signing_mandatory = smb_signing_is_mandatory(
615 xconn->smb1.signing_state);
616
617 START_PROFILE(SMBsesssetupX);
618
619 ZERO_STRUCT(lm_resp);
620 ZERO_STRUCT(nt_resp);
621 ZERO_STRUCT(plaintext_password);
622
623 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
624
625 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
626 signing_allowed = true;
627 }
628 if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
629 signing_mandatory = true;
630 }
631
632 /*
633 * We can call srv_set_signing_negotiated() each time.
634 * It finds out when it needs to turn into a noop
635 * itself.
636 */
637 srv_set_signing_negotiated(xconn,
638 signing_allowed,
639 signing_mandatory);
640
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)) {
645
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;
654 }
655
656 if (SVAL(req->vwv+4, 0) == 0) {
657 setup_new_vc_session(req->sconn);
658 }
659
660 reply_sesssetup_and_X_spnego(req);
661 END_PROFILE(SMBsesssetupX);
662 return;
663 }
664
665 smb_bufsize = SVAL(req->vwv+2, 0);
666
667 if (get_Protocol() < PROTOCOL_NT1) {
668 uint16_t passlen1 = SVAL(req->vwv+7, 0);
669
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);
673
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;
679 }
680
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;
687 }
688
689 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
690 req->buf + passlen1, STR_TERMINATE);
691 user = tmp ? tmp : "";
692
693 domain = "";
694
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;
702
703 if (!xconn->smb1.sessions.done_sesssetup) {
704 global_client_caps = IVAL(req->vwv+11, 0);
705
706 if (!(global_client_caps & CAP_STATUS32)) {
707 remove_from_common_flags2(
708 FLAGS2_32_BIT_ERROR_CODES);
709 }
710
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.
714 */
715
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);
721 }
722 }
723 }
724
725 if (!doencrypt) {
726 /* both Win95 and WinNT stuff up the password
727 * lengths for non-encrypting systems. Uggh.
728
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
733
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. */
737
738 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
739 passlen2 != 1) {
740 passlen2 = 0;
741 }
742 }
743
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;
751 }
752
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;
759 }
760
761 /* Save the lanman2 password and the NT md4 password. */
762
763 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
764 doencrypt = False;
765 }
766
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;
773
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);
791 }
792 if (!pass) {
793 reply_nterror(req, nt_status_squash(
794 NT_STATUS_INVALID_PARAMETER));
795 END_PROFILE(SMBsesssetupX);
796 return;
797 }
798 plaintext_password = data_blob(pass, strlen(pass)+1);
799 }
800
801 p += passlen1 + passlen2;
802
803 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
804 STR_TERMINATE);
805 user = tmp ? tmp : "";
806
807 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
808 STR_TERMINATE);
809 domain = tmp ? tmp : "";
810
811 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
812 STR_TERMINATE);
813 native_os = tmp ? tmp : "";
814
815 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
816 STR_TERMINATE);
817 native_lanman = tmp ? tmp : "";
818
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 */
825
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");
833 }
834
835 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
836 "PrimaryDomain=[%s]\n",
837 domain, native_os, native_lanman, primary_domain));
838
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 );
844 }
845
846 }
847
848 if (SVAL(req->vwv+4, 0) == 0) {
849 setup_new_vc_session(req->sconn);
850 }
851
852 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
853 domain, user, get_remote_machine_name()));
854
855 if (*user) {
856 if (xconn->smb1.negprot.spnego) {
857
858 /* This has to be here, because this is a perfectly
859 * valid behaviour for guest logons :-( */
860
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;
868 }
869 fstrcpy(sub_user, user);
870 } else {
871 fstrcpy(sub_user, "");
872 }
873
874 sub_set_smb_name(sub_user);
875
876 reload_services(sconn, conn_snum_used, true);
877
878 if (!*user) {
879
880 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
881
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;
892 }
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);
901 }
902 } else {
903 struct auth4_context *plaintext_auth_context = NULL;
904
905 nt_status = make_auth4_context(
906 talloc_tos(), &plaintext_auth_context);
907
908 if (NT_STATUS_IS_OK(nt_status)) {
909 uint8_t chal[8];
910
911 plaintext_auth_context->get_ntlm_challenge(
912 plaintext_auth_context, chal);
913
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;
921 }
922
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);
926 }
927 TALLOC_FREE(plaintext_auth_context);
928 }
929 }
930
931 TALLOC_FREE(user_info);
932
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;
940 }
941
942 data_blob_clear_free(&plaintext_password);
943
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 */
948
949 if (get_Protocol() >= PROTOCOL_NT1) {
950 push_signature(&req->outbuf);
951 /* perhaps grab OS version here?? */
952 }
953
954 if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
955 action |= SMB_SETUP_GUEST;
956 }
957
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 */
960
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;
969 }
970
971 if (session_info->session_key.length > 0) {
972 uint8_t session_key[16];
973
974 /*
975 * Note: the SMB1 signing key is not truncated to 16 byte!
976 */
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;
987 }
988
989 /*
990 * The application key is truncated/padded to 16 bytes
991 */
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;
1008 }
1009
1010 /*
1011 * Place the application key into the session_info
1012 */
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;
1023 }
1024 }
1025
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;
1034 }
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++;
1042
1043 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1044 is_authenticated = true;
1045 session->compat->homes_snum =
1046 register_homes_share(session_info->unix_info->unix_name);
1047 }
1048
1049 if (srv_is_signing_negotiated(xconn) &&
1050 is_authenticated &&
1051 session->global->signing_key.length > 0)
1052 {
1053 /*
1054 * Try and turn on server signing on the first non-guest
1055 * sessionsetup.
1056 */
1057 srv_set_signing(xconn,
1058 session->global->signing_key,
1059 nt_resp.data ? nt_resp : lm_resp);
1060 }
1061
1062 set_current_user_info(session_info->unix_info->sanitized_username,
1063 session_info->unix_info->unix_name,
1064 session_info->info->domain_name);
1065
1066 session->status = NT_STATUS_OK;
1067 session->global->auth_session_info = talloc_move(session->global,
1068 &session_info);
1069 session->global->auth_session_info_seqnum += 1;
1070 session->global->channels[0].auth_session_info_seqnum =
1071 session->global->auth_session_info_seqnum;
1072 session->global->auth_time = now;
1073 session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1074
1075 nt_status = smbXsrv_session_update(session);
1076 if (!NT_STATUS_IS_OK(nt_status)) {
1077 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1078 (unsigned long long)session->compat->vuid,
1079 nt_errstr(nt_status)));
1080 data_blob_free(&nt_resp);
1081 data_blob_free(&lm_resp);
1082 TALLOC_FREE(session);
1083 reply_nterror(req, nt_status_squash(nt_status));
1084 END_PROFILE(SMBsesssetupX);
1085 return;
1086 }
1087
1088 if (!session_claim(session)) {
1089 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1090 (unsigned long long)session->compat->vuid));
1091 data_blob_free(&nt_resp);
1092 data_blob_free(&lm_resp);
1093 TALLOC_FREE(session);
1094 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1095 END_PROFILE(SMBsesssetupX);
1096 return;
1097 }
1098
1099 /* current_user_info is changed on new vuid */
1100 reload_services(sconn, conn_snum_used, true);
1101
1102 sess_vuid = session->global->session_wire_id;
1103
1104 data_blob_free(&nt_resp);
1105 data_blob_free(&lm_resp);
1106
1107 SSVAL(req->outbuf,smb_vwv2,action);
1108 SSVAL(req->outbuf,smb_uid,sess_vuid);
1109 SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1110 req->vuid = sess_vuid;
1111
1112 if (!xconn->smb1.sessions.done_sesssetup) {
1113 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1114 reply_force_doserror(req, ERRSRV, ERRerror);
1115 END_PROFILE(SMBsesssetupX);
1116 return;
1117 }
1118 xconn->smb1.sessions.max_send = smb_bufsize;
1119 xconn->smb1.sessions.done_sesssetup = true;
1120 }
1121
1122 END_PROFILE(SMBsesssetupX);
1123}
Note: See TracBrowser for help on using the repository browser.