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