Fix type error in debug message
[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(NULL, 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(NULL, 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                                   const char *mechOID,
252                                   uint16 vuid,
253                                   bool *p_invalidate_vuid)
254 {
255         TALLOC_CTX *mem_ctx;
256         DATA_BLOB ticket;
257         char *client, *p, *domain;
258         fstring netbios_domain_name;
259         struct passwd *pw;
260         fstring user;
261         int sess_vuid = req->vuid;
262         NTSTATUS ret = NT_STATUS_OK;
263         struct PAC_DATA *pac_data = NULL;
264         DATA_BLOB ap_rep, ap_rep_wrapped, response;
265         auth_serversupplied_info *server_info = NULL;
266         DATA_BLOB session_key = data_blob_null;
267         uint8 tok_id[2];
268         DATA_BLOB nullblob = data_blob_null;
269         fstring real_username;
270         bool map_domainuser_to_guest = False;
271         bool username_was_mapped;
272         struct PAC_LOGON_INFO *logon_info = NULL;
273
274         ZERO_STRUCT(ticket);
275         ZERO_STRUCT(ap_rep);
276         ZERO_STRUCT(ap_rep_wrapped);
277         ZERO_STRUCT(response);
278
279         /* Normally we will always invalidate the intermediate vuid. */
280         *p_invalidate_vuid = True;
281
282         mem_ctx = talloc_init("reply_spnego_kerberos");
283         if (mem_ctx == NULL) {
284                 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
285                 return;
286         }
287
288         if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
289                 talloc_destroy(mem_ctx);
290                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
291                 return;
292         }
293
294         ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
295                                 &client, &pac_data, &ap_rep,
296                                 &session_key, True);
297
298         data_blob_free(&ticket);
299
300         if (!NT_STATUS_IS_OK(ret)) {
301 #if 0
302                 /* Experiment that failed.
303                  * See "only happens with a KDC" comment below. */
304
305                 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
306
307                         /*
308                          * Windows in this case returns
309                          * NT_STATUS_MORE_PROCESSING_REQUIRED
310                          * with a negTokenTarg blob containing an krb5_error
311                          * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
312                          * The client then fixes its clock and continues rather
313                          * than giving an error. JRA.
314                          * -- Looks like this only happens with a KDC. JRA.
315                          */
316
317                         bool ok = make_krb5_skew_error(&ap_rep);
318                         if (!ok) {
319                                 talloc_destroy(mem_ctx);
320                                 return ERROR_NT(nt_status_squash(
321                                                 NT_STATUS_LOGON_FAILURE));
322                         }
323                         ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
324                                         TOK_ID_KRB_ERROR);
325                         response = spnego_gen_auth_response(&ap_rep_wrapped,
326                                         ret, OID_KERBEROS5_OLD);
327                         reply_sesssetup_blob(conn, inbuf, outbuf, response,
328                                         NT_STATUS_MORE_PROCESSING_REQUIRED);
329
330                         /*
331                          * In this one case we don't invalidate the
332                          * intermediate vuid as we're expecting the client
333                          * to re-use it for the next sessionsetupX packet. JRA.
334                          */
335
336                         *p_invalidate_vuid = False;
337
338                         data_blob_free(&ap_rep);
339                         data_blob_free(&ap_rep_wrapped);
340                         data_blob_free(&response);
341                         talloc_destroy(mem_ctx);
342                         return -1; /* already replied */
343                 }
344 #else
345                 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
346                         ret = NT_STATUS_LOGON_FAILURE;
347                 }
348 #endif
349                 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
350                                 nt_errstr(ret)));
351                 talloc_destroy(mem_ctx);
352                 reply_nterror(req, nt_status_squash(ret));
353                 return;
354         }
355
356         DEBUG(3,("Ticket name is [%s]\n", client));
357
358         p = strchr_m(client, '@');
359         if (!p) {
360                 DEBUG(3,("Doesn't look like a valid principal\n"));
361                 data_blob_free(&ap_rep);
362                 data_blob_free(&session_key);
363                 SAFE_FREE(client);
364                 talloc_destroy(mem_ctx);
365                 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
366                 return;
367         }
368
369         *p = 0;
370
371         /* save the PAC data if we have it */
372
373         if (pac_data) {
374                 logon_info = get_logon_info_from_pac(pac_data);
375                 if (logon_info) {
376                         netsamlogon_cache_store( client, &logon_info->info3 );
377                 }
378         }
379
380         if (!strequal(p+1, lp_realm())) {
381                 DEBUG(3,("Ticket for foreign realm %s@%s\n", client, p+1));
382                 if (!lp_allow_trusted_domains()) {
383                         data_blob_free(&ap_rep);
384                         data_blob_free(&session_key);
385                         SAFE_FREE(client);
386                         talloc_destroy(mem_ctx);
387                         reply_nterror(req, nt_status_squash(
388                                               NT_STATUS_LOGON_FAILURE));
389                         return;
390                 }
391         }
392
393         /* this gives a fully qualified user name (ie. with full realm).
394            that leads to very long usernames, but what else can we do? */
395
396         domain = p+1;
397
398         if (logon_info && logon_info->info3.base.domain.string) {
399                 fstrcpy(netbios_domain_name,
400                         logon_info->info3.base.domain.string);
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 mapping 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(NULL, &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         server_info->nss_token |= username_was_mapped;
534
535         /* we need to build the token for the user. make_server_info_guest()
536            already does this */
537
538         if ( !server_info->ptok ) {
539                 ret = create_local_token( server_info );
540                 if ( !NT_STATUS_IS_OK(ret) ) {
541                         DEBUG(10,("failed to create local token: %s\n",
542                                 nt_errstr(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
562         data_blob_free(&server_info->user_session_key);
563         server_info->user_session_key = session_key;
564         session_key = data_blob_null;
565
566         sess_vuid = register_existing_vuid(sess_vuid,
567                                         server_info,
568                                         nullblob,
569                                         client);
570
571         SAFE_FREE(client);
572
573         reply_outbuf(req, 4, 0);
574         SSVAL(req->outbuf,smb_uid,sess_vuid);
575
576         if (sess_vuid == UID_FIELD_INVALID ) {
577                 ret = NT_STATUS_LOGON_FAILURE;
578         } else {
579                 /* current_user_info is changed on new vuid */
580                 reload_services( True );
581
582                 SSVAL(req->outbuf, smb_vwv3, 0);
583
584                 if (server_info->guest) {
585                         SSVAL(req->outbuf,smb_vwv2,1);
586                 }
587
588                 SSVAL(req->outbuf, smb_uid, sess_vuid);
589
590                 sessionsetup_start_signing_engine(server_info, req->inbuf);
591                 /* Successful logon. Keep this vuid. */
592                 *p_invalidate_vuid = False;
593         }
594
595         /* wrap that up in a nice GSS-API wrapping */
596         if (NT_STATUS_IS_OK(ret)) {
597                 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
598                                 TOK_ID_KRB_AP_REP);
599         } else {
600                 ap_rep_wrapped = data_blob_null;
601         }
602         response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
603                         mechOID);
604         reply_sesssetup_blob(req, response, ret);
605
606         data_blob_free(&ap_rep);
607         data_blob_free(&ap_rep_wrapped);
608         data_blob_free(&response);
609         TALLOC_FREE(mem_ctx);
610 }
611
612 #endif
613
614 /****************************************************************************
615  Send a session setup reply, wrapped in SPNEGO.
616  Get vuid and check first.
617  End the NTLMSSP exchange context if we are OK/complete fail
618  This should be split into two functions, one to handle each
619  leg of the NTLM auth steps.
620 ***************************************************************************/
621
622 static void reply_spnego_ntlmssp(struct smb_request *req,
623                                  uint16 vuid,
624                                  AUTH_NTLMSSP_STATE **auth_ntlmssp_state,
625                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
626                                  const char *OID,
627                                  bool wrap)
628 {
629         DATA_BLOB response;
630         struct auth_serversupplied_info *server_info = NULL;
631
632         if (NT_STATUS_IS_OK(nt_status)) {
633                 server_info = (*auth_ntlmssp_state)->server_info;
634         } else {
635                 nt_status = do_map_to_guest(nt_status,
636                             &server_info,
637                             (*auth_ntlmssp_state)->ntlmssp_state->user,
638                             (*auth_ntlmssp_state)->ntlmssp_state->domain);
639         }
640
641         reply_outbuf(req, 4, 0);
642
643         SSVAL(req->outbuf, smb_uid, vuid);
644
645         if (NT_STATUS_IS_OK(nt_status)) {
646                 DATA_BLOB nullblob = data_blob_null;
647
648                 if (!is_partial_auth_vuid(vuid)) {
649                         nt_status = NT_STATUS_LOGON_FAILURE;
650                         goto out;
651                 }
652
653                 data_blob_free(&server_info->user_session_key);
654                 server_info->user_session_key =
655                         data_blob_talloc(
656                         server_info,
657                         (*auth_ntlmssp_state)->ntlmssp_state->session_key.data,
658                         (*auth_ntlmssp_state)->ntlmssp_state->session_key.length);
659
660                 /* register_existing_vuid keeps the server info */
661                 if (register_existing_vuid(vuid,
662                                 server_info, nullblob,
663                                 (*auth_ntlmssp_state)->ntlmssp_state->user) !=
664                                         vuid) {
665                         nt_status = NT_STATUS_LOGON_FAILURE;
666                         goto out;
667                 }
668
669                 (*auth_ntlmssp_state)->server_info = NULL;
670
671                 /* current_user_info is changed on new vuid */
672                 reload_services( True );
673
674                 SSVAL(req->outbuf, smb_vwv3, 0);
675
676                 if (server_info->guest) {
677                         SSVAL(req->outbuf,smb_vwv2,1);
678                 }
679
680                 sessionsetup_start_signing_engine(server_info,
681                                                   (uint8 *)req->inbuf);
682         }
683
684   out:
685
686         if (wrap) {
687                 response = spnego_gen_auth_response(ntlmssp_blob,
688                                 nt_status, OID);
689         } else {
690                 response = *ntlmssp_blob;
691         }
692
693         reply_sesssetup_blob(req, response, nt_status);
694         if (wrap) {
695                 data_blob_free(&response);
696         }
697
698         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
699            and the other end, that we are not finished yet. */
700
701         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
702                 /* NB. This is *NOT* an error case. JRA */
703                 auth_ntlmssp_end(auth_ntlmssp_state);
704                 if (!NT_STATUS_IS_OK(nt_status)) {
705                         /* Kill the intermediate vuid */
706                         invalidate_vuid(vuid);
707                 }
708         }
709 }
710
711 /****************************************************************************
712  Is this a krb5 mechanism ?
713 ****************************************************************************/
714
715 NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
716                 DATA_BLOB *pblob_out,
717                 char **kerb_mechOID)
718 {
719         char *OIDs[ASN1_MAX_OIDS];
720         int i;
721         NTSTATUS ret = NT_STATUS_OK;
722
723         *kerb_mechOID = NULL;
724
725         /* parse out the OIDs and the first sec blob */
726         if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
727                 return NT_STATUS_LOGON_FAILURE;
728         }
729
730         /* only look at the first OID for determining the mechToken --
731            according to RFC2478, we should choose the one we want
732            and renegotiate, but i smell a client bug here..
733
734            Problem observed when connecting to a member (samba box)
735            of an AD domain as a user in a Samba domain.  Samba member
736            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
737            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
738            NTLMSSP mechtoken.                 --jerry              */
739
740 #ifdef HAVE_KRB5
741         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
742             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
743                 *kerb_mechOID = SMB_STRDUP(OIDs[0]);
744                 if (*kerb_mechOID == NULL) {
745                         ret = NT_STATUS_NO_MEMORY;
746                 }
747         }
748 #endif
749
750         for (i=0;OIDs[i];i++) {
751                 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
752                 free(OIDs[i]);
753         }
754         return ret;
755 }
756
757 /****************************************************************************
758  Fall back from krb5 to NTLMSSP.
759 ****************************************************************************/
760
761 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
762                                                 uint16 vuid)
763 {
764         DATA_BLOB response;
765
766         reply_outbuf(req, 4, 0);
767         SSVAL(req->outbuf,smb_uid,vuid);
768
769         DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
770                 "but set to downgrade to NTLMSSP\n"));
771
772         response = spnego_gen_auth_response(NULL,
773                         NT_STATUS_MORE_PROCESSING_REQUIRED,
774                         OID_NTLMSSP);
775         reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
776         data_blob_free(&response);
777 }
778
779 /****************************************************************************
780  Reply to a session setup spnego negotiate packet.
781 ****************************************************************************/
782
783 static void reply_spnego_negotiate(struct smb_request *req,
784                                    uint16 vuid,
785                                    DATA_BLOB blob1,
786                                    AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
787 {
788         DATA_BLOB secblob;
789         DATA_BLOB chal;
790         char *kerb_mech = NULL;
791         NTSTATUS status;
792
793         status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
794         if (!NT_STATUS_IS_OK(status)) {
795                 /* Kill the intermediate vuid */
796                 invalidate_vuid(vuid);
797                 reply_nterror(req, nt_status_squash(status));
798                 return;
799         }
800
801         DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
802                                 (unsigned long)secblob.length));
803
804 #ifdef HAVE_KRB5
805         if (kerb_mech && ((lp_security()==SEC_ADS) ||
806                                 lp_use_kerberos_keytab()) ) {
807                 bool destroy_vuid = True;
808                 reply_spnego_kerberos(req, &secblob, kerb_mech,
809                                       vuid, &destroy_vuid);
810                 data_blob_free(&secblob);
811                 if (destroy_vuid) {
812                         /* Kill the intermediate vuid */
813                         invalidate_vuid(vuid);
814                 }
815                 SAFE_FREE(kerb_mech);
816                 return;
817         }
818 #endif
819
820         if (*auth_ntlmssp_state) {
821                 auth_ntlmssp_end(auth_ntlmssp_state);
822         }
823
824         if (kerb_mech) {
825                 data_blob_free(&secblob);
826                 /* The mechtoken is a krb5 ticket, but
827                  * we need to fall back to NTLM. */
828                 reply_spnego_downgrade_to_ntlmssp(req, vuid);
829                 SAFE_FREE(kerb_mech);
830                 return;
831         }
832
833         status = auth_ntlmssp_start(auth_ntlmssp_state);
834         if (!NT_STATUS_IS_OK(status)) {
835                 /* Kill the intermediate vuid */
836                 invalidate_vuid(vuid);
837                 reply_nterror(req, nt_status_squash(status));
838                 return;
839         }
840
841         status = auth_ntlmssp_update(*auth_ntlmssp_state,
842                                         secblob, &chal);
843
844         data_blob_free(&secblob);
845
846         reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
847                              &chal, status, OID_NTLMSSP, true);
848
849         data_blob_free(&chal);
850
851         /* already replied */
852         return;
853 }
854
855 /****************************************************************************
856  Reply to a session setup spnego auth packet.
857 ****************************************************************************/
858
859 static void reply_spnego_auth(struct smb_request *req,
860                               uint16 vuid,
861                               DATA_BLOB blob1,
862                               AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
863 {
864         DATA_BLOB auth = data_blob_null;
865         DATA_BLOB auth_reply = data_blob_null;
866         DATA_BLOB secblob = data_blob_null;
867         NTSTATUS status = NT_STATUS_LOGON_FAILURE;
868
869         if (!spnego_parse_auth(blob1, &auth)) {
870 #if 0
871                 file_save("auth.dat", blob1.data, blob1.length);
872 #endif
873                 /* Kill the intermediate vuid */
874                 invalidate_vuid(vuid);
875
876                 reply_nterror(req, nt_status_squash(
877                                       NT_STATUS_LOGON_FAILURE));
878                 return;
879         }
880
881         if (auth.data[0] == ASN1_APPLICATION(0)) {
882                 /* Might be a second negTokenTarg packet */
883                 char *kerb_mech = NULL;
884
885                 status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
886
887                 if (!NT_STATUS_IS_OK(status)) {
888                         /* Kill the intermediate vuid */
889                         invalidate_vuid(vuid);
890                         reply_nterror(req, nt_status_squash(status));
891                         return;
892                 }
893
894                 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
895                                 (unsigned long)secblob.length));
896 #ifdef HAVE_KRB5
897                 if (kerb_mech && ((lp_security()==SEC_ADS) ||
898                                         lp_use_kerberos_keytab()) ) {
899                         bool destroy_vuid = True;
900                         reply_spnego_kerberos(req, &secblob, kerb_mech,
901                                               vuid, &destroy_vuid);
902                         data_blob_free(&secblob);
903                         data_blob_free(&auth);
904                         if (destroy_vuid) {
905                                 /* Kill the intermediate vuid */
906                                 invalidate_vuid(vuid);
907                         }
908                         SAFE_FREE(kerb_mech);
909                         return;
910                 }
911 #endif
912                 /* Can't blunder into NTLMSSP auth if we have
913                  * a krb5 ticket. */
914
915                 if (kerb_mech) {
916                         /* Kill the intermediate vuid */
917                         invalidate_vuid(vuid);
918                         DEBUG(3,("reply_spnego_auth: network "
919                                 "misconfiguration, client sent us a "
920                                 "krb5 ticket and kerberos security "
921                                 "not enabled"));
922                         reply_nterror(req, nt_status_squash(
923                                         NT_STATUS_LOGON_FAILURE));
924                         SAFE_FREE(kerb_mech);
925                 }
926         }
927
928         /* If we get here it wasn't a negTokenTarg auth packet. */
929         data_blob_free(&secblob);
930
931         if (!*auth_ntlmssp_state) {
932                 status = auth_ntlmssp_start(auth_ntlmssp_state);
933                 if (!NT_STATUS_IS_OK(status)) {
934                         /* Kill the intermediate vuid */
935                         invalidate_vuid(vuid);
936                         reply_nterror(req, nt_status_squash(status));
937                         return;
938                 }
939         }
940
941         status = auth_ntlmssp_update(*auth_ntlmssp_state,
942                                         auth, &auth_reply);
943
944         data_blob_free(&auth);
945
946         /* Don't send the mechid as we've already sent this (RFC4178). */
947
948         reply_spnego_ntlmssp(req, vuid,
949                              auth_ntlmssp_state,
950                              &auth_reply, status, NULL, true);
951
952         data_blob_free(&auth_reply);
953
954         /* and tell smbd that we have already replied to this packet */
955         return;
956 }
957
958 /****************************************************************************
959  List to store partial SPNEGO auth fragments.
960 ****************************************************************************/
961
962 static struct pending_auth_data *pd_list;
963
964 /****************************************************************************
965  Delete an entry on the list.
966 ****************************************************************************/
967
968 static void delete_partial_auth(struct pending_auth_data *pad)
969 {
970         if (!pad) {
971                 return;
972         }
973         DLIST_REMOVE(pd_list, pad);
974         data_blob_free(&pad->partial_data);
975         SAFE_FREE(pad);
976 }
977
978 /****************************************************************************
979  Search for a partial SPNEGO auth fragment matching an smbpid.
980 ****************************************************************************/
981
982 static struct pending_auth_data *get_pending_auth_data(uint16 smbpid)
983 {
984         struct pending_auth_data *pad;
985
986         for (pad = pd_list; pad; pad = pad->next) {
987                 if (pad->smbpid == smbpid) {
988                         break;
989                 }
990         }
991         return pad;
992 }
993
994 /****************************************************************************
995  Check the size of an SPNEGO blob. If we need more return
996  NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
997  the blob to be more than 64k.
998 ****************************************************************************/
999
1000 static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid,
1001                 DATA_BLOB *pblob)
1002 {
1003         struct pending_auth_data *pad = NULL;
1004         ASN1_DATA data;
1005         size_t needed_len = 0;
1006
1007         pad = get_pending_auth_data(smbpid);
1008
1009         /* Ensure we have some data. */
1010         if (pblob->length == 0) {
1011                 /* Caller can cope. */
1012                 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
1013                 delete_partial_auth(pad);
1014                 return NT_STATUS_OK;
1015         }
1016
1017         /* Were we waiting for more data ? */
1018         if (pad) {
1019                 DATA_BLOB tmp_blob;
1020                 size_t copy_len = MIN(65536, pblob->length);
1021
1022                 /* Integer wrap paranoia.... */
1023
1024                 if (pad->partial_data.length + copy_len <
1025                                 pad->partial_data.length ||
1026                     pad->partial_data.length + copy_len < copy_len) {
1027
1028                         DEBUG(2,("check_spnego_blob_complete: integer wrap "
1029                                 "pad->partial_data.length = %u, "
1030                                 "copy_len = %u\n",
1031                                 (unsigned int)pad->partial_data.length,
1032                                 (unsigned int)copy_len ));
1033
1034                         delete_partial_auth(pad);
1035                         return NT_STATUS_INVALID_PARAMETER;
1036                 }
1037
1038                 DEBUG(10,("check_spnego_blob_complete: "
1039                         "pad->partial_data.length = %u, "
1040                         "pad->needed_len = %u, "
1041                         "copy_len = %u, "
1042                         "pblob->length = %u,\n",
1043                         (unsigned int)pad->partial_data.length,
1044                         (unsigned int)pad->needed_len,
1045                         (unsigned int)copy_len,
1046                         (unsigned int)pblob->length ));
1047
1048                 tmp_blob = data_blob(NULL,
1049                                 pad->partial_data.length + copy_len);
1050
1051                 /* Concatenate the two (up to copy_len) bytes. */
1052                 memcpy(tmp_blob.data,
1053                         pad->partial_data.data,
1054                         pad->partial_data.length);
1055                 memcpy(tmp_blob.data + pad->partial_data.length,
1056                         pblob->data,
1057                         copy_len);
1058
1059                 /* Replace the partial data. */
1060                 data_blob_free(&pad->partial_data);
1061                 pad->partial_data = tmp_blob;
1062                 ZERO_STRUCT(tmp_blob);
1063
1064                 /* Are we done ? */
1065                 if (pblob->length >= pad->needed_len) {
1066                         /* Yes, replace pblob. */
1067                         data_blob_free(pblob);
1068                         *pblob = pad->partial_data;
1069                         ZERO_STRUCT(pad->partial_data);
1070                         delete_partial_auth(pad);
1071                         return NT_STATUS_OK;
1072                 }
1073
1074                 /* Still need more data. */
1075                 pad->needed_len -= copy_len;
1076                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
1077         }
1078
1079         if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
1080             (pblob->data[0] != ASN1_CONTEXT(1))) {
1081                 /* Not something we can determine the
1082                  * length of.
1083                  */
1084                 return NT_STATUS_OK;
1085         }
1086
1087         /* This is a new SPNEGO sessionsetup - see if
1088          * the data given in this blob is enough.
1089          */
1090
1091         asn1_load(&data, *pblob);
1092         asn1_start_tag(&data, pblob->data[0]);
1093         if (data.has_error || data.nesting == NULL) {
1094                 asn1_free(&data);
1095                 /* Let caller catch. */
1096                 return NT_STATUS_OK;
1097         }
1098
1099         /* Integer wrap paranoia.... */
1100
1101         if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
1102             data.nesting->taglen + data.nesting->start < data.nesting->start) {
1103
1104                 DEBUG(2,("check_spnego_blob_complete: integer wrap "
1105                         "data.nesting->taglen = %u, "
1106                         "data.nesting->start = %u\n",
1107                         (unsigned int)data.nesting->taglen,
1108                         (unsigned int)data.nesting->start ));
1109
1110                 asn1_free(&data);
1111                 return NT_STATUS_INVALID_PARAMETER;
1112         }
1113
1114         /* Total length of the needed asn1 is the tag length
1115          * plus the current offset. */
1116
1117         needed_len = data.nesting->taglen + data.nesting->start;
1118         asn1_free(&data);
1119
1120         DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
1121                 "pblob->length = %u\n",
1122                 (unsigned int)needed_len,
1123                 (unsigned int)pblob->length ));
1124
1125         if (needed_len <= pblob->length) {
1126                 /* Nothing to do - blob is complete. */
1127                 return NT_STATUS_OK;
1128         }
1129
1130         /* Refuse the blob if it's bigger than 64k. */
1131         if (needed_len > 65536) {
1132                 DEBUG(2,("check_spnego_blob_complete: needed_len "
1133                         "too large (%u)\n",
1134                         (unsigned int)needed_len ));
1135                 return NT_STATUS_INVALID_PARAMETER;
1136         }
1137
1138         /* We must store this blob until complete. */
1139         if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1140                 return NT_STATUS_NO_MEMORY;
1141         }
1142         pad->needed_len = needed_len - pblob->length;
1143         pad->partial_data = data_blob(pblob->data, pblob->length);
1144         if (pad->partial_data.data == NULL) {
1145                 SAFE_FREE(pad);
1146                 return NT_STATUS_NO_MEMORY;
1147         }
1148         pad->smbpid = smbpid;
1149         pad->vuid = vuid;
1150         DLIST_ADD(pd_list, pad);
1151
1152         return NT_STATUS_MORE_PROCESSING_REQUIRED;
1153 }
1154
1155 /****************************************************************************
1156  Reply to a session setup command.
1157  conn POINTER CAN BE NULL HERE !
1158 ****************************************************************************/
1159
1160 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1161 {
1162         uint8 *p;
1163         DATA_BLOB blob1;
1164         size_t bufrem;
1165         fstring native_os, native_lanman, primary_domain;
1166         const char *p2;
1167         uint16 data_blob_len = SVAL(req->inbuf, smb_vwv7);
1168         enum remote_arch_types ra_type = get_remote_arch();
1169         int vuid = SVAL(req->inbuf,smb_uid);
1170         user_struct *vuser = NULL;
1171         NTSTATUS status = NT_STATUS_OK;
1172         uint16 smbpid = req->smbpid;
1173         uint16 smb_flag2 = req->flags2;
1174
1175         DEBUG(3,("Doing spnego session setup\n"));
1176
1177         if (global_client_caps == 0) {
1178                 global_client_caps = IVAL(req->inbuf,smb_vwv10);
1179
1180                 if (!(global_client_caps & CAP_STATUS32)) {
1181                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1182                 }
1183
1184         }
1185
1186         p = (uint8 *)smb_buf(req->inbuf);
1187
1188         if (data_blob_len == 0) {
1189                 /* an invalid request */
1190                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1191                 return;
1192         }
1193
1194         bufrem = smb_bufrem(req->inbuf, p);
1195         /* pull the spnego blob */
1196         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1197
1198 #if 0
1199         file_save("negotiate.dat", blob1.data, blob1.length);
1200 #endif
1201
1202         p2 = (char *)req->inbuf + smb_vwv13 + data_blob_len;
1203         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_os, p2,
1204                               sizeof(native_os), STR_TERMINATE);
1205         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, native_lanman, p2,
1206                               sizeof(native_lanman), STR_TERMINATE);
1207         p2 += srvstr_pull_buf(req->inbuf, smb_flag2, primary_domain, p2,
1208                               sizeof(primary_domain), STR_TERMINATE);
1209         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1210                 native_os, native_lanman, primary_domain));
1211
1212         if ( ra_type == RA_WIN2K ) {
1213                 /* Vista sets neither the OS or lanman strings */
1214
1215                 if ( !strlen(native_os) && !strlen(native_lanman) )
1216                         set_remote_arch(RA_VISTA);
1217
1218                 /* Windows 2003 doesn't set the native lanman string,
1219                    but does set primary domain which is a bug I think */
1220
1221                 if ( !strlen(native_lanman) ) {
1222                         ra_lanman_string( primary_domain );
1223                 } else {
1224                         ra_lanman_string( native_lanman );
1225                 }
1226         }
1227
1228         /* Did we get a valid vuid ? */
1229         if (!is_partial_auth_vuid(vuid)) {
1230                 /* No, then try and see if this is an intermediate sessionsetup
1231                  * for a large SPNEGO packet. */
1232                 struct pending_auth_data *pad = get_pending_auth_data(smbpid);
1233                 if (pad) {
1234                         DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1235                                 "pending vuid %u\n",
1236                                 (unsigned int)pad->vuid ));
1237                         vuid = pad->vuid;
1238                 }
1239         }
1240
1241         /* Do we have a valid vuid now ? */
1242         if (!is_partial_auth_vuid(vuid)) {
1243                 /* No, start a new authentication setup. */
1244                 vuid = register_initial_vuid();
1245                 if (vuid == UID_FIELD_INVALID) {
1246                         data_blob_free(&blob1);
1247                         reply_nterror(req, nt_status_squash(
1248                                               NT_STATUS_INVALID_PARAMETER));
1249                         return;
1250                 }
1251         }
1252
1253         vuser = get_partial_auth_user_struct(vuid);
1254         /* This MUST be valid. */
1255         if (!vuser) {
1256                 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1257         }
1258
1259         /* Large (greater than 4k) SPNEGO blobs are split into multiple
1260          * sessionsetup requests as the Windows limit on the security blob
1261          * field is 4k. Bug #4400. JRA.
1262          */
1263
1264         status = check_spnego_blob_complete(smbpid, vuid, &blob1);
1265         if (!NT_STATUS_IS_OK(status)) {
1266                 if (!NT_STATUS_EQUAL(status,
1267                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1268                         /* Real error - kill the intermediate vuid */
1269                         invalidate_vuid(vuid);
1270                 }
1271                 data_blob_free(&blob1);
1272                 reply_nterror(req, nt_status_squash(status));
1273                 return;
1274         }
1275
1276         if (blob1.data[0] == ASN1_APPLICATION(0)) {
1277
1278                 /* its a negTokenTarg packet */
1279
1280                 reply_spnego_negotiate(req, vuid, blob1,
1281                                        &vuser->auth_ntlmssp_state);
1282                 data_blob_free(&blob1);
1283                 return;
1284         }
1285
1286         if (blob1.data[0] == ASN1_CONTEXT(1)) {
1287
1288                 /* its a auth packet */
1289
1290                 reply_spnego_auth(req, vuid, blob1,
1291                                   &vuser->auth_ntlmssp_state);
1292                 data_blob_free(&blob1);
1293                 return;
1294         }
1295
1296         if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1297                 DATA_BLOB chal;
1298
1299                 if (!vuser->auth_ntlmssp_state) {
1300                         status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
1301                         if (!NT_STATUS_IS_OK(status)) {
1302                                 /* Kill the intermediate vuid */
1303                                 invalidate_vuid(vuid);
1304                                 data_blob_free(&blob1);
1305                                 reply_nterror(req, nt_status_squash(status));
1306                                 return;
1307                         }
1308                 }
1309
1310                 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1311                                                 blob1, &chal);
1312
1313                 data_blob_free(&blob1);
1314
1315                 reply_spnego_ntlmssp(req, vuid,
1316                                      &vuser->auth_ntlmssp_state,
1317                                      &chal, status, OID_NTLMSSP, false);
1318                 data_blob_free(&chal);
1319                 return;
1320         }
1321
1322         /* what sort of packet is this? */
1323         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1324
1325         data_blob_free(&blob1);
1326
1327         reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1328 }
1329
1330 /****************************************************************************
1331  On new VC == 0, shutdown *all* old connections and users.
1332  It seems that only NT4.x does this. At W2K and above (XP etc.).
1333  a new session setup with VC==0 is ignored.
1334 ****************************************************************************/
1335
1336 static int shutdown_other_smbds(struct db_record *rec,
1337                                 const struct connections_key *key,
1338                                 const struct connections_data *crec,
1339                                 void *private_data)
1340 {
1341         const char *ip = (const char *)private_data;
1342
1343         if (!process_exists(crec->pid)) {
1344                 return 0;
1345         }
1346
1347         if (procid_is_me(&crec->pid)) {
1348                 return 0;
1349         }
1350
1351         if (strcmp(ip, crec->addr) != 0) {
1352                 return 0;
1353         }
1354
1355         DEBUG(0,("shutdown_other_smbds: shutting down pid %d "
1356                  "(IP %s)\n", procid_to_pid(&crec->pid), ip));
1357
1358         messaging_send(smbd_messaging_context(), crec->pid, MSG_SHUTDOWN,
1359                        &data_blob_null);
1360         return 0;
1361 }
1362
1363 static void setup_new_vc_session(void)
1364 {
1365         char addr[INET6_ADDRSTRLEN];
1366
1367         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1368                 "compatible we would close all old resources.\n"));
1369 #if 0
1370         conn_close_all();
1371         invalidate_all_vuids();
1372 #endif
1373         if (lp_reset_on_zero_vc()) {
1374                 connections_forall(shutdown_other_smbds,
1375                         CONST_DISCARD(void *,
1376                         client_addr(get_client_fd(),addr,sizeof(addr))));
1377         }
1378 }
1379
1380 /****************************************************************************
1381  Reply to a session setup command.
1382 ****************************************************************************/
1383
1384 void reply_sesssetup_and_X(struct smb_request *req)
1385 {
1386         int sess_vuid;
1387         int smb_bufsize;
1388         DATA_BLOB lm_resp;
1389         DATA_BLOB nt_resp;
1390         DATA_BLOB plaintext_password;
1391         fstring user;
1392         fstring sub_user; /* Sainitised username for substituion */
1393         fstring domain;
1394         fstring native_os;
1395         fstring native_lanman;
1396         fstring primary_domain;
1397         static bool done_sesssetup = False;
1398         auth_usersupplied_info *user_info = NULL;
1399         auth_serversupplied_info *server_info = NULL;
1400         uint16 smb_flag2 = req->flags2;
1401
1402         NTSTATUS nt_status;
1403
1404         bool doencrypt = global_encrypted_passwords_negotiated;
1405
1406         START_PROFILE(SMBsesssetupX);
1407
1408         ZERO_STRUCT(lm_resp);
1409         ZERO_STRUCT(nt_resp);
1410         ZERO_STRUCT(plaintext_password);
1411
1412         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1413
1414         /* a SPNEGO session setup has 12 command words, whereas a normal
1415            NT1 session setup has 13. See the cifs spec. */
1416         if (req->wct == 12 &&
1417             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1418
1419                 if (!global_spnego_negotiated) {
1420                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1421                                  "at SPNEGO session setup when it was not "
1422                                  "negotiated.\n"));
1423                         reply_nterror(req, nt_status_squash(
1424                                               NT_STATUS_LOGON_FAILURE));
1425                         END_PROFILE(SMBsesssetupX);
1426                         return;
1427                 }
1428
1429                 if (SVAL(req->inbuf,smb_vwv4) == 0) {
1430                         setup_new_vc_session();
1431                 }
1432
1433                 reply_sesssetup_and_X_spnego(req);
1434                 END_PROFILE(SMBsesssetupX);
1435                 return;
1436         }
1437
1438         smb_bufsize = SVAL(req->inbuf,smb_vwv2);
1439
1440         if (Protocol < PROTOCOL_NT1) {
1441                 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1442
1443                 /* Never do NT status codes with protocols before NT1 as we
1444                  * don't get client caps. */
1445                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1446
1447                 if ((passlen1 > MAX_PASS_LEN)
1448                     || (passlen1 > smb_bufrem(req->inbuf,
1449                                               smb_buf(req->inbuf)))) {
1450                         reply_nterror(req, nt_status_squash(
1451                                               NT_STATUS_INVALID_PARAMETER));
1452                         END_PROFILE(SMBsesssetupX);
1453                         return;
1454                 }
1455
1456                 if (doencrypt) {
1457                         lm_resp = data_blob(smb_buf(req->inbuf), passlen1);
1458                 } else {
1459                         plaintext_password = data_blob(smb_buf(req->inbuf),
1460                                                        passlen1+1);
1461                         /* Ensure null termination */
1462                         plaintext_password.data[passlen1] = 0;
1463                 }
1464
1465                 srvstr_pull_buf(req->inbuf, req->flags2, user,
1466                                 smb_buf(req->inbuf)+passlen1, sizeof(user),
1467                                 STR_TERMINATE);
1468                 *domain = 0;
1469
1470         } else {
1471                 uint16 passlen1 = SVAL(req->inbuf,smb_vwv7);
1472                 uint16 passlen2 = SVAL(req->inbuf,smb_vwv8);
1473                 enum remote_arch_types ra_type = get_remote_arch();
1474                 char *p = smb_buf(req->inbuf);
1475                 char *save_p = smb_buf(req->inbuf);
1476                 uint16 byte_count;
1477
1478
1479                 if(global_client_caps == 0) {
1480                         global_client_caps = IVAL(req->inbuf,smb_vwv11);
1481
1482                         if (!(global_client_caps & CAP_STATUS32)) {
1483                                 remove_from_common_flags2(
1484                                                 FLAGS2_32_BIT_ERROR_CODES);
1485                         }
1486
1487                         /* client_caps is used as final determination if
1488                          * client is NT or Win95. This is needed to return
1489                          * the correct error codes in some circumstances.
1490                         */
1491
1492                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1493                                         ra_type == RA_WIN95) {
1494                                 if(!(global_client_caps & (CAP_NT_SMBS|
1495                                                         CAP_STATUS32))) {
1496                                         set_remote_arch( RA_WIN95);
1497                                 }
1498                         }
1499                 }
1500
1501                 if (!doencrypt) {
1502                         /* both Win95 and WinNT stuff up the password
1503                          * lengths for non-encrypting systems. Uggh.
1504
1505                            if passlen1==24 its a win95 system, and its setting
1506                            the password length incorrectly. Luckily it still
1507                            works with the default code because Win95 will null
1508                            terminate the password anyway
1509
1510                            if passlen1>0 and passlen2>0 then maybe its a NT box
1511                            and its setting passlen2 to some random value which
1512                            really stuffs things up. we need to fix that one.  */
1513
1514                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1515                                         passlen2 != 1) {
1516                                 passlen2 = 0;
1517                         }
1518                 }
1519
1520                 /* check for nasty tricks */
1521                 if (passlen1 > MAX_PASS_LEN
1522                     || passlen1 > smb_bufrem(req->inbuf, p)) {
1523                         reply_nterror(req, nt_status_squash(
1524                                               NT_STATUS_INVALID_PARAMETER));
1525                         END_PROFILE(SMBsesssetupX);
1526                         return;
1527                 }
1528
1529                 if (passlen2 > MAX_PASS_LEN
1530                     || passlen2 > smb_bufrem(req->inbuf, p+passlen1)) {
1531                         reply_nterror(req, nt_status_squash(
1532                                               NT_STATUS_INVALID_PARAMETER));
1533                         END_PROFILE(SMBsesssetupX);
1534                         return;
1535                 }
1536
1537                 /* Save the lanman2 password and the NT md4 password. */
1538
1539                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1540                         doencrypt = False;
1541                 }
1542
1543                 if (doencrypt) {
1544                         lm_resp = data_blob(p, passlen1);
1545                         nt_resp = data_blob(p+passlen1, passlen2);
1546                 } else if (lp_security() != SEC_SHARE) {
1547                         /*
1548                          * In share level we should ignore any passwords, so
1549                          * only read them if we're not.
1550                          */
1551                         char *pass = NULL;
1552                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1553
1554                         if (unic && (passlen2 == 0) && passlen1) {
1555                                 /* Only a ascii plaintext password was sent. */
1556                                 (void)srvstr_pull_talloc(talloc_tos(),
1557                                                         req->inbuf,
1558                                                         req->flags2,
1559                                                         &pass,
1560                                                         smb_buf(req->inbuf),
1561                                                         passlen1,
1562                                                         STR_TERMINATE|STR_ASCII);
1563                         } else {
1564                                 (void)srvstr_pull_talloc(talloc_tos(),
1565                                                         req->inbuf,
1566                                                         req->flags2,
1567                                                         &pass,
1568                                                         smb_buf(req->inbuf),
1569                                                         unic ? passlen2 : passlen1,
1570                                                         STR_TERMINATE);
1571                         }
1572                         if (!pass) {
1573                                 reply_nterror(req, nt_status_squash(
1574                                               NT_STATUS_INVALID_PARAMETER));
1575                                 END_PROFILE(SMBsesssetupX);
1576                                 return;
1577                         }
1578                         plaintext_password = data_blob(pass, strlen(pass)+1);
1579                 }
1580
1581                 p += passlen1 + passlen2;
1582                 p += srvstr_pull_buf(req->inbuf, req->flags2, user, p,
1583                                      sizeof(user), STR_TERMINATE);
1584                 p += srvstr_pull_buf(req->inbuf, req->flags2, domain, p,
1585                                      sizeof(domain), STR_TERMINATE);
1586                 p += srvstr_pull_buf(req->inbuf, req->flags2, native_os,
1587                                      p, sizeof(native_os), STR_TERMINATE);
1588                 p += srvstr_pull_buf(req->inbuf, req->flags2,
1589                                      native_lanman, p, sizeof(native_lanman),
1590                                      STR_TERMINATE);
1591
1592                 /* not documented or decoded by Ethereal but there is one more
1593                  * string in the extra bytes which is the same as the
1594                  * PrimaryDomain when using extended security.  Windows NT 4
1595                  * and 2003 use this string to store the native lanman string.
1596                  * Windows 9x does not include a string here at all so we have
1597                  * to check if we have any extra bytes left */
1598
1599                 byte_count = SVAL(req->inbuf, smb_vwv13);
1600                 if ( PTR_DIFF(p, save_p) < byte_count) {
1601                         p += srvstr_pull_buf(req->inbuf, req->flags2,
1602                                              primary_domain, p,
1603                                              sizeof(primary_domain),
1604                                              STR_TERMINATE);
1605                 } else {
1606                         fstrcpy( primary_domain, "null" );
1607                 }
1608
1609                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
1610                         "PrimaryDomain=[%s]\n",
1611                         domain, native_os, native_lanman, primary_domain));
1612
1613                 if ( ra_type == RA_WIN2K ) {
1614                         if ( strlen(native_lanman) == 0 )
1615                                 ra_lanman_string( primary_domain );
1616                         else
1617                                 ra_lanman_string( native_lanman );
1618                 }
1619
1620         }
1621
1622         if (SVAL(req->inbuf,smb_vwv4) == 0) {
1623                 setup_new_vc_session();
1624         }
1625
1626         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1627                                 domain, user, get_remote_machine_name()));
1628
1629         if (*user) {
1630                 if (global_spnego_negotiated) {
1631
1632                         /* This has to be here, because this is a perfectly
1633                          * valid behaviour for guest logons :-( */
1634
1635                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1636                                 "at 'normal' session setup after "
1637                                 "negotiating spnego.\n"));
1638                         reply_nterror(req, nt_status_squash(
1639                                               NT_STATUS_LOGON_FAILURE));
1640                         END_PROFILE(SMBsesssetupX);
1641                         return;
1642                 }
1643                 fstrcpy(sub_user, user);
1644         } else {
1645                 fstrcpy(sub_user, lp_guestaccount());
1646         }
1647
1648         sub_set_smb_name(sub_user);
1649
1650         reload_services(True);
1651
1652         if (lp_security() == SEC_SHARE) {
1653                 /* In share level we should ignore any passwords */
1654
1655                 data_blob_free(&lm_resp);
1656                 data_blob_free(&nt_resp);
1657                 data_blob_clear_free(&plaintext_password);
1658
1659                 map_username(sub_user);
1660                 add_session_user(sub_user);
1661                 add_session_workgroup(domain);
1662                 /* Then force it to null for the benfit of the code below */
1663                 *user = 0;
1664         }
1665
1666         if (!*user) {
1667
1668                 nt_status = check_guest_password(&server_info);
1669
1670         } else if (doencrypt) {
1671                 if (!negprot_global_auth_context) {
1672                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
1673                                 "session setup without negprot denied!\n"));
1674                         reply_nterror(req, nt_status_squash(
1675                                               NT_STATUS_LOGON_FAILURE));
1676                         END_PROFILE(SMBsesssetupX);
1677                         return;
1678                 }
1679                 nt_status = make_user_info_for_reply_enc(&user_info, user,
1680                                                 domain,
1681                                                 lm_resp, nt_resp);
1682                 if (NT_STATUS_IS_OK(nt_status)) {
1683                         nt_status = negprot_global_auth_context->check_ntlm_password(
1684                                         negprot_global_auth_context,
1685                                         user_info,
1686                                         &server_info);
1687                 }
1688         } else {
1689                 struct auth_context *plaintext_auth_context = NULL;
1690                 const uint8 *chal;
1691
1692                 nt_status = make_auth_context_subsystem(
1693                                 &plaintext_auth_context);
1694
1695                 if (NT_STATUS_IS_OK(nt_status)) {
1696                         chal = plaintext_auth_context->get_ntlm_challenge(
1697                                         plaintext_auth_context);
1698
1699                         if (!make_user_info_for_reply(&user_info,
1700                                                       user, domain, chal,
1701                                                       plaintext_password)) {
1702                                 nt_status = NT_STATUS_NO_MEMORY;
1703                         }
1704
1705                         if (NT_STATUS_IS_OK(nt_status)) {
1706                                 nt_status = plaintext_auth_context->check_ntlm_password(
1707                                                 plaintext_auth_context,
1708                                                 user_info,
1709                                                 &server_info);
1710
1711                                 (plaintext_auth_context->free)(
1712                                                 &plaintext_auth_context);
1713                         }
1714                 }
1715         }
1716
1717         free_user_info(&user_info);
1718
1719         if (!NT_STATUS_IS_OK(nt_status)) {
1720                 nt_status = do_map_to_guest(nt_status, &server_info,
1721                                 user, domain);
1722         }
1723
1724         if (!NT_STATUS_IS_OK(nt_status)) {
1725                 data_blob_free(&nt_resp);
1726                 data_blob_free(&lm_resp);
1727                 data_blob_clear_free(&plaintext_password);
1728                 reply_nterror(req, nt_status_squash(nt_status));
1729                 END_PROFILE(SMBsesssetupX);
1730                 return;
1731         }
1732
1733         /* Ensure we can't possible take a code path leading to a
1734          * null defref. */
1735         if (!server_info) {
1736                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1737                 END_PROFILE(SMBsesssetupX);
1738                 return;
1739         }
1740
1741         nt_status = create_local_token(server_info);
1742         if (!NT_STATUS_IS_OK(nt_status)) {
1743                 DEBUG(10, ("create_local_token failed: %s\n",
1744                            nt_errstr(nt_status)));
1745                 data_blob_free(&nt_resp);
1746                 data_blob_free(&lm_resp);
1747                 data_blob_clear_free(&plaintext_password);
1748                 reply_nterror(req, nt_status_squash(nt_status));
1749                 END_PROFILE(SMBsesssetupX);
1750                 return;
1751         }
1752
1753         data_blob_clear_free(&plaintext_password);
1754
1755         /* it's ok - setup a reply */
1756         reply_outbuf(req, 3, 0);
1757         if (Protocol >= PROTOCOL_NT1) {
1758                 push_signature(&req->outbuf);
1759                 /* perhaps grab OS version here?? */
1760         }
1761
1762         if (server_info->guest) {
1763                 SSVAL(req->outbuf,smb_vwv2,1);
1764         }
1765
1766         /* register the name and uid as being validated, so further connections
1767            to a uid can get through without a password, on the same VC */
1768
1769         if (lp_security() == SEC_SHARE) {
1770                 sess_vuid = UID_FIELD_INVALID;
1771                 TALLOC_FREE(server_info);
1772         } else {
1773                 /* Ignore the initial vuid. */
1774                 sess_vuid = register_initial_vuid();
1775                 if (sess_vuid == UID_FIELD_INVALID) {
1776                         data_blob_free(&nt_resp);
1777                         data_blob_free(&lm_resp);
1778                         reply_nterror(req, nt_status_squash(
1779                                               NT_STATUS_LOGON_FAILURE));
1780                         END_PROFILE(SMBsesssetupX);
1781                         return;
1782                 }
1783                 /* register_existing_vuid keeps the server info */
1784                 sess_vuid = register_existing_vuid(sess_vuid,
1785                                         server_info,
1786                                         nt_resp.data ? nt_resp : lm_resp,
1787                                         sub_user);
1788                 if (sess_vuid == UID_FIELD_INVALID) {
1789                         data_blob_free(&nt_resp);
1790                         data_blob_free(&lm_resp);
1791                         reply_nterror(req, nt_status_squash(
1792                                               NT_STATUS_LOGON_FAILURE));
1793                         END_PROFILE(SMBsesssetupX);
1794                         return;
1795                 }
1796
1797                 /* current_user_info is changed on new vuid */
1798                 reload_services( True );
1799
1800                 sessionsetup_start_signing_engine(server_info, req->inbuf);
1801         }
1802
1803         data_blob_free(&nt_resp);
1804         data_blob_free(&lm_resp);
1805
1806         SSVAL(req->outbuf,smb_uid,sess_vuid);
1807         SSVAL(req->inbuf,smb_uid,sess_vuid);
1808
1809         if (!done_sesssetup)
1810                 max_send = MIN(max_send,smb_bufsize);
1811
1812         done_sesssetup = True;
1813
1814         END_PROFILE(SMBsesssetupX);
1815         chain_reply(req);
1816         return;
1817 }