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