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