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