1 /* This file is part of GNU Radius.
2 Copyright (C) 2000,2001,2002,2003,2004,2005,
3 2006,2007,2008 Free Software Foundation, Inc.
4
5 Written by Sergey Poznyakoff
6
7 GNU Radius is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Radius is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Radius; if not, write to the Free Software Foundation,
19 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21 #define LOG_EMPTY_USERNAME
22
23 #ifdef HAVE_CONFIG_H
24 # include <config.h>
25 #endif
26
27 #include <sys/types.h>
28 #include <sys/socket.h>
29 #include <sys/time.h>
30 #include <sys/file.h>
31 #include <sys/stat.h>
32 #include <netinet/in.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <netdb.h>
36 #include <pwd.h>
37 #include <time.h>
38 #include <ctype.h>
39 #include <unistd.h>
40 #include <signal.h>
41 #include <errno.h>
42 #include <sys/wait.h>
43 #include <fcntl.h>
44
45 #include <radiusd.h>
46 #include <radius/radutmp.h>
47 #include <rewrite.h>
48
49 int doradwtmp = 1;
50
51 static int write_wtmp(struct radutmp *ut);
52 static int write_nas_restart(int status, grad_uint32_t addr);
53 static int check_ts(struct radutmp *ut);
54
55 int rad_acct_system(radiusd_request_t *radreq, int dowtmp);
56 int rad_acct_db(radiusd_request_t *radreq, int authtype);
57 int rad_acct_ext(radiusd_request_t *radreq);
58
59
60 /* Zap a user, or all users on a NAS, from the radutmp file. */
61 int
radzap(grad_uint32_t nasaddr,int port,char * user,time_t t)62 radzap(grad_uint32_t nasaddr, int port, char *user, time_t t)
63 {
64 struct radutmp *up;
65 radut_file_t file;
66 grad_uint32_t netaddr;
67
68 if (t == 0) time(&t);
69 netaddr = htonl(nasaddr);
70
71 if (file = grad_ut_setent(grad_utmp_file, 0)) {
72 /* Find the entry for this NAS / portno combination. */
73 while (up = grad_ut_getent(file)) {
74 if (((nasaddr != 0 && netaddr != up->nas_address) ||
75 (port >= 0 && port != up->nas_port) ||
76 (user != NULL && strcmp(up->login, user) != 0) ||
77 up->type != P_LOGIN))
78 continue;
79 /* Zap the entry */
80 up->type = P_IDLE;
81 up->time = t;
82 grad_ut_putent(file, up);
83 /* Add a logout entry to the wtmp file. */
84 write_wtmp(up);
85 }
86 grad_ut_endent(file);
87 }
88
89 return 0;
90 }
91
92 static void
store_session_id(char * buffer,int len,char * id,int idlen)93 store_session_id(char *buffer, int len, char *id, int idlen)
94 {
95 int off = idlen - len;
96 if (off < 0)
97 off = 0;
98 memcpy(buffer, id + off, len);
99 buffer[len-1] = 0;
100 }
101
102 int
write_wtmp(struct radutmp * ut)103 write_wtmp(struct radutmp *ut)
104 {
105 return grad_radwtmp_putent(grad_wtmp_file, ut);
106 }
107
108 void
backslashify(char * dst,char * src,int len)109 backslashify(char *dst, char *src, int len)
110 {
111 #define CHECK(l,m) \
112 if (l <= m) goto end; else l -= m
113
114 #define ESCAPE(c)\
115 CHECK(len,2);\
116 src++;\
117 *dst++ = '\\';\
118 *dst++ = c
119
120 while (*src && len > 1) {
121 switch (*src) {
122 case '\\':
123 ESCAPE('\\');
124 break;
125 case '\a':
126 ESCAPE('a');
127 break;
128 case '\b':
129 ESCAPE('b');
130 break;
131 case '\f':
132 ESCAPE('f');
133 break;
134 case '\n':
135 ESCAPE('n');
136 break;
137 case '\r':
138 ESCAPE('r');
139 break;
140 case '\t':
141 ESCAPE('t');
142 break;
143 default:
144 *dst++ = *src++;
145 len--;
146 }
147 }
148
149 end:
150 *dst = 0;
151 }
152
153 int
check_attribute(grad_avp_t * check_pairs,int pair_attr,int pair_value,int def)154 check_attribute(grad_avp_t *check_pairs, int pair_attr,
155 int pair_value, int def)
156 {
157 grad_avp_t *pair;
158
159 if ((pair = grad_avl_find(check_pairs, pair_attr)) == NULL)
160 return def;
161 do {
162 if (pair->avp_lvalue == pair_value)
163 return 1;
164 check_pairs = pair->next;
165 } while (check_pairs
166 && (pair = grad_avl_find(check_pairs, pair_attr)));
167 return 0;
168 }
169
170 #ifdef DA_ACCT_TYPE
171 # define ACCT_TYPE(req,t) check_attribute(req, DA_ACCT_TYPE, t, 1)
172 #else
173 # define ACCT_TYPE(req,t) 1
174 #endif
175
176
177 /* Store logins in the RADIUS utmp file. */
178 int
rad_acct_system(radiusd_request_t * radreq,int dowtmp)179 rad_acct_system(radiusd_request_t *radreq, int dowtmp)
180 {
181 struct radutmp ut;
182 grad_avp_t *vp;
183 int status = -1;
184 int nas_address = 0;
185 int protocol = -1;
186 time_t t;
187 int ret = 0, rc;
188 int port_seen = 0;
189 char buf[GRAD_MAX_LONGNAME];
190
191 /* Do not do anything if system accounting is not requested */
192 if (!acct_system)
193 return 0;
194
195 /* A packet should have Acct-Status-Type attribute */
196 if ((vp = grad_avl_find(radreq->request->avlist, DA_ACCT_STATUS_TYPE))
197 == NULL) {
198 grad_log_req(GRAD_LOG_ERR, radreq->request,
199 _("no Acct-Status-Type attribute"));
200 return -1;
201 }
202
203 status = vp->avp_lvalue;
204
205 time(&t);
206 memset(&ut, 0, sizeof(ut));
207 ut.porttype = -1; /* Unknown so far */
208
209 if (radreq->realm) {
210 grad_server_t *server =
211 grad_list_item(radreq->realm->queue->servers,
212 radreq->server_no);
213 if (server)
214 ut.realm_address = server->addr;
215 }
216
217 /* Fill in radutmp structure */
218 for (vp = radreq->request->avlist; vp; vp = vp->next) {
219 switch (vp->attribute) {
220 case DA_USER_NAME:
221 backslashify(ut.login, vp->avp_strvalue, RUT_NAMESIZE);
222 break;
223
224 case DA_ORIG_USER_NAME:
225 backslashify(ut.orig_login, vp->avp_strvalue, RUT_NAMESIZE);
226 break;
227
228 case DA_LOGIN_IP_HOST:
229 case DA_FRAMED_IP_ADDRESS:
230 ut.framed_address = htonl(vp->avp_lvalue);
231 break;
232
233 case DA_FRAMED_PROTOCOL:
234 protocol = vp->avp_lvalue;
235 break;
236
237 case DA_NAS_IP_ADDRESS:
238 nas_address = vp->avp_lvalue;
239 ut.nas_address = htonl(vp->avp_lvalue);
240 break;
241
242 case DA_NAS_PORT_ID:
243 ut.nas_port = vp->avp_lvalue;
244 port_seen = 1;
245 break;
246
247 case DA_ACCT_DELAY_TIME:
248 ut.delay = vp->avp_lvalue;
249 break;
250
251 case DA_CALLING_STATION_ID:
252 store_session_id(ut.caller_id,
253 sizeof(ut.caller_id),
254 vp->avp_strvalue,
255 vp->avp_strlength);
256 break;
257
258 case DA_CALLED_STATION_ID:
259 break;
260
261 case DA_ACCT_SESSION_ID:
262 store_session_id(ut.session_id,
263 sizeof(ut.session_id),
264 vp->avp_strvalue,
265 vp->avp_strlength);
266 break;
267
268 case DA_NAS_PORT_TYPE:
269 ut.porttype = vp->avp_lvalue;
270 break;
271 }
272 }
273
274 if (ut.orig_login[0] == 0)
275 strncpy(ut.orig_login, ut.login, sizeof(ut.orig_login));
276
277 /* If we didn't find out the NAS address, use the originator's
278 IP address. */
279 if (nas_address == 0) {
280 nas_address = radreq->request->ipaddr;
281 ut.nas_address = htonl(nas_address);
282 }
283
284 #ifdef LOG_EMPTY_USERNAME
285 if (ut.login[0] == 0 && ut.caller_id[0] != 0) {
286 ut.login[0] = '#';
287 store_session_id(ut.login+1,
288 RUT_NAMESIZE-2,
289 ut.caller_id,
290 strlen(ut.caller_id));
291 }
292 #endif
293
294 ut.proto = protocol;
295 ut.time = t - ut.delay;
296
297 /* Process Accounting-On/Off records */
298 if (status == DV_ACCT_STATUS_TYPE_ACCOUNTING_ON && nas_address) {
299 grad_log(GRAD_LOG_NOTICE,
300 _("NAS %s started (Accounting-On packet seen)"),
301 grad_nas_ip_to_name(nas_address, buf, sizeof buf));
302 radzap(nas_address, -1, NULL, ut.time);
303 write_nas_restart(status, ut.nas_address);
304 return 0;
305 }
306 if (status == DV_ACCT_STATUS_TYPE_ACCOUNTING_OFF && nas_address) {
307 grad_log(GRAD_LOG_NOTICE,
308 _("NAS %s shut down (Accounting-Off packet seen)"),
309 grad_nas_ip_to_name(nas_address, buf, sizeof buf));
310 radzap(nas_address, -1, NULL, ut.time);
311 write_nas_restart(status, ut.nas_address);
312 return 0;
313 }
314
315 /* If we don't know the type of entry pretend we succeeded. */
316 if (status != DV_ACCT_STATUS_TYPE_START &&
317 status != DV_ACCT_STATUS_TYPE_STOP &&
318 status != DV_ACCT_STATUS_TYPE_ALIVE) {
319 grad_log_req(GRAD_LOG_NOTICE,
320 radreq->request, _("unknown packet type (%d)"),
321 status);
322 return 0;
323 } else if (status == DV_ACCT_STATUS_TYPE_START ||
324 status == DV_ACCT_STATUS_TYPE_STOP) {
325 GRAD_DEBUG7(1,
326 "%s: User %s at NAS %s port %d session %-*.*s",
327 status == DV_ACCT_STATUS_TYPE_START ? "start" : "stop",
328 ut.login,
329 grad_nas_ip_to_name(nas_address, buf, sizeof buf),
330 ut.nas_port,
331 sizeof(ut.session_id),
332 sizeof(ut.session_id),
333 ut.session_id);
334 }
335
336 /* Decide if we should store this record into radutmp/radwtmp.
337 We skip records:
338
339 - if NAS-Port-Id attribute is absent
340 - if request has one or more Acct-Type attributes
341 and no one of them requires system accounting.
342 (The Acct-Type pairs can be inserted only via
343 raddb/hints */
344 if (!port_seen)
345 return 0;
346
347 if (!ACCT_TYPE(radreq->request->avlist, DV_ACCT_TYPE_SYSTEM)) {
348 GRAD_DEBUG1(1,"Acct type system disabled for %s", ut.login);
349 return 0;
350 }
351
352 /* Update radutmp file. */
353 rc = grad_utmp_putent(grad_utmp_file, &ut, status);
354 GRAD_DEBUG3(1, "grad_utmp_putent=%d for %s/%s",
355 rc, ut.login, ut.session_id);
356
357 /* Don't write wtmp if we don't have a username, or
358 if this is an update record and the original record
359 was already written. */
360 if ((status != DV_ACCT_STATUS_TYPE_STOP && ut.login[0] == 0) ||
361 rc == PUTENT_UPDATE)
362 dowtmp = 0;
363
364 /* Write a RADIUS wtmp log file. */
365 if (dowtmp) {
366 stat_update(&ut, status);
367 write_wtmp(&ut);
368 } else if (rc == PUTENT_UPDATE) {
369 stat_update(&ut, status);
370 } else {
371 ret = -1;
372 stat_inc(acct, radreq->request->ipaddr, num_norecords);
373 grad_log_req(GRAD_LOG_NOTICE, radreq->request,
374 _("NOT writing wtmp record"));
375 }
376 return ret;
377 }
378
379 static void
disable_system_acct()380 disable_system_acct()
381 {
382 radut_file_t file;
383 struct radutmp *up;
384 int written = 0;
385
386 if ((file = grad_ut_setent(grad_utmp_file, 0)) == NULL)
387 return;
388
389 while (up = grad_ut_getent(file)) {
390 switch (up->type) {
391 case P_LOGIN:
392 up->type = P_IDLE;
393 time(&up->time);
394 grad_ut_putent(file, up);
395 /* Add a logout entry to the wtmp file. */
396 write_wtmp(up);
397 break;
398
399 case P_ACCT_ENABLED:
400 time(&up->time);
401 up->type = P_ACCT_DISABLED;
402 grad_ut_putent(file, up);
403 write_wtmp(up);
404 written = 1;
405 break;
406
407 case P_ACCT_DISABLED:
408 written = 1;
409 break;
410 }
411 }
412
413 if (!written) {
414 struct radutmp ut;
415
416 memset(&ut, 0, sizeof ut);
417 time(&ut.time);
418 ut.type = P_ACCT_DISABLED;
419 grad_ut_putent(file, &ut);
420 }
421 grad_ut_endent(file);
422 grad_log(GRAD_LOG_INFO, _("System accounting is disabled"));
423 }
424
425 static void
enable_system_acct()426 enable_system_acct()
427 {
428 radut_file_t file;
429 struct radutmp *up, ut;
430
431 if ((file = grad_ut_setent(grad_utmp_file, 0)) == NULL)
432 return;
433
434 while (up = grad_ut_getent(file)) {
435 if (up->type == P_ACCT_DISABLED) {
436 up->type = P_ACCT_ENABLED;
437 time(&up->time);
438 grad_ut_putent(file, up);
439 /* Add an entry to the wtmp file. */
440 write_wtmp(up);
441 }
442 }
443 grad_ut_endent(file);
444 }
445
446 void
system_acct_init()447 system_acct_init()
448 {
449 if (acct_system)
450 enable_system_acct();
451 else
452 disable_system_acct();
453 }
454
455 int
mkdir_path(char * path,int perms)456 mkdir_path(char *path, int perms)
457 {
458 struct stat st;
459
460 if (stat(path, &st)) {
461 char *p;
462
463 if (errno != ENOENT) {
464 grad_log(GRAD_LOG_ERR|GRAD_LOG_PERROR,
465 _("Cannot stat path component: %s"),
466 path);
467 return 1;
468 }
469
470 p = strrchr(path, '/');
471 if (p && p > path) {
472 int rc;
473 *p = 0;
474 rc = mkdir_path(path, perms);
475 *p = '/';
476 if (rc)
477 return 1;
478 }
479
480 if (mkdir(path, perms)) {
481 grad_log(GRAD_LOG_ERR|GRAD_LOG_PERROR,
482 _("Cannot create directory %s"),
483 path);
484 return 1;
485 }
486 } else if (!S_ISDIR(st.st_mode)) {
487 grad_log(GRAD_LOG_ERR,
488 _("Path component is not a directory: %s"),
489 path);
490 return 1;
491 }
492 return 0;
493 }
494
495 static int
check_acct_dir()496 check_acct_dir()
497 {
498 struct stat st;
499
500 if (stat(grad_acct_dir, &st) == 0) {
501 if (S_ISDIR(st.st_mode)) {
502 if (access(grad_acct_dir, W_OK)) {
503 grad_log(GRAD_LOG_ERR,
504 _("%s: directory not writable"),
505 grad_acct_dir);
506 return 1;
507 }
508 return 0;
509 } else {
510 grad_log(GRAD_LOG_ERR, _("%s: not a directory"),
511 grad_acct_dir);
512 return 1;
513 }
514 }
515
516 if (mkdir_path(grad_acct_dir, 0755))
517 return 1;
518 return 0;
519 }
520
521 static int acct_dir_status;
522
523 static void
acct_after_config_hook(void * arg ARG_UNUSED,void * data ARG_UNUSED)524 acct_after_config_hook(void *arg ARG_UNUSED, void *data ARG_UNUSED)
525 {
526 if (auth_detail || acct_detail) {
527 acct_dir_status = check_acct_dir();
528 if (acct_dir_status) {
529 grad_log(GRAD_LOG_NOTICE,
530 _("Detailed accounting is disabled"));
531 auth_detail = acct_detail = 0;
532 }
533 }
534 }
535
536 void
acct_init()537 acct_init()
538 {
539 radiusd_set_postconfig_hook(acct_after_config_hook, NULL, 0);
540 }
541
542 static char *
make_legacy_detail_filename(radiusd_request_t * radreq,char * default_filename)543 make_legacy_detail_filename(radiusd_request_t *radreq, char *default_filename)
544 {
545 char nasname[GRAD_MAX_LONGNAME];
546 grad_nas_t *cl;
547 grad_uint32_t ip;
548 grad_avp_t *pair;
549
550 /* Find out the name of this terminal server. We try to find
551 the DA_NAS_IP_ADDRESS in the naslist file. If that fails,
552 we look for the originating address.
553 Only if that fails we resort to a name lookup. */
554
555 cl = NULL;
556 ip = radreq->request->ipaddr;
557 if ((pair = grad_avl_find(radreq->request->avlist, DA_NAS_IP_ADDRESS)) != NULL)
558 ip = pair->avp_lvalue;
559
560 if (radreq->realm) {
561 grad_server_t *server =
562 grad_list_item(radreq->realm->queue->servers,
563 radreq->server_no);
564 if (server)
565 ip = server->addr;
566 }
567
568 if ((cl = grad_nas_lookup_ip(ip)) != NULL) {
569 if (cl->shortname[0])
570 strcpy(nasname, cl->shortname);
571 else
572 strcpy(nasname, cl->longname);
573 }
574
575 if (cl == NULL)
576 grad_ip_gethostname(ip, nasname, sizeof(nasname));
577
578 return grad_mkfilename(nasname, default_filename);
579 }
580
581 static char *
make_detail_filename(radiusd_request_t * req,char * template,char * default_filename)582 make_detail_filename(radiusd_request_t *req, char *template,
583 char *default_filename)
584 {
585 if (!template) {
586 return make_legacy_detail_filename(req, default_filename);
587 } else if (template[0] == '=') {
588 grad_value_t val;
589 /*FIXME: Should be compiled!*/
590 if (rewrite_interpret(template+1, req->request, &val))
591 return NULL;
592 if (val.type != String) {
593 grad_log(GRAD_LOG_ERR, "%s: %s",
594 template+1, _("wrong return type"));
595 /* Nothing to free in val */
596 return NULL;
597 }
598 return val.datum.sval.data;
599 } else {
600 struct obstack stk;
601 char *ptr;
602
603 obstack_init(&stk);
604 ptr = radius_xlate(&stk, template, req->request, NULL);
605 if (ptr)
606 ptr = grad_estrdup(ptr);
607 obstack_free(&stk, NULL);
608 return ptr;
609 }
610 }
611
612 static int
make_path_to_file(char * filename,int perms)613 make_path_to_file(char *filename, int perms)
614 {
615 char *p = strrchr(filename, '/');
616 if (p) {
617 int rc;
618 *p = 0;
619 rc = mkdir_path(filename, perms);
620 *p = '/';
621 return rc;
622 }
623 return 0;
624 }
625
626 int
write_detail(radiusd_request_t * radreq,int authtype,int rtype)627 write_detail(radiusd_request_t *radreq, int authtype, int rtype)
628 {
629 FILE *outfd;
630 char *save;
631 grad_avp_t *pair;
632 time_t curtime;
633 int ret = 0;
634 char *filename;
635 char *template;
636 char *deffilename;
637
638 if (acct_dir_status)
639 return 1;
640
641 curtime = time(0);
642
643 switch (rtype) {
644 case R_ACCT:
645 template = acct_detail_template;
646 deffilename = "detail";
647 break;
648
649 case R_AUTH:
650 template = auth_detail_template;
651 deffilename = "detail.auth";
652 break;
653
654 default:
655 return 1;
656 }
657
658 filename = make_detail_filename(radreq, template, deffilename);
659 if (!filename)
660 return 1;
661
662 /* Change to the accounting directory */
663 if (chdir(grad_acct_dir)) {
664 grad_free(filename);
665 return 1;
666 }
667
668 /* Create a directory for this nas. */
669 make_path_to_file(filename, 0755);
670
671 /* Write Detail file. */
672 if ((outfd = fopen(filename, "a")) == NULL) {
673 grad_log(GRAD_LOG_ERR|GRAD_LOG_PERROR,
674 _("can't open %s"), filename);
675 ret = 1;
676 } else {
677
678 /* Post a timestamp */
679 fprintf(outfd, "%s", ctime(&curtime));
680
681 /* Decide which username to log */
682 if (!strip_names) {
683 /* user wants a full (non-stripped) name to appear
684 in detail */
685
686 pair = grad_avl_find(radreq->request->avlist,
687 DA_ORIG_USER_NAME);
688 if (pair)
689 pair->name = "User-Name";
690 else
691 pair = grad_avl_find(radreq->request->avlist,
692 DA_USER_NAME);
693 if (pair) {
694 fprintf(outfd, "\t%s\n",
695 grad_format_pair(pair, 0, &save));
696 free(save);
697 }
698 }
699
700 /* Write each attribute/value to the log file */
701 for (pair = radreq->request->avlist; pair; pair = pair->next) {
702 if (pair->prop & GRAD_AP_INTERNAL)
703 continue;
704 switch (pair->attribute) {
705 case DA_USER_PASSWORD:
706 break;
707 case DA_USER_NAME:
708 case DA_ORIG_USER_NAME:
709 if (!strip_names)
710 break;
711 default:
712 fprintf(outfd, "\t%s\n",
713 grad_format_pair(pair, 0, &save));
714 free(save);
715 }
716 }
717
718 /* Add non-protocol attibutes. */
719 fprintf(outfd, "\tTimestamp = %ld\n", curtime);
720 switch (authtype) {
721 case REQ_AUTH_OK:
722 fprintf(outfd, "\tRequest-Authenticator = Verified\n");
723 break;
724 case REQ_AUTH_ZERO:
725 fprintf(outfd, "\tRequest-Authenticator = None\n");
726 break;
727 case REQ_AUTH_BAD:
728 fprintf(outfd, "\tRequest-Authenticator = Unverified\n");
729 break;
730 default:
731 fprintf(outfd, "\tRequest-Authenticator = %d\n",
732 authtype);
733 break;
734 }
735 fprintf(outfd, "\n");
736 fclose(outfd);
737 ret = 0;
738 }
739
740 grad_free(filename);
741 chdir("/");
742 return ret;
743 }
744
745 int
rad_acct_db(radiusd_request_t * radreq,int authtype)746 rad_acct_db(radiusd_request_t *radreq, int authtype)
747 {
748 int rc = 0;
749
750 if (acct_detail
751 && ACCT_TYPE(radreq->request->avlist, DV_ACCT_TYPE_DETAIL))
752 rc = write_detail(radreq, authtype, R_ACCT);
753 if (ACCT_TYPE(radreq->request->avlist, DV_ACCT_TYPE_SQL))
754 radiusd_sql_acct(radreq);
755 return rc;
756 }
757
758 int
rad_acct_ext(radiusd_request_t * radreq)759 rad_acct_ext(radiusd_request_t *radreq)
760 {
761 grad_avp_t *p;
762 int rc = 0;
763
764 #ifdef USE_SERVER_GUILE
765 for (p = grad_avl_find(radreq->request->avlist, DA_SCHEME_ACCT_PROCEDURE);
766 p;
767 p = grad_avl_find(p->next, DA_SCHEME_ACCT_PROCEDURE))
768 scheme_acct(p->avp_strvalue, radreq);
769 #endif
770 for (p = grad_avl_find(radreq->request->avlist, DA_ACCT_EXT_PROGRAM);
771 p;
772 p = grad_avl_find(p->next, DA_ACCT_EXT_PROGRAM)) {
773 radius_eval_avp(radreq, p, NULL, 1);
774 switch (p->avp_strvalue[0]) {
775 case '/':
776 rc = radius_exec_program(p->avp_strvalue, radreq, NULL,
777 1);
778 break;
779 case '|':
780 filter_acct(p->avp_strvalue+1, radreq);
781 }
782 }
783 return rc;
784 }
785
786 /* run accounting modules */
787 int
rad_accounting(radiusd_request_t * radreq,int activefd,int verified)788 rad_accounting(radiusd_request_t *radreq, int activefd, int verified)
789 {
790 log_open(GRAD_LOG_ACCT);
791
792 huntgroup_access(radreq, NULL);
793
794 #if defined(RT_ASCEND_EVENT_REQUEST) && defined(RT_ASCEND_EVENT_RESPONSE)
795 /* Special handling for Ascend-Event-Request */
796 if (radreq->request->code == RT_ASCEND_EVENT_REQUEST) {
797 write_detail(radreq, verified, R_ACCT);
798 radius_send_reply(RT_ASCEND_EVENT_RESPONSE,
799 radreq, NULL, NULL, activefd);
800 stat_inc(acct, radreq->request->ipaddr, num_resp);
801 return 0;
802 }
803 #endif
804
805 if (rad_acct_system(radreq, doradwtmp) == 0 &&
806 rad_acct_db(radreq, verified) == 0 &&
807 rad_acct_ext(radreq) == 0) {
808 /* Now send back an ACK to the NAS. */
809 radius_send_reply(RT_ACCOUNTING_RESPONSE,
810 radreq, NULL, NULL, activefd);
811 stat_inc(acct, radreq->request->ipaddr, num_resp);
812 return 0;
813 }
814
815 return -1;
816 }
817
818 int
write_nas_restart(int status,grad_uint32_t addr)819 write_nas_restart(int status, grad_uint32_t addr)
820 {
821 struct radutmp ut;
822
823 memset(&ut, 0, sizeof(ut));
824 if (status == DV_ACCT_STATUS_TYPE_ACCOUNTING_ON)
825 ut.type = P_NAS_START;
826 else
827 ut.type = P_NAS_SHUTDOWN;
828 ut.nas_address = addr;
829 time(&ut.time);
830 return write_wtmp(&ut);
831 }
832
833
834 /* Multiple login checking */
835
836 int
radutmp_mlc_collect_user(char * name,radiusd_request_t * request,grad_list_t ** sess_list)837 radutmp_mlc_collect_user(char *name, radiusd_request_t *request,
838 grad_list_t **sess_list)
839 {
840 radut_file_t file;
841 struct radutmp *up;
842
843 if ((file = grad_ut_setent(grad_utmp_file, 0)) == NULL)
844 return 1;
845
846 while (up = grad_ut_getent(file)) {
847 if (strncmp(name, up->login, RUT_NAMESIZE) == 0 &&
848 up->type == P_LOGIN) {
849 struct radutmp *tmp;
850
851 if (*sess_list == NULL)
852 *sess_list = grad_list_create();
853 tmp = grad_emalloc(sizeof(*tmp));
854 memcpy(tmp, up, sizeof(*tmp));
855 grad_list_append(*sess_list, tmp);
856 }
857 }
858 grad_ut_endent(file);
859 return 0;
860 }
861
862 int
radutmp_mlc_collect_realm(radiusd_request_t * request,grad_list_t ** sess_list)863 radutmp_mlc_collect_realm(radiusd_request_t *request, grad_list_t **sess_list)
864 {
865 radut_file_t file;
866 struct radutmp *up;
867
868 if ((file = grad_ut_setent(grad_utmp_file, 0)) == NULL)
869 return 1;
870
871 while (up = grad_ut_getent(file)) {
872 if (up->type == P_LOGIN
873 && grad_realm_verify_ip(request->realm, up->realm_address)) {
874 struct radutmp *tmp;
875
876 if (*sess_list == NULL)
877 *sess_list = grad_list_create();
878 tmp = grad_emalloc(sizeof(*tmp));
879 memcpy(tmp, up, sizeof(*tmp));
880 grad_list_append(*sess_list, tmp);
881 }
882 }
883 grad_ut_endent(file);
884 return 0;
885 }
886
887 void
radutmp_mlc_close(struct radutmp * up)888 radutmp_mlc_close(struct radutmp *up)
889 {
890 up->type = P_IDLE;
891 up->time = time(NULL);
892 grad_utmp_putent(grad_utmp_file, up, DV_ACCT_STATUS_TYPE_STOP);
893 }
894
895 int
radutmp_mlc_enabled_p()896 radutmp_mlc_enabled_p()
897 {
898 return acct_system;
899 }
900
901
902
903
904
905
906
907
908
909
910