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