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