smbd: Factor out "has_other_nonposix_opens"
[bbaumbach/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         size_t ip_len;
486         struct messaging_context *msg_ctx;
487 };
488
489 static int shutdown_other_smbds(struct smbXsrv_session_global0 *session,
490                                 void *private_data)
491 {
492         struct shutdown_state *state = (struct shutdown_state *)private_data;
493         struct server_id self_pid = messaging_server_id(state->msg_ctx);
494         struct server_id pid = session->channels[0].server_id;
495         const char *addr = session->channels[0].remote_address;
496         const char *port_colon;
497         size_t addr_len;
498         struct server_id_buf tmp;
499
500         DEBUG(10, ("shutdown_other_smbds: %s, %s\n",
501                    server_id_str_buf(pid, &tmp), addr));
502
503         if (!process_exists(pid)) {
504                 DEBUG(10, ("process does not exist\n"));
505                 return 0;
506         }
507
508         if (serverid_equal(&pid, &self_pid)) {
509                 DEBUG(10, ("It's me\n"));
510                 return 0;
511         }
512
513         port_colon = strrchr(addr, ':');
514         if (port_colon == NULL) {
515                 DBG_DEBUG("addr %s in contains no port\n", addr);
516                 return 0;
517         }
518         addr_len = port_colon - addr;
519
520         if ((addr_len != state->ip_len) ||
521             (strncmp(addr, state->ip, state->ip_len) != 0)) {
522                 DEBUG(10, ("%s (%zu) does not match %s (%zu)\n",
523                            state->ip, state->ip_len, addr, addr_len));
524                 return 0;
525         }
526
527         DEBUG(1, ("shutdown_other_smbds: shutting down pid %u "
528                   "(IP %s)\n", (unsigned int)procid_to_pid(&pid),
529                   state->ip));
530
531         messaging_send(state->msg_ctx, pid, MSG_SHUTDOWN,
532                        &data_blob_null);
533         return 0;
534 }
535
536 static void setup_new_vc_session(struct smbd_server_connection *sconn)
537 {
538         DEBUG(2,("setup_new_vc_session: New VC == 0, if NT4.x "
539                 "compatible we would close all old resources.\n"));
540
541         if (lp_reset_on_zero_vc()) {
542                 char *addr;
543                 const char *port_colon;
544                 struct shutdown_state state;
545
546                 addr = tsocket_address_string(
547                         sconn->remote_address, talloc_tos());
548                 if (addr == NULL) {
549                         return;
550                 }
551                 state.ip = addr;
552
553                 port_colon = strrchr(addr, ':');
554                 if (port_colon == NULL) {
555                         return;
556                 }
557                 state.ip_len = port_colon - addr;
558                 state.msg_ctx = sconn->msg_ctx;
559                 smbXsrv_session_global_traverse(shutdown_other_smbds, &state);
560                 TALLOC_FREE(addr);
561         }
562 }
563
564 /****************************************************************************
565  Reply to a session setup command.
566 ****************************************************************************/
567
568 struct reply_sesssetup_and_X_state {
569         struct smb_request *req;
570         struct auth4_context *auth_context;
571         struct auth_usersupplied_info *user_info;
572         const char *user;
573         const char *domain;
574         DATA_BLOB lm_resp;
575         DATA_BLOB nt_resp;
576         DATA_BLOB plaintext_password;
577 };
578
579 static int reply_sesssetup_and_X_state_destructor(
580                 struct reply_sesssetup_and_X_state *state)
581 {
582         data_blob_clear_free(&state->nt_resp);
583         data_blob_clear_free(&state->lm_resp);
584         data_blob_clear_free(&state->plaintext_password);
585         return 0;
586 }
587
588 void reply_sesssetup_and_X(struct smb_request *req)
589 {
590         struct reply_sesssetup_and_X_state *state = NULL;
591         uint64_t sess_vuid;
592         uint16_t smb_bufsize;
593         char *tmp;
594         fstring sub_user; /* Sanitised username for substituion */
595         const char *native_os;
596         const char *native_lanman;
597         const char *primary_domain;
598         struct auth_session_info *session_info = NULL;
599         uint16_t smb_flag2 = req->flags2;
600         uint16_t action = 0;
601         bool is_authenticated = false;
602         NTTIME now = timeval_to_nttime(&req->request_time);
603         struct smbXsrv_session *session = NULL;
604         NTSTATUS nt_status;
605         struct smbXsrv_connection *xconn = req->xconn;
606         struct smbd_server_connection *sconn = req->sconn;
607         bool doencrypt = xconn->smb1.negprot.encrypted_passwords;
608         bool signing_allowed = false;
609         bool signing_mandatory = smb_signing_is_mandatory(
610                 xconn->smb1.signing_state);
611
612         START_PROFILE(SMBsesssetupX);
613
614         DEBUG(3,("wct=%d flg2=0x%x\n", req->wct, req->flags2));
615
616         state = talloc_zero(req, struct reply_sesssetup_and_X_state);
617         if (state == NULL) {
618                 reply_nterror(req, NT_STATUS_NO_MEMORY);
619                 END_PROFILE(SMBsesssetupX);
620                 return;
621         }
622         state->req = req;
623         talloc_set_destructor(state, reply_sesssetup_and_X_state_destructor);
624
625         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES) {
626                 signing_allowed = true;
627         }
628         if (req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) {
629                 signing_mandatory = true;
630         }
631
632         /*
633          * We can call srv_set_signing_negotiated() each time.
634          * It finds out when it needs to turn into a noop
635          * itself.
636          */
637         srv_set_signing_negotiated(xconn,
638                                    signing_allowed,
639                                    signing_mandatory);
640
641         /* a SPNEGO session setup has 12 command words, whereas a normal
642            NT1 session setup has 13. See the cifs spec. */
643         if (req->wct == 12 &&
644             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
645
646                 if (!xconn->smb1.negprot.spnego) {
647                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
648                                  "at SPNEGO session setup when it was not "
649                                  "negotiated.\n"));
650                         reply_nterror(req, nt_status_squash(
651                                               NT_STATUS_LOGON_FAILURE));
652                         END_PROFILE(SMBsesssetupX);
653                         return;
654                 }
655
656                 if (SVAL(req->vwv+4, 0) == 0) {
657                         setup_new_vc_session(req->sconn);
658                 }
659
660                 reply_sesssetup_and_X_spnego(req);
661                 END_PROFILE(SMBsesssetupX);
662                 return;
663         }
664
665         smb_bufsize = SVAL(req->vwv+2, 0);
666
667         if (get_Protocol() < PROTOCOL_NT1) {
668                 uint16_t passlen1 = SVAL(req->vwv+7, 0);
669
670                 /* Never do NT status codes with protocols before NT1 as we
671                  * don't get client caps. */
672                 remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
673
674                 if ((passlen1 > MAX_PASS_LEN) || (passlen1 > req->buflen)) {
675                         reply_nterror(req, nt_status_squash(
676                                               NT_STATUS_INVALID_PARAMETER));
677                         END_PROFILE(SMBsesssetupX);
678                         return;
679                 }
680
681                 if (doencrypt) {
682                         state->lm_resp = data_blob_talloc(state,
683                                                           req->buf,
684                                                           passlen1);
685                 } else {
686                         state->plaintext_password = data_blob_talloc(state,
687                                                                 req->buf,
688                                                                 passlen1+1);
689                         /* Ensure null termination */
690                         state->plaintext_password.data[passlen1] = 0;
691                 }
692
693                 srvstr_pull_req_talloc(state, req, &tmp,
694                                        req->buf + passlen1, STR_TERMINATE);
695                 state->user = tmp ? tmp : "";
696
697                 state->domain = "";
698
699         } else {
700                 uint16_t passlen1 = SVAL(req->vwv+7, 0);
701                 uint16_t passlen2 = SVAL(req->vwv+8, 0);
702                 enum remote_arch_types ra_type = get_remote_arch();
703                 const uint8_t *p = req->buf;
704                 const uint8_t *save_p = req->buf;
705                 uint16_t byte_count;
706
707                 if (!xconn->smb1.sessions.done_sesssetup) {
708                         global_client_caps = IVAL(req->vwv+11, 0);
709
710                         if (!(global_client_caps & CAP_STATUS32)) {
711                                 remove_from_common_flags2(
712                                                 FLAGS2_32_BIT_ERROR_CODES);
713                         }
714
715                         /* client_caps is used as final determination if
716                          * client is NT or Win95. This is needed to return
717                          * the correct error codes in some circumstances.
718                         */
719
720                         if(ra_type == RA_WINNT || ra_type == RA_WIN2K ||
721                                         ra_type == RA_WIN95) {
722                                 if(!(global_client_caps & (CAP_NT_SMBS|
723                                                         CAP_STATUS32))) {
724                                         set_remote_arch( RA_WIN95);
725                                 }
726                         }
727                 }
728
729                 if (!doencrypt) {
730                         /* both Win95 and WinNT stuff up the password
731                          * lengths for non-encrypting systems. Uggh.
732
733                            if passlen1==24 its a win95 system, and its setting
734                            the password length incorrectly. Luckily it still
735                            works with the default code because Win95 will null
736                            terminate the password anyway
737
738                            if passlen1>0 and passlen2>0 then maybe its a NT box
739                            and its setting passlen2 to some random value which
740                            really stuffs things up. we need to fix that one.  */
741
742                         if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 &&
743                                         passlen2 != 1) {
744                                 passlen2 = 0;
745                         }
746                 }
747
748                 /* check for nasty tricks */
749                 if (passlen1 > MAX_PASS_LEN
750                     || passlen1 > smbreq_bufrem(req, p)) {
751                         reply_nterror(req, nt_status_squash(
752                                               NT_STATUS_INVALID_PARAMETER));
753                         END_PROFILE(SMBsesssetupX);
754                         return;
755                 }
756
757                 if (passlen2 > MAX_PASS_LEN
758                     || passlen2 > smbreq_bufrem(req, p+passlen1)) {
759                         reply_nterror(req, nt_status_squash(
760                                               NT_STATUS_INVALID_PARAMETER));
761                         END_PROFILE(SMBsesssetupX);
762                         return;
763                 }
764
765                 /* Save the lanman2 password and the NT md4 password. */
766
767                 if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) {
768                         doencrypt = False;
769                 }
770
771                 if (doencrypt) {
772                         state->lm_resp = data_blob_talloc(state, p, passlen1);
773                         state->nt_resp = data_blob_talloc(state, p+passlen1, passlen2);
774                 } else {
775                         char *pass = NULL;
776                         bool unic= smb_flag2 & FLAGS2_UNICODE_STRINGS;
777
778                         if (unic && (passlen2 == 0) && passlen1) {
779                                 /* Only a ascii plaintext password was sent. */
780                                 (void)srvstr_pull_talloc(state,
781                                                         req->inbuf,
782                                                         req->flags2,
783                                                         &pass,
784                                                         req->buf,
785                                                         passlen1,
786                                                         STR_TERMINATE|STR_ASCII);
787                         } else {
788                                 (void)srvstr_pull_talloc(state,
789                                                         req->inbuf,
790                                                         req->flags2,
791                                                         &pass,
792                                                         req->buf,
793                                                         unic ? passlen2 : passlen1,
794                                                         STR_TERMINATE);
795                         }
796                         if (!pass) {
797                                 reply_nterror(req, nt_status_squash(
798                                               NT_STATUS_INVALID_PARAMETER));
799                                 END_PROFILE(SMBsesssetupX);
800                                 return;
801                         }
802                         state->plaintext_password = data_blob_talloc(state,
803                                                                 pass,
804                                                                 strlen(pass)+1);
805                 }
806
807                 p += passlen1 + passlen2;
808
809                 p += srvstr_pull_req_talloc(state, req, &tmp, p,
810                                             STR_TERMINATE);
811                 state->user = tmp ? tmp : "";
812
813                 p += srvstr_pull_req_talloc(state, req, &tmp, p,
814                                             STR_TERMINATE);
815                 state->domain = tmp ? tmp : "";
816
817                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
818                                             STR_TERMINATE);
819                 native_os = tmp ? tmp : "";
820
821                 p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
822                                             STR_TERMINATE);
823                 native_lanman = tmp ? tmp : "";
824
825                 /* not documented or decoded by Ethereal but there is one more
826                  * string in the extra bytes which is the same as the
827                  * PrimaryDomain when using extended security.  Windows NT 4
828                  * and 2003 use this string to store the native lanman string.
829                  * Windows 9x does not include a string here at all so we have
830                  * to check if we have any extra bytes left */
831
832                 byte_count = SVAL(req->vwv+13, 0);
833                 if ( PTR_DIFF(p, save_p) < byte_count) {
834                         p += srvstr_pull_req_talloc(talloc_tos(), req, &tmp, p,
835                                                     STR_TERMINATE);
836                         primary_domain = tmp ? tmp : "";
837                 } else {
838                         primary_domain = talloc_strdup(talloc_tos(), "null");
839                 }
840
841                 DEBUG(3,("Domain=[%s]  NativeOS=[%s] NativeLanMan=[%s] "
842                         "PrimaryDomain=[%s]\n",
843                         state->domain, native_os, native_lanman, primary_domain));
844
845                 if ( ra_type == RA_WIN2K ) {
846                         if ( strlen(native_lanman) == 0 )
847                                 ra_lanman_string( primary_domain );
848                         else
849                                 ra_lanman_string( native_lanman );
850                 }
851
852         }
853
854         if (SVAL(req->vwv+4, 0) == 0) {
855                 setup_new_vc_session(req->sconn);
856         }
857
858         DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",
859                  state->domain, state->user, get_remote_machine_name()));
860
861         if (*state->user) {
862                 if (xconn->smb1.negprot.spnego) {
863
864                         /* This has to be here, because this is a perfectly
865                          * valid behaviour for guest logons :-( */
866
867                         DEBUG(0,("reply_sesssetup_and_X:  Rejecting attempt "
868                                 "at 'normal' session setup after "
869                                 "negotiating spnego.\n"));
870                         reply_nterror(req, nt_status_squash(
871                                               NT_STATUS_LOGON_FAILURE));
872                         END_PROFILE(SMBsesssetupX);
873                         return;
874                 }
875                 fstrcpy(sub_user, state->user);
876         } else {
877                 fstrcpy(sub_user, "");
878         }
879
880         sub_set_smb_name(sub_user);
881
882         reload_services(sconn, conn_snum_used, true);
883
884         if (!*state->user) {
885                 DEBUG(3,("Got anonymous request\n"));
886
887                 nt_status = make_auth4_context(state, &state->auth_context);
888                 if (NT_STATUS_IS_OK(nt_status)) {
889                         uint8_t chal[8];
890
891                         state->auth_context->get_ntlm_challenge(
892                                         state->auth_context, chal);
893
894                         if (!make_user_info_guest(state,
895                                                   sconn->remote_address,
896                                                   sconn->local_address,
897                                                   "SMB", &state->user_info)) {
898                                 nt_status =  NT_STATUS_NO_MEMORY;
899                         }
900
901                         if (NT_STATUS_IS_OK(nt_status)) {
902                                 state->user_info->auth_description = "guest";
903                         }
904                 }
905         } else if (doencrypt) {
906                 state->auth_context = xconn->smb1.negprot.auth_context;
907                 if (state->auth_context == NULL) {
908                         DEBUG(0, ("reply_sesssetup_and_X:  Attempted encrypted "
909                                 "session setup without negprot denied!\n"));
910                         reply_nterror(req, nt_status_squash(
911                                               NT_STATUS_LOGON_FAILURE));
912                         END_PROFILE(SMBsesssetupX);
913                         return;
914                 }
915                 nt_status = make_user_info_for_reply_enc(state,
916                                                          &state->user_info,
917                                                          state->user,
918                                                          state->domain,
919                                                          sconn->remote_address,
920                                                          sconn->local_address,
921                                                          "SMB",
922                                                          state->lm_resp,
923                                                          state->nt_resp);
924
925                 if (NT_STATUS_IS_OK(nt_status)) {
926                         state->user_info->auth_description = "bare-NTLM";
927                 }
928         } else {
929                 nt_status = make_auth4_context(state, &state->auth_context);
930                 if (NT_STATUS_IS_OK(nt_status)) {
931                         uint8_t chal[8];
932
933                         state->auth_context->get_ntlm_challenge(
934                                         state->auth_context, chal);
935
936                         if (!make_user_info_for_reply(state,
937                                                       &state->user_info,
938                                                       state->user,
939                                                       state->domain,
940                                                       sconn->remote_address,
941                                                       sconn->local_address,
942                                                       "SMB",
943                                                       chal,
944                                                       state->plaintext_password)) {
945                                 nt_status = NT_STATUS_NO_MEMORY;
946                         }
947
948                         if (NT_STATUS_IS_OK(nt_status)) {
949                                 state->user_info->auth_description = "plaintext";
950                         }
951                 }
952         }
953
954         if (!NT_STATUS_IS_OK(nt_status)) {
955                 reply_nterror(req, nt_status_squash(nt_status));
956                 END_PROFILE(SMBsesssetupX);
957                 return;
958         }
959
960         nt_status = auth_check_password_session_info(state->auth_context,
961                                                      req, state->user_info,
962                                                      &session_info);
963         TALLOC_FREE(state->user_info);
964         if (!NT_STATUS_IS_OK(nt_status)) {
965                 reply_nterror(req, nt_status_squash(nt_status));
966                 END_PROFILE(SMBsesssetupX);
967                 return;
968         }
969
970         /* it's ok - setup a reply */
971         reply_outbuf(req, 3, 0);
972         SSVAL(req->outbuf, smb_vwv0, 0xff); /* andx chain ends */
973         SSVAL(req->outbuf, smb_vwv1, 0);    /* no andx offset */
974
975         if (get_Protocol() >= PROTOCOL_NT1) {
976                 push_signature(&req->outbuf);
977                 /* perhaps grab OS version here?? */
978         }
979
980         if (security_session_user_level(session_info, NULL) == SECURITY_GUEST) {
981                 action |= SMB_SETUP_GUEST;
982         }
983
984         /* register the name and uid as being validated, so further connections
985            to a uid can get through without a password, on the same VC */
986
987         nt_status = smbXsrv_session_create(xconn,
988                                            now, &session);
989         if (!NT_STATUS_IS_OK(nt_status)) {
990                 reply_nterror(req, nt_status_squash(nt_status));
991                 END_PROFILE(SMBsesssetupX);
992                 return;
993         }
994
995         if (session_info->session_key.length > 0) {
996                 uint8_t session_key[16];
997
998                 /*
999                  * Note: the SMB1 signing key is not truncated to 16 byte!
1000                  */
1001                 session->global->signing_key =
1002                         data_blob_dup_talloc(session->global,
1003                                              session_info->session_key);
1004                 if (session->global->signing_key.data == NULL) {
1005                         TALLOC_FREE(session);
1006                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1007                         END_PROFILE(SMBsesssetupX);
1008                         return;
1009                 }
1010
1011                 /*
1012                  * The application key is truncated/padded to 16 bytes
1013                  */
1014                 ZERO_STRUCT(session_key);
1015                 memcpy(session_key, session->global->signing_key.data,
1016                        MIN(session->global->signing_key.length,
1017                            sizeof(session_key)));
1018                 session->global->application_key =
1019                         data_blob_talloc(session->global,
1020                                          session_key,
1021                                          sizeof(session_key));
1022                 ZERO_STRUCT(session_key);
1023                 if (session->global->application_key.data == NULL) {
1024                         TALLOC_FREE(session);
1025                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1026                         END_PROFILE(SMBsesssetupX);
1027                         return;
1028                 }
1029
1030                 /*
1031                  * Place the application key into the session_info
1032                  */
1033                 data_blob_clear_free(&session_info->session_key);
1034                 session_info->session_key = data_blob_dup_talloc(session_info,
1035                                                 session->global->application_key);
1036                 if (session_info->session_key.data == NULL) {
1037                         TALLOC_FREE(session);
1038                         reply_nterror(req, NT_STATUS_NO_MEMORY);
1039                         END_PROFILE(SMBsesssetupX);
1040                         return;
1041                 }
1042         }
1043
1044         session->compat = talloc_zero(session, struct user_struct);
1045         if (session->compat == NULL) {
1046                 TALLOC_FREE(session);
1047                 reply_nterror(req, NT_STATUS_NO_MEMORY);
1048                 END_PROFILE(SMBsesssetupX);
1049                 return;
1050         }
1051         session->compat->session = session;
1052         session->compat->homes_snum = -1;
1053         session->compat->session_info = session_info;
1054         session->compat->session_keystr = NULL;
1055         session->compat->vuid = session->global->session_wire_id;
1056         DLIST_ADD(sconn->users, session->compat);
1057         sconn->num_users++;
1058
1059         if (security_session_user_level(session_info, NULL) >= SECURITY_USER) {
1060                 is_authenticated = true;
1061                 session->compat->homes_snum =
1062                         register_homes_share(session_info->unix_info->unix_name);
1063         }
1064
1065         if (srv_is_signing_negotiated(xconn) &&
1066             is_authenticated &&
1067             session->global->signing_key.length > 0)
1068         {
1069                 /*
1070                  * Try and turn on server signing on the first non-guest
1071                  * sessionsetup.
1072                  */
1073                 srv_set_signing(xconn,
1074                         session->global->signing_key,
1075                         state->nt_resp.data ? state->nt_resp : state->lm_resp);
1076         }
1077
1078         set_current_user_info(session_info->unix_info->sanitized_username,
1079                               session_info->unix_info->unix_name,
1080                               session_info->info->domain_name);
1081
1082         session->status = NT_STATUS_OK;
1083         session->global->auth_session_info = talloc_move(session->global,
1084                                                          &session_info);
1085         session->global->auth_session_info_seqnum += 1;
1086         session->global->channels[0].auth_session_info_seqnum =
1087                 session->global->auth_session_info_seqnum;
1088         session->global->auth_time = now;
1089         session->global->expiration_time = GENSEC_EXPIRE_TIME_INFINITY;
1090
1091         nt_status = smbXsrv_session_update(session);
1092         if (!NT_STATUS_IS_OK(nt_status)) {
1093                 DEBUG(0, ("smb1: Failed to update session for vuid=%llu - %s\n",
1094                           (unsigned long long)session->compat->vuid,
1095                           nt_errstr(nt_status)));
1096                 TALLOC_FREE(session);
1097                 reply_nterror(req, nt_status_squash(nt_status));
1098                 END_PROFILE(SMBsesssetupX);
1099                 return;
1100         }
1101
1102         if (!session_claim(session)) {
1103                 DEBUG(1, ("smb1: Failed to claim session for vuid=%llu\n",
1104                           (unsigned long long)session->compat->vuid));
1105                 TALLOC_FREE(session);
1106                 reply_nterror(req, NT_STATUS_LOGON_FAILURE);
1107                 END_PROFILE(SMBsesssetupX);
1108                 return;
1109         }
1110
1111         /* current_user_info is changed on new vuid */
1112         reload_services(sconn, conn_snum_used, true);
1113
1114         sess_vuid = session->global->session_wire_id;
1115
1116         SSVAL(req->outbuf,smb_vwv2,action);
1117         SSVAL(req->outbuf,smb_uid,sess_vuid);
1118         SSVAL(discard_const_p(char, req->inbuf),smb_uid,sess_vuid);
1119         req->vuid = sess_vuid;
1120
1121         if (!xconn->smb1.sessions.done_sesssetup) {
1122                 if (smb_bufsize < SMB_BUFFER_SIZE_MIN) {
1123                         reply_force_doserror(req, ERRSRV, ERRerror);
1124                         END_PROFILE(SMBsesssetupX);
1125                         return;
1126                 }
1127                 xconn->smb1.sessions.max_send = smb_bufsize;
1128                 xconn->smb1.sessions.done_sesssetup = true;
1129         }
1130
1131         TALLOC_FREE(state);
1132         END_PROFILE(SMBsesssetupX);
1133 }