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