xref: /openbsd/usr.sbin/ldapd/filter.c (revision 264ca280)
1 /*	$OpenBSD: filter.c,v 1.3 2014/09/21 05:33:49 daniel Exp $ */
2 
3 /*
4  * Copyright (c) 2009, 2010 Martin Hedenfalk <martinh@openbsd.org>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <sys/queue.h>
20 #include <sys/types.h>
21 
22 #include <string.h>
23 #include <stdint.h>
24 
25 #include "ldapd.h"
26 
27 static int	 ldap_filt_eq(struct ber_element *root, struct plan *plan);
28 static int	 ldap_filt_subs(struct ber_element *root, struct plan *plan);
29 static int	 ldap_filt_and(struct ber_element *root, struct plan *plan);
30 static int	 ldap_filt_or(struct ber_element *root, struct plan *plan);
31 static int	 ldap_filt_not(struct ber_element *root, struct plan *plan);
32 
33 static int
34 ldap_filt_eq(struct ber_element *root, struct plan *plan)
35 {
36 	char			*vs;
37 	struct ber_element	*a, *vals, *v;
38 
39 	if (plan->adesc != NULL)
40 		a = ldap_get_attribute(root, plan->adesc);
41 	else
42 		a = ldap_find_attribute(root, plan->at);
43 	if (a == NULL) {
44 		log_debug("no attribute [%s] found", plan->adesc ? plan->adesc : ATTR_NAME(plan->at));
45 		return -1;
46 	}
47 
48 	vals = a->be_next;
49 	if (vals == NULL)
50 		return -1;
51 
52 	for (v = vals->be_sub; v; v = v->be_next) {
53 		if (ber_get_string(v, &vs) != 0)
54 			continue;
55 		if (strcasecmp(plan->assert.value, vs) == 0)
56 			return 0;
57 	}
58 
59 	return -1;
60 }
61 
62 static int
63 ldap_filt_subs_value(struct ber_element *v, struct ber_element *sub)
64 {
65 	int		 class;
66 	unsigned long	 type;
67 	const char	*cmpval;
68 	char		*vs, *p, *end;
69 
70 	if (ber_get_string(v, &vs) != 0)
71 		return -1;
72 
73 	for (; sub; sub = sub->be_next) {
74 		if (ber_scanf_elements(sub, "ts", &class, &type, &cmpval) != 0)
75 			return -1;
76 
77 		if (class != BER_CLASS_CONTEXT)
78 			return -1;
79 
80 		switch (type) {
81 		case LDAP_FILT_SUBS_INIT:
82 			if (strncasecmp(cmpval, vs, strlen(cmpval)) == 0)
83 				vs += strlen(cmpval);
84 			else
85 				return 1; /* no match */
86 			break;
87 		case LDAP_FILT_SUBS_ANY:
88 			if ((p = strcasestr(vs, cmpval)) != NULL)
89 				vs = p + strlen(cmpval);
90 			else
91 				return 1; /* no match */
92 			break;
93 		case LDAP_FILT_SUBS_FIN:
94 			if (strlen(vs) < strlen(cmpval))
95 				return 1; /* no match */
96 			end = vs + strlen(vs) - strlen(cmpval);
97 			if (strcasecmp(end, cmpval) == 0)
98 				vs = end + strlen(cmpval);
99 			else
100 				return 1; /* no match */
101 			break;
102 		default:
103 			log_warnx("invalid subfilter type %d", type);
104 			return -1;
105 		}
106 	}
107 
108 	return 0; /* match */
109 }
110 
111 static int
112 ldap_filt_subs(struct ber_element *root, struct plan *plan)
113 {
114 	const char		*attr;
115 	struct ber_element	*a, *v;
116 
117 	if (plan->adesc != NULL)
118 		a = ldap_get_attribute(root, plan->adesc);
119 	else
120 		a = ldap_find_attribute(root, plan->at);
121 	if (a == NULL) {
122 		log_debug("no attribute [%s] found", plan->adesc ? plan->adesc : ATTR_NAME(plan->at));
123 		return -1;
124 	}
125 
126 	if (ber_scanf_elements(a, "s(e", &attr, &v) != 0)
127 		return -1; /* internal failure, false or undefined? */
128 
129 	/* Loop through all values, stop if any matches.
130 	 */
131 	for (; v; v = v->be_next) {
132 		/* All substrings must match. */
133 		switch (ldap_filt_subs_value(v, plan->assert.substring)) {
134 		case 0:
135 			return 0;
136 		case -1:
137 			return -1;
138 		default:
139 			break;
140 		}
141 	}
142 
143 	/* All values checked, no match. */
144 	return -1;
145 }
146 
147 static int
148 ldap_filt_and(struct ber_element *root, struct plan *plan)
149 {
150 	struct plan	*arg;
151 
152 	TAILQ_FOREACH(arg, &plan->args, next)
153 		if (ldap_matches_filter(root, arg) != 0)
154 			return -1;
155 
156 	return 0;
157 }
158 
159 static int
160 ldap_filt_or(struct ber_element *root, struct plan *plan)
161 {
162 	struct plan	*arg;
163 
164 	TAILQ_FOREACH(arg, &plan->args, next)
165 		if (ldap_matches_filter(root, arg) == 0)
166 			return 0;
167 
168 	return -1;
169 }
170 
171 static int
172 ldap_filt_not(struct ber_element *root, struct plan *plan)
173 {
174 	struct plan	*arg;
175 
176 	TAILQ_FOREACH(arg, &plan->args, next)
177 		if (ldap_matches_filter(root, arg) != 0)
178 			return 0;
179 
180 	return -1;
181 }
182 
183 static int
184 ldap_filt_presence(struct ber_element *root, struct plan *plan)
185 {
186 	struct ber_element	*a;
187 
188 	if (plan->adesc != NULL)
189 		a = ldap_get_attribute(root, plan->adesc);
190 	else
191 		a = ldap_find_attribute(root, plan->at);
192 	if (a == NULL) {
193 		log_debug("no attribute [%s] found", plan->adesc ? plan->adesc : ATTR_NAME(plan->at));
194 		return -1;
195 	}
196 
197 	return 0;
198 }
199 
200 int
201 ldap_matches_filter(struct ber_element *root, struct plan *plan)
202 {
203 	if (plan == NULL)
204 		return 0;
205 
206 	switch (plan->op) {
207 	case LDAP_FILT_EQ:
208 	case LDAP_FILT_APPR:
209 		return ldap_filt_eq(root, plan);
210 	case LDAP_FILT_SUBS:
211 		return ldap_filt_subs(root, plan);
212 	case LDAP_FILT_AND:
213 		return ldap_filt_and(root, plan);
214 	case LDAP_FILT_OR:
215 		return ldap_filt_or(root, plan);
216 	case LDAP_FILT_NOT:
217 		return ldap_filt_not(root, plan);
218 	case LDAP_FILT_PRES:
219 		return ldap_filt_presence(root, plan);
220 	default:
221 		log_warnx("filter type %d not implemented", plan->op);
222 		return -1;
223 	}
224 }
225 
226