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