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