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