/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- do_map_to_guest
- push_signature
- sessionsetup_start_signing_engine
- reply_sesssetup_blob
- check_guest_password
- make_krb5_skew_error
- reply_spnego_kerberos
- reply_spnego_ntlmssp
- parse_spnego_mechanisms
- reply_spnego_downgrade_to_ntlmssp
- reply_spnego_negotiate
- reply_spnego_auth
- delete_partial_auth
- get_pending_auth_data
- check_spnego_blob_complete
- reply_sesssetup_and_X_spnego
- shutdown_other_smbds
- setup_new_vc_session
- reply_sesssetup_and_X
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 "smbd/globals.h"
27
28 extern enum protocol_types Protocol;
29
30 /*
31 on a logon error possibly map the error to success if "map to guest"
32 is set approriately
33 */
34 static NTSTATUS do_map_to_guest(NTSTATUS status,
/* [<][>][^][v][top][bottom][index][help] */
35 auth_serversupplied_info **server_info,
36 const char *user, const char *domain)
37 {
38 if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
39 if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
40 (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
41 DEBUG(3,("No such user %s [%s] - using guest account\n",
42 user, domain));
43 status = make_server_info_guest(NULL, server_info);
44 }
45 }
46
47 if (NT_STATUS_EQUAL(status, NT_STATUS_WRONG_PASSWORD)) {
48 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
49 DEBUG(3,("Registered username %s for guest access\n",
50 user));
51 status = make_server_info_guest(NULL, server_info);
52 }
53 }
54
55 return status;
56 }
57
58 /****************************************************************************
59 Add the standard 'Samba' signature to the end of the session setup.
60 ****************************************************************************/
61
62 static int push_signature(uint8 **outbuf)
/* [<][>][^][v][top][bottom][index][help] */
63 {
64 char *lanman;
65 int result, tmp;
66
67 result = 0;
68
69 tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
70
71 if (tmp == -1) return -1;
72 result += tmp;
73
74 if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
75 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
76 SAFE_FREE(lanman);
77 }
78 else {
79 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
80 }
81
82 if (tmp == -1) return -1;
83 result += tmp;
84
85 tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
86
87 if (tmp == -1) return -1;
88 result += tmp;
89
90 return result;
91 }
92
93 /****************************************************************************
94 Start the signing engine if needed. Don't fail signing here.
95 ****************************************************************************/
96
97 static void sessionsetup_start_signing_engine(
/* [<][>][^][v][top][bottom][index][help] */
98 const auth_serversupplied_info *server_info,
99 const uint8 *inbuf)
100 {
101 if (!server_info->guest && !srv_signing_started()) {
102 /* We need to start the signing engine
103 * here but a W2K client sends the old
104 * "BSRSPYL " signature instead of the
105 * correct one. Subsequent packets will
106 * be correct.
107 */
108 srv_check_sign_mac((char *)inbuf, False);
109 }
110 }
111
112 /****************************************************************************
113 Send a security blob via a session setup reply.
114 ****************************************************************************/
115
116 static void reply_sesssetup_blob(struct smb_request *req,
/* [<][>][^][v][top][bottom][index][help] */
117 DATA_BLOB blob,
118 NTSTATUS nt_status)
119 {
120 if (!NT_STATUS_IS_OK(nt_status) &&
121 !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
122 reply_nterror(req, nt_status_squash(nt_status));
123 return;
124 }
125
126 nt_status = nt_status_squash(nt_status);
127 SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
128 SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
129 SSVAL(req->outbuf, smb_vwv3, blob.length);
130
131 if ((message_push_blob(&req->outbuf, blob) == -1)
132 || (push_signature(&req->outbuf) == -1)) {
133 reply_nterror(req, NT_STATUS_NO_MEMORY);
134 }
135 }
136
137 /****************************************************************************
138 Do a 'guest' logon, getting back the
139 ****************************************************************************/
140
141 static NTSTATUS check_guest_password(auth_serversupplied_info **server_info)
/* [<][>][^][v][top][bottom][index][help] */
142 {
143 struct auth_context *auth_context;
144 auth_usersupplied_info *user_info = NULL;
145
146 NTSTATUS nt_status;
147 unsigned char chal[8];
148
149 ZERO_STRUCT(chal);
150
151 DEBUG(3,("Got anonymous request\n"));
152
153 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_fixed(&auth_context,
154 chal))) {
155 return nt_status;
156 }
157
158 if (!make_user_info_guest(&user_info)) {
159 (auth_context->free)(&auth_context);
160 return NT_STATUS_NO_MEMORY;
161 }
162
163 nt_status = auth_context->check_ntlm_password(auth_context,
164 user_info,
165 server_info);
166 (auth_context->free)(&auth_context);
167 free_user_info(&user_info);
168 return nt_status;
169 }
170
171
172 #ifdef HAVE_KRB5
173
174 #if 0
175 /* Experiment that failed. See "only happens with a KDC" comment below. */
176 /****************************************************************************
177 Cerate a clock skew error blob for a Windows client.
178 ****************************************************************************/
179
180 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
/* [<][>][^][v][top][bottom][index][help] */
181 {
182 krb5_context context = NULL;
183 krb5_error_code kerr = 0;
184 krb5_data reply;
185 krb5_principal host_princ = NULL;
186 char *host_princ_s = NULL;
187 bool ret = False;
188
189 *pblob_out = data_blob_null;
190
191 initialize_krb5_error_table();
192 kerr = krb5_init_context(&context);
193 if (kerr) {
194 return False;
195 }
196 /* Create server principal. */
197 asprintf(&host_princ_s, "%s$@%s", global_myname(), lp_realm());
198 if (!host_princ_s) {
199 goto out;
200 }
201 strlower_m(host_princ_s);
202
203 kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
204 if (kerr) {
205 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
206 "for name %s: Error %s\n",
207 host_princ_s, error_message(kerr) ));
208 goto out;
209 }
210
211 kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
212 host_princ, &reply);
213 if (kerr) {
214 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
215 "failed: Error %s\n",
216 error_message(kerr) ));
217 goto out;
218 }
219
220 *pblob_out = data_blob(reply.data, reply.length);
221 kerberos_free_data_contents(context,&reply);
222 ret = True;
223
224 out:
225
226 if (host_princ_s) {
227 SAFE_FREE(host_princ_s);
228 }
229 if (host_princ) {
230 krb5_free_principal(context, host_princ);
231 }
232 krb5_free_context(context);
233 return ret;
234 }
235 #endif
236
237 /****************************************************************************
238 Reply to a session setup spnego negotiate packet for kerberos.
239 ****************************************************************************/
240
241 static void reply_spnego_kerberos(struct smb_request *req,
/* [<][>][^][v][top][bottom][index][help] */
242 DATA_BLOB *secblob,
243 const char *mechOID,
244 uint16 vuid,
245 bool *p_invalidate_vuid)
246 {
247 TALLOC_CTX *mem_ctx;
248 DATA_BLOB ticket;
249 char *client, *p, *domain;
250 fstring netbios_domain_name;
251 struct passwd *pw;
252 fstring user;
253 int sess_vuid = req->vuid;
254 NTSTATUS ret = NT_STATUS_OK;
255 struct PAC_DATA *pac_data = NULL;
256 DATA_BLOB ap_rep, ap_rep_wrapped, response;
257 auth_serversupplied_info *server_info = NULL;
258 DATA_BLOB session_key = data_blob_null;
259 uint8 tok_id[2];
260 DATA_BLOB nullblob = data_blob_null;
261 fstring real_username;
262 bool map_domainuser_to_guest = False;
263 bool username_was_mapped;
264 struct PAC_LOGON_INFO *logon_info = NULL;
265
266 ZERO_STRUCT(ticket);
267 ZERO_STRUCT(ap_rep);
268 ZERO_STRUCT(ap_rep_wrapped);
269 ZERO_STRUCT(response);
270
271 /* Normally we will always invalidate the intermediate vuid. */
272 *p_invalidate_vuid = True;
273
274 mem_ctx = talloc_init("reply_spnego_kerberos");
275 if (mem_ctx == NULL) {
276 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
277 return;
278 }
279
280 if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
281 talloc_destroy(mem_ctx);
282 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
283 return;
284 }
285
286 ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
287 &client, &pac_data, &ap_rep,
288 &session_key, True);
289
290 data_blob_free(&ticket);
291
292 if (!NT_STATUS_IS_OK(ret)) {
293 #if 0
294 /* Experiment that failed.
295 * See "only happens with a KDC" comment below. */
296
297 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
298
299 /*
300 * Windows in this case returns
301 * NT_STATUS_MORE_PROCESSING_REQUIRED
302 * with a negTokenTarg blob containing an krb5_error
303 * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
304 * The client then fixes its clock and continues rather
305 * than giving an error. JRA.
306 * -- Looks like this only happens with a KDC. JRA.
307 */
308
309 bool ok = make_krb5_skew_error(&ap_rep);
310 if (!ok) {
311 talloc_destroy(mem_ctx);
312 return ERROR_NT(nt_status_squash(
313 NT_STATUS_LOGON_FAILURE));
314 }
315 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
316 TOK_ID_KRB_ERROR);
317 response = spnego_gen_auth_response(&ap_rep_wrapped,
318 ret, OID_KERBEROS5_OLD);
319 reply_sesssetup_blob(conn, inbuf, outbuf, response,
320 NT_STATUS_MORE_PROCESSING_REQUIRED);
321
322 /*
323 * In this one case we don't invalidate the
324 * intermediate vuid as we're expecting the client
325 * to re-use it for the next sessionsetupX packet. JRA.
326 */
327
328 *p_invalidate_vuid = False;
329
330 data_blob_free(&ap_rep);
331 data_blob_free(&ap_rep_wrapped);
332 data_blob_free(&response);
333 talloc_destroy(mem_ctx);
334 return -1; /* already replied */
335 }
336 #else
337 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
338 ret = NT_STATUS_LOGON_FAILURE;
339 }
340 #endif
341 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
342 nt_errstr(ret)));
343 talloc_destroy(mem_ctx);
344 reply_nterror(req, nt_status_squash(ret));
345 return;
346 }
347
348 DEBUG(3,("Ticket name is [%s]\n", client));
349
350 p = strchr_m(client, '@');
351 if (!p) {
352 DEBUG(3,("Doesn't look like a valid principal\n"));
353 data_blob_free(&ap_rep);
354 data_blob_free(&session_key);
355 talloc_destroy(mem_ctx);
356 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
357 return;
358 }
359
360 *p = 0;
361
362 /* save the PAC data if we have it */
363
364 if (pac_data) {
365 logon_info = get_logon_info_from_pac(pac_data);
366 if (logon_info) {
367 netsamlogon_cache_store( client, &logon_info->info3 );
368 }
369 }
370
371 if (!strequal(p+1, lp_realm())) {
372 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
373 if (!lp_allow_trusted_domains()) {
374 data_blob_free(&ap_rep);
375 data_blob_free(&session_key);
376 talloc_destroy(mem_ctx);
377 reply_nterror(req, nt_status_squash(
378 NT_STATUS_LOGON_FAILURE));
379 return;
380 }
381 }
382
383 /* this gives a fully qualified user name (ie. with full realm).
384 that leads to very long usernames, but what else can we do? */
385
386 domain = p+1;
387
388 if (logon_info && logon_info->info3.base.domain.string) {
389 fstrcpy(netbios_domain_name,
390 logon_info->info3.base.domain.string);
391 domain = netbios_domain_name;
392 DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain));
393
394 } else {
395
396 /* If we have winbind running, we can (and must) shorten the
397 username by using the short netbios name. Otherwise we will
398 have inconsistent user names. With Kerberos, we get the
399 fully qualified realm, with ntlmssp we get the short
400 name. And even w2k3 does use ntlmssp if you for example
401 connect to an ip address. */
402
403 wbcErr wbc_status;
404 struct wbcDomainInfo *info = NULL;
405
406 DEBUG(10, ("Mapping [%s] to short name\n", domain));
407
408 wbc_status = wbcDomainInfo(domain, &info);
409
410 if (WBC_ERROR_IS_OK(wbc_status)) {
411
412 fstrcpy(netbios_domain_name,
413 info->short_name);
414
415 wbcFreeMemory(info);
416 domain = netbios_domain_name;
417 DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain));
418 } else {
419 DEBUG(3, ("Could not find short name: %s\n",
420 wbcErrorString(wbc_status)));
421 }
422 }
423
424 fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
425
426 /* lookup the passwd struct, create a new user if necessary */
427
428 username_was_mapped = map_username( user );
429
430 pw = smb_getpwnam( mem_ctx, user, real_username, True );
431
432 if (pw) {
433 /* if a real user check pam account restrictions */
434 /* only really perfomed if "obey pam restriction" is true */
435 /* do this before an eventual mapping to guest occurs */
436 ret = smb_pam_accountcheck(pw->pw_name);
437 if ( !NT_STATUS_IS_OK(ret)) {
438 DEBUG(1,("PAM account restriction "
439 "prevents user login\n"));
440 data_blob_free(&ap_rep);
441 data_blob_free(&session_key);
442 TALLOC_FREE(mem_ctx);
443 reply_nterror(req, nt_status_squash(ret));
444 return;
445 }
446 }
447
448 if (!pw) {
449
450 /* this was originally the behavior of Samba 2.2, if a user
451 did not have a local uid but has been authenticated, then
452 map them to a guest account */
453
454 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
455 map_domainuser_to_guest = True;
456 fstrcpy(user,lp_guestaccount());
457 pw = smb_getpwnam( mem_ctx, user, real_username, True );
458 }
459
460 /* extra sanity check that the guest account is valid */
461
462 if ( !pw ) {
463 DEBUG(1,("Username %s is invalid on this system\n",
464 user));
465 data_blob_free(&ap_rep);
466 data_blob_free(&session_key);
467 TALLOC_FREE(mem_ctx);
468 reply_nterror(req, nt_status_squash(
469 NT_STATUS_LOGON_FAILURE));
470 return;
471 }
472 }
473
474 /* setup the string used by %U */
475
476 sub_set_smb_name( real_username );
477 reload_services(True);
478
479 if ( map_domainuser_to_guest ) {
480 make_server_info_guest(NULL, &server_info);
481 } else if (logon_info) {
482 /* pass the unmapped username here since map_username()
483 will be called again from inside make_server_info_info3() */
484
485 ret = make_server_info_info3(mem_ctx, client, domain,
486 &server_info, &logon_info->info3);
487 if ( !NT_STATUS_IS_OK(ret) ) {
488 DEBUG(1,("make_server_info_info3 failed: %s!\n",
489 nt_errstr(ret)));
490 data_blob_free(&ap_rep);
491 data_blob_free(&session_key);
492 TALLOC_FREE(mem_ctx);
493 reply_nterror(req, nt_status_squash(ret));
494 return;
495 }
496
497 } else {
498 ret = make_server_info_pw(&server_info, real_username, pw);
499
500 if ( !NT_STATUS_IS_OK(ret) ) {
501 DEBUG(1,("make_server_info_pw failed: %s!\n",
502 nt_errstr(ret)));
503 data_blob_free(&ap_rep);
504 data_blob_free(&session_key);
505 TALLOC_FREE(mem_ctx);
506 reply_nterror(req, nt_status_squash(ret));
507 return;
508 }
509
510 /* make_server_info_pw does not set the domain. Without this
511 * we end up with the local netbios name in substitutions for
512 * %D. */
513
514 if (server_info->sam_account != NULL) {
515 pdb_set_domain(server_info->sam_account,
516 domain, PDB_SET);
517 }
518 }
519
520 server_info->nss_token |= username_was_mapped;
521
522 /* we need to build the token for the user. make_server_info_guest()
523 already does this */
524
525 if ( !server_info->ptok ) {
526 ret = create_local_token( server_info );
527 if ( !NT_STATUS_IS_OK(ret) ) {
528 DEBUG(10,("failed to create local token: %s\n",
529 nt_errstr(ret)));
530 data_blob_free(&ap_rep);
531 data_blob_free(&session_key);
532 TALLOC_FREE( mem_ctx );
533 TALLOC_FREE( server_info );
534 reply_nterror(req, nt_status_squash(ret));
535 return;
536 }
537 }
538
539 if (!is_partial_auth_vuid(sess_vuid)) {
540 sess_vuid = register_initial_vuid();
541 }
542
543 data_blob_free(&server_info->user_session_key);
544 server_info->user_session_key = session_key;
545 session_key = data_blob_null;
546
547 /* register_existing_vuid keeps the server info */
548 /* register_existing_vuid takes ownership of session_key on success,
549 * no need to free after this on success. A better interface would copy
550 * it.... */
551
552 sess_vuid = register_existing_vuid(sess_vuid,
553 server_info,
554 nullblob,
555 client);
556
557 reply_outbuf(req, 4, 0);
558 SSVAL(req->outbuf,smb_uid,sess_vuid);
559
560 if (sess_vuid == UID_FIELD_INVALID ) {
561 ret = NT_STATUS_LOGON_FAILURE;
562 } else {
563 /* current_user_info is changed on new vuid */
564 reload_services( True );
565
566 SSVAL(req->outbuf, smb_vwv3, 0);
567
568 if (server_info->guest) {
569 SSVAL(req->outbuf,smb_vwv2,1);
570 }
571
572 SSVAL(req->outbuf, smb_uid, sess_vuid);
573
574 sessionsetup_start_signing_engine(server_info, req->inbuf);
575 /* Successful logon. Keep this vuid. */
576 *p_invalidate_vuid = False;
577 }
578
579 /* wrap that up in a nice GSS-API wrapping */
580 if (NT_STATUS_IS_OK(ret)) {
581 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
582 TOK_ID_KRB_AP_REP);
583 } else {
584 ap_rep_wrapped = data_blob_null;
585 }
586 response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
587 mechOID);
588 reply_sesssetup_blob(req, response, ret);
589
590 data_blob_free(&ap_rep);
591 data_blob_free(&ap_rep_wrapped);
592 data_blob_free(&response);
593 TALLOC_FREE(mem_ctx);
594 }
595
596 #endif
597
598 /****************************************************************************
599 Send a session setup reply, wrapped in SPNEGO.
600 Get vuid and check first.
601 End the NTLMSSP exchange context if we are OK/complete fail
602 This should be split into two functions, one to handle each
603 leg of the NTLM auth steps.
604 ***************************************************************************/
605
606 static void reply_spnego_ntlmssp(struct smb_request *req,
/* [<][>][^][v][top][bottom][index][help] */
607 uint16 vuid,
608 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
609 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
610 const char *OID,
611 bool wrap)
612 {
613 DATA_BLOB response;
614 struct auth_serversupplied_info *server_info = NULL;
615
616 if (NT_STATUS_IS_OK(nt_status)) {
617 server_info = (*auth_ntlmssp_state)->server_info;
618 } else {
619 nt_status = do_map_to_guest(nt_status,
620 &server_info,
621 (*auth_ntlmssp_state)->ntlmssp_state->user,
622 (*auth_ntlmssp_state)->ntlmssp_state->domain);
623 }
624
625 reply_outbuf(req, 4, 0);
626
627 SSVAL(req->outbuf, smb_uid, vuid);
628
629 if (NT_STATUS_IS_OK(nt_status)) {
630 DATA_BLOB nullblob = data_blob_null;
631
632 if (!is_partial_auth_vuid(vuid)) {
633 nt_status = NT_STATUS_LOGON_FAILURE;
634 goto out;
635 }
636
637 data_blob_free(&server_info->user_session_key);
638 server_info->user_session_key =
639 data_blob_talloc(
640 server_info,
641 (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
642 (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
643
644 /* register_existing_vuid keeps the server info */
645 if (register_existing_vuid(vuid,
646 server_info, nullblob,
647 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
648 vuid) {
649 nt_status = NT_STATUS_LOGON_FAILURE;
650 goto out;
651 }
652
653 (*auth_ntlmssp_state)->server_info = NULL;
654
655 /* current_user_info is changed on new vuid */
656 reload_services( True );
657
658 SSVAL(req->outbuf, smb_vwv3, 0);
659
660 if (server_info->guest) {
661 SSVAL(req->outbuf,smb_vwv2,1);
662 }
663
664 sessionsetup_start_signing_engine(server_info,
665 (uint8 *)req->inbuf);
666 }
667
668 out:
669
670 if (wrap) {
671 response = spnego_gen_auth_response(ntlmssp_blob,
672 nt_status, OID);
673 } else {
674 response = *ntlmssp_blob;
675 }
676
677 reply_sesssetup_blob(req, response, nt_status);
678 if (wrap) {
679 data_blob_free(&response);
680 }
681
682 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
683 and the other end, that we are not finished yet. */
684
685 if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
686 /* NB. This is *NOT* an error case. JRA */
687 auth_ntlmssp_end(auth_ntlmssp_state);
688 if (!NT_STATUS_IS_OK(nt_status)) {
689 /* Kill the intermediate vuid */
690 invalidate_vuid(vuid);
691 }
692 }
693 }
694
695 /****************************************************************************
696 Is this a krb5 mechanism ?
697 ****************************************************************************/
698
699 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
/* [<][>][^][v][top][bottom][index][help] */
700 DATA_BLOB *pblob_out,
701 char **kerb_mechOID)
702 {
703 char *OIDs[ASN1_MAX_OIDS];
704 int i;
705 NTSTATUS ret = NT_STATUS_OK;
706
707 *kerb_mechOID = NULL;
708
709 /* parse out the OIDs and the first sec blob */
710 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
711 return NT_STATUS_LOGON_FAILURE;
712 }
713
714 /* only look at the first OID for determining the mechToken --
715 according to RFC2478, we should choose the one we want
716 and renegotiate, but i smell a client bug here..
717
718 Problem observed when connecting to a member (samba box)
719 of an AD domain as a user in a Samba domain. Samba member
720 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
721 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
722 NTLMSSP mechtoken. --jerry */
723
724 #ifdef HAVE_KRB5
725 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
726 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
727 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
728 if (*kerb_mechOID == NULL) {
729 ret = NT_STATUS_NO_MEMORY;
730 }
731 }
732 #endif
733
734 for (i=0;OIDs[i];i++) {
735 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
736 talloc_free(OIDs[i]);
737 }
738 return ret;
739 }
740
741 /****************************************************************************
742 Fall back from krb5 to NTLMSSP.
743 ****************************************************************************/
744
745 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
/* [<][>][^][v][top][bottom][index][help] */
746 uint16 vuid)
747 {
748 DATA_BLOB response;
749
750 reply_outbuf(req, 4, 0);
751 SSVAL(req->outbuf,smb_uid,vuid);
752
753 DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
754 "but set to downgrade to NTLMSSP\n"));
755
756 response = spnego_gen_auth_response(NULL,
757 NT_STATUS_MORE_PROCESSING_REQUIRED,
758 OID_NTLMSSP);
759 reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
760 data_blob_free(&response);
761 }
762
763 /****************************************************************************
764 Reply to a session setup spnego negotiate packet.
765 ****************************************************************************/
766
767 static void reply_spnego_negotiate(struct smb_request *req,
/* [<][>][^][v][top][bottom][index][help] */
768 uint16 vuid,
769 DATA_BLOB blob1,
770 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
771 {
772 DATA_BLOB secblob;
773 DATA_BLOB chal;
774 char *kerb_mech = NULL;
775 NTSTATUS status;
776
777 status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
778 if (!NT_STATUS_IS_OK(status)) {
779 /* Kill the intermediate vuid */
780 invalidate_vuid(vuid);
781 reply_nterror(req, nt_status_squash(status));
782 return;
783 }
784
785 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
786 (unsigned long)secblob.length));
787
788 #ifdef HAVE_KRB5
789 if (kerb_mech && ((lp_security()==SEC_ADS) ||
790 USE_KERBEROS_KEYTAB) ) {
791 bool destroy_vuid = True;
792 reply_spnego_kerberos(req, &secblob, kerb_mech,
793 vuid, &destroy_vuid);
794 data_blob_free(&secblob);
795 if (destroy_vuid) {
796 /* Kill the intermediate vuid */
797 invalidate_vuid(vuid);
798 }
799 SAFE_FREE(kerb_mech);
800 return;
801 }
802 #endif
803
804 if (*auth_ntlmssp_state) {
805 auth_ntlmssp_end(auth_ntlmssp_state);
806 }
807
808 if (kerb_mech) {
809 data_blob_free(&secblob);
810 /* The mechtoken is a krb5 ticket, but
811 * we need to fall back to NTLM. */
812 reply_spnego_downgrade_to_ntlmssp(req, vuid);
813 SAFE_FREE(kerb_mech);
814 return;
815 }
816
817 status = auth_ntlmssp_start(auth_ntlmssp_state);
818 if (!NT_STATUS_IS_OK(status)) {
819 /* Kill the intermediate vuid */
820 invalidate_vuid(vuid);
821 reply_nterror(req, nt_status_squash(status));
822 return;
823 }
824
825 status = auth_ntlmssp_update(*auth_ntlmssp_state,
826 secblob, &chal);
827
828 data_blob_free(&secblob);
829
830 reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
831 &chal, status, OID_NTLMSSP, true);
832
833 data_blob_free(&chal);
834
835 /* already replied */
836 return;
837 }
838
839 /****************************************************************************
840 Reply to a session setup spnego auth packet.
841 ****************************************************************************/
842
843 static void reply_spnego_auth(struct smb_request *req,
/* [<][>][^][v][top][bottom][index][help] */
844 uint16 vuid,
845 DATA_BLOB blob1,
846 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
847 {
848 DATA_BLOB auth = data_blob_null;
849 DATA_BLOB auth_reply = data_blob_null;
850 DATA_BLOB secblob = data_blob_null;
851 NTSTATUS status = NT_STATUS_LOGON_FAILURE;
852
853 if (!spnego_parse_auth(blob1, &auth)) {
854 #if 0
855 file_save("auth.dat", blob1.data, blob1.length);
856 #endif
857 /* Kill the intermediate vuid */
858 invalidate_vuid(vuid);
859
860 reply_nterror(req, nt_status_squash(
861 NT_STATUS_LOGON_FAILURE));
862 return;
863 }
864
865 if (auth.data[0] == ASN1_APPLICATION(0)) {
866 /* Might be a second negTokenTarg packet */
867 char *kerb_mech = NULL;
868
869 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
870
871 if (!NT_STATUS_IS_OK(status)) {
872 /* Kill the intermediate vuid */
873 invalidate_vuid(vuid);
874 reply_nterror(req, nt_status_squash(status));
875 return;
876 }
877
878 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
879 (unsigned long)secblob.length));
880 #ifdef HAVE_KRB5
881 if (kerb_mech && ((lp_security()==SEC_ADS) ||
882 USE_KERBEROS_KEYTAB)) {
883 bool destroy_vuid = True;
884 reply_spnego_kerberos(req, &secblob, kerb_mech,
885 vuid, &destroy_vuid);
886 data_blob_free(&secblob);
887 data_blob_free(&auth);
888 if (destroy_vuid) {
889 /* Kill the intermediate vuid */
890 invalidate_vuid(vuid);
891 }
892 SAFE_FREE(kerb_mech);
893 return;
894 }
895 #endif
896 /* Can't blunder into NTLMSSP auth if we have
897 * a krb5 ticket. */
898
899 if (kerb_mech) {
900 /* Kill the intermediate vuid */
901 invalidate_vuid(vuid);
902 DEBUG(3,("reply_spnego_auth: network "
903 "misconfiguration, client sent us a "
904 "krb5 ticket and kerberos security "
905 "not enabled\n"));
906 reply_nterror(req, nt_status_squash(
907 NT_STATUS_LOGON_FAILURE));
908 SAFE_FREE(kerb_mech);
909 }
910 }
911
912 /* If we get here it wasn't a negTokenTarg auth packet. */
913 data_blob_free(&secblob);
914
915 if (!*auth_ntlmssp_state) {
916 status = auth_ntlmssp_start(auth_ntlmssp_state);
917 if (!NT_STATUS_IS_OK(status)) {
918 /* Kill the intermediate vuid */
919 invalidate_vuid(vuid);
920 reply_nterror(req, nt_status_squash(status));
921 return;
922 }
923 }
924
925 status = auth_ntlmssp_update(*auth_ntlmssp_state,
926 auth, &auth_reply);
927
928 data_blob_free(&auth);
929
930 /* Don't send the mechid as we've already sent this (RFC4178). */
931
932 reply_spnego_ntlmssp(req, vuid,
933 auth_ntlmssp_state,
934 &auth_reply, status, NULL, true);
935
936 data_blob_free(&auth_reply);
937
938 /* and tell smbd that we have already replied to this packet */
939 return;
940 }
941
942 /****************************************************************************
943 Delete an entry on the list.
944 ****************************************************************************/
945
946 static void delete_partial_auth(struct pending_auth_data *pad)
/* [<][>][^][v][top][bottom][index][help] */
947 {
948 if (!pad) {
949 return;
950 }
951 DLIST_REMOVE(pd_list, pad);
952 data_blob_free(&pad->partial_data);
953 SAFE_FREE(pad);
954 }
955
956 /****************************************************************************
957 Search for a partial SPNEGO auth fragment matching an smbpid.
958 ****************************************************************************/
959
960 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
/* [<][>][^][v][top][bottom][index][help] */
961 {
962 struct pending_auth_data *pad;
963
964 for (pad = pd_list; pad; pad = pad->next) {
965 if (pad->smbpid == smbpid) {
966 break;
967 }
968 }
969 return pad;
970 }
971
972 /****************************************************************************
973 Check the size of an SPNEGO blob. If we need more return
974 NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
975 the blob to be more than 64k.
976 ****************************************************************************/
977
978 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
/* [<][>][^][v][top][bottom][index][help] */
979 DATA_BLOB *pblob)
980 {
981 struct pending_auth_data *pad = NULL;
982 ASN1_DATA *data;
983 size_t needed_len = 0;
984
985 pad = get_pending_auth_data(smbpid);
986
987 /* Ensure we have some data. */
988 if (pblob->length == 0) {
989 /* Caller can cope. */
990 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
991 delete_partial_auth(pad);
992 return NT_STATUS_OK;
993 }
994
995 /* Were we waiting for more data ? */
996 if (pad) {
997 DATA_BLOB tmp_blob;
998 size_t copy_len = MIN(65536, pblob->length);
999
1000 /* Integer wrap paranoia.... */
1001
1002 if (pad->partial_data.length + copy_len <
1003 pad->partial_data.length ||
1004 pad->partial_data.length + copy_len < copy_len) {
1005
1006 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1007 "pad->partial_data.length = %u, "
1008 "copy_len = %u\n",
1009 (unsigned int)pad->partial_data.length,
1010 (unsigned int)copy_len ));
1011
1012 delete_partial_auth(pad);
1013 return NT_STATUS_INVALID_PARAMETER;
1014 }
1015
1016 DEBUG(10,("check_spnego_blob_complete: "
1017 "pad->partial_data.length = %u, "
1018 "pad->needed_len = %u, "
1019 "copy_len = %u, "
1020 "pblob->length = %u,\n",
1021 (unsigned int)pad->partial_data.length,
1022 (unsigned int)pad->needed_len,
1023 (unsigned int)copy_len,
1024 (unsigned int)pblob->length ));
1025
1026 tmp_blob = data_blob(NULL,
1027 pad->partial_data.length + copy_len);
1028
1029 /* Concatenate the two (up to copy_len) bytes. */
1030 memcpy(tmp_blob.data,
1031 pad->partial_data.data,
1032 pad->partial_data.length);
1033 memcpy(tmp_blob.data + pad->partial_data.length,
1034 pblob->data,
1035 copy_len);
1036
1037 /* Replace the partial data. */
1038 data_blob_free(&pad->partial_data);
1039 pad->partial_data = tmp_blob;
1040 ZERO_STRUCT(tmp_blob);
1041
1042 /* Are we done ? */
1043 if (pblob->length >= pad->needed_len) {
1044 /* Yes, replace pblob. */
1045 data_blob_free(pblob);
1046 *pblob = pad->partial_data;
1047 ZERO_STRUCT(pad->partial_data);
1048 delete_partial_auth(pad);
1049 return NT_STATUS_OK;
1050 }
1051
1052 /* Still need more data. */
1053 pad->needed_len -= copy_len;
1054 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1055 }
1056
1057 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1058 (pblob->data[0] != ASN1_CONTEXT(1))) {
1059 /* Not something we can determine the
1060 * length of.
1061 */
1062 return NT_STATUS_OK;
1063 }
1064
1065 /* This is a new SPNEGO sessionsetup - see if
1066 * the data given in this blob is enough.
1067 */
1068
1069 data = asn1_init(NULL);
1070 if (data == NULL) {
1071 return NT_STATUS_NO_MEMORY;
1072 }
1073
1074 asn1_load(data, *pblob);
1075 asn1_start_tag(data, pblob->data[0]);
1076 if (data->has_error || data->nesting == NULL) {
1077 asn1_free(data);
1078 /* Let caller catch. */
1079 return NT_STATUS_OK;
1080 }
1081
1082 /* Integer wrap paranoia.... */
1083
1084 if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
1085 data->nesting->taglen + data->nesting->start < data->nesting->start) {
1086
1087 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1088 "data.nesting->taglen = %u, "
1089 "data.nesting->start = %u\n",
1090 (unsigned int)data->nesting->taglen,
1091 (unsigned int)data->nesting->start ));
1092
1093 asn1_free(data);
1094 return NT_STATUS_INVALID_PARAMETER;
1095 }
1096
1097 /* Total length of the needed asn1 is the tag length
1098 * plus the current offset. */
1099
1100 needed_len = data->nesting->taglen + data->nesting->start;
1101 asn1_free(data);
1102
1103 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1104 "pblob->length = %u\n",
1105 (unsigned int)needed_len,
1106 (unsigned int)pblob->length ));
1107
1108 if (needed_len <= pblob->length) {
1109 /* Nothing to do - blob is complete. */
1110 return NT_STATUS_OK;
1111 }
1112
1113 /* Refuse the blob if it's bigger than 64k. */
1114 if (needed_len > 65536) {
1115 DEBUG(2,("check_spnego_blob_complete: needed_len "
1116 "too large (%u)\n",
1117 (unsigned int)needed_len ));
1118 return NT_STATUS_INVALID_PARAMETER;
1119 }
1120
1121 /* We must store this blob until complete. */
1122 if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1123 return NT_STATUS_NO_MEMORY;
1124 }
1125 pad->needed_len = needed_len - pblob->length;
1126 pad->partial_data = data_blob(pblob->data, pblob->length);
1127 if (pad->partial_data.data == NULL) {
1128 SAFE_FREE(pad);
1129 return NT_STATUS_NO_MEMORY;
1130 }
1131 pad->smbpid = smbpid;
1132 pad->vuid = vuid;
1133 DLIST_ADD(pd_list, pad);
1134
1135 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1136 }
1137
1138 /****************************************************************************
1139 Reply to a session setup command.
1140 conn POINTER CAN BE NULL HERE !
1141 ****************************************************************************/
1142
1143 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1144 {
1145 const uint8 *p;
1146 DATA_BLOB blob1;
1147 size_t bufrem;
1148 char *tmp;
1149 const char *native_os;
1150 const char *native_lanman;
1151 const char *primary_domain;
1152 const char *p2;
1153 uint16 data_blob_len = SVAL(req->vwv+7, 0);
1154 enum remote_arch_types ra_type = get_remote_arch();
1155 int vuid = req->vuid;
1156 user_struct *vuser = NULL;
1157 NTSTATUS status = NT_STATUS_OK;
1158 uint16 smbpid = req->smbpid;
1159
1160 DEBUG(3,("Doing spnego session setup\n"));
1161
1162 if (global_client_caps == 0) {
1163 global_client_caps = IVAL(req->vwv+10, 0);
1164
1165 if (!(global_client_caps & CAP_STATUS32)) {
1166 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1167 }
1168
1169 }
1170
1171 p = req->buf;
1172
1173 if (data_blob_len == 0) {
1174 /* an invalid request */
1175 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1176 return;
1177 }
1178
1179 bufrem = smbreq_bufrem(req, p);
1180 /* pull the spnego blob */
1181 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1182
1183 #if 0
1184 file_save("negotiate.dat", blob1.data, blob1.length);
1185 #endif
1186
1187 p2 = (char *)req->buf + data_blob_len;
1188
1189 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1190 STR_TERMINATE);
1191 native_os = tmp ? tmp : "";
1192
1193 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1194 STR_TERMINATE);
1195 native_lanman = tmp ? tmp : "";
1196
1197 p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1198 STR_TERMINATE);
1199 primary_domain = tmp ? tmp : "";
1200
1201 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1202 native_os, native_lanman, primary_domain));
1203
1204 if ( ra_type == RA_WIN2K ) {
1205 /* Vista sets neither the OS or lanman strings */
1206
1207 if ( !strlen(native_os) && !strlen(native_lanman) )
1208 set_remote_arch(RA_VISTA);
1209
1210 /* Windows 2003 doesn't set the native lanman string,
1211 but does set primary domain which is a bug I think */
1212
1213 if ( !strlen(native_lanman) ) {
1214 ra_lanman_string( primary_domain );
1215 } else {
1216 ra_lanman_string( native_lanman );
1217 }
1218 }
1219
1220 /* Did we get a valid vuid ? */
1221 if (!is_partial_auth_vuid(vuid)) {
1222 /* No, then try and see if this is an intermediate sessionsetup
1223 * for a large SPNEGO packet. */
1224 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1225 if (pad) {
1226 DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1227 "pending vuid %u\n",
1228 (unsigned int)pad->vuid ));
1229 vuid = pad->vuid;
1230 }
1231 }
1232
1233 /* Do we have a valid vuid now ? */
1234 if (!is_partial_auth_vuid(vuid)) {
1235 /* No, start a new authentication setup. */
1236 vuid = register_initial_vuid();
1237 if (vuid == UID_FIELD_INVALID) {
1238 data_blob_free(&blob1);
1239 reply_nterror(req, nt_status_squash(
1240 NT_STATUS_INVALID_PARAMETER));
1241 return;
1242 }
1243 }
1244
1245 vuser = get_partial_auth_user_struct(vuid);
1246 /* This MUST be valid. */
1247 if (!vuser) {
1248 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1249 }
1250
1251 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1252 * sessionsetup requests as the Windows limit on the security blob
1253 * field is 4k. Bug #4400. JRA.
1254 */
1255
1256 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1257 if (!NT_STATUS_IS_OK(status)) {
1258 if (!NT_STATUS_EQUAL(status,
1259 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1260 /* Real error - kill the intermediate vuid */
1261 invalidate_vuid(vuid);
1262 }
1263 data_blob_free(&blob1);
1264 reply_nterror(req, nt_status_squash(status));
1265 return;
1266 }
1267
1268 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1269
1270 /* its a negTokenTarg packet */
1271
1272 reply_spnego_negotiate(req, vuid, blob1,
1273 &vuser->auth_ntlmssp_state);
1274 data_blob_free(&blob1);
1275 return;
1276 }
1277
1278 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1279
1280 /* its a auth packet */
1281
1282 reply_spnego_auth(req, vuid, blob1,
1283 &vuser->auth_ntlmssp_state);
1284 data_blob_free(&blob1);
1285 return;
1286 }
1287
1288 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1289 DATA_BLOB chal;
1290
1291 if (!vuser->auth_ntlmssp_state) {
1292 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1293 if (!NT_STATUS_IS_OK(status)) {
1294 /* Kill the intermediate vuid */
1295 invalidate_vuid(vuid);
1296 data_blob_free(&blob1);
1297 reply_nterror(req, nt_status_squash(status));
1298 return;
1299 }
1300 }
1301
1302 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1303 blob1, &chal);
1304
1305 data_blob_free(&blob1);
1306
1307 reply_spnego_ntlmssp(req, vuid,
1308 &vuser->auth_ntlmssp_state,
1309 &chal, status, OID_NTLMSSP, false);
1310 data_blob_free(&chal);
1311 return;
1312 }
1313
1314 /* what sort of packet is this? */
1315 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1316
1317 data_blob_free(&blob1);
1318
1319 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1320 }
1321
1322 /****************************************************************************
1323 On new VC == 0, shutdown *all* old connections and users.
1324 It seems that only NT4.x does this. At W2K and above (XP etc.).
1325 a new session setup with VC==0 is ignored.
1326 ****************************************************************************/
1327
1328 static int shutdown_other_smbds(struct db_record *rec,
/* [<][>][^][v][top][bottom][index][help] */
1329 const struct connections_key *key,
1330 const struct connections_data *crec,
1331 void *private_data)
1332 {
1333 const char *ip = (const char *)private_data;
1334
1335 if (!process_exists(crec->pid)) {
1336 return 0;
1337 }
1338
1339 if (procid_is_me(&crec->pid)) {
1340 return 0;
1341 }
1342
1343 if (strcmp(ip, crec->addr) != 0) {
1344 return 0;
1345 }
1346
1347 DEBUG(0,("shutdown_other_smbds: shutting down pid %u "
1348 "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid), ip));
1349
1350 messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1351 &data_blob_null);
1352 return 0;
1353 }
1354
1355 static void setup_new_vc_session(void)
/* [<][>][^][v][top][bottom][index][help] */
1356 {
1357 char addr[INET6_ADDRSTRLEN];
1358
1359 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1360 "compatible we would close all old resources.\n"));
1361 #if 0
1362 conn_close_all();
1363 invalidate_all_vuids();
1364 #endif
1365 if (lp_reset_on_zero_vc()) {
1366 connections_forall(shutdown_other_smbds,
1367 CONST_DISCARD(void *,
1368 client_addr(get_client_fd(),addr,sizeof(addr))));
1369 }
1370 }
1371
1372 /****************************************************************************
1373 Reply to a session setup command.
1374 ****************************************************************************/
1375
1376 void reply_sesssetup_and_X(struct smb_request *req)
/* [<][>][^][v][top][bottom][index][help] */
1377 {
1378 int sess_vuid;
1379 int smb_bufsize;
1380 DATA_BLOB lm_resp;
1381 DATA_BLOB nt_resp;
1382 DATA_BLOB plaintext_password;
1383 char *tmp;
1384 const char *user;
1385 fstring sub_user; /* Sainitised username for substituion */
1386 const char *domain;
1387 const char *native_os;
1388 const char *native_lanman;
1389 const char *primary_domain;
1390 auth_usersupplied_info *user_info = NULL;
1391 auth_serversupplied_info *server_info = NULL;
1392 uint16 smb_flag2 = req->flags2;
1393
1394 NTSTATUS nt_status;
1395
1396 bool doencrypt = global_encrypted_passwords_negotiated;
1397
1398 START_PROFILE(SMBsesssetupX);
1399
1400 ZERO_STRUCT(lm_resp);
1401 ZERO_STRUCT(nt_resp);
1402 ZERO_STRUCT(plaintext_password);
1403
1404 DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1405
1406 /* a SPNEGO session setup has 12 command words, whereas a normal
1407 NT1 session setup has 13. See the cifs spec. */
1408 if (req->wct == 12 &&
1409 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1410
1411 if (!global_spnego_negotiated) {
1412 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1413 "at SPNEGO session setup when it was not "
1414 "negotiated.\n"));
1415 reply_nterror(req, nt_status_squash(
1416 NT_STATUS_LOGON_FAILURE));
1417 END_PROFILE(SMBsesssetupX);
1418 return;
1419 }
1420
1421 if (SVAL(req->vwv+4, 0) == 0) {
1422 setup_new_vc_session();
1423 }
1424
1425 reply_sesssetup_and_X_spnego(req);
1426 END_PROFILE(SMBsesssetupX);
1427 return;
1428 }
1429
1430 smb_bufsize = SVAL(req->vwv+2, 0);
1431
1432 if (Protocol < PROTOCOL_NT1) {
1433 uint16 passlen1 = SVAL(req->vwv+7, 0);
1434
1435 /* Never do NT status codes with protocols before NT1 as we
1436 * don't get client caps. */
1437 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1438
1439 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1440 reply_nterror(req, nt_status_squash(
1441 NT_STATUS_INVALID_PARAMETER));
1442 END_PROFILE(SMBsesssetupX);
1443 return;
1444 }
1445
1446 if (doencrypt) {
1447 lm_resp = data_blob(req->buf, passlen1);
1448 } else {
1449 plaintext_password = data_blob(req->buf, passlen1+1);
1450 /* Ensure null termination */
1451 plaintext_password.data[passlen1] = 0;
1452 }
1453
1454 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1455 req->buf + passlen1, STR_TERMINATE);
1456 user = tmp ? tmp : "";
1457
1458 domain = "";
1459
1460 } else {
1461 uint16 passlen1 = SVAL(req->vwv+7, 0);
1462 uint16 passlen2 = SVAL(req->vwv+8, 0);
1463 enum remote_arch_types ra_type = get_remote_arch();
1464 const uint8_t *p = req->buf;
1465 const uint8_t *save_p = req->buf;
1466 uint16 byte_count;
1467
1468
1469 if(global_client_caps == 0) {
1470 global_client_caps = IVAL(req->vwv+11, 0);
1471
1472 if (!(global_client_caps & CAP_STATUS32)) {
1473 remove_from_common_flags2(
1474 FLAGS2_32_BIT_ERROR_CODES);
1475 }
1476
1477 /* client_caps is used as final determination if
1478 * client is NT or Win95. This is needed to return
1479 * the correct error codes in some circumstances.
1480 */
1481
1482 if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1483 ra_type == RA_WIN95) {
1484 if(!(global_client_caps & (CAP_NT_SMBS|
1485 CAP_STATUS32))) {
1486 set_remote_arch( RA_WIN95);
1487 }
1488 }
1489 }
1490
1491 if (!doencrypt) {
1492 /* both Win95 and WinNT stuff up the password
1493 * lengths for non-encrypting systems. Uggh.
1494
1495 if passlen1==24 its a win95 system, and its setting
1496 the password length incorrectly. Luckily it still
1497 works with the default code because Win95 will null
1498 terminate the password anyway
1499
1500 if passlen1>0 and passlen2>0 then maybe its a NT box
1501 and its setting passlen2 to some random value which
1502 really stuffs things up. we need to fix that one. */
1503
1504 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1505 passlen2 != 1) {
1506 passlen2 = 0;
1507 }
1508 }
1509
1510 /* check for nasty tricks */
1511 if (passlen1 > MAX_PASS_LEN
1512 || passlen1 > smbreq_bufrem(req, p)) {
1513 reply_nterror(req, nt_status_squash(
1514 NT_STATUS_INVALID_PARAMETER));
1515 END_PROFILE(SMBsesssetupX);
1516 return;
1517 }
1518
1519 if (passlen2 > MAX_PASS_LEN
1520 || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1521 reply_nterror(req, nt_status_squash(
1522 NT_STATUS_INVALID_PARAMETER));
1523 END_PROFILE(SMBsesssetupX);
1524 return;
1525 }
1526
1527 /* Save the lanman2 password and the NT md4 password. */
1528
1529 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1530 doencrypt = False;
1531 }
1532
1533 if (doencrypt) {
1534 lm_resp = data_blob(p, passlen1);
1535 nt_resp = data_blob(p+passlen1, passlen2);
1536 } else if (lp_security() != SEC_SHARE) {
1537 /*
1538 * In share level we should ignore any passwords, so
1539 * only read them if we're not.
1540 */
1541 char *pass = NULL;
1542 bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1543
1544 if (unic && (passlen2 == 0) && passlen1) {
1545 /* Only a ascii plaintext password was sent. */
1546 (void)srvstr_pull_talloc(talloc_tos(),
1547 req->inbuf,
1548 req->flags2,
1549 &pass,
1550 req->buf,
1551 passlen1,
1552 STR_TERMINATE|STR_ASCII);
1553 } else {
1554 (void)srvstr_pull_talloc(talloc_tos(),
1555 req->inbuf,
1556 req->flags2,
1557 &pass,
1558 req->buf,
1559 unic ? passlen2 : passlen1,
1560 STR_TERMINATE);
1561 }
1562 if (!pass) {
1563 reply_nterror(req, nt_status_squash(
1564 NT_STATUS_INVALID_PARAMETER));
1565 END_PROFILE(SMBsesssetupX);
1566 return;
1567 }
1568 plaintext_password = data_blob(pass, strlen(pass)+1);
1569 }
1570
1571 p += passlen1 + passlen2;
1572
1573 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1574 STR_TERMINATE);
1575 user = tmp ? tmp : "";
1576
1577 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1578 STR_TERMINATE);
1579 domain = tmp ? tmp : "";
1580
1581 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1582 STR_TERMINATE);
1583 native_os = tmp ? tmp : "";
1584
1585 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1586 STR_TERMINATE);
1587 native_lanman = tmp ? tmp : "";
1588
1589 /* not documented or decoded by Ethereal but there is one more
1590 * string in the extra bytes which is the same as the
1591 * PrimaryDomain when using extended security. Windows NT 4
1592 * and 2003 use this string to store the native lanman string.
1593 * Windows 9x does not include a string here at all so we have
1594 * to check if we have any extra bytes left */
1595
1596 byte_count = SVAL(req->vwv+13, 0);
1597 if ( PTR_DIFF(p, save_p) < byte_count) {
1598 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1599 STR_TERMINATE);
1600 primary_domain = tmp ? tmp : "";
1601 } else {
1602 primary_domain = talloc_strdup(talloc_tos(), "null");
1603 }
1604
1605 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] "
1606 "PrimaryDomain=[%s]\n",
1607 domain, native_os, native_lanman, primary_domain));
1608
1609 if ( ra_type == RA_WIN2K ) {
1610 if ( strlen(native_lanman) == 0 )
1611 ra_lanman_string( primary_domain );
1612 else
1613 ra_lanman_string( native_lanman );
1614 }
1615
1616 }
1617
1618 if (SVAL(req->vwv+4, 0) == 0) {
1619 setup_new_vc_session();
1620 }
1621
1622 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1623 domain, user, get_remote_machine_name()));
1624
1625 if (*user) {
1626 if (global_spnego_negotiated) {
1627
1628 /* This has to be here, because this is a perfectly
1629 * valid behaviour for guest logons :-( */
1630
1631 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt "
1632 "at 'normal' session setup after "
1633 "negotiating spnego.\n"));
1634 reply_nterror(req, nt_status_squash(
1635 NT_STATUS_LOGON_FAILURE));
1636 END_PROFILE(SMBsesssetupX);
1637 return;
1638 }
1639 fstrcpy(sub_user, user);
1640 } else {
1641 fstrcpy(sub_user, lp_guestaccount());
1642 }
1643
1644 sub_set_smb_name(sub_user);
1645
1646 reload_services(True);
1647
1648 if (lp_security() == SEC_SHARE) {
1649 /* In share level we should ignore any passwords */
1650
1651 data_blob_free(&lm_resp);
1652 data_blob_free(&nt_resp);
1653 data_blob_clear_free(&plaintext_password);
1654
1655 map_username(sub_user);
1656 add_session_user(sub_user);
1657 add_session_workgroup(domain);
1658 /* Then force it to null for the benfit of the code below */
1659 user = "";
1660 }
1661
1662 if (!*user) {
1663
1664 nt_status = check_guest_password(&server_info);
1665
1666 } else if (doencrypt) {
1667 if (!negprot_global_auth_context) {
1668 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted "
1669 "session setup without negprot denied!\n"));
1670 reply_nterror(req, nt_status_squash(
1671 NT_STATUS_LOGON_FAILURE));
1672 END_PROFILE(SMBsesssetupX);
1673 return;
1674 }
1675 nt_status = make_user_info_for_reply_enc(&user_info, user,
1676 domain,
1677 lm_resp, nt_resp);
1678 if (NT_STATUS_IS_OK(nt_status)) {
1679 nt_status = negprot_global_auth_context->check_ntlm_password(
1680 negprot_global_auth_context,
1681 user_info,
1682 &server_info);
1683 }
1684 } else {
1685 struct auth_context *plaintext_auth_context = NULL;
1686
1687 nt_status = make_auth_context_subsystem(
1688 &plaintext_auth_context);
1689
1690 if (NT_STATUS_IS_OK(nt_status)) {
1691 uint8_t chal[8];
1692
1693 plaintext_auth_context->get_ntlm_challenge(
1694 plaintext_auth_context, chal);
1695
1696 if (!make_user_info_for_reply(&user_info,
1697 user, domain, chal,
1698 plaintext_password)) {
1699 nt_status = NT_STATUS_NO_MEMORY;
1700 }
1701
1702 if (NT_STATUS_IS_OK(nt_status)) {
1703 nt_status = plaintext_auth_context->check_ntlm_password(
1704 plaintext_auth_context,
1705 user_info,
1706 &server_info);
1707
1708 (plaintext_auth_context->free)(
1709 &plaintext_auth_context);
1710 }
1711 }
1712 }
1713
1714 free_user_info(&user_info);
1715
1716 if (!NT_STATUS_IS_OK(nt_status)) {
1717 nt_status = do_map_to_guest(nt_status, &server_info,
1718 user, domain);
1719 }
1720
1721 if (!NT_STATUS_IS_OK(nt_status)) {
1722 data_blob_free(&nt_resp);
1723 data_blob_free(&lm_resp);
1724 data_blob_clear_free(&plaintext_password);
1725 reply_nterror(req, nt_status_squash(nt_status));
1726 END_PROFILE(SMBsesssetupX);
1727 return;
1728 }
1729
1730 /* Ensure we can't possible take a code path leading to a
1731 * null defref. */
1732 if (!server_info) {
1733 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1734 END_PROFILE(SMBsesssetupX);
1735 return;
1736 }
1737
1738 if (!server_info->ptok) {
1739 nt_status = create_local_token(server_info);
1740
1741 if (!NT_STATUS_IS_OK(nt_status)) {
1742 DEBUG(10, ("create_local_token failed: %s\n",
1743 nt_errstr(nt_status)));
1744 data_blob_free(&nt_resp);
1745 data_blob_free(&lm_resp);
1746 data_blob_clear_free(&plaintext_password);
1747 reply_nterror(req, nt_status_squash(nt_status));
1748 END_PROFILE(SMBsesssetupX);
1749 return;
1750 }
1751 }
1752
1753 data_blob_clear_free(&plaintext_password);
1754
1755 /* it's ok - setup a reply */
1756 reply_outbuf(req, 3, 0);
1757 if (Protocol >= PROTOCOL_NT1) {
1758 push_signature(&req->outbuf);
1759 /* perhaps grab OS version here?? */
1760 }
1761
1762 if (server_info->guest) {
1763 SSVAL(req->outbuf,smb_vwv2,1);
1764 }
1765
1766 /* register the name and uid as being validated, so further connections
1767 to a uid can get through without a password, on the same VC */
1768
1769 if (lp_security() == SEC_SHARE) {
1770 sess_vuid = UID_FIELD_INVALID;
1771 TALLOC_FREE(server_info);
1772 } else {
1773 /* Ignore the initial vuid. */
1774 sess_vuid = register_initial_vuid();
1775 if (sess_vuid == UID_FIELD_INVALID) {
1776 data_blob_free(&nt_resp);
1777 data_blob_free(&lm_resp);
1778 reply_nterror(req, nt_status_squash(
1779 NT_STATUS_LOGON_FAILURE));
1780 END_PROFILE(SMBsesssetupX);
1781 return;
1782 }
1783 /* register_existing_vuid keeps the server info */
1784 sess_vuid = register_existing_vuid(sess_vuid,
1785 server_info,
1786 nt_resp.data ? nt_resp : lm_resp,
1787 sub_user);
1788 if (sess_vuid == UID_FIELD_INVALID) {
1789 data_blob_free(&nt_resp);
1790 data_blob_free(&lm_resp);
1791 reply_nterror(req, nt_status_squash(
1792 NT_STATUS_LOGON_FAILURE));
1793 END_PROFILE(SMBsesssetupX);
1794 return;
1795 }
1796
1797 /* current_user_info is changed on new vuid */
1798 reload_services( True );
1799
1800 sessionsetup_start_signing_engine(server_info, req->inbuf);
1801 }
1802
1803 data_blob_free(&nt_resp);
1804 data_blob_free(&lm_resp);
1805
1806 SSVAL(req->outbuf,smb_uid,sess_vuid);
1807 SSVAL(req->inbuf,smb_uid,sess_vuid);
1808 req->vuid = sess_vuid;
1809
1810 if (!done_sesssetup)
1811 max_send = MIN(max_send,smb_bufsize);
1812
1813 done_sesssetup = True;
1814
1815 END_PROFILE(SMBsesssetupX);
1816 chain_reply(req);
1817 return;
1818 }