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