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