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