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