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