source: branches/samba-3.0/source/smbd/sesssetup.c@ 223

Last change on this file since 223 was 165, checked in by Paul Smedley, 16 years ago

Add 'missing' 3.0.34 diffs

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