All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rlm_preprocess.c
Go to the documentation of this file.
1 /*
2  * This program is 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 (at
5  * 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: 98c4a4a706a7edea01bb63cdb7105a4fbd90d5a5 $
19  * @file rlm_preprocess.c
20  * @brief Fixes up requests, and processes huntgroups/hints files.
21  *
22  * @copyright 2000,2006 The FreeRADIUS server project
23  * @copyright 2000 Alan DeKok <aland@ox.org>
24  */
25 RCSID("$Id: 98c4a4a706a7edea01bb63cdb7105a4fbd90d5a5 $")
26 
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/modules.h>
29 #include <freeradius-devel/rad_assert.h>
30 
31 #include <ctype.h>
32 
33 typedef struct rlm_preprocess_t {
34  char const *huntgroup_file;
35  char const *hints_file;
46 
47 static const CONF_PARSER module_config[] = {
48  { FR_CONF_OFFSET("huntgroups", PW_TYPE_FILE_INPUT, rlm_preprocess_t, huntgroup_file) },
49  { FR_CONF_OFFSET("hints", PW_TYPE_FILE_INPUT, rlm_preprocess_t, hints_file) },
50  { FR_CONF_OFFSET("with_ascend_hack", PW_TYPE_BOOLEAN, rlm_preprocess_t, with_ascend_hack), .dflt = "no" },
51  { FR_CONF_OFFSET("ascend_channels_per_line", PW_TYPE_INTEGER, rlm_preprocess_t, ascend_channels_per_line), .dflt = "23" },
52 
53  { FR_CONF_OFFSET("with_ntdomain_hack", PW_TYPE_BOOLEAN, rlm_preprocess_t, with_ntdomain_hack), .dflt = "no" },
54  { FR_CONF_OFFSET("with_specialix_jetstream_hack", PW_TYPE_BOOLEAN, rlm_preprocess_t, with_specialix_jetstream_hack), .dflt = "no" },
55  { FR_CONF_OFFSET("with_cisco_vsa_hack", PW_TYPE_BOOLEAN, rlm_preprocess_t, with_cisco_vsa_hack), .dflt = "no" },
56  { FR_CONF_OFFSET("with_alvarion_vsa_hack", PW_TYPE_BOOLEAN, rlm_preprocess_t, with_alvarion_vsa_hack), .dflt = "no" },
57 #if 0
58  { FR_CONF_OFFSET("with_cablelabs_vsa_hack", PW_TYPE_BOOLEAN, rlm_preprocess_t, with_cablelabs_vsa_hack) },
59 #endif
61 };
62 
63 /*
64  * See if a VALUE_PAIR list contains Fall-Through = Yes
65  */
66 static int fall_through(VALUE_PAIR *vp)
67 {
68  VALUE_PAIR *tmp;
69  tmp = fr_pair_find_by_num(vp, 0, PW_FALL_THROUGH, TAG_ANY);
70 
71  return tmp ? tmp->vp_integer : 0;
72 }
73 
74 /*
75  * This hack changes Ascend's wierd port numberings
76  * to standard 0-??? port numbers so that the "+" works
77  * for IP address assignments.
78  */
79 static void ascend_nasport_hack(VALUE_PAIR *nas_port, int channels_per_line)
80 {
81  int service;
82  int line;
83  int channel;
84 
85  if (!nas_port) {
86  return;
87  }
88 
89  if (nas_port->vp_integer > 9999) {
90  service = nas_port->vp_integer/10000; /* 1=digital 2=analog */
91  line = (nas_port->vp_integer - (10000 * service)) / 100;
92  channel = nas_port->vp_integer - ((10000 * service) + (100 * line));
93  nas_port->vp_integer = (channel - 1) + ((line - 1) * channels_per_line);
94  }
95 }
96 
97 /*
98  * This hack strips out Cisco's VSA duplicities in lines
99  * (Cisco not implemented VSA's in standard way.
100  *
101  * Cisco sends it's VSA attributes with the attribute name *again*
102  * in the string, like: H323-Attribute = "h323-attribute=value".
103  * This sort of behaviour is nonsense.
104  */
105 static void cisco_vsa_hack(REQUEST *request)
106 {
107  int vendorcode;
108  char *ptr;
109  char newattr[MAX_STRING_LEN];
110  VALUE_PAIR *vp;
111  vp_cursor_t cursor;
112  for (vp = fr_cursor_init(&cursor, &request->packet->vps);
113  vp;
114  vp = fr_cursor_next(&cursor)) {
115  vendorcode = vp->da->vendor;
116  if (!((vendorcode == 9) || (vendorcode == 6618))) {
117  continue; /* not a Cisco or Quintum VSA, continue */
118  }
119 
120  if (vp->da->type != PW_TYPE_STRING) {
121  continue;
122  }
123 
124  /*
125  * No weird packing. Ignore it.
126  */
127  ptr = strchr(vp->vp_strvalue, '='); /* find an '=' */
128  if (!ptr) {
129  continue;
130  }
131 
132  /*
133  * Cisco-AVPair's get packed as:
134  *
135  * Cisco-AVPair = "h323-foo-bar = baz"
136  * Cisco-AVPair = "h323-foo-bar=baz"
137  *
138  * which makes sense only if you're a lunatic.
139  * This code looks for the attribute named inside
140  * of the string, and if it exists, adds it as a new
141  * attribute.
142  */
143  if (vp->da->attr == 1) {
144  char const *p;
145 
146  p = vp->vp_strvalue;
147  gettoken(&p, newattr, sizeof(newattr), false);
148 
149  if (fr_dict_attr_by_name(NULL, newattr) != NULL) {
150  pair_make_request(newattr, ptr + 1, T_OP_EQ);
151  }
152  } else { /* h322-foo-bar = "h323-foo-bar = baz" */
153  /*
154  * We strip out the duplicity from the
155  * value field, we use only the value on
156  * the right side of the '=' character.
157  */
158  fr_pair_value_strcpy(vp, ptr + 1);
159  }
160  }
161 }
162 
163 
164 /*
165  * Don't even ask what this is doing...
166  */
168 {
169  int number = 1;
170  vp_cursor_t cursor;
171 
172  for (vp = fr_cursor_init(&cursor, &vp);
173  vp;
174  vp = fr_cursor_next(&cursor)) {
175  fr_dict_attr_t const *da;
176 
177  if (vp->da->vendor != 12394) {
178  continue;
179  }
180 
181  if (vp->da->type != PW_TYPE_STRING) {
182  continue;
183  }
184 
185  da = fr_dict_attr_by_num(NULL, 12394, number);
186  if (!da) {
187  continue;
188  }
189 
190  vp->da = da;
191 
192  number++;
193  }
194 }
195 
196 /*
197  * Cablelabs magic, taken from:
198  *
199  * http://www.cablelabs.com/packetcable/downloads/specs/PKT-SP-EM-I12-05812.pdf
200  *
201  * Sample data is:
202  *
203  * 0x0001d2d2026d30310000000000003030
204  * 3130303030000e812333000100033031
205  * 00000000000030303130303030000000
206  * 00063230313230313331303630323231
207  * 2e3633390000000081000500
208  */
209 
210 typedef struct cl_timezone_t {
211  uint8_t dst;
212  uint8_t sign;
213  uint8_t hh[2];
214  uint8_t mm[2];
215  uint8_t ss[2];
216 } cl_timezone_t;
217 
218 typedef struct cl_bcid_t {
219  uint32_t timestamp;
220  uint8_t element_id[8];
222  uint32_t event_counter;
223 } cl_bcid_t;
224 
225 typedef struct cl_em_hdr_t {
226  uint16_t version;
228  uint16_t message_type;
229  uint16_t element_type;
230  uint8_t element_id[8];
232  uint32_t sequence_number;
233  uint8_t event_time[18];
234  uint8_t status[4];
235  uint8_t priority;
236  uint16_t attr_count; /* of normal Cablelabs VSAs */
237  uint8_t event_object;
238 } cl_em_hdr_t;
239 
240 
241 static void cablelabs_vsa_hack(VALUE_PAIR **list)
242 {
243  VALUE_PAIR *ev;
244 
245  ev = fr_pair_find_by_num(*list, 4491, 1, TAG_ANY); /* Cablelabs-Event-Message */
246  if (!ev) {
247  return;
248  }
249 
250  /*
251  * FIXME: write 100's of lines of code to decode
252  * each data structure above.
253  */
254 }
255 
256 /*
257  * Mangle username if needed, IN PLACE.
258  */
259 static void rad_mangle(rlm_preprocess_t *inst, REQUEST *request)
260 {
261  int num_proxy_state;
262  VALUE_PAIR *namepair;
263  VALUE_PAIR *request_pairs;
264  VALUE_PAIR *tmp;
265  vp_cursor_t cursor;
266 
267  /*
268  * Get the username from the request
269  * If it isn't there, then we can't mangle the request.
270  */
271  request_pairs = request->packet->vps;
272  namepair = fr_pair_find_by_num(request_pairs, 0, PW_USER_NAME, TAG_ANY);
273  if (!namepair || (namepair->vp_length == 0)) {
274  return;
275  }
276 
277  if (inst->with_ntdomain_hack) {
278  char *ptr;
279  char newname[MAX_STRING_LEN];
280 
281  /*
282  * Windows NT machines often authenticate themselves as
283  * NT_DOMAIN\username. Try to be smart about this.
284  *
285  * FIXME: should we handle this as a REALM ?
286  */
287  if ((ptr = strchr(namepair->vp_strvalue, '\\')) != NULL) {
288  strlcpy(newname, ptr + 1, sizeof(newname));
289  /* Same size */
290  fr_pair_value_strcpy(namepair, newname);
291  }
292  }
293 
294  if (inst->with_specialix_jetstream_hack) {
295  /*
296  * Specialix Jetstream 8500 24 port access server.
297  * If the user name is 10 characters or longer, a "/"
298  * and the excess characters after the 10th are
299  * appended to the user name.
300  *
301  * Reported by Lucas Heise <root@laonet.net>
302  */
303  if ((strlen(namepair->vp_strvalue) > 10) &&
304  (namepair->vp_strvalue[10] == '/')) {
305  fr_pair_value_strcpy(namepair, namepair->vp_strvalue + 11);
306  }
307  }
308 
309  /*
310  * Small check: if Framed-Protocol present but Service-Type
311  * is missing, add Service-Type = Framed-User.
312  */
313  if (fr_pair_find_by_num(request_pairs, 0, PW_FRAMED_PROTOCOL, TAG_ANY) != NULL &&
314  fr_pair_find_by_num(request_pairs, 0, PW_SERVICE_TYPE, TAG_ANY) == NULL) {
315  tmp = radius_pair_create(request->packet, &request->packet->vps, PW_SERVICE_TYPE, 0);
316  tmp->vp_integer = PW_FRAMED_USER;
317  }
318 
319  num_proxy_state = 0;
320  for (tmp = fr_cursor_init(&cursor, &request->packet->vps);
321  tmp;
322  tmp = fr_cursor_next(&cursor)) {
323  if (tmp->da->vendor != 0) {
324  continue;
325  }
326 
327  if (tmp->da->attr != PW_PROXY_STATE) {
328  continue;
329  }
330 
331  num_proxy_state++;
332  }
333 
334  if (num_proxy_state > 10) {
335  RWDEBUG("There are more than 10 Proxy-State attributes in the request");
336  RWDEBUG("You have likely configured an infinite proxy loop");
337  }
338 }
339 
340 /*
341  * Compare the request with the "reply" part in the
342  * huntgroup, which normally only contains username or group.
343  * At least one of the "reply" items has to match.
344  */
345 static int hunt_paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check)
346 {
347  vp_cursor_t cursor;
348  VALUE_PAIR *check_item;
349  VALUE_PAIR *tmp;
350  int result = -1;
351 
352  if (!check) return 0;
353 
354  for (check_item = fr_cursor_init(&cursor, &check);
355  check_item && (result != 0);
356  check_item = fr_cursor_next(&cursor)) {
357  /* FIXME: fr_pair_list_copy should be removed once VALUE_PAIRs are no longer in linked lists */
358  tmp = fr_pair_copy(request, check_item);
359  tmp->op = check_item->op;
360  result = paircompare(req, request, check_item, NULL);
361  fr_pair_list_free(&tmp);
362  }
363 
364  return result;
365 }
366 
367 
368 /*
369  * Add hints to the info sent by the terminal server
370  * based on the pattern of the username, and other attributes.
371  */
372 static int hints_setup(PAIR_LIST *hints, REQUEST *request)
373 {
374  char const *name;
375  VALUE_PAIR *add;
376  VALUE_PAIR *tmp;
377  PAIR_LIST *i;
378  VALUE_PAIR *request_pairs;
379  int updated = 0, ft;
380 
381  request_pairs = request->packet->vps;
382 
383  if (!hints || !request_pairs)
384  return RLM_MODULE_NOOP;
385 
386  /*
387  * Check for valid input, zero length names not permitted
388  */
389  name = (tmp = fr_pair_find_by_num(request_pairs, 0, PW_USER_NAME, TAG_ANY)) ?
390  tmp->vp_strvalue : NULL;
391  if (!name || name[0] == 0) {
392  /*
393  * No name, nothing to do.
394  */
395  return RLM_MODULE_NOOP;
396  }
397 
398  for (i = hints; i; i = i->next) {
399  /*
400  * Use "paircompare", which is a little more general...
401  */
402  if (((strcmp(i->name, "DEFAULT") == 0) || (strcmp(i->name, name) == 0)) &&
403  (paircompare(request, request_pairs, i->check, NULL) == 0)) {
404  RDEBUG2("hints: Matched %s at %d", i->name, i->lineno);
405  /*
406  * Now add all attributes to the request list,
407  * except PW_STRIP_USER_NAME and PW_FALL_THROUGH
408  * and xlat them.
409  */
410  add = fr_pair_list_copy(request->packet, i->reply);
411  ft = fall_through(add);
412 
413  fr_pair_delete_by_num(&add, 0, PW_STRIP_USER_NAME, TAG_ANY);
414  fr_pair_delete_by_num(&add, 0, PW_FALL_THROUGH, TAG_ANY);
415  radius_pairmove(request, &request->packet->vps, add, true);
416 
417  updated = 1;
418  if (!ft) {
419  break;
420  }
421  }
422  }
423 
424  if (updated == 0) {
425  return RLM_MODULE_NOOP;
426  }
427 
428  return RLM_MODULE_UPDATED;
429 }
430 
431 /*
432  * See if we have access to the huntgroup.
433  */
434 static int huntgroup_access(REQUEST *request, PAIR_LIST *huntgroups)
435 {
436  PAIR_LIST *i;
437  int r = RLM_MODULE_OK;
438  VALUE_PAIR *request_pairs = request->packet->vps;
439 
440  /*
441  * We're not controlling access by huntgroups:
442  * Allow them in.
443  */
444  if (!huntgroups) {
445  return RLM_MODULE_OK;
446  }
447 
448  for (i = huntgroups; i; i = i->next) {
449  /*
450  * See if this entry matches.
451  */
452  if (paircompare(request, request_pairs, i->check, NULL) != 0) {
453  continue;
454  }
455 
456  /*
457  * Now check for access.
458  */
459  r = RLM_MODULE_REJECT;
460  if (hunt_paircmp(request, request_pairs, i->reply) == 0) {
461  VALUE_PAIR *vp;
462 
463  /*
464  * We've matched the huntgroup, so add it in
465  * to the list of request pairs.
466  */
467  vp = fr_pair_find_by_num(request_pairs, 0, PW_HUNTGROUP_NAME, TAG_ANY);
468  if (!vp) {
469  vp = radius_pair_create(request->packet, &request->packet->vps, PW_HUNTGROUP_NAME, 0);
470  fr_pair_value_strcpy(vp, i->name);
471  }
472  r = RLM_MODULE_OK;
473  }
474  break;
475  }
476 
477  return r;
478 }
479 
480 /*
481  * If the NAS wasn't smart enought to add a NAS-IP-Address
482  * to the request, then add it ourselves.
483  */
484 static int add_nas_attr(REQUEST *request)
485 {
486  VALUE_PAIR *nas;
487 
488  switch (request->packet->src_ipaddr.af) {
489  case AF_INET:
490  nas = fr_pair_find_by_num(request->packet->vps, 0, PW_NAS_IP_ADDRESS, TAG_ANY);
491  if (!nas) {
492  nas = radius_pair_create(request->packet, &request->packet->vps, PW_NAS_IP_ADDRESS, 0);
493  nas->vp_ipaddr = request->packet->src_ipaddr.ipaddr.ip4addr.s_addr;
494  }
495  break;
496 
497  case AF_INET6:
498  nas = fr_pair_find_by_num(request->packet->vps, 0, PW_NAS_IPV6_ADDRESS, TAG_ANY);
499  if (!nas) {
500  nas = radius_pair_create(request->packet, &request->packet->vps, PW_NAS_IPV6_ADDRESS, 0);
501  memcpy(&nas->vp_ipv6addr, &request->packet->src_ipaddr.ipaddr,
502  sizeof(request->packet->src_ipaddr.ipaddr));
503  }
504  break;
505 
506  default:
507  ERROR("Unknown address family for packet");
508  return -1;
509  }
510 
511  return 0;
512 }
513 
514 
515 /*
516  * Initialize.
517  */
518 static int mod_instantiate(UNUSED CONF_SECTION *conf, void *instance)
519 {
520  int ret;
521  rlm_preprocess_t *inst = instance;
522 
523  /*
524  * Read the huntgroups file.
525  */
526  if (inst->huntgroup_file) {
527  ret = pairlist_read(inst, inst->huntgroup_file, &(inst->huntgroups), 0);
528  if (ret < 0) {
529  ERROR("rlm_preprocess: Error reading %s", inst->huntgroup_file);
530 
531  return -1;
532  }
533  }
534 
535  /*
536  * Read the hints file.
537  */
538  if (inst->hints_file) {
539  ret = pairlist_read(inst, inst->hints_file, &(inst->hints), 0);
540  if (ret < 0) {
541  ERROR("rlm_preprocess: Error reading %s", inst->hints_file);
542 
543  return -1;
544  }
545  }
546 
547  return 0;
548 }
549 
550 /*
551  * Preprocess a request.
552  */
553 static rlm_rcode_t CC_HINT(nonnull) mod_authorize(void *instance, REQUEST *request)
554 {
555  int r;
556  rlm_preprocess_t *inst = instance;
557 
558  VALUE_PAIR *vp;
559 
560  /*
561  * Mangle the username, to get rid of stupid implementation
562  * bugs.
563  */
564  rad_mangle(inst, request);
565 
566  if (inst->with_ascend_hack) {
567  /*
568  * If we're using Ascend systems, hack the NAS-Port-Id
569  * in place, to go from Ascend's weird values to something
570  * approaching rationality.
571  */
572  ascend_nasport_hack(fr_pair_find_by_num(request->packet->vps, 0, PW_NAS_PORT, TAG_ANY),
574  }
575 
576  if (inst->with_cisco_vsa_hack) {
577  /*
578  * We need to run this hack because the h323-conf-id
579  * attribute should be used.
580  */
581  cisco_vsa_hack(request);
582  }
583 
584  if (inst->with_alvarion_vsa_hack) {
585  /*
586  * We need to run this hack because the Alvarion
587  * people are crazy.
588  */
589  alvarion_vsa_hack(request->packet->vps);
590  }
591 
592  if (inst->with_cablelabs_vsa_hack) {
593  /*
594  * We need to run this hack because the Cablelabs
595  * people are crazy.
596  */
597  cablelabs_vsa_hack(&request->packet->vps);
598  }
599 
600  /*
601  * Add an event timestamp. Means Event-Timestamp can be used
602  * consistently instead of one letter expansions.
603  */
604  vp = fr_pair_find_by_num(request->packet->vps, 0, PW_EVENT_TIMESTAMP, TAG_ANY);
605  if (!vp) {
606  vp = radius_pair_create(request->packet, &request->packet->vps, PW_EVENT_TIMESTAMP, 0);
607  vp->vp_date = request->packet->timestamp.tv_sec;
608  }
609 
610  /*
611  * Note that we add the Request-Src-IP-Address to the request
612  * structure BEFORE checking huntgroup access. This allows
613  * the Request-Src-IP-Address to be used for huntgroup
614  * comparisons.
615  */
616  if (add_nas_attr(request) < 0) {
617  return RLM_MODULE_FAIL;
618  }
619 
620  hints_setup(inst->hints, request);
621 
622  /*
623  * If there is a PW_CHAP_PASSWORD attribute but there
624  * is PW_CHAP_CHALLENGE we need to add it so that other
625  * modules can use it as a normal attribute.
626  */
627  if (fr_pair_find_by_num(request->packet->vps, 0, PW_CHAP_PASSWORD, TAG_ANY) &&
628  fr_pair_find_by_num(request->packet->vps, 0, PW_CHAP_CHALLENGE, TAG_ANY) == NULL) {
629  vp = radius_pair_create(request->packet, &request->packet->vps, PW_CHAP_CHALLENGE, 0);
630  fr_pair_value_memcpy(vp, request->packet->vector, AUTH_VECTOR_LEN);
631  }
632 
633  if ((r = huntgroup_access(request, inst->huntgroups)) != RLM_MODULE_OK) {
634  char buf[1024];
635  RIDEBUG("No huntgroup access: [%s] (%s)",
636  request->username ? request->username->vp_strvalue : "<NO User-Name>",
637  auth_name(buf, sizeof(buf), request, 1));
638 
639  return r;
640  }
641 
642  return RLM_MODULE_OK; /* Meaning: try next authorization module */
643 }
644 
645 /*
646  * Preprocess a request before accounting
647  */
648 static rlm_rcode_t CC_HINT(nonnull) mod_preaccounting(void *instance, REQUEST *request)
649 {
650  int r;
651  VALUE_PAIR *vp;
652  rlm_preprocess_t *inst = instance;
653 
654  /*
655  * Ensure that we have the SAME user name for both
656  * authentication && accounting.
657  */
658  rad_mangle(inst, request);
659 
660  if (inst->with_cisco_vsa_hack) {
661  /*
662  * We need to run this hack because the h323-conf-id
663  * attribute should be used.
664  */
665  cisco_vsa_hack(request);
666  }
667 
668  if (inst->with_alvarion_vsa_hack) {
669  /*
670  * We need to run this hack because the Alvarion
671  * people are crazy.
672  */
673  alvarion_vsa_hack(request->packet->vps);
674  }
675 
676  if (inst->with_cablelabs_vsa_hack) {
677  /*
678  * We need to run this hack because the Cablelabs
679  * people are crazy.
680  */
681  cablelabs_vsa_hack(&request->packet->vps);
682  }
683 
684  /*
685  * Ensure that we log the NAS IP Address in the packet.
686  */
687  if (add_nas_attr(request) < 0) {
688  return RLM_MODULE_FAIL;
689  }
690 
691  hints_setup(inst->hints, request);
692 
693  /*
694  * Add an event timestamp. This means that the rest of
695  * the server can use it, rather than various error-prone
696  * manual calculations.
697  */
698  vp = fr_pair_find_by_num(request->packet->vps, 0, PW_EVENT_TIMESTAMP, TAG_ANY);
699  if (!vp) {
700  VALUE_PAIR *delay;
701 
702  vp = radius_pair_create(request->packet, &request->packet->vps, PW_EVENT_TIMESTAMP, 0);
703  vp->vp_date = request->packet->timestamp.tv_sec;
704 
705  delay = fr_pair_find_by_num(request->packet->vps, 0, PW_ACCT_DELAY_TIME, TAG_ANY);
706  if (delay) {
707  if ((delay->vp_integer >= vp->vp_date) || (delay->vp_integer == UINT32_MAX)) {
708  RWARN("Ignoring invalid Acct-Delay-time of %u seconds", delay->vp_integer);
709  } else {
710  vp->vp_date -= delay->vp_integer;
711  }
712  }
713  }
714 
715  if ((r = huntgroup_access(request, inst->huntgroups)) != RLM_MODULE_OK) {
716  char buf[1024];
717  RIDEBUG("No huntgroup access: [%s] (%s)",
718  request->username ? request->username->vp_strvalue : "<NO User-Name>",
719  auth_name(buf, sizeof(buf), request, 1));
720  return r;
721  }
722 
723  return r;
724 }
725 
726 /* globally exported name */
727 extern module_t rlm_preprocess;
728 module_t rlm_preprocess = {
730  .name = "preprocess",
731  .inst_size = sizeof(rlm_preprocess_t),
732  .config = module_config,
733  .instantiate = mod_instantiate,
734  .methods = {
736  [MOD_PREACCT] = mod_preaccounting
737  },
738 };
739 
void fr_pair_list_free(VALUE_PAIR **)
Free memory used by a valuepair list.
Definition: pair.c:544
#define PW_TYPE_FILE_INPUT
File matching value must exist, and must be readable.
Definition: conffile.h:204
void radius_pairmove(REQUEST *request, VALUE_PAIR **to, VALUE_PAIR *from, bool do_xlat) CC_HINT(nonnull)
Definition: evaluate.c:774
uint8_t mm[2]
uint16_t version
char const * name
Definition: tmpl.h:120
The module is OK, continue.
Definition: radiusd.h:91
static int mod_instantiate(UNUSED CONF_SECTION *conf, void *instance)
VALUE_PAIR * check
Definition: tmpl.h:121
Metadata exported by the module.
Definition: modules.h:134
Dictionary attribute.
Definition: dict.h:77
PAIR_LIST * hints
#define RWARN(fmt,...)
Definition: log.h:206
fr_ipaddr_t src_ipaddr
Src IP address of packet.
Definition: libradius.h:149
static char const * name
static rlm_rcode_t CC_HINT(nonnull)
int paircompare(REQUEST *request, VALUE_PAIR *req_list, VALUE_PAIR *check, VALUE_PAIR **rep_list)
Compare two pair lists except for the password information.
Definition: pair.c:479
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
static rlm_rcode_t mod_authorize(void *instance, REQUEST *request)
Handle authorization requests using Couchbase document data.
static int hints_setup(PAIR_LIST *hints, REQUEST *request)
char * auth_name(char *buf, size_t buflen, REQUEST *request, bool do_cli)
Definition: auth.c:37
#define UNUSED
Definition: libradius.h:134
#define RLM_MODULE_INIT
Definition: modules.h:86
#define PW_FRAMED_USER
Definition: radius.h:174
VALUE_PAIR * vps
Result of decoding the packet into VALUE_PAIRs.
Definition: libradius.h:162
#define CONF_PARSER_TERMINATOR
Definition: conffile.h:289
#define pair_make_request(_a, _b, _c)
Definition: radiusd.h:545
VALUE_PAIR * fr_cursor_init(vp_cursor_t *cursor, VALUE_PAIR *const *node)
Setup a cursor to iterate over attribute pairs.
Definition: cursor.c:60
cl_timezone_t timezone
uint8_t element_id[8]
uint8_t ss[2]
#define inst
Definition: token.h:46
struct rlm_preprocess_t rlm_preprocess_t
uint8_t priority
uint32_t sequence_number
Defines a CONF_PAIR to C data type mapping.
Definition: conffile.h:267
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
Definition: pair.h:144
uint8_t event_object
PAIR_LIST * huntgroups
uint16_t message_type
int af
Address family.
Definition: inet.h:42
char const * huntgroup_file
VALUE_PAIR * fr_pair_list_copy(TALLOC_CTX *ctx, VALUE_PAIR *from)
Copy a pairlist.
Definition: pair.c:1394
static void alvarion_vsa_hack(VALUE_PAIR *vp)
struct pair_list * next
Definition: tmpl.h:124
#define AUTH_VECTOR_LEN
Definition: libradius.h:118
void fr_pair_value_strcpy(VALUE_PAIR *vp, char const *src)
Copy data into an "string" data type.
Definition: pair.c:2013
static void rad_mangle(rlm_preprocess_t *inst, REQUEST *request)
uint8_t hh[2]
unsigned int attr
Attribute number.
Definition: dict.h:79
Immediately reject the request.
Definition: radiusd.h:89
union fr_ipaddr_t::@1 ipaddr
bool with_specialix_jetstream_hack
uint32_t timestamp
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
uint8_t element_id[8]
A truth value.
Definition: radius.h:56
FR_TOKEN op
Operator to use when moving or inserting valuepair into a list.
Definition: pair.h:118
32 Bit unsigned integer.
Definition: radius.h:34
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
static rs_t * conf
Definition: radsniff.c:46
cl_timezone_t time_zone
void fr_pair_delete_by_num(VALUE_PAIR **head, unsigned int vendor, unsigned int attr, int8_t tag)
Delete matching pairs.
Definition: pair.c:797
uint32_t event_counter
Module succeeded without doing anything.
Definition: radiusd.h:96
static void ascend_nasport_hack(VALUE_PAIR *nas_port, int channels_per_line)
uint16_t element_type
#define RDEBUG2(fmt,...)
Definition: log.h:244
#define RIDEBUG(fmt,...)
Definition: log.h:248
uint8_t status[4]
uint64_t magic
Used to validate module struct.
Definition: modules.h:135
Module failed, don't reply.
Definition: radiusd.h:90
#define TAG_ANY
Definition: pair.h:191
int lineno
Definition: tmpl.h:123
static void cisco_vsa_hack(REQUEST *request)
struct cl_em_hdr_t cl_em_hdr_t
#define FR_CONF_OFFSET(_n, _t, _s, _f)
Definition: conffile.h:168
FR_TOKEN gettoken(char const **ptr, char *buf, int buflen, bool unescape)
Definition: token.c:405
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
Definition: cursor.c:263
RADIUS_PACKET * packet
Incoming request.
Definition: radiusd.h:221
static void cablelabs_vsa_hack(VALUE_PAIR **list)
bool with_cablelabs_vsa_hack
module_t rlm_preprocess
static int fall_through(VALUE_PAIR *vp)
2 methods index for preacct section.
Definition: modules.h:43
struct cl_timezone_t cl_timezone_t
VALUE_PAIR * fr_pair_copy(TALLOC_CTX *ctx, VALUE_PAIR const *vp)
Copy a single valuepair.
Definition: pair.c:129
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
static int add_nas_attr(REQUEST *request)
uint16_t attr_count
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
static const CONF_PARSER module_config[]
#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
#define RWDEBUG(fmt,...)
Definition: log.h:251
uint8_t event_time[18]
PW_TYPE type
Value type.
Definition: dict.h:80
1 methods index for authorize section.
Definition: modules.h:42
#define RCSID(id)
Definition: build.h:135
static int r
Definition: rbmonkey.c:66
uint32_t ascend_channels_per_line
OK (pairs modified).
Definition: radiusd.h:97
char const * hints_file
VALUE_PAIR * reply
Definition: tmpl.h:122
int pairlist_read(TALLOC_CTX *ctx, char const *file, PAIR_LIST **list, int complain)
Definition: files.c:80
static int huntgroup_access(REQUEST *request, PAIR_LIST *huntgroups)
#define ERROR(fmt,...)
Definition: log.h:145
cl_bcid_t bcid
void fr_pair_value_memcpy(VALUE_PAIR *vp, uint8_t const *src, size_t len)
Copy data into an "octets" data type.
Definition: pair.c:1905
struct cl_bcid_t cl_bcid_t
static int hunt_paircmp(REQUEST *req, VALUE_PAIR *request, VALUE_PAIR *check)
fr_dict_attr_t const * fr_dict_attr_by_name(fr_dict_t *dict, char const *attr)
Locate a fr_dict_attr_t by its name.
Definition: dict.c:3493