The FreeRADIUS server $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
Loading...
Searching...
No Matches
paircmp.c
Go to the documentation of this file.
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15 */
16
17/**
18 * $Id: d133e58a1390dc449109aa2a2c2c13cdbb3f25b4 $
19 *
20 * @brief Valuepair functions that are radiusd-specific and as such do not
21 * belong in the library.
22 * @file src/lib/server/paircmp.c
23 *
24 * @ingroup AVP
25 *
26 * @copyright 2000,2006 The FreeRADIUS server project
27 * @copyright 2000 Alan DeKok (aland@freeradius.org)
28 */
29
30RCSID("$Id: d133e58a1390dc449109aa2a2c2c13cdbb3f25b4 $")
31
32#include <freeradius-devel/server/paircmp.h>
33#include <freeradius-devel/server/regex.h>
34#include <freeradius-devel/server/request.h>
35#include <freeradius-devel/unlang/xlat.h>
36#include <freeradius-devel/util/debug.h>
37#include <ctype.h>
38
39/** Compares check and vp by value.
40 *
41 * Does not call any per-attribute comparison function, but does honour
42 * check.operator. Basically does "vp.value check.op check.value".
43 *
44 * @param[in] request Current request.
45 * @param[in] check rvalue, and operator.
46 * @param[in] vp lvalue.
47 * @return
48 * - 0 if check and vp are equal
49 * - -1 if vp value is less than check value.
50 * - 1 is vp value is more than check value.
51 * - -2 on error.
52 */
53#ifdef HAVE_REGEX
54int paircmp_pairs(request_t *request, fr_pair_t const *check, fr_pair_t *vp)
55#else
57#endif
58{
59 int ret = 0;
60
61 /*
62 * Check for =* and !* and return appropriately
63 */
64 if (check->op == T_OP_CMP_TRUE) return 0;
65 if (check->op == T_OP_CMP_FALSE) return 1;
66
67 if (!vp) {
68 REDEBUG("Non-Unary operations require two operands");
69 return -2;
70 }
71
72#ifdef HAVE_REGEX
73 if ((check->op == T_OP_REG_EQ) || (check->op == T_OP_REG_NE)) {
74 ssize_t slen;
75 regex_t *preg = NULL;
76 uint32_t subcaptures;
77 fr_regmatch_t *regmatch;
78
79 char *expr = NULL, *value = NULL;
80 char const *expr_p, *value_p;
81
82 if (check->vp_type == FR_TYPE_STRING) {
83 expr_p = check->vp_strvalue;
84 } else {
85 fr_value_box_aprint(request, &expr, &check->data, NULL);
86 expr_p = expr;
87 }
88
89 if (vp->vp_type == FR_TYPE_STRING) {
90 value_p = vp->vp_strvalue;
91 } else {
92 fr_value_box_aprint(request, &value, &vp->data, NULL);
93 value_p = value;
94 }
95
96 if (!expr_p || !value_p) {
97 REDEBUG("Error stringifying operand for regular expression");
98
99 regex_error:
100 talloc_free(preg);
101 talloc_free(expr);
103 return -2;
104 }
105
106 /*
107 * Include substring matches.
108 */
109 slen = regex_compile(request, &preg, expr_p, talloc_array_length(expr_p) - 1,
110 NULL, true, true);
111 if (slen <= 0) {
112 REMARKER(expr_p, -slen, "%s", fr_strerror());
113
114 goto regex_error;
115 }
116
117 subcaptures = regex_subcapture_count(preg);
118 if (!subcaptures) subcaptures = REQUEST_MAX_REGEX + 1; /* +1 for %{0} (whole match) capture group */
119 MEM(regmatch = regex_match_data_alloc(NULL, subcaptures));
120
121 /*
122 * Evaluate the expression
123 */
124 slen = regex_exec(preg, value_p, talloc_array_length(value_p) - 1, regmatch);
125 if (slen < 0) {
126 RPERROR("Invalid regex");
127
128 goto regex_error;
129 }
130
131 if (check->op == T_OP_REG_EQ) {
132 /*
133 * Add in %{0}. %{1}, etc.
134 */
135 regex_sub_to_request(request, &preg, &regmatch);
136 ret = (slen == 1) ? 0 : -1;
137 } else {
138 ret = (slen != 1) ? 0 : -1;
139 }
140
141 talloc_free(regmatch);
142 talloc_free(preg);
143 talloc_free(expr);
145
146 goto finish;
147 }
148#endif
149
150 /*
151 * Attributes must be of the same type.
152 *
153 * FIXME: deal with type mismatch properly if one side contain
154 * OCTETS or STRING by converting the other side to
155 * a string
156 *
157 */
158 if (vp->vp_type != check->vp_type) return -1;
159
160 /*
161 * Not a regular expression, compare the types.
162 */
163 switch (check->vp_type) {
164 case FR_TYPE_OCTETS:
165 if (vp->vp_length != check->vp_length) {
166 ret = 1; /* NOT equal */
167 break;
168 }
169 ret = memcmp(vp->vp_strvalue, check->vp_strvalue, vp->vp_length);
170 break;
171
172 case FR_TYPE_STRING:
173 ret = strcmp(vp->vp_strvalue, check->vp_strvalue);
174 break;
175
176 case FR_TYPE_UINT8:
177 ret = vp->vp_uint8 - check->vp_uint8;
178 break;
179
180 case FR_TYPE_UINT16:
181 ret = vp->vp_uint16 - check->vp_uint16;
182 break;
183
184 case FR_TYPE_UINT32:
185 ret = vp->vp_uint32 - check->vp_uint32;
186 break;
187
188 case FR_TYPE_UINT64:
189 /*
190 * Don't want integer overflow!
191 */
192 if (vp->vp_uint64 < check->vp_uint64) {
193 ret = -1;
194 } else if (vp->vp_uint64 > check->vp_uint64) {
195 ret = +1;
196 } else {
197 ret = 0;
198 }
199 break;
200
201 case FR_TYPE_INT32:
202 ret = CMP(vp->vp_int32, check->vp_int32);
203 break;
204
205 case FR_TYPE_DATE:
206 ret = fr_unix_time_cmp(vp->vp_date, check->vp_date);
207 break;
208
210 ret = ntohl(vp->vp_ipv4addr) - ntohl(check->vp_ipv4addr);
211 break;
212
214 ret = memcmp(vp->vp_ip.addr.v6.s6_addr, check->vp_ip.addr.v6.s6_addr,
215 sizeof(vp->vp_ip.addr.v6.s6_addr));
216 break;
217
220 ret = fr_pair_cmp_op(check->op, vp, check);
221 if (ret == -1) return -2; // error
222 if (check->op == T_OP_LT || check->op == T_OP_LE)
223 ret = (ret == 1) ? -1 : 1;
224 else if (check->op == T_OP_GT || check->op == T_OP_GE)
225 ret = (ret == 1) ? 1 : -1;
226 else if (check->op == T_OP_CMP_EQ)
227 ret = (ret == 1) ? 0 : -1;
228 break;
229
230 case FR_TYPE_IFID:
231 ret = memcmp(vp->vp_ifid, check->vp_ifid, sizeof(vp->vp_ifid));
232 break;
233
234 default:
235 break;
236 }
237
238finish:
239 if (ret > 0) return 1;
240 if (ret < 0) return -1;
241 return 0;
242}
#define RCSID(id)
Definition build.h:483
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
Definition build.h:112
#define UNUSED
Definition build.h:315
#define MEM(x)
Definition debug.h:36
Test enumeration values.
Definition dict_test.h:92
#define RPERROR(fmt,...)
Definition log.h:302
#define REMARKER(_str, _marker_idx, _marker,...)
Output string with error marker, showing where format error occurred.
Definition log.h:498
talloc_free(reap)
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_IPV6_PREFIX
IPv6 Prefix.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT16
16 Bit unsigned integer.
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
@ FR_TYPE_UINT8
8 Bit unsigned integer.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_INT32
32 Bit signed integer.
@ FR_TYPE_UINT64
64 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_IPV4_PREFIX
IPv4 Prefix.
@ FR_TYPE_IFID
Interface ID.
@ FR_TYPE_OCTETS
Raw octets.
unsigned int uint32_t
long int ssize_t
#define check(_handle, _len_p)
Definition bio.c:44
int paircmp_pairs(UNUSED request_t *request, fr_pair_t const *check, fr_pair_t *vp)
Compares check and vp by value.
Definition paircmp.c:56
#define REDEBUG(fmt,...)
Definition radclient.h:52
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition pair.h:68
static int8_t fr_unix_time_cmp(fr_unix_time_t a, fr_unix_time_t b)
Compare two fr_unix_time_t values.
Definition time.h:944
@ T_OP_CMP_TRUE
Definition token.h:104
@ T_OP_CMP_FALSE
Definition token.h:105
@ T_OP_REG_EQ
Definition token.h:102
@ T_OP_CMP_EQ
Definition token.h:106
@ T_OP_LE
Definition token.h:100
@ T_OP_GE
Definition token.h:98
@ T_OP_GT
Definition token.h:99
@ T_OP_LT
Definition token.h:101
@ T_OP_REG_NE
Definition token.h:103
#define fr_pair_cmp_op(_op, _a, _b)
Compare two attributes using and operator.
Definition pair.h:666
char const * fr_strerror(void)
Get the last library error.
Definition strerror.c:554
static fr_slen_t fr_value_box_aprint(TALLOC_CTX *ctx, char **out, fr_value_box_t const *data, fr_sbuff_escape_rules_t const *e_rules) 1(fr_value_box_print