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