aboutsummaryrefslogtreecommitdiffstats
path: root/main/openldap/CVE-2020-12243.patch
blob: d8e10f5bc667bee9883f36e00aa909ea72e1367d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
From 98464c11df8247d6a11b52e294ba5dd4f0380440 Mon Sep 17 00:00:00 2001
From: Howard Chu <hyc@openldap.org>
Date: Thu, 16 Apr 2020 01:08:19 +0100
Subject: [PATCH] ITS#9202 limit depth of nested filters

Using a hardcoded limit for now; no reasonable apps
should ever run into it.
---
 servers/slapd/filter.c | 41 ++++++++++++++++++++++++++++++++---------
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/servers/slapd/filter.c b/servers/slapd/filter.c
index 3252cf2a7..ed57bbd7b 100644
--- a/servers/slapd/filter.c
+++ b/servers/slapd/filter.c
@@ -37,11 +37,16 @@
 const Filter *slap_filter_objectClass_pres;
 const struct berval *slap_filterstr_objectClass_pres;
 
+#ifndef SLAPD_MAX_FILTER_DEPTH
+#define SLAPD_MAX_FILTER_DEPTH	5000
+#endif
+
 static int	get_filter_list(
 	Operation *op,
 	BerElement *ber,
 	Filter **f,
-	const char **text );
+	const char **text,
+	int depth );
 
 static int	get_ssa(
 	Operation *op,
@@ -80,12 +85,13 @@ filter_destroy( void )
 	return;
 }
 
-int
-get_filter(
+static int
+get_filter0(
 	Operation *op,
 	BerElement *ber,
 	Filter **filt,
-	const char **text )
+	const char **text,
+	int depth )
 {
 	ber_tag_t	tag;
 	ber_len_t	len;
@@ -126,6 +132,11 @@ get_filter(
 	 *
 	 */
 
+	if( depth > SLAPD_MAX_FILTER_DEPTH ) {
+		*text = "filter nested too deeply";
+		return SLAPD_DISCONNECT;
+	}
+
 	tag = ber_peek_tag( ber, &len );
 
 	if( tag == LBER_ERROR ) {
@@ -221,7 +232,7 @@ get_filter(
 
 	case LDAP_FILTER_AND:
 		Debug( LDAP_DEBUG_FILTER, "AND\n", 0, 0, 0 );
-		err = get_filter_list( op, ber, &f.f_and, text );
+		err = get_filter_list( op, ber, &f.f_and, text, depth+1 );
 		if ( err != LDAP_SUCCESS ) {
 			break;
 		}
@@ -234,7 +245,7 @@ get_filter(
 
 	case LDAP_FILTER_OR:
 		Debug( LDAP_DEBUG_FILTER, "OR\n", 0, 0, 0 );
-		err = get_filter_list( op, ber, &f.f_or, text );
+		err = get_filter_list( op, ber, &f.f_or, text, depth+1 );
 		if ( err != LDAP_SUCCESS ) {
 			break;
 		}
@@ -248,7 +259,7 @@ get_filter(
 	case LDAP_FILTER_NOT:
 		Debug( LDAP_DEBUG_FILTER, "NOT\n", 0, 0, 0 );
 		(void) ber_skip_tag( ber, &len );
-		err = get_filter( op, ber, &f.f_not, text );
+		err = get_filter0( op, ber, &f.f_not, text, depth+1 );
 		if ( err != LDAP_SUCCESS ) {
 			break;
 		}
@@ -311,10 +322,22 @@ get_filter(
 	return( err );
 }
 
+int
+get_filter(
+	Operation *op,
+	BerElement *ber,
+	Filter **filt,
+	const char **text )
+{
+	return get_filter0( op, ber, filt, text, 0 );
+}
+
+
 static int
 get_filter_list( Operation *op, BerElement *ber,
 	Filter **f,
-	const char **text )
+	const char **text,
+	int depth )
 {
 	Filter		**new;
 	int		err;
@@ -328,7 +351,7 @@ get_filter_list( Operation *op, BerElement *ber,
 		tag != LBER_DEFAULT;
 		tag = ber_next_element( ber, &len, last ) )
 	{
-		err = get_filter( op, ber, new, text );
+		err = get_filter0( op, ber, new, text, depth );
 		if ( err != LDAP_SUCCESS )
 			return( err );
 		new = &(*new)->f_next;
-- 
GitLab