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