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