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