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