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