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