s3-auth: Added remote_address to ntlmssp server.
[mat/samba.git] / source3 / smbd / sesssetup.c
1 /*
2    Unix SMB/CIFS implementation.
3    handle SMBsessionsetup
4    Copyright (C) Andrew Tridgell 1998-2001
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7    Copyright (C) Luke Howard          2003
8    Copyright (C) Volker Lendecke      2007
9    Copyright (C) Jeremy Allison       2007
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "../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(sconn->remote_address,
666                                     auth_ntlmssp_state);
667         if (!NT_STATUS_IS_OK(status)) {
668                 /* Kill the intermediate vuid */
669                 invalidate_vuid(sconn, vuid);
670                 reply_nterror(req, nt_status_squash(status));
671                 return;
672         }
673
674         status = auth_ntlmssp_update(*auth_ntlmssp_state,
675                                         secblob, &chal);
676
677         data_blob_free(&secblob);
678
679         reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
680                              &chal, status, OID_NTLMSSP, true);
681
682         data_blob_free(&chal);
683
684         /* already replied */
685         return;
686 }
687
688 /****************************************************************************
689  Reply to a session setup spnego auth packet.
690 ****************************************************************************/
691
692 static void reply_spnego_auth(struct smb_request *req,
693                               uint16 vuid,
694                               DATA_BLOB blob1,
695                               struct auth_ntlmssp_state **auth_ntlmssp_state)
696 {
697         DATA_BLOB auth = data_blob_null;
698         DATA_BLOB auth_reply = data_blob_null;
699         DATA_BLOB secblob = data_blob_null;
700         NTSTATUS status = NT_STATUS_LOGON_FAILURE;
701         struct smbd_server_connection *sconn = req->sconn;
702
703         if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
704 #if 0
705                 file_save("auth.dat", blob1.data, blob1.length);
706 #endif
707                 /* Kill the intermediate vuid */
708                 invalidate_vuid(sconn, vuid);
709
710                 reply_nterror(req, nt_status_squash(
711                                       NT_STATUS_LOGON_FAILURE));
712                 return;
713         }
714
715         if (auth.data[0] == ASN1_APPLICATION(0)) {
716                 /* Might be a second negTokenTarg packet */
717                 char *kerb_mech = NULL;
718
719                 status = parse_spnego_mechanisms(talloc_tos(),
720                                 auth, &secblob, &kerb_mech);
721
722                 if (!NT_STATUS_IS_OK(status)) {
723                         /* Kill the intermediate vuid */
724                         invalidate_vuid(sconn, vuid);
725                         reply_nterror(req, nt_status_squash(status));
726                         return;
727                 }
728
729                 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
730                                 (unsigned long)secblob.length));
731 #ifdef HAVE_KRB5
732                 if (kerb_mech && ((lp_security()==SEC_ADS) ||
733                                         USE_KERBEROS_KEYTAB)) {
734                         bool destroy_vuid = True;
735                         reply_spnego_kerberos(req, &secblob, kerb_mech,
736                                               vuid, &destroy_vuid);
737                         data_blob_free(&secblob);
738                         data_blob_free(&auth);
739                         if (destroy_vuid) {
740                                 /* Kill the intermediate vuid */
741                                 invalidate_vuid(sconn, vuid);
742                         }
743                         TALLOC_FREE(kerb_mech);
744                         return;
745                 }
746 #endif
747                 /* Can't blunder into NTLMSSP auth if we have
748                  * a krb5 ticket. */
749
750                 if (kerb_mech) {
751                         /* Kill the intermediate vuid */
752                         invalidate_vuid(sconn, vuid);
753                         DEBUG(3,("reply_spnego_auth: network "
754                                 "misconfiguration, client sent us a "
755                                 "krb5 ticket and kerberos security "
756                                 "not enabled\n"));
757                         reply_nterror(req, nt_status_squash(
758                                         NT_STATUS_LOGON_FAILURE));
759                         TALLOC_FREE(kerb_mech);
760                 }
761         }
762
763         /* If we get here it wasn't a negTokenTarg auth packet. */
764         data_blob_free(&secblob);
765
766         if (!*auth_ntlmssp_state) {
767                 status = auth_ntlmssp_start(sconn->remote_address,
768                                             auth_ntlmssp_state);
769                 if (!NT_STATUS_IS_OK(status)) {
770                         /* Kill the intermediate vuid */
771                         invalidate_vuid(sconn, vuid);
772                         reply_nterror(req, nt_status_squash(status));
773                         return;
774                 }
775         }
776
777         status = auth_ntlmssp_update(*auth_ntlmssp_state,
778                                         auth, &auth_reply);
779
780         data_blob_free(&auth);
781
782         /* Don't send the mechid as we've already sent this (RFC4178). */
783
784         reply_spnego_ntlmssp(req, vuid,
785                              auth_ntlmssp_state,
786                              &auth_reply, status, NULL, true);
787
788         data_blob_free(&auth_reply);
789
790         /* and tell smbd that we have already replied to this packet */
791         return;
792 }
793
794 /****************************************************************************
795  Delete an entry on the list.
796 ****************************************************************************/
797
798 static void delete_partial_auth(struct smbd_server_connection *sconn,
799                                 struct pending_auth_data *pad)
800 {
801         if (!pad) {
802                 return;
803         }
804         DLIST_REMOVE(sconn->smb1.pd_list, pad);
805         data_blob_free(&pad->partial_data);
806         SAFE_FREE(pad);
807 }
808
809 /****************************************************************************
810  Search for a partial SPNEGO auth fragment matching an smbpid.
811 ****************************************************************************/
812
813 static struct pending_auth_data *get_pending_auth_data(
814                 struct smbd_server_connection *sconn,
815                 uint16_t smbpid)
816 {
817         struct pending_auth_data *pad;
818 /*
819  * NOTE: using the smbpid here is completely wrong...
820  *       see [MS-SMB]
821  *       3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
822  */
823         for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
824                 if (pad->smbpid == smbpid) {
825                         break;
826                 }
827         }
828         return pad;
829 }
830
831 /****************************************************************************
832  Check the size of an SPNEGO blob. If we need more return
833  NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
834  the blob to be more than 64k.
835 ****************************************************************************/
836
837 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
838                                            uint16 smbpid, uint16 vuid,
839                                            DATA_BLOB *pblob)
840 {
841         struct pending_auth_data *pad = NULL;
842         ASN1_DATA *data;
843         size_t needed_len = 0;
844
845         pad = get_pending_auth_data(sconn, smbpid);
846
847         /* Ensure we have some data. */
848         if (pblob->length == 0) {
849                 /* Caller can cope. */
850                 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
851                 delete_partial_auth(sconn, pad);
852                 return NT_STATUS_OK;
853         }
854
855         /* Were we waiting for more data ? */
856         if (pad) {
857                 DATA_BLOB tmp_blob;
858                 size_t copy_len = MIN(65536, pblob->length);
859
860                 /* Integer wrap paranoia.... */
861
862                 if (pad->partial_data.length + copy_len <
863                                 pad->partial_data.length ||
864                     pad->partial_data.length + copy_len < copy_len) {
865
866                         DEBUG(2,("check_spnego_blob_complete: integer wrap "
867                                 "pad->partial_data.length = %u, "
868                                 "copy_len = %u\n",
869                                 (unsigned int)pad->partial_data.length,
870                                 (unsigned int)copy_len ));
871
872                         delete_partial_auth(sconn, pad);
873                         return NT_STATUS_INVALID_PARAMETER;
874                 }
875
876                 DEBUG(10,("check_spnego_blob_complete: "
877                         "pad->partial_data.length = %u, "
878                         "pad->needed_len = %u, "
879                         "copy_len = %u, "
880                         "pblob->length = %u,\n",
881                         (unsigned int)pad->partial_data.length,
882                         (unsigned int)pad->needed_len,
883                         (unsigned int)copy_len,
884                         (unsigned int)pblob->length ));
885
886                 tmp_blob = data_blob(NULL,
887                                 pad->partial_data.length + copy_len);
888
889                 /* Concatenate the two (up to copy_len) bytes. */
890                 memcpy(tmp_blob.data,
891                         pad->partial_data.data,
892                         pad->partial_data.length);
893                 memcpy(tmp_blob.data + pad->partial_data.length,
894                         pblob->data,
895                         copy_len);
896
897                 /* Replace the partial data. */
898                 data_blob_free(&pad->partial_data);
899                 pad->partial_data = tmp_blob;
900                 ZERO_STRUCT(tmp_blob);
901
902                 /* Are we done ? */
903                 if (pblob->length >= pad->needed_len) {
904                         /* Yes, replace pblob. */
905                         data_blob_free(pblob);
906                         *pblob = pad->partial_data;
907                         ZERO_STRUCT(pad->partial_data);
908                         delete_partial_auth(sconn, pad);
909                         return NT_STATUS_OK;
910                 }
911
912                 /* Still need more data. */
913                 pad->needed_len -= copy_len;
914                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
915         }
916
917         if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
918             (pblob->data[0] != ASN1_CONTEXT(1))) {
919                 /* Not something we can determine the
920                  * length of.
921                  */
922                 return NT_STATUS_OK;
923         }
924
925         /* This is a new SPNEGO sessionsetup - see if
926          * the data given in this blob is enough.
927          */
928
929         data = asn1_init(NULL);
930         if (data == NULL) {
931                 return NT_STATUS_NO_MEMORY;
932         }
933
934         asn1_load(data, *pblob);
935         if (asn1_start_tag(data, pblob->data[0])) {
936                 /* asn1_start_tag checks if the given
937                    length of the blob is enough to complete
938                    the tag. If it returns true we know
939                    there is nothing to do - the blob is
940                    complete. */
941                 asn1_free(data);
942                 return NT_STATUS_OK;
943         }
944
945         if (data->nesting == NULL) {
946                 /* Incorrect tag, allocation failed,
947                    or reading the tag length failed.
948                    Let the caller catch. */
949                 asn1_free(data);
950                 return NT_STATUS_OK;
951         }
952
953         /* Here we know asn1_start_tag() has set data->has_error to true.
954            asn1_tag_remaining() will have failed due to the given blob
955            being too short. We need to work out how short. */
956
957         /* Integer wrap paranoia.... */
958
959         if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
960             data->nesting->taglen + data->nesting->start < data->nesting->start) {
961
962                 DEBUG(2,("check_spnego_blob_complete: integer wrap "
963                         "data.nesting->taglen = %u, "
964                         "data.nesting->start = %u\n",
965                         (unsigned int)data->nesting->taglen,
966                         (unsigned int)data->nesting->start ));
967
968                 asn1_free(data);
969                 return NT_STATUS_INVALID_PARAMETER;
970         }
971
972         /* Total length of the needed asn1 is the tag length
973          * plus the current offset. */
974
975         needed_len = data->nesting->taglen + data->nesting->start;
976         asn1_free(data);
977
978         DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
979                 "pblob->length = %u\n",
980                 (unsigned int)needed_len,
981                 (unsigned int)pblob->length ));
982
983         if (needed_len <= pblob->length) {
984                 /* Nothing to do - blob is complete. */
985                 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
986                    above should have caught this !!! */
987                 DEBUG(0,("check_spnego_blob_complete: logic "
988                         "error (needed_len = %u, "
989                         "pblob->length = %u).\n",
990                         (unsigned int)needed_len,
991                         (unsigned int)pblob->length ));
992                 return NT_STATUS_OK;
993         }
994
995         /* Refuse the blob if it's bigger than 64k. */
996         if (needed_len > 65536) {
997                 DEBUG(2,("check_spnego_blob_complete: needed_len "
998                         "too large (%u)\n",
999                         (unsigned int)needed_len ));
1000                 return NT_STATUS_INVALID_PARAMETER;
1001         }
1002
1003         /* We must store this blob until complete. */
1004         if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
1005                 return NT_STATUS_NO_MEMORY;
1006         }
1007         pad->needed_len = needed_len - pblob->length;
1008         pad->partial_data = data_blob(pblob->data, pblob->length);
1009         if (pad->partial_data.data == NULL) {
1010                 SAFE_FREE(pad);
1011                 return NT_STATUS_NO_MEMORY;
1012         }
1013         pad->smbpid = smbpid;
1014         pad->vuid = vuid;
1015         DLIST_ADD(sconn->smb1.pd_list, pad);
1016
1017         return NT_STATUS_MORE_PROCESSING_REQUIRED;
1018 }
1019
1020 /****************************************************************************
1021  Reply to a session setup command.
1022  conn POINTER CAN BE NULL HERE !
1023 ****************************************************************************/
1024
1025 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
1026 {
1027         const uint8 *p;
1028         DATA_BLOB blob1;
1029         size_t bufrem;
1030         char *tmp;
1031         const char *native_os;
1032         const char *native_lanman;
1033         const char *primary_domain;
1034         const char *p2;
1035         uint16 data_blob_len = SVAL(req->vwv+7, 0);
1036         enum remote_arch_types ra_type = get_remote_arch();
1037         int vuid = req->vuid;
1038         user_struct *vuser = NULL;
1039         NTSTATUS status = NT_STATUS_OK;
1040         uint16 smbpid = req->smbpid;
1041         struct smbd_server_connection *sconn = req->sconn;
1042
1043         DEBUG(3,("Doing spnego session setup\n"));
1044
1045         if (global_client_caps == 0) {
1046                 global_client_caps = IVAL(req->vwv+10, 0);
1047
1048                 if (!(global_client_caps & CAP_STATUS32)) {
1049                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1050                 }
1051
1052         }
1053
1054         p = req->buf;
1055
1056         if (data_blob_len == 0) {
1057                 /* an invalid request */
1058                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1059                 return;
1060         }
1061
1062         bufrem = smbreq_bufrem(req, p);
1063         /* pull the spnego blob */
1064         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1065
1066 #if 0
1067         file_save("negotiate.dat", blob1.data, blob1.length);
1068 #endif
1069
1070         p2 = (const char *)req->buf + blob1.length;
1071
1072         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1073                                      STR_TERMINATE);
1074         native_os = tmp ? tmp : "";
1075
1076         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1077                                      STR_TERMINATE);
1078         native_lanman = tmp ? tmp : "";
1079
1080         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1081                                      STR_TERMINATE);
1082         primary_domain = tmp ? tmp : "";
1083
1084         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1085                 native_os, native_lanman, primary_domain));
1086
1087         if ( ra_type == RA_WIN2K ) {
1088                 /* Vista sets neither the OS or lanman strings */
1089
1090                 if ( !strlen(native_os) && !strlen(native_lanman) )
1091                         set_remote_arch(RA_VISTA);
1092
1093                 /* Windows 2003 doesn't set the native lanman string,
1094                    but does set primary domain which is a bug I think */
1095
1096                 if ( !strlen(native_lanman) ) {
1097                         ra_lanman_string( primary_domain );
1098                 } else {
1099                         ra_lanman_string( native_lanman );
1100                 }
1101         } else if ( ra_type == RA_VISTA ) {
1102                 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1103                         set_remote_arch(RA_OSX);
1104                 }
1105         }
1106
1107         /* Did we get a valid vuid ? */
1108         if (!is_partial_auth_vuid(sconn, vuid)) {
1109                 /* No, then try and see if this is an intermediate sessionsetup
1110                  * for a large SPNEGO packet. */
1111                 struct pending_auth_data *pad;
1112                 pad = get_pending_auth_data(sconn, smbpid);
1113                 if (pad) {
1114                         DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1115                                 "pending vuid %u\n",
1116                                 (unsigned int)pad->vuid ));
1117                         vuid = pad->vuid;
1118                 }
1119         }
1120
1121         /* Do we have a valid vuid now ? */
1122         if (!is_partial_auth_vuid(sconn, vuid)) {
1123                 /* No, start a new authentication setup. */
1124                 vuid = register_initial_vuid(sconn);
1125                 if (vuid == UID_FIELD_INVALID) {
1126                         data_blob_free(&blob1);
1127                         reply_nterror(req, nt_status_squash(
1128                                               NT_STATUS_INVALID_PARAMETER));
1129                         return;
1130                 }
1131         }
1132
1133         vuser = get_partial_auth_user_struct(sconn, vuid);
1134         /* This MUST be valid. */
1135         if (!vuser) {
1136                 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1137         }
1138
1139         /* Large (greater than 4k) SPNEGO blobs are split into multiple
1140          * sessionsetup requests as the Windows limit on the security blob
1141          * field is 4k. Bug #4400. JRA.
1142          */
1143
1144         status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1145         if (!NT_STATUS_IS_OK(status)) {
1146                 if (!NT_STATUS_EQUAL(status,
1147                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1148                         /* Real error - kill the intermediate vuid */
1149                         invalidate_vuid(sconn, vuid);
1150                 }
1151                 data_blob_free(&blob1);
1152                 reply_nterror(req, nt_status_squash(status));
1153                 return;
1154         }
1155
1156         if (blob1.data[0] == ASN1_APPLICATION(0)) {
1157
1158                 /* its a negTokenTarg packet */
1159
1160                 reply_spnego_negotiate(req, vuid, blob1,
1161                                        &vuser->auth_ntlmssp_state);
1162                 data_blob_free(&blob1);
1163                 return;
1164         }
1165
1166         if (blob1.data[0] == ASN1_CONTEXT(1)) {
1167
1168                 /* its a auth packet */
1169
1170                 reply_spnego_auth(req, vuid, blob1,
1171                                   &vuser->auth_ntlmssp_state);
1172                 data_blob_free(&blob1);
1173                 return;
1174         }
1175
1176         if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1177                 DATA_BLOB chal;
1178
1179                 if (!vuser->auth_ntlmssp_state) {
1180                         status = auth_ntlmssp_start(sconn->remote_address,
1181                                                     &vuser->auth_ntlmssp_state);
1182                         if (!NT_STATUS_IS_OK(status)) {
1183                                 /* Kill the intermediate vuid */
1184                                 invalidate_vuid(sconn, vuid);
1185                                 data_blob_free(&blob1);
1186                                 reply_nterror(req, nt_status_squash(status));
1187                                 return;
1188                         }
1189                 }
1190
1191                 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1192                                                 blob1, &chal);
1193
1194                 data_blob_free(&blob1);
1195
1196                 reply_spnego_ntlmssp(req, vuid,
1197                                      &vuser->auth_ntlmssp_state,
1198                                      &chal, status, OID_NTLMSSP, false);
1199                 data_blob_free(&chal);
1200                 return;
1201         }
1202
1203         /* what sort of packet is this? */
1204         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1205
1206         data_blob_free(&blob1);
1207
1208         reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1209 }
1210
1211 /****************************************************************************
1212  On new VC == 0, shutdown *all* old connections and users.
1213  It seems that only NT4.x does this. At W2K and above (XP etc.).
1214  a new session setup with VC==0 is ignored.
1215 ****************************************************************************/
1216
1217 struct shutdown_state {
1218         const char *ip;
1219         struct messaging_context *msg_ctx;
1220 };
1221
1222 static int shutdown_other_smbds(const struct connections_key *key,
1223                                 const struct connections_data *crec,
1224                                 void *private_data)
1225 {
1226         struct shutdown_state *state = (struct shutdown_state *)private_data;
1227
1228         DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1229                    server_id_str(talloc_tos(), &crec->pid), crec->addr));
1230
1231         if (!process_exists(crec->pid)) {
1232                 DEBUG(10, ("process does not exist\n"));
1233                 return 0;
1234         }
1235
1236         if (procid_is_me(&crec->pid)) {
1237                 DEBUG(10, ("It's me\n"));
1238                 return 0;
1239         }
1240
1241         if (strcmp(state->ip, crec->addr) != 0) {
1242                 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1243                 return 0;
1244         }
1245
1246         DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1247                   "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1248                   state->ip));
1249
1250         messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1251                        &data_blob_null);
1252         return 0;
1253 }
1254
1255 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1256 {
1257         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1258                 "compatible we would close all old resources.\n"));
1259 #if 0
1260         conn_close_all();
1261         invalidate_all_vuids();
1262 #endif
1263         if (lp_reset_on_zero_vc()) {
1264                 char *addr;
1265                 struct shutdown_state state;
1266
1267                 addr = tsocket_address_inet_addr_string(
1268                         sconn->remote_address, talloc_tos());
1269                 if (addr == NULL) {
1270                         return;
1271                 }
1272                 state.ip = addr;
1273                 state.msg_ctx = sconn->msg_ctx;
1274                 connections_forall_read(shutdown_other_smbds, &state);
1275                 TALLOC_FREE(addr);
1276         }
1277 }
1278
1279 /****************************************************************************
1280  Reply to a session setup command.
1281 ****************************************************************************/
1282
1283 void reply_sesssetup_and_X(struct smb_request *req)
1284 {
1285         int sess_vuid;
1286         int smb_bufsize;
1287         DATA_BLOB lm_resp;
1288         DATA_BLOB nt_resp;
1289         DATA_BLOB plaintext_password;
1290         char *tmp;
1291         const char *user;
1292         fstring sub_user; /* Sanitised username for substituion */
1293         const char *domain;
1294         const char *native_os;
1295         const char *native_lanman;
1296         const char *primary_domain;
1297         struct auth_usersupplied_info *user_info = NULL;
1298         struct auth_serversupplied_info *server_info = NULL;
1299         struct auth_serversupplied_info *session_info = NULL;
1300         uint16 smb_flag2 = req->flags2;
1301
1302         NTSTATUS nt_status;
1303         struct smbd_server_connection *sconn = req->sconn;
1304
1305         bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1306
1307         START_PROFILE(SMBsesssetupX);
1308
1309         ZERO_STRUCT(lm_resp);
1310         ZERO_STRUCT(nt_resp);
1311         ZERO_STRUCT(plaintext_password);
1312
1313         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1314
1315         /* a SPNEGO session setup has 12 command words, whereas a normal
1316            NT1 session setup has 13. See the cifs spec. */
1317         if (req->wct == 12 &&
1318             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1319
1320                 if (!sconn->smb1.negprot.spnego) {
1321                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1322                                  "at SPNEGO session setup when it was not "
1323                                  "negotiated.\n"));
1324                         reply_nterror(req, nt_status_squash(
1325                                               NT_STATUS_LOGON_FAILURE));
1326                         END_PROFILE(SMBsesssetupX);
1327                         return;
1328                 }
1329
1330                 if (SVAL(req->vwv+4, 0) == 0) {
1331                         setup_new_vc_session(req->sconn);
1332                 }
1333
1334                 reply_sesssetup_and_X_spnego(req);
1335                 END_PROFILE(SMBsesssetupX);
1336                 return;
1337         }
1338
1339         smb_bufsize = SVAL(req->vwv+2, 0);
1340
1341         if (get_Protocol() < PROTOCOL_NT1) {
1342                 uint16 passlen1 = SVAL(req->vwv+7, 0);
1343
1344                 /* Never do NT status codes with protocols before NT1 as we
1345                  * don't get client caps. */
1346                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1347
1348                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1349                         reply_nterror(req, nt_status_squash(
1350                                               NT_STATUS_INVALID_PARAMETER));
1351                         END_PROFILE(SMBsesssetupX);
1352                         return;
1353                 }
1354
1355                 if (doencrypt) {
1356                         lm_resp = data_blob(req->buf, passlen1);
1357                 } else {
1358                         plaintext_password = data_blob(req->buf, passlen1+1);
1359                         /* Ensure null termination */
1360                         plaintext_password.data[passlen1] = 0;
1361                 }
1362
1363                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1364                                        req->buf + passlen1, STR_TERMINATE);
1365                 user = tmp ? tmp : "";
1366
1367                 domain = "";
1368
1369         } else {
1370                 uint16 passlen1 = SVAL(req->vwv+7, 0);
1371                 uint16 passlen2 = SVAL(req->vwv+8, 0);
1372                 enum remote_arch_types ra_type = get_remote_arch();
1373                 const uint8_t *p = req->buf;
1374                 const uint8_t *save_p = req->buf;
1375                 uint16 byte_count;
1376
1377
1378                 if(global_client_caps == 0) {
1379                         global_client_caps = IVAL(req->vwv+11, 0);
1380
1381                         if (!(global_client_caps & CAP_STATUS32)) {
1382                                 remove_from_common_flags2(
1383                                                 FLAGS2_32_BIT_ERROR_CODES);
1384                         }
1385
1386                         /* client_caps is used as final determination if
1387                          * client is NT or Win95. This is needed to return
1388                          * the correct error codes in some circumstances.
1389                         */
1390
1391                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1392                                         ra_type == RA_WIN95) {
1393                                 if(!(global_client_caps & (CAP_NT_SMBS|
1394                                                         CAP_STATUS32))) {
1395                                         set_remote_arch( RA_WIN95);
1396                                 }
1397                         }
1398                 }
1399
1400                 if (!doencrypt) {
1401                         /* both Win95 and WinNT stuff up the password
1402                          * lengths for non-encrypting systems. Uggh.
1403
1404                            if passlen1==24 its a win95 system, and its setting
1405                            the password length incorrectly. Luckily it still
1406                            works with the default code because Win95 will null
1407                            terminate the password anyway
1408
1409                            if passlen1>0 and passlen2>0 then maybe its a NT box
1410                            and its setting passlen2 to some random value which
1411                            really stuffs things up. we need to fix that one.  */
1412
1413                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1414                                         passlen2 != 1) {
1415                                 passlen2 = 0;
1416                         }
1417                 }
1418
1419                 /* check for nasty tricks */
1420                 if (passlen1 > MAX_PASS_LEN
1421                     || passlen1 > smbreq_bufrem(req, p)) {
1422                         reply_nterror(req, nt_status_squash(
1423                                               NT_STATUS_INVALID_PARAMETER));
1424                         END_PROFILE(SMBsesssetupX);
1425                         return;
1426                 }
1427
1428                 if (passlen2 > MAX_PASS_LEN
1429                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1430                         reply_nterror(req, nt_status_squash(
1431                                               NT_STATUS_INVALID_PARAMETER));
1432                         END_PROFILE(SMBsesssetupX);
1433                         return;
1434                 }
1435
1436                 /* Save the lanman2 password and the NT md4 password. */
1437
1438                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1439                         doencrypt = False;
1440                 }
1441
1442                 if (doencrypt) {
1443                         lm_resp = data_blob(p, passlen1);
1444                         nt_resp = data_blob(p+passlen1, passlen2);
1445                 } else if (lp_security() != SEC_SHARE) {
1446                         /*
1447                          * In share level we should ignore any passwords, so
1448                          * only read them if we're not.
1449                          */
1450                         char *pass = NULL;
1451                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1452
1453                         if (unic && (passlen2 == 0) && passlen1) {
1454                                 /* Only a ascii plaintext password was sent. */
1455                                 (void)srvstr_pull_talloc(talloc_tos(),
1456                                                         req->inbuf,
1457                                                         req->flags2,
1458                                                         &pass,
1459                                                         req->buf,
1460                                                         passlen1,
1461                                                         STR_TERMINATE|STR_ASCII);
1462                         } else {
1463                                 (void)srvstr_pull_talloc(talloc_tos(),
1464                                                         req->inbuf,
1465                                                         req->flags2,
1466                                                         &pass,
1467                                                         req->buf,
1468                                                         unic ? passlen2 : passlen1,
1469                                                         STR_TERMINATE);
1470                         }
1471                         if (!pass) {
1472                                 reply_nterror(req, nt_status_squash(
1473                                               NT_STATUS_INVALID_PARAMETER));
1474                                 END_PROFILE(SMBsesssetupX);
1475                                 return;
1476                         }
1477                         plaintext_password = data_blob(pass, strlen(pass)+1);
1478                 }
1479
1480                 p += passlen1 + passlen2;
1481
1482                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1483                                             STR_TERMINATE);
1484                 user = tmp ? tmp : "";
1485
1486                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1487                                             STR_TERMINATE);
1488                 domain = tmp ? tmp : "";
1489
1490                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1491                                             STR_TERMINATE);
1492                 native_os = tmp ? tmp : "";
1493
1494                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1495                                             STR_TERMINATE);
1496                 native_lanman = tmp ? tmp : "";
1497
1498                 /* not documented or decoded by Ethereal but there is one more
1499                  * string in the extra bytes which is the same as the
1500                  * PrimaryDomain when using extended security.  Windows NT 4
1501                  * and 2003 use this string to store the native lanman string.
1502                  * Windows 9x does not include a string here at all so we have
1503                  * to check if we have any extra bytes left */
1504
1505                 byte_count = SVAL(req->vwv+13, 0);
1506                 if ( PTR_DIFF(p, save_p) < byte_count) {
1507                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1508                                                     STR_TERMINATE);
1509                         primary_domain = tmp ? tmp : "";
1510                 } else {
1511                         primary_domain = talloc_strdup(talloc_tos(), "null");
1512                 }
1513
1514                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
1515                         "PrimaryDomain=[%s]\n",
1516                         domain, native_os, native_lanman, primary_domain));
1517
1518                 if ( ra_type == RA_WIN2K ) {
1519                         if ( strlen(native_lanman) == 0 )
1520                                 ra_lanman_string( primary_domain );
1521                         else
1522                                 ra_lanman_string( native_lanman );
1523                 }
1524
1525         }
1526
1527         if (SVAL(req->vwv+4, 0) == 0) {
1528                 setup_new_vc_session(req->sconn);
1529         }
1530
1531         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1532                                 domain, user, get_remote_machine_name()));
1533
1534         if (*user) {
1535                 if (sconn->smb1.negprot.spnego) {
1536
1537                         /* This has to be here, because this is a perfectly
1538                          * valid behaviour for guest logons :-( */
1539
1540                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1541                                 "at 'normal' session setup after "
1542                                 "negotiating spnego.\n"));
1543                         reply_nterror(req, nt_status_squash(
1544                                               NT_STATUS_LOGON_FAILURE));
1545                         END_PROFILE(SMBsesssetupX);
1546                         return;
1547                 }
1548                 fstrcpy(sub_user, user);
1549         } else {
1550                 fstrcpy(sub_user, lp_guestaccount());
1551         }
1552
1553         sub_set_smb_name(sub_user);
1554
1555         reload_services(sconn->msg_ctx, sconn->sock, True);
1556
1557         if (lp_security() == SEC_SHARE) {
1558                 char *sub_user_mapped = NULL;
1559                 /* In share level we should ignore any passwords */
1560
1561                 data_blob_free(&lm_resp);
1562                 data_blob_free(&nt_resp);
1563                 data_blob_clear_free(&plaintext_password);
1564
1565                 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1566                 if (!sub_user_mapped) {
1567                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1568                         END_PROFILE(SMBsesssetupX);
1569                         return;
1570                 }
1571                 fstrcpy(sub_user, sub_user_mapped);
1572                 add_session_user(sconn, sub_user);
1573                 add_session_workgroup(sconn, domain);
1574                 /* Then force it to null for the benfit of the code below */
1575                 user = "";
1576         }
1577
1578         if (!*user) {
1579
1580                 nt_status = check_guest_password(&server_info);
1581
1582         } else if (doencrypt) {
1583                 struct auth_context *negprot_auth_context = NULL;
1584                 negprot_auth_context = sconn->smb1.negprot.auth_context;
1585                 if (!negprot_auth_context) {
1586                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
1587                                 "session setup without negprot denied!\n"));
1588                         reply_nterror(req, nt_status_squash(
1589                                               NT_STATUS_LOGON_FAILURE));
1590                         END_PROFILE(SMBsesssetupX);
1591                         return;
1592                 }
1593                 nt_status = make_user_info_for_reply_enc(&user_info, user,
1594                                                 domain,
1595                                                 lm_resp, nt_resp);
1596                 if (NT_STATUS_IS_OK(nt_status)) {
1597                         nt_status = negprot_auth_context->check_ntlm_password(
1598                                         negprot_auth_context,
1599                                         user_info,
1600                                         &server_info);
1601                 }
1602         } else {
1603                 struct auth_context *plaintext_auth_context = NULL;
1604
1605                 nt_status = make_auth_context_subsystem(
1606                         talloc_tos(), &plaintext_auth_context);
1607
1608                 if (NT_STATUS_IS_OK(nt_status)) {
1609                         uint8_t chal[8];
1610
1611                         plaintext_auth_context->get_ntlm_challenge(
1612                                         plaintext_auth_context, chal);
1613
1614                         if (!make_user_info_for_reply(&user_info,
1615                                                       user, domain, chal,
1616                                                       plaintext_password)) {
1617                                 nt_status = NT_STATUS_NO_MEMORY;
1618                         }
1619
1620                         if (NT_STATUS_IS_OK(nt_status)) {
1621                                 nt_status = plaintext_auth_context->check_ntlm_password(
1622                                                 plaintext_auth_context,
1623                                                 user_info,
1624                                                 &server_info);
1625
1626                                 TALLOC_FREE(plaintext_auth_context);
1627                         }
1628                 }
1629         }
1630
1631         free_user_info(&user_info);
1632
1633         if (!NT_STATUS_IS_OK(nt_status)) {
1634                 nt_status = do_map_to_guest(nt_status, &server_info,
1635                                 user, domain);
1636         }
1637
1638         if (!NT_STATUS_IS_OK(nt_status)) {
1639                 data_blob_free(&nt_resp);
1640                 data_blob_free(&lm_resp);
1641                 data_blob_clear_free(&plaintext_password);
1642                 reply_nterror(req, nt_status_squash(nt_status));
1643                 END_PROFILE(SMBsesssetupX);
1644                 return;
1645         }
1646
1647         nt_status = create_local_token(req, server_info, NULL, &session_info);
1648         TALLOC_FREE(server_info);
1649
1650         if (!NT_STATUS_IS_OK(nt_status)) {
1651                 DEBUG(10, ("create_local_token failed: %s\n",
1652                            nt_errstr(nt_status)));
1653                 data_blob_free(&nt_resp);
1654                 data_blob_free(&lm_resp);
1655                 data_blob_clear_free(&plaintext_password);
1656                 reply_nterror(req, nt_status_squash(nt_status));
1657                 END_PROFILE(SMBsesssetupX);
1658                 return;
1659         }
1660
1661         data_blob_clear_free(&plaintext_password);
1662
1663         /* it's ok - setup a reply */
1664         reply_outbuf(req, 3, 0);
1665         if (get_Protocol() >= PROTOCOL_NT1) {
1666                 push_signature(&req->outbuf);
1667                 /* perhaps grab OS version here?? */
1668         }
1669
1670         if (session_info->guest) {
1671                 SSVAL(req->outbuf,smb_vwv2,1);
1672         }
1673
1674         /* register the name and uid as being validated, so further connections
1675            to a uid can get through without a password, on the same VC */
1676
1677         if (lp_security() == SEC_SHARE) {
1678                 sess_vuid = UID_FIELD_INVALID;
1679                 TALLOC_FREE(session_info);
1680         } else {
1681                 /* Ignore the initial vuid. */
1682                 sess_vuid = register_initial_vuid(sconn);
1683                 if (sess_vuid == UID_FIELD_INVALID) {
1684                         data_blob_free(&nt_resp);
1685                         data_blob_free(&lm_resp);
1686                         reply_nterror(req, nt_status_squash(
1687                                               NT_STATUS_LOGON_FAILURE));
1688                         END_PROFILE(SMBsesssetupX);
1689                         return;
1690                 }
1691                 /* register_existing_vuid keeps the session_info */
1692                 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1693                                         session_info,
1694                                         nt_resp.data ? nt_resp : lm_resp,
1695                                         sub_user);
1696                 if (sess_vuid == UID_FIELD_INVALID) {
1697                         data_blob_free(&nt_resp);
1698                         data_blob_free(&lm_resp);
1699                         reply_nterror(req, nt_status_squash(
1700                                               NT_STATUS_LOGON_FAILURE));
1701                         END_PROFILE(SMBsesssetupX);
1702                         return;
1703                 }
1704
1705                 /* current_user_info is changed on new vuid */
1706                 reload_services(sconn->msg_ctx, sconn->sock, True);
1707         }
1708
1709         data_blob_free(&nt_resp);
1710         data_blob_free(&lm_resp);
1711
1712         SSVAL(req->outbuf,smb_uid,sess_vuid);
1713         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1714         req->vuid = sess_vuid;
1715
1716         if (!sconn->smb1.sessions.done_sesssetup) {
1717                 sconn->smb1.sessions.max_send =
1718                         MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1719         }
1720         sconn->smb1.sessions.done_sesssetup = true;
1721
1722         END_PROFILE(SMBsesssetupX);
1723         chain_reply(req);
1724         return;
1725 }