source: trunk/samba-3.0.25pre1/source/smbd/sesssetup.c@ 1

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

Initial code import

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