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