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