s3: Pass the rhost through smb_pam_accountcheck
[samba.git] / source3 / smbd / smb2_sesssetup.c
1 /*
2    Unix SMB/CIFS implementation.
3    Core SMB2 server
4
5    Copyright (C) Stefan Metzmacher 2009
6    Copyright (C) Jeremy Allison 2010
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "includes.h"
23 #include "smbd/globals.h"
24 #include "../libcli/smb/smb_common.h"
25 #include "../libcli/auth/spnego.h"
26 #include "../libcli/auth/ntlmssp.h"
27 #include "ntlmssp_wrap.h"
28 #include "../librpc/gen_ndr/krb5pac.h"
29 #include "libads/kerberos_proto.h"
30
31 static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req,
32                                         uint64_t in_session_id,
33                                         uint8_t in_security_mode,
34                                         DATA_BLOB in_security_buffer,
35                                         uint16_t *out_session_flags,
36                                         DATA_BLOB *out_security_buffer,
37                                         uint64_t *out_session_id);
38
39 NTSTATUS smbd_smb2_request_process_sesssetup(struct smbd_smb2_request *smb2req)
40 {
41         const uint8_t *inhdr;
42         const uint8_t *inbody;
43         int i = smb2req->current_idx;
44         uint8_t *outhdr;
45         DATA_BLOB outbody;
46         DATA_BLOB outdyn;
47         size_t expected_body_size = 0x19;
48         size_t body_size;
49         uint64_t in_session_id;
50         uint8_t in_security_mode;
51         uint16_t in_security_offset;
52         uint16_t in_security_length;
53         DATA_BLOB in_security_buffer;
54         uint16_t out_session_flags;
55         uint64_t out_session_id;
56         uint16_t out_security_offset;
57         DATA_BLOB out_security_buffer;
58         NTSTATUS status;
59
60         inhdr = (const uint8_t *)smb2req->in.vector[i+0].iov_base;
61
62         if (smb2req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
63                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
64         }
65
66         inbody = (const uint8_t *)smb2req->in.vector[i+1].iov_base;
67
68         body_size = SVAL(inbody, 0x00);
69         if (body_size != expected_body_size) {
70                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
71         }
72
73         in_security_offset = SVAL(inbody, 0x0C);
74         in_security_length = SVAL(inbody, 0x0E);
75
76         if (in_security_offset != (SMB2_HDR_BODY + (body_size & 0xFFFFFFFE))) {
77                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
78         }
79
80         if (in_security_length > smb2req->in.vector[i+2].iov_len) {
81                 return smbd_smb2_request_error(smb2req, NT_STATUS_INVALID_PARAMETER);
82         }
83
84         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
85         in_security_mode = CVAL(inbody, 0x03);
86         in_security_buffer.data = (uint8_t *)smb2req->in.vector[i+2].iov_base;
87         in_security_buffer.length = in_security_length;
88
89         status = smbd_smb2_session_setup(smb2req,
90                                          in_session_id,
91                                          in_security_mode,
92                                          in_security_buffer,
93                                          &out_session_flags,
94                                          &out_security_buffer,
95                                          &out_session_id);
96         if (!NT_STATUS_IS_OK(status) &&
97             !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
98                 status = nt_status_squash(status);
99                 return smbd_smb2_request_error(smb2req, status);
100         }
101
102         out_security_offset = SMB2_HDR_BODY + 0x08;
103
104         outhdr = (uint8_t *)smb2req->out.vector[i].iov_base;
105
106         outbody = data_blob_talloc(smb2req->out.vector, NULL, 0x08);
107         if (outbody.data == NULL) {
108                 return smbd_smb2_request_error(smb2req, NT_STATUS_NO_MEMORY);
109         }
110
111         SBVAL(outhdr, SMB2_HDR_SESSION_ID, out_session_id);
112
113         SSVAL(outbody.data, 0x00, 0x08 + 1);    /* struct size */
114         SSVAL(outbody.data, 0x02,
115               out_session_flags);               /* session flags */
116         SSVAL(outbody.data, 0x04,
117               out_security_offset);             /* security buffer offset */
118         SSVAL(outbody.data, 0x06,
119               out_security_buffer.length);      /* security buffer length */
120
121         outdyn = out_security_buffer;
122
123         return smbd_smb2_request_done_ex(smb2req, status, outbody, &outdyn,
124                                          __location__);
125 }
126
127 static int smbd_smb2_session_destructor(struct smbd_smb2_session *session)
128 {
129         if (session->sconn == NULL) {
130                 return 0;
131         }
132
133         /* first free all tcons */
134         while (session->tcons.list) {
135                 talloc_free(session->tcons.list);
136         }
137
138         idr_remove(session->sconn->smb2.sessions.idtree, session->vuid);
139         DLIST_REMOVE(session->sconn->smb2.sessions.list, session);
140         invalidate_vuid(session->sconn, session->vuid);
141
142         session->vuid = 0;
143         session->status = NT_STATUS_USER_SESSION_DELETED;
144         session->sconn = NULL;
145
146         return 0;
147 }
148
149 static NTSTATUS setup_ntlmssp_server_info(struct smbd_smb2_session *session,
150                                 NTSTATUS status)
151 {
152         if (NT_STATUS_IS_OK(status)) {
153                 status = auth_ntlmssp_steal_server_info(session,
154                                 session->auth_ntlmssp_state,
155                                 &session->server_info);
156         } else {
157                 /* Note that this server_info won't have a session
158                  * key.  But for map to guest, that's exactly the right
159                  * thing - we can't reasonably guess the key the
160                  * client wants, as the password was wrong */
161                 status = do_map_to_guest(status,
162                         &session->server_info,
163                         auth_ntlmssp_get_username(session->auth_ntlmssp_state),
164                         auth_ntlmssp_get_domain(session->auth_ntlmssp_state));
165         }
166         return status;
167 }
168
169 #ifdef HAVE_KRB5
170 static NTSTATUS smbd_smb2_session_setup_krb5(struct smbd_smb2_session *session,
171                                         struct smbd_smb2_request *smb2req,
172                                         uint8_t in_security_mode,
173                                         const DATA_BLOB *secblob,
174                                         const char *mechOID,
175                                         uint16_t *out_session_flags,
176                                         DATA_BLOB *out_security_buffer,
177                                         uint64_t *out_session_id)
178 {
179         DATA_BLOB ap_rep = data_blob_null;
180         DATA_BLOB ap_rep_wrapped = data_blob_null;
181         DATA_BLOB ticket = data_blob_null;
182         DATA_BLOB session_key = data_blob_null;
183         DATA_BLOB secblob_out = data_blob_null;
184         uint8 tok_id[2];
185         struct PAC_LOGON_INFO *logon_info = NULL;
186         char *client = NULL;
187         char *p = NULL;
188         char *domain = NULL;
189         struct passwd *pw = NULL;
190         NTSTATUS status;
191         fstring user;
192         fstring real_username;
193         fstring tmp;
194         bool username_was_mapped = false;
195         bool map_domainuser_to_guest = false;
196
197         if (!spnego_parse_krb5_wrap(talloc_tos(), *secblob, &ticket, tok_id)) {
198                 status = NT_STATUS_LOGON_FAILURE;
199                 goto fail;
200         }
201
202         status = ads_verify_ticket(smb2req, lp_realm(), 0, &ticket,
203                                 &client, &logon_info, &ap_rep,
204                                 &session_key, true);
205
206         if (!NT_STATUS_IS_OK(status)) {
207                 DEBUG(1,("smb2: Failed to verify incoming ticket with error %s!\n",
208                         nt_errstr(status)));
209                 if (!NT_STATUS_EQUAL(status, NT_STATUS_TIME_DIFFERENCE_AT_DC)) {
210                         status = NT_STATUS_LOGON_FAILURE;
211                 }
212                 goto fail;
213         }
214
215         DEBUG(3,("smb2: Ticket name is [%s]\n", client));
216
217         p = strchr_m(client, '@');
218         if (!p) {
219                 DEBUG(3,("smb2: %s Doesn't look like a valid principal\n",
220                         client));
221                 status = NT_STATUS_LOGON_FAILURE;
222                 goto fail;
223         }
224
225         *p = 0;
226
227         /* save the PAC data if we have it */
228
229         if (logon_info) {
230                 netsamlogon_cache_store(client, &logon_info->info3);
231         }
232
233         if (!strequal(p+1, lp_realm())) {
234                 DEBUG(3,("smb2: Ticket for foreign realm %s@%s\n", client, p+1));
235                 if (!lp_allow_trusted_domains()) {
236                         status = NT_STATUS_LOGON_FAILURE;
237                         goto fail;
238                 }
239         }
240
241         /* this gives a fully qualified user name (ie. with full realm).
242            that leads to very long usernames, but what else can we do? */
243
244         domain = p+1;
245
246         if (logon_info && logon_info->info3.base.domain.string) {
247                 domain = talloc_strdup(talloc_tos(),
248                                         logon_info->info3.base.domain.string);
249                 if (!domain) {
250                         status = NT_STATUS_NO_MEMORY;
251                         goto fail;
252                 }
253                 DEBUG(10, ("smb2: Mapped to [%s] (using PAC)\n", domain));
254         } else {
255
256                 /* If we have winbind running, we can (and must) shorten the
257                    username by using the short netbios name. Otherwise we will
258                    have inconsistent user names. With Kerberos, we get the
259                    fully qualified realm, with ntlmssp we get the short
260                    name. And even w2k3 does use ntlmssp if you for example
261                    connect to an ip address. */
262
263                 wbcErr wbc_status;
264                 struct wbcDomainInfo *info = NULL;
265
266                 DEBUG(10, ("smb2: Mapping [%s] to short name\n", domain));
267
268                 wbc_status = wbcDomainInfo(domain, &info);
269
270                 if (WBC_ERROR_IS_OK(wbc_status)) {
271                         domain = talloc_strdup(talloc_tos(), info->short_name);
272
273                         wbcFreeMemory(info);
274                         if (!domain) {
275                                 status = NT_STATUS_NO_MEMORY;
276                                 goto fail;
277                         }
278                         DEBUG(10, ("smb2: Mapped to [%s] (using Winbind)\n", domain));
279                 } else {
280                         DEBUG(3, ("smb2: Could not find short name: %s\n",
281                                 wbcErrorString(wbc_status)));
282                 }
283         }
284
285         /* We have to use fstring for this - map_username requires it. */
286         fstr_sprintf(user, "%s%c%s", domain, *lp_winbind_separator(), client);
287
288         /* lookup the passwd struct, create a new user if necessary */
289
290         username_was_mapped = map_username(user);
291
292         pw = smb_getpwnam(talloc_tos(), user, real_username, true );
293         if (pw) {
294                 /* if a real user check pam account restrictions */
295                 /* only really perfomed if "obey pam restriction" is true */
296                 /* do this before an eventual mapping to guest occurs */
297                 status = smb_pam_accountcheck(
298                         pw->pw_name, smb2req->sconn->client_id.name);
299                 if (!NT_STATUS_IS_OK(status)) {
300                         DEBUG(1,("smb2: PAM account restriction "
301                                 "prevents user login\n"));
302                         goto fail;
303                 }
304         }
305
306         if (!pw) {
307
308                 /* this was originally the behavior of Samba 2.2, if a user
309                    did not have a local uid but has been authenticated, then
310                    map them to a guest account */
311
312                 if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){
313                         map_domainuser_to_guest = true;
314                         fstrcpy(user,lp_guestaccount());
315                         pw = smb_getpwnam(talloc_tos(), user, real_username, true );
316                 }
317
318                 /* extra sanity check that the guest account is valid */
319
320                 if (!pw) {
321                         DEBUG(1,("smb2: Username %s is invalid on this system\n",
322                                 user));
323                         status = NT_STATUS_LOGON_FAILURE;
324                         goto fail;
325                 }
326         }
327
328         /* setup the string used by %U */
329
330         sub_set_smb_name(real_username);
331         reload_services(smb2req->sconn->msg_ctx, smb2req->sconn->sock, true);
332
333         if (map_domainuser_to_guest) {
334                 make_server_info_guest(session, &session->server_info);
335         } else if (logon_info) {
336                 /* pass the unmapped username here since map_username()
337                    will be called again from inside make_server_info_info3() */
338
339                 status = make_server_info_info3(session,
340                                                 client,
341                                                 domain,
342                                                 &session->server_info,
343                                                 &logon_info->info3);
344                 if (!NT_STATUS_IS_OK(status) ) {
345                         DEBUG(1,("smb2: make_server_info_info3 failed: %s!\n",
346                                 nt_errstr(status)));
347                         goto fail;
348                 }
349
350         } else {
351                 /*
352                  * We didn't get a PAC, we have to make up the user
353                  * ourselves. Try to ask the pdb backend to provide
354                  * SID consistency with ntlmssp session setup
355                  */
356                 struct samu *sampass;
357                 /* The stupid make_server_info_XX functions here
358                    don't take a talloc context. */
359                 struct auth_serversupplied_info *tmp_server_info = NULL;
360
361                 sampass = samu_new(talloc_tos());
362                 if (sampass == NULL) {
363                         status = NT_STATUS_NO_MEMORY;
364                         goto fail;
365                 }
366
367                 if (pdb_getsampwnam(sampass, real_username)) {
368                         DEBUG(10, ("smb2: found user %s in passdb, calling "
369                                 "make_server_info_sam\n", real_username));
370                         status = make_server_info_sam(&tmp_server_info, sampass);
371                         TALLOC_FREE(sampass);
372                 } else {
373                         /*
374                          * User not in passdb, make it up artificially
375                          */
376                         TALLOC_FREE(sampass);
377                         DEBUG(10, ("smb2: didn't find user %s in passdb, calling "
378                                 "make_server_info_pw\n", real_username));
379                         status = make_server_info_pw(&tmp_server_info,
380                                         real_username,
381                                         pw);
382                 }
383
384                 if (!NT_STATUS_IS_OK(status)) {
385                         DEBUG(1,("smb2: make_server_info_[sam|pw] failed: %s!\n",
386                                 nt_errstr(status)));
387                         goto fail;
388                 }
389
390                 /* Steal tmp_server_info into the session->server_info
391                    pointer. */
392                 session->server_info = talloc_move(session, &tmp_server_info);
393
394                 /* make_server_info_pw does not set the domain. Without this
395                  * we end up with the local netbios name in substitutions for
396                  * %D. */
397
398                 if (session->server_info->info3 != NULL) {
399                         session->server_info->info3->base.domain.string =
400                                 talloc_strdup(session->server_info->info3, domain);
401                 }
402
403         }
404
405         session->server_info->nss_token |= username_was_mapped;
406
407         /* we need to build the token for the user. make_server_info_guest()
408            already does this */
409
410         if (!session->server_info->ptok ) {
411                 status = create_local_token(session->server_info);
412                 if (!NT_STATUS_IS_OK(status)) {
413                         DEBUG(10,("smb2: failed to create local token: %s\n",
414                                 nt_errstr(status)));
415                         goto fail;
416                 }
417         }
418
419         if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
420              lp_server_signing() == Required) {
421                 session->do_signing = true;
422         }
423
424         if (session->server_info->guest) {
425                 /* we map anonymous to guest internally */
426                 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
427                 *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
428                 /* force no signing */
429                 session->do_signing = false;
430         }
431
432         data_blob_free(&session->server_info->user_session_key);
433         session->server_info->user_session_key =
434                         data_blob_talloc(
435                                 session->server_info,
436                                 session_key.data,
437                                 session_key.length);
438         if (session_key.length > 0) {
439                 if (session->server_info->user_session_key.data == NULL) {
440                         status = NT_STATUS_NO_MEMORY;
441                         goto fail;
442                 }
443         }
444         session->session_key = session->server_info->user_session_key;
445
446         session->compat_vuser = talloc_zero(session, user_struct);
447         if (session->compat_vuser == NULL) {
448                 status = NT_STATUS_NO_MEMORY;
449                 goto fail;
450         }
451         session->compat_vuser->auth_ntlmssp_state = NULL;
452         session->compat_vuser->homes_snum = -1;
453         session->compat_vuser->server_info = session->server_info;
454         session->compat_vuser->session_keystr = NULL;
455         session->compat_vuser->vuid = session->vuid;
456         DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser);
457
458         /* This is a potentially untrusted username */
459         alpha_strcpy(tmp,
460                 client,
461                 ". _-$",
462                 sizeof(tmp));
463         session->server_info->sanitized_username = talloc_strdup(
464                         session->server_info, tmp);
465
466         if (!session->server_info->guest) {
467                 session->compat_vuser->homes_snum =
468                         register_homes_share(session->server_info->unix_name);
469         }
470
471         if (!session_claim(session->sconn, session->compat_vuser)) {
472                 DEBUG(1, ("smb2: Failed to claim session "
473                         "for vuid=%d\n",
474                         session->compat_vuser->vuid));
475                 goto fail;
476         }
477
478         session->status = NT_STATUS_OK;
479
480         /*
481          * we attach the session to the request
482          * so that the response can be signed
483          */
484         smb2req->session = session;
485         if (session->do_signing) {
486                 smb2req->do_signing = true;
487         }
488
489         global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
490         status = NT_STATUS_OK;
491
492         /* wrap that up in a nice GSS-API wrapping */
493         ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep,
494                                 TOK_ID_KRB_AP_REP);
495
496         secblob_out = spnego_gen_auth_response(
497                                         talloc_tos(),
498                                         &ap_rep_wrapped,
499                                         status,
500                                         mechOID);
501
502         *out_security_buffer = data_blob_talloc(smb2req,
503                                                 secblob_out.data,
504                                                 secblob_out.length);
505         if (secblob_out.data && out_security_buffer->data == NULL) {
506                 status = NT_STATUS_NO_MEMORY;
507                 goto fail;
508         }
509
510         data_blob_free(&ap_rep);
511         data_blob_free(&ap_rep_wrapped);
512         data_blob_free(&ticket);
513         data_blob_free(&session_key);
514         data_blob_free(&secblob_out);
515
516         *out_session_id = session->vuid;
517
518         return NT_STATUS_OK;
519
520   fail:
521
522         data_blob_free(&ap_rep);
523         data_blob_free(&ap_rep_wrapped);
524         data_blob_free(&ticket);
525         data_blob_free(&session_key);
526         data_blob_free(&secblob_out);
527
528         ap_rep_wrapped = data_blob_null;
529         secblob_out = spnego_gen_auth_response(
530                                         talloc_tos(),
531                                         &ap_rep_wrapped,
532                                         status,
533                                         mechOID);
534
535         *out_security_buffer = data_blob_talloc(smb2req,
536                                                 secblob_out.data,
537                                                 secblob_out.length);
538         data_blob_free(&secblob_out);
539         return status;
540 }
541 #endif
542
543 static NTSTATUS smbd_smb2_spnego_negotiate(struct smbd_smb2_session *session,
544                                         struct smbd_smb2_request *smb2req,
545                                         uint8_t in_security_mode,
546                                         DATA_BLOB in_security_buffer,
547                                         uint16_t *out_session_flags,
548                                         DATA_BLOB *out_security_buffer,
549                                         uint64_t *out_session_id)
550 {
551         DATA_BLOB secblob_in = data_blob_null;
552         DATA_BLOB chal_out = data_blob_null;
553         char *kerb_mech = NULL;
554         NTSTATUS status;
555
556         /* Ensure we have no old NTLM state around. */
557         TALLOC_FREE(session->auth_ntlmssp_state);
558
559         status = parse_spnego_mechanisms(talloc_tos(), in_security_buffer,
560                         &secblob_in, &kerb_mech);
561         if (!NT_STATUS_IS_OK(status)) {
562                 goto out;
563         }
564
565 #ifdef HAVE_KRB5
566         if (kerb_mech && ((lp_security()==SEC_ADS) ||
567                                 USE_KERBEROS_KEYTAB) ) {
568                 status = smbd_smb2_session_setup_krb5(session,
569                                 smb2req,
570                                 in_security_mode,
571                                 &secblob_in,
572                                 kerb_mech,
573                                 out_session_flags,
574                                 out_security_buffer,
575                                 out_session_id);
576
577                 goto out;
578         }
579 #endif
580
581         if (kerb_mech) {
582                 /* The mechtoken is a krb5 ticket, but
583                  * we need to fall back to NTLM. */
584
585                 DEBUG(3,("smb2: Got krb5 ticket in SPNEGO "
586                         "but set to downgrade to NTLMSSP\n"));
587
588                 status = NT_STATUS_MORE_PROCESSING_REQUIRED;
589         } else {
590                 /* Fall back to NTLMSSP. */
591                 status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
592                 if (!NT_STATUS_IS_OK(status)) {
593                         goto out;
594                 }
595
596                 status = auth_ntlmssp_update(session->auth_ntlmssp_state,
597                                              secblob_in,
598                                              &chal_out);
599         }
600
601         if (!NT_STATUS_IS_OK(status) &&
602                         !NT_STATUS_EQUAL(status,
603                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
604                 goto out;
605         }
606
607         *out_security_buffer = spnego_gen_auth_response(smb2req,
608                                                 &chal_out,
609                                                 status,
610                                                 OID_NTLMSSP);
611         if (out_security_buffer->data == NULL) {
612                 status = NT_STATUS_NO_MEMORY;
613                 goto out;
614         }
615         *out_session_id = session->vuid;
616
617   out:
618
619         data_blob_free(&secblob_in);
620         data_blob_free(&chal_out);
621         TALLOC_FREE(kerb_mech);
622         if (!NT_STATUS_IS_OK(status) &&
623                         !NT_STATUS_EQUAL(status,
624                                 NT_STATUS_MORE_PROCESSING_REQUIRED)) {
625                 TALLOC_FREE(session->auth_ntlmssp_state);
626                 TALLOC_FREE(session);
627         }
628         return status;
629 }
630
631 static NTSTATUS smbd_smb2_common_ntlmssp_auth_return(struct smbd_smb2_session *session,
632                                         struct smbd_smb2_request *smb2req,
633                                         uint8_t in_security_mode,
634                                         DATA_BLOB in_security_buffer,
635                                         uint16_t *out_session_flags,
636                                         uint64_t *out_session_id)
637 {
638         fstring tmp;
639
640         if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) ||
641             lp_server_signing() == Required) {
642                 session->do_signing = true;
643         }
644
645         if (session->server_info->guest) {
646                 /* we map anonymous to guest internally */
647                 *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST;
648                 *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL;
649                 /* force no signing */
650                 session->do_signing = false;
651         }
652
653         session->session_key = session->server_info->user_session_key;
654
655         session->compat_vuser = talloc_zero(session, user_struct);
656         if (session->compat_vuser == NULL) {
657                 TALLOC_FREE(session->auth_ntlmssp_state);
658                 TALLOC_FREE(session);
659                 return NT_STATUS_NO_MEMORY;
660         }
661         session->compat_vuser->auth_ntlmssp_state = session->auth_ntlmssp_state;
662         session->compat_vuser->homes_snum = -1;
663         session->compat_vuser->server_info = session->server_info;
664         session->compat_vuser->session_keystr = NULL;
665         session->compat_vuser->vuid = session->vuid;
666         DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser);
667
668         /* This is a potentially untrusted username */
669         alpha_strcpy(tmp,
670                      auth_ntlmssp_get_username(session->auth_ntlmssp_state),
671                      ". _-$",
672                      sizeof(tmp));
673         session->server_info->sanitized_username = talloc_strdup(
674                 session->server_info, tmp);
675
676         if (!session->compat_vuser->server_info->guest) {
677                 session->compat_vuser->homes_snum =
678                         register_homes_share(session->server_info->unix_name);
679         }
680
681         if (!session_claim(session->sconn, session->compat_vuser)) {
682                 DEBUG(1, ("smb2: Failed to claim session "
683                         "for vuid=%d\n",
684                         session->compat_vuser->vuid));
685                 TALLOC_FREE(session->auth_ntlmssp_state);
686                 TALLOC_FREE(session);
687                 return NT_STATUS_LOGON_FAILURE;
688         }
689
690
691         session->status = NT_STATUS_OK;
692
693         /*
694          * we attach the session to the request
695          * so that the response can be signed
696          */
697         smb2req->session = session;
698         if (session->do_signing) {
699                 smb2req->do_signing = true;
700         }
701
702         global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32);
703
704         *out_session_id = session->vuid;
705
706         return NT_STATUS_OK;
707 }
708
709 static NTSTATUS smbd_smb2_spnego_auth(struct smbd_smb2_session *session,
710                                         struct smbd_smb2_request *smb2req,
711                                         uint8_t in_security_mode,
712                                         DATA_BLOB in_security_buffer,
713                                         uint16_t *out_session_flags,
714                                         DATA_BLOB *out_security_buffer,
715                                         uint64_t *out_session_id)
716 {
717         DATA_BLOB auth = data_blob_null;
718         DATA_BLOB auth_out = data_blob_null;
719         NTSTATUS status;
720
721         if (!spnego_parse_auth(talloc_tos(), in_security_buffer, &auth)) {
722                 TALLOC_FREE(session);
723                 return NT_STATUS_LOGON_FAILURE;
724         }
725
726         if (auth.data[0] == ASN1_APPLICATION(0)) {
727                 /* Might be a second negTokenTarg packet */
728                 DATA_BLOB secblob_in = data_blob_null;
729                 char *kerb_mech = NULL;
730
731                 status = parse_spnego_mechanisms(talloc_tos(),
732                                 in_security_buffer,
733                                 &secblob_in, &kerb_mech);
734                 if (!NT_STATUS_IS_OK(status)) {
735                         TALLOC_FREE(session);
736                         return status;
737                 }
738
739 #ifdef HAVE_KRB5
740                 if (kerb_mech && ((lp_security()==SEC_ADS) ||
741                                         USE_KERBEROS_KEYTAB) ) {
742                         status = smbd_smb2_session_setup_krb5(session,
743                                         smb2req,
744                                         in_security_mode,
745                                         &secblob_in,
746                                         kerb_mech,
747                                         out_session_flags,
748                                         out_security_buffer,
749                                         out_session_id);
750
751                         data_blob_free(&secblob_in);
752                         TALLOC_FREE(kerb_mech);
753                         if (!NT_STATUS_IS_OK(status)) {
754                                 TALLOC_FREE(session);
755                         }
756                         return status;
757                 }
758 #endif
759
760                 /* Can't blunder into NTLMSSP auth if we have
761                  * a krb5 ticket. */
762
763                 if (kerb_mech) {
764                         DEBUG(3,("smb2: network "
765                                 "misconfiguration, client sent us a "
766                                 "krb5 ticket and kerberos security "
767                                 "not enabled\n"));
768                         TALLOC_FREE(session);
769                         data_blob_free(&secblob_in);
770                         TALLOC_FREE(kerb_mech);
771                         return NT_STATUS_LOGON_FAILURE;
772                 }
773
774                 data_blob_free(&secblob_in);
775         }
776
777         if (session->auth_ntlmssp_state == NULL) {
778                 status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
779                 if (!NT_STATUS_IS_OK(status)) {
780                         data_blob_free(&auth);
781                         TALLOC_FREE(session);
782                         return status;
783                 }
784         }
785
786         status = auth_ntlmssp_update(session->auth_ntlmssp_state,
787                                      auth,
788                                      &auth_out);
789         /* We need to call setup_ntlmssp_server_info() if status==NT_STATUS_OK,
790            or if status is anything except NT_STATUS_MORE_PROCESSING_REQUIRED,
791            as this can trigger map to guest. */
792         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
793                 status = setup_ntlmssp_server_info(session, status);
794         }
795
796         if (!NT_STATUS_IS_OK(status) &&
797                         !NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
798                 TALLOC_FREE(session->auth_ntlmssp_state);
799                 data_blob_free(&auth);
800                 TALLOC_FREE(session);
801                 return status;
802         }
803
804         data_blob_free(&auth);
805
806         *out_security_buffer = spnego_gen_auth_response(smb2req,
807                                 &auth_out, status, NULL);
808
809         if (out_security_buffer->data == NULL) {
810                 TALLOC_FREE(session->auth_ntlmssp_state);
811                 TALLOC_FREE(session);
812                 return NT_STATUS_NO_MEMORY;
813         }
814
815         *out_session_id = session->vuid;
816
817         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
818                 return NT_STATUS_MORE_PROCESSING_REQUIRED;
819         }
820
821         /* We're done - claim the session. */
822         return smbd_smb2_common_ntlmssp_auth_return(session,
823                                                 smb2req,
824                                                 in_security_mode,
825                                                 in_security_buffer,
826                                                 out_session_flags,
827                                                 out_session_id);
828 }
829
830 static NTSTATUS smbd_smb2_raw_ntlmssp_auth(struct smbd_smb2_session *session,
831                                         struct smbd_smb2_request *smb2req,
832                                         uint8_t in_security_mode,
833                                         DATA_BLOB in_security_buffer,
834                                         uint16_t *out_session_flags,
835                                         DATA_BLOB *out_security_buffer,
836                                         uint64_t *out_session_id)
837 {
838         NTSTATUS status;
839         DATA_BLOB secblob_out = data_blob_null;
840
841         if (session->auth_ntlmssp_state == NULL) {
842                 status = auth_ntlmssp_start(&session->auth_ntlmssp_state);
843                 if (!NT_STATUS_IS_OK(status)) {
844                         TALLOC_FREE(session);
845                         return status;
846                 }
847         }
848
849         /* RAW NTLMSSP */
850         status = auth_ntlmssp_update(session->auth_ntlmssp_state,
851                                      in_security_buffer,
852                                      &secblob_out);
853
854         if (NT_STATUS_IS_OK(status) ||
855                         NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
856                 *out_security_buffer = data_blob_talloc(smb2req,
857                                                 secblob_out.data,
858                                                 secblob_out.length);
859                 if (secblob_out.data && out_security_buffer->data == NULL) {
860                         TALLOC_FREE(session->auth_ntlmssp_state);
861                         TALLOC_FREE(session);
862                         return NT_STATUS_NO_MEMORY;
863                 }
864         }
865
866         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
867                 *out_session_id = session->vuid;
868                 return status;
869         }
870
871         status = setup_ntlmssp_server_info(session, status);
872
873         if (!NT_STATUS_IS_OK(status)) {
874                 TALLOC_FREE(session->auth_ntlmssp_state);
875                 TALLOC_FREE(session);
876                 return status;
877         }
878         *out_session_id = session->vuid;
879
880         return smbd_smb2_common_ntlmssp_auth_return(session,
881                                                 smb2req,
882                                                 in_security_mode,
883                                                 in_security_buffer,
884                                                 out_session_flags,
885                                                 out_session_id);
886 }
887
888 static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req,
889                                         uint64_t in_session_id,
890                                         uint8_t in_security_mode,
891                                         DATA_BLOB in_security_buffer,
892                                         uint16_t *out_session_flags,
893                                         DATA_BLOB *out_security_buffer,
894                                         uint64_t *out_session_id)
895 {
896         struct smbd_smb2_session *session;
897
898         *out_session_flags = 0;
899         *out_session_id = 0;
900
901         if (in_session_id == 0) {
902                 int id;
903
904                 /* create a new session */
905                 session = talloc_zero(smb2req->sconn, struct smbd_smb2_session);
906                 if (session == NULL) {
907                         return NT_STATUS_NO_MEMORY;
908                 }
909                 session->status = NT_STATUS_MORE_PROCESSING_REQUIRED;
910                 id = idr_get_new_random(smb2req->sconn->smb2.sessions.idtree,
911                                         session,
912                                         smb2req->sconn->smb2.sessions.limit);
913                 if (id == -1) {
914                         return NT_STATUS_INSUFFICIENT_RESOURCES;
915                 }
916                 session->vuid = id;
917
918                 session->tcons.idtree = idr_init(session);
919                 if (session->tcons.idtree == NULL) {
920                         return NT_STATUS_NO_MEMORY;
921                 }
922                 session->tcons.limit = 0x0000FFFE;
923                 session->tcons.list = NULL;
924
925                 DLIST_ADD_END(smb2req->sconn->smb2.sessions.list, session,
926                               struct smbd_smb2_session *);
927                 session->sconn = smb2req->sconn;
928                 talloc_set_destructor(session, smbd_smb2_session_destructor);
929         } else {
930                 void *p;
931
932                 /* lookup an existing session */
933                 p = idr_find(smb2req->sconn->smb2.sessions.idtree, in_session_id);
934                 if (p == NULL) {
935                         return NT_STATUS_USER_SESSION_DELETED;
936                 }
937                 session = talloc_get_type_abort(p, struct smbd_smb2_session);
938         }
939
940         if (NT_STATUS_IS_OK(session->status)) {
941                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
942         }
943
944         if (in_security_buffer.data[0] == ASN1_APPLICATION(0)) {
945                 return smbd_smb2_spnego_negotiate(session,
946                                                 smb2req,
947                                                 in_security_mode,
948                                                 in_security_buffer,
949                                                 out_session_flags,
950                                                 out_security_buffer,
951                                                 out_session_id);
952         } else if (in_security_buffer.data[0] == ASN1_CONTEXT(1)) {
953                 return smbd_smb2_spnego_auth(session,
954                                                 smb2req,
955                                                 in_security_mode,
956                                                 in_security_buffer,
957                                                 out_session_flags,
958                                                 out_security_buffer,
959                                                 out_session_id);
960         } else if (strncmp((char *)(in_security_buffer.data), "NTLMSSP", 7) == 0) {
961                 return smbd_smb2_raw_ntlmssp_auth(session,
962                                                 smb2req,
963                                                 in_security_mode,
964                                                 in_security_buffer,
965                                                 out_session_flags,
966                                                 out_security_buffer,
967                                                 out_session_id);
968         }
969
970         /* Unknown packet type. */
971         DEBUG(1,("Unknown packet type %u in smb2 sessionsetup\n",
972                 (unsigned int)in_security_buffer.data[0] ));
973         TALLOC_FREE(session->auth_ntlmssp_state);
974         TALLOC_FREE(session);
975         return NT_STATUS_LOGON_FAILURE;
976 }
977
978 NTSTATUS smbd_smb2_request_check_session(struct smbd_smb2_request *req)
979 {
980         const uint8_t *inhdr;
981         const uint8_t *outhdr;
982         int i = req->current_idx;
983         uint64_t in_session_id;
984         void *p;
985         struct smbd_smb2_session *session;
986         bool chained_fixup = false;
987
988         inhdr = (const uint8_t *)req->in.vector[i+0].iov_base;
989
990         in_session_id = BVAL(inhdr, SMB2_HDR_SESSION_ID);
991
992         if (in_session_id == (0xFFFFFFFFFFFFFFFFLL)) {
993                 if (req->async) {
994                         /*
995                          * async request - fill in session_id from
996                          * already setup request out.vector[].iov_base.
997                          */
998                         outhdr = (const uint8_t *)req->out.vector[i].iov_base;
999                         in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1000                 } else if (i > 2) {
1001                         /*
1002                          * Chained request - fill in session_id from
1003                          * the previous request out.vector[].iov_base.
1004                          */
1005                         outhdr = (const uint8_t *)req->out.vector[i-3].iov_base;
1006                         in_session_id = BVAL(outhdr, SMB2_HDR_SESSION_ID);
1007                         chained_fixup = true;
1008                 }
1009         }
1010
1011         /* lookup an existing session */
1012         p = idr_find(req->sconn->smb2.sessions.idtree, in_session_id);
1013         if (p == NULL) {
1014                 return NT_STATUS_USER_SESSION_DELETED;
1015         }
1016         session = talloc_get_type_abort(p, struct smbd_smb2_session);
1017
1018         if (!NT_STATUS_IS_OK(session->status)) {
1019                 return NT_STATUS_ACCESS_DENIED;
1020         }
1021
1022         set_current_user_info(session->server_info->sanitized_username,
1023                               session->server_info->unix_name,
1024                               session->server_info->info3->base.domain.string);
1025
1026         req->session = session;
1027
1028         if (chained_fixup) {
1029                 /* Fix up our own outhdr. */
1030                 outhdr = (const uint8_t *)req->out.vector[i].iov_base;
1031                 SBVAL(outhdr, SMB2_HDR_SESSION_ID, in_session_id);
1032         }
1033         return NT_STATUS_OK;
1034 }
1035
1036 NTSTATUS smbd_smb2_request_process_logoff(struct smbd_smb2_request *req)
1037 {
1038         const uint8_t *inbody;
1039         int i = req->current_idx;
1040         DATA_BLOB outbody;
1041         size_t expected_body_size = 0x04;
1042         size_t body_size;
1043
1044         if (req->in.vector[i+1].iov_len != (expected_body_size & 0xFFFFFFFE)) {
1045                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1046         }
1047
1048         inbody = (const uint8_t *)req->in.vector[i+1].iov_base;
1049
1050         body_size = SVAL(inbody, 0x00);
1051         if (body_size != expected_body_size) {
1052                 return smbd_smb2_request_error(req, NT_STATUS_INVALID_PARAMETER);
1053         }
1054
1055         /*
1056          * TODO: cancel all outstanding requests on the session
1057          *       and delete all tree connections.
1058          */
1059         smbd_smb2_session_destructor(req->session);
1060         /*
1061          * we may need to sign the response, so we need to keep
1062          * the session until the response is sent to the wire.
1063          */
1064         talloc_steal(req, req->session);
1065
1066         outbody = data_blob_talloc(req->out.vector, NULL, 0x04);
1067         if (outbody.data == NULL) {
1068                 return smbd_smb2_request_error(req, NT_STATUS_NO_MEMORY);
1069         }
1070
1071         SSVAL(outbody.data, 0x00, 0x04);        /* struct size */
1072         SSVAL(outbody.data, 0x02, 0);           /* reserved */
1073
1074         return smbd_smb2_request_done(req, outbody, NULL);
1075 }