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