s3:smbd: remember the time of the session setup auth_time
[metze/samba/wip.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 **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 *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 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 = xconn->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
515         DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
516                    server_id_str(talloc_tos(), &pid), addr));
517
518         if (!process_exists(pid)) {
519                 DEBUG(10, ("process does not exist\n"));
520                 return 0;
521         }
522
523         if (serverid_equal(&pid, &self_pid)) {
524                 DEBUG(10, ("It's me\n"));
525                 return 0;
526         }
527
528         /*
529          * here we use strstr() because 'addr'
530          * (session->channels[0].remote_address)
531          * contains a string like:
532          * 'ipv4:127.0.0.1:48163'
533          */
534         if (strstr(addr, state->ip)  == NULL) {
535                 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
536                 return 0;
537         }
538
539         DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
540                   "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
541                   state->ip));
542
543         messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
544                        &data_blob_null);
545         return 0;
546 }
547
548 static void setup_new_vc_session(struct smbd_server_connection *sconn)
549 {
550         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
551                 "compatible we would close all old resources.\n"));
552 #if 0
553         conn_close_all();
554         invalidate_all_vuids();
555 #endif
556         if (lp_reset_on_zero_vc()) {
557                 char *addr;
558                 struct shutdown_state state;
559
560                 addr = tsocket_address_inet_addr_string(
561                         sconn->remote_address, talloc_tos());
562                 if (addr == NULL) {
563                         return;
564                 }
565                 state.ip = addr;
566                 state.msg_ctx = sconn->msg_ctx;
567                 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
568                 TALLOC_FREE(addr);
569         }
570 }
571
572 /****************************************************************************
573  Reply to a session setup command.
574 ****************************************************************************/
575
576 void reply_sesssetup_and_X(struct smb_request *req)
577 {
578         uint64_t sess_vuid;
579         uint16_t smb_bufsize;
580         DATA_BLOB lm_resp;
581         DATA_BLOB nt_resp;
582         DATA_BLOB plaintext_password;
583         char *tmp;
584         const char *user;
585         fstring sub_user; /* Sanitised username for substituion */
586         const char *domain;
587         const char *native_os;
588         const char *native_lanman;
589         const char *primary_domain;
590         struct auth_usersupplied_info *user_info = NULL;
591         struct auth_session_info *session_info = NULL;
592         uint16 smb_flag2 = req->flags2;
593         uint16_t action = 0;
594         NTTIME now = timeval_to_nttime(&req->request_time);
595         struct smbXsrv_session *session = NULL;
596         NTSTATUS nt_status;
597         struct smbXsrv_connection *xconn = req->xconn;
598         struct smbd_server_connection *sconn = xconn->sconn;
599         bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
600         bool signing_allowed = false;
601         bool signing_mandatory = false;
602
603         START_PROFILE(SMBsesssetupX);
604
605         ZERO_STRUCT(lm_resp);
606         ZERO_STRUCT(nt_resp);
607         ZERO_STRUCT(plaintext_password);
608
609         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
610
611         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
612                 signing_allowed = true;
613         }
614         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
615                 signing_mandatory = true;
616         }
617
618         /*
619          * We can call srv_set_signing_negotiated() each time.
620          * It finds out when it needs to turn into a noop
621          * itself.
622          */
623         srv_set_signing_negotiated(xconn,
624                                    signing_allowed,
625                                    signing_mandatory);
626
627         /* a SPNEGO session setup has 12 command words, whereas a normal
628            NT1 session setup has 13. See the cifs spec. */
629         if (req->wct == 12 &&
630             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
631
632                 if (!xconn->smb1.negprot.spnego) {
633                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
634                                  "at SPNEGO session setup when it was not "
635                                  "negotiated.\n"));
636                         reply_nterror(req, nt_status_squash(
637                                               NT_STATUS_LOGON_FAILURE));
638                         END_PROFILE(SMBsesssetupX);
639                         return;
640                 }
641
642                 if (SVAL(req->vwv+4, 0) == 0) {
643                         setup_new_vc_session(req->sconn);
644                 }
645
646                 reply_sesssetup_and_X_spnego(req);
647                 END_PROFILE(SMBsesssetupX);
648                 return;
649         }
650
651         smb_bufsize = SVAL(req->vwv+2, 0);
652
653         if (get_Protocol() < PROTOCOL_NT1) {
654                 uint16 passlen1 = SVAL(req->vwv+7, 0);
655
656                 /* Never do NT status codes with protocols before NT1 as we
657                  * don't get client caps. */
658                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
659
660                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
661                         reply_nterror(req, nt_status_squash(
662                                               NT_STATUS_INVALID_PARAMETER));
663                         END_PROFILE(SMBsesssetupX);
664                         return;
665                 }
666
667                 if (doencrypt) {
668                         lm_resp = data_blob(req->buf, passlen1);
669                 } else {
670                         plaintext_password = data_blob(req->buf, passlen1+1);
671                         /* Ensure null termination */
672                         plaintext_password.data[passlen1] = 0;
673                 }
674
675                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
676                                        req->buf + passlen1, STR_TERMINATE);
677                 user = tmp ? tmp : "";
678
679                 domain = "";
680
681         } else {
682                 uint16 passlen1 = SVAL(req->vwv+7, 0);
683                 uint16 passlen2 = SVAL(req->vwv+8, 0);
684                 enum remote_arch_types ra_type = get_remote_arch();
685                 const uint8_t *p = req->buf;
686                 const uint8_t *save_p = req->buf;
687                 uint16 byte_count;
688
689                 if (!xconn->smb1.sessions.done_sesssetup) {
690                         global_client_caps = IVAL(req->vwv+11, 0);
691
692                         if (!(global_client_caps & CAP_STATUS32)) {
693                                 remove_from_common_flags2(
694                                                 FLAGS2_32_BIT_ERROR_CODES);
695                         }
696
697                         /* client_caps is used as final determination if
698                          * client is NT or Win95. This is needed to return
699                          * the correct error codes in some circumstances.
700                         */
701
702                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
703                                         ra_type == RA_WIN95) {
704                                 if(!(global_client_caps & (CAP_NT_SMBS|
705                                                         CAP_STATUS32))) {
706                                         set_remote_arch( RA_WIN95);
707                                 }
708                         }
709                 }
710
711                 if (!doencrypt) {
712                         /* both Win95 and WinNT stuff up the password
713                          * lengths for non-encrypting systems. Uggh.
714
715                            if passlen1==24 its a win95 system, and its setting
716                            the password length incorrectly. Luckily it still
717                            works with the default code because Win95 will null
718                            terminate the password anyway
719
720                            if passlen1>0 and passlen2>0 then maybe its a NT box
721                            and its setting passlen2 to some random value which
722                            really stuffs things up. we need to fix that one.  */
723
724                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
725                                         passlen2 != 1) {
726                                 passlen2 = 0;
727                         }
728                 }
729
730                 /* check for nasty tricks */
731                 if (passlen1 > MAX_PASS_LEN
732                     || passlen1 > smbreq_bufrem(req, p)) {
733                         reply_nterror(req, nt_status_squash(
734                                               NT_STATUS_INVALID_PARAMETER));
735                         END_PROFILE(SMBsesssetupX);
736                         return;
737                 }
738
739                 if (passlen2 > MAX_PASS_LEN
740                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
741                         reply_nterror(req, nt_status_squash(
742                                               NT_STATUS_INVALID_PARAMETER));
743                         END_PROFILE(SMBsesssetupX);
744                         return;
745                 }
746
747                 /* Save the lanman2 password and the NT md4 password. */
748
749                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
750                         doencrypt = False;
751                 }
752
753                 if (doencrypt) {
754                         lm_resp = data_blob(p, passlen1);
755                         nt_resp = data_blob(p+passlen1, passlen2);
756                 } else {
757                         char *pass = NULL;
758                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
759
760                         if (unic && (passlen2 == 0) && passlen1) {
761                                 /* Only a ascii plaintext password was sent. */
762                                 (void)srvstr_pull_talloc(talloc_tos(),
763                                                         req->inbuf,
764                                                         req->flags2,
765                                                         &pass,
766                                                         req->buf,
767                                                         passlen1,
768                                                         STR_TERMINATE|STR_ASCII);
769                         } else {
770                                 (void)srvstr_pull_talloc(talloc_tos(),
771                                                         req->inbuf,
772                                                         req->flags2,
773                                                         &pass,
774                                                         req->buf,
775                                                         unic ? passlen2 : passlen1,
776                                                         STR_TERMINATE);
777                         }
778                         if (!pass) {
779                                 reply_nterror(req, nt_status_squash(
780                                               NT_STATUS_INVALID_PARAMETER));
781                                 END_PROFILE(SMBsesssetupX);
782                                 return;
783                         }
784                         plaintext_password = data_blob(pass, strlen(pass)+1);
785                 }
786
787                 p += passlen1 + passlen2;
788
789                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
790                                             STR_TERMINATE);
791                 user = tmp ? tmp : "";
792
793                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
794                                             STR_TERMINATE);
795                 domain = tmp ? tmp : "";
796
797                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
798                                             STR_TERMINATE);
799                 native_os = tmp ? tmp : "";
800
801                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
802                                             STR_TERMINATE);
803                 native_lanman = tmp ? tmp : "";
804
805                 /* not documented or decoded by Ethereal but there is one more
806                  * string in the extra bytes which is the same as the
807                  * PrimaryDomain when using extended security.  Windows NT 4
808                  * and 2003 use this string to store the native lanman string.
809                  * Windows 9x does not include a string here at all so we have
810                  * to check if we have any extra bytes left */
811
812                 byte_count = SVAL(req->vwv+13, 0);
813                 if ( PTR_DIFF(p, save_p) < byte_count) {
814                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
815                                                     STR_TERMINATE);
816                         primary_domain = tmp ? tmp : "";
817                 } else {
818                         primary_domain = talloc_strdup(talloc_tos(), "null");
819                 }
820
821                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
822                         "PrimaryDomain=[%s]\n",
823                         domain, native_os, native_lanman, primary_domain));
824
825                 if ( ra_type == RA_WIN2K ) {
826                         if ( strlen(native_lanman) == 0 )
827                                 ra_lanman_string( primary_domain );
828                         else
829                                 ra_lanman_string( native_lanman );
830                 }
831
832         }
833
834         if (SVAL(req->vwv+4, 0) == 0) {
835                 setup_new_vc_session(req->sconn);
836         }
837
838         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
839                                 domain, user, get_remote_machine_name()));
840
841         if (*user) {
842                 if (xconn->smb1.negprot.spnego) {
843
844                         /* This has to be here, because this is a perfectly
845                          * valid behaviour for guest logons :-( */
846
847                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
848                                 "at 'normal' session setup after "
849                                 "negotiating spnego.\n"));
850                         reply_nterror(req, nt_status_squash(
851                                               NT_STATUS_LOGON_FAILURE));
852                         END_PROFILE(SMBsesssetupX);
853                         return;
854                 }
855                 fstrcpy(sub_user, user);
856         } else {
857                 fstrcpy(sub_user, "");
858         }
859
860         sub_set_smb_name(sub_user);
861
862         reload_services(sconn, conn_snum_used, true);
863
864         if (!*user) {
865
866                 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
867
868         } else if (doencrypt) {
869                 struct auth4_context *negprot_auth_context = NULL;
870                 negprot_auth_context = xconn->smb1.negprot.auth_context;
871                 if (!negprot_auth_context) {
872                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
873                                 "session setup without negprot denied!\n"));
874                         reply_nterror(req, nt_status_squash(
875                                               NT_STATUS_LOGON_FAILURE));
876                         END_PROFILE(SMBsesssetupX);
877                         return;
878                 }
879                 nt_status = make_user_info_for_reply_enc(talloc_tos(),
880                                                          &user_info, user,
881                                                          domain,
882                                                          sconn->remote_address,
883                                                          lm_resp, nt_resp);
884                 if (NT_STATUS_IS_OK(nt_status)) {
885                         nt_status = auth_check_password_session_info(negprot_auth_context, 
886                                                                      req, user_info, &session_info);
887                 }
888         } else {
889                 struct auth4_context *plaintext_auth_context = NULL;
890
891                 nt_status = make_auth4_context(
892                         talloc_tos(), &plaintext_auth_context);
893
894                 if (NT_STATUS_IS_OK(nt_status)) {
895                         uint8_t chal[8];
896
897                         plaintext_auth_context->get_ntlm_challenge(
898                                         plaintext_auth_context, chal);
899
900                         if (!make_user_info_for_reply(talloc_tos(),
901                                                       &user_info,
902                                                       user, domain,
903                                                       sconn->remote_address,
904                                                       chal,
905                                                       plaintext_password)) {
906                                 nt_status = NT_STATUS_NO_MEMORY;
907                         }
908
909                         if (NT_STATUS_IS_OK(nt_status)) {
910                                 nt_status = auth_check_password_session_info(plaintext_auth_context, 
911                                                                              req, user_info, &session_info);
912                         }
913                         TALLOC_FREE(plaintext_auth_context);
914                 }
915         }
916
917         TALLOC_FREE(user_info);
918
919         if (!NT_STATUS_IS_OK(nt_status)) {
920                 data_blob_free(&nt_resp);
921                 data_blob_free(&lm_resp);
922                 data_blob_clear_free(&plaintext_password);
923                 reply_nterror(req, nt_status_squash(nt_status));
924                 END_PROFILE(SMBsesssetupX);
925                 return;
926         }
927
928         data_blob_clear_free(&plaintext_password);
929
930         /* it's ok - setup a reply */
931         reply_outbuf(req, 3, 0);
932         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
933         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
934
935         if (get_Protocol() >= PROTOCOL_NT1) {
936                 push_signature(&req->outbuf);
937                 /* perhaps grab OS version here?? */
938         }
939
940         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
941                 action = 1;
942         }
943
944         /* register the name and uid as being validated, so further connections
945            to a uid can get through without a password, on the same VC */
946
947         nt_status = smbXsrv_session_create(xconn,
948                                            now, &session);
949         if (!NT_STATUS_IS_OK(nt_status)) {
950                 data_blob_free(&nt_resp);
951                 data_blob_free(&lm_resp);
952                 reply_nterror(req, nt_status_squash(nt_status));
953                 END_PROFILE(SMBsesssetupX);
954                 return;
955         }
956
957         if (session_info->session_key.length > 0) {
958                 uint8_t session_key[16];
959
960                 /*
961                  * Note: the SMB1 signing key is not truncated to 16 byte!
962                  */
963                 session->global->signing_key =
964                         data_blob_dup_talloc(session->global,
965                                              session_info->session_key);
966                 if (session->global->signing_key.data == NULL) {
967                         data_blob_free(&nt_resp);
968                         data_blob_free(&lm_resp);
969                         TALLOC_FREE(session);
970                         reply_nterror(req, NT_STATUS_NO_MEMORY);
971                         END_PROFILE(SMBsesssetupX);
972                         return;
973                 }
974
975                 /*
976                  * The application key is truncated/padded to 16 bytes
977                  */
978                 ZERO_STRUCT(session_key);
979                 memcpy(session_key, session->global->signing_key.data,
980                        MIN(session->global->signing_key.length,
981                            sizeof(session_key)));
982                 session->global->application_key =
983                         data_blob_talloc(session->global,
984                                          session_key,
985                                          sizeof(session_key));
986                 ZERO_STRUCT(session_key);
987                 if (session->global->application_key.data == NULL) {
988                         data_blob_free(&nt_resp);
989                         data_blob_free(&lm_resp);
990                         TALLOC_FREE(session);
991                         reply_nterror(req, NT_STATUS_NO_MEMORY);
992                         END_PROFILE(SMBsesssetupX);
993                         return;
994                 }
995
996                 /*
997                  * Place the application key into the session_info
998                  */
999                 data_blob_clear_free(&session_info->session_key);
1000                 session_info->session_key = data_blob_dup_talloc(session_info,
1001                                                 session->global->application_key);
1002                 if (session_info->session_key.data == NULL) {
1003                         data_blob_free(&nt_resp);
1004                         data_blob_free(&lm_resp);
1005                         TALLOC_FREE(session);
1006                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1007                         END_PROFILE(SMBsesssetupX);
1008                         return;
1009                 }
1010         }
1011
1012         session->compat = talloc_zero(session, struct user_struct);
1013         if (session->compat == 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         session->compat->session = session;
1022         session->compat->homes_snum = -1;
1023         session->compat->session_info = session_info;
1024         session->compat->session_keystr = NULL;
1025         session->compat->vuid = session->global->session_wire_id;
1026         DLIST_ADD(sconn->users, session->compat);
1027         sconn->num_users++;
1028
1029         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1030                 session->compat->homes_snum =
1031                         register_homes_share(session_info->unix_info->unix_name);
1032         }
1033
1034         if (srv_is_signing_negotiated(xconn) &&
1035             action == 0 &&
1036             session->global->signing_key.length > 0)
1037         {
1038                 /*
1039                  * Try and turn on server signing on the first non-guest
1040                  * sessionsetup.
1041                  */
1042                 srv_set_signing(xconn,
1043                         session->global->signing_key,
1044                         nt_resp.data ? nt_resp : lm_resp);
1045         }
1046
1047         set_current_user_info(session_info->unix_info->sanitized_username,
1048                               session_info->unix_info->unix_name,
1049                               session_info->info->domain_name);
1050
1051         session->status = NT_STATUS_OK;
1052         session->global->auth_session_info = talloc_move(session->global,
1053                                                          &session_info);
1054         session->global->auth_session_info_seqnum += 1;
1055         session->global->channels[0].auth_session_info_seqnum =
1056                 session->global->auth_session_info_seqnum;
1057         session->global->auth_time = now;
1058         session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1059
1060         nt_status = smbXsrv_session_update(session);
1061         if (!NT_STATUS_IS_OK(nt_status)) {
1062                 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1063                           (unsigned long long)session->compat->vuid,
1064                           nt_errstr(nt_status)));
1065                 data_blob_free(&nt_resp);
1066                 data_blob_free(&lm_resp);
1067                 TALLOC_FREE(session);
1068                 reply_nterror(req, nt_status_squash(nt_status));
1069                 END_PROFILE(SMBsesssetupX);
1070                 return;
1071         }
1072
1073         if (!session_claim(session)) {
1074                 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1075                           (unsigned long long)session->compat->vuid));
1076                 data_blob_free(&nt_resp);
1077                 data_blob_free(&lm_resp);
1078                 TALLOC_FREE(session);
1079                 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1080                 END_PROFILE(SMBsesssetupX);
1081                 return;
1082         }
1083
1084         /* current_user_info is changed on new vuid */
1085         reload_services(sconn, conn_snum_used, true);
1086
1087         sess_vuid = session->global->session_wire_id;
1088
1089         data_blob_free(&nt_resp);
1090         data_blob_free(&lm_resp);
1091
1092         SSVAL(req->outbuf,smb_vwv2,action);
1093         SSVAL(req->outbuf,smb_uid,sess_vuid);
1094         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1095         req->vuid = sess_vuid;
1096
1097         if (!xconn->smb1.sessions.done_sesssetup) {
1098                 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1099                         reply_force_doserror(req, ERRSRV, ERRerror);
1100                         END_PROFILE(SMBsesssetupX);
1101                         return;
1102                 }
1103                 xconn->smb1.sessions.max_send = smb_bufsize;
1104                 xconn->smb1.sessions.done_sesssetup = true;
1105         }
1106
1107         END_PROFILE(SMBsesssetupX);
1108 }