diff -ru radiusd-cistron-1.6.0-orig/raddb/dictionary radiusd-cistron-1.6.0-stable/raddb/dictionary --- radiusd-cistron-1.6.0-orig/raddb/dictionary Wed Sep 8 11:08:06 1999 +++ radiusd-cistron-1.6.0-stable/raddb/dictionary Mon Sep 27 20:18:49 1999 @@ -104,6 +104,7 @@ ATTRIBUTE Add-Port-To-IP-Address 501 integer ATTRIBUTE Exec-Program 502 string ATTRIBUTE Exec-Program-Wait 503 string +ATTRIBUTE Exec-Program-Stop 504 string # These attributes CANNOT go in the reply item list. ATTRIBUTE User-Category 1029 string Only in radiusd-cistron-1.6.0-orig/scripts: rc.radiusd diff -ru radiusd-cistron-1.6.0-orig/src/acct.c radiusd-cistron-1.6.0-stable/src/acct.c --- radiusd-cistron-1.6.0-orig/src/acct.c Wed May 5 11:53:15 1999 +++ radiusd-cistron-1.6.0-stable/src/acct.c Tue Sep 28 16:49:50 1999 @@ -643,7 +643,6 @@ log(L_ERR, "Acct: Couldn't open file %s", buffer); ret = -1; } else { - /* Post a timestamp */ fputs(ctime(&curtime), outfd); @@ -682,7 +681,6 @@ return ret; } - /* * rad_accounting: call both the old and new style accounting functions. */ @@ -691,6 +689,8 @@ int reply = 0; int auth; char pw_digest[16]; + VALUE_PAIR *user_reply; + VALUE_PAIR *pair; /* * See if we know this client, then check the @@ -722,6 +722,21 @@ reply = 1; if (rad_accounting_new(authreq, doradwtmp) == 0) reply = 1; + } + + /* + * Is there a program_stop? + */ + if (exec_program_stop) { + /* + * Is this a stop accounting request? + */ + pair = pairfind(authreq->request, PW_ACCT_STATUS_TYPE); + if (pair && (pair->lvalue == PW_STATUS_STOP)) { + log(L_DBG, "rad_accounting(): Exec-Program-Stop = \"%s\"", exec_program_stop); + user_reply = authreq->server_reply; + radius_exec_program_stop(exec_program_stop, authreq->request, &user_reply); + } } if (reply) { diff -ru radiusd-cistron-1.6.0-orig/src/exec.c radiusd-cistron-1.6.0-stable/src/exec.c --- radiusd-cistron-1.6.0-orig/src/exec.c Tue May 4 17:34:28 1999 +++ radiusd-cistron-1.6.0-stable/src/exec.c Tue Sep 28 16:07:37 1999 @@ -35,6 +35,7 @@ * %a Protocol (SLIP/PPP) * %s Speed (PW_CONNECT_INFO) * %i Calling Station ID + * %T Accouting Session Time * */ char *radius_xlate(char *str, VALUE_PAIR *request, VALUE_PAIR *reply) @@ -131,6 +132,15 @@ strcpy(buf + i, "unknown"); i += strlen(buf + i); break; + case 'T': /* Accounting Session Time */ + n = 0; + if ((tmp = pairfind(request, + PW_ACCT_SESSION_TIME)) != NULL) { + n = tmp->lvalue; + } + sprintf(buf + i, "%d", n); + i += strlen(buf + i); + break; default: buf[i++] = '%'; buf[i++] = *p; @@ -349,5 +359,59 @@ log(L_ERR|L_CONS, "Exec-Program: Abnormal child exit (killed or coredump)"); return 1; +} + +#define MAX_ARGV_LEN 32 + +int radius_exec_program_stop(char *cmd, VALUE_PAIR *request, VALUE_PAIR **reply) +{ + const char *SEP = " \t"; + pid_t pid; + char *buf, *p; + char *argv[MAX_ARGV_LEN + 1]; + int argc = 0; + + pid = fork(); + if (pid) { + /* Parent */ + + if (pid < 0) { + log(L_ERR|L_CONS, "radius_exec_program_stop(): Couldn't fork: %m"); + return -1; + } + + return 0; + } + else { + /* Child */ + + buf = radius_xlate(cmd, request, *reply); + + /* + * XXX FIXME: This is debugging info. + */ + log(L_INFO, "Exec-Program-Stop: %s", buf); + + /* + * Build vector list and execute. + */ + p = strtok(buf, SEP); + while (p && (argc < MAX_ARGV_LEN)) { + argv[argc++] = p; + p = strtok(0, SEP); + } + argv[argc] = 0; + if (argc < 1) { + log(L_ERR, "Exec-Program-Stop: Empty command line."); + exit(1); + } + execv(argv[0], argv); + + log(L_ERR, "Exec-Program-Stop: exec() failed: %s: %m", argv[0]); + + exit(1); + } + + return 0; } diff -ru radiusd-cistron-1.6.0-orig/src/files.c radiusd-cistron-1.6.0-stable/src/files.c --- radiusd-cistron-1.6.0-orig/src/files.c Wed Sep 8 11:13:43 1999 +++ radiusd-cistron-1.6.0-stable/src/files.c Tue Sep 28 13:43:19 1999 @@ -2057,6 +2057,7 @@ if (!use_dbm) { PAIR_LIST *entry; VALUE_PAIR *pair; + VALUE_PAIR *reply; for (entry = users; entry; entry = entry->next) { for (pair = entry->reply; pair; pair = pair->next) { @@ -2071,7 +2072,27 @@ } } } + + /* + * See if we need to execute a program-stop. + */ + for (entry = users; entry; entry = entry->next) { + reply = entry->reply; + pair = pairfind(reply, PW_EXEC_PROGRAM_STOP); + if (pair) { + if (exec_program_stop) + free(exec_program_stop); + exec_program_stop = strdup(pair->strvalue); + if (exec_program_stop) + log(L_DBG, "rad_authenticate(): Exec-Program-Stop = \"%s\"", exec_program_stop); + else + log(L_DBG, "rad_authenticate(): Exec-Program-Stop = "); + pairdelete(&reply, PW_EXEC_PROGRAM_STOP); + } + } + } + sprintf(buffer, "%s/%s", radius_dir, RADIUS_HUNTGROUPS); huntgroups = file_read(buffer, 0); diff -ru radiusd-cistron-1.6.0-orig/src/radius.h radiusd-cistron-1.6.0-stable/src/radius.h --- radiusd-cistron-1.6.0-orig/src/radius.h Wed Sep 8 11:08:29 1999 +++ radiusd-cistron-1.6.0-stable/src/radius.h Mon Sep 27 20:10:46 1999 @@ -119,6 +119,7 @@ #define PW_ADD_PORT_TO_IP_ADDRESS 501 #define PW_EXEC_PROGRAM 502 #define PW_EXEC_PROGRAM_WAIT 503 +#define PW_EXEC_PROGRAM_STOP 504 #define PW_AUTHTYPE 1000 #define PW_PREFIX 1003 diff -ru radiusd-cistron-1.6.0-orig/src/radiusd.c radiusd-cistron-1.6.0-stable/src/radiusd.c --- radiusd-cistron-1.6.0-orig/src/radiusd.c Sun Jul 25 07:18:11 1999 +++ radiusd-cistron-1.6.0-stable/src/radiusd.c Tue Sep 28 12:56:30 1999 @@ -72,6 +72,7 @@ int log_auth_pass = 0; int auth_port; int acct_port; +char *exec_program_stop = 0; /* * Make sure recv_buffer is aligned properly. diff -ru radiusd-cistron-1.6.0-orig/src/radiusd.h radiusd-cistron-1.6.0-stable/src/radiusd.h --- radiusd-cistron-1.6.0-orig/src/radiusd.h Wed Sep 8 10:47:41 1999 +++ radiusd-cistron-1.6.0-stable/src/radiusd.h Tue Sep 28 13:12:29 1999 @@ -171,6 +171,7 @@ extern int log_auth_pass; extern int auth_port; extern int acct_port; +extern char *exec_program_stop; /* * Function prototypes. @@ -202,6 +203,7 @@ /* radiusd.c */ int radius_exec_program(char *, VALUE_PAIR *, VALUE_PAIR **, int, char **user_msg); +int radius_exec_program_stop(char *, VALUE_PAIR *, VALUE_PAIR **); void debug_pair(FILE *, VALUE_PAIR *); int log_err (char *); void sig_cleanup(int);