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