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