mirror of
https://github.com/samba-team/samba.git
synced 2025-01-25 06:04:04 +03:00
CVE-2020-10704: S4 ldap server: Limit request sizes
Check the size of authenticated and anonymous ldap requests and reject them if they exceed the limits in smb.conf Credit to OSS-Fuzz REF: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=20454 BUG: https://bugzilla.samba.org/show_bug.cgi?id=14334 Signed-off-by: Gary Lockyer <gary@catalyst.net.nz> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
parent
d7e5213818
commit
28ee4acc83
@ -1 +0,0 @@
|
|||||||
^samba.tests.ldap_raw.samba.tests.ldap_raw.RawLdapTest.test_search_exceeds_maximum_permitted_size\(ad_dc\)
|
|
@ -441,6 +441,10 @@ static void ldapsrv_accept_tls_done(struct tevent_req *subreq)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ldapsrv_call_read_done(struct tevent_req *subreq);
|
static void ldapsrv_call_read_done(struct tevent_req *subreq);
|
||||||
|
static NTSTATUS ldapsrv_packet_check(
|
||||||
|
void *private_data,
|
||||||
|
DATA_BLOB blob,
|
||||||
|
size_t *packet_size);
|
||||||
|
|
||||||
static bool ldapsrv_call_read_next(struct ldapsrv_connection *conn)
|
static bool ldapsrv_call_read_next(struct ldapsrv_connection *conn)
|
||||||
{
|
{
|
||||||
@ -494,7 +498,7 @@ static bool ldapsrv_call_read_next(struct ldapsrv_connection *conn)
|
|||||||
conn->connection->event.ctx,
|
conn->connection->event.ctx,
|
||||||
conn->sockets.active,
|
conn->sockets.active,
|
||||||
7, /* initial_read_size */
|
7, /* initial_read_size */
|
||||||
ldap_full_packet,
|
ldapsrv_packet_check,
|
||||||
conn);
|
conn);
|
||||||
if (subreq == NULL) {
|
if (subreq == NULL) {
|
||||||
ldapsrv_terminate_connection(conn, "ldapsrv_call_read_next: "
|
ldapsrv_terminate_connection(conn, "ldapsrv_call_read_next: "
|
||||||
@ -520,6 +524,9 @@ static bool ldapsrv_call_read_next(struct ldapsrv_connection *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void ldapsrv_call_process_done(struct tevent_req *subreq);
|
static void ldapsrv_call_process_done(struct tevent_req *subreq);
|
||||||
|
static int ldapsrv_check_packet_size(
|
||||||
|
struct ldapsrv_connection *conn,
|
||||||
|
size_t size);
|
||||||
|
|
||||||
static void ldapsrv_call_read_done(struct tevent_req *subreq)
|
static void ldapsrv_call_read_done(struct tevent_req *subreq)
|
||||||
{
|
{
|
||||||
@ -530,6 +537,7 @@ static void ldapsrv_call_read_done(struct tevent_req *subreq)
|
|||||||
struct ldapsrv_call *call;
|
struct ldapsrv_call *call;
|
||||||
struct asn1_data *asn1;
|
struct asn1_data *asn1;
|
||||||
DATA_BLOB blob;
|
DATA_BLOB blob;
|
||||||
|
int ret = LDAP_SUCCESS;
|
||||||
|
|
||||||
conn->sockets.read_req = NULL;
|
conn->sockets.read_req = NULL;
|
||||||
|
|
||||||
@ -560,6 +568,14 @@ static void ldapsrv_call_read_done(struct tevent_req *subreq)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = ldapsrv_check_packet_size(conn, blob.length);
|
||||||
|
if (ret != LDAP_SUCCESS) {
|
||||||
|
ldapsrv_terminate_connection(
|
||||||
|
conn,
|
||||||
|
"Request packet too large");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
asn1 = asn1_init(call, ASN1_MAX_TREE_DEPTH);
|
asn1 = asn1_init(call, ASN1_MAX_TREE_DEPTH);
|
||||||
if (asn1 == NULL) {
|
if (asn1 == NULL) {
|
||||||
ldapsrv_terminate_connection(conn, "no memory");
|
ldapsrv_terminate_connection(conn, "no memory");
|
||||||
@ -1362,6 +1378,84 @@ static void ldapsrv_post_fork(struct task_server *task, struct process_details *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the size of an ldap request packet.
|
||||||
|
*
|
||||||
|
* For authenticated connections the maximum packet size is controlled by
|
||||||
|
* the smb.conf parameter "ldap max authenticated request size"
|
||||||
|
*
|
||||||
|
* For anonymous connections the maximum packet size is controlled by
|
||||||
|
* the smb.conf parameter "ldap max anonymous request size"
|
||||||
|
*/
|
||||||
|
static int ldapsrv_check_packet_size(
|
||||||
|
struct ldapsrv_connection *conn,
|
||||||
|
size_t size)
|
||||||
|
{
|
||||||
|
bool is_anonymous = false;
|
||||||
|
size_t max_size = 0;
|
||||||
|
|
||||||
|
max_size = lpcfg_ldap_max_anonymous_request_size(conn->lp_ctx);
|
||||||
|
if (size <= max_size) {
|
||||||
|
return LDAP_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request is larger than the maximum unauthenticated request size.
|
||||||
|
* As this code is called frequently we avoid calling
|
||||||
|
* security_token_is_anonymous if possible
|
||||||
|
*/
|
||||||
|
if (conn->session_info != NULL &&
|
||||||
|
conn->session_info->security_token != NULL) {
|
||||||
|
is_anonymous = security_token_is_anonymous(
|
||||||
|
conn->session_info->security_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_anonymous) {
|
||||||
|
DBG_WARNING(
|
||||||
|
"LDAP request size (%zu) exceeds (%zu)\n",
|
||||||
|
size,
|
||||||
|
max_size);
|
||||||
|
return LDAP_UNWILLING_TO_PERFORM;
|
||||||
|
}
|
||||||
|
|
||||||
|
max_size = lpcfg_ldap_max_authenticated_request_size(conn->lp_ctx);
|
||||||
|
if (size > max_size) {
|
||||||
|
DBG_WARNING(
|
||||||
|
"LDAP request size (%zu) exceeds (%zu)\n",
|
||||||
|
size,
|
||||||
|
max_size);
|
||||||
|
return LDAP_UNWILLING_TO_PERFORM;
|
||||||
|
}
|
||||||
|
return LDAP_SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the blob contains enough data to be a valid packet
|
||||||
|
* If there is a packet header check the size to ensure that it does not
|
||||||
|
* exceed the maximum sizes.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static NTSTATUS ldapsrv_packet_check(
|
||||||
|
void *private_data,
|
||||||
|
DATA_BLOB blob,
|
||||||
|
size_t *packet_size)
|
||||||
|
{
|
||||||
|
NTSTATUS ret;
|
||||||
|
struct ldapsrv_connection *conn = private_data;
|
||||||
|
int result = LDB_SUCCESS;
|
||||||
|
|
||||||
|
ret = ldap_full_packet(private_data, blob, packet_size);
|
||||||
|
if (!NT_STATUS_IS_OK(ret)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
result = ldapsrv_check_packet_size(conn, *packet_size);
|
||||||
|
if (result != LDAP_SUCCESS) {
|
||||||
|
return NT_STATUS_LDAP(result);
|
||||||
|
}
|
||||||
|
return NT_STATUS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS server_service_ldap_init(TALLOC_CTX *ctx)
|
NTSTATUS server_service_ldap_init(TALLOC_CTX *ctx)
|
||||||
{
|
{
|
||||||
static const struct service_details details = {
|
static const struct service_details details = {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user