GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ldapd/filter.c Lines: 0 90 0.0 %
Date: 2017-11-07 Branches: 0 81 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: filter.c,v 1.4 2017/01/20 11:55:08 benno 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
#include "log.h"
27
28
static int	 ldap_filt_eq(struct ber_element *root, struct plan *plan);
29
static int	 ldap_filt_subs(struct ber_element *root, struct plan *plan);
30
static int	 ldap_filt_and(struct ber_element *root, struct plan *plan);
31
static int	 ldap_filt_or(struct ber_element *root, struct plan *plan);
32
static int	 ldap_filt_not(struct ber_element *root, struct plan *plan);
33
34
static int
35
ldap_filt_eq(struct ber_element *root, struct plan *plan)
36
{
37
	char			*vs;
38
	struct ber_element	*a, *vals, *v;
39
40
	if (plan->adesc != NULL)
41
		a = ldap_get_attribute(root, plan->adesc);
42
	else
43
		a = ldap_find_attribute(root, plan->at);
44
	if (a == NULL) {
45
		log_debug("no attribute [%s] found", plan->adesc ? plan->adesc : ATTR_NAME(plan->at));
46
		return -1;
47
	}
48
49
	vals = a->be_next;
50
	if (vals == NULL)
51
		return -1;
52
53
	for (v = vals->be_sub; v; v = v->be_next) {
54
		if (ber_get_string(v, &vs) != 0)
55
			continue;
56
		if (strcasecmp(plan->assert.value, vs) == 0)
57
			return 0;
58
	}
59
60
	return -1;
61
}
62
63
static int
64
ldap_filt_subs_value(struct ber_element *v, struct ber_element *sub)
65
{
66
	int		 class;
67
	unsigned long	 type;
68
	const char	*cmpval;
69
	char		*vs, *p, *end;
70
71
	if (ber_get_string(v, &vs) != 0)
72
		return -1;
73
74
	for (; sub; sub = sub->be_next) {
75
		if (ber_scanf_elements(sub, "ts", &class, &type, &cmpval) != 0)
76
			return -1;
77
78
		if (class != BER_CLASS_CONTEXT)
79
			return -1;
80
81
		switch (type) {
82
		case LDAP_FILT_SUBS_INIT:
83
			if (strncasecmp(cmpval, vs, strlen(cmpval)) == 0)
84
				vs += strlen(cmpval);
85
			else
86
				return 1; /* no match */
87
			break;
88
		case LDAP_FILT_SUBS_ANY:
89
			if ((p = strcasestr(vs, cmpval)) != NULL)
90
				vs = p + strlen(cmpval);
91
			else
92
				return 1; /* no match */
93
			break;
94
		case LDAP_FILT_SUBS_FIN:
95
			if (strlen(vs) < strlen(cmpval))
96
				return 1; /* no match */
97
			end = vs + strlen(vs) - strlen(cmpval);
98
			if (strcasecmp(end, cmpval) == 0)
99
				vs = end + strlen(cmpval);
100
			else
101
				return 1; /* no match */
102
			break;
103
		default:
104
			log_warnx("invalid subfilter type %d", type);
105
			return -1;
106
		}
107
	}
108
109
	return 0; /* match */
110
}
111
112
static int
113
ldap_filt_subs(struct ber_element *root, struct plan *plan)
114
{
115
	const char		*attr;
116
	struct ber_element	*a, *v;
117
118
	if (plan->adesc != NULL)
119
		a = ldap_get_attribute(root, plan->adesc);
120
	else
121
		a = ldap_find_attribute(root, plan->at);
122
	if (a == NULL) {
123
		log_debug("no attribute [%s] found", plan->adesc ? plan->adesc : ATTR_NAME(plan->at));
124
		return -1;
125
	}
126
127
	if (ber_scanf_elements(a, "s(e", &attr, &v) != 0)
128
		return -1; /* internal failure, false or undefined? */
129
130
	/* Loop through all values, stop if any matches.
131
	 */
132
	for (; v; v = v->be_next) {
133
		/* All substrings must match. */
134
		switch (ldap_filt_subs_value(v, plan->assert.substring)) {
135
		case 0:
136
			return 0;
137
		case -1:
138
			return -1;
139
		default:
140
			break;
141
		}
142
	}
143
144
	/* All values checked, no match. */
145
	return -1;
146
}
147
148
static int
149
ldap_filt_and(struct ber_element *root, struct plan *plan)
150
{
151
	struct plan	*arg;
152
153
	TAILQ_FOREACH(arg, &plan->args, next)
154
		if (ldap_matches_filter(root, arg) != 0)
155
			return -1;
156
157
	return 0;
158
}
159
160
static int
161
ldap_filt_or(struct ber_element *root, struct plan *plan)
162
{
163
	struct plan	*arg;
164
165
	TAILQ_FOREACH(arg, &plan->args, next)
166
		if (ldap_matches_filter(root, arg) == 0)
167
			return 0;
168
169
	return -1;
170
}
171
172
static int
173
ldap_filt_not(struct ber_element *root, struct plan *plan)
174
{
175
	struct plan	*arg;
176
177
	TAILQ_FOREACH(arg, &plan->args, next)
178
		if (ldap_matches_filter(root, arg) != 0)
179
			return 0;
180
181
	return -1;
182
}
183
184
static int
185
ldap_filt_presence(struct ber_element *root, struct plan *plan)
186
{
187
	struct ber_element	*a;
188
189
	if (plan->adesc != NULL)
190
		a = ldap_get_attribute(root, plan->adesc);
191
	else
192
		a = ldap_find_attribute(root, plan->at);
193
	if (a == NULL) {
194
		log_debug("no attribute [%s] found", plan->adesc ? plan->adesc : ATTR_NAME(plan->at));
195
		return -1;
196
	}
197
198
	return 0;
199
}
200
201
int
202
ldap_matches_filter(struct ber_element *root, struct plan *plan)
203
{
204
	if (plan == NULL)
205
		return 0;
206
207
	switch (plan->op) {
208
	case LDAP_FILT_EQ:
209
	case LDAP_FILT_APPR:
210
		return ldap_filt_eq(root, plan);
211
	case LDAP_FILT_SUBS:
212
		return ldap_filt_subs(root, plan);
213
	case LDAP_FILT_AND:
214
		return ldap_filt_and(root, plan);
215
	case LDAP_FILT_OR:
216
		return ldap_filt_or(root, plan);
217
	case LDAP_FILT_NOT:
218
		return ldap_filt_not(root, plan);
219
	case LDAP_FILT_PRES:
220
		return ldap_filt_presence(root, plan);
221
	default:
222
		log_warnx("filter type %d not implemented", plan->op);
223
		return -1;
224
	}
225
}
226