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