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