2cf32c9b9a409cac2a7e9e5edbc7ffc4f22155be
[abartlet/samba.git/.git] / source3 / smbd / sesssetup.c
1 /*
2    Unix SMB/CIFS implementation.
3    handle SMBsessionsetup
4    Copyright (C) Andrew Tridgell 1998-2001
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7    Copyright (C) Luke Howard          2003
8    Copyright (C) Volker Lendecke      2007
9    Copyright (C) Jeremy Allison       2007
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "smbd/globals.h"
27 #include "../libcli/auth/spnego.h"
28 #include "../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 = smbd_server_conn;
256
257         ZERO_STRUCT(ticket);
258         ZERO_STRUCT(ap_rep);
259         ZERO_STRUCT(ap_rep_wrapped);
260         ZERO_STRUCT(response);
261
262         /* Normally we will always invalidate the intermediate vuid. */
263         *p_invalidate_vuid = True;
264
265         mem_ctx = talloc_init("reply_spnego_kerberos");
266         if (mem_ctx == NULL) {
267                 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
268                 return;
269         }
270
271         if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) {
272                 talloc_destroy(mem_ctx);
273                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
274                 return;
275         }
276
277         ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
278                                 &client, &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         session_key = data_blob_null;
565
566         /* register_existing_vuid keeps the server info */
567         /* register_existing_vuid takes ownership of session_key on success,
568          * no need to free after this on success. A better interface would copy
569          * it.... */
570
571         sess_vuid = register_existing_vuid(sconn,
572                                         sess_vuid,
573                                         server_info,
574                                         nullblob,
575                                         client);
576
577         reply_outbuf(req, 4, 0);
578         SSVAL(req->outbuf,smb_uid,sess_vuid);
579
580         if (sess_vuid == UID_FIELD_INVALID ) {
581                 ret = NT_STATUS_LOGON_FAILURE;
582         } else {
583                 /* current_user_info is changed on new vuid */
584                 reload_services( True );
585
586                 SSVAL(req->outbuf, smb_vwv3, 0);
587
588                 if (server_info->guest) {
589                         SSVAL(req->outbuf,smb_vwv2,1);
590                 }
591
592                 SSVAL(req->outbuf, smb_uid, sess_vuid);
593
594                 /* Successful logon. Keep this vuid. */
595                 *p_invalidate_vuid = False;
596         }
597
598         /* wrap that up in a nice GSS-API wrapping */
599         if (NT_STATUS_IS_OK(ret)) {
600                 ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
601                                 TOK_ID_KRB_AP_REP);
602         } else {
603                 ap_rep_wrapped = data_blob_null;
604         }
605         response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
606                         mechOID);
607         reply_sesssetup_blob(req, response, ret);
608
609         data_blob_free(&ap_rep);
610         data_blob_free(&ap_rep_wrapped);
611         data_blob_free(&response);
612         TALLOC_FREE(mem_ctx);
613 }
614
615 #endif
616
617 /****************************************************************************
618  Send a session setup reply, wrapped in SPNEGO.
619  Get vuid and check first.
620  End the NTLMSSP exchange context if we are OK/complete fail
621  This should be split into two functions, one to handle each
622  leg of the NTLM auth steps.
623 ***************************************************************************/
624
625 static void reply_spnego_ntlmssp(struct smb_request *req,
626                                  uint16 vuid,
627                                  struct auth_ntlmssp_state **auth_ntlmssp_state,
628                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
629                                  const char *OID,
630                                  bool wrap)
631 {
632         bool do_invalidate = true;
633         DATA_BLOB response;
634         struct auth_serversupplied_info *server_info = NULL;
635         struct smbd_server_connection *sconn = smbd_server_conn;
636
637         if (NT_STATUS_IS_OK(nt_status)) {
638                 nt_status = auth_ntlmssp_server_info(talloc_tos(), (*auth_ntlmssp_state), &server_info);
639         } else {
640                 /* Note that this server_info won't have a session
641                  * key.  But for map to guest, that's exactly the right
642                  * thing - we can't reasonably guess the key the
643                  * client wants, as the password was wrong */
644                 nt_status = do_map_to_guest(nt_status,
645                                             &server_info,
646                                             auth_ntlmssp_get_username(*auth_ntlmssp_state),
647                                             auth_ntlmssp_get_domain(*auth_ntlmssp_state));
648         }
649
650         reply_outbuf(req, 4, 0);
651
652         SSVAL(req->outbuf, smb_uid, vuid);
653
654         if (NT_STATUS_IS_OK(nt_status)) {
655                 DATA_BLOB nullblob = data_blob_null;
656
657                 if (!is_partial_auth_vuid(sconn, vuid)) {
658                         nt_status = NT_STATUS_LOGON_FAILURE;
659                         goto out;
660                 }
661
662                 /* register_existing_vuid keeps the server info */
663                 if (register_existing_vuid(sconn, vuid,
664                                            server_info, nullblob,
665                                            auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
666                                            vuid) {
667                         /* The problem is, *auth_ntlmssp_state points
668                          * into the vuser this will have
669                          * talloc_free()'ed in
670                          * register_existing_vuid() */
671                         do_invalidate = false;
672                         nt_status = NT_STATUS_LOGON_FAILURE;
673                         goto out;
674                 }
675
676                 /* current_user_info is changed on new vuid */
677                 reload_services( True );
678
679                 SSVAL(req->outbuf, smb_vwv3, 0);
680
681                 if (server_info->guest) {
682                         SSVAL(req->outbuf,smb_vwv2,1);
683                 }
684         }
685
686   out:
687
688         if (wrap) {
689                 response = spnego_gen_auth_response(ntlmssp_blob,
690                                 nt_status, OID);
691         } else {
692                 response = *ntlmssp_blob;
693         }
694
695         reply_sesssetup_blob(req, response, nt_status);
696         if (wrap) {
697                 data_blob_free(&response);
698         }
699
700         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
701            and the other end, that we are not finished yet. */
702
703         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
704                 /* NB. This is *NOT* an error case. JRA */
705                 if (do_invalidate) {
706                         auth_ntlmssp_end(auth_ntlmssp_state);
707                         if (!NT_STATUS_IS_OK(nt_status)) {
708                                 /* Kill the intermediate vuid */
709                                 invalidate_vuid(sconn, vuid);
710                         }
711                 }
712         }
713 }
714
715 /****************************************************************************
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                                    struct 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                               struct 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(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 }