All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
rlm_radutmp.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: 9f45f1083bf9620144c4c7be021e531a395d106c $
19  * @file rlm_radutmp.c
20  * @brief Tracks sessions.
21  *
22  * @copyright 2000-2013 The FreeRADIUS server project
23  */
24 RCSID("$Id: 9f45f1083bf9620144c4c7be021e531a395d106c $")
25 
26 #include <freeradius-devel/radiusd.h>
27 #include <freeradius-devel/radutmp.h>
28 #include <freeradius-devel/modules.h>
29 #include <freeradius-devel/rad_assert.h>
30 
31 #include <fcntl.h>
32 
33 #include "config.h"
34 
35 #define LOCK_LEN sizeof(struct radutmp)
36 
37 static char const porttypes[] = "ASITX";
38 
39 /*
40  * used for caching radutmp lookups in the accounting component. The
41  * session (checksimul) component doesn't use it, but probably should.
42  */
43 typedef struct nas_port {
44  uint32_t nasaddr;
45  uint16_t port;
46  off_t offset;
47  struct nas_port *next;
48 } NAS_PORT;
49 
50 typedef struct rlm_radutmp_t {
52  char const *filename;
53  char const *username;
55  bool check_nas;
56  uint32_t permission;
59 
60 static const CONF_PARSER module_config[] = {
61  { FR_CONF_OFFSET("filename", PW_TYPE_FILE_OUTPUT | PW_TYPE_REQUIRED, rlm_radutmp_t, filename), .dflt = RADUTMP },
62  { FR_CONF_OFFSET("username", PW_TYPE_STRING | PW_TYPE_REQUIRED | PW_TYPE_XLAT, rlm_radutmp_t, username), .dflt = "%{User-Name}" },
63  { FR_CONF_OFFSET("case_sensitive", PW_TYPE_BOOLEAN, rlm_radutmp_t, case_sensitive), .dflt = "yes" },
64  { FR_CONF_OFFSET("check_with_nas", PW_TYPE_BOOLEAN, rlm_radutmp_t, check_nas), .dflt = "yes" },
65  { FR_CONF_OFFSET("permissions", PW_TYPE_INTEGER, rlm_radutmp_t, permission), .dflt = "0644" },
66  { FR_CONF_OFFSET("caller_id", PW_TYPE_BOOLEAN, rlm_radutmp_t, caller_id_ok), .dflt = "no" },
68 };
69 
70 
71 #ifdef WITH_ACCOUNTING
72 /*
73  * Zap all users on a NAS from the radutmp file.
74  */
75 static rlm_rcode_t radutmp_zap(REQUEST *request, char const *filename, uint32_t nasaddr, time_t t)
76 {
77  struct radutmp u;
78  int fd;
79 
80  if (t == 0) time(&t);
81 
82  fd = open(filename, O_RDWR);
83  if (fd < 0) {
84  REDEBUG("Error accessing file %s: %s", filename, fr_syserror(errno));
85  return RLM_MODULE_FAIL;
86  }
87 
88  /*
89  * Lock the utmp file, prefer lockf() over flock().
90  */
91  if (rad_lockfd(fd, LOCK_LEN) < 0) {
92  REDEBUG("Failed to acquire lock on file %s: %s", filename, fr_syserror(errno));
93  close(fd);
94  return RLM_MODULE_FAIL;
95  }
96 
97  /*
98  * Find the entry for this NAS / portno combination.
99  */
100  while (read(fd, &u, sizeof(u)) == sizeof(u)) {
101  if ((nasaddr != 0 && nasaddr != u.nas_address) || u.type != P_LOGIN) {
102  continue;
103  }
104  /*
105  * Match. Zap it.
106  */
107  if (lseek(fd, -(off_t)sizeof(u), SEEK_CUR) < 0) {
108  REDEBUG("radutmp_zap: negative lseek!");
109  lseek(fd, (off_t)0, SEEK_SET);
110  }
111  u.type = P_IDLE;
112  u.time = t;
113 
114  if (write(fd, &u, sizeof(u)) < 0) {
115  REDEBUG("Failed writing: %s", fr_syserror(errno));
116 
117  close(fd);
118  return RLM_MODULE_FAIL;
119  }
120  }
121  close(fd); /* and implicitely release the locks */
122 
123  return RLM_MODULE_OK;
124 }
125 
126 /*
127  * Lookup a NAS_PORT in the nas_port_list
128  */
129 static NAS_PORT *nas_port_find(NAS_PORT *nas_port_list, uint32_t nasaddr, uint16_t port)
130 {
131  NAS_PORT *cl;
132 
133  for(cl = nas_port_list; cl; cl = cl->next) {
134  if (nasaddr == cl->nasaddr &&
135  port == cl->port)
136  break;
137  }
138 
139  return cl;
140 }
141 
142 
143 /*
144  * Store logins in the RADIUS utmp file.
145  */
146 static rlm_rcode_t CC_HINT(nonnull) mod_accounting(void *instance, REQUEST *request)
147 {
148  rlm_rcode_t rcode = RLM_MODULE_OK;
149  struct radutmp ut, u;
150  vp_cursor_t cursor;
151  VALUE_PAIR *vp;
152  int status = -1;
153  int protocol = -1;
154  time_t t;
155  int fd = -1;
156  bool port_seen = false;
157  int off;
158  rlm_radutmp_t *inst = instance;
159  char ip_name[INET_ADDRSTRLEN]; /* 255.255.255.255 */
160  char const *nas;
161  NAS_PORT *cache;
162  int r;
163 
164  char *filename = NULL;
165  char *expanded = NULL;
166 
167  if (request->packet->src_ipaddr.af != AF_INET) {
168  DEBUG("rlm_radutmp: IPv6 not supported!");
169  return RLM_MODULE_NOOP;
170  }
171 
172  /*
173  * Which type is this.
174  */
175  if ((vp = fr_pair_find_by_num(request->packet->vps, 0, PW_ACCT_STATUS_TYPE, TAG_ANY)) == NULL) {
176  RDEBUG("No Accounting-Status-Type record");
177  return RLM_MODULE_NOOP;
178  }
179  status = vp->vp_integer;
180 
181  /*
182  * Look for weird reboot packets.
183  *
184  * ComOS (up to and including 3.5.1b20) does not send
185  * standard PW_STATUS_ACCOUNTING_XXX messages.
186  *
187  * Check for: o no Acct-Session-Time, or time of 0
188  * o Acct-Session-Id of "00000000".
189  *
190  * We could also check for NAS-Port, that attribute
191  * should NOT be present (but we don't right now).
192  */
193  if ((status != PW_STATUS_ACCOUNTING_ON) &&
194  (status != PW_STATUS_ACCOUNTING_OFF)) do {
195  int check1 = 0;
196  int check2 = 0;
197 
198  if ((vp = fr_pair_find_by_num(request->packet->vps, 0, PW_ACCT_SESSION_TIME, TAG_ANY))
199  == NULL || vp->vp_date == 0)
200  check1 = 1;
201  if ((vp = fr_pair_find_by_num(request->packet->vps, 0, PW_ACCT_SESSION_ID, TAG_ANY))
202  != NULL && vp->vp_length == 8 &&
203  memcmp(vp->vp_strvalue, "00000000", 8) == 0)
204  check2 = 1;
205  if (check1 == 0 || check2 == 0) {
206  break;
207  }
208  INFO("rlm_radutmp: converting reboot records");
209  if (status == PW_STATUS_STOP)
210  status = PW_STATUS_ACCOUNTING_OFF;
211  if (status == PW_STATUS_START)
212  status = PW_STATUS_ACCOUNTING_ON;
213  } while(0);
214 
215  time(&t);
216  memset(&ut, 0, sizeof(ut));
217  ut.porttype = 'A';
218  ut.nas_address = htonl(INADDR_NONE);
219 
220  /*
221  * First, find the interesting attributes.
222  */
223  for (vp = fr_cursor_init(&cursor, &request->packet->vps);
224  vp;
225  vp = fr_cursor_next(&cursor)) {
226  if (!vp->da->vendor) switch (vp->da->attr) {
227  case PW_LOGIN_IP_HOST:
228  case PW_FRAMED_IP_ADDRESS:
229  ut.framed_address = vp->vp_ipaddr;
230  break;
231 
232  case PW_FRAMED_PROTOCOL:
233  protocol = vp->vp_integer;
234  break;
235 
236  case PW_NAS_IP_ADDRESS:
237  ut.nas_address = vp->vp_ipaddr;
238  break;
239 
240  case PW_NAS_PORT:
241  ut.nas_port = vp->vp_integer;
242  port_seen = true;
243  break;
244 
245  case PW_ACCT_DELAY_TIME:
246  ut.delay = vp->vp_integer;
247  break;
248 
249  case PW_ACCT_SESSION_ID:
250  /*
251  * If length > 8, only store the
252  * last 8 bytes.
253  */
254  off = vp->vp_length - sizeof(ut.session_id);
255  /*
256  * Ascend is br0ken - it adds a \0
257  * to the end of any string.
258  * Compensate.
259  */
260  if (vp->vp_length > 0 &&
261  vp->vp_strvalue[vp->vp_length - 1] == 0)
262  off--;
263  if (off < 0) off = 0;
264  memcpy(ut.session_id, vp->vp_strvalue + off,
265  sizeof(ut.session_id));
266  break;
267 
268  case PW_NAS_PORT_TYPE:
269  if (vp->vp_integer <= 4)
270  ut.porttype = porttypes[vp->vp_integer];
271  break;
272 
273  case PW_CALLING_STATION_ID:
274  if (inst->caller_id_ok) strlcpy(ut.caller_id, vp->vp_strvalue, sizeof(ut.caller_id));
275  break;
276  }
277  }
278 
279  /*
280  * If we didn't find out the NAS address, use the
281  * originator's IP address.
282  */
283  if (ut.nas_address == htonl(INADDR_NONE)) {
284  ut.nas_address = request->packet->src_ipaddr.ipaddr.ip4addr.s_addr;
285  nas = request->client->shortname;
286 
287  } else if (request->packet->src_ipaddr.ipaddr.ip4addr.s_addr == ut.nas_address) { /* might be a client, might not be. */
288  nas = request->client->shortname;
289 
290  /*
291  * The NAS isn't a client, it's behind
292  * a proxy server. In that case, just
293  * get the IP address.
294  */
295  } else {
296  nas = inet_ntop(AF_INET, &ut.nas_address, ip_name, sizeof(ip_name));
297  }
298 
299  /*
300  * Set the protocol field.
301  */
302  if (protocol == PW_PPP) {
303  ut.proto = 'P';
304  } else if (protocol == PW_SLIP) {
305  ut.proto = 'S';
306  } else {
307  ut.proto = 'T';
308  }
309 
310  ut.time = t - ut.delay;
311 
312  /*
313  * Get the utmp filename, via xlat.
314  */
315  filename = NULL;
316  if (radius_axlat(&filename, request, inst->filename, NULL, NULL) < 0) {
317  return RLM_MODULE_FAIL;
318  }
319 
320  /*
321  * See if this was a reboot.
322  *
323  * Hmm... we may not want to zap all of the users when the NAS comes up, because of issues with receiving
324  * UDP packets out of order.
325  */
326  if (status == PW_STATUS_ACCOUNTING_ON && (ut.nas_address != htonl(INADDR_NONE))) {
327  RIDEBUG("NAS %s restarted (Accounting-On packet seen)", nas);
328  rcode = radutmp_zap(request, filename, ut.nas_address, ut.time);
329 
330  goto finish;
331  }
332 
333  if (status == PW_STATUS_ACCOUNTING_OFF && (ut.nas_address != htonl(INADDR_NONE))) {
334  RIDEBUG("NAS %s rebooted (Accounting-Off packet seen)", nas);
335  rcode = radutmp_zap(request, filename, ut.nas_address, ut.time);
336 
337  goto finish;
338  }
339 
340  /*
341  * If we don't know this type of entry pretend we succeeded.
342  */
343  if (status != PW_STATUS_START && status != PW_STATUS_STOP && status != PW_STATUS_ALIVE) {
344  REDEBUG("NAS %s port %u unknown packet type %d)", nas, ut.nas_port, status);
345  rcode = RLM_MODULE_NOOP;
346 
347  goto finish;
348  }
349 
350  /*
351  * Translate the User-Name attribute, or whatever else they told us to use.
352  */
353  if (radius_axlat(&expanded, request, inst->username, NULL, NULL) < 0) {
354  rcode = RLM_MODULE_FAIL;
355 
356  goto finish;
357  }
358  strlcpy(ut.login, expanded, RUT_NAMESIZE);
359  TALLOC_FREE(expanded);
360 
361  /*
362  * Perhaps we don't want to store this record into
363  * radutmp. We skip records:
364  *
365  * - without a NAS-Port (telnet / tcp access)
366  * - with the username "!root" (console admin login)
367  */
368  if (!port_seen) {
369  RWDEBUG2("No NAS-Port seen. Cannot do anything. Checkrad will probably not work!");
370  rcode = RLM_MODULE_NOOP;
371 
372  goto finish;
373  }
374 
375  if (strncmp(ut.login, "!root", RUT_NAMESIZE) == 0) {
376  RDEBUG2("Not recording administrative user");
377  rcode = RLM_MODULE_NOOP;
378 
379  goto finish;
380  }
381 
382  /*
383  * Enter into the radutmp file.
384  */
385  fd = open(filename, O_RDWR|O_CREAT, inst->permission);
386  if (fd < 0) {
387  REDEBUG("Error accessing file %s: %s", filename, fr_syserror(errno));
388  rcode = RLM_MODULE_FAIL;
389 
390  goto finish;
391  }
392 
393  /*
394  * Lock the utmp file, prefer lockf() over flock().
395  */
396  if (rad_lockfd(fd, LOCK_LEN) < 0) {
397  REDEBUG("Error acquiring lock on %s: %s", filename, fr_syserror(errno));
398  rcode = RLM_MODULE_FAIL;
399 
400  goto finish;
401  }
402 
403  /*
404  * Find the entry for this NAS / portno combination.
405  */
406  if ((cache = nas_port_find(inst->nas_port_list, ut.nas_address, ut.nas_port)) != NULL) {
407  if (lseek(fd, (off_t)cache->offset, SEEK_SET) < 0) {
408  rcode = RLM_MODULE_FAIL;
409  goto finish;
410  }
411  }
412 
413  r = 0;
414  off = 0;
415  while (read(fd, &u, sizeof(u)) == sizeof(u)) {
416  off += sizeof(u);
417  if ((u.nas_address != ut.nas_address) || (u.nas_port != ut.nas_port)) {
418  continue;
419  }
420 
421  /*
422  * Don't compare stop records to unused entries.
423  */
424  if (status == PW_STATUS_STOP && u.type == P_IDLE) {
425  continue;
426  }
427 
428  if ((status == PW_STATUS_STOP) && strncmp(ut.session_id, u.session_id, sizeof(u.session_id)) != 0) {
429  /*
430  * Don't complain if this is not a
431  * login record (some clients can
432  * send _only_ logout records).
433  */
434  if (u.type == P_LOGIN) {
435  RWDEBUG("Logout entry for NAS %s port %u has wrong ID", nas, u.nas_port);
436  }
437 
438  r = -1;
439  break;
440  }
441 
442  if ((status == PW_STATUS_START) && strncmp(ut.session_id, u.session_id, sizeof(u.session_id)) == 0 &&
443  u.time >= ut.time) {
444  if (u.type == P_LOGIN) {
445  INFO("rlm_radutmp: Login entry for NAS %s port %u duplicate",
446  nas, u.nas_port);
447  r = -1;
448  break;
449  }
450 
451  RWDEBUG("Login entry for NAS %s port %u wrong order", nas, u.nas_port);
452  r = -1;
453  break;
454  }
455 
456  /*
457  * FIXME: the ALIVE record could need some more checking, but anyway I'd
458  * rather rewrite this mess -- miquels.
459  */
460  if ((status == PW_STATUS_ALIVE) && strncmp(ut.session_id, u.session_id, sizeof(u.session_id)) == 0 &&
461  u.type == P_LOGIN) {
462  /*
463  * Keep the original login time.
464  */
465  ut.time = u.time;
466  }
467 
468  if (lseek(fd, -(off_t)sizeof(u), SEEK_CUR) < 0) {
469  RWDEBUG("negative lseek!");
470  lseek(fd, (off_t)0, SEEK_SET);
471  off = 0;
472  } else {
473  off -= sizeof(u);
474  }
475 
476  r = 1;
477  break;
478  } /* read the file until we find a match */
479 
480  /*
481  * Found the entry, do start/update it with
482  * the information from the packet.
483  */
484  if ((r >= 0) && (status == PW_STATUS_START || status == PW_STATUS_ALIVE)) {
485  /*
486  * Remember where the entry was, because it's
487  * easier than searching through the entire file.
488  */
489  if (!cache) {
490  cache = talloc_zero(NULL, NAS_PORT);
491  if (cache) {
492  cache->nasaddr = ut.nas_address;
493  cache->port = ut.nas_port;
494  cache->offset = off;
495  cache->next = inst->nas_port_list;
496  inst->nas_port_list = cache;
497  }
498  }
499 
500  ut.type = P_LOGIN;
501  if (write(fd, &ut, sizeof(u)) < 0) {
502  REDEBUG("Failed writing: %s", fr_syserror(errno));
503 
504  rcode = RLM_MODULE_FAIL;
505  goto finish;
506  }
507  }
508 
509  /*
510  * The user has logged off, delete the entry by
511  * re-writing it in place.
512  */
513  if (status == PW_STATUS_STOP) {
514  if (r > 0) {
515  u.type = P_IDLE;
516  u.time = ut.time;
517  u.delay = ut.delay;
518  if (write(fd, &u, sizeof(u)) < 0) {
519  REDEBUG("Failed writing: %s", fr_syserror(errno));
520 
521  rcode = RLM_MODULE_FAIL;
522  goto finish;
523  }
524  } else if (r == 0) {
525  RWDEBUG("Logout for NAS %s port %u, but no Login record", nas, ut.nas_port);
526  }
527  }
528 
529  finish:
530 
531  talloc_free(filename);
532 
533  if (fd > -1) {
534  close(fd); /* and implicitely release the locks */
535  }
536 
537  return rcode;
538 }
539 #endif
540 
541 #ifdef WITH_SESSION_MGMT
542 /*
543  * See if a user is already logged in. Sets request->simul_count to the
544  * current session count for this user and sets request->simul_mpp to 2
545  * if it looks like a multilink attempt based on the requested IP
546  * address, otherwise leaves request->simul_mpp alone.
547  *
548  * Check twice. If on the first pass the user exceeds his
549  * max. number of logins, do a second pass and validate all
550  * logins by querying the terminal server (using eg. SNMP).
551  */
552 static rlm_rcode_t CC_HINT(nonnull) mod_checksimul(void *instance, REQUEST *request)
553 {
554  rlm_rcode_t rcode = RLM_MODULE_OK;
555  struct radutmp u;
556  int fd = -1;
557  VALUE_PAIR *vp;
558  uint32_t ipno = 0;
559  char const *call_num = NULL;
560  rlm_radutmp_t *inst = instance;
561 
562  char *expanded = NULL;
563  ssize_t len;
564 
565  /*
566  * Get the filename, via xlat.
567  */
568  if (radius_axlat(&expanded, request, inst->filename, NULL, NULL) < 0) {
569  return RLM_MODULE_FAIL;
570  }
571 
572  fd = open(expanded, O_RDWR);
573  if (fd < 0) {
574  /*
575  * If the file doesn't exist, then no users
576  * are logged in.
577  */
578  if (errno == ENOENT) {
579  request->simul_count=0;
580  return RLM_MODULE_OK;
581  }
582 
583  /*
584  * Error accessing the file.
585  */
586  ERROR("rlm_radumtp: Error accessing file %s: %s", expanded, fr_syserror(errno));
587 
588  rcode = RLM_MODULE_FAIL;
589 
590  goto finish;
591  }
592 
593  TALLOC_FREE(expanded);
594 
595  len = radius_axlat(&expanded, request, inst->username, NULL, NULL);
596  if (len < 0) {
597  rcode = RLM_MODULE_FAIL;
598 
599  goto finish;
600  }
601 
602  if (!len) {
603  rcode = RLM_MODULE_NOOP;
604 
605  goto finish;
606  }
607 
608  /*
609  * WTF? This is probably wrong... we probably want to
610  * be able to check users across multiple session accounting
611  * methods.
612  */
613  request->simul_count = 0;
614 
615  /*
616  * Loop over utmp, counting how many people MAY be logged in.
617  */
618  while (read(fd, &u, sizeof(u)) == sizeof(u)) {
619  if (((strncmp(expanded, u.login, RUT_NAMESIZE) == 0) ||
620  (!inst->case_sensitive && (strncasecmp(expanded, u.login, RUT_NAMESIZE) == 0))) &&
621  (u.type == P_LOGIN)) {
622  ++request->simul_count;
623  }
624  }
625 
626  /*
627  * The number of users logged in is OK,
628  * OR, we've been told to not check the NAS.
629  */
630  if ((request->simul_count < request->simul_max) || !inst->check_nas) {
631  rcode = RLM_MODULE_OK;
632 
633  goto finish;
634  }
635  lseek(fd, (off_t)0, SEEK_SET);
636 
637  /*
638  * Setup some stuff, like for MPP detection.
639  */
640  if ((vp = fr_pair_find_by_num(request->packet->vps, 0, PW_FRAMED_IP_ADDRESS, TAG_ANY)) != NULL) {
641  ipno = vp->vp_ipaddr;
642  }
643 
644  if ((vp = fr_pair_find_by_num(request->packet->vps, 0, PW_CALLING_STATION_ID, TAG_ANY)) != NULL) {
645  call_num = vp->vp_strvalue;
646  }
647 
648  /*
649  * lock the file while reading/writing.
650  */
651  rad_lockfd(fd, LOCK_LEN);
652 
653  /*
654  * FIXME: If we get a 'Start' for a user/nas/port which is
655  * listed, but for which we did NOT get a 'Stop', then
656  * it's not a duplicate session. This happens with
657  * static IP's like DSL.
658  */
659  request->simul_count = 0;
660  while (read(fd, &u, sizeof(u)) == sizeof(u)) {
661  if (((strncmp(expanded, u.login, RUT_NAMESIZE) == 0) || (!inst->case_sensitive &&
662  (strncasecmp(expanded, u.login, RUT_NAMESIZE) == 0))) && (u.type == P_LOGIN)) {
663  char session_id[sizeof(u.session_id) + 1];
664  char utmp_login[sizeof(u.login) + 1];
665 
666  /* Guarantee string is NULL terminated */
667  u.session_id[sizeof(u.session_id) - 1] = '\0';
668  strlcpy(session_id, u.session_id, sizeof(session_id));
669 
670  /*
671  * The login name MAY fill the whole field,
672  * and thus won't be zero-filled.
673  *
674  * Note that we take the user name from
675  * the utmp file, as that's the canonical
676  * form. The 'login' variable may contain
677  * a string which is an upper/lowercase
678  * version of u.login. When we call the
679  * routine to check the terminal server,
680  * the NAS may be case sensitive.
681  *
682  * e.g. We ask if "bob" is using a port,
683  * and the NAS says "no", because "BOB"
684  * is using the port.
685  */
686  memset(utmp_login, 0, sizeof(utmp_login));
687  memcpy(utmp_login, u.login, sizeof(u.login));
688 
689  /*
690  * rad_check_ts may take seconds
691  * to return, and we don't want
692  * to block everyone else while
693  * that's happening. */
694  rad_unlockfd(fd, LOCK_LEN);
695  rcode = rad_check_ts(u.nas_address, u.nas_port, utmp_login, session_id);
696  rad_lockfd(fd, LOCK_LEN);
697 
698  if (rcode == 0) {
699  /*
700  * Stale record - zap it.
701  */
702  session_zap(request, u.nas_address, u.nas_port, expanded, session_id,
703  u.framed_address, u.proto, 0);
704  }
705  else if (rcode == 1) {
706  /*
707  * User is still logged in.
708  */
709  ++request->simul_count;
710 
711  /*
712  * Does it look like a MPP attempt?
713  */
714  if (strchr("SCPA", u.proto) && ipno && u.framed_address == ipno) {
715  request->simul_mpp = 2;
716  } else if (strchr("SCPA", u.proto) && call_num && !strncmp(u.caller_id, call_num,16)) {
717  request->simul_mpp = 2;
718  }
719  } else {
720  RWDEBUG("Failed to check the terminal server for user '%s'.", utmp_login);
721  rcode = RLM_MODULE_FAIL;
722 
723  goto finish;
724  }
725  }
726  }
727  finish:
728 
729  talloc_free(expanded);
730 
731  if (fd > -1) {
732  close(fd); /* and implicitely release the locks */
733  }
734 
735  return rcode;
736 }
737 #endif
738 
739 /* globally exported name */
740 extern module_t rlm_radutmp;
741 module_t rlm_radutmp = {
743  .name = "radutmp",
745  .inst_size = sizeof(rlm_radutmp_t),
746  .config = module_config,
747  .methods = {
748 #ifdef WITH_ACCOUNTING
750 #endif
751 #ifdef WITH_SESSION_MGMT
753 #endif
754  },
755 };
756 
ssize_t ssize_t ssize_t radius_axlat(char **out, REQUEST *request, char const *fmt, xlat_escape_t escape, void *escape_ctx) CC_HINT(nonnull(1
int type
Definition: radutmp.h:64
char login[32]
Definition: radutmp.h:54
#define PW_PPP
Definition: radius.h:186
NAS_PORT * nas_port_list
Definition: rlm_radutmp.c:51
#define PW_SLIP
Definition: radius.h:187
int session_zap(REQUEST *request, uint32_t nasaddr, uint32_t nas_port, char const *user, char const *sessionid, uint32_t cliaddr, char proto, int session_time)
Definition: session.c:37
int rad_lockfd(int fd, int lock_len)
Definition: misc.c:141
static rlm_rcode_t mod_accounting(void *instance, REQUEST *request)
Write accounting data to Couchbase documents.
The module is OK, continue.
Definition: radiusd.h:91
Metadata exported by the module.
Definition: modules.h:134
#define RLM_TYPE_THREAD_UNSAFE
Module is not threadsafe.
Definition: modules.h:76
#define INFO(fmt,...)
Definition: log.h:143
#define RADUTMP
Definition: conf.h:12
#define RLM_MODULE_INIT
Definition: modules.h:86
#define CONF_PARSER_TERMINATOR
Definition: conffile.h:289
char const * inet_ntop(int af, void const *src, char *dst, size_t cnt)
Definition: missing.c:538
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
time_t delay
Definition: radutmp.h:63
#define PW_STATUS_ALIVE
Definition: radius.h:193
unsigned int nas_address
Definition: radutmp.h:59
#define PW_STATUS_START
Definition: radius.h:191
struct nas_port * next
Definition: rlm_radutmp.c:47
#define inst
char session_id[8]
Definition: radutmp.h:57
#define RLM_TYPE_HUP_SAFE
Will be restarted on HUP.
Definition: modules.h:79
unsigned int nas_port
Definition: radutmp.h:56
Defines a CONF_PAIR to C data type mapping.
Definition: conffile.h:267
char porttype
Definition: radutmp.h:65
Abstraction to allow iterating over different configurations of VALUE_PAIRs.
Definition: pair.h:144
static rlm_rcode_t radutmp_zap(REQUEST *request, char const *filename, uint32_t nasaddr, time_t t)
Definition: rlm_radutmp.c:75
uint32_t nasaddr
Definition: rlm_radutmp.c:44
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: log.c:238
unsigned int framed_address
Definition: radutmp.h:60
#define P_IDLE
Definition: radutmp.h:50
char caller_id[16]
Definition: radutmp.h:67
#define DEBUG(fmt,...)
Definition: log.h:175
time_t time
Definition: radutmp.h:62
bool caller_id_ok
Definition: rlm_radutmp.c:57
#define PW_TYPE_XLAT
string will be dynamically expanded.
Definition: conffile.h:207
4 methods index for checksimul section.
Definition: modules.h:45
unsigned int attr
Attribute number.
Definition: dict.h:79
uint32_t permission
Definition: rlm_radutmp.c:56
int proto
Definition: radutmp.h:61
3 methods index for accounting section.
Definition: modules.h:44
unsigned int vendor
Vendor that defines this attribute.
Definition: dict.h:78
bool case_sensitive
Definition: rlm_radutmp.c:54
Stores an attribute, a value and various bits of other data.
Definition: pair.h:112
static rlm_rcode_t mod_checksimul(void *instance, REQUEST *request)
Check if a given user is already logged in.
int rad_check_ts(uint32_t nasaddr, uint32_t nas_port, char const *user, char const *sessionid)
Definition: session.c:126
module_t rlm_radutmp
Definition: rlm_radutmp.c:741
A truth value.
Definition: radius.h:56
32 Bit unsigned integer.
Definition: radius.h:34
enum rlm_rcodes rlm_rcode_t
Return codes indicating the result of the module call.
#define RWDEBUG2(fmt,...)
Definition: log.h:252
off_t offset
Definition: rlm_radutmp.c:46
Module succeeded without doing anything.
Definition: radiusd.h:96
uint16_t port
Definition: rlm_radutmp.c:45
#define RDEBUG2(fmt,...)
Definition: log.h:244
#define RIDEBUG(fmt,...)
Definition: log.h:248
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
struct nas_port NAS_PORT
#define PW_TYPE_FILE_OUTPUT
File matching value must exist, and must be writeable.
Definition: conffile.h:205
#define FR_CONF_OFFSET(_n, _t, _s, _f)
Definition: conffile.h:168
#define P_LOGIN
Definition: radutmp.h:51
VALUE_PAIR * fr_cursor_next(vp_cursor_t *cursor)
Advanced the cursor to the next VALUE_PAIR.
Definition: cursor.c:263
int strncasecmp(char *s1, char *s2, int n)
Definition: missing.c:43
#define PW_STATUS_ACCOUNTING_ON
Definition: radius.h:194
int rad_unlockfd(int fd, int lock_len)
Definition: misc.c:191
#define LOCK_LEN
Definition: rlm_radutmp.c:35
#define REDEBUG(fmt,...)
Definition: log.h:254
struct rlm_radutmp_t rlm_radutmp_t
#define PW_TYPE_REQUIRED
Error out if no matching CONF_PAIR is found, and no dflt value is set.
Definition: conffile.h:200
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
#define PW_STATUS_STOP
Definition: radius.h:192
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:38
char const * username
Definition: rlm_radutmp.c:53
fr_dict_attr_t const * da
Dictionary attribute defines the attribute.
Definition: pair.h:113
static NAS_PORT * nas_port_find(NAS_PORT *nas_port_list, uint32_t nasaddr, uint16_t port)
Definition: rlm_radutmp.c:129
static rlm_rcode_t CC_HINT(nonnull)
Definition: rlm_radutmp.c:146
String of printable characters.
Definition: radius.h:33
#define RWDEBUG(fmt,...)
Definition: log.h:251
#define RCSID(id)
Definition: build.h:135
static int r
Definition: rbmonkey.c:66
char const * filename
Definition: rlm_radutmp.c:52
static const CONF_PARSER module_config[]
Definition: rlm_radutmp.c:60
#define PW_STATUS_ACCOUNTING_OFF
Definition: radius.h:195
#define RDEBUG(fmt,...)
Definition: log.h:243
#define RUT_NAMESIZE
Definition: radutmp.h:74
#define ERROR(fmt,...)
Definition: log.h:145
static char const porttypes[]
Definition: rlm_radutmp.c:37