*/
#include "includes.h"
-#include "auth/credentials/credentials.h"
+#include <tevent.h>
#include "auth/gensec/gensec.h"
#include "auth/auth.h"
#include "libcli/smb2/smb2.h"
#include "libcli/smb2/smb2_calls.h"
#include "smb_server/smb_server.h"
-#include "smb_server/service_smb_proto.h"
#include "smb_server/smb2/smb2_server.h"
#include "smbd/service_stream.h"
-#include "param/param.h"
+#include "lib/stream/packet.h"
static void smb2srv_sesssetup_send(struct smb2srv_request *req, union smb_sesssetup *io)
{
- uint16_t credit;
-
if (NT_STATUS_IS_OK(req->status)) {
- credit = 0x0003;
+ /* nothing */
} else if (NT_STATUS_EQUAL(req->status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- credit = 0x0002;
+ /* nothing */
} else {
smb2srv_send_error(req, req->status);
return;
SMB2SRV_CHECK(smb2srv_setup_reply(req, 0x08, true, io->smb2.out.secblob.length));
- SSVAL(req->out.hdr, SMB2_HDR_CREDIT, credit);
SBVAL(req->out.hdr, SMB2_HDR_SESSION_ID, io->smb2.out.uid);
SSVAL(req->out.body, 0x02, io->smb2.out.session_flags);
struct smbsrv_session *smb_sess;
};
-static void smb2srv_sesssetup_callback(struct gensec_update_request *greq, void *private_data)
+static void smb2srv_sesssetup_callback(struct tevent_req *subreq)
{
- struct smb2srv_sesssetup_callback_ctx *ctx = talloc_get_type(private_data,
+ struct smb2srv_sesssetup_callback_ctx *ctx = tevent_req_callback_data(subreq,
struct smb2srv_sesssetup_callback_ctx);
struct smb2srv_request *req = ctx->req;
union smb_sesssetup *io = ctx->io;
struct smbsrv_session *smb_sess = ctx->smb_sess;
struct auth_session_info *session_info = NULL;
+ enum security_user_level user_level;
NTSTATUS status;
- status = gensec_update_recv(greq, req, &io->smb2.out.secblob);
+ packet_recv_enable(req->smb_conn->packet);
+
+ status = gensec_update_recv(subreq, req, &io->smb2.out.secblob);
+ TALLOC_FREE(subreq);
if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
goto done;
} else if (!NT_STATUS_IS_OK(status)) {
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;
}
}
req->session = smb_sess;
- if (smb_sess->smb2_signing.required) {
- /* activate smb2 signing on the session */
- smb_sess->smb2_signing.active = true;
+ user_level = security_session_user_level(smb_sess->session_info, NULL);
+ if (user_level >= SECURITY_USER) {
+ if (smb_sess->smb2_signing.required) {
+ /* activate smb2 signing on the session */
+ smb_sess->smb2_signing.active = true;
+ }
+ /* we need to sign the session setup response */
+ req->is_signed = true;
}
+
done:
io->smb2.out.uid = smb_sess->vuid;
failed:
- req->status = auth_nt_status_squash(status);
+ req->status = nt_status_squash(status);
smb2srv_sesssetup_send(req, io);
if (!NT_STATUS_IS_OK(status) && !
NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
struct smb2srv_sesssetup_callback_ctx *callback_ctx;
struct smbsrv_session *smb_sess = NULL;
uint64_t vuid;
+ struct tevent_req *subreq;
io->smb2.out.session_flags = 0;
io->smb2.out.uid = 0;
if (vuid == 0) {
struct gensec_security *gensec_ctx;
- status = gensec_server_start(req,
- req->smb_conn->connection->event.ctx,
- lp_gensec_settings(req, req->smb_conn->lp_ctx),
- req->smb_conn->connection->msg_ctx,
- &gensec_ctx);
+ status = samba_server_gensec_start(req,
+ req->smb_conn->connection->event.ctx,
+ req->smb_conn->connection->msg_ctx,
+ req->smb_conn->lp_ctx,
+ req->smb_conn->negotiate.server_credentials,
+ "cifs",
+ &gensec_ctx);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
goto failed;
}
- gensec_set_credentials(gensec_ctx, req->smb_conn->negotiate.server_credentials);
-
- gensec_set_target_service(gensec_ctx, "cifs");
-
gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
status = gensec_start_mech_by_oid(gensec_ctx, GENSEC_OID_SPNEGO);
}
if (!smb_sess) {
+ status = NT_STATUS_USER_SESSION_DELETED;
+ goto failed;
+ }
+
+ if (smb_sess->session_info) {
/* see WSPP test suite - test 11 */
status = NT_STATUS_REQUEST_NOT_ACCEPTED;
goto failed;
callback_ctx->io = io;
callback_ctx->smb_sess = smb_sess;
- gensec_update_send(smb_sess->gensec_ctx, io->smb2.in.secblob,
- smb2srv_sesssetup_callback, callback_ctx);
+ subreq = gensec_update_send(callback_ctx,
+ req->smb_conn->connection->event.ctx,
+ smb_sess->gensec_ctx,
+ io->smb2.in.secblob);
+ if (!subreq) goto nomem;
+ tevent_req_set_callback(subreq, smb2srv_sesssetup_callback, callback_ctx);
/* note that we ignore SMB2_NEGOTIATE_SIGNING_ENABLED from the client.
This is deliberate as windows does not set it even when it does
set SMB2_NEGOTIATE_SIGNING_REQUIRED */
if (io->smb2.in.security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) {
smb_sess->smb2_signing.required = true;
- } else if (req->smb_conn->smb2_signing_required) {
- /*
- * if required signing was negotiates in SMB2 Negotiate
- * then the client made an error not using it here
- */
- DEBUG(1, ("SMB2 signing required on the connection but not used on session\n"));
- req->status = NT_STATUS_FOOBAR;
- goto failed;
}
+ /* 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);
+
return;
nomem:
status = NT_STATUS_NO_MEMORY;
failed:
talloc_free(smb_sess);
- req->status = auth_nt_status_squash(status);
+ req->status = nt_status_squash(status);
smb2srv_sesssetup_send(req, io);
}
void smb2srv_logoff_recv(struct smb2srv_request *req)
{
- uint16_t _pad;
-
SMB2SRV_CHECK_BODY_SIZE(req, 0x04, false);
- _pad = SVAL(req->in.body, 0x02);
-
req->status = smb2srv_logoff_backend(req);
if (req->control_flags & SMB2SRV_REQ_CTRL_FLAG_NOT_REPLY) {