All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
paircmp.c
Go to the documentation of this file.
1 /*
2  * paircmp.c Valuepair functions for various attributes
3  *
4  * Version: $Id: 0ba22af30a7a7bfd9b282fa0c881e9b7cca5f89a $
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2000,2006 The FreeRADIUS server project
21  * Copyright 2000 Alan DeKok <aland@ox.org>
22  */
23 
24 RCSID("$Id: 0ba22af30a7a7bfd9b282fa0c881e9b7cca5f89a $")
25 
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/rad_assert.h>
28 #include "rlm_expr.h"
29 
30 /*
31  * Compare a Connect-Info and a Connect-Rate
32  */
33 static int connectcmp(UNUSED void *instance,
34  REQUEST *request UNUSED,
35  VALUE_PAIR *req,
36  VALUE_PAIR *check,
37  UNUSED VALUE_PAIR *check_pairs,
38  UNUSED VALUE_PAIR **reply_pairs)
39 {
40  int rate;
41 
42  VERIFY_VP(req);
43  VERIFY_VP(check);
44 
45  rate = atoi(req->vp_strvalue);
46  return rate - check->vp_integer;
47 }
48 
49 /*
50  * Compare prefix/suffix.
51  *
52  * If they compare:
53  * - if PW_STRIP_USER_NAME is present in check_pairs,
54  * strip the username of prefix/suffix.
55  * - if PW_STRIP_USER_NAME is not present in check_pairs,
56  * add a PW_STRIPPED_USER_NAME to the request.
57  */
58 static int presufcmp(UNUSED void *instance,
59  REQUEST *request,
60  VALUE_PAIR *req,
61  VALUE_PAIR *check,
62  VALUE_PAIR *check_pairs,
63  UNUSED VALUE_PAIR **reply_pairs)
64 {
65  VALUE_PAIR *vp;
66  char const *name;
67  char rest[MAX_STRING_LEN];
68  int len, namelen;
69  int ret = -1;
70 
71  if (!request) {
72  return -1;
73  }
74 
75  VERIFY_VP(req);
76  VERIFY_VP(check);
77  rad_assert(req->da->type == PW_TYPE_STRING);
78 
79  name = req->vp_strvalue;
80 
81  RDEBUG3("Comparing name \"%s\" and check value \"%s\"", name, check->vp_strvalue);
82 
83  len = strlen(check->vp_strvalue);
84  if (check->da->vendor == 0) switch (check->da->attr) {
85  case PW_PREFIX:
86  ret = strncmp(name, check->vp_strvalue, len);
87  if (ret == 0)
88  strlcpy(rest, name + len, sizeof(rest));
89  break;
90  case PW_SUFFIX:
91  namelen = strlen(name);
92  if (namelen < len)
93  break;
94  ret = strcmp(name + namelen - len,
95  check->vp_strvalue);
96  if (ret == 0) {
97  strlcpy(rest, name, namelen - len + 1);
98  }
99  break;
100  }
101  if (ret != 0) {
102  return ret;
103  }
104 
105  /*
106  * If Strip-User-Name == No, then don't do any more.
107  */
108  vp = fr_pair_find_by_num(check_pairs, 0, PW_STRIP_USER_NAME, TAG_ANY);
109  if (vp && !vp->vp_integer) return ret;
110 
111  /*
112  * See where to put the stripped user name.
113  */
114  vp = fr_pair_find_by_num(check_pairs, 0, PW_STRIPPED_USER_NAME, TAG_ANY);
115  if (!vp) {
116  /*
117  * If "request" is NULL, then the memory will be
118  * lost!
119  */
120  vp = radius_pair_create(request->packet, &req, PW_STRIPPED_USER_NAME, 0);
121  if (!vp) return ret;
122  request->username = vp;
123  }
124 
125  fr_pair_value_strcpy(vp, rest);
126 
127  return ret;
128 }
129 
130 
131 /*
132  * Compare the request packet type.
133  */
134 static int packetcmp(UNUSED void *instance,
135  REQUEST *request,
136  UNUSED VALUE_PAIR *req,
137  VALUE_PAIR *check,
138  UNUSED VALUE_PAIR *check_pairs,
139  UNUSED VALUE_PAIR **reply_pairs)
140 {
141  VERIFY_VP(check);
142 
143  if (request->packet->code == check->vp_integer) {
144  return 0;
145  }
146 
147  return 1;
148 }
149 
150 /*
151  * Compare the response packet type.
152  */
153 static int responsecmp(UNUSED void *instance,
154  REQUEST *request,
155  UNUSED VALUE_PAIR *req,
156  VALUE_PAIR *check,
157  UNUSED VALUE_PAIR *check_pairs,
158  UNUSED VALUE_PAIR **reply_pairs)
159 {
160  VERIFY_VP(check);
161 
162  if (request->reply->code == check->vp_integer) {
163  return 0;
164  }
165 
166  return 1;
167 }
168 
169 /*
170  * Generic comparisons, via xlat.
171  */
172 static int genericcmp(UNUSED void *instance,
173  REQUEST *request,
174  VALUE_PAIR *req,
175  VALUE_PAIR *check,
176  UNUSED VALUE_PAIR *check_pairs,
177  UNUSED VALUE_PAIR **reply_pairs)
178 {
179  VERIFY_VP(check);
180 
181  if ((check->op != T_OP_REG_EQ) &&
182  (check->op != T_OP_REG_NE)) {
183  int rcode;
184  char name[1024];
185  char value[1024];
186  VALUE_PAIR *vp;
187 
188  snprintf(name, sizeof(name), "%%{%s}", check->da->name);
189 
190  if (radius_xlat(value, sizeof(value), request, name, NULL, NULL) < 0) {
191  return 0;
192  }
193  vp = fr_pair_make(req, NULL, check->da->name, value, check->op);
194 
195  /*
196  * Paircmp returns 0 for failed comparison, 1 for succeeded -1 for error.
197  */
198  rcode = fr_pair_cmp(check, vp);
199 
200  /*
201  * We're being called from radius_callback_compare,
202  * which wants 0 for success, and 1 for fail (sigh)
203  *
204  * We should really fix the API so that it is
205  * consistent. i.e. the comparison callbacks should
206  * return ONLY the resut of comparing A to B.
207  * The radius_callback_cmp function should then
208  * take care of using the operator to see if the
209  * condition (A OP B) is true or not.
210  *
211  * This would also allow "<", etc. to work in the
212  * callback functions...
213  *
214  * See rlm_ldap, ...groupcmp() for something that
215  * returns 0 for matched, and 1 for didn't match.
216  */
217  rcode = !rcode;
218  fr_pair_list_free(&vp);
219 
220  return rcode;
221  }
222 
223  /*
224  * Will do the xlat for us
225  */
226  return radius_compare_vps(request, check, NULL);
227 }
228 
229 static int generic_attrs[] = {
230  PW_CLIENT_IP_ADDRESS,
231  PW_PACKET_SRC_IP_ADDRESS,
232  PW_PACKET_DST_IP_ADDRESS,
233  PW_PACKET_SRC_PORT,
234  PW_PACKET_DST_PORT,
235  PW_REQUEST_PROCESSING_STAGE,
236  PW_PACKET_SRC_IPV6_ADDRESS,
237  PW_PACKET_DST_IPV6_ADDRESS,
238  PW_VIRTUAL_SERVER,
239  0
240 };
241 
242 /*
243  * Register server-builtin special attributes.
244  */
245 void pair_builtincompare_add(void *instance)
246 {
247  int i;
248 
249  paircompare_register(fr_dict_attr_by_num(NULL, 0, PW_PREFIX), fr_dict_attr_by_num(NULL, 0, PW_USER_NAME), false, presufcmp, instance);
250  paircompare_register(fr_dict_attr_by_num(NULL, 0, PW_SUFFIX), fr_dict_attr_by_num(NULL, 0, PW_USER_NAME), false, presufcmp, instance);
251  paircompare_register(fr_dict_attr_by_num(NULL, 0, PW_CONNECT_RATE), fr_dict_attr_by_num(NULL, 0,
252  PW_CONNECT_INFO),
253  false, connectcmp, instance);
254  paircompare_register(fr_dict_attr_by_num(NULL, 0, PW_PACKET_TYPE), NULL, true, packetcmp, instance);
255  paircompare_register(fr_dict_attr_by_num(NULL, 0, PW_RESPONSE_PACKET_TYPE), NULL, true, responsecmp, instance);
256 
257  for (i = 0; generic_attrs[i] != 0; i++) {
258  paircompare_register(fr_dict_attr_by_num(NULL, 0, generic_attrs[i]), NULL, true, genericcmp, instance);
259  }
260 }
void fr_pair_list_free(VALUE_PAIR **)
Free memory used by a valuepair list.
Definition: pair.c:544
int paircompare_register(fr_dict_attr_t const *attribute, fr_dict_attr_t const *from, bool first_only, RAD_COMPARE_FUNC func, void *instance)
Register a function as compare function.
Definition: pair.c:395
static char const * name
VALUE_PAIR * radius_pair_create(TALLOC_CTX *ctx, VALUE_PAIR **vps, unsigned int attribute, unsigned int vendor)
Create a VALUE_PAIR and add it to a list of VALUE_PAIR s.
Definition: pair.c:704
VALUE_PAIR * username
Cached username VALUE_PAIR from request RADIUS_PACKET.
Definition: radiusd.h:222
#define VERIFY_VP(_x)
Definition: pair.h:44
#define UNUSED
Definition: libradius.h:134
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
Definition: snprintf.c:686
#define rad_assert(expr)
Definition: rad_assert.h:38
static int responsecmp(UNUSED void *instance, REQUEST *request, UNUSED VALUE_PAIR *req, VALUE_PAIR *check, UNUSED VALUE_PAIR *check_pairs, UNUSED VALUE_PAIR **reply_pairs)
Definition: paircmp.c:153
static int genericcmp(UNUSED void *instance, REQUEST *request, VALUE_PAIR *req, VALUE_PAIR *check, UNUSED VALUE_PAIR *check_pairs, UNUSED VALUE_PAIR **reply_pairs)
Definition: paircmp.c:172
void fr_pair_value_strcpy(VALUE_PAIR *vp, char const *src)
Copy data into an "string" data type.
Definition: pair.c:2013
static int packetcmp(UNUSED void *instance, REQUEST *request, UNUSED VALUE_PAIR *req, VALUE_PAIR *check, UNUSED VALUE_PAIR *check_pairs, UNUSED VALUE_PAIR **reply_pairs)
Definition: paircmp.c:134
unsigned int attr
Attribute number.
Definition: dict.h:79
unsigned int code
Packet code (type).
Definition: libradius.h:155
unsigned int vendor
Vendor that defines this attribute.
Definition: dict.h:78
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
RADIUS_PACKET * reply
Outgoing response.
Definition: radiusd.h:225
FR_TOKEN op
Operator to use when moving or inserting valuepair into a list.
Definition: pair.h:118
ssize_t radius_xlat(char *out, size_t outlen, REQUEST *request, char const *fmt, xlat_escape_t escape, void *escape_ctx) CC_HINT(nonnull(1
static int presufcmp(UNUSED void *instance, REQUEST *request, VALUE_PAIR *req, VALUE_PAIR *check, VALUE_PAIR *check_pairs, UNUSED VALUE_PAIR **reply_pairs)
Definition: paircmp.c:58
char name[1]
Attribute name.
Definition: dict.h:89
#define TAG_ANY
Definition: pair.h:191
void pair_builtincompare_add(void *instance)
Definition: paircmp.c:245
RADIUS_PACKET * packet
Incoming request.
Definition: radiusd.h:221
static int generic_attrs[]
Definition: paircmp.c:229
int fr_pair_cmp(VALUE_PAIR *a, VALUE_PAIR *b)
Compare two pairs, using the operator from "a".
Definition: pair.c:850
VALUE_PAIR * fr_pair_find_by_num(VALUE_PAIR *head, unsigned int vendor, unsigned int attr, int8_t tag)
Find the pair with the matching attribute.
Definition: pair.c:639
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:38
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
Definition: pair.h:113
#define MAX_STRING_LEN
Definition: libradius.h:120
fr_dict_attr_t const * fr_dict_attr_by_num(fr_dict_t *dict, unsigned int vendor, unsigned int attr)
Lookup a fr_dict_attr_t by its vendor and attribute numbers.
Definition: dict.c:3519
String of printable characters.
Definition: radius.h:33
PW_TYPE type
Value type.
Definition: dict.h:80
#define RCSID(id)
Definition: build.h:135
int radius_compare_vps(REQUEST *request, VALUE_PAIR *check, VALUE_PAIR *vp)
VALUE_PAIR * fr_pair_make(TALLOC_CTX *ctx, VALUE_PAIR **vps, char const *attribute, char const *value, FR_TOKEN op)
Create a VALUE_PAIR from ASCII strings.
Definition: pair.c:338
static int connectcmp(UNUSED void *instance, REQUEST *request UNUSED, VALUE_PAIR *req, VALUE_PAIR *check, UNUSED VALUE_PAIR *check_pairs, UNUSED VALUE_PAIR **reply_pairs)
Definition: paircmp.c:33
#define RDEBUG3(fmt,...)
Definition: log.h:245