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