s3:smbd: move sconn->smb1.sessions.* to xconn->smb1.sessions.*
[metze/samba-autobuild/.git] / source3 / smbd / sesssetup.c
1 /*
2    Unix SMB/CIFS implementation.
3    handle SMBsessionsetup
4    Copyright (C) Andrew Tridgell 1998-2001
5    Copyright (C) Andrew Bartlett      2001
6    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
7    Copyright (C) Luke Howard          2003
8    Copyright (C) Volker Lendecke      2007
9    Copyright (C) Jeremy Allison       2007
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "../lib/tsocket/tsocket.h"
27 #include "smbd/smbd.h"
28 #include "smbd/globals.h"
29 #include "../libcli/auth/spnego.h"
30 #include "../auth/ntlmssp/ntlmssp.h"
31 #include "../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 smbd_server_connection *sconn = req->sconn;
135         struct smbXsrv_connection *xconn = sconn->conn;
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(sconn->conn,
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(sconn->conn,
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, sconn->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(sconn) &&
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(sconn,
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                 if (client_caps & CAP_DYNAMIC_REAUTH) {
358                         session->global->expiration_time =
359                                 gensec_expire_time(session->gensec);
360                 } else {
361                         session->global->expiration_time =
362                                 GENSEC_EXPIRE_TIME_INFINITY;
363                 }
364
365                 if (!session_claim(session)) {
366                         DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
367                                   (unsigned long long)session->compat->vuid));
368                         data_blob_free(&out_blob);
369                         TALLOC_FREE(session);
370                         reply_nterror(req, NT_STATUS_LOGON_FAILURE);
371                         return;
372                 }
373
374                 status = smbXsrv_session_update(session);
375                 if (!NT_STATUS_IS_OK(status)) {
376                         DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
377                                   (unsigned long long)session->compat->vuid,
378                                   nt_errstr(status)));
379                         data_blob_free(&out_blob);
380                         TALLOC_FREE(session);
381                         reply_nterror(req, NT_STATUS_LOGON_FAILURE);
382                         return;
383                 }
384
385                 if (!xconn->smb1.sessions.done_sesssetup) {
386                         if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
387                                 reply_force_doserror(req, ERRSRV, ERRerror);
388                                 return;
389                         }
390                         xconn->smb1.sessions.max_send = smb_bufsize;
391                         xconn->smb1.sessions.done_sesssetup = true;
392                 }
393
394                 /* current_user_info is changed on new vuid */
395                 reload_services(sconn, conn_snum_used, true);
396         } else if (NT_STATUS_IS_OK(status)) {
397                 struct auth_session_info *session_info = NULL;
398
399                 status = gensec_session_info(session->gensec,
400                                              session,
401                                              &session_info);
402                 if (!NT_STATUS_IS_OK(status)) {
403                         DEBUG(1,("Failed to generate session_info "
404                                  "(user and group token) for session setup: %s\n",
405                                  nt_errstr(status)));
406                         data_blob_free(&out_blob);
407                         TALLOC_FREE(session);
408                         reply_nterror(req, nt_status_squash(status));
409                         return;
410                 }
411
412                 if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
413                         action = 1;
414                 }
415
416                 /*
417                  * Keep the application key
418                  */
419                 data_blob_clear_free(&session_info->session_key);
420                 session_info->session_key =
421                         session->global->auth_session_info->session_key;
422                 talloc_steal(session_info, session_info->session_key.data);
423                 TALLOC_FREE(session->global->auth_session_info);
424
425                 session->compat->session_info = session_info;
426
427                 session->compat->vuid = session->global->session_wire_id;
428
429                 if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
430                         session->compat->homes_snum =
431                                 register_homes_share(session_info->unix_info->unix_name);
432                 }
433
434                 set_current_user_info(session_info->unix_info->sanitized_username,
435                                       session_info->unix_info->unix_name,
436                                       session_info->info->domain_name);
437
438                 session->status = NT_STATUS_OK;
439                 session->global->auth_session_info = talloc_move(session->global,
440                                                                  &session_info);
441                 session->global->auth_session_info_seqnum += 1;
442                 session->global->channels[0].auth_session_info_seqnum =
443                         session->global->auth_session_info_seqnum;
444                 if (client_caps & CAP_DYNAMIC_REAUTH) {
445                         session->global->expiration_time =
446                                 gensec_expire_time(session->gensec);
447                 } else {
448                         session->global->expiration_time =
449                                 GENSEC_EXPIRE_TIME_INFINITY;
450                 }
451
452                 status = smbXsrv_session_update(session);
453                 if (!NT_STATUS_IS_OK(status)) {
454                         DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
455                                   (unsigned long long)session->compat->vuid,
456                                   nt_errstr(status)));
457                         data_blob_free(&out_blob);
458                         TALLOC_FREE(session);
459                         reply_nterror(req, NT_STATUS_LOGON_FAILURE);
460                         return;
461                 }
462
463                 conn_clear_vuid_caches(sconn, session->compat->vuid);
464
465                 /* current_user_info is changed on new vuid */
466                 reload_services(sconn, conn_snum_used, true);
467         }
468
469         vuid = session->global->session_wire_id;
470
471         reply_outbuf(req, 4, 0);
472
473         SSVAL(req->outbuf, smb_uid, vuid);
474         SIVAL(req->outbuf, smb_rcls, NT_STATUS_V(status));
475         SSVAL(req->outbuf, smb_vwv0, 0xFF); /* no chaining possible */
476         SSVAL(req->outbuf, smb_vwv2, action);
477         SSVAL(req->outbuf, smb_vwv3, out_blob.length);
478
479         if (message_push_blob(&req->outbuf, out_blob) == -1) {
480                 data_blob_free(&out_blob);
481                 TALLOC_FREE(session);
482                 reply_nterror(req, NT_STATUS_NO_MEMORY);
483                 return;
484         }
485         data_blob_free(&out_blob);
486
487         if (push_signature(&req->outbuf) == -1) {
488                 TALLOC_FREE(session);
489                 reply_nterror(req, NT_STATUS_NO_MEMORY);
490                 return;
491         }
492 }
493
494 /****************************************************************************
495  On new VC == 0, shutdown *all* old connections and users.
496  It seems that only NT4.x does this. At W2K and above (XP etc.).
497  a new session setup with VC==0 is ignored.
498 ****************************************************************************/
499
500 struct shutdown_state {
501         const char *ip;
502         struct messaging_context *msg_ctx;
503 };
504
505 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
506                                 void *private_data)
507 {
508         struct shutdown_state *state = (struct shutdown_state *)private_data;
509         struct server_id self_pid = messaging_server_id(state->msg_ctx);
510         struct server_id pid = session->channels[0].server_id;
511         const char *addr = session->channels[0].remote_address;
512
513         DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
514                    server_id_str(talloc_tos(), &pid), addr));
515
516         if (!process_exists(pid)) {
517                 DEBUG(10, ("process does not exist\n"));
518                 return 0;
519         }
520
521         if (serverid_equal(&pid, &self_pid)) {
522                 DEBUG(10, ("It's me\n"));
523                 return 0;
524         }
525
526         /*
527          * here we use strstr() because 'addr'
528          * (session->channels[0].remote_address)
529          * contains a string like:
530          * 'ipv4:127.0.0.1:48163'
531          */
532         if (strstr(addr, state->ip)  == NULL) {
533                 DEBUG(10, ("%s does not match %s\n", state->ip, addr));
534                 return 0;
535         }
536
537         DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
538                   "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
539                   state->ip));
540
541         messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
542                        &data_blob_null);
543         return 0;
544 }
545
546 static void setup_new_vc_session(struct smbd_server_connection *sconn)
547 {
548         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
549                 "compatible we would close all old resources.\n"));
550 #if 0
551         conn_close_all();
552         invalidate_all_vuids();
553 #endif
554         if (lp_reset_on_zero_vc()) {
555                 char *addr;
556                 struct shutdown_state state;
557
558                 addr = tsocket_address_inet_addr_string(
559                         sconn->remote_address, talloc_tos());
560                 if (addr == NULL) {
561                         return;
562                 }
563                 state.ip = addr;
564                 state.msg_ctx = sconn->msg_ctx;
565                 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
566                 TALLOC_FREE(addr);
567         }
568 }
569
570 /****************************************************************************
571  Reply to a session setup command.
572 ****************************************************************************/
573
574 void reply_sesssetup_and_X(struct smb_request *req)
575 {
576         uint64_t sess_vuid;
577         uint16_t smb_bufsize;
578         DATA_BLOB lm_resp;
579         DATA_BLOB nt_resp;
580         DATA_BLOB plaintext_password;
581         char *tmp;
582         const char *user;
583         fstring sub_user; /* Sanitised username for substituion */
584         const char *domain;
585         const char *native_os;
586         const char *native_lanman;
587         const char *primary_domain;
588         struct auth_usersupplied_info *user_info = NULL;
589         struct auth_session_info *session_info = NULL;
590         uint16 smb_flag2 = req->flags2;
591         uint16_t action = 0;
592         NTTIME now = timeval_to_nttime(&req->request_time);
593         struct smbXsrv_session *session = NULL;
594         NTSTATUS nt_status;
595         struct smbd_server_connection *sconn = req->sconn;
596         struct smbXsrv_connection *xconn = sconn->conn;
597         bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
598         bool signing_allowed = false;
599         bool signing_mandatory = false;
600
601         START_PROFILE(SMBsesssetupX);
602
603         ZERO_STRUCT(lm_resp);
604         ZERO_STRUCT(nt_resp);
605         ZERO_STRUCT(plaintext_password);
606
607         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
608
609         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
610                 signing_allowed = true;
611         }
612         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
613                 signing_mandatory = true;
614         }
615
616         /*
617          * We can call srv_set_signing_negotiated() each time.
618          * It finds out when it needs to turn into a noop
619          * itself.
620          */
621         srv_set_signing_negotiated(req->sconn,
622                                    signing_allowed,
623                                    signing_mandatory);
624
625         /* a SPNEGO session setup has 12 command words, whereas a normal
626            NT1 session setup has 13. See the cifs spec. */
627         if (req->wct == 12 &&
628             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
629
630                 if (!xconn->smb1.negprot.spnego) {
631                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
632                                  "at SPNEGO session setup when it was not "
633                                  "negotiated.\n"));
634                         reply_nterror(req, nt_status_squash(
635                                               NT_STATUS_LOGON_FAILURE));
636                         END_PROFILE(SMBsesssetupX);
637                         return;
638                 }
639
640                 if (SVAL(req->vwv+4, 0) == 0) {
641                         setup_new_vc_session(req->sconn);
642                 }
643
644                 reply_sesssetup_and_X_spnego(req);
645                 END_PROFILE(SMBsesssetupX);
646                 return;
647         }
648
649         smb_bufsize = SVAL(req->vwv+2, 0);
650
651         if (get_Protocol() < PROTOCOL_NT1) {
652                 uint16 passlen1 = SVAL(req->vwv+7, 0);
653
654                 /* Never do NT status codes with protocols before NT1 as we
655                  * don't get client caps. */
656                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
657
658                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
659                         reply_nterror(req, nt_status_squash(
660                                               NT_STATUS_INVALID_PARAMETER));
661                         END_PROFILE(SMBsesssetupX);
662                         return;
663                 }
664
665                 if (doencrypt) {
666                         lm_resp = data_blob(req->buf, passlen1);
667                 } else {
668                         plaintext_password = data_blob(req->buf, passlen1+1);
669                         /* Ensure null termination */
670                         plaintext_password.data[passlen1] = 0;
671                 }
672
673                 srvstr_pull_req_talloc(talloc_tos(), req, &tmp,
674                                        req->buf + passlen1, STR_TERMINATE);
675                 user = tmp ? tmp : "";
676
677                 domain = "";
678
679         } else {
680                 uint16 passlen1 = SVAL(req->vwv+7, 0);
681                 uint16 passlen2 = SVAL(req->vwv+8, 0);
682                 enum remote_arch_types ra_type = get_remote_arch();
683                 const uint8_t *p = req->buf;
684                 const uint8_t *save_p = req->buf;
685                 uint16 byte_count;
686
687                 if (!xconn->smb1.sessions.done_sesssetup) {
688                         global_client_caps = IVAL(req->vwv+11, 0);
689
690                         if (!(global_client_caps & CAP_STATUS32)) {
691                                 remove_from_common_flags2(
692                                                 FLAGS2_32_BIT_ERROR_CODES);
693                         }
694
695                         /* client_caps is used as final determination if
696                          * client is NT or Win95. This is needed to return
697                          * the correct error codes in some circumstances.
698                         */
699
700                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
701                                         ra_type == RA_WIN95) {
702                                 if(!(global_client_caps & (CAP_NT_SMBS|
703                                                         CAP_STATUS32))) {
704                                         set_remote_arch( RA_WIN95);
705                                 }
706                         }
707                 }
708
709                 if (!doencrypt) {
710                         /* both Win95 and WinNT stuff up the password
711                          * lengths for non-encrypting systems. Uggh.
712
713                            if passlen1==24 its a win95 system, and its setting
714                            the password length incorrectly. Luckily it still
715                            works with the default code because Win95 will null
716                            terminate the password anyway
717
718                            if passlen1>0 and passlen2>0 then maybe its a NT box
719                            and its setting passlen2 to some random value which
720                            really stuffs things up. we need to fix that one.  */
721
722                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
723                                         passlen2 != 1) {
724                                 passlen2 = 0;
725                         }
726                 }
727
728                 /* check for nasty tricks */
729                 if (passlen1 > MAX_PASS_LEN
730                     || passlen1 > smbreq_bufrem(req, p)) {
731                         reply_nterror(req, nt_status_squash(
732                                               NT_STATUS_INVALID_PARAMETER));
733                         END_PROFILE(SMBsesssetupX);
734                         return;
735                 }
736
737                 if (passlen2 > MAX_PASS_LEN
738                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
739                         reply_nterror(req, nt_status_squash(
740                                               NT_STATUS_INVALID_PARAMETER));
741                         END_PROFILE(SMBsesssetupX);
742                         return;
743                 }
744
745                 /* Save the lanman2 password and the NT md4 password. */
746
747                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
748                         doencrypt = False;
749                 }
750
751                 if (doencrypt) {
752                         lm_resp = data_blob(p, passlen1);
753                         nt_resp = data_blob(p+passlen1, passlen2);
754                 } else {
755                         char *pass = NULL;
756                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
757
758                         if (unic && (passlen2 == 0) && passlen1) {
759                                 /* Only a ascii plaintext password was sent. */
760                                 (void)srvstr_pull_talloc(talloc_tos(),
761                                                         req->inbuf,
762                                                         req->flags2,
763                                                         &pass,
764                                                         req->buf,
765                                                         passlen1,
766                                                         STR_TERMINATE|STR_ASCII);
767                         } else {
768                                 (void)srvstr_pull_talloc(talloc_tos(),
769                                                         req->inbuf,
770                                                         req->flags2,
771                                                         &pass,
772                                                         req->buf,
773                                                         unic ? passlen2 : passlen1,
774                                                         STR_TERMINATE);
775                         }
776                         if (!pass) {
777                                 reply_nterror(req, nt_status_squash(
778                                               NT_STATUS_INVALID_PARAMETER));
779                                 END_PROFILE(SMBsesssetupX);
780                                 return;
781                         }
782                         plaintext_password = data_blob(pass, strlen(pass)+1);
783                 }
784
785                 p += passlen1 + passlen2;
786
787                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
788                                             STR_TERMINATE);
789                 user = tmp ? tmp : "";
790
791                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
792                                             STR_TERMINATE);
793                 domain = tmp ? tmp : "";
794
795                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
796                                             STR_TERMINATE);
797                 native_os = tmp ? tmp : "";
798
799                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
800                                             STR_TERMINATE);
801                 native_lanman = tmp ? tmp : "";
802
803                 /* not documented or decoded by Ethereal but there is one more
804                  * string in the extra bytes which is the same as the
805                  * PrimaryDomain when using extended security.  Windows NT 4
806                  * and 2003 use this string to store the native lanman string.
807                  * Windows 9x does not include a string here at all so we have
808                  * to check if we have any extra bytes left */
809
810                 byte_count = SVAL(req->vwv+13, 0);
811                 if ( PTR_DIFF(p, save_p) < byte_count) {
812                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
813                                                     STR_TERMINATE);
814                         primary_domain = tmp ? tmp : "";
815                 } else {
816                         primary_domain = talloc_strdup(talloc_tos(), "null");
817                 }
818
819                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
820                         "PrimaryDomain=[%s]\n",
821                         domain, native_os, native_lanman, primary_domain));
822
823                 if ( ra_type == RA_WIN2K ) {
824                         if ( strlen(native_lanman) == 0 )
825                                 ra_lanman_string( primary_domain );
826                         else
827                                 ra_lanman_string( native_lanman );
828                 }
829
830         }
831
832         if (SVAL(req->vwv+4, 0) == 0) {
833                 setup_new_vc_session(req->sconn);
834         }
835
836         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
837                                 domain, user, get_remote_machine_name()));
838
839         if (*user) {
840                 if (xconn->smb1.negprot.spnego) {
841
842                         /* This has to be here, because this is a perfectly
843                          * valid behaviour for guest logons :-( */
844
845                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
846                                 "at 'normal' session setup after "
847                                 "negotiating spnego.\n"));
848                         reply_nterror(req, nt_status_squash(
849                                               NT_STATUS_LOGON_FAILURE));
850                         END_PROFILE(SMBsesssetupX);
851                         return;
852                 }
853                 fstrcpy(sub_user, user);
854         } else {
855                 fstrcpy(sub_user, "");
856         }
857
858         sub_set_smb_name(sub_user);
859
860         reload_services(sconn, conn_snum_used, true);
861
862         if (!*user) {
863
864                 nt_status = check_guest_password(sconn->remote_address, req, &session_info);
865
866         } else if (doencrypt) {
867                 struct auth4_context *negprot_auth_context = NULL;
868                 negprot_auth_context = xconn->smb1.negprot.auth_context;
869                 if (!negprot_auth_context) {
870                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
871                                 "session setup without negprot denied!\n"));
872                         reply_nterror(req, nt_status_squash(
873                                               NT_STATUS_LOGON_FAILURE));
874                         END_PROFILE(SMBsesssetupX);
875                         return;
876                 }
877                 nt_status = make_user_info_for_reply_enc(talloc_tos(),
878                                                          &user_info, user,
879                                                          domain,
880                                                          sconn->remote_address,
881                                                          lm_resp, nt_resp);
882                 if (NT_STATUS_IS_OK(nt_status)) {
883                         nt_status = auth_check_password_session_info(negprot_auth_context, 
884                                                                      req, user_info, &session_info);
885                 }
886         } else {
887                 struct auth4_context *plaintext_auth_context = NULL;
888
889                 nt_status = make_auth4_context(
890                         talloc_tos(), &plaintext_auth_context);
891
892                 if (NT_STATUS_IS_OK(nt_status)) {
893                         uint8_t chal[8];
894
895                         plaintext_auth_context->get_ntlm_challenge(
896                                         plaintext_auth_context, chal);
897
898                         if (!make_user_info_for_reply(talloc_tos(),
899                                                       &user_info,
900                                                       user, domain,
901                                                       sconn->remote_address,
902                                                       chal,
903                                                       plaintext_password)) {
904                                 nt_status = NT_STATUS_NO_MEMORY;
905                         }
906
907                         if (NT_STATUS_IS_OK(nt_status)) {
908                                 nt_status = auth_check_password_session_info(plaintext_auth_context, 
909                                                                              req, user_info, &session_info);
910                         }
911                         TALLOC_FREE(plaintext_auth_context);
912                 }
913         }
914
915         TALLOC_FREE(user_info);
916
917         if (!NT_STATUS_IS_OK(nt_status)) {
918                 data_blob_free(&nt_resp);
919                 data_blob_free(&lm_resp);
920                 data_blob_clear_free(&plaintext_password);
921                 reply_nterror(req, nt_status_squash(nt_status));
922                 END_PROFILE(SMBsesssetupX);
923                 return;
924         }
925
926         data_blob_clear_free(&plaintext_password);
927
928         /* it's ok - setup a reply */
929         reply_outbuf(req, 3, 0);
930         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
931         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
932
933         if (get_Protocol() >= PROTOCOL_NT1) {
934                 push_signature(&req->outbuf);
935                 /* perhaps grab OS version here?? */
936         }
937
938         if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
939                 action = 1;
940         }
941
942         /* register the name and uid as being validated, so further connections
943            to a uid can get through without a password, on the same VC */
944
945         nt_status = smbXsrv_session_create(sconn->conn,
946                                            now, &session);
947         if (!NT_STATUS_IS_OK(nt_status)) {
948                 data_blob_free(&nt_resp);
949                 data_blob_free(&lm_resp);
950                 reply_nterror(req, nt_status_squash(nt_status));
951                 END_PROFILE(SMBsesssetupX);
952                 return;
953         }
954
955         if (session_info->session_key.length > 0) {
956                 uint8_t session_key[16];
957
958                 /*
959                  * Note: the SMB1 signing key is not truncated to 16 byte!
960                  */
961                 session->global->signing_key =
962                         data_blob_dup_talloc(session->global,
963                                              session_info->session_key);
964                 if (session->global->signing_key.data == NULL) {
965                         data_blob_free(&nt_resp);
966                         data_blob_free(&lm_resp);
967                         TALLOC_FREE(session);
968                         reply_nterror(req, NT_STATUS_NO_MEMORY);
969                         END_PROFILE(SMBsesssetupX);
970                         return;
971                 }
972
973                 /*
974                  * The application key is truncated/padded to 16 bytes
975                  */
976                 ZERO_STRUCT(session_key);
977                 memcpy(session_key, session->global->signing_key.data,
978                        MIN(session->global->signing_key.length,
979                            sizeof(session_key)));
980                 session->global->application_key =
981                         data_blob_talloc(session->global,
982                                          session_key,
983                                          sizeof(session_key));
984                 ZERO_STRUCT(session_key);
985                 if (session->global->application_key.data == NULL) {
986                         data_blob_free(&nt_resp);
987                         data_blob_free(&lm_resp);
988                         TALLOC_FREE(session);
989                         reply_nterror(req, NT_STATUS_NO_MEMORY);
990                         END_PROFILE(SMBsesssetupX);
991                         return;
992                 }
993
994                 /*
995                  * Place the application key into the session_info
996                  */
997                 data_blob_clear_free(&session_info->session_key);
998                 session_info->session_key = data_blob_dup_talloc(session_info,
999                                                 session->global->application_key);
1000                 if (session_info->session_key.data == NULL) {
1001                         data_blob_free(&nt_resp);
1002                         data_blob_free(&lm_resp);
1003                         TALLOC_FREE(session);
1004                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1005                         END_PROFILE(SMBsesssetupX);
1006                         return;
1007                 }
1008         }
1009
1010         session->compat = talloc_zero(session, struct user_struct);
1011         if (session->compat == NULL) {
1012                 data_blob_free(&nt_resp);
1013                 data_blob_free(&lm_resp);
1014                 TALLOC_FREE(session);
1015                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1016                 END_PROFILE(SMBsesssetupX);
1017                 return;
1018         }
1019         session->compat->session = session;
1020         session->compat->homes_snum = -1;
1021         session->compat->session_info = session_info;
1022         session->compat->session_keystr = NULL;
1023         session->compat->vuid = session->global->session_wire_id;
1024         DLIST_ADD(sconn->users, session->compat);
1025         sconn->num_users++;
1026
1027         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1028                 session->compat->homes_snum =
1029                         register_homes_share(session_info->unix_info->unix_name);
1030         }
1031
1032         if (srv_is_signing_negotiated(sconn) &&
1033             action == 0 &&
1034             session->global->signing_key.length > 0)
1035         {
1036                 /*
1037                  * Try and turn on server signing on the first non-guest
1038                  * sessionsetup.
1039                  */
1040                 srv_set_signing(sconn,
1041                         session->global->signing_key,
1042                         nt_resp.data ? nt_resp : lm_resp);
1043         }
1044
1045         set_current_user_info(session_info->unix_info->sanitized_username,
1046                               session_info->unix_info->unix_name,
1047                               session_info->info->domain_name);
1048
1049         session->status = NT_STATUS_OK;
1050         session->global->auth_session_info = talloc_move(session->global,
1051                                                          &session_info);
1052         session->global->auth_session_info_seqnum += 1;
1053         session->global->channels[0].auth_session_info_seqnum =
1054                 session->global->auth_session_info_seqnum;
1055         session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1056
1057         nt_status = smbXsrv_session_update(session);
1058         if (!NT_STATUS_IS_OK(nt_status)) {
1059                 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1060                           (unsigned long long)session->compat->vuid,
1061                           nt_errstr(nt_status)));
1062                 data_blob_free(&nt_resp);
1063                 data_blob_free(&lm_resp);
1064                 TALLOC_FREE(session);
1065                 reply_nterror(req, nt_status_squash(nt_status));
1066                 END_PROFILE(SMBsesssetupX);
1067                 return;
1068         }
1069
1070         if (!session_claim(session)) {
1071                 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1072                           (unsigned long long)session->compat->vuid));
1073                 data_blob_free(&nt_resp);
1074                 data_blob_free(&lm_resp);
1075                 TALLOC_FREE(session);
1076                 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1077                 END_PROFILE(SMBsesssetupX);
1078                 return;
1079         }
1080
1081         /* current_user_info is changed on new vuid */
1082         reload_services(sconn, conn_snum_used, true);
1083
1084         sess_vuid = session->global->session_wire_id;
1085
1086         data_blob_free(&nt_resp);
1087         data_blob_free(&lm_resp);
1088
1089         SSVAL(req->outbuf,smb_vwv2,action);
1090         SSVAL(req->outbuf,smb_uid,sess_vuid);
1091         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1092         req->vuid = sess_vuid;
1093
1094         if (!xconn->smb1.sessions.done_sesssetup) {
1095                 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1096                         reply_force_doserror(req, ERRSRV, ERRerror);
1097                         END_PROFILE(SMBsesssetupX);
1098                         return;
1099                 }
1100                 xconn->smb1.sessions.max_send = smb_bufsize;
1101                 xconn->smb1.sessions.done_sesssetup = true;
1102         }
1103
1104         END_PROFILE(SMBsesssetupX);
1105 }