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

Last change on this file since 158 was 158, checked in by Paul Smedley, 17 years ago

Update source to 3.0.32

File size: 47.0 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****************************************************************************/
102
103static BOOL reply_sesssetup_blob(connection_struct *conn, char *outbuf,
104 DATA_BLOB blob, NTSTATUS nt_status)
105{
106 char *p;
107
108 if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
109 ERROR_NT(nt_status_squash(nt_status));
110 } else {
111 set_message(outbuf,4,0,True);
112
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 if (sess_vuid == UID_FIELD_INVALID ) {
522 ret = NT_STATUS_LOGON_FAILURE;
523 } else {
524 /* current_user_info is changed on new vuid */
525 reload_services( True );
526
527 set_message(outbuf,4,0,True);
528 SSVAL(outbuf, smb_vwv3, 0);
529
530 if (server_info->guest) {
531 SSVAL(outbuf,smb_vwv2,1);
532 }
533
534 SSVAL(outbuf, smb_uid, sess_vuid);
535
536 sessionsetup_start_signing_engine(server_info, inbuf);
537 }
538
539 /* wrap that up in a nice GSS-API wrapping */
540 if (NT_STATUS_IS_OK(ret)) {
541 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep, TOK_ID_KRB_AP_REP);
542 } else {
543 ap_rep_wrapped = data_blob(NULL, 0);
544 }
545 response = spnego_gen_auth_response(&ap_rep_wrapped, ret, OID_KERBEROS5_OLD);
546 reply_sesssetup_blob(conn, outbuf, response, ret);
547
548 data_blob_free(&ap_rep);
549 data_blob_free(&ap_rep_wrapped);
550 data_blob_free(&response);
551 TALLOC_FREE(mem_ctx);
552
553 return -1; /* already replied */
554}
555#endif
556
557/****************************************************************************
558 Send a session setup reply, wrapped in SPNEGO.
559 Get vuid and check first.
560 End the NTLMSSP exchange context if we are OK/complete fail
561 This should be split into two functions, one to handle each
562 leg of the NTLM auth steps.
563***************************************************************************/
564
565static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf,
566 uint16 vuid,
567 AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
568 DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
569 BOOL wrap)
570{
571 BOOL ret;
572 DATA_BLOB response;
573 struct auth_serversupplied_info *server_info = NULL;
574
575 if (NT_STATUS_IS_OK(nt_status)) {
576 server_info = (*auth_ntlmssp_state)->server_info;
577 } else {
578 nt_status = do_map_to_guest(nt_status,
579 &server_info,
580 (*auth_ntlmssp_state)->ntlmssp_state->user,
581 (*auth_ntlmssp_state)->ntlmssp_state->domain);
582 }
583
584 if (NT_STATUS_IS_OK(nt_status)) {
585 int sess_vuid;
586 DATA_BLOB nullblob = data_blob(NULL, 0);
587 DATA_BLOB session_key = data_blob((*auth_ntlmssp_state)->ntlmssp_state->session_key.data, (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
588
589 /* register_vuid keeps the server info */
590 sess_vuid = register_vuid(server_info, session_key, nullblob, (*auth_ntlmssp_state)->ntlmssp_state->user);
591 (*auth_ntlmssp_state)->server_info = NULL;
592
593 if (sess_vuid == UID_FIELD_INVALID ) {
594 nt_status = NT_STATUS_LOGON_FAILURE;
595 } else {
596
597 /* current_user_info is changed on new vuid */
598 reload_services( True );
599
600 set_message(outbuf,4,0,True);
601 SSVAL(outbuf, smb_vwv3, 0);
602
603 if (server_info->guest) {
604 SSVAL(outbuf,smb_vwv2,1);
605 }
606
607 SSVAL(outbuf,smb_uid,sess_vuid);
608
609 sessionsetup_start_signing_engine(server_info, inbuf);
610 }
611 }
612
613 if (wrap) {
614 response = spnego_gen_auth_response(ntlmssp_blob, nt_status, OID_NTLMSSP);
615 } else {
616 response = *ntlmssp_blob;
617 }
618
619 ret = reply_sesssetup_blob(conn, outbuf, response, nt_status);
620 if (wrap) {
621 data_blob_free(&response);
622 }
623
624 /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
625 and the other end, that we are not finished yet. */
626
627 if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
628 /* NB. This is *NOT* an error case. JRA */
629 auth_ntlmssp_end(auth_ntlmssp_state);
630 /* Kill the intermediate vuid */
631 invalidate_intermediate_vuid(vuid);
632 }
633
634 return ret;
635}
636
637/****************************************************************************
638 Is this a krb5 mechanism ?
639****************************************************************************/
640
641static NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out, BOOL *p_is_krb5)
642{
643 char *OIDs[ASN1_MAX_OIDS];
644 int i;
645
646 *p_is_krb5 = False;
647
648 /* parse out the OIDs and the first sec blob */
649 if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
650 return NT_STATUS_LOGON_FAILURE;
651 }
652
653 /* only look at the first OID for determining the mechToken --
654 accoirding to RFC2478, we should choose the one we want
655 and renegotiate, but i smell a client bug here..
656
657 Problem observed when connecting to a member (samba box)
658 of an AD domain as a user in a Samba domain. Samba member
659 server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
660 client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
661 NTLMSSP mechtoken. --jerry */
662
663#ifdef HAVE_KRB5
664 if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
665 strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
666 *p_is_krb5 = True;
667 }
668#endif
669
670 for (i=0;OIDs[i];i++) {
671 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
672 free(OIDs[i]);
673 }
674 return NT_STATUS_OK;
675}
676
677/****************************************************************************
678 Reply to a session setup spnego negotiate packet.
679****************************************************************************/
680
681static int reply_spnego_negotiate(connection_struct *conn,
682 char *inbuf,
683 char *outbuf,
684 uint16 vuid,
685 int length, int bufsize,
686 DATA_BLOB blob1,
687 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
688{
689 DATA_BLOB secblob;
690 DATA_BLOB chal;
691 BOOL got_kerberos_mechanism = False;
692 NTSTATUS status;
693
694 status = parse_spnego_mechanisms(blob1, &secblob, &got_kerberos_mechanism);
695 if (!NT_STATUS_IS_OK(status)) {
696 /* Kill the intermediate vuid */
697 invalidate_intermediate_vuid(vuid);
698 return ERROR_NT(nt_status_squash(status));
699 }
700
701 DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length));
702
703#ifdef HAVE_KRB5
704 if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
705 BOOL destroy_vuid = True;
706 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
707 length, bufsize, &secblob, &destroy_vuid);
708 data_blob_free(&secblob);
709 if (destroy_vuid) {
710 /* Kill the intermediate vuid */
711 invalidate_intermediate_vuid(vuid);
712 }
713 return ret;
714 }
715#endif
716
717 if (got_kerberos_mechanism) {
718 invalidate_intermediate_vuid(vuid);
719 DEBUG(3,("reply_spnego_negotiate: network "
720 "misconfiguration, client sent us a "
721 "krb5 ticket and kerberos security "
722 "not enabled"));
723 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
724 }
725
726 if (*auth_ntlmssp_state) {
727 auth_ntlmssp_end(auth_ntlmssp_state);
728 }
729
730 status = auth_ntlmssp_start(auth_ntlmssp_state);
731 if (!NT_STATUS_IS_OK(status)) {
732 /* Kill the intermediate vuid */
733 invalidate_intermediate_vuid(vuid);
734 return ERROR_NT(nt_status_squash(status));
735 }
736
737 status = auth_ntlmssp_update(*auth_ntlmssp_state,
738 secblob, &chal);
739
740 data_blob_free(&secblob);
741
742 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state,
743 &chal, status, True);
744
745 data_blob_free(&chal);
746
747 /* already replied */
748 return -1;
749}
750
751/****************************************************************************
752 Reply to a session setup spnego auth packet.
753****************************************************************************/
754
755static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
756 uint16 vuid,
757 int length, int bufsize,
758 DATA_BLOB blob1,
759 AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
760{
761 DATA_BLOB auth = data_blob(NULL,0);
762 DATA_BLOB auth_reply = data_blob(NULL,0);
763 DATA_BLOB secblob = data_blob(NULL,0);
764 NTSTATUS status = NT_STATUS_INVALID_PARAMETER;
765
766 if (!spnego_parse_auth(blob1, &auth)) {
767#if 0
768 file_save("auth.dat", blob1.data, blob1.length);
769#endif
770 /* Kill the intermediate vuid */
771 invalidate_intermediate_vuid(vuid);
772
773 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
774 }
775
776 if (auth.data[0] == ASN1_APPLICATION(0)) {
777 /* Might be a second negTokenTarg packet */
778
779 BOOL got_krb5_mechanism = False;
780 status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism);
781 if (NT_STATUS_IS_OK(status)) {
782 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length));
783#ifdef HAVE_KRB5
784 if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
785 BOOL destroy_vuid = True;
786 int ret = reply_spnego_kerberos(conn, inbuf, outbuf,
787 length, bufsize, &secblob, &destroy_vuid);
788 data_blob_free(&secblob);
789 data_blob_free(&auth);
790 if (destroy_vuid) {
791 /* Kill the intermediate vuid */
792 invalidate_intermediate_vuid(vuid);
793 }
794 return ret;
795 }
796#endif
797 }
798 }
799
800 /* If we get here it wasn't a negTokenTarg auth packet. */
801 data_blob_free(&secblob);
802
803 if (!*auth_ntlmssp_state) {
804 /* Kill the intermediate vuid */
805 invalidate_intermediate_vuid(vuid);
806
807 /* auth before negotiatiate? */
808 return ERROR_NT(NT_STATUS_LOGON_FAILURE);
809 }
810
811 status = auth_ntlmssp_update(*auth_ntlmssp_state,
812 auth, &auth_reply);
813
814 data_blob_free(&auth);
815
816 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
817 auth_ntlmssp_state,
818 &auth_reply, status, True);
819
820 data_blob_free(&auth_reply);
821
822 /* and tell smbd that we have already replied to this packet */
823 return -1;
824}
825
826/****************************************************************************
827 List to store partial SPNEGO auth fragments.
828****************************************************************************/
829
830static struct pending_auth_data *pd_list;
831
832/****************************************************************************
833 Delete an entry on the list.
834****************************************************************************/
835
836static void delete_partial_auth(struct pending_auth_data *pad)
837{
838 if (!pad) {
839 return;
840 }
841 DLIST_REMOVE(pd_list, pad);
842 data_blob_free(&pad->partial_data);
843 SAFE_FREE(pad);
844}
845
846/****************************************************************************
847 Search for a partial SPNEGO auth fragment matching an smbpid.
848****************************************************************************/
849
850static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
851{
852 struct pending_auth_data *pad;
853
854 for (pad = pd_list; pad; pad = pad->next) {
855 if (pad->smbpid == smbpid) {
856 break;
857 }
858 }
859 return pad;
860}
861
862/****************************************************************************
863 Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED,
864 else return NT_STATUS_OK. Don't allow the blob to be more than 64k.
865****************************************************************************/
866
867static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob)
868{
869 struct pending_auth_data *pad = NULL;
870 ASN1_DATA data;
871 size_t needed_len = 0;
872
873 pad = get_pending_auth_data(smbpid);
874
875 /* Ensure we have some data. */
876 if (pblob->length == 0) {
877 /* Caller can cope. */
878 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
879 delete_partial_auth(pad);
880 return NT_STATUS_OK;
881 }
882
883 /* Were we waiting for more data ? */
884 if (pad) {
885 DATA_BLOB tmp_blob;
886 size_t copy_len = MIN(65536, pblob->length);
887
888 /* Integer wrap paranoia.... */
889
890 if (pad->partial_data.length + copy_len < pad->partial_data.length ||
891 pad->partial_data.length + copy_len < copy_len) {
892
893 DEBUG(2,("check_spnego_blob_complete: integer wrap "
894 "pad->partial_data.length = %u, "
895 "copy_len = %u\n",
896 (unsigned int)pad->partial_data.length,
897 (unsigned int)copy_len ));
898
899 delete_partial_auth(pad);
900 return NT_STATUS_INVALID_PARAMETER;
901 }
902
903 DEBUG(10,("check_spnego_blob_complete: "
904 "pad->partial_data.length = %u, "
905 "pad->needed_len = %u, "
906 "copy_len = %u, "
907 "pblob->length = %u,\n",
908 (unsigned int)pad->partial_data.length,
909 (unsigned int)pad->needed_len,
910 (unsigned int)copy_len,
911 (unsigned int)pblob->length ));
912
913 tmp_blob = data_blob(NULL,
914 pad->partial_data.length + copy_len);
915
916 /* Concatenate the two (up to copy_len) bytes. */
917 memcpy(tmp_blob.data,
918 pad->partial_data.data,
919 pad->partial_data.length);
920 memcpy(tmp_blob.data + pad->partial_data.length,
921 pblob->data,
922 copy_len);
923
924 /* Replace the partial data. */
925 data_blob_free(&pad->partial_data);
926 pad->partial_data = tmp_blob;
927 ZERO_STRUCT(tmp_blob);
928
929 /* Are we done ? */
930 if (pblob->length >= pad->needed_len) {
931 /* Yes, replace pblob. */
932 data_blob_free(pblob);
933 *pblob = pad->partial_data;
934 ZERO_STRUCT(pad->partial_data);
935 delete_partial_auth(pad);
936 return NT_STATUS_OK;
937 }
938
939 /* Still need more data. */
940 pad->needed_len -= copy_len;
941 return NT_STATUS_MORE_PROCESSING_REQUIRED;
942 }
943
944 if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
945 (pblob->data[0] != ASN1_CONTEXT(1))) {
946 /* Not something we can determine the
947 * length of.
948 */
949 return NT_STATUS_OK;
950 }
951
952 /* This is a new SPNEGO sessionsetup - see if
953 * the data given in this blob is enough.
954 */
955
956 asn1_load(&data, *pblob);
957 asn1_start_tag(&data, pblob->data[0]);
958 if (data.has_error || data.nesting == NULL) {
959 asn1_free(&data);
960 /* Let caller catch. */
961 return NT_STATUS_OK;
962 }
963
964 /* Integer wrap paranoia.... */
965
966 if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
967 data.nesting->taglen + data.nesting->start < data.nesting->start) {
968
969 DEBUG(2,("check_spnego_blob_complete: integer wrap "
970 "data.nesting->taglen = %u, "
971 "data.nesting->start = %u\n",
972 (unsigned int)data.nesting->taglen,
973 (unsigned int)data.nesting->start ));
974
975 asn1_free(&data);
976 return NT_STATUS_INVALID_PARAMETER;
977 }
978
979 /* Total length of the needed asn1 is the tag length
980 * plus the current offset. */
981
982 needed_len = data.nesting->taglen + data.nesting->start;
983 asn1_free(&data);
984
985 DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
986 "pblob->length = %u\n",
987 (unsigned int)needed_len,
988 (unsigned int)pblob->length ));
989
990 if (needed_len <= pblob->length) {
991 /* Nothing to do - blob is complete. */
992 return NT_STATUS_OK;
993 }
994
995 /* Refuse the blob if it's bigger than 64k. */
996 if (needed_len > 65536) {
997 DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
998 (unsigned int)needed_len ));
999 return NT_STATUS_INVALID_PARAMETER;
1000 }
1001
1002 /* We must store this blob until complete. */
1003 pad = SMB_MALLOC(sizeof(struct pending_auth_data));
1004 if (!pad) {
1005 return NT_STATUS_NO_MEMORY;
1006 }
1007 pad->needed_len = needed_len - pblob->length;
1008 pad->partial_data = data_blob(pblob->data, pblob->length);
1009 if (pad->partial_data.data == NULL) {
1010 SAFE_FREE(pad);
1011 return NT_STATUS_NO_MEMORY;
1012 }
1013 pad->smbpid = smbpid;
1014 pad->vuid = vuid;
1015 DLIST_ADD(pd_list, pad);
1016
1017 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1018}
1019
1020/****************************************************************************
1021 Reply to a session setup command.
1022 conn POINTER CAN BE NULL HERE !
1023****************************************************************************/
1024
1025static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
1026 char *outbuf,
1027 int length,int bufsize)
1028{
1029 uint8 *p;
1030 DATA_BLOB blob1;
1031 int ret;
1032 size_t bufrem;
1033 fstring native_os, native_lanman, primary_domain;
1034 char *p2;
1035 uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
1036 enum remote_arch_types ra_type = get_remote_arch();
1037 int vuid = SVAL(inbuf,smb_uid);
1038 user_struct *vuser = NULL;
1039 NTSTATUS status = NT_STATUS_OK;
1040 uint16 smbpid = SVAL(inbuf,smb_pid);
1041
1042 DEBUG(3,("Doing spnego session setup\n"));
1043
1044 if (global_client_caps == 0) {
1045 global_client_caps = IVAL(inbuf,smb_vwv10);
1046
1047 if (!(global_client_caps & CAP_STATUS32)) {
1048 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1049 }
1050
1051 }
1052
1053 p = (uint8 *)smb_buf(inbuf);
1054
1055 if (data_blob_len == 0) {
1056 /* an invalid request */
1057 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1058 }
1059
1060 bufrem = smb_bufrem(inbuf, p);
1061 /* pull the spnego blob */
1062 blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1063
1064#if 0
1065 file_save("negotiate.dat", blob1.data, blob1.length);
1066#endif
1067
1068 p2 = inbuf + smb_vwv13 + data_blob_len;
1069 p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
1070 p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
1071 p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
1072 DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1073 native_os, native_lanman, primary_domain));
1074
1075 if ( ra_type == RA_WIN2K ) {
1076 /* Vista sets neither the OS or lanman strings */
1077
1078 if ( !strlen(native_os) && !strlen(native_lanman) )
1079 set_remote_arch(RA_VISTA);
1080
1081 /* Windows 2003 doesn't set the native lanman string,
1082 but does set primary domain which is a bug I think */
1083
1084 if ( !strlen(native_lanman) ) {
1085 ra_lanman_string( primary_domain );
1086 } else {
1087 ra_lanman_string( native_lanman );
1088 }
1089 }
1090
1091 vuser = get_partial_auth_user_struct(vuid);
1092 if (!vuser) {
1093 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1094 if (pad) {
1095 DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
1096 (unsigned int)pad->vuid ));
1097 vuid = pad->vuid;
1098 vuser = get_partial_auth_user_struct(vuid);
1099 }
1100 }
1101
1102 if (!vuser) {
1103 vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
1104 if (vuid == UID_FIELD_INVALID ) {
1105 data_blob_free(&blob1);
1106 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1107 }
1108
1109 vuser = get_partial_auth_user_struct(vuid);
1110 }
1111
1112 if (!vuser) {
1113 data_blob_free(&blob1);
1114 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1115 }
1116
1117 SSVAL(outbuf,smb_uid,vuid);
1118
1119 /* Large (greater than 4k) SPNEGO blobs are split into multiple
1120 * sessionsetup requests as the Windows limit on the security blob
1121 * field is 4k. Bug #4400. JRA.
1122 */
1123
1124 status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1125 if (!NT_STATUS_IS_OK(status)) {
1126 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1127 /* Real error - kill the intermediate vuid */
1128 invalidate_intermediate_vuid(vuid);
1129 }
1130 data_blob_free(&blob1);
1131 return ERROR_NT(nt_status_squash(status));
1132 }
1133
1134 if (blob1.data[0] == ASN1_APPLICATION(0)) {
1135 /* its a negTokenTarg packet */
1136 ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1137 &vuser->auth_ntlmssp_state);
1138 data_blob_free(&blob1);
1139 return ret;
1140 }
1141
1142 if (blob1.data[0] == ASN1_CONTEXT(1)) {
1143 /* its a auth packet */
1144 ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
1145 &vuser->auth_ntlmssp_state);
1146 data_blob_free(&blob1);
1147 return ret;
1148 }
1149
1150 if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1151 DATA_BLOB chal;
1152 if (!vuser->auth_ntlmssp_state) {
1153 status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1154 if (!NT_STATUS_IS_OK(status)) {
1155 /* Kill the intermediate vuid */
1156 invalidate_intermediate_vuid(vuid);
1157 data_blob_free(&blob1);
1158 return ERROR_NT(nt_status_squash(status));
1159 }
1160 }
1161
1162 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1163 blob1, &chal);
1164
1165 data_blob_free(&blob1);
1166
1167 reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid,
1168 &vuser->auth_ntlmssp_state,
1169 &chal, status, False);
1170 data_blob_free(&chal);
1171 return -1;
1172 }
1173
1174 /* what sort of packet is this? */
1175 DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1176
1177 data_blob_free(&blob1);
1178
1179 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1180}
1181
1182/****************************************************************************
1183 On new VC == 0, shutdown *all* old connections and users.
1184 It seems that only NT4.x does this. At W2K and above (XP etc.).
1185 a new session setup with VC==0 is ignored.
1186****************************************************************************/
1187
1188static int shutdown_other_smbds(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf,
1189 void *p)
1190{
1191 struct sessionid sessionid;
1192 const char *ip = (const char *)p;
1193
1194 SMB_ASSERT(dbuf.dsize == sizeof(sessionid));
1195 memcpy(&sessionid, dbuf.dptr, sizeof(sessionid));
1196
1197 if (!process_exists(pid_to_procid(sessionid.pid))) {
1198 return 0;
1199 }
1200
1201 if (sessionid.pid == sys_getpid()) {
1202 return 0;
1203 }
1204
1205 if (strcmp(ip, sessionid.ip_addr) != 0) {
1206 return 0;
1207 }
1208
1209 message_send_pid(pid_to_procid(sessionid.pid), MSG_SHUTDOWN,
1210 NULL, 0, True);
1211 return 0;
1212}
1213
1214static void setup_new_vc_session(void)
1215{
1216 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1217#if 0
1218 conn_close_all();
1219 invalidate_all_vuids();
1220#endif
1221 if (lp_reset_on_zero_vc()) {
1222 session_traverse(shutdown_other_smbds, client_addr());
1223 }
1224}
1225
1226/****************************************************************************
1227 Reply to a session setup command.
1228****************************************************************************/
1229
1230int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
1231 int length,int bufsize)
1232{
1233 int sess_vuid;
1234 int smb_bufsize;
1235 DATA_BLOB lm_resp;
1236 DATA_BLOB nt_resp;
1237 DATA_BLOB plaintext_password;
1238 fstring user;
1239 fstring sub_user; /* Sainitised username for substituion */
1240 fstring domain;
1241 fstring native_os;
1242 fstring native_lanman;
1243 fstring primary_domain;
1244 static BOOL done_sesssetup = False;
1245 auth_usersupplied_info *user_info = NULL;
1246 auth_serversupplied_info *server_info = NULL;
1247
1248 NTSTATUS nt_status;
1249
1250 BOOL doencrypt = global_encrypted_passwords_negotiated;
1251
1252 DATA_BLOB session_key;
1253
1254 START_PROFILE(SMBsesssetupX);
1255
1256 ZERO_STRUCT(lm_resp);
1257 ZERO_STRUCT(nt_resp);
1258 ZERO_STRUCT(plaintext_password);
1259
1260 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
1261
1262 /* a SPNEGO session setup has 12 command words, whereas a normal
1263 NT1 session setup has 13. See the cifs spec. */
1264 if (CVAL(inbuf, smb_wct) == 12 &&
1265 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
1266 if (!global_spnego_negotiated) {
1267 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1268 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1269 }
1270
1271 if (SVAL(inbuf,smb_vwv4) == 0) {
1272 setup_new_vc_session();
1273 }
1274 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
1275 }
1276
1277 smb_bufsize = SVAL(inbuf,smb_vwv2);
1278
1279 if (Protocol < PROTOCOL_NT1) {
1280 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1281
1282 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1283 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1284
1285 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
1286 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1287 }
1288
1289 if (doencrypt) {
1290 lm_resp = data_blob(smb_buf(inbuf), passlen1);
1291 } else {
1292 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
1293 /* Ensure null termination */
1294 plaintext_password.data[passlen1] = 0;
1295 }
1296
1297 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
1298 *domain = 0;
1299
1300 } else {
1301 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1302 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
1303 enum remote_arch_types ra_type = get_remote_arch();
1304 char *p = smb_buf(inbuf);
1305 char *save_p = smb_buf(inbuf);
1306 uint16 byte_count;
1307
1308
1309 if(global_client_caps == 0) {
1310 global_client_caps = IVAL(inbuf,smb_vwv11);
1311
1312 if (!(global_client_caps & CAP_STATUS32)) {
1313 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1314 }
1315
1316 /* client_caps is used as final determination if client is NT or Win95.
1317 This is needed to return the correct error codes in some
1318 circumstances.
1319 */
1320
1321 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
1322 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
1323 set_remote_arch( RA_WIN95);
1324 }
1325 }
1326 }
1327
1328 if (!doencrypt) {
1329 /* both Win95 and WinNT stuff up the password lengths for
1330 non-encrypting systems. Uggh.
1331
1332 if passlen1==24 its a win95 system, and its setting the
1333 password length incorrectly. Luckily it still works with the
1334 default code because Win95 will null terminate the password
1335 anyway
1336
1337 if passlen1>0 and passlen2>0 then maybe its a NT box and its
1338 setting passlen2 to some random value which really stuffs
1339 things up. we need to fix that one. */
1340
1341 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
1342 passlen2 = 0;
1343 }
1344
1345 /* check for nasty tricks */
1346 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
1347 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1348 }
1349
1350 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
1351 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1352 }
1353
1354 /* Save the lanman2 password and the NT md4 password. */
1355
1356 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1357 doencrypt = False;
1358 }
1359
1360 if (doencrypt) {
1361 lm_resp = data_blob(p, passlen1);
1362 nt_resp = data_blob(p+passlen1, passlen2);
1363 } else {
1364 pstring pass;
1365 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
1366
1367#if 0
1368 /* This was the previous fix. Not sure if it's still valid. JRA. */
1369 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
1370 /* NT4.0 stuffs up plaintext unicode password lengths... */
1371 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
1372 sizeof(pass), passlen1, STR_TERMINATE);
1373#endif
1374
1375 if (unic && (passlen2 == 0) && passlen1) {
1376 /* Only a ascii plaintext password was sent. */
1377 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
1378 passlen1, STR_TERMINATE|STR_ASCII);
1379 } else {
1380 srvstr_pull(inbuf, pass, smb_buf(inbuf),
1381 sizeof(pass), unic ? passlen2 : passlen1,
1382 STR_TERMINATE);
1383 }
1384 plaintext_password = data_blob(pass, strlen(pass)+1);
1385 }
1386
1387 p += passlen1 + passlen2;
1388 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
1389 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
1390 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
1391 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
1392
1393 /* not documented or decoded by Ethereal but there is one more string
1394 in the extra bytes which is the same as the PrimaryDomain when using
1395 extended security. Windows NT 4 and 2003 use this string to store
1396 the native lanman string. Windows 9x does not include a string here
1397 at all so we have to check if we have any extra bytes left */
1398
1399 byte_count = SVAL(inbuf, smb_vwv13);
1400 if ( PTR_DIFF(p, save_p) < byte_count)
1401 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
1402 else
1403 fstrcpy( primary_domain, "null" );
1404
1405 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1406 domain, native_os, native_lanman, primary_domain));
1407
1408 if ( ra_type == RA_WIN2K ) {
1409 if ( strlen(native_lanman) == 0 )
1410 ra_lanman_string( primary_domain );
1411 else
1412 ra_lanman_string( native_lanman );
1413 }
1414
1415 }
1416
1417 if (SVAL(inbuf,smb_vwv4) == 0) {
1418 setup_new_vc_session();
1419 }
1420
1421 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1422
1423 if (*user) {
1424 if (global_spnego_negotiated) {
1425
1426 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1427
1428 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1429 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1430 }
1431 fstrcpy(sub_user, user);
1432 } else {
1433 fstrcpy(sub_user, lp_guestaccount());
1434 }
1435
1436 sub_set_smb_name(sub_user);
1437
1438 reload_services(True);
1439
1440 if (lp_security() == SEC_SHARE) {
1441 /* in share level we should ignore any passwords */
1442
1443 data_blob_free(&lm_resp);
1444 data_blob_free(&nt_resp);
1445 data_blob_clear_free(&plaintext_password);
1446
1447 map_username(sub_user);
1448 add_session_user(sub_user);
1449 add_session_workgroup(domain);
1450 /* Then force it to null for the benfit of the code below */
1451 *user = 0;
1452 }
1453
1454 if (!*user) {
1455
1456 nt_status = check_guest_password(&server_info);
1457
1458 } else if (doencrypt) {
1459 if (!negprot_global_auth_context) {
1460 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1461 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1462 }
1463 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1464 lm_resp, nt_resp);
1465 if (NT_STATUS_IS_OK(nt_status)) {
1466 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1467 user_info,
1468 &server_info);
1469 }
1470 } else {
1471 struct auth_context *plaintext_auth_context = NULL;
1472 const uint8 *chal;
1473
1474 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1475
1476 if (NT_STATUS_IS_OK(nt_status)) {
1477 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1478
1479 if (!make_user_info_for_reply(&user_info,
1480 user, domain, chal,
1481 plaintext_password)) {
1482 nt_status = NT_STATUS_NO_MEMORY;
1483 }
1484
1485 if (NT_STATUS_IS_OK(nt_status)) {
1486 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1487 user_info,
1488 &server_info);
1489
1490 (plaintext_auth_context->free)(&plaintext_auth_context);
1491 }
1492 }
1493 }
1494
1495 free_user_info(&user_info);
1496
1497 if (!NT_STATUS_IS_OK(nt_status)) {
1498 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1499 }
1500
1501 if (!NT_STATUS_IS_OK(nt_status)) {
1502 data_blob_free(&nt_resp);
1503 data_blob_free(&lm_resp);
1504 data_blob_clear_free(&plaintext_password);
1505 return ERROR_NT(nt_status_squash(nt_status));
1506 }
1507
1508 /* Ensure we can't possible take a code path leading to a null defref. */
1509 if (!server_info) {
1510 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1511 }
1512
1513 if (!server_info->ptok) {
1514 nt_status = create_local_token(server_info);
1515 if (!NT_STATUS_IS_OK(nt_status)) {
1516 DEBUG(10, ("create_local_token failed: %s\n",
1517 nt_errstr(nt_status)));
1518 data_blob_free(&nt_resp);
1519 data_blob_free(&lm_resp);
1520 data_blob_clear_free(&plaintext_password);
1521 return ERROR_NT(nt_status_squash(nt_status));
1522 }
1523 }
1524
1525 if (server_info->user_session_key.data) {
1526 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1527 } else {
1528 session_key = data_blob(NULL, 0);
1529 }
1530
1531 data_blob_clear_free(&plaintext_password);
1532
1533 /* it's ok - setup a reply */
1534 set_message(outbuf,3,0,True);
1535 if (Protocol >= PROTOCOL_NT1) {
1536 char *p = smb_buf( outbuf );
1537 p += add_signature( outbuf, p );
1538 set_message_end( outbuf, p );
1539 /* perhaps grab OS version here?? */
1540 }
1541
1542 if (server_info->guest) {
1543 SSVAL(outbuf,smb_vwv2,1);
1544 }
1545
1546 /* register the name and uid as being validated, so further connections
1547 to a uid can get through without a password, on the same VC */
1548
1549 if (lp_security() == SEC_SHARE) {
1550 sess_vuid = UID_FIELD_INVALID;
1551 data_blob_free(&session_key);
1552 TALLOC_FREE(server_info);
1553 } else {
1554 /* register_vuid keeps the server info */
1555 sess_vuid = register_vuid(server_info, session_key,
1556 nt_resp.data ? nt_resp : lm_resp,
1557 sub_user);
1558 if (sess_vuid == UID_FIELD_INVALID) {
1559 data_blob_free(&nt_resp);
1560 data_blob_free(&lm_resp);
1561 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1562 }
1563
1564 /* current_user_info is changed on new vuid */
1565 reload_services( True );
1566
1567 sessionsetup_start_signing_engine(server_info, inbuf);
1568 }
1569
1570 data_blob_free(&nt_resp);
1571 data_blob_free(&lm_resp);
1572
1573 SSVAL(outbuf,smb_uid,sess_vuid);
1574 SSVAL(inbuf,smb_uid,sess_vuid);
1575
1576 if (!done_sesssetup)
1577 max_send = MIN(max_send,smb_bufsize);
1578
1579 done_sesssetup = True;
1580
1581 END_PROFILE(SMBsesssetupX);
1582 return chain_reply(inbuf,outbuf,length,bufsize);
1583}
Note: See TracBrowser for help on using the repository browser.