#include "smbd/service_stream.h"
#include "param/param.h"
#include "../lib/tsocket/tsocket.h"
+#include "lib/stream/packet.h"
struct sesssetup_context {
- struct auth_context *auth_context;
+ struct auth4_context *auth_context;
struct smbsrv_request *req;
};
struct smbsrv_request *req = state->req;
union smb_sesssetup *sess = talloc_get_type(req->io_ptr, union smb_sesssetup);
- struct auth_serversupplied_info *server_info = NULL;
+ struct auth_user_info_dc *user_info_dc = NULL;
struct auth_session_info *session_info;
struct smbsrv_session *smb_sess;
NTSTATUS status;
uint32_t flags;
- status = auth_check_password_recv(subreq, req, &server_info);
+ status = auth_check_password_recv(subreq, req, &user_info_dc);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) goto failed;
flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
- if (server_info->authenticated) {
+ if (user_info_dc->info->authenticated) {
flags |= AUTH_SESSION_INFO_AUTHENTICATED;
}
- /* This references server_info into session_info */
- status = req->smb_conn->negotiate.auth_context->generate_session_info(req,
- req->smb_conn->negotiate.auth_context,
- server_info, flags, &session_info);
+ /* This references user_info_dc into session_info */
+ status = req->smb_conn->negotiate.auth_context->generate_session_info(req->smb_conn->negotiate.auth_context,
+ req,
+ user_info_dc, sess->old.in.user,
+ flags, &session_info);
if (!NT_STATUS_IS_OK(status)) goto failed;
/* allocate a new session */
sess->old.out.vuid = smb_sess->vuid;
failed:
- status = auth_nt_status_squash(status);
+ status = nt_status_squash(status);
smbsrv_sesssetup_backend_send(req, sess, status);
}
if (!remote_machine) goto nomem;
}
- user_info = talloc(req, struct auth_usersupplied_info);
+ user_info = talloc_zero(req, struct auth_usersupplied_info);
if (!user_info) goto nomem;
user_info->mapped_state = false;
struct sesssetup_context *state = tevent_req_callback_data(subreq, struct sesssetup_context);
struct smbsrv_request *req = state->req;
union smb_sesssetup *sess = talloc_get_type(req->io_ptr, union smb_sesssetup);
- struct auth_serversupplied_info *server_info = NULL;
+ struct auth_user_info_dc *user_info_dc = NULL;
struct auth_session_info *session_info;
struct smbsrv_session *smb_sess;
uint32_t flags;
NTSTATUS status;
- status = auth_check_password_recv(subreq, req, &server_info);
+ status = auth_check_password_recv(subreq, req, &user_info_dc);
TALLOC_FREE(subreq);
if (!NT_STATUS_IS_OK(status)) goto failed;
flags = AUTH_SESSION_INFO_DEFAULT_GROUPS;
- if (server_info->authenticated) {
+ if (user_info_dc->info->authenticated) {
flags |= AUTH_SESSION_INFO_AUTHENTICATED;
}
-
- /* This references server_info into session_info */
- status = state->auth_context->generate_session_info(req,
- state->auth_context,
- server_info,
+ /* This references user_info_dc into session_info */
+ status = state->auth_context->generate_session_info(state->auth_context,
+ req,
+ user_info_dc,
+ sess->nt1.in.user,
flags,
&session_info);
if (!NT_STATUS_IS_OK(status)) goto failed;
done:
status = NT_STATUS_OK;
failed:
- status = auth_nt_status_squash(status);
+ status = nt_status_squash(status);
smbsrv_sesssetup_backend_send(req, sess, status);
}
const char *remote_machine = NULL;
struct tevent_req *subreq;
struct sesssetup_context *state;
+ bool allow_raw = lpcfg_raw_ntlmv2_auth(req->smb_conn->lp_ctx);
sess->nt1.out.vuid = 0;
sess->nt1.out.action = 0;
if (!remote_machine) goto nomem;
}
- user_info = talloc(req, struct auth_usersupplied_info);
+ user_info = talloc_zero(req, struct auth_usersupplied_info);
if (!user_info) goto nomem;
user_info->mapped_state = false;
user_info->password.response.nt = sess->nt1.in.password2;
user_info->password.response.nt.data = talloc_steal(user_info, sess->nt1.in.password2.data);
+ if (!allow_raw && user_info->password.response.nt.length >= 48) {
+ /*
+ * NTLMv2_RESPONSE has at least 48 bytes
+ * and should only be supported via NTLMSSP.
+ */
+ status = NT_STATUS_INVALID_PARAMETER;
+ goto failed;
+ }
+
subreq = auth_check_password_send(state,
req->smb_conn->connection->event.ctx,
state->auth_context,
nomem:
status = NT_STATUS_NO_MEMORY;
failed:
- status = auth_nt_status_squash(status);
+ status = nt_status_squash(status);
smbsrv_sesssetup_backend_send(req, sess, status);
}
DATA_BLOB session_key;
status = gensec_update_recv(subreq, req, &sess->spnego.out.secblob);
+ packet_recv_enable(req->smb_conn->packet);
TALLOC_FREE(subreq);
if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
goto done;
goto failed;
}
- status = gensec_session_info(smb_sess->gensec_ctx, &session_info);
+ status = gensec_session_info(smb_sess->gensec_ctx, smb_sess, &session_info);
if (!NT_STATUS_IS_OK(status)) goto failed;
- skey_status = gensec_session_key(smb_sess->gensec_ctx, &session_key);
+ /* The session_key is only needed until the end of the smbsrv_setup_signing() call */
+ skey_status = gensec_session_key(smb_sess->gensec_ctx, req, &session_key);
if (NT_STATUS_IS_OK(skey_status)) {
smbsrv_setup_signing(req->smb_conn, &session_key, NULL);
}
done:
sess->spnego.out.vuid = smb_sess->vuid;
failed:
- status = auth_nt_status_squash(status);
+ status = nt_status_squash(status);
smbsrv_sesssetup_backend_send(req, sess, status);
if (!NT_STATUS_IS_OK(status) &&
!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
{
NTSTATUS status;
struct smbsrv_session *smb_sess = NULL;
+ bool is_smb_sess_new = false;
struct sesssetup_spnego_state *s = NULL;
uint16_t vuid;
struct tevent_req *subreq;
vuid = SVAL(req->in.hdr,HDR_UID);
/* lookup an existing session */
- smb_sess = smbsrv_session_find_sesssetup(req->smb_conn, vuid);
- if (!smb_sess) {
+ if (vuid == 0) {
struct gensec_security *gensec_ctx;
status = samba_server_gensec_start(req,
status = NT_STATUS_INSUFFICIENT_RESOURCES;
goto failed;
}
+ is_smb_sess_new = true;
+ } else {
+ smb_sess = smbsrv_session_find_sesssetup(req->smb_conn, vuid);
}
if (!smb_sess) {
- status = NT_STATUS_ACCESS_DENIED;
+ status = NT_STATUS_DOS(ERRSRV, ERRbaduid);
+ goto failed;
+ }
+
+ if (smb_sess->session_info) {
+ status = NT_STATUS_INVALID_PARAMETER;
goto failed;
}
if (!subreq) {
goto nomem;
}
+ /* disable receipt of more packets on this socket until we've
+ finished with the session setup. This avoids a problem with
+ crashes if we get EOF on the socket while processing a session
+ setup */
+ packet_recv_disable(req->smb_conn->packet);
tevent_req_set_callback(subreq, sesssetup_spnego_send, s);
return;
nomem:
status = NT_STATUS_NO_MEMORY;
failed:
- talloc_free(smb_sess);
- status = auth_nt_status_squash(status);
+ if (is_smb_sess_new) {
+ talloc_free(smb_sess);
+ }
+ status = nt_status_squash(status);
smbsrv_sesssetup_backend_send(req, sess, status);
}