summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2021-07-09 15:36:12 +0200
committerStefan Metzmacher <metze@samba.org>2021-07-15 00:06:31 +0000
commit95a3bf588819bf7a71a333f823a5191fa49ac9dc (patch)
treec04703be288d124bc83ae71456fe3453ed7eeffc
parentf8f4a9faf099eb768eaa25f1e1a7d126b75291d0 (diff)
downloadsamba-95a3bf588819bf7a71a333f823a5191fa49ac9dc.tar.gz
s3:smbd: fallback to smb2srv_session_lookup_global() for session setups with failed signing
The motivation is to get the same error responses as a windows server. We already fallback to smb2srv_session_lookup_global() in other places where we don't have a valid session in the current smbd process. If signing is failing while verifying a session setup request, we should do the same if we don't have a valid channel binding for the connection yet. Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
-rw-r--r--selftest/knownfail.d/smb2.session9
-rw-r--r--source3/smbd/smb2_server.c48
2 files changed, 43 insertions, 14 deletions
diff --git a/selftest/knownfail.d/smb2.session b/selftest/knownfail.d/smb2.session
deleted file mode 100644
index 4521b67888e..00000000000
--- a/selftest/knownfail.d/smb2.session
+++ /dev/null
@@ -1,9 +0,0 @@
-^samba3.smb2.session.*bind_negative_smb3encGtoCs
-^samba3.smb2.session.ntlm.bind_negative_smb210s.ad_dc
-^samba3.smb2.session.ntlm.bind_negative_smb2to3s.ad_dc
-^samba3.smb2.session.ntlm.bind_negative_smb3to2s.ad_dc
-^samba3.smb2.session.ntlm.bind_negative_smb3to3s.ad_dc
-^samba3.smb2.session.krb5.bind_negative_smb210s.ad_dc
-^samba3.smb2.session.krb5.bind_negative_smb2to3s.ad_dc
-^samba3.smb2.session.krb5.bind_negative_smb3to2s.ad_dc
-^samba3.smb2.session.krb5.bind_negative_smb3to3s.ad_dc
diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c
index a2f2447595d..2d9f0d2cc74 100644
--- a/source3/smbd/smb2_server.c
+++ b/source3/smbd/smb2_server.c
@@ -2119,19 +2119,27 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req,
static
struct smb2_signing_key *smbd_smb2_signing_key(struct smbXsrv_session *session,
- struct smbXsrv_connection *xconn)
+ struct smbXsrv_connection *xconn,
+ bool *_has_channel)
{
struct smbXsrv_channel_global0 *c = NULL;
NTSTATUS status;
struct smb2_signing_key *key = NULL;
+ bool has_channel = false;
status = smbXsrv_session_find_channel(session, xconn, &c);
if (NT_STATUS_IS_OK(status)) {
key = c->signing_key;
+ has_channel = true;
}
if (!smb2_signing_key_valid(key)) {
key = session->global->signing_key;
+ has_channel = false;
+ }
+
+ if (_has_channel != NULL) {
+ *_has_channel = has_channel;
}
return key;
@@ -2338,7 +2346,7 @@ static void smbd_smb2_request_pending_timer(struct tevent_context *ev,
} else if (req->do_signing) {
struct smbXsrv_session *x = req->session;
struct smb2_signing_key *signing_key =
- smbd_smb2_signing_key(x, xconn);
+ smbd_smb2_signing_key(x, xconn, NULL);
status = smb2_signing_sign_pdu(signing_key,
&state->vector[1+SMBD_SMB2_HDR_IOV_OFS],
@@ -3080,6 +3088,7 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
signing_required = false;
} else if (signing_required || (flags & SMB2_HDR_FLAG_SIGNED)) {
struct smb2_signing_key *signing_key = NULL;
+ bool has_channel = false;
if (x == NULL) {
/*
@@ -3101,7 +3110,7 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
return smbd_smb2_request_error(req, status);
}
- signing_key = smbd_smb2_signing_key(x, xconn);
+ signing_key = smbd_smb2_signing_key(x, xconn, &has_channel);
/*
* If we have a signing key, we should
@@ -3114,6 +3123,33 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
status = smb2_signing_check_pdu(signing_key,
SMBD_SMB2_IN_HDR_IOV(req),
SMBD_SMB2_NUM_IOV_PER_REQ - 1);
+ if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED) &&
+ opcode == SMB2_OP_SESSSETUP && !has_channel &&
+ NT_STATUS_IS_OK(session_status))
+ {
+ if (!NT_STATUS_EQUAL(x->status, NT_STATUS_BAD_LOGON_SESSION_STATE)) {
+ struct smbXsrv_session *session = NULL;
+ NTSTATUS error;
+
+ error = smb2srv_session_lookup_global(req->xconn->client,
+ x->global->session_wire_id,
+ req,
+ &session);
+ if (!NT_STATUS_IS_OK(error)) {
+ return smbd_smb2_request_error(req, error);
+ }
+
+ /*
+ * We fallback to a session of
+ * another process in order to
+ * get the signing correct.
+ *
+ * We don't set req->last_session_id here.
+ */
+ req->session = x = session;
+ }
+ goto skipped_signing;
+ }
if (!NT_STATUS_IS_OK(status)) {
return smbd_smb2_request_error(req, status);
}
@@ -3165,6 +3201,8 @@ NTSTATUS smbd_smb2_request_dispatch(struct smbd_smb2_request *req)
}
}
+skipped_signing:
+
if (flags & SMB2_HDR_FLAG_CHAINED) {
req->compound_related = true;
}
@@ -3594,7 +3632,7 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
if (req->do_signing && firsttf->iov_len == 0) {
struct smbXsrv_session *x = req->session;
struct smb2_signing_key *signing_key =
- smbd_smb2_signing_key(x, xconn);
+ smbd_smb2_signing_key(x, xconn, NULL);
/*
* we need to remember the signing key
@@ -3648,7 +3686,7 @@ static NTSTATUS smbd_smb2_request_reply(struct smbd_smb2_request *req)
} else if (req->do_signing) {
struct smbXsrv_session *x = req->session;
struct smb2_signing_key *signing_key =
- smbd_smb2_signing_key(x, xconn);
+ smbd_smb2_signing_key(x, xconn, NULL);
status = smb2_signing_sign_pdu(signing_key,
outhdr,