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

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

Update source to 3.0.28a

File size: 46.9 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 = (struct sessionid *)dbuf.dptr;
1192 const char *ip = (const char *)p;
1193
1194 if (!process_exists(pid_to_procid(sessionid->pid))) {
1195 return 0;
1196 }
1197
1198 if (sessionid->pid == sys_getpid()) {
1199 return 0;
1200 }
1201
1202 if (strcmp(ip, sessionid->ip_addr) != 0) {
1203 return 0;
1204 }
1205
1206 message_send_pid(pid_to_procid(sessionid->pid), MSG_SHUTDOWN,
1207 NULL, 0, True);
1208 return 0;
1209}
1210
1211static void setup_new_vc_session(void)
1212{
1213 DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x compatible we would close all old resources.\n"));
1214#if 0
1215 conn_close_all();
1216 invalidate_all_vuids();
1217#endif
1218 if (lp_reset_on_zero_vc()) {
1219 session_traverse(shutdown_other_smbds, client_addr());
1220 }
1221}
1222
1223/****************************************************************************
1224 Reply to a session setup command.
1225****************************************************************************/
1226
1227int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
1228 int length,int bufsize)
1229{
1230 int sess_vuid;
1231 int smb_bufsize;
1232 DATA_BLOB lm_resp;
1233 DATA_BLOB nt_resp;
1234 DATA_BLOB plaintext_password;
1235 fstring user;
1236 fstring sub_user; /* Sainitised username for substituion */
1237 fstring domain;
1238 fstring native_os;
1239 fstring native_lanman;
1240 fstring primary_domain;
1241 static BOOL done_sesssetup = False;
1242 auth_usersupplied_info *user_info = NULL;
1243 auth_serversupplied_info *server_info = NULL;
1244
1245 NTSTATUS nt_status;
1246
1247 BOOL doencrypt = global_encrypted_passwords_negotiated;
1248
1249 DATA_BLOB session_key;
1250
1251 START_PROFILE(SMBsesssetupX);
1252
1253 ZERO_STRUCT(lm_resp);
1254 ZERO_STRUCT(nt_resp);
1255 ZERO_STRUCT(plaintext_password);
1256
1257 DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2)));
1258
1259 /* a SPNEGO session setup has 12 command words, whereas a normal
1260 NT1 session setup has 13. See the cifs spec. */
1261 if (CVAL(inbuf, smb_wct) == 12 &&
1262 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
1263 if (!global_spnego_negotiated) {
1264 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n"));
1265 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1266 }
1267
1268 if (SVAL(inbuf,smb_vwv4) == 0) {
1269 setup_new_vc_session();
1270 }
1271 return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize);
1272 }
1273
1274 smb_bufsize = SVAL(inbuf,smb_vwv2);
1275
1276 if (Protocol < PROTOCOL_NT1) {
1277 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1278
1279 /* Never do NT status codes with protocols before NT1 as we don't get client caps. */
1280 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1281
1282 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) {
1283 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1284 }
1285
1286 if (doencrypt) {
1287 lm_resp = data_blob(smb_buf(inbuf), passlen1);
1288 } else {
1289 plaintext_password = data_blob(smb_buf(inbuf), passlen1+1);
1290 /* Ensure null termination */
1291 plaintext_password.data[passlen1] = 0;
1292 }
1293
1294 srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE);
1295 *domain = 0;
1296
1297 } else {
1298 uint16 passlen1 = SVAL(inbuf,smb_vwv7);
1299 uint16 passlen2 = SVAL(inbuf,smb_vwv8);
1300 enum remote_arch_types ra_type = get_remote_arch();
1301 char *p = smb_buf(inbuf);
1302 char *save_p = smb_buf(inbuf);
1303 uint16 byte_count;
1304
1305
1306 if(global_client_caps == 0) {
1307 global_client_caps = IVAL(inbuf,smb_vwv11);
1308
1309 if (!(global_client_caps & CAP_STATUS32)) {
1310 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1311 }
1312
1313 /* client_caps is used as final determination if client is NT or Win95.
1314 This is needed to return the correct error codes in some
1315 circumstances.
1316 */
1317
1318 if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
1319 if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
1320 set_remote_arch( RA_WIN95);
1321 }
1322 }
1323 }
1324
1325 if (!doencrypt) {
1326 /* both Win95 and WinNT stuff up the password lengths for
1327 non-encrypting systems. Uggh.
1328
1329 if passlen1==24 its a win95 system, and its setting the
1330 password length incorrectly. Luckily it still works with the
1331 default code because Win95 will null terminate the password
1332 anyway
1333
1334 if passlen1>0 and passlen2>0 then maybe its a NT box and its
1335 setting passlen2 to some random value which really stuffs
1336 things up. we need to fix that one. */
1337
1338 if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
1339 passlen2 = 0;
1340 }
1341
1342 /* check for nasty tricks */
1343 if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) {
1344 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1345 }
1346
1347 if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) {
1348 return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
1349 }
1350
1351 /* Save the lanman2 password and the NT md4 password. */
1352
1353 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1354 doencrypt = False;
1355 }
1356
1357 if (doencrypt) {
1358 lm_resp = data_blob(p, passlen1);
1359 nt_resp = data_blob(p+passlen1, passlen2);
1360 } else {
1361 pstring pass;
1362 BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS;
1363
1364#if 0
1365 /* This was the previous fix. Not sure if it's still valid. JRA. */
1366 if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) {
1367 /* NT4.0 stuffs up plaintext unicode password lengths... */
1368 srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1,
1369 sizeof(pass), passlen1, STR_TERMINATE);
1370#endif
1371
1372 if (unic && (passlen2 == 0) && passlen1) {
1373 /* Only a ascii plaintext password was sent. */
1374 srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass),
1375 passlen1, STR_TERMINATE|STR_ASCII);
1376 } else {
1377 srvstr_pull(inbuf, pass, smb_buf(inbuf),
1378 sizeof(pass), unic ? passlen2 : passlen1,
1379 STR_TERMINATE);
1380 }
1381 plaintext_password = data_blob(pass, strlen(pass)+1);
1382 }
1383
1384 p += passlen1 + passlen2;
1385 p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE);
1386 p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE);
1387 p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE);
1388 p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE);
1389
1390 /* not documented or decoded by Ethereal but there is one more string
1391 in the extra bytes which is the same as the PrimaryDomain when using
1392 extended security. Windows NT 4 and 2003 use this string to store
1393 the native lanman string. Windows 9x does not include a string here
1394 at all so we have to check if we have any extra bytes left */
1395
1396 byte_count = SVAL(inbuf, smb_vwv13);
1397 if ( PTR_DIFF(p, save_p) < byte_count)
1398 p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE);
1399 else
1400 fstrcpy( primary_domain, "null" );
1401
1402 DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1403 domain, native_os, native_lanman, primary_domain));
1404
1405 if ( ra_type == RA_WIN2K ) {
1406 if ( strlen(native_lanman) == 0 )
1407 ra_lanman_string( primary_domain );
1408 else
1409 ra_lanman_string( native_lanman );
1410 }
1411
1412 }
1413
1414 if (SVAL(inbuf,smb_vwv4) == 0) {
1415 setup_new_vc_session();
1416 }
1417
1418 DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name()));
1419
1420 if (*user) {
1421 if (global_spnego_negotiated) {
1422
1423 /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */
1424
1425 DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n"));
1426 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1427 }
1428 fstrcpy(sub_user, user);
1429 } else {
1430 fstrcpy(sub_user, lp_guestaccount());
1431 }
1432
1433 sub_set_smb_name(sub_user);
1434
1435 reload_services(True);
1436
1437 if (lp_security() == SEC_SHARE) {
1438 /* in share level we should ignore any passwords */
1439
1440 data_blob_free(&lm_resp);
1441 data_blob_free(&nt_resp);
1442 data_blob_clear_free(&plaintext_password);
1443
1444 map_username(sub_user);
1445 add_session_user(sub_user);
1446 add_session_workgroup(domain);
1447 /* Then force it to null for the benfit of the code below */
1448 *user = 0;
1449 }
1450
1451 if (!*user) {
1452
1453 nt_status = check_guest_password(&server_info);
1454
1455 } else if (doencrypt) {
1456 if (!negprot_global_auth_context) {
1457 DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n"));
1458 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1459 }
1460 nt_status = make_user_info_for_reply_enc(&user_info, user, domain,
1461 lm_resp, nt_resp);
1462 if (NT_STATUS_IS_OK(nt_status)) {
1463 nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context,
1464 user_info,
1465 &server_info);
1466 }
1467 } else {
1468 struct auth_context *plaintext_auth_context = NULL;
1469 const uint8 *chal;
1470
1471 nt_status = make_auth_context_subsystem(&plaintext_auth_context);
1472
1473 if (NT_STATUS_IS_OK(nt_status)) {
1474 chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context);
1475
1476 if (!make_user_info_for_reply(&user_info,
1477 user, domain, chal,
1478 plaintext_password)) {
1479 nt_status = NT_STATUS_NO_MEMORY;
1480 }
1481
1482 if (NT_STATUS_IS_OK(nt_status)) {
1483 nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context,
1484 user_info,
1485 &server_info);
1486
1487 (plaintext_auth_context->free)(&plaintext_auth_context);
1488 }
1489 }
1490 }
1491
1492 free_user_info(&user_info);
1493
1494 if (!NT_STATUS_IS_OK(nt_status)) {
1495 nt_status = do_map_to_guest(nt_status, &server_info, user, domain);
1496 }
1497
1498 if (!NT_STATUS_IS_OK(nt_status)) {
1499 data_blob_free(&nt_resp);
1500 data_blob_free(&lm_resp);
1501 data_blob_clear_free(&plaintext_password);
1502 return ERROR_NT(nt_status_squash(nt_status));
1503 }
1504
1505 /* Ensure we can't possible take a code path leading to a null defref. */
1506 if (!server_info) {
1507 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1508 }
1509
1510 nt_status = create_local_token(server_info);
1511 if (!NT_STATUS_IS_OK(nt_status)) {
1512 DEBUG(10, ("create_local_token failed: %s\n",
1513 nt_errstr(nt_status)));
1514 data_blob_free(&nt_resp);
1515 data_blob_free(&lm_resp);
1516 data_blob_clear_free(&plaintext_password);
1517 return ERROR_NT(nt_status_squash(nt_status));
1518 }
1519
1520 if (server_info->user_session_key.data) {
1521 session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
1522 } else {
1523 session_key = data_blob(NULL, 0);
1524 }
1525
1526 data_blob_clear_free(&plaintext_password);
1527
1528 /* it's ok - setup a reply */
1529 set_message(outbuf,3,0,True);
1530 if (Protocol >= PROTOCOL_NT1) {
1531 char *p = smb_buf( outbuf );
1532 p += add_signature( outbuf, p );
1533 set_message_end( outbuf, p );
1534 /* perhaps grab OS version here?? */
1535 }
1536
1537 if (server_info->guest) {
1538 SSVAL(outbuf,smb_vwv2,1);
1539 }
1540
1541 /* register the name and uid as being validated, so further connections
1542 to a uid can get through without a password, on the same VC */
1543
1544 if (lp_security() == SEC_SHARE) {
1545 sess_vuid = UID_FIELD_INVALID;
1546 data_blob_free(&session_key);
1547 TALLOC_FREE(server_info);
1548 } else {
1549 /* register_vuid keeps the server info */
1550 sess_vuid = register_vuid(server_info, session_key,
1551 nt_resp.data ? nt_resp : lm_resp,
1552 sub_user);
1553 if (sess_vuid == UID_FIELD_INVALID) {
1554 data_blob_free(&nt_resp);
1555 data_blob_free(&lm_resp);
1556 return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
1557 }
1558
1559 /* current_user_info is changed on new vuid */
1560 reload_services( True );
1561
1562 sessionsetup_start_signing_engine(server_info, inbuf);
1563 }
1564
1565 data_blob_free(&nt_resp);
1566 data_blob_free(&lm_resp);
1567
1568 SSVAL(outbuf,smb_uid,sess_vuid);
1569 SSVAL(inbuf,smb_uid,sess_vuid);
1570
1571 if (!done_sesssetup)
1572 max_send = MIN(max_send,smb_bufsize);
1573
1574 done_sesssetup = True;
1575
1576 END_PROFILE(SMBsesssetupX);
1577 return chain_reply(inbuf,outbuf,length,bufsize);
1578}
Note: See TracBrowser for help on using the repository browser.