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