3 Unix SMB/CIFS implementation.
5 Copyright (C) Andrew Tridgell 1998-2001
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2001-2005
7 Copyright (C) Jim McDonough 2002
8 Copyright (C) Luke Howard 2003
9 Copyright (C) Stefan Metzmacher 2005
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.
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.
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/>.
28 #include "auth/gensec/gensec.h"
29 #include "auth/auth.h"
30 #include "smb_server/smb_server.h"
31 #include "samba/service_stream.h"
32 #include "param/param.h"
33 #include "../lib/tsocket/tsocket.h"
34 #include "lib/stream/packet.h"
36 struct sesssetup_context
{
37 struct auth4_context
*auth_context
;
38 struct smbsrv_request
*req
;
42 * Log the SMB authentication, as by not calling GENSEC we won't log
43 * it during the gensec_session_info().
45 void smbsrv_not_spengo_sesssetup_authz_log(struct smbsrv_request
*req
,
46 struct auth_session_info
*session_info
)
48 struct tsocket_address
*local_address
;
49 struct tsocket_address
*remote_address
;
50 TALLOC_CTX
*frame
= talloc_stackframe();
52 remote_address
= socket_get_remote_addr(req
->smb_conn
->connection
->socket
,
54 local_address
= socket_get_local_addr(req
->smb_conn
->connection
->socket
,
57 log_successful_authz_event(req
->smb_conn
->connection
->msg_ctx
,
58 req
->smb_conn
->lp_ctx
,
63 AUTHZ_TRANSPORT_PROTECTION_SMB
,
65 NULL
/* client_audit_info */,
66 NULL
/* server_audit_info */);
74 setup the OS, Lanman and domain portions of a session setup reply
76 static void sesssetup_common_strings(struct smbsrv_request
*req
,
77 char **os
, char **lanman
, char **domain
)
79 (*os
) = talloc_asprintf(req
, "Unix");
80 (*lanman
) = talloc_asprintf(req
, "Samba %s", SAMBA_VERSION_STRING
);
81 (*domain
) = talloc_asprintf(req
, "%s",
82 lpcfg_workgroup(req
->smb_conn
->lp_ctx
));
85 static void smbsrv_sesssetup_backend_send(struct smbsrv_request
*req
,
86 union smb_sesssetup
*sess
,
89 if (NT_STATUS_IS_OK(status
)) {
90 req
->smb_conn
->negotiate
.done_sesssetup
= true;
91 /* we need to keep the session long term */
92 req
->session
= talloc_steal(req
->smb_conn
, req
->session
);
94 smbsrv_reply_sesssetup_send(req
, sess
, status
);
97 static void sesssetup_old_send(struct tevent_req
*subreq
)
99 struct sesssetup_context
*state
= tevent_req_callback_data(subreq
, struct sesssetup_context
);
100 struct smbsrv_request
*req
= state
->req
;
102 union smb_sesssetup
*sess
= talloc_get_type(req
->io_ptr
, union smb_sesssetup
);
103 struct auth_user_info_dc
*user_info_dc
= NULL
;
104 struct auth_session_info
*session_info
;
105 struct smbsrv_session
*smb_sess
;
107 uint8_t authoritative
= 1;
110 status
= auth_check_password_recv(subreq
, req
, &user_info_dc
,
113 if (!NT_STATUS_IS_OK(status
)) goto failed
;
115 flags
= AUTH_SESSION_INFO_DEFAULT_GROUPS
;
116 if (!(user_info_dc
->info
->user_flags
& NETLOGON_GUEST
)) {
117 flags
|= AUTH_SESSION_INFO_AUTHENTICATED
;
119 /* This references user_info_dc into session_info */
120 status
= req
->smb_conn
->negotiate
.auth_context
->generate_session_info(req
->smb_conn
->negotiate
.auth_context
,
122 user_info_dc
, sess
->old
.in
.user
,
123 flags
, &session_info
);
124 if (!NT_STATUS_IS_OK(status
)) goto failed
;
126 /* allocate a new session */
127 smb_sess
= smbsrv_session_new(req
->smb_conn
, req
, NULL
);
129 status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
133 smbsrv_not_spengo_sesssetup_authz_log(req
, session_info
);
135 /* Ensure this is marked as a 'real' vuid, not one
136 * simply valid for the session setup leg */
137 status
= smbsrv_session_sesssetup_finished(smb_sess
, session_info
);
138 if (!NT_STATUS_IS_OK(status
)) goto failed
;
140 /* To correctly process any AndX packet (like a tree connect)
141 * we need to fill in the session on the request here */
142 req
->session
= smb_sess
;
143 sess
->old
.out
.vuid
= smb_sess
->vuid
;
146 status
= nt_status_squash(status
);
147 smbsrv_sesssetup_backend_send(req
, sess
, status
);
151 handler for old style session setup
153 static void sesssetup_old(struct smbsrv_request
*req
, union smb_sesssetup
*sess
)
155 struct auth_usersupplied_info
*user_info
= NULL
;
156 struct tsocket_address
*remote_address
, *local_address
;
157 const char *remote_machine
= NULL
;
158 struct tevent_req
*subreq
;
159 struct sesssetup_context
*state
;
161 sess
->old
.out
.vuid
= 0;
162 sess
->old
.out
.action
= 0;
164 sesssetup_common_strings(req
,
166 &sess
->old
.out
.lanman
,
167 &sess
->old
.out
.domain
);
169 if (!req
->smb_conn
->negotiate
.done_sesssetup
) {
170 req
->smb_conn
->negotiate
.max_send
= sess
->old
.in
.bufsize
;
173 if (req
->smb_conn
->negotiate
.calling_name
) {
174 remote_machine
= req
->smb_conn
->negotiate
.calling_name
->name
;
177 remote_address
= socket_get_remote_addr(req
->smb_conn
->connection
->socket
, req
);
178 if (!remote_address
) goto nomem
;
180 if (!remote_machine
) {
181 remote_machine
= tsocket_address_inet_addr_string(remote_address
, req
);
182 if (!remote_machine
) goto nomem
;
185 local_address
= socket_get_local_addr(req
->smb_conn
->connection
->socket
, req
);
186 if (!local_address
) goto nomem
;
188 user_info
= talloc_zero(req
, struct auth_usersupplied_info
);
189 if (!user_info
) goto nomem
;
191 user_info
->service_description
= "SMB";
193 user_info
->logon_parameters
= 0;
194 user_info
->flags
= 0;
195 user_info
->client
.account_name
= sess
->old
.in
.user
;
196 user_info
->client
.domain_name
= sess
->old
.in
.domain
;
197 user_info
->workstation_name
= remote_machine
;
199 user_info
->remote_host
= talloc_steal(user_info
, remote_address
);
200 user_info
->local_host
= talloc_steal(user_info
, local_address
);
202 user_info
->password_state
= AUTH_PASSWORD_RESPONSE
;
203 user_info
->password
.response
.lanman
= sess
->old
.in
.password
;
204 user_info
->password
.response
.lanman
.data
= talloc_steal(user_info
, sess
->old
.in
.password
.data
);
205 user_info
->password
.response
.nt
= data_blob(NULL
, 0);
207 state
= talloc(req
, struct sesssetup_context
);
208 if (!state
) goto nomem
;
210 if (req
->smb_conn
->negotiate
.auth_context
) {
211 state
->auth_context
= req
->smb_conn
->negotiate
.auth_context
;
213 /* TODO: should we use just "anonymous" here? */
214 NTSTATUS status
= auth_context_create(state
,
215 req
->smb_conn
->connection
->event
.ctx
,
216 req
->smb_conn
->connection
->msg_ctx
,
217 req
->smb_conn
->lp_ctx
,
218 &state
->auth_context
);
219 if (!NT_STATUS_IS_OK(status
)) {
220 smbsrv_sesssetup_backend_send(req
, sess
, status
);
227 subreq
= auth_check_password_send(state
,
228 req
->smb_conn
->connection
->event
.ctx
,
229 req
->smb_conn
->negotiate
.auth_context
,
231 if (!subreq
) goto nomem
;
232 tevent_req_set_callback(subreq
, sesssetup_old_send
, state
);
236 smbsrv_sesssetup_backend_send(req
, sess
, NT_STATUS_NO_MEMORY
);
239 static void sesssetup_nt1_send(struct tevent_req
*subreq
)
241 struct sesssetup_context
*state
= tevent_req_callback_data(subreq
, struct sesssetup_context
);
242 struct smbsrv_request
*req
= state
->req
;
243 union smb_sesssetup
*sess
= talloc_get_type(req
->io_ptr
, union smb_sesssetup
);
244 struct auth_user_info_dc
*user_info_dc
= NULL
;
245 struct auth_session_info
*session_info
;
246 struct smbsrv_session
*smb_sess
;
247 uint8_t authoritative
= 1;
251 status
= auth_check_password_recv(subreq
, req
, &user_info_dc
,
254 if (!NT_STATUS_IS_OK(status
)) goto failed
;
256 flags
= AUTH_SESSION_INFO_DEFAULT_GROUPS
;
257 if (!(user_info_dc
->info
->user_flags
& NETLOGON_GUEST
)) {
258 flags
|= AUTH_SESSION_INFO_AUTHENTICATED
;
260 /* This references user_info_dc into session_info */
261 status
= state
->auth_context
->generate_session_info(state
->auth_context
,
267 if (!NT_STATUS_IS_OK(status
)) goto failed
;
269 /* allocate a new session */
270 smb_sess
= smbsrv_session_new(req
->smb_conn
, req
, NULL
);
272 status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
276 smbsrv_not_spengo_sesssetup_authz_log(req
, session_info
);
278 /* Ensure this is marked as a 'real' vuid, not one
279 * simply valid for the session setup leg */
280 status
= smbsrv_session_sesssetup_finished(smb_sess
, session_info
);
281 if (!NT_STATUS_IS_OK(status
)) goto failed
;
283 /* To correctly process any AndX packet (like a tree connect)
284 * we need to fill in the session on the request here */
285 req
->session
= smb_sess
;
286 sess
->nt1
.out
.vuid
= smb_sess
->vuid
;
288 if (!smbsrv_setup_signing(req
->smb_conn
, &session_info
->session_key
, &sess
->nt1
.in
.password2
)) {
289 /* Already signing, or disabled */
294 status
= NT_STATUS_OK
;
296 status
= nt_status_squash(status
);
297 smbsrv_sesssetup_backend_send(req
, sess
, status
);
301 handler for NT1 style session setup
303 static void sesssetup_nt1(struct smbsrv_request
*req
, union smb_sesssetup
*sess
)
306 struct auth_usersupplied_info
*user_info
= NULL
;
307 struct tsocket_address
*remote_address
, *local_address
;
308 const char *remote_machine
= NULL
;
309 struct tevent_req
*subreq
;
310 struct sesssetup_context
*state
;
311 bool allow_raw
= lpcfg_raw_ntlmv2_auth(req
->smb_conn
->lp_ctx
);
313 sess
->nt1
.out
.vuid
= 0;
314 sess
->nt1
.out
.action
= 0;
316 sesssetup_common_strings(req
,
318 &sess
->nt1
.out
.lanman
,
319 &sess
->nt1
.out
.domain
);
321 if (!req
->smb_conn
->negotiate
.done_sesssetup
) {
322 req
->smb_conn
->negotiate
.max_send
= sess
->nt1
.in
.bufsize
;
323 req
->smb_conn
->negotiate
.client_caps
= sess
->nt1
.in
.capabilities
;
326 state
= talloc(req
, struct sesssetup_context
);
327 if (!state
) goto nomem
;
331 if (req
->smb_conn
->negotiate
.oid
) {
332 if (sess
->nt1
.in
.user
&& *sess
->nt1
.in
.user
) {
333 /* We can't accept a normal login, because we
334 * don't have a challenge */
335 status
= NT_STATUS_LOGON_FAILURE
;
339 /* TODO: should we use just "anonymous" here? */
340 status
= auth_context_create(state
,
341 req
->smb_conn
->connection
->event
.ctx
,
342 req
->smb_conn
->connection
->msg_ctx
,
343 req
->smb_conn
->lp_ctx
,
344 &state
->auth_context
);
345 if (!NT_STATUS_IS_OK(status
)) goto failed
;
346 } else if (req
->smb_conn
->negotiate
.auth_context
) {
347 state
->auth_context
= req
->smb_conn
->negotiate
.auth_context
;
349 /* TODO: should we use just "anonymous" here? */
350 status
= auth_context_create(state
,
351 req
->smb_conn
->connection
->event
.ctx
,
352 req
->smb_conn
->connection
->msg_ctx
,
353 req
->smb_conn
->lp_ctx
,
354 &state
->auth_context
);
355 if (!NT_STATUS_IS_OK(status
)) goto failed
;
358 if (req
->smb_conn
->negotiate
.calling_name
) {
359 remote_machine
= req
->smb_conn
->negotiate
.calling_name
->name
;
362 remote_address
= socket_get_remote_addr(req
->smb_conn
->connection
->socket
, req
);
363 if (!remote_address
) goto nomem
;
365 if (!remote_machine
) {
366 remote_machine
= tsocket_address_inet_addr_string(remote_address
, req
);
367 if (!remote_machine
) goto nomem
;
370 local_address
= socket_get_local_addr(req
->smb_conn
->connection
->socket
, req
);
371 if (!local_address
) goto nomem
;
373 user_info
= talloc_zero(req
, struct auth_usersupplied_info
);
374 if (!user_info
) goto nomem
;
376 user_info
->service_description
= "SMB";
377 user_info
->auth_description
= "bare-NTLM";
379 user_info
->logon_parameters
= 0;
380 user_info
->flags
= 0;
381 user_info
->client
.account_name
= sess
->nt1
.in
.user
;
382 user_info
->client
.domain_name
= sess
->nt1
.in
.domain
;
383 user_info
->workstation_name
= remote_machine
;
384 user_info
->remote_host
= talloc_steal(user_info
, remote_address
);
385 user_info
->local_host
= talloc_steal(user_info
, local_address
);
387 user_info
->password_state
= AUTH_PASSWORD_RESPONSE
;
388 user_info
->password
.response
.lanman
= sess
->nt1
.in
.password1
;
389 user_info
->password
.response
.lanman
.data
= talloc_steal(user_info
, sess
->nt1
.in
.password1
.data
);
390 user_info
->password
.response
.nt
= sess
->nt1
.in
.password2
;
391 user_info
->password
.response
.nt
.data
= talloc_steal(user_info
, sess
->nt1
.in
.password2
.data
);
393 if (!allow_raw
&& user_info
->password
.response
.nt
.length
>= 48) {
395 * NTLMv2_RESPONSE has at least 48 bytes
396 * and should only be supported via NTLMSSP.
398 status
= NT_STATUS_INVALID_PARAMETER
;
402 subreq
= auth_check_password_send(state
,
403 req
->smb_conn
->connection
->event
.ctx
,
406 if (!subreq
) goto nomem
;
407 tevent_req_set_callback(subreq
, sesssetup_nt1_send
, state
);
412 status
= NT_STATUS_NO_MEMORY
;
414 status
= nt_status_squash(status
);
415 smbsrv_sesssetup_backend_send(req
, sess
, status
);
418 struct sesssetup_spnego_state
{
419 struct smbsrv_request
*req
;
420 union smb_sesssetup
*sess
;
421 struct smbsrv_session
*smb_sess
;
424 static void sesssetup_spnego_send(struct tevent_req
*subreq
)
426 struct sesssetup_spnego_state
*s
= tevent_req_callback_data(subreq
,
427 struct sesssetup_spnego_state
);
428 struct smbsrv_request
*req
= s
->req
;
429 union smb_sesssetup
*sess
= s
->sess
;
430 struct smbsrv_session
*smb_sess
= s
->smb_sess
;
431 struct auth_session_info
*session_info
= NULL
;
433 NTSTATUS skey_status
;
434 DATA_BLOB session_key
;
436 status
= gensec_update_recv(subreq
, req
, &sess
->spnego
.out
.secblob
);
437 packet_recv_enable(req
->smb_conn
->packet
);
439 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
441 } else if (!NT_STATUS_IS_OK(status
)) {
445 status
= gensec_session_info(smb_sess
->gensec_ctx
, smb_sess
, &session_info
);
446 if (!NT_STATUS_IS_OK(status
)) goto failed
;
448 /* The session_key is only needed until the end of the smbsrv_setup_signing() call */
449 skey_status
= gensec_session_key(smb_sess
->gensec_ctx
, req
, &session_key
);
450 if (NT_STATUS_IS_OK(skey_status
)) {
451 smbsrv_setup_signing(req
->smb_conn
, &session_key
, NULL
);
454 /* Ensure this is marked as a 'real' vuid, not one
455 * simply valid for the session setup leg */
456 status
= smbsrv_session_sesssetup_finished(smb_sess
, session_info
);
457 if (!NT_STATUS_IS_OK(status
)) goto failed
;
459 req
->session
= smb_sess
;
462 sess
->spnego
.out
.vuid
= smb_sess
->vuid
;
464 status
= nt_status_squash(status
);
465 smbsrv_sesssetup_backend_send(req
, sess
, status
);
466 if (!NT_STATUS_IS_OK(status
) &&
467 !NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
468 talloc_free(smb_sess
);
473 handler for SPNEGO style session setup
475 static void sesssetup_spnego(struct smbsrv_request
*req
, union smb_sesssetup
*sess
)
478 struct smbsrv_session
*smb_sess
= NULL
;
479 bool is_smb_sess_new
= false;
480 struct sesssetup_spnego_state
*s
= NULL
;
482 struct tevent_req
*subreq
;
484 sess
->spnego
.out
.vuid
= 0;
485 sess
->spnego
.out
.action
= 0;
487 sesssetup_common_strings(req
,
488 &sess
->spnego
.out
.os
,
489 &sess
->spnego
.out
.lanman
,
490 &sess
->spnego
.out
.workgroup
);
492 if (!req
->smb_conn
->negotiate
.done_sesssetup
) {
493 req
->smb_conn
->negotiate
.max_send
= sess
->spnego
.in
.bufsize
;
494 req
->smb_conn
->negotiate
.client_caps
= sess
->spnego
.in
.capabilities
;
497 vuid
= SVAL(req
->in
.hdr
,HDR_UID
);
499 /* lookup an existing session */
501 struct gensec_security
*gensec_ctx
;
502 struct tsocket_address
*remote_address
, *local_address
;
503 status
= samba_server_gensec_start(req
,
504 req
->smb_conn
->connection
->event
.ctx
,
505 req
->smb_conn
->connection
->msg_ctx
,
506 req
->smb_conn
->lp_ctx
,
507 req
->smb_conn
->negotiate
.server_credentials
,
510 if (!NT_STATUS_IS_OK(status
)) {
511 DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status
)));
515 gensec_want_feature(gensec_ctx
, GENSEC_FEATURE_SESSION_KEY
);
516 gensec_want_feature(gensec_ctx
, GENSEC_FEATURE_SMB_TRANSPORT
);
518 remote_address
= socket_get_remote_addr(req
->smb_conn
->connection
->socket
,
520 if (!remote_address
) {
521 status
= NT_STATUS_INTERNAL_ERROR
;
522 DBG_ERR("Failed to obtain remote address\n");
526 status
= gensec_set_remote_address(gensec_ctx
,
528 if (!NT_STATUS_IS_OK(status
)) {
529 DBG_ERR("Failed to set remote address\n");
533 local_address
= socket_get_local_addr(req
->smb_conn
->connection
->socket
,
535 if (!local_address
) {
536 status
= NT_STATUS_INTERNAL_ERROR
;
537 DBG_ERR("Failed to obtain local address\n");
541 status
= gensec_set_local_address(gensec_ctx
,
543 if (!NT_STATUS_IS_OK(status
)) {
544 DBG_ERR("Failed to set local address\n");
548 status
= gensec_set_target_service_description(gensec_ctx
,
551 if (!NT_STATUS_IS_OK(status
)) {
552 DBG_ERR("Failed to set service description\n");
556 status
= gensec_start_mech_by_oid(gensec_ctx
, req
->smb_conn
->negotiate
.oid
);
557 if (!NT_STATUS_IS_OK(status
)) {
558 DEBUG(1, ("Failed to start GENSEC %s server code: %s\n",
559 gensec_get_name_by_oid(gensec_ctx
, req
->smb_conn
->negotiate
.oid
), nt_errstr(status
)));
563 /* allocate a new session */
564 smb_sess
= smbsrv_session_new(req
->smb_conn
, req
->smb_conn
, gensec_ctx
);
566 status
= NT_STATUS_INSUFFICIENT_RESOURCES
;
569 is_smb_sess_new
= true;
571 smb_sess
= smbsrv_session_find_sesssetup(req
->smb_conn
, vuid
);
575 status
= NT_STATUS_DOS(ERRSRV
, ERRbaduid
);
579 if (smb_sess
->session_info
) {
580 status
= NT_STATUS_INVALID_PARAMETER
;
584 if (!smb_sess
->gensec_ctx
) {
585 status
= NT_STATUS_INTERNAL_ERROR
;
586 DEBUG(1, ("Internal ERROR: no gensec_ctx on session: %s\n", nt_errstr(status
)));
590 s
= talloc(req
, struct sesssetup_spnego_state
);
594 s
->smb_sess
= smb_sess
;
596 subreq
= gensec_update_send(s
,
597 req
->smb_conn
->connection
->event
.ctx
,
598 smb_sess
->gensec_ctx
,
599 sess
->spnego
.in
.secblob
);
603 /* disable receipt of more packets on this socket until we've
604 finished with the session setup. This avoids a problem with
605 crashes if we get EOF on the socket while processing a session
607 packet_recv_disable(req
->smb_conn
->packet
);
608 tevent_req_set_callback(subreq
, sesssetup_spnego_send
, s
);
613 status
= NT_STATUS_NO_MEMORY
;
615 if (is_smb_sess_new
) {
616 talloc_free(smb_sess
);
618 status
= nt_status_squash(status
);
619 smbsrv_sesssetup_backend_send(req
, sess
, status
);
623 backend for sessionsetup call - this takes all 3 variants of the call
625 void smbsrv_sesssetup_backend(struct smbsrv_request
*req
,
626 union smb_sesssetup
*sess
)
628 switch (sess
->old
.level
) {
629 case RAW_SESSSETUP_OLD
:
630 sesssetup_old(req
, sess
);
633 case RAW_SESSSETUP_NT1
:
634 sesssetup_nt1(req
, sess
);
637 case RAW_SESSSETUP_SPNEGO
:
638 sesssetup_spnego(req
, sess
);
641 case RAW_SESSSETUP_SMB2
:
645 smbsrv_sesssetup_backend_send(req
, sess
, NT_STATUS_INVALID_LEVEL
);