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

Last change on this file since 104 was 58, checked in by Paul Smedley, 18 years ago

Report OS name = OS/2-eComStation - fixes ticket #23

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