s3:smbd: remove pending_auth_data logic
[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 "../auth/ntlmssp/ntlmssp.h"
31 #include "../librpc/gen_ndr/krb5pac.h"
32 #include "libads/kerberos_proto.h"
33 #include "../lib/util/asn1.h"
34 #include "auth.h"
35 #include "messages.h"
36 #include "smbprofile.h"
37 #include "../libcli/security/security.h"
38 #include "auth/gensec/gensec.h"
39
40 /****************************************************************************
41  Add the standard 'Samba' signature to the end of the session setup.
42 ****************************************************************************/
43
44 static int push_signature(uint8 **outbuf)
45 {
46         char *lanman;
47         int result, tmp;
48
49         result = 0;
50
51         tmp = message_push_string(outbuf, "Unix", STR_TERMINATE);
52
53         if (tmp == -1) return -1;
54         result += tmp;
55
56         if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
57                 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
58                 SAFE_FREE(lanman);
59         }
60         else {
61                 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
62         }
63
64         if (tmp == -1) return -1;
65         result += tmp;
66
67         tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
68
69         if (tmp == -1) return -1;
70         result += tmp;
71
72         return result;
73 }
74
75 /****************************************************************************
76  Send a security blob via a session setup reply.
77 ****************************************************************************/
78
79 static void reply_sesssetup_blob(struct smb_request *req,
80                                  DATA_BLOB blob,
81                                  NTSTATUS nt_status)
82 {
83         if (!NT_STATUS_IS_OK(nt_status) &&
84             !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
85                 reply_nterror(req, nt_status_squash(nt_status));
86                 return;
87         }
88
89         nt_status = nt_status_squash(nt_status);
90         SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(nt_status));
91         SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
92         SSVAL(req->outbuf, smb_vwv3, blob.length);
93
94         if ((message_push_blob(&req->outbuf, blob) == -1)
95             || (push_signature(&req->outbuf) == -1)) {
96                 reply_nterror(req, NT_STATUS_NO_MEMORY);
97         }
98 }
99
100 /****************************************************************************
101  Do a 'guest' logon, getting back the
102 ****************************************************************************/
103
104 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
105                                      struct auth_serversupplied_info **server_info)
106 {
107         struct auth_context *auth_context;
108         struct auth_usersupplied_info *user_info = NULL;
109
110         NTSTATUS nt_status;
111         static unsigned char chal[8] = { 0, };
112
113         DEBUG(3,("Got anonymous request\n"));
114
115         nt_status = make_auth_context_fixed(talloc_tos(), &auth_context, chal);
116         if (!NT_STATUS_IS_OK(nt_status)) {
117                 return nt_status;
118         }
119
120         if (!make_user_info_guest(remote_address, &user_info)) {
121                 TALLOC_FREE(auth_context);
122                 return NT_STATUS_NO_MEMORY;
123         }
124
125         nt_status = auth_context->check_ntlm_password(auth_context,
126                                                 user_info,
127                                                 server_info);
128         TALLOC_FREE(auth_context);
129         free_user_info(&user_info);
130         return nt_status;
131 }
132
133
134 #ifdef HAVE_KRB5
135
136 #if 0
137 /* Experiment that failed. See "only happens with a KDC" comment below. */
138 /****************************************************************************
139  Cerate a clock skew error blob for a Windows client.
140 ****************************************************************************/
141
142 static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
143 {
144         krb5_context context = NULL;
145         krb5_error_code kerr = 0;
146         krb5_data reply;
147         krb5_principal host_princ = NULL;
148         char *host_princ_s = NULL;
149         bool ret = False;
150
151         *pblob_out = data_blob_null;
152
153         initialize_krb5_error_table();
154         kerr = krb5_init_context(&context);
155         if (kerr) {
156                 return False;
157         }
158         /* Create server principal. */
159         asprintf(&host_princ_s, "%s$@%s", lp_netbios_name(), lp_realm());
160         if (!host_princ_s) {
161                 goto out;
162         }
163         strlower_m(host_princ_s);
164
165         kerr = smb_krb5_parse_name(context, host_princ_s, &host_princ);
166         if (kerr) {
167                 DEBUG(10,("make_krb5_skew_error: smb_krb5_parse_name failed "
168                         "for name %s: Error %s\n",
169                         host_princ_s, error_message(kerr) ));
170                 goto out;
171         }
172
173         kerr = smb_krb5_mk_error(context, KRB5KRB_AP_ERR_SKEW,
174                         host_princ, &reply);
175         if (kerr) {
176                 DEBUG(10,("make_krb5_skew_error: smb_krb5_mk_error "
177                         "failed: Error %s\n",
178                         error_message(kerr) ));
179                 goto out;
180         }
181
182         *pblob_out = data_blob(reply.data, reply.length);
183         kerberos_free_data_contents(context,&reply);
184         ret = True;
185
186   out:
187
188         if (host_princ_s) {
189                 SAFE_FREE(host_princ_s);
190         }
191         if (host_princ) {
192                 krb5_free_principal(context, host_princ);
193         }
194         krb5_free_context(context);
195         return ret;
196 }
197 #endif
198
199 /****************************************************************************
200  Reply to a session setup spnego negotiate packet for kerberos.
201 ****************************************************************************/
202
203 static void reply_spnego_kerberos(struct smb_request *req,
204                                   DATA_BLOB *secblob,
205                                   const char *mechOID,
206                                   uint16 vuid,
207                                   bool *p_invalidate_vuid)
208 {
209         TALLOC_CTX *mem_ctx;
210         DATA_BLOB ticket;
211         struct passwd *pw;
212         int sess_vuid = req->vuid;
213         NTSTATUS ret = NT_STATUS_OK;
214         DATA_BLOB ap_rep, ap_rep_wrapped, response;
215         struct auth_session_info *session_info = NULL;
216         DATA_BLOB session_key = data_blob_null;
217         uint8 tok_id[2];
218         DATA_BLOB nullblob = data_blob_null;
219         bool map_domainuser_to_guest = False;
220         bool username_was_mapped;
221         struct PAC_LOGON_INFO *logon_info = NULL;
222         struct smbd_server_connection *sconn = req->sconn;
223         char *principal;
224         char *user;
225         char *domain;
226         char *real_username;
227
228         ZERO_STRUCT(ticket);
229         ZERO_STRUCT(ap_rep);
230         ZERO_STRUCT(ap_rep_wrapped);
231         ZERO_STRUCT(response);
232
233         /* Normally we will always invalidate the intermediate vuid. */
234         *p_invalidate_vuid = True;
235
236         mem_ctx = talloc_init("reply_spnego_kerberos");
237         if (mem_ctx == NULL) {
238                 reply_nterror(req, nt_status_squash(NT_STATUS_NO_MEMORY));
239                 return;
240         }
241
242         if (!spnego_parse_krb5_wrap(mem_ctx, *secblob, &ticket, tok_id)) {
243                 talloc_destroy(mem_ctx);
244                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
245                 return;
246         }
247
248         ret = ads_verify_ticket(mem_ctx, lp_realm(), 0, &ticket,
249                                 &principal, &logon_info, &ap_rep,
250                                 &session_key, True);
251
252         data_blob_free(&ticket);
253
254         if (!NT_STATUS_IS_OK(ret)) {
255 #if 0
256                 /* Experiment that failed.
257                  * See "only happens with a KDC" comment below. */
258
259                 if (NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
260
261                         /*
262                          * Windows in this case returns
263                          * NT_STATUS_MORE_PROCESSING_REQUIRED
264                          * with a negTokenTarg blob containing an krb5_error
265                          * struct ASN1 encoded containing KRB5KRB_AP_ERR_SKEW.
266                          * The client then fixes its clock and continues rather
267                          * than giving an error. JRA.
268                          * -- Looks like this only happens with a KDC. JRA.
269                          */
270
271                         bool ok = make_krb5_skew_error(&ap_rep);
272                         if (!ok) {
273                                 talloc_destroy(mem_ctx);
274                                 return ERROR_NT(nt_status_squash(
275                                                 NT_STATUS_LOGON_FAILURE));
276                         }
277                         ap_rep_wrapped = spnego_gen_krb5_wrap(ap_rep,
278                                         TOK_ID_KRB_ERROR);
279                         response = spnego_gen_auth_response(&ap_rep_wrapped,
280                                         ret, OID_KERBEROS5_OLD);
281                         reply_sesssetup_blob(conn, inbuf, outbuf, response,
282                                         NT_STATUS_MORE_PROCESSING_REQUIRED);
283
284                         /*
285                          * In this one case we don't invalidate the
286                          * intermediate vuid as we're expecting the client
287                          * to re-use it for the next sessionsetupX packet. JRA.
288                          */
289
290                         *p_invalidate_vuid = False;
291
292                         data_blob_free(&ap_rep);
293                         data_blob_free(&ap_rep_wrapped);
294                         data_blob_free(&response);
295                         talloc_destroy(mem_ctx);
296                         return -1; /* already replied */
297                 }
298 #else
299                 if (!NT_STATUS_EQUAL(ret, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
300                         ret = NT_STATUS_LOGON_FAILURE;
301                 }
302 #endif
303                 DEBUG(1,("Failed to verify incoming ticket with error %s!\n",
304                                 nt_errstr(ret)));
305                 talloc_destroy(mem_ctx);
306                 reply_nterror(req, nt_status_squash(ret));
307                 return;
308         }
309
310         ret = get_user_from_kerberos_info(talloc_tos(),
311                                           sconn->remote_hostname,
312                                           principal, logon_info,
313                                           &username_was_mapped,
314                                           &map_domainuser_to_guest,
315                                           &user, &domain,
316                                           &real_username, &pw);
317         if (!NT_STATUS_IS_OK(ret)) {
318                 data_blob_free(&ap_rep);
319                 data_blob_free(&session_key);
320                 talloc_destroy(mem_ctx);
321                 reply_nterror(req,nt_status_squash(NT_STATUS_LOGON_FAILURE));
322                 return;
323         }
324
325         /* save the PAC data if we have it */
326         if (logon_info) {
327                 netsamlogon_cache_store(user, &logon_info->info3);
328         }
329
330         /* setup the string used by %U */
331         sub_set_smb_name(real_username);
332
333         /* reload services so that the new %U is taken into account */
334         reload_services(sconn, conn_snum_used, true);
335
336         ret = make_session_info_krb5(mem_ctx,
337                                      user, domain, real_username, pw,
338                                      logon_info, map_domainuser_to_guest,
339                                      username_was_mapped,
340                                      &session_key,
341                                      &session_info);
342         data_blob_free(&session_key);
343         if (!NT_STATUS_IS_OK(ret)) {
344                 DEBUG(1, ("make_server_info_krb5 failed!\n"));
345                 data_blob_free(&ap_rep);
346                 TALLOC_FREE(mem_ctx);
347                 reply_nterror(req, nt_status_squash(ret));
348                 return;
349         }
350
351         if (!is_partial_auth_vuid(sconn, sess_vuid)) {
352                 sess_vuid = register_initial_vuid(sconn);
353         }
354
355         /* register_existing_vuid keeps the server info */
356         /* register_existing_vuid takes ownership of session_key on success,
357          * no need to free after this on success. A better interface would copy
358          * it.... */
359
360         sess_vuid = register_existing_vuid(sconn, sess_vuid,
361                                            session_info, nullblob);
362
363         reply_outbuf(req, 4, 0);
364         SSVAL(req->outbuf,smb_uid,sess_vuid);
365
366         if (sess_vuid == UID_FIELD_INVALID ) {
367                 ret = NT_STATUS_LOGON_FAILURE;
368         } else {
369                 /* current_user_info is changed on new vuid */
370                 reload_services(sconn, conn_snum_used, true);
371
372                 SSVAL(req->outbuf, smb_vwv3, 0);
373
374                 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
375                         SSVAL(req->outbuf,smb_vwv2,1);
376                 }
377
378                 SSVAL(req->outbuf, smb_uid, sess_vuid);
379
380                 /* Successful logon. Keep this vuid. */
381                 *p_invalidate_vuid = False;
382         }
383
384         /* wrap that up in a nice GSS-API wrapping */
385         if (NT_STATUS_IS_OK(ret)) {
386                 ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
387                                 TOK_ID_KRB_AP_REP);
388         } else {
389                 ap_rep_wrapped = data_blob_null;
390         }
391         response = spnego_gen_auth_response(talloc_tos(), &ap_rep_wrapped, ret,
392                         mechOID);
393         reply_sesssetup_blob(req, response, ret);
394
395         data_blob_free(&ap_rep);
396         data_blob_free(&ap_rep_wrapped);
397         data_blob_free(&response);
398         TALLOC_FREE(mem_ctx);
399 }
400
401 #endif
402
403 /****************************************************************************
404  Send a session setup reply, wrapped in SPNEGO.
405  Get vuid and check first.
406  End the NTLMSSP exchange context if we are OK/complete fail
407  This should be split into two functions, one to handle each
408  leg of the NTLM auth steps.
409 ***************************************************************************/
410
411 static void reply_spnego_ntlmssp(struct smb_request *req,
412                                  uint16 vuid,
413                                  struct gensec_security **gensec_security,
414                                  DATA_BLOB *ntlmssp_blob, NTSTATUS nt_status,
415                                  const char *OID,
416                                  bool wrap)
417 {
418         bool do_invalidate = true;
419         DATA_BLOB response;
420         struct auth_session_info *session_info = NULL;
421         struct smbd_server_connection *sconn = req->sconn;
422
423         if (NT_STATUS_IS_OK(nt_status)) {
424                 nt_status = gensec_session_info(*gensec_security,
425                                                 talloc_tos(),
426                                                 &session_info);
427         }
428
429         reply_outbuf(req, 4, 0);
430
431         SSVAL(req->outbuf, smb_uid, vuid);
432
433         if (NT_STATUS_IS_OK(nt_status)) {
434                 DATA_BLOB nullblob = data_blob_null;
435
436                 if (!is_partial_auth_vuid(sconn, vuid)) {
437                         nt_status = NT_STATUS_LOGON_FAILURE;
438                         goto out;
439                 }
440
441                 /* register_existing_vuid keeps the server info */
442                 if (register_existing_vuid(sconn, vuid,
443                                            session_info, nullblob) !=
444                                            vuid) {
445                         /* The problem is, *gensec_security points
446                          * into the vuser this will have
447                          * talloc_free()'ed in
448                          * register_existing_vuid() */
449                         do_invalidate = false;
450                         nt_status = NT_STATUS_LOGON_FAILURE;
451                         goto out;
452                 }
453
454                 /* current_user_info is changed on new vuid */
455                 reload_services(sconn, conn_snum_used, true);
456
457                 SSVAL(req->outbuf, smb_vwv3, 0);
458
459                 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
460                         SSVAL(req->outbuf,smb_vwv2,1);
461                 }
462         }
463
464   out:
465
466         if (wrap) {
467                 response = spnego_gen_auth_response(talloc_tos(),
468                                 ntlmssp_blob,
469                                 nt_status, OID);
470         } else {
471                 response = *ntlmssp_blob;
472         }
473
474         reply_sesssetup_blob(req, response, nt_status);
475         if (wrap) {
476                 data_blob_free(&response);
477         }
478
479         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
480            and the other end, that we are not finished yet. */
481
482         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
483                 /* NB. This is *NOT* an error case. JRA */
484                 if (do_invalidate) {
485                         TALLOC_FREE(*gensec_security);
486                         if (!NT_STATUS_IS_OK(nt_status)) {
487                                 /* Kill the intermediate vuid */
488                                 invalidate_vuid(sconn, vuid);
489                         }
490                 }
491         }
492 }
493
494 /****************************************************************************
495  Is this a krb5 mechanism ?
496 ****************************************************************************/
497
498 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
499                 DATA_BLOB blob_in,
500                 DATA_BLOB *pblob_out,
501                 char **kerb_mechOID)
502 {
503         char *OIDs[ASN1_MAX_OIDS];
504         int i;
505         NTSTATUS ret = NT_STATUS_OK;
506
507         *kerb_mechOID = NULL;
508
509         /* parse out the OIDs and the first sec blob */
510         if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
511                         (OIDs[0] == NULL)) {
512                 return NT_STATUS_LOGON_FAILURE;
513         }
514
515         /* only look at the first OID for determining the mechToken --
516            according to RFC2478, we should choose the one we want
517            and renegotiate, but i smell a client bug here..
518
519            Problem observed when connecting to a member (samba box)
520            of an AD domain as a user in a Samba domain.  Samba member
521            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
522            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
523            NTLMSSP mechtoken.                 --jerry              */
524
525 #ifdef HAVE_KRB5
526         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
527             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
528                 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
529                 if (*kerb_mechOID == NULL) {
530                         ret = NT_STATUS_NO_MEMORY;
531                 }
532         }
533 #endif
534
535         for (i=0;OIDs[i];i++) {
536                 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
537                 talloc_free(OIDs[i]);
538         }
539         return ret;
540 }
541
542 /****************************************************************************
543  Fall back from krb5 to NTLMSSP.
544 ****************************************************************************/
545
546 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
547                                                 uint16 vuid)
548 {
549         DATA_BLOB response;
550
551         reply_outbuf(req, 4, 0);
552         SSVAL(req->outbuf,smb_uid,vuid);
553
554         DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
555                 "but set to downgrade to NTLMSSP\n"));
556
557         response = spnego_gen_auth_response(talloc_tos(), NULL,
558                         NT_STATUS_MORE_PROCESSING_REQUIRED,
559                         OID_NTLMSSP);
560         reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
561         data_blob_free(&response);
562 }
563
564 /****************************************************************************
565  Reply to a session setup spnego negotiate packet.
566 ****************************************************************************/
567
568 static void reply_spnego_negotiate(struct smb_request *req,
569                                    uint16 vuid,
570                                    DATA_BLOB blob1,
571                                    struct gensec_security **gensec_security)
572 {
573         DATA_BLOB secblob;
574         DATA_BLOB chal;
575         char *kerb_mech = NULL;
576         NTSTATUS status;
577         struct smbd_server_connection *sconn = req->sconn;
578
579         status = parse_spnego_mechanisms(talloc_tos(),
580                         blob1, &secblob, &kerb_mech);
581         if (!NT_STATUS_IS_OK(status)) {
582                 /* Kill the intermediate vuid */
583                 invalidate_vuid(sconn, vuid);
584                 reply_nterror(req, nt_status_squash(status));
585                 return;
586         }
587
588         DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
589                                 (unsigned long)secblob.length));
590
591 #ifdef HAVE_KRB5
592         if (kerb_mech && ((lp_security()==SEC_ADS) ||
593                                 USE_KERBEROS_KEYTAB) ) {
594                 bool destroy_vuid = True;
595                 reply_spnego_kerberos(req, &secblob, kerb_mech,
596                                       vuid, &destroy_vuid);
597                 data_blob_free(&secblob);
598                 if (destroy_vuid) {
599                         /* Kill the intermediate vuid */
600                         invalidate_vuid(sconn, vuid);
601                 }
602                 TALLOC_FREE(kerb_mech);
603                 return;
604         }
605 #endif
606
607         TALLOC_FREE(*gensec_security);
608
609         if (kerb_mech) {
610                 data_blob_free(&secblob);
611                 /* The mechtoken is a krb5 ticket, but
612                  * we need to fall back to NTLM. */
613                 reply_spnego_downgrade_to_ntlmssp(req, vuid);
614                 TALLOC_FREE(kerb_mech);
615                 return;
616         }
617
618         status = auth_generic_prepare(NULL, sconn->remote_address,
619                                       gensec_security);
620         if (!NT_STATUS_IS_OK(status)) {
621                 /* Kill the intermediate vuid */
622                 invalidate_vuid(sconn, vuid);
623                 reply_nterror(req, nt_status_squash(status));
624                 return;
625         }
626
627         gensec_want_feature(*gensec_security, GENSEC_FEATURE_SESSION_KEY);
628         gensec_want_feature(*gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
629
630         status = gensec_start_mech_by_oid(*gensec_security, GENSEC_OID_NTLMSSP);
631         if (!NT_STATUS_IS_OK(status)) {
632                 /* Kill the intermediate vuid */
633                 invalidate_vuid(sconn, vuid);
634                 reply_nterror(req, nt_status_squash(status));
635                 return;
636         }
637
638         status = gensec_update(*gensec_security, talloc_tos(),
639                                NULL, secblob, &chal);
640
641         data_blob_free(&secblob);
642
643         reply_spnego_ntlmssp(req, vuid, gensec_security,
644                              &chal, status, OID_NTLMSSP, true);
645
646         data_blob_free(&chal);
647
648         /* already replied */
649         return;
650 }
651
652 /****************************************************************************
653  Reply to a session setup spnego auth packet.
654 ****************************************************************************/
655
656 static void reply_spnego_auth(struct smb_request *req,
657                               uint16 vuid,
658                               DATA_BLOB blob1,
659                               struct gensec_security **gensec_security)
660 {
661         DATA_BLOB auth = data_blob_null;
662         DATA_BLOB auth_reply = data_blob_null;
663         DATA_BLOB secblob = data_blob_null;
664         NTSTATUS status = NT_STATUS_LOGON_FAILURE;
665         struct smbd_server_connection *sconn = req->sconn;
666
667         if (!spnego_parse_auth(talloc_tos(), blob1, &auth)) {
668 #if 0
669                 file_save("auth.dat", blob1.data, blob1.length);
670 #endif
671                 /* Kill the intermediate vuid */
672                 invalidate_vuid(sconn, vuid);
673
674                 reply_nterror(req, nt_status_squash(
675                                       NT_STATUS_LOGON_FAILURE));
676                 return;
677         }
678
679         if (auth.data[0] == ASN1_APPLICATION(0)) {
680                 /* Might be a second negTokenTarg packet */
681                 char *kerb_mech = NULL;
682
683                 status = parse_spnego_mechanisms(talloc_tos(),
684                                 auth, &secblob, &kerb_mech);
685
686                 if (!NT_STATUS_IS_OK(status)) {
687                         /* Kill the intermediate vuid */
688                         invalidate_vuid(sconn, vuid);
689                         reply_nterror(req, nt_status_squash(status));
690                         return;
691                 }
692
693                 DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
694                                 (unsigned long)secblob.length));
695 #ifdef HAVE_KRB5
696                 if (kerb_mech && ((lp_security()==SEC_ADS) ||
697                                         USE_KERBEROS_KEYTAB)) {
698                         bool destroy_vuid = True;
699                         reply_spnego_kerberos(req, &secblob, kerb_mech,
700                                               vuid, &destroy_vuid);
701                         data_blob_free(&secblob);
702                         data_blob_free(&auth);
703                         if (destroy_vuid) {
704                                 /* Kill the intermediate vuid */
705                                 invalidate_vuid(sconn, vuid);
706                         }
707                         TALLOC_FREE(kerb_mech);
708                         return;
709                 }
710 #endif
711                 /* Can't blunder into NTLMSSP auth if we have
712                  * a krb5 ticket. */
713
714                 if (kerb_mech) {
715                         /* Kill the intermediate vuid */
716                         invalidate_vuid(sconn, vuid);
717                         DEBUG(3,("reply_spnego_auth: network "
718                                 "misconfiguration, client sent us a "
719                                 "krb5 ticket and kerberos security "
720                                 "not enabled\n"));
721                         reply_nterror(req, nt_status_squash(
722                                         NT_STATUS_LOGON_FAILURE));
723                         TALLOC_FREE(kerb_mech);
724                 }
725         }
726
727         /* If we get here it wasn't a negTokenTarg auth packet. */
728         data_blob_free(&secblob);
729
730         if (!*gensec_security) {
731                 status = auth_generic_prepare(NULL, sconn->remote_address,
732                                               gensec_security);
733                 if (!NT_STATUS_IS_OK(status)) {
734                         /* Kill the intermediate vuid */
735                         invalidate_vuid(sconn, vuid);
736                         reply_nterror(req, nt_status_squash(status));
737                         return;
738                 }
739
740                 gensec_want_feature(*gensec_security, GENSEC_FEATURE_SESSION_KEY);
741                 gensec_want_feature(*gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
742
743                 status = gensec_start_mech_by_oid(*gensec_security, GENSEC_OID_NTLMSSP);
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
752         status = gensec_update(*gensec_security, talloc_tos(),
753                                NULL, auth, &auth_reply);
754
755         data_blob_free(&auth);
756
757         /* Don't send the mechid as we've already sent this (RFC4178). */
758
759         reply_spnego_ntlmssp(req, vuid,
760                              gensec_security,
761                              &auth_reply, status, NULL, true);
762
763         data_blob_free(&auth_reply);
764
765         /* and tell smbd that we have already replied to this packet */
766         return;
767 }
768
769 /****************************************************************************
770  Reply to a session setup command.
771  conn POINTER CAN BE NULL HERE !
772 ****************************************************************************/
773
774 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
775 {
776         const uint8 *p;
777         DATA_BLOB blob1;
778         size_t bufrem;
779         char *tmp;
780         const char *native_os;
781         const char *native_lanman;
782         const char *primary_domain;
783         const char *p2;
784         uint16 data_blob_len = SVAL(req->vwv+7, 0);
785         enum remote_arch_types ra_type = get_remote_arch();
786         int vuid = req->vuid;
787         user_struct *vuser = NULL;
788         NTSTATUS status = NT_STATUS_OK;
789         struct smbd_server_connection *sconn = req->sconn;
790         DATA_BLOB chal;
791
792         DEBUG(3,("Doing spnego session setup\n"));
793
794         if (global_client_caps == 0) {
795                 global_client_caps = IVAL(req->vwv+10, 0);
796
797                 if (!(global_client_caps & CAP_STATUS32)) {
798                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
799                 }
800
801         }
802
803         p = req->buf;
804
805         if (data_blob_len == 0) {
806                 /* an invalid request */
807                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
808                 return;
809         }
810
811         bufrem = smbreq_bufrem(req, p);
812         /* pull the spnego blob */
813         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
814
815 #if 0
816         file_save("negotiate.dat", blob1.data, blob1.length);
817 #endif
818
819         p2 = (const char *)req->buf + blob1.length;
820
821         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
822                                      STR_TERMINATE);
823         native_os = tmp ? tmp : "";
824
825         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
826                                      STR_TERMINATE);
827         native_lanman = tmp ? tmp : "";
828
829         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
830                                      STR_TERMINATE);
831         primary_domain = tmp ? tmp : "";
832
833         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
834                 native_os, native_lanman, primary_domain));
835
836         if ( ra_type == RA_WIN2K ) {
837                 /* Vista sets neither the OS or lanman strings */
838
839                 if ( !strlen(native_os) && !strlen(native_lanman) )
840                         set_remote_arch(RA_VISTA);
841
842                 /* Windows 2003 doesn't set the native lanman string,
843                    but does set primary domain which is a bug I think */
844
845                 if ( !strlen(native_lanman) ) {
846                         ra_lanman_string( primary_domain );
847                 } else {
848                         ra_lanman_string( native_lanman );
849                 }
850         } else if ( ra_type == RA_VISTA ) {
851                 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
852                         set_remote_arch(RA_OSX);
853                 }
854         }
855
856         /* Do we have a valid vuid now ? */
857         if (!is_partial_auth_vuid(sconn, vuid)) {
858                 /* No, start a new authentication setup. */
859                 vuid = register_initial_vuid(sconn);
860                 if (vuid == UID_FIELD_INVALID) {
861                         data_blob_free(&blob1);
862                         reply_nterror(req, nt_status_squash(
863                                               NT_STATUS_INVALID_PARAMETER));
864                         return;
865                 }
866         }
867
868         vuser = get_partial_auth_user_struct(sconn, vuid);
869         /* This MUST be valid. */
870         if (!vuser) {
871                 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
872         }
873
874         if (!vuser->gensec_security) {
875                 status = auth_generic_prepare(vuser, sconn->remote_address,
876                                               &vuser->gensec_security);
877                 if (!NT_STATUS_IS_OK(status)) {
878                         /* Kill the intermediate vuid */
879                         invalidate_vuid(sconn, vuid);
880                         data_blob_free(&blob1);
881                         reply_nterror(req, nt_status_squash(status));
882                         return;
883                 }
884
885                 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_SESSION_KEY);
886                 gensec_want_feature(vuser->gensec_security, GENSEC_FEATURE_UNIX_TOKEN);
887
888                 if (sconn->use_gensec_hook) {
889                         status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_SPNEGO);
890                 } else {
891                         status = gensec_start_mech_by_oid(vuser->gensec_security, GENSEC_OID_NTLMSSP);
892                 }
893                 if (!NT_STATUS_IS_OK(status)) {
894                         /* Kill the intermediate vuid */
895                         invalidate_vuid(sconn, vuid);
896                         data_blob_free(&blob1);
897                         reply_nterror(req, nt_status_squash(status));
898                         return;
899                 }
900         }
901
902         status = gensec_update(vuser->gensec_security,
903                                talloc_tos(), NULL,
904                                blob1, &chal);
905
906         data_blob_free(&blob1);
907
908         reply_spnego_ntlmssp(req, vuid,
909                              &vuser->gensec_security,
910                              &chal, status, NULL, false);
911         data_blob_free(&chal);
912         return;
913 }
914
915 /****************************************************************************
916  On new VC == 0, shutdown *all* old connections and users.
917  It seems that only NT4.x does this. At W2K and above (XP etc.).
918  a new session setup with VC==0 is ignored.
919 ****************************************************************************/
920
921 struct shutdown_state {
922         const char *ip;
923         struct messaging_context *msg_ctx;
924 };
925
926 static int shutdown_other_smbds(const struct connections_key *key,
927                                 const struct connections_data *crec,
928                                 void *private_data)
929 {
930         struct shutdown_state *state = (struct shutdown_state *)private_data;
931
932         DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
933                    server_id_str(talloc_tos(), &crec->pid), crec->addr));
934
935         if (!process_exists(crec->pid)) {
936                 DEBUG(10, ("process does not exist\n"));
937                 return 0;
938         }
939
940         if (procid_is_me(&crec->pid)) {
941                 DEBUG(10, ("It's me\n"));
942                 return 0;
943         }
944
945         if (strcmp(state->ip, crec->addr) != 0) {
946                 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
947                 return 0;
948         }
949
950         DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
951                   "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
952                   state->ip));
953
954         messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
955                        &data_blob_null);
956         return 0;
957 }
958
959 static void setup_new_vc_session(struct smbd_server_connection *sconn)
960 {
961         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
962                 "compatible we would close all old resources.\n"));
963 #if 0
964         conn_close_all();
965         invalidate_all_vuids();
966 #endif
967         if (lp_reset_on_zero_vc()) {
968                 char *addr;
969                 struct shutdown_state state;
970
971                 addr = tsocket_address_inet_addr_string(
972                         sconn->remote_address, talloc_tos());
973                 if (addr == NULL) {
974                         return;
975                 }
976                 state.ip = addr;
977                 state.msg_ctx = sconn->msg_ctx;
978                 connections_forall_read(shutdown_other_smbds, &state);
979                 TALLOC_FREE(addr);
980         }
981 }
982
983 /****************************************************************************
984  Reply to a session setup command.
985 ****************************************************************************/
986
987 void reply_sesssetup_and_X(struct smb_request *req)
988 {
989         int sess_vuid;
990         int smb_bufsize;
991         DATA_BLOB lm_resp;
992         DATA_BLOB nt_resp;
993         DATA_BLOB plaintext_password;
994         char *tmp;
995         const char *user;
996         fstring sub_user; /* Sanitised username for substituion */
997         const char *domain;
998         const char *native_os;
999         const char *native_lanman;
1000         const char *primary_domain;
1001         struct auth_usersupplied_info *user_info = NULL;
1002         struct auth_serversupplied_info *server_info = NULL;
1003         struct auth_session_info *session_info = NULL;
1004         uint16 smb_flag2 = req->flags2;
1005
1006         NTSTATUS nt_status;
1007         struct smbd_server_connection *sconn = req->sconn;
1008
1009         bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1010         bool signing_allowed = false;
1011         bool signing_mandatory = false;
1012
1013         START_PROFILE(SMBsesssetupX);
1014
1015         ZERO_STRUCT(lm_resp);
1016         ZERO_STRUCT(nt_resp);
1017         ZERO_STRUCT(plaintext_password);
1018
1019         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1020
1021         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
1022                 signing_allowed = true;
1023         }
1024         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
1025                 signing_mandatory = true;
1026         }
1027
1028         /*
1029          * We can call srv_set_signing_negotiated() each time.
1030          * It finds out when it needs to turn into a noop
1031          * itself.
1032          */
1033         srv_set_signing_negotiated(req->sconn,
1034                                    signing_allowed,
1035                                    signing_mandatory);
1036
1037         /* a SPNEGO session setup has 12 command words, whereas a normal
1038            NT1 session setup has 13. See the cifs spec. */
1039         if (req->wct == 12 &&
1040             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1041
1042                 if (!sconn->smb1.negprot.spnego) {
1043                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1044                                  "at SPNEGO session setup when it was not "
1045                                  "negotiated.\n"));
1046                         reply_nterror(req, nt_status_squash(
1047                                               NT_STATUS_LOGON_FAILURE));
1048                         END_PROFILE(SMBsesssetupX);
1049                         return;
1050                 }
1051
1052                 if (SVAL(req->vwv+4, 0) == 0) {
1053                         setup_new_vc_session(req->sconn);
1054                 }
1055
1056                 reply_sesssetup_and_X_spnego(req);
1057                 END_PROFILE(SMBsesssetupX);
1058                 return;
1059         }
1060
1061         smb_bufsize = SVAL(req->vwv+2, 0);
1062
1063         if (get_Protocol() < PROTOCOL_NT1) {
1064                 uint16 passlen1 = SVAL(req->vwv+7, 0);
1065
1066                 /* Never do NT status codes with protocols before NT1 as we
1067                  * don't get client caps. */
1068                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1069
1070                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1071                         reply_nterror(req, nt_status_squash(
1072                                               NT_STATUS_INVALID_PARAMETER));
1073                         END_PROFILE(SMBsesssetupX);
1074                         return;
1075                 }
1076
1077                 if (doencrypt) {
1078                         lm_resp = data_blob(req->buf, passlen1);
1079                 } else {
1080                         plaintext_password = data_blob(req->buf, passlen1+1);
1081                         /* Ensure null termination */
1082                         plaintext_password.data[passlen1] = 0;
1083                 }
1084
1085                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1086                                        req->buf + passlen1, STR_TERMINATE);
1087                 user = tmp ? tmp : "";
1088
1089                 domain = "";
1090
1091         } else {
1092                 uint16 passlen1 = SVAL(req->vwv+7, 0);
1093                 uint16 passlen2 = SVAL(req->vwv+8, 0);
1094                 enum remote_arch_types ra_type = get_remote_arch();
1095                 const uint8_t *p = req->buf;
1096                 const uint8_t *save_p = req->buf;
1097                 uint16 byte_count;
1098
1099
1100                 if(global_client_caps == 0) {
1101                         global_client_caps = IVAL(req->vwv+11, 0);
1102
1103                         if (!(global_client_caps & CAP_STATUS32)) {
1104                                 remove_from_common_flags2(
1105                                                 FLAGS2_32_BIT_ERROR_CODES);
1106                         }
1107
1108                         /* client_caps is used as final determination if
1109                          * client is NT or Win95. This is needed to return
1110                          * the correct error codes in some circumstances.
1111                         */
1112
1113                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1114                                         ra_type == RA_WIN95) {
1115                                 if(!(global_client_caps & (CAP_NT_SMBS|
1116                                                         CAP_STATUS32))) {
1117                                         set_remote_arch( RA_WIN95);
1118                                 }
1119                         }
1120                 }
1121
1122                 if (!doencrypt) {
1123                         /* both Win95 and WinNT stuff up the password
1124                          * lengths for non-encrypting systems. Uggh.
1125
1126                            if passlen1==24 its a win95 system, and its setting
1127                            the password length incorrectly. Luckily it still
1128                            works with the default code because Win95 will null
1129                            terminate the password anyway
1130
1131                            if passlen1>0 and passlen2>0 then maybe its a NT box
1132                            and its setting passlen2 to some random value which
1133                            really stuffs things up. we need to fix that one.  */
1134
1135                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1136                                         passlen2 != 1) {
1137                                 passlen2 = 0;
1138                         }
1139                 }
1140
1141                 /* check for nasty tricks */
1142                 if (passlen1 > MAX_PASS_LEN
1143                     || passlen1 > smbreq_bufrem(req, p)) {
1144                         reply_nterror(req, nt_status_squash(
1145                                               NT_STATUS_INVALID_PARAMETER));
1146                         END_PROFILE(SMBsesssetupX);
1147                         return;
1148                 }
1149
1150                 if (passlen2 > MAX_PASS_LEN
1151                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1152                         reply_nterror(req, nt_status_squash(
1153                                               NT_STATUS_INVALID_PARAMETER));
1154                         END_PROFILE(SMBsesssetupX);
1155                         return;
1156                 }
1157
1158                 /* Save the lanman2 password and the NT md4 password. */
1159
1160                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1161                         doencrypt = False;
1162                 }
1163
1164                 if (doencrypt) {
1165                         lm_resp = data_blob(p, passlen1);
1166                         nt_resp = data_blob(p+passlen1, passlen2);
1167                 } else if (lp_security() != SEC_SHARE) {
1168                         /*
1169                          * In share level we should ignore any passwords, so
1170                          * only read them if we're not.
1171                          */
1172                         char *pass = NULL;
1173                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1174
1175                         if (unic && (passlen2 == 0) && passlen1) {
1176                                 /* Only a ascii plaintext password was sent. */
1177                                 (void)srvstr_pull_talloc(talloc_tos(),
1178                                                         req->inbuf,
1179                                                         req->flags2,
1180                                                         &pass,
1181                                                         req->buf,
1182                                                         passlen1,
1183                                                         STR_TERMINATE|STR_ASCII);
1184                         } else {
1185                                 (void)srvstr_pull_talloc(talloc_tos(),
1186                                                         req->inbuf,
1187                                                         req->flags2,
1188                                                         &pass,
1189                                                         req->buf,
1190                                                         unic ? passlen2 : passlen1,
1191                                                         STR_TERMINATE);
1192                         }
1193                         if (!pass) {
1194                                 reply_nterror(req, nt_status_squash(
1195                                               NT_STATUS_INVALID_PARAMETER));
1196                                 END_PROFILE(SMBsesssetupX);
1197                                 return;
1198                         }
1199                         plaintext_password = data_blob(pass, strlen(pass)+1);
1200                 }
1201
1202                 p += passlen1 + passlen2;
1203
1204                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1205                                             STR_TERMINATE);
1206                 user = tmp ? tmp : "";
1207
1208                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1209                                             STR_TERMINATE);
1210                 domain = tmp ? tmp : "";
1211
1212                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1213                                             STR_TERMINATE);
1214                 native_os = tmp ? tmp : "";
1215
1216                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1217                                             STR_TERMINATE);
1218                 native_lanman = tmp ? tmp : "";
1219
1220                 /* not documented or decoded by Ethereal but there is one more
1221                  * string in the extra bytes which is the same as the
1222                  * PrimaryDomain when using extended security.  Windows NT 4
1223                  * and 2003 use this string to store the native lanman string.
1224                  * Windows 9x does not include a string here at all so we have
1225                  * to check if we have any extra bytes left */
1226
1227                 byte_count = SVAL(req->vwv+13, 0);
1228                 if ( PTR_DIFF(p, save_p) < byte_count) {
1229                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1230                                                     STR_TERMINATE);
1231                         primary_domain = tmp ? tmp : "";
1232                 } else {
1233                         primary_domain = talloc_strdup(talloc_tos(), "null");
1234                 }
1235
1236                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
1237                         "PrimaryDomain=[%s]\n",
1238                         domain, native_os, native_lanman, primary_domain));
1239
1240                 if ( ra_type == RA_WIN2K ) {
1241                         if ( strlen(native_lanman) == 0 )
1242                                 ra_lanman_string( primary_domain );
1243                         else
1244                                 ra_lanman_string( native_lanman );
1245                 }
1246
1247         }
1248
1249         if (SVAL(req->vwv+4, 0) == 0) {
1250                 setup_new_vc_session(req->sconn);
1251         }
1252
1253         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1254                                 domain, user, get_remote_machine_name()));
1255
1256         if (*user) {
1257                 if (sconn->smb1.negprot.spnego) {
1258
1259                         /* This has to be here, because this is a perfectly
1260                          * valid behaviour for guest logons :-( */
1261
1262                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1263                                 "at 'normal' session setup after "
1264                                 "negotiating spnego.\n"));
1265                         reply_nterror(req, nt_status_squash(
1266                                               NT_STATUS_LOGON_FAILURE));
1267                         END_PROFILE(SMBsesssetupX);
1268                         return;
1269                 }
1270                 fstrcpy(sub_user, user);
1271         } else {
1272                 fstrcpy(sub_user, "");
1273         }
1274
1275         sub_set_smb_name(sub_user);
1276
1277         reload_services(sconn, conn_snum_used, true);
1278
1279         if (lp_security() == SEC_SHARE) {
1280                 char *sub_user_mapped = NULL;
1281                 /* In share level we should ignore any passwords */
1282
1283                 data_blob_free(&lm_resp);
1284                 data_blob_free(&nt_resp);
1285                 data_blob_clear_free(&plaintext_password);
1286
1287                 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1288                 if (!sub_user_mapped) {
1289                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1290                         END_PROFILE(SMBsesssetupX);
1291                         return;
1292                 }
1293                 fstrcpy(sub_user, sub_user_mapped);
1294                 add_session_user(sconn, sub_user);
1295                 add_session_workgroup(sconn, domain);
1296                 /* Then force it to null for the benfit of the code below */
1297                 user = "";
1298         }
1299
1300         if (!*user) {
1301
1302                 nt_status = check_guest_password(sconn->remote_address, &server_info);
1303
1304         } else if (doencrypt) {
1305                 struct auth_context *negprot_auth_context = NULL;
1306                 negprot_auth_context = sconn->smb1.negprot.auth_context;
1307                 if (!negprot_auth_context) {
1308                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
1309                                 "session setup without negprot denied!\n"));
1310                         reply_nterror(req, nt_status_squash(
1311                                               NT_STATUS_LOGON_FAILURE));
1312                         END_PROFILE(SMBsesssetupX);
1313                         return;
1314                 }
1315                 nt_status = make_user_info_for_reply_enc(&user_info, user,
1316                                                 domain,
1317                                                 sconn->remote_address,
1318                                                 lm_resp, nt_resp);
1319                 if (NT_STATUS_IS_OK(nt_status)) {
1320                         nt_status = negprot_auth_context->check_ntlm_password(
1321                                         negprot_auth_context,
1322                                         user_info,
1323                                         &server_info);
1324                 }
1325         } else {
1326                 struct auth_context *plaintext_auth_context = NULL;
1327
1328                 nt_status = make_auth_context_subsystem(
1329                         talloc_tos(), &plaintext_auth_context);
1330
1331                 if (NT_STATUS_IS_OK(nt_status)) {
1332                         uint8_t chal[8];
1333
1334                         plaintext_auth_context->get_ntlm_challenge(
1335                                         plaintext_auth_context, chal);
1336
1337                         if (!make_user_info_for_reply(&user_info,
1338                                                       user, domain,
1339                                                       sconn->remote_address,
1340                                                       chal,
1341                                                       plaintext_password)) {
1342                                 nt_status = NT_STATUS_NO_MEMORY;
1343                         }
1344
1345                         if (NT_STATUS_IS_OK(nt_status)) {
1346                                 nt_status = plaintext_auth_context->check_ntlm_password(
1347                                                 plaintext_auth_context,
1348                                                 user_info,
1349                                                 &server_info);
1350
1351                                 TALLOC_FREE(plaintext_auth_context);
1352                         }
1353                 }
1354         }
1355
1356         free_user_info(&user_info);
1357
1358         if (!NT_STATUS_IS_OK(nt_status)) {
1359                 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
1360                                                         user, domain);
1361         }
1362
1363         if (!NT_STATUS_IS_OK(nt_status)) {
1364                 data_blob_free(&nt_resp);
1365                 data_blob_free(&lm_resp);
1366                 data_blob_clear_free(&plaintext_password);
1367                 reply_nterror(req, nt_status_squash(nt_status));
1368                 END_PROFILE(SMBsesssetupX);
1369                 return;
1370         }
1371
1372         nt_status = create_local_token(req, server_info, NULL, sub_user, &session_info);
1373         TALLOC_FREE(server_info);
1374
1375         if (!NT_STATUS_IS_OK(nt_status)) {
1376                 DEBUG(10, ("create_local_token failed: %s\n",
1377                            nt_errstr(nt_status)));
1378                 data_blob_free(&nt_resp);
1379                 data_blob_free(&lm_resp);
1380                 data_blob_clear_free(&plaintext_password);
1381                 reply_nterror(req, nt_status_squash(nt_status));
1382                 END_PROFILE(SMBsesssetupX);
1383                 return;
1384         }
1385
1386         data_blob_clear_free(&plaintext_password);
1387
1388         /* it's ok - setup a reply */
1389         reply_outbuf(req, 3, 0);
1390         if (get_Protocol() >= PROTOCOL_NT1) {
1391                 push_signature(&req->outbuf);
1392                 /* perhaps grab OS version here?? */
1393         }
1394
1395         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
1396                 SSVAL(req->outbuf,smb_vwv2,1);
1397         }
1398
1399         /* register the name and uid as being validated, so further connections
1400            to a uid can get through without a password, on the same VC */
1401
1402         if (lp_security() == SEC_SHARE) {
1403                 sess_vuid = UID_FIELD_INVALID;
1404                 TALLOC_FREE(session_info);
1405         } else {
1406                 /* Ignore the initial vuid. */
1407                 sess_vuid = register_initial_vuid(sconn);
1408                 if (sess_vuid == UID_FIELD_INVALID) {
1409                         data_blob_free(&nt_resp);
1410                         data_blob_free(&lm_resp);
1411                         reply_nterror(req, nt_status_squash(
1412                                               NT_STATUS_LOGON_FAILURE));
1413                         END_PROFILE(SMBsesssetupX);
1414                         return;
1415                 }
1416                 /* register_existing_vuid keeps the session_info */
1417                 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1418                                         session_info,
1419                                         nt_resp.data ? nt_resp : lm_resp);
1420                 if (sess_vuid == UID_FIELD_INVALID) {
1421                         data_blob_free(&nt_resp);
1422                         data_blob_free(&lm_resp);
1423                         reply_nterror(req, nt_status_squash(
1424                                               NT_STATUS_LOGON_FAILURE));
1425                         END_PROFILE(SMBsesssetupX);
1426                         return;
1427                 }
1428
1429                 /* current_user_info is changed on new vuid */
1430                 reload_services(sconn, conn_snum_used, true);
1431         }
1432
1433         data_blob_free(&nt_resp);
1434         data_blob_free(&lm_resp);
1435
1436         SSVAL(req->outbuf,smb_uid,sess_vuid);
1437         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1438         req->vuid = sess_vuid;
1439
1440         if (!sconn->smb1.sessions.done_sesssetup) {
1441                 sconn->smb1.sessions.max_send =
1442                         MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1443         }
1444         sconn->smb1.sessions.done_sesssetup = true;
1445
1446         END_PROFILE(SMBsesssetupX);
1447         chain_reply(req);
1448         return;
1449 }