s3-ntlmssp Remove calls to auth_ntlmssp_and_flags from the server
[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, user);
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                                            auth_ntlmssp_get_username(*auth_ntlmssp_state)) !=
453                                            vuid) {
454                         /* The problem is, *auth_ntlmssp_state points
455                          * into the vuser this will have
456                          * talloc_free()'ed in
457                          * register_existing_vuid() */
458                         do_invalidate = false;
459                         nt_status = NT_STATUS_LOGON_FAILURE;
460                         goto out;
461                 }
462
463                 /* current_user_info is changed on new vuid */
464                 reload_services(sconn->msg_ctx, sconn->sock, True);
465
466                 SSVAL(req->outbuf, smb_vwv3, 0);
467
468                 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
469                         SSVAL(req->outbuf,smb_vwv2,1);
470                 }
471         }
472
473   out:
474
475         if (wrap) {
476                 response = spnego_gen_auth_response(talloc_tos(),
477                                 ntlmssp_blob,
478                                 nt_status, OID);
479         } else {
480                 response = *ntlmssp_blob;
481         }
482
483         reply_sesssetup_blob(req, response, nt_status);
484         if (wrap) {
485                 data_blob_free(&response);
486         }
487
488         /* NT_STATUS_MORE_PROCESSING_REQUIRED from our NTLMSSP code tells us,
489            and the other end, that we are not finished yet. */
490
491         if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
492                 /* NB. This is *NOT* an error case. JRA */
493                 if (do_invalidate) {
494                         TALLOC_FREE(*auth_ntlmssp_state);
495                         if (!NT_STATUS_IS_OK(nt_status)) {
496                                 /* Kill the intermediate vuid */
497                                 invalidate_vuid(sconn, vuid);
498                         }
499                 }
500         }
501 }
502
503 /****************************************************************************
504  Is this a krb5 mechanism ?
505 ****************************************************************************/
506
507 NTSTATUS parse_spnego_mechanisms(TALLOC_CTX *ctx,
508                 DATA_BLOB blob_in,
509                 DATA_BLOB *pblob_out,
510                 char **kerb_mechOID)
511 {
512         char *OIDs[ASN1_MAX_OIDS];
513         int i;
514         NTSTATUS ret = NT_STATUS_OK;
515
516         *kerb_mechOID = NULL;
517
518         /* parse out the OIDs and the first sec blob */
519         if (!spnego_parse_negTokenInit(ctx, blob_in, OIDs, NULL, pblob_out) ||
520                         (OIDs[0] == NULL)) {
521                 return NT_STATUS_LOGON_FAILURE;
522         }
523
524         /* only look at the first OID for determining the mechToken --
525            according to RFC2478, we should choose the one we want
526            and renegotiate, but i smell a client bug here..
527
528            Problem observed when connecting to a member (samba box)
529            of an AD domain as a user in a Samba domain.  Samba member
530            server sent back krb5/mskrb5/ntlmssp as mechtypes, but the
531            client (2ksp3) replied with ntlmssp/mskrb5/krb5 and an
532            NTLMSSP mechtoken.                 --jerry              */
533
534 #ifdef HAVE_KRB5
535         if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
536             strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
537                 *kerb_mechOID = talloc_strdup(ctx, OIDs[0]);
538                 if (*kerb_mechOID == NULL) {
539                         ret = NT_STATUS_NO_MEMORY;
540                 }
541         }
542 #endif
543
544         for (i=0;OIDs[i];i++) {
545                 DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
546                 talloc_free(OIDs[i]);
547         }
548         return ret;
549 }
550
551 /****************************************************************************
552  Fall back from krb5 to NTLMSSP.
553 ****************************************************************************/
554
555 static void reply_spnego_downgrade_to_ntlmssp(struct smb_request *req,
556                                                 uint16 vuid)
557 {
558         DATA_BLOB response;
559
560         reply_outbuf(req, 4, 0);
561         SSVAL(req->outbuf,smb_uid,vuid);
562
563         DEBUG(3,("reply_spnego_downgrade_to_ntlmssp: Got krb5 ticket in SPNEGO "
564                 "but set to downgrade to NTLMSSP\n"));
565
566         response = spnego_gen_auth_response(talloc_tos(), NULL,
567                         NT_STATUS_MORE_PROCESSING_REQUIRED,
568                         OID_NTLMSSP);
569         reply_sesssetup_blob(req, response, NT_STATUS_MORE_PROCESSING_REQUIRED);
570         data_blob_free(&response);
571 }
572
573 /****************************************************************************
574  Reply to a session setup spnego negotiate packet.
575 ****************************************************************************/
576
577 static void reply_spnego_negotiate(struct smb_request *req,
578                                    uint16 vuid,
579                                    DATA_BLOB blob1,
580                                    struct auth_ntlmssp_state **auth_ntlmssp_state)
581 {
582         DATA_BLOB secblob;
583         DATA_BLOB chal;
584         char *kerb_mech = NULL;
585         NTSTATUS status;
586         struct smbd_server_connection *sconn = req->sconn;
587
588         status = parse_spnego_mechanisms(talloc_tos(),
589                         blob1, &secblob, &kerb_mech);
590         if (!NT_STATUS_IS_OK(status)) {
591                 /* Kill the intermediate vuid */
592                 invalidate_vuid(sconn, vuid);
593                 reply_nterror(req, nt_status_squash(status));
594                 return;
595         }
596
597         DEBUG(3,("reply_spnego_negotiate: Got secblob of size %lu\n",
598                                 (unsigned long)secblob.length));
599
600 #ifdef HAVE_KRB5
601         if (kerb_mech && ((lp_security()==SEC_ADS) ||
602                                 USE_KERBEROS_KEYTAB) ) {
603                 bool destroy_vuid = True;
604                 reply_spnego_kerberos(req, &secblob, kerb_mech,
605                                       vuid, &destroy_vuid);
606                 data_blob_free(&secblob);
607                 if (destroy_vuid) {
608                         /* Kill the intermediate vuid */
609                         invalidate_vuid(sconn, vuid);
610                 }
611                 TALLOC_FREE(kerb_mech);
612                 return;
613         }
614 #endif
615
616         TALLOC_FREE(*auth_ntlmssp_state);
617
618         if (kerb_mech) {
619                 data_blob_free(&secblob);
620                 /* The mechtoken is a krb5 ticket, but
621                  * we need to fall back to NTLM. */
622                 reply_spnego_downgrade_to_ntlmssp(req, vuid);
623                 TALLOC_FREE(kerb_mech);
624                 return;
625         }
626
627         status = auth_ntlmssp_start(sconn->remote_address,
628                                     auth_ntlmssp_state);
629         if (!NT_STATUS_IS_OK(status)) {
630                 /* Kill the intermediate vuid */
631                 invalidate_vuid(sconn, vuid);
632                 reply_nterror(req, nt_status_squash(status));
633                 return;
634         }
635
636         auth_ntlmssp_want_feature(*auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
637
638         status = auth_ntlmssp_update(*auth_ntlmssp_state, talloc_tos(),
639                                         secblob, &chal);
640
641         data_blob_free(&secblob);
642
643         reply_spnego_ntlmssp(req, vuid, auth_ntlmssp_state,
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 auth_ntlmssp_state **auth_ntlmssp_state)
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 (!*auth_ntlmssp_state) {
731                 status = auth_ntlmssp_start(sconn->remote_address,
732                                             auth_ntlmssp_state);
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
741         status = auth_ntlmssp_update(*auth_ntlmssp_state, talloc_tos(),
742                                      auth, &auth_reply);
743
744         data_blob_free(&auth);
745
746         /* Don't send the mechid as we've already sent this (RFC4178). */
747
748         reply_spnego_ntlmssp(req, vuid,
749                              auth_ntlmssp_state,
750                              &auth_reply, status, NULL, true);
751
752         data_blob_free(&auth_reply);
753
754         /* and tell smbd that we have already replied to this packet */
755         return;
756 }
757
758 /****************************************************************************
759  Delete an entry on the list.
760 ****************************************************************************/
761
762 static void delete_partial_auth(struct smbd_server_connection *sconn,
763                                 struct pending_auth_data *pad)
764 {
765         if (!pad) {
766                 return;
767         }
768         DLIST_REMOVE(sconn->smb1.pd_list, pad);
769         data_blob_free(&pad->partial_data);
770         SAFE_FREE(pad);
771 }
772
773 /****************************************************************************
774  Search for a partial SPNEGO auth fragment matching an smbpid.
775 ****************************************************************************/
776
777 static struct pending_auth_data *get_pending_auth_data(
778                 struct smbd_server_connection *sconn,
779                 uint16_t smbpid)
780 {
781         struct pending_auth_data *pad;
782 /*
783  * NOTE: using the smbpid here is completely wrong...
784  *       see [MS-SMB]
785  *       3.3.5.3 Receiving an SMB_COM_SESSION_SETUP_ANDX Request
786  */
787         for (pad = sconn->smb1.pd_list; pad; pad = pad->next) {
788                 if (pad->smbpid == smbpid) {
789                         break;
790                 }
791         }
792         return pad;
793 }
794
795 /****************************************************************************
796  Check the size of an SPNEGO blob. If we need more return
797  NT_STATUS_MORE_PROCESSING_REQUIRED, else return NT_STATUS_OK. Don't allow
798  the blob to be more than 64k.
799 ****************************************************************************/
800
801 static NTSTATUS check_spnego_blob_complete(struct smbd_server_connection *sconn,
802                                            uint16 smbpid, uint16 vuid,
803                                            DATA_BLOB *pblob)
804 {
805         struct pending_auth_data *pad = NULL;
806         ASN1_DATA *data;
807         size_t needed_len = 0;
808
809         pad = get_pending_auth_data(sconn, smbpid);
810
811         /* Ensure we have some data. */
812         if (pblob->length == 0) {
813                 /* Caller can cope. */
814                 DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
815                 delete_partial_auth(sconn, pad);
816                 return NT_STATUS_OK;
817         }
818
819         /* Were we waiting for more data ? */
820         if (pad) {
821                 DATA_BLOB tmp_blob;
822                 size_t copy_len = MIN(65536, pblob->length);
823
824                 /* Integer wrap paranoia.... */
825
826                 if (pad->partial_data.length + copy_len <
827                                 pad->partial_data.length ||
828                     pad->partial_data.length + copy_len < copy_len) {
829
830                         DEBUG(2,("check_spnego_blob_complete: integer wrap "
831                                 "pad->partial_data.length = %u, "
832                                 "copy_len = %u\n",
833                                 (unsigned int)pad->partial_data.length,
834                                 (unsigned int)copy_len ));
835
836                         delete_partial_auth(sconn, pad);
837                         return NT_STATUS_INVALID_PARAMETER;
838                 }
839
840                 DEBUG(10,("check_spnego_blob_complete: "
841                         "pad->partial_data.length = %u, "
842                         "pad->needed_len = %u, "
843                         "copy_len = %u, "
844                         "pblob->length = %u,\n",
845                         (unsigned int)pad->partial_data.length,
846                         (unsigned int)pad->needed_len,
847                         (unsigned int)copy_len,
848                         (unsigned int)pblob->length ));
849
850                 tmp_blob = data_blob(NULL,
851                                 pad->partial_data.length + copy_len);
852
853                 /* Concatenate the two (up to copy_len) bytes. */
854                 memcpy(tmp_blob.data,
855                         pad->partial_data.data,
856                         pad->partial_data.length);
857                 memcpy(tmp_blob.data + pad->partial_data.length,
858                         pblob->data,
859                         copy_len);
860
861                 /* Replace the partial data. */
862                 data_blob_free(&pad->partial_data);
863                 pad->partial_data = tmp_blob;
864                 ZERO_STRUCT(tmp_blob);
865
866                 /* Are we done ? */
867                 if (pblob->length >= pad->needed_len) {
868                         /* Yes, replace pblob. */
869                         data_blob_free(pblob);
870                         *pblob = pad->partial_data;
871                         ZERO_STRUCT(pad->partial_data);
872                         delete_partial_auth(sconn, pad);
873                         return NT_STATUS_OK;
874                 }
875
876                 /* Still need more data. */
877                 pad->needed_len -= copy_len;
878                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
879         }
880
881         if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
882             (pblob->data[0] != ASN1_CONTEXT(1))) {
883                 /* Not something we can determine the
884                  * length of.
885                  */
886                 return NT_STATUS_OK;
887         }
888
889         /* This is a new SPNEGO sessionsetup - see if
890          * the data given in this blob is enough.
891          */
892
893         data = asn1_init(NULL);
894         if (data == NULL) {
895                 return NT_STATUS_NO_MEMORY;
896         }
897
898         asn1_load(data, *pblob);
899         if (asn1_start_tag(data, pblob->data[0])) {
900                 /* asn1_start_tag checks if the given
901                    length of the blob is enough to complete
902                    the tag. If it returns true we know
903                    there is nothing to do - the blob is
904                    complete. */
905                 asn1_free(data);
906                 return NT_STATUS_OK;
907         }
908
909         if (data->nesting == NULL) {
910                 /* Incorrect tag, allocation failed,
911                    or reading the tag length failed.
912                    Let the caller catch. */
913                 asn1_free(data);
914                 return NT_STATUS_OK;
915         }
916
917         /* Here we know asn1_start_tag() has set data->has_error to true.
918            asn1_tag_remaining() will have failed due to the given blob
919            being too short. We need to work out how short. */
920
921         /* Integer wrap paranoia.... */
922
923         if (data->nesting->taglen + data->nesting->start < data->nesting->taglen ||
924             data->nesting->taglen + data->nesting->start < data->nesting->start) {
925
926                 DEBUG(2,("check_spnego_blob_complete: integer wrap "
927                         "data.nesting->taglen = %u, "
928                         "data.nesting->start = %u\n",
929                         (unsigned int)data->nesting->taglen,
930                         (unsigned int)data->nesting->start ));
931
932                 asn1_free(data);
933                 return NT_STATUS_INVALID_PARAMETER;
934         }
935
936         /* Total length of the needed asn1 is the tag length
937          * plus the current offset. */
938
939         needed_len = data->nesting->taglen + data->nesting->start;
940         asn1_free(data);
941
942         DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
943                 "pblob->length = %u\n",
944                 (unsigned int)needed_len,
945                 (unsigned int)pblob->length ));
946
947         if (needed_len <= pblob->length) {
948                 /* Nothing to do - blob is complete. */
949                 /* THIS SHOULD NOT HAPPEN - asn1_start_tag()
950                    above should have caught this !!! */
951                 DEBUG(0,("check_spnego_blob_complete: logic "
952                         "error (needed_len = %u, "
953                         "pblob->length = %u).\n",
954                         (unsigned int)needed_len,
955                         (unsigned int)pblob->length ));
956                 return NT_STATUS_OK;
957         }
958
959         /* Refuse the blob if it's bigger than 64k. */
960         if (needed_len > 65536) {
961                 DEBUG(2,("check_spnego_blob_complete: needed_len "
962                         "too large (%u)\n",
963                         (unsigned int)needed_len ));
964                 return NT_STATUS_INVALID_PARAMETER;
965         }
966
967         /* We must store this blob until complete. */
968         if (!(pad = SMB_MALLOC_P(struct pending_auth_data))) {
969                 return NT_STATUS_NO_MEMORY;
970         }
971         pad->needed_len = needed_len - pblob->length;
972         pad->partial_data = data_blob(pblob->data, pblob->length);
973         if (pad->partial_data.data == NULL) {
974                 SAFE_FREE(pad);
975                 return NT_STATUS_NO_MEMORY;
976         }
977         pad->smbpid = smbpid;
978         pad->vuid = vuid;
979         DLIST_ADD(sconn->smb1.pd_list, pad);
980
981         return NT_STATUS_MORE_PROCESSING_REQUIRED;
982 }
983
984 /****************************************************************************
985  Reply to a session setup command.
986  conn POINTER CAN BE NULL HERE !
987 ****************************************************************************/
988
989 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
990 {
991         const uint8 *p;
992         DATA_BLOB blob1;
993         size_t bufrem;
994         char *tmp;
995         const char *native_os;
996         const char *native_lanman;
997         const char *primary_domain;
998         const char *p2;
999         uint16 data_blob_len = SVAL(req->vwv+7, 0);
1000         enum remote_arch_types ra_type = get_remote_arch();
1001         int vuid = req->vuid;
1002         user_struct *vuser = NULL;
1003         NTSTATUS status = NT_STATUS_OK;
1004         uint16 smbpid = req->smbpid;
1005         struct smbd_server_connection *sconn = req->sconn;
1006
1007         DEBUG(3,("Doing spnego session setup\n"));
1008
1009         if (global_client_caps == 0) {
1010                 global_client_caps = IVAL(req->vwv+10, 0);
1011
1012                 if (!(global_client_caps & CAP_STATUS32)) {
1013                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1014                 }
1015
1016         }
1017
1018         p = req->buf;
1019
1020         if (data_blob_len == 0) {
1021                 /* an invalid request */
1022                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1023                 return;
1024         }
1025
1026         bufrem = smbreq_bufrem(req, p);
1027         /* pull the spnego blob */
1028         blob1 = data_blob(p, MIN(bufrem, data_blob_len));
1029
1030 #if 0
1031         file_save("negotiate.dat", blob1.data, blob1.length);
1032 #endif
1033
1034         p2 = (const char *)req->buf + blob1.length;
1035
1036         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1037                                      STR_TERMINATE);
1038         native_os = tmp ? tmp : "";
1039
1040         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1041                                      STR_TERMINATE);
1042         native_lanman = tmp ? tmp : "";
1043
1044         p2 += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p2,
1045                                      STR_TERMINATE);
1046         primary_domain = tmp ? tmp : "";
1047
1048         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
1049                 native_os, native_lanman, primary_domain));
1050
1051         if ( ra_type == RA_WIN2K ) {
1052                 /* Vista sets neither the OS or lanman strings */
1053
1054                 if ( !strlen(native_os) && !strlen(native_lanman) )
1055                         set_remote_arch(RA_VISTA);
1056
1057                 /* Windows 2003 doesn't set the native lanman string,
1058                    but does set primary domain which is a bug I think */
1059
1060                 if ( !strlen(native_lanman) ) {
1061                         ra_lanman_string( primary_domain );
1062                 } else {
1063                         ra_lanman_string( native_lanman );
1064                 }
1065         } else if ( ra_type == RA_VISTA ) {
1066                 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
1067                         set_remote_arch(RA_OSX);
1068                 }
1069         }
1070
1071         /* Did we get a valid vuid ? */
1072         if (!is_partial_auth_vuid(sconn, vuid)) {
1073                 /* No, then try and see if this is an intermediate sessionsetup
1074                  * for a large SPNEGO packet. */
1075                 struct pending_auth_data *pad;
1076                 pad = get_pending_auth_data(sconn, smbpid);
1077                 if (pad) {
1078                         DEBUG(10,("reply_sesssetup_and_X_spnego: found "
1079                                 "pending vuid %u\n",
1080                                 (unsigned int)pad->vuid ));
1081                         vuid = pad->vuid;
1082                 }
1083         }
1084
1085         /* Do we have a valid vuid now ? */
1086         if (!is_partial_auth_vuid(sconn, vuid)) {
1087                 /* No, start a new authentication setup. */
1088                 vuid = register_initial_vuid(sconn);
1089                 if (vuid == UID_FIELD_INVALID) {
1090                         data_blob_free(&blob1);
1091                         reply_nterror(req, nt_status_squash(
1092                                               NT_STATUS_INVALID_PARAMETER));
1093                         return;
1094                 }
1095         }
1096
1097         vuser = get_partial_auth_user_struct(sconn, vuid);
1098         /* This MUST be valid. */
1099         if (!vuser) {
1100                 smb_panic("reply_sesssetup_and_X_spnego: invalid vuid.");
1101         }
1102
1103         /* Large (greater than 4k) SPNEGO blobs are split into multiple
1104          * sessionsetup requests as the Windows limit on the security blob
1105          * field is 4k. Bug #4400. JRA.
1106          */
1107
1108         status = check_spnego_blob_complete(sconn, smbpid, vuid, &blob1);
1109         if (!NT_STATUS_IS_OK(status)) {
1110                 if (!NT_STATUS_EQUAL(status,
1111                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
1112                         /* Real error - kill the intermediate vuid */
1113                         invalidate_vuid(sconn, vuid);
1114                 }
1115                 data_blob_free(&blob1);
1116                 reply_nterror(req, nt_status_squash(status));
1117                 return;
1118         }
1119
1120         if (blob1.data[0] == ASN1_APPLICATION(0)) {
1121
1122                 /* its a negTokenTarg packet */
1123
1124                 reply_spnego_negotiate(req, vuid, blob1,
1125                                        &vuser->auth_ntlmssp_state);
1126                 data_blob_free(&blob1);
1127                 return;
1128         }
1129
1130         if (blob1.data[0] == ASN1_CONTEXT(1)) {
1131
1132                 /* its a auth packet */
1133
1134                 reply_spnego_auth(req, vuid, blob1,
1135                                   &vuser->auth_ntlmssp_state);
1136                 data_blob_free(&blob1);
1137                 return;
1138         }
1139
1140         if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
1141                 DATA_BLOB chal;
1142
1143                 if (!vuser->auth_ntlmssp_state) {
1144                         status = auth_ntlmssp_start(sconn->remote_address,
1145                                                     &vuser->auth_ntlmssp_state);
1146                         if (!NT_STATUS_IS_OK(status)) {
1147                                 /* Kill the intermediate vuid */
1148                                 invalidate_vuid(sconn, vuid);
1149                                 data_blob_free(&blob1);
1150                                 reply_nterror(req, nt_status_squash(status));
1151                                 return;
1152                         }
1153                 }
1154
1155                 status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
1156                                              talloc_tos(),
1157                                              blob1, &chal);
1158
1159                 data_blob_free(&blob1);
1160
1161                 reply_spnego_ntlmssp(req, vuid,
1162                                      &vuser->auth_ntlmssp_state,
1163                                      &chal, status, OID_NTLMSSP, false);
1164                 data_blob_free(&chal);
1165                 return;
1166         }
1167
1168         /* what sort of packet is this? */
1169         DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
1170
1171         data_blob_free(&blob1);
1172
1173         reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
1174 }
1175
1176 /****************************************************************************
1177  On new VC == 0, shutdown *all* old connections and users.
1178  It seems that only NT4.x does this. At W2K and above (XP etc.).
1179  a new session setup with VC==0 is ignored.
1180 ****************************************************************************/
1181
1182 struct shutdown_state {
1183         const char *ip;
1184         struct messaging_context *msg_ctx;
1185 };
1186
1187 static int shutdown_other_smbds(const struct connections_key *key,
1188                                 const struct connections_data *crec,
1189                                 void *private_data)
1190 {
1191         struct shutdown_state *state = (struct shutdown_state *)private_data;
1192
1193         DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
1194                    server_id_str(talloc_tos(), &crec->pid), crec->addr));
1195
1196         if (!process_exists(crec->pid)) {
1197                 DEBUG(10, ("process does not exist\n"));
1198                 return 0;
1199         }
1200
1201         if (procid_is_me(&crec->pid)) {
1202                 DEBUG(10, ("It's me\n"));
1203                 return 0;
1204         }
1205
1206         if (strcmp(state->ip, crec->addr) != 0) {
1207                 DEBUG(10, ("%s does not match %s\n", state->ip, crec->addr));
1208                 return 0;
1209         }
1210
1211         DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
1212                   "(IP %s)\n", (unsigned int)procid_to_pid(&crec->pid),
1213                   state->ip));
1214
1215         messaging_send(state->msg_ctx, crec->pid, MSG_SHUTDOWN,
1216                        &data_blob_null);
1217         return 0;
1218 }
1219
1220 static void setup_new_vc_session(struct smbd_server_connection *sconn)
1221 {
1222         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
1223                 "compatible we would close all old resources.\n"));
1224 #if 0
1225         conn_close_all();
1226         invalidate_all_vuids();
1227 #endif
1228         if (lp_reset_on_zero_vc()) {
1229                 char *addr;
1230                 struct shutdown_state state;
1231
1232                 addr = tsocket_address_inet_addr_string(
1233                         sconn->remote_address, talloc_tos());
1234                 if (addr == NULL) {
1235                         return;
1236                 }
1237                 state.ip = addr;
1238                 state.msg_ctx = sconn->msg_ctx;
1239                 connections_forall_read(shutdown_other_smbds, &state);
1240                 TALLOC_FREE(addr);
1241         }
1242 }
1243
1244 /****************************************************************************
1245  Reply to a session setup command.
1246 ****************************************************************************/
1247
1248 void reply_sesssetup_and_X(struct smb_request *req)
1249 {
1250         int sess_vuid;
1251         int smb_bufsize;
1252         DATA_BLOB lm_resp;
1253         DATA_BLOB nt_resp;
1254         DATA_BLOB plaintext_password;
1255         char *tmp;
1256         const char *user;
1257         fstring sub_user; /* Sanitised username for substituion */
1258         const char *domain;
1259         const char *native_os;
1260         const char *native_lanman;
1261         const char *primary_domain;
1262         struct auth_usersupplied_info *user_info = NULL;
1263         struct auth_serversupplied_info *server_info = NULL;
1264         struct auth_session_info *session_info = NULL;
1265         uint16 smb_flag2 = req->flags2;
1266
1267         NTSTATUS nt_status;
1268         struct smbd_server_connection *sconn = req->sconn;
1269
1270         bool doencrypt = sconn->smb1.negprot.encrypted_passwords;
1271
1272         START_PROFILE(SMBsesssetupX);
1273
1274         ZERO_STRUCT(lm_resp);
1275         ZERO_STRUCT(nt_resp);
1276         ZERO_STRUCT(plaintext_password);
1277
1278         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
1279
1280         /* a SPNEGO session setup has 12 command words, whereas a normal
1281            NT1 session setup has 13. See the cifs spec. */
1282         if (req->wct == 12 &&
1283             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
1284
1285                 if (!sconn->smb1.negprot.spnego) {
1286                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1287                                  "at SPNEGO session setup when it was not "
1288                                  "negotiated.\n"));
1289                         reply_nterror(req, nt_status_squash(
1290                                               NT_STATUS_LOGON_FAILURE));
1291                         END_PROFILE(SMBsesssetupX);
1292                         return;
1293                 }
1294
1295                 if (SVAL(req->vwv+4, 0) == 0) {
1296                         setup_new_vc_session(req->sconn);
1297                 }
1298
1299                 reply_sesssetup_and_X_spnego(req);
1300                 END_PROFILE(SMBsesssetupX);
1301                 return;
1302         }
1303
1304         smb_bufsize = SVAL(req->vwv+2, 0);
1305
1306         if (get_Protocol() < PROTOCOL_NT1) {
1307                 uint16 passlen1 = SVAL(req->vwv+7, 0);
1308
1309                 /* Never do NT status codes with protocols before NT1 as we
1310                  * don't get client caps. */
1311                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
1312
1313                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
1314                         reply_nterror(req, nt_status_squash(
1315                                               NT_STATUS_INVALID_PARAMETER));
1316                         END_PROFILE(SMBsesssetupX);
1317                         return;
1318                 }
1319
1320                 if (doencrypt) {
1321                         lm_resp = data_blob(req->buf, passlen1);
1322                 } else {
1323                         plaintext_password = data_blob(req->buf, passlen1+1);
1324                         /* Ensure null termination */
1325                         plaintext_password.data[passlen1] = 0;
1326                 }
1327
1328                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
1329                                        req->buf + passlen1, STR_TERMINATE);
1330                 user = tmp ? tmp : "";
1331
1332                 domain = "";
1333
1334         } else {
1335                 uint16 passlen1 = SVAL(req->vwv+7, 0);
1336                 uint16 passlen2 = SVAL(req->vwv+8, 0);
1337                 enum remote_arch_types ra_type = get_remote_arch();
1338                 const uint8_t *p = req->buf;
1339                 const uint8_t *save_p = req->buf;
1340                 uint16 byte_count;
1341
1342
1343                 if(global_client_caps == 0) {
1344                         global_client_caps = IVAL(req->vwv+11, 0);
1345
1346                         if (!(global_client_caps & CAP_STATUS32)) {
1347                                 remove_from_common_flags2(
1348                                                 FLAGS2_32_BIT_ERROR_CODES);
1349                         }
1350
1351                         /* client_caps is used as final determination if
1352                          * client is NT or Win95. This is needed to return
1353                          * the correct error codes in some circumstances.
1354                         */
1355
1356                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
1357                                         ra_type == RA_WIN95) {
1358                                 if(!(global_client_caps & (CAP_NT_SMBS|
1359                                                         CAP_STATUS32))) {
1360                                         set_remote_arch( RA_WIN95);
1361                                 }
1362                         }
1363                 }
1364
1365                 if (!doencrypt) {
1366                         /* both Win95 and WinNT stuff up the password
1367                          * lengths for non-encrypting systems. Uggh.
1368
1369                            if passlen1==24 its a win95 system, and its setting
1370                            the password length incorrectly. Luckily it still
1371                            works with the default code because Win95 will null
1372                            terminate the password anyway
1373
1374                            if passlen1>0 and passlen2>0 then maybe its a NT box
1375                            and its setting passlen2 to some random value which
1376                            really stuffs things up. we need to fix that one.  */
1377
1378                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
1379                                         passlen2 != 1) {
1380                                 passlen2 = 0;
1381                         }
1382                 }
1383
1384                 /* check for nasty tricks */
1385                 if (passlen1 > MAX_PASS_LEN
1386                     || passlen1 > smbreq_bufrem(req, p)) {
1387                         reply_nterror(req, nt_status_squash(
1388                                               NT_STATUS_INVALID_PARAMETER));
1389                         END_PROFILE(SMBsesssetupX);
1390                         return;
1391                 }
1392
1393                 if (passlen2 > MAX_PASS_LEN
1394                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
1395                         reply_nterror(req, nt_status_squash(
1396                                               NT_STATUS_INVALID_PARAMETER));
1397                         END_PROFILE(SMBsesssetupX);
1398                         return;
1399                 }
1400
1401                 /* Save the lanman2 password and the NT md4 password. */
1402
1403                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
1404                         doencrypt = False;
1405                 }
1406
1407                 if (doencrypt) {
1408                         lm_resp = data_blob(p, passlen1);
1409                         nt_resp = data_blob(p+passlen1, passlen2);
1410                 } else if (lp_security() != SEC_SHARE) {
1411                         /*
1412                          * In share level we should ignore any passwords, so
1413                          * only read them if we're not.
1414                          */
1415                         char *pass = NULL;
1416                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
1417
1418                         if (unic && (passlen2 == 0) && passlen1) {
1419                                 /* Only a ascii plaintext password was sent. */
1420                                 (void)srvstr_pull_talloc(talloc_tos(),
1421                                                         req->inbuf,
1422                                                         req->flags2,
1423                                                         &pass,
1424                                                         req->buf,
1425                                                         passlen1,
1426                                                         STR_TERMINATE|STR_ASCII);
1427                         } else {
1428                                 (void)srvstr_pull_talloc(talloc_tos(),
1429                                                         req->inbuf,
1430                                                         req->flags2,
1431                                                         &pass,
1432                                                         req->buf,
1433                                                         unic ? passlen2 : passlen1,
1434                                                         STR_TERMINATE);
1435                         }
1436                         if (!pass) {
1437                                 reply_nterror(req, nt_status_squash(
1438                                               NT_STATUS_INVALID_PARAMETER));
1439                                 END_PROFILE(SMBsesssetupX);
1440                                 return;
1441                         }
1442                         plaintext_password = data_blob(pass, strlen(pass)+1);
1443                 }
1444
1445                 p += passlen1 + passlen2;
1446
1447                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1448                                             STR_TERMINATE);
1449                 user = tmp ? tmp : "";
1450
1451                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1452                                             STR_TERMINATE);
1453                 domain = tmp ? tmp : "";
1454
1455                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1456                                             STR_TERMINATE);
1457                 native_os = tmp ? tmp : "";
1458
1459                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1460                                             STR_TERMINATE);
1461                 native_lanman = tmp ? tmp : "";
1462
1463                 /* not documented or decoded by Ethereal but there is one more
1464                  * string in the extra bytes which is the same as the
1465                  * PrimaryDomain when using extended security.  Windows NT 4
1466                  * and 2003 use this string to store the native lanman string.
1467                  * Windows 9x does not include a string here at all so we have
1468                  * to check if we have any extra bytes left */
1469
1470                 byte_count = SVAL(req->vwv+13, 0);
1471                 if ( PTR_DIFF(p, save_p) < byte_count) {
1472                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
1473                                                     STR_TERMINATE);
1474                         primary_domain = tmp ? tmp : "";
1475                 } else {
1476                         primary_domain = talloc_strdup(talloc_tos(), "null");
1477                 }
1478
1479                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
1480                         "PrimaryDomain=[%s]\n",
1481                         domain, native_os, native_lanman, primary_domain));
1482
1483                 if ( ra_type == RA_WIN2K ) {
1484                         if ( strlen(native_lanman) == 0 )
1485                                 ra_lanman_string( primary_domain );
1486                         else
1487                                 ra_lanman_string( native_lanman );
1488                 }
1489
1490         }
1491
1492         if (SVAL(req->vwv+4, 0) == 0) {
1493                 setup_new_vc_session(req->sconn);
1494         }
1495
1496         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
1497                                 domain, user, get_remote_machine_name()));
1498
1499         if (*user) {
1500                 if (sconn->smb1.negprot.spnego) {
1501
1502                         /* This has to be here, because this is a perfectly
1503                          * valid behaviour for guest logons :-( */
1504
1505                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
1506                                 "at 'normal' session setup after "
1507                                 "negotiating spnego.\n"));
1508                         reply_nterror(req, nt_status_squash(
1509                                               NT_STATUS_LOGON_FAILURE));
1510                         END_PROFILE(SMBsesssetupX);
1511                         return;
1512                 }
1513                 fstrcpy(sub_user, user);
1514         } else {
1515                 fstrcpy(sub_user, lp_guestaccount());
1516         }
1517
1518         sub_set_smb_name(sub_user);
1519
1520         reload_services(sconn->msg_ctx, sconn->sock, True);
1521
1522         if (lp_security() == SEC_SHARE) {
1523                 char *sub_user_mapped = NULL;
1524                 /* In share level we should ignore any passwords */
1525
1526                 data_blob_free(&lm_resp);
1527                 data_blob_free(&nt_resp);
1528                 data_blob_clear_free(&plaintext_password);
1529
1530                 (void)map_username(talloc_tos(), sub_user, &sub_user_mapped);
1531                 if (!sub_user_mapped) {
1532                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1533                         END_PROFILE(SMBsesssetupX);
1534                         return;
1535                 }
1536                 fstrcpy(sub_user, sub_user_mapped);
1537                 add_session_user(sconn, sub_user);
1538                 add_session_workgroup(sconn, domain);
1539                 /* Then force it to null for the benfit of the code below */
1540                 user = "";
1541         }
1542
1543         if (!*user) {
1544
1545                 nt_status = check_guest_password(sconn->remote_address, &server_info);
1546
1547         } else if (doencrypt) {
1548                 struct auth_context *negprot_auth_context = NULL;
1549                 negprot_auth_context = sconn->smb1.negprot.auth_context;
1550                 if (!negprot_auth_context) {
1551                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
1552                                 "session setup without negprot denied!\n"));
1553                         reply_nterror(req, nt_status_squash(
1554                                               NT_STATUS_LOGON_FAILURE));
1555                         END_PROFILE(SMBsesssetupX);
1556                         return;
1557                 }
1558                 nt_status = make_user_info_for_reply_enc(&user_info, user,
1559                                                 domain,
1560                                                 sconn->remote_address,
1561                                                 lm_resp, nt_resp);
1562                 if (NT_STATUS_IS_OK(nt_status)) {
1563                         nt_status = negprot_auth_context->check_ntlm_password(
1564                                         negprot_auth_context,
1565                                         user_info,
1566                                         &server_info);
1567                 }
1568         } else {
1569                 struct auth_context *plaintext_auth_context = NULL;
1570
1571                 nt_status = make_auth_context_subsystem(
1572                         talloc_tos(), &plaintext_auth_context);
1573
1574                 if (NT_STATUS_IS_OK(nt_status)) {
1575                         uint8_t chal[8];
1576
1577                         plaintext_auth_context->get_ntlm_challenge(
1578                                         plaintext_auth_context, chal);
1579
1580                         if (!make_user_info_for_reply(&user_info,
1581                                                       user, domain,
1582                                                       sconn->remote_address,
1583                                                       chal,
1584                                                       plaintext_password)) {
1585                                 nt_status = NT_STATUS_NO_MEMORY;
1586                         }
1587
1588                         if (NT_STATUS_IS_OK(nt_status)) {
1589                                 nt_status = plaintext_auth_context->check_ntlm_password(
1590                                                 plaintext_auth_context,
1591                                                 user_info,
1592                                                 &server_info);
1593
1594                                 TALLOC_FREE(plaintext_auth_context);
1595                         }
1596                 }
1597         }
1598
1599         free_user_info(&user_info);
1600
1601         if (!NT_STATUS_IS_OK(nt_status)) {
1602                 nt_status = do_map_to_guest_server_info(nt_status, &server_info,
1603                                                         user, domain);
1604         }
1605
1606         if (!NT_STATUS_IS_OK(nt_status)) {
1607                 data_blob_free(&nt_resp);
1608                 data_blob_free(&lm_resp);
1609                 data_blob_clear_free(&plaintext_password);
1610                 reply_nterror(req, nt_status_squash(nt_status));
1611                 END_PROFILE(SMBsesssetupX);
1612                 return;
1613         }
1614
1615         nt_status = create_local_token(req, server_info, NULL, &session_info);
1616         TALLOC_FREE(server_info);
1617
1618         if (!NT_STATUS_IS_OK(nt_status)) {
1619                 DEBUG(10, ("create_local_token failed: %s\n",
1620                            nt_errstr(nt_status)));
1621                 data_blob_free(&nt_resp);
1622                 data_blob_free(&lm_resp);
1623                 data_blob_clear_free(&plaintext_password);
1624                 reply_nterror(req, nt_status_squash(nt_status));
1625                 END_PROFILE(SMBsesssetupX);
1626                 return;
1627         }
1628
1629         data_blob_clear_free(&plaintext_password);
1630
1631         /* it's ok - setup a reply */
1632         reply_outbuf(req, 3, 0);
1633         if (get_Protocol() >= PROTOCOL_NT1) {
1634                 push_signature(&req->outbuf);
1635                 /* perhaps grab OS version here?? */
1636         }
1637
1638         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
1639                 SSVAL(req->outbuf,smb_vwv2,1);
1640         }
1641
1642         /* register the name and uid as being validated, so further connections
1643            to a uid can get through without a password, on the same VC */
1644
1645         if (lp_security() == SEC_SHARE) {
1646                 sess_vuid = UID_FIELD_INVALID;
1647                 TALLOC_FREE(session_info);
1648         } else {
1649                 /* Ignore the initial vuid. */
1650                 sess_vuid = register_initial_vuid(sconn);
1651                 if (sess_vuid == UID_FIELD_INVALID) {
1652                         data_blob_free(&nt_resp);
1653                         data_blob_free(&lm_resp);
1654                         reply_nterror(req, nt_status_squash(
1655                                               NT_STATUS_LOGON_FAILURE));
1656                         END_PROFILE(SMBsesssetupX);
1657                         return;
1658                 }
1659                 /* register_existing_vuid keeps the session_info */
1660                 sess_vuid = register_existing_vuid(sconn, sess_vuid,
1661                                         session_info,
1662                                         nt_resp.data ? nt_resp : lm_resp,
1663                                         sub_user);
1664                 if (sess_vuid == UID_FIELD_INVALID) {
1665                         data_blob_free(&nt_resp);
1666                         data_blob_free(&lm_resp);
1667                         reply_nterror(req, nt_status_squash(
1668                                               NT_STATUS_LOGON_FAILURE));
1669                         END_PROFILE(SMBsesssetupX);
1670                         return;
1671                 }
1672
1673                 /* current_user_info is changed on new vuid */
1674                 reload_services(sconn->msg_ctx, sconn->sock, True);
1675         }
1676
1677         data_blob_free(&nt_resp);
1678         data_blob_free(&lm_resp);
1679
1680         SSVAL(req->outbuf,smb_uid,sess_vuid);
1681         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1682         req->vuid = sess_vuid;
1683
1684         if (!sconn->smb1.sessions.done_sesssetup) {
1685                 sconn->smb1.sessions.max_send =
1686                         MIN(sconn->smb1.sessions.max_send,smb_bufsize);
1687         }
1688         sconn->smb1.sessions.done_sesssetup = true;
1689
1690         END_PROFILE(SMBsesssetupX);
1691         chain_reply(req);
1692         return;
1693 }