CVE-2016-2114: s3:smbd: enforce "server signing = mandatory"
[kai/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 "auth.h"
30 #include "messages.h"
31 #include "smbprofile.h"
32 #include "../libcli/security/security.h"
33 #include "auth/gensec/gensec.h"
34 #include "lib/conn_tdb.h"
35 #include "../libcli/smb/smb_signing.h"
36
37 /****************************************************************************
38  Add the standard 'Samba' signature to the end of the session setup.
39 ****************************************************************************/
40
41 static int push_signature(uint8_t **outbuf)
42 {
43         char *lanman;
44         int result, tmp;
45         fstring native_os;
46
47         result = 0;
48
49         fstr_sprintf(native_os, "Windows %d.%d", SAMBA_MAJOR_NBT_ANNOUNCE_VERSION,
50                 SAMBA_MINOR_NBT_ANNOUNCE_VERSION);
51
52         tmp = message_push_string(outbuf, native_os, STR_TERMINATE);
53
54         if (tmp == -1) return -1;
55         result += tmp;
56
57         if (asprintf(&lanman, "Samba %s", samba_version_string()) != -1) {
58                 tmp = message_push_string(outbuf, lanman, STR_TERMINATE);
59                 SAFE_FREE(lanman);
60         }
61         else {
62                 tmp = message_push_string(outbuf, "Samba", STR_TERMINATE);
63         }
64
65         if (tmp == -1) return -1;
66         result += tmp;
67
68         tmp = message_push_string(outbuf, lp_workgroup(), STR_TERMINATE);
69
70         if (tmp == -1) return -1;
71         result += tmp;
72
73         return result;
74 }
75
76 /****************************************************************************
77  Do a 'guest' logon, getting back the
78 ****************************************************************************/
79
80 static NTSTATUS check_guest_password(const struct tsocket_address *remote_address,
81                                      TALLOC_CTX *mem_ctx, 
82                                      struct auth_session_info **session_info)
83 {
84         struct auth4_context *auth_context;
85         struct auth_usersupplied_info *user_info = NULL;
86         uint8_t chal[8];
87         NTSTATUS nt_status;
88
89         DEBUG(3,("Got anonymous request\n"));
90
91         nt_status = make_auth4_context(talloc_tos(), &auth_context);
92         if (!NT_STATUS_IS_OK(nt_status)) {
93                 return nt_status;
94         }
95
96         auth_context->get_ntlm_challenge(auth_context,
97                                          chal);
98
99         if (!make_user_info_guest(talloc_tos(), remote_address, &user_info)) {
100                 TALLOC_FREE(auth_context);
101                 return NT_STATUS_NO_MEMORY;
102         }
103
104         nt_status = auth_check_password_session_info(auth_context, 
105                                                      mem_ctx, user_info, session_info);
106         TALLOC_FREE(user_info);
107         TALLOC_FREE(auth_context);
108         return nt_status;
109 }
110
111 /****************************************************************************
112  Reply to a session setup command.
113  conn POINTER CAN BE NULL HERE !
114 ****************************************************************************/
115
116 static void reply_sesssetup_and_X_spnego(struct smb_request *req)
117 {
118         const uint8_t *p;
119         DATA_BLOB in_blob;
120         DATA_BLOB out_blob = data_blob_null;
121         size_t bufrem;
122         char *tmp;
123         const char *native_os;
124         const char *native_lanman;
125         const char *primary_domain;
126         uint16_t data_blob_len = SVAL(req->vwv+7, 0);
127         enum remote_arch_types ra_type = get_remote_arch();
128         uint64_t vuid = req->vuid;
129         NTSTATUS status = NT_STATUS_OK;
130         struct smbXsrv_connection *xconn = req->xconn;
131         struct smbd_server_connection *sconn = req->sconn;
132         uint16_t action = 0;
133         NTTIME now = timeval_to_nttime(&req->request_time);
134         struct smbXsrv_session *session = NULL;
135         uint16_t smb_bufsize = SVAL(req->vwv+2, 0);
136         uint32_t client_caps = IVAL(req->vwv+10, 0);
137         struct smbXsrv_session_auth0 *auth;
138
139         DEBUG(3,("Doing spnego session setup\n"));
140
141         if (!xconn->smb1.sessions.done_sesssetup) {
142                 global_client_caps = client_caps;
143
144                 if (!(global_client_caps & CAP_STATUS32)) {
145                         remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
146                 }
147         }
148
149         p = req->buf;
150
151         if (data_blob_len == 0) {
152                 /* an invalid request */
153                 reply_nterror(req, nt_status_squash(NT_STATUS_LOGON_FAILURE));
154                 return;
155         }
156
157         bufrem = smbreq_bufrem(req, p);
158         /* pull the spnego blob */
159         in_blob = data_blob_const(p, MIN(bufrem, data_blob_len));
160
161 #if 0
162         file_save("negotiate.dat", in_blob.data, in_blob.length);
163 #endif
164
165         p = req->buf + in_blob.length;
166
167         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
168                                      STR_TERMINATE);
169         native_os = tmp ? tmp : "";
170
171         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
172                                      STR_TERMINATE);
173         native_lanman = tmp ? tmp : "";
174
175         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
176                                      STR_TERMINATE);
177         primary_domain = tmp ? tmp : "";
178
179         DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n",
180                 native_os, native_lanman, primary_domain));
181
182         if ( ra_type == RA_WIN2K ) {
183                 /* Vista sets neither the OS or lanman strings */
184
185                 if ( !strlen(native_os) && !strlen(native_lanman) )
186                         set_remote_arch(RA_VISTA);
187
188                 /* Windows 2003 doesn't set the native lanman string,
189                    but does set primary domain which is a bug I think */
190
191                 if ( !strlen(native_lanman) ) {
192                         ra_lanman_string( primary_domain );
193                 } else {
194                         ra_lanman_string( native_lanman );
195                 }
196         } else if ( ra_type == RA_VISTA ) {
197                 if ( strncmp(native_os, "Mac OS X", 8) == 0 ) {
198                         set_remote_arch(RA_OSX);
199                 }
200         }
201
202         if (vuid != 0) {
203                 status = smb1srv_session_lookup(xconn,
204                                                 vuid, now,
205                                                 &session);
206                 if (NT_STATUS_EQUAL(status, NT_STATUS_USER_SESSION_DELETED)) {
207                         reply_force_doserror(req, ERRSRV, ERRbaduid);
208                         return;
209                 }
210                 if (NT_STATUS_EQUAL(status, NT_STATUS_NETWORK_SESSION_EXPIRED)) {
211                         status = NT_STATUS_OK;
212                 }
213                 if (NT_STATUS_IS_OK(status)) {
214                         session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
215                         status = NT_STATUS_MORE_PROCESSING_REQUIRED;
216                         TALLOC_FREE(session->pending_auth);
217                 }
218                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
219                         reply_nterror(req, nt_status_squash(status));
220                         return;
221                 }
222         }
223
224         if (session == NULL) {
225                 /* create a new session */
226                 status = smbXsrv_session_create(xconn,
227                                                 now, &session);
228                 if (!NT_STATUS_IS_OK(status)) {
229                         reply_nterror(req, nt_status_squash(status));
230                         return;
231                 }
232         }
233
234         status = smbXsrv_session_find_auth(session, xconn, now, &auth);
235         if (!NT_STATUS_IS_OK(status)) {
236                 status = smbXsrv_session_create_auth(session, xconn, now,
237                                                      0, /* flags */
238                                                      0, /* security */
239                                                      &auth);
240                 if (!NT_STATUS_IS_OK(status)) {
241                         reply_nterror(req, nt_status_squash(status));
242                         return;
243                 }
244         }
245
246         if (auth->gensec == NULL) {
247                 status = auth_generic_prepare(session, xconn->remote_address,
248                                               &auth->gensec);
249                 if (!NT_STATUS_IS_OK(status)) {
250                         TALLOC_FREE(session);
251                         reply_nterror(req, nt_status_squash(status));
252                         return;
253                 }
254
255                 gensec_want_feature(auth->gensec, GENSEC_FEATURE_SESSION_KEY);
256                 gensec_want_feature(auth->gensec, GENSEC_FEATURE_UNIX_TOKEN);
257
258                 status = gensec_start_mech_by_oid(auth->gensec,
259                                                   GENSEC_OID_SPNEGO);
260                 if (!NT_STATUS_IS_OK(status)) {
261                         DEBUG(0, ("Failed to start SPNEGO handler!\n"));
262                         TALLOC_FREE(session);;
263                         reply_nterror(req, nt_status_squash(status));
264                         return;
265                 }
266         }
267
268         become_root();
269         status = gensec_update(auth->gensec,
270                                talloc_tos(),
271                                in_blob, &out_blob);
272         unbecome_root();
273         if (!NT_STATUS_IS_OK(status) &&
274             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
275                 TALLOC_FREE(session);
276                 reply_nterror(req, nt_status_squash(status));
277                 return;
278         }
279
280         if (NT_STATUS_IS_OK(status) && session->global->auth_session_info == NULL) {
281                 struct auth_session_info *session_info = NULL;
282
283                 status = gensec_session_info(auth->gensec,
284                                              session,
285                                              &session_info);
286                 if (!NT_STATUS_IS_OK(status)) {
287                         DEBUG(1,("Failed to generate session_info "
288                                  "(user and group token) for session setup: %s\n",
289                                  nt_errstr(status)));
290                         data_blob_free(&out_blob);
291                         TALLOC_FREE(session);
292                         reply_nterror(req, nt_status_squash(status));
293                         return;
294                 }
295
296                 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
297                         action = 1;
298                 }
299
300                 if (session_info->session_key.length > 0) {
301                         struct smbXsrv_session *x = session;
302
303                         /*
304                          * Note: the SMB1 signing key is not truncated to 16 byte!
305                          */
306                         x->global->signing_key =
307                                 data_blob_dup_talloc(x->global,
308                                                      session_info->session_key);
309                         if (x->global->signing_key.data == NULL) {
310                                 data_blob_free(&out_blob);
311                                 TALLOC_FREE(session);
312                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
313                                 return;
314                         }
315
316                         /*
317                          * clear the session key
318                          * the first tcon will add setup the application key
319                          */
320                         data_blob_clear_free(&session_info->session_key);
321                 }
322
323                 session->compat = talloc_zero(session, struct user_struct);
324                 if (session->compat == NULL) {
325                         data_blob_free(&out_blob);
326                         TALLOC_FREE(session);
327                         reply_nterror(req, NT_STATUS_NO_MEMORY);
328                         return;
329                 }
330                 session->compat->session = session;
331                 session->compat->homes_snum = -1;
332                 session->compat->session_info = session_info;
333                 session->compat->session_keystr = NULL;
334                 session->compat->vuid = session->global->session_wire_id;
335                 DLIST_ADD(sconn->users, session->compat);
336                 sconn->num_users++;
337
338                 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
339                         session->compat->homes_snum =
340                                 register_homes_share(session_info->unix_info->unix_name);
341                 }
342
343                 if (srv_is_signing_negotiated(xconn) &&
344                     action == 0 &&
345                     session->global->signing_key.length > 0)
346                 {
347                         /*
348                          * Try and turn on server signing on the first non-guest
349                          * sessionsetup.
350                          */
351                         srv_set_signing(xconn,
352                                 session->global->signing_key,
353                                 data_blob_null);
354                 }
355
356                 set_current_user_info(session_info->unix_info->sanitized_username,
357                                       session_info->unix_info->unix_name,
358                                       session_info->info->domain_name);
359
360                 session->status = NT_STATUS_OK;
361                 session->global->auth_session_info = talloc_move(session->global,
362                                                                  &session_info);
363                 session->global->auth_session_info_seqnum += 1;
364                 session->global->channels[0].auth_session_info_seqnum =
365                         session->global->auth_session_info_seqnum;
366                 session->global->auth_time = now;
367                 if (client_caps & CAP_DYNAMIC_REAUTH) {
368                         session->global->expiration_time =
369                                 gensec_expire_time(auth->gensec);
370                 } else {
371                         session->global->expiration_time =
372                                 GENSEC_EXPIRE_TIME_INFINITY;
373                 }
374
375                 if (!session_claim(session)) {
376                         DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
377                                   (unsigned long long)session->compat->vuid));
378                         data_blob_free(&out_blob);
379                         TALLOC_FREE(session);
380                         reply_nterror(req, NT_STATUS_LOGON_FAILURE);
381                         return;
382                 }
383
384                 status = smbXsrv_session_update(session);
385                 if (!NT_STATUS_IS_OK(status)) {
386                         DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
387                                   (unsigned long long)session->compat->vuid,
388                                   nt_errstr(status)));
389                         data_blob_free(&out_blob);
390                         TALLOC_FREE(session);
391                         reply_nterror(req, NT_STATUS_LOGON_FAILURE);
392                         return;
393                 }
394
395                 if (!xconn->smb1.sessions.done_sesssetup) {
396                         if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
397                                 reply_force_doserror(req, ERRSRV, ERRerror);
398                                 return;
399                         }
400                         xconn->smb1.sessions.max_send = smb_bufsize;
401                         xconn->smb1.sessions.done_sesssetup = true;
402                 }
403
404                 /* current_user_info is changed on new vuid */
405                 reload_services(sconn, conn_snum_used, true);
406         } else if (NT_STATUS_IS_OK(status)) {
407                 struct auth_session_info *session_info = NULL;
408
409                 status = gensec_session_info(auth->gensec,
410                                              session,
411                                              &session_info);
412                 if (!NT_STATUS_IS_OK(status)) {
413                         DEBUG(1,("Failed to generate session_info "
414                                  "(user and group token) for session setup: %s\n",
415                                  nt_errstr(status)));
416                         data_blob_free(&out_blob);
417                         TALLOC_FREE(session);
418                         reply_nterror(req, nt_status_squash(status));
419                         return;
420                 }
421
422                 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
423                         action = 1;
424                 }
425
426                 /*
427                  * Keep the application key
428                  */
429                 data_blob_clear_free(&session_info->session_key);
430                 session_info->session_key =
431                         session->global->auth_session_info->session_key;
432                 talloc_steal(session_info, session_info->session_key.data);
433                 TALLOC_FREE(session->global->auth_session_info);
434
435                 session->compat->session_info = session_info;
436
437                 session->compat->vuid = session->global->session_wire_id;
438
439                 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
440                         session->compat->homes_snum =
441                                 register_homes_share(session_info->unix_info->unix_name);
442                 }
443
444                 set_current_user_info(session_info->unix_info->sanitized_username,
445                                       session_info->unix_info->unix_name,
446                                       session_info->info->domain_name);
447
448                 session->status = NT_STATUS_OK;
449                 session->global->auth_session_info = talloc_move(session->global,
450                                                                  &session_info);
451                 session->global->auth_session_info_seqnum += 1;
452                 session->global->channels[0].auth_session_info_seqnum =
453                         session->global->auth_session_info_seqnum;
454                 session->global->auth_time = now;
455                 if (client_caps & CAP_DYNAMIC_REAUTH) {
456                         session->global->expiration_time =
457                                 gensec_expire_time(auth->gensec);
458                 } else {
459                         session->global->expiration_time =
460                                 GENSEC_EXPIRE_TIME_INFINITY;
461                 }
462
463                 status = smbXsrv_session_update(session);
464                 if (!NT_STATUS_IS_OK(status)) {
465                         DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
466                                   (unsigned long long)session->compat->vuid,
467                                   nt_errstr(status)));
468                         data_blob_free(&out_blob);
469                         TALLOC_FREE(session);
470                         reply_nterror(req, NT_STATUS_LOGON_FAILURE);
471                         return;
472                 }
473
474                 conn_clear_vuid_caches(sconn, session->compat->vuid);
475
476                 /* current_user_info is changed on new vuid */
477                 reload_services(sconn, conn_snum_used, true);
478         }
479
480         vuid = session->global->session_wire_id;
481
482         reply_outbuf(req, 4, 0);
483
484         SSVAL(req->outbuf, smb_uid, vuid);
485         SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
486         SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
487         SSVAL(req->outbuf, smb_vwv2, action);
488         SSVAL(req->outbuf, smb_vwv3, out_blob.length);
489
490         if (message_push_blob(&req->outbuf, out_blob) == -1) {
491                 data_blob_free(&out_blob);
492                 TALLOC_FREE(session);
493                 reply_nterror(req, NT_STATUS_NO_MEMORY);
494                 return;
495         }
496         data_blob_free(&out_blob);
497
498         if (push_signature(&req->outbuf) == -1) {
499                 TALLOC_FREE(session);
500                 reply_nterror(req, NT_STATUS_NO_MEMORY);
501                 return;
502         }
503 }
504
505 /****************************************************************************
506  On new VC == 0, shutdown *all* old connections and users.
507  It seems that only NT4.x does this. At W2K and above (XP etc.).
508  a new session setup with VC==0 is ignored.
509 ****************************************************************************/
510
511 struct shutdown_state {
512         const char *ip;
513         struct messaging_context *msg_ctx;
514 };
515
516 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
517                                 void *private_data)
518 {
519         struct shutdown_state *state = (struct shutdown_state *)private_data;
520         struct server_id self_pid = messaging_server_id(state->msg_ctx);
521         struct server_id pid = session->channels[0].server_id;
522         const char *addr = session->channels[0].remote_address;
523         struct server_id_buf tmp;
524
525         DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
526                    server_id_str_buf(pid, &tmp), addr));
527
528         if (!process_exists(pid)) {
529                 DEBUG(10, ("process does not exist\n"));
530                 return 0;
531         }
532
533         if (serverid_equal(&pid, &self_pid)) {
534                 DEBUG(10, ("It's me\n"));
535                 return 0;
536         }
537
538         /*
539          * here we use strstr() because 'addr'
540          * (session->channels[0].remote_address)
541          * contains a string like:
542          * 'ipv4:127.0.0.1:48163'
543          */
544         if (strstr(addr, state->ip)  == NULL) {
545                 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
546                 return 0;
547         }
548
549         DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
550                   "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
551                   state->ip));
552
553         messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
554                        &data_blob_null);
555         return 0;
556 }
557
558 static void setup_new_vc_session(struct smbd_server_connection *sconn)
559 {
560         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
561                 "compatible we would close all old resources.\n"));
562 #if 0
563         conn_close_all();
564         invalidate_all_vuids();
565 #endif
566         if (lp_reset_on_zero_vc()) {
567                 char *addr;
568                 struct shutdown_state state;
569
570                 addr = tsocket_address_inet_addr_string(
571                         sconn->remote_address, talloc_tos());
572                 if (addr == NULL) {
573                         return;
574                 }
575                 state.ip = addr;
576                 state.msg_ctx = sconn->msg_ctx;
577                 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
578                 TALLOC_FREE(addr);
579         }
580 }
581
582 /****************************************************************************
583  Reply to a session setup command.
584 ****************************************************************************/
585
586 void reply_sesssetup_and_X(struct smb_request *req)
587 {
588         uint64_t sess_vuid;
589         uint16_t smb_bufsize;
590         DATA_BLOB lm_resp;
591         DATA_BLOB nt_resp;
592         DATA_BLOB plaintext_password;
593         char *tmp;
594         const char *user;
595         fstring sub_user; /* Sanitised username for substituion */
596         const char *domain;
597         const char *native_os;
598         const char *native_lanman;
599         const char *primary_domain;
600         struct auth_usersupplied_info *user_info = NULL;
601         struct auth_session_info *session_info = NULL;
602         uint16_t smb_flag2 = req->flags2;
603         uint16_t action = 0;
604         NTTIME now = timeval_to_nttime(&req->request_time);
605         struct smbXsrv_session *session = NULL;
606         NTSTATUS nt_status;
607         struct smbXsrv_connection *xconn = req->xconn;
608         struct smbd_server_connection *sconn = req->sconn;
609         bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
610         bool signing_allowed = false;
611         bool signing_mandatory = smb_signing_is_mandatory(
612                 xconn->smb1.signing_state);
613
614         START_PROFILE(SMBsesssetupX);
615
616         ZERO_STRUCT(lm_resp);
617         ZERO_STRUCT(nt_resp);
618         ZERO_STRUCT(plaintext_password);
619
620         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
621
622         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
623                 signing_allowed = true;
624         }
625         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
626                 signing_mandatory = true;
627         }
628
629         /*
630          * We can call srv_set_signing_negotiated() each time.
631          * It finds out when it needs to turn into a noop
632          * itself.
633          */
634         srv_set_signing_negotiated(xconn,
635                                    signing_allowed,
636                                    signing_mandatory);
637
638         /* a SPNEGO session setup has 12 command words, whereas a normal
639            NT1 session setup has 13. See the cifs spec. */
640         if (req->wct == 12 &&
641             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
642
643                 if (!xconn->smb1.negprot.spnego) {
644                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
645                                  "at SPNEGO session setup when it was not "
646                                  "negotiated.\n"));
647                         reply_nterror(req, nt_status_squash(
648                                               NT_STATUS_LOGON_FAILURE));
649                         END_PROFILE(SMBsesssetupX);
650                         return;
651                 }
652
653                 if (SVAL(req->vwv+4, 0) == 0) {
654                         setup_new_vc_session(req->sconn);
655                 }
656
657                 reply_sesssetup_and_X_spnego(req);
658                 END_PROFILE(SMBsesssetupX);
659                 return;
660         }
661
662         smb_bufsize = SVAL(req->vwv+2, 0);
663
664         if (get_Protocol() < PROTOCOL_NT1) {
665                 uint16_t passlen1 = SVAL(req->vwv+7, 0);
666
667                 /* Never do NT status codes with protocols before NT1 as we
668                  * don't get client caps. */
669                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
670
671                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
672                         reply_nterror(req, nt_status_squash(
673                                               NT_STATUS_INVALID_PARAMETER));
674                         END_PROFILE(SMBsesssetupX);
675                         return;
676                 }
677
678                 if (doencrypt) {
679                         lm_resp = data_blob(req->buf, passlen1);
680                 } else {
681                         plaintext_password = data_blob(req->buf, passlen1+1);
682                         /* Ensure null termination */
683                         plaintext_password.data[passlen1] = 0;
684                 }
685
686                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
687                                        req->buf + passlen1, STR_TERMINATE);
688                 user = tmp ? tmp : "";
689
690                 domain = "";
691
692         } else {
693                 uint16_t passlen1 = SVAL(req->vwv+7, 0);
694                 uint16_t passlen2 = SVAL(req->vwv+8, 0);
695                 enum remote_arch_types ra_type = get_remote_arch();
696                 const uint8_t *p = req->buf;
697                 const uint8_t *save_p = req->buf;
698                 uint16_t byte_count;
699
700                 if (!xconn->smb1.sessions.done_sesssetup) {
701                         global_client_caps = IVAL(req->vwv+11, 0);
702
703                         if (!(global_client_caps & CAP_STATUS32)) {
704                                 remove_from_common_flags2(
705                                                 FLAGS2_32_BIT_ERROR_CODES);
706                         }
707
708                         /* client_caps is used as final determination if
709                          * client is NT or Win95. This is needed to return
710                          * the correct error codes in some circumstances.
711                         */
712
713                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
714                                         ra_type == RA_WIN95) {
715                                 if(!(global_client_caps & (CAP_NT_SMBS|
716                                                         CAP_STATUS32))) {
717                                         set_remote_arch( RA_WIN95);
718                                 }
719                         }
720                 }
721
722                 if (!doencrypt) {
723                         /* both Win95 and WinNT stuff up the password
724                          * lengths for non-encrypting systems. Uggh.
725
726                            if passlen1==24 its a win95 system, and its setting
727                            the password length incorrectly. Luckily it still
728                            works with the default code because Win95 will null
729                            terminate the password anyway
730
731                            if passlen1>0 and passlen2>0 then maybe its a NT box
732                            and its setting passlen2 to some random value which
733                            really stuffs things up. we need to fix that one.  */
734
735                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
736                                         passlen2 != 1) {
737                                 passlen2 = 0;
738                         }
739                 }
740
741                 /* check for nasty tricks */
742                 if (passlen1 > MAX_PASS_LEN
743                     || passlen1 > smbreq_bufrem(req, p)) {
744                         reply_nterror(req, nt_status_squash(
745                                               NT_STATUS_INVALID_PARAMETER));
746                         END_PROFILE(SMBsesssetupX);
747                         return;
748                 }
749
750                 if (passlen2 > MAX_PASS_LEN
751                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
752                         reply_nterror(req, nt_status_squash(
753                                               NT_STATUS_INVALID_PARAMETER));
754                         END_PROFILE(SMBsesssetupX);
755                         return;
756                 }
757
758                 /* Save the lanman2 password and the NT md4 password. */
759
760                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
761                         doencrypt = False;
762                 }
763
764                 if (doencrypt) {
765                         lm_resp = data_blob(p, passlen1);
766                         nt_resp = data_blob(p+passlen1, passlen2);
767                 } else {
768                         char *pass = NULL;
769                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
770
771                         if (unic && (passlen2 == 0) && passlen1) {
772                                 /* Only a ascii plaintext password was sent. */
773                                 (void)srvstr_pull_talloc(talloc_tos(),
774                                                         req->inbuf,
775                                                         req->flags2,
776                                                         &pass,
777                                                         req->buf,
778                                                         passlen1,
779                                                         STR_TERMINATE|STR_ASCII);
780                         } else {
781                                 (void)srvstr_pull_talloc(talloc_tos(),
782                                                         req->inbuf,
783                                                         req->flags2,
784                                                         &pass,
785                                                         req->buf,
786                                                         unic ? passlen2 : passlen1,
787                                                         STR_TERMINATE);
788                         }
789                         if (!pass) {
790                                 reply_nterror(req, nt_status_squash(
791                                               NT_STATUS_INVALID_PARAMETER));
792                                 END_PROFILE(SMBsesssetupX);
793                                 return;
794                         }
795                         plaintext_password = data_blob(pass, strlen(pass)+1);
796                 }
797
798                 p += passlen1 + passlen2;
799
800                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
801                                             STR_TERMINATE);
802                 user = tmp ? tmp : "";
803
804                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
805                                             STR_TERMINATE);
806                 domain = tmp ? tmp : "";
807
808                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
809                                             STR_TERMINATE);
810                 native_os = tmp ? tmp : "";
811
812                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
813                                             STR_TERMINATE);
814                 native_lanman = tmp ? tmp : "";
815
816                 /* not documented or decoded by Ethereal but there is one more
817                  * string in the extra bytes which is the same as the
818                  * PrimaryDomain when using extended security.  Windows NT 4
819                  * and 2003 use this string to store the native lanman string.
820                  * Windows 9x does not include a string here at all so we have
821                  * to check if we have any extra bytes left */
822
823                 byte_count = SVAL(req->vwv+13, 0);
824                 if ( PTR_DIFF(p, save_p) < byte_count) {
825                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
826                                                     STR_TERMINATE);
827                         primary_domain = tmp ? tmp : "";
828                 } else {
829                         primary_domain = talloc_strdup(talloc_tos(), "null");
830                 }
831
832                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
833                         "PrimaryDomain=[%s]\n",
834                         domain, native_os, native_lanman, primary_domain));
835
836                 if ( ra_type == RA_WIN2K ) {
837                         if ( strlen(native_lanman) == 0 )
838                                 ra_lanman_string( primary_domain );
839                         else
840                                 ra_lanman_string( native_lanman );
841                 }
842
843         }
844
845         if (SVAL(req->vwv+4, 0) == 0) {
846                 setup_new_vc_session(req->sconn);
847         }
848
849         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
850                                 domain, user, get_remote_machine_name()));
851
852         if (*user) {
853                 if (xconn->smb1.negprot.spnego) {
854
855                         /* This has to be here, because this is a perfectly
856                          * valid behaviour for guest logons :-( */
857
858                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
859                                 "at 'normal' session setup after "
860                                 "negotiating spnego.\n"));
861                         reply_nterror(req, nt_status_squash(
862                                               NT_STATUS_LOGON_FAILURE));
863                         END_PROFILE(SMBsesssetupX);
864                         return;
865                 }
866                 fstrcpy(sub_user, user);
867         } else {
868                 fstrcpy(sub_user, "");
869         }
870
871         sub_set_smb_name(sub_user);
872
873         reload_services(sconn, conn_snum_used, true);
874
875         if (!*user) {
876
877                 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
878
879         } else if (doencrypt) {
880                 struct auth4_context *negprot_auth_context = NULL;
881                 negprot_auth_context = xconn->smb1.negprot.auth_context;
882                 if (!negprot_auth_context) {
883                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
884                                 "session setup without negprot denied!\n"));
885                         reply_nterror(req, nt_status_squash(
886                                               NT_STATUS_LOGON_FAILURE));
887                         END_PROFILE(SMBsesssetupX);
888                         return;
889                 }
890                 nt_status = make_user_info_for_reply_enc(talloc_tos(),
891                                                          &user_info, user,
892                                                          domain,
893                                                          sconn->remote_address,
894                                                          lm_resp, nt_resp);
895                 if (NT_STATUS_IS_OK(nt_status)) {
896                         nt_status = auth_check_password_session_info(negprot_auth_context, 
897                                                                      req, user_info, &session_info);
898                 }
899         } else {
900                 struct auth4_context *plaintext_auth_context = NULL;
901
902                 nt_status = make_auth4_context(
903                         talloc_tos(), &plaintext_auth_context);
904
905                 if (NT_STATUS_IS_OK(nt_status)) {
906                         uint8_t chal[8];
907
908                         plaintext_auth_context->get_ntlm_challenge(
909                                         plaintext_auth_context, chal);
910
911                         if (!make_user_info_for_reply(talloc_tos(),
912                                                       &user_info,
913                                                       user, domain,
914                                                       sconn->remote_address,
915                                                       chal,
916                                                       plaintext_password)) {
917                                 nt_status = NT_STATUS_NO_MEMORY;
918                         }
919
920                         if (NT_STATUS_IS_OK(nt_status)) {
921                                 nt_status = auth_check_password_session_info(plaintext_auth_context, 
922                                                                              req, user_info, &session_info);
923                         }
924                         TALLOC_FREE(plaintext_auth_context);
925                 }
926         }
927
928         TALLOC_FREE(user_info);
929
930         if (!NT_STATUS_IS_OK(nt_status)) {
931                 data_blob_free(&nt_resp);
932                 data_blob_free(&lm_resp);
933                 data_blob_clear_free(&plaintext_password);
934                 reply_nterror(req, nt_status_squash(nt_status));
935                 END_PROFILE(SMBsesssetupX);
936                 return;
937         }
938
939         data_blob_clear_free(&plaintext_password);
940
941         /* it's ok - setup a reply */
942         reply_outbuf(req, 3, 0);
943         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
944         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
945
946         if (get_Protocol() >= PROTOCOL_NT1) {
947                 push_signature(&req->outbuf);
948                 /* perhaps grab OS version here?? */
949         }
950
951         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
952                 action = 1;
953         }
954
955         /* register the name and uid as being validated, so further connections
956            to a uid can get through without a password, on the same VC */
957
958         nt_status = smbXsrv_session_create(xconn,
959                                            now, &session);
960         if (!NT_STATUS_IS_OK(nt_status)) {
961                 data_blob_free(&nt_resp);
962                 data_blob_free(&lm_resp);
963                 reply_nterror(req, nt_status_squash(nt_status));
964                 END_PROFILE(SMBsesssetupX);
965                 return;
966         }
967
968         if (session_info->session_key.length > 0) {
969                 uint8_t session_key[16];
970
971                 /*
972                  * Note: the SMB1 signing key is not truncated to 16 byte!
973                  */
974                 session->global->signing_key =
975                         data_blob_dup_talloc(session->global,
976                                              session_info->session_key);
977                 if (session->global->signing_key.data == NULL) {
978                         data_blob_free(&nt_resp);
979                         data_blob_free(&lm_resp);
980                         TALLOC_FREE(session);
981                         reply_nterror(req, NT_STATUS_NO_MEMORY);
982                         END_PROFILE(SMBsesssetupX);
983                         return;
984                 }
985
986                 /*
987                  * The application key is truncated/padded to 16 bytes
988                  */
989                 ZERO_STRUCT(session_key);
990                 memcpy(session_key, session->global->signing_key.data,
991                        MIN(session->global->signing_key.length,
992                            sizeof(session_key)));
993                 session->global->application_key =
994                         data_blob_talloc(session->global,
995                                          session_key,
996                                          sizeof(session_key));
997                 ZERO_STRUCT(session_key);
998                 if (session->global->application_key.data == NULL) {
999                         data_blob_free(&nt_resp);
1000                         data_blob_free(&lm_resp);
1001                         TALLOC_FREE(session);
1002                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1003                         END_PROFILE(SMBsesssetupX);
1004                         return;
1005                 }
1006
1007                 /*
1008                  * Place the application key into the session_info
1009                  */
1010                 data_blob_clear_free(&session_info->session_key);
1011                 session_info->session_key = data_blob_dup_talloc(session_info,
1012                                                 session->global->application_key);
1013                 if (session_info->session_key.data == NULL) {
1014                         data_blob_free(&nt_resp);
1015                         data_blob_free(&lm_resp);
1016                         TALLOC_FREE(session);
1017                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1018                         END_PROFILE(SMBsesssetupX);
1019                         return;
1020                 }
1021         }
1022
1023         session->compat = talloc_zero(session, struct user_struct);
1024         if (session->compat == NULL) {
1025                 data_blob_free(&nt_resp);
1026                 data_blob_free(&lm_resp);
1027                 TALLOC_FREE(session);
1028                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1029                 END_PROFILE(SMBsesssetupX);
1030                 return;
1031         }
1032         session->compat->session = session;
1033         session->compat->homes_snum = -1;
1034         session->compat->session_info = session_info;
1035         session->compat->session_keystr = NULL;
1036         session->compat->vuid = session->global->session_wire_id;
1037         DLIST_ADD(sconn->users, session->compat);
1038         sconn->num_users++;
1039
1040         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1041                 session->compat->homes_snum =
1042                         register_homes_share(session_info->unix_info->unix_name);
1043         }
1044
1045         if (srv_is_signing_negotiated(xconn) &&
1046             action == 0 &&
1047             session->global->signing_key.length > 0)
1048         {
1049                 /*
1050                  * Try and turn on server signing on the first non-guest
1051                  * sessionsetup.
1052                  */
1053                 srv_set_signing(xconn,
1054                         session->global->signing_key,
1055                         nt_resp.data ? nt_resp : lm_resp);
1056         }
1057
1058         set_current_user_info(session_info->unix_info->sanitized_username,
1059                               session_info->unix_info->unix_name,
1060                               session_info->info->domain_name);
1061
1062         session->status = NT_STATUS_OK;
1063         session->global->auth_session_info = talloc_move(session->global,
1064                                                          &session_info);
1065         session->global->auth_session_info_seqnum += 1;
1066         session->global->channels[0].auth_session_info_seqnum =
1067                 session->global->auth_session_info_seqnum;
1068         session->global->auth_time = now;
1069         session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1070
1071         nt_status = smbXsrv_session_update(session);
1072         if (!NT_STATUS_IS_OK(nt_status)) {
1073                 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1074                           (unsigned long long)session->compat->vuid,
1075                           nt_errstr(nt_status)));
1076                 data_blob_free(&nt_resp);
1077                 data_blob_free(&lm_resp);
1078                 TALLOC_FREE(session);
1079                 reply_nterror(req, nt_status_squash(nt_status));
1080                 END_PROFILE(SMBsesssetupX);
1081                 return;
1082         }
1083
1084         if (!session_claim(session)) {
1085                 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1086                           (unsigned long long)session->compat->vuid));
1087                 data_blob_free(&nt_resp);
1088                 data_blob_free(&lm_resp);
1089                 TALLOC_FREE(session);
1090                 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1091                 END_PROFILE(SMBsesssetupX);
1092                 return;
1093         }
1094
1095         /* current_user_info is changed on new vuid */
1096         reload_services(sconn, conn_snum_used, true);
1097
1098         sess_vuid = session->global->session_wire_id;
1099
1100         data_blob_free(&nt_resp);
1101         data_blob_free(&lm_resp);
1102
1103         SSVAL(req->outbuf,smb_vwv2,action);
1104         SSVAL(req->outbuf,smb_uid,sess_vuid);
1105         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1106         req->vuid = sess_vuid;
1107
1108         if (!xconn->smb1.sessions.done_sesssetup) {
1109                 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1110                         reply_force_doserror(req, ERRSRV, ERRerror);
1111                         END_PROFILE(SMBsesssetupX);
1112                         return;
1113                 }
1114                 xconn->smb1.sessions.max_send = smb_bufsize;
1115                 xconn->smb1.sessions.done_sesssetup = true;
1116         }
1117
1118         END_PROFILE(SMBsesssetupX);
1119 }