Only in radiusd-cistron-1.5.4.3: README.1st diff -u -r radiusd-cistron-1.5.4.3.orig/doc/README radiusd-cistron-1.5.4.3/doc/README --- radiusd-cistron-1.5.4.3.orig/doc/README Sat Oct 31 22:10:11 1998 +++ radiusd-cistron-1.5.4.3/doc/README Fri Nov 6 21:03:43 1998 @@ -150,6 +150,13 @@ Exec-Program string program to execute after authentication Exec-Program-Wait string ditto, but wait for program to finish before sending back auth. reply Login-Time string Defines when user may login. + Exec-Program-Timeout string same as Exec-Program-Wait, except when + auth is OK (zero exit status), stdout of + program will show session timeout in + seconds + Exec-Program-Account string same as Exec-Program, except that it is + called on arrival of accounting (not + authentication!) messages. Exec-Program can take arguments. You can use macros in the arguments: @@ -163,3 +170,13 @@ %i Calling Station ID + %e Length of session (Acct-Session-Time attribute), in seconds + %d Delay Time (Acct-Delay-Time attribute), in seconds + %i Session ID (Acct-Session-ID attribute) + %r Input-Octets (Acct-Input-Octets attribute) + %w Output-Octets (Acct-Output-Octets attribute) + %q Input-Packets (Acct-Input-Packets attribute) + %y Output-Packets (Acct-Output-Packets attribute) + + Be aware that %e, %d and %i macros have meaning only when used with + Exec-Program-Account attribute. Taken from the reply as defined thusfar: @@ -205,4 +222,37 @@ is set to 1800 seconds so that she is kicked off at 18:00. + + If Exec-Program-Timeout returns a non-zero exit status, access will be + denied to the user. If the external program printed something on its + standard output, this will be sent along with the rejection as Port-Message. + If exit status is zero, access will be enabled to the user, and + Session-Timeout will be set to value which is printed on standard output + (in seconds). If this value is zero, no Session-Timeout will be set. + If Exec-Program-Timeout attribute is present, any other manually set + Session-Timeout attribute will be deleted. It means that attribute + Exec-Program-Timeout excludes Session-Timeout attribute. + + When external program is called due to presence of Exec-Program-Account + attribute, radiusd will not wait for it to finish and will not chech its exit + status. Exec-Program-Account atrtibute is to be set in users file, and + You must be very careful where to place it, since users file is not scanned + during accounting process in radiusd normal behaviour. I suggest to place it + in the beginning of the file, before any other statements (to make sure that it + is the only statement used from users file during accounting). For example: + + # Beginning of users file + # + + DEFAULT Acct-Status-Type = "Start" + Exec-Program-Account = "/usr/local/radius/acct-start %u %i %p %n %f %a %s %e %d" + + DEFAULT Acct-Status-Type = "Stop" + Exec-Program-Account = "/usr/local/radius/acct-stop %u %i %p %n %f %a %s %e %d" + + # ... other statements ... + + Note that there is no "Fall-Through" statement, and that it is possible to + use separate programs for "Start" and "Stop" accounting requests. + 5. LOG FILES diff -u -r radiusd-cistron-1.5.4.3.orig/raddb/dictionary radiusd-cistron-1.5.4.3/raddb/dictionary --- radiusd-cistron-1.5.4.3.orig/raddb/dictionary Tue Nov 3 01:08:07 1998 +++ radiusd-cistron-1.5.4.3/raddb/dictionary Fri Nov 6 21:08:13 1998 @@ -109,7 +109,9 @@ ATTRIBUTE Exec-Program-Wait 1039 string ATTRIBUTE Hint 1040 string ATTRIBUTE Pam-Auth 1041 string ATTRIBUTE Login-Time 1042 string +ATTRIBUTE Exec-Program-Timeout 1043 string +ATTRIBUTE Exec-Program-Account 1044 string # # Non-Protocol Attributes diff -u -r radiusd-cistron-1.5.4.3.orig/src/acct.c radiusd-cistron-1.5.4.3/src/acct.c --- radiusd-cistron-1.5.4.3.orig/src/acct.c Sun Nov 1 00:22:13 1998 +++ radiusd-cistron-1.5.4.3/src/acct.c Fri Nov 6 21:06:15 1998 @@ -226,6 +226,56 @@ return 0; } +/* + * Move attributes from one list to the other + * if not already present. + */ +static void pairmove(VALUE_PAIR **to, VALUE_PAIR **from) +{ + VALUE_PAIR *tail, *i, *next; + VALUE_PAIR *last = NULL; + int has_password = 0; + + if (*to == NULL) { + *to = *from; + *from = NULL; + return; + } + + tail = *to; + for(i = *to; i; i = i->next) { + if (i->attribute == PW_PASSWORD || + i->attribute == PW_CHAP_PASSWORD || + i->attribute == PW_CRYPT_PASSWORD) + has_password = 1; + tail = i; + } + + for(i = *from; i; i = next) { + next = i->next; + if (has_password && + (i->attribute == PW_PASSWORD || + i->attribute == PW_CHAP_PASSWORD || + i->attribute == PW_CRYPT_PASSWORD)) { + last = i; + continue; + } + if (i->attribute == PW_FALL_THROUGH || + (i->attribute != PW_HINT && + pairfind(*to, i->attribute) != 0)) { + last = i; + continue; + } + if (last) + last->next = next; + else + *from = next; + tail->next = i; + i->next = NULL; + tail = i; + } +} + /* * Store logins in the RADIUS utmp file. @@ -235,6 +285,8 @@ struct radutmp ut, u; struct utmp wt; VALUE_PAIR *vp; + VALUE_PAIR *user_check = NULL; + VALUE_PAIR *user_reply = NULL; int rb_record = 0; int status = -1; int nas_address = 0; @@ -248,6 +300,8 @@ int port_seen = 0; int nas_port_type = 0; int off; + int exec_account = 0; + char *exec_account_program = NULL; /* * Which type is this. @@ -317,6 +371,17 @@ hints_setup(authreq->request); presuf_setup(authreq->request); } + + /* + * Add attributes from users file for this username + */ + if (user_find((pairfind(authreq->request, PW_USER_NAME))->strvalue, + authreq->request, &user_check, &user_reply) == 0) { + pairmove(&(authreq->request), &user_reply); + pairfree(user_reply); + pairfree(user_check); + } + time(&t); memset(&ut, 0, sizeof(ut)); memset(&wt, 0, sizeof(wt)); @@ -369,6 +434,10 @@ strncpy(ut.caller_id, vp->strvalue, sizeof(ut.caller_id)); ut.caller_id[sizeof(ut.caller_id)] = 0; break; + case PW_EXEC_PROGRAM_ACCOUNT: + exec_account = 1; + exec_account_program = strdup(vp->strvalue); + break; } } @@ -575,7 +644,13 @@ fclose(fp); } - + /* + * Call external accounting program. + */ + if (exec_account) + radius_exec_program(exec_account_program, + authreq->request, authreq->request, 0, NULL ); + return ret; } diff -u -r radiusd-cistron-1.5.4.3.orig/src/auth.c radiusd-cistron-1.5.4.3/src/auth.c --- radiusd-cistron-1.5.4.3.orig/src/auth.c Thu Oct 8 20:12:43 1998 +++ radiusd-cistron-1.5.4.3/src/auth.c Fri Nov 6 21:56:38 1998 @@ -543,6 +543,7 @@ VALUE_PAIR *user_check; VALUE_PAIR *user_reply; VALUE_PAIR *proxy_pairs; + VALUE_PAIR *session_timeout; int result, r; char pw_digest[16]; char userpass[128]; @@ -552,6 +553,9 @@ char *exec_program; int exec_wait; int seen_callback_id; + int exec_timeout; + DICT_ATTR *attr; + user_check = NULL; user_reply = NULL; @@ -763,6 +767,7 @@ */ exec_program = NULL; exec_wait = 0; + exec_timeout = 0; if ((auth_item = pairfind(user_reply, PW_EXEC_PROGRAM)) != NULL) { exec_wait = 0; exec_program = strdup(auth_item->strvalue); @@ -773,6 +778,14 @@ exec_program = strdup(auth_item->strvalue); pairdelete(&user_reply, PW_EXEC_PROGRAM_WAIT); } + if ((auth_item = pairfind(user_reply, PW_EXEC_PROGRAM_TIMEOUT)) != NULL) { + exec_wait = 1; + exec_timeout = 1; + exec_program = strdup(auth_item->strvalue); + pairdelete(&user_reply, PW_EXEC_PROGRAM_TIMEOUT); + if (pairfind(user_reply, PW_SESSION_TIMEOUT)) + pairdelete(&user_reply, PW_SESSION_TIMEOUT); + } /* * Hack - allow % expansion in certain value strings. @@ -815,6 +828,32 @@ pairfree(user_check); pairfree(user_reply); return 0; + } else if (exec_timeout) { + /* + * session_timeout is stored in user_msg + */ + if (atoi(user_msg)) { + /* + * set actuall session_timeout, if not + * equal to 0; otherwise there is no + * session_timeout + */ + if((session_timeout = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) == + (VALUE_PAIR *)NULL) { + log(L_CONS|L_ERR, "no memory"); + exit(1); + } + attr = dict_attrfind( "Session-Timeout" ); + strcpy(session_timeout->name, attr->name); + session_timeout->attribute = attr->value; + session_timeout->type = attr->type; + session_timeout->lvalue = (UINT4)atoi(user_msg); + pairadd(&user_reply, session_timeout); + log(L_AUTH, + "Login OK: session_timeout=%i", + session_timeout->lvalue); + } + user_msg = NULL; } } diff -u -r radiusd-cistron-1.5.4.3.orig/src/exec.c radiusd-cistron-1.5.4.3/src/exec.c --- radiusd-cistron-1.5.4.3.orig/src/exec.c Fri Oct 2 14:31:44 1998 +++ radiusd-cistron-1.5.4.3/src/exec.c Fri Nov 6 21:40:37 1998 @@ -35,6 +35,13 @@ * %a Protocol (SLIP/PPP) * %s Speed (PW_CONNECT_INFO) * %i Calling Station ID + * %e Session-Time (PW_ACCT_SESSION_TIME) + * %d Delay-Time (PW_ACCT_DELAY_TIME) + * %i Session-ID (PW_ACCT_SESSION_ID) + * %r Input-Octets (PW_ACCT_INPUT_OCTETS) + * %w Output-Octets (PW_ACCT_OUTPUT_OCTETS) + * %q Input-Packets (PW_ACCT_INPUT_PACKETS) + * %y Output-Packets (PW_ACCT_OUTPUT_PACKETS) * */ char *radius_xlate(char *str, VALUE_PAIR *request, VALUE_PAIR *reply) @@ -131,6 +138,68 @@ strcpy(buf + i, "unknown"); i += strlen(buf + i); break; + case 'e': /* 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; + case 'd': /* Delay-Time */ + n = 0; + if ((tmp = pairfind(request, + PW_ACCT_DELAY_TIME)) != NULL) { + n = tmp->lvalue; + } + sprintf(buf + i, "%d", n); + i += strlen(buf + i); + break; + case 'i': /* Session-ID */ + if ((tmp = pairfind(request, + PW_ACCT_SESSION_ID)) != NULL) + strcpy(buf + i, tmp->strvalue); + else + strcpy(buf + i, "unknown"); + i += strlen(buf + i); + break; + case 'r': /* Input-Octets */ + n = 0; + if ((tmp = pairfind(request, + PW_ACCT_INPUT_OCTETS )) != NULL) { + n = tmp->lvalue; + } + sprintf(buf + i, "%d", n); + i += strlen(buf + i); + break; + case 'w': /* Output-Octets */ + n = 0; + if ((tmp = pairfind(request, + PW_ACCT_OUTPUT_OCTETS )) != NULL) { + n = tmp->lvalue; + } + sprintf(buf + i, "%d", n); + i += strlen(buf + i); + break; + case 'q': /* Input-Packets */ + n = 0; + if ((tmp = pairfind(request, + PW_ACCT_INPUT_PACKETS )) != NULL) { + n = tmp->lvalue; + } + sprintf(buf + i, "%d", n); + i += strlen(buf + i); + break; + case 'y': /* Output-Packets */ + n = 0; + if ((tmp = pairfind(request, + PW_ACCT_OUTPUT_PACKETS )) != NULL) { + n = tmp->lvalue; + } + sprintf(buf + i, "%d", n); + i += strlen(buf + i); + break; default: buf[i++] = '%'; buf[i++] = *p; diff -u -r radiusd-cistron-1.5.4.3.orig/src/radius.h radiusd-cistron-1.5.4.3/src/radius.h --- radiusd-cistron-1.5.4.3.orig/src/radius.h Fri Oct 30 15:30:10 1998 +++ radiusd-cistron-1.5.4.3/src/radius.h Fri Nov 6 21:07:40 1998 @@ -133,6 +133,8 @@ #define PW_HINT 1040 #define PAM_AUTH_ATTR 1041 #define PW_LOGIN_TIME 1042 +#define PW_EXEC_PROGRAM_TIMEOUT 1043 +#define PW_EXEC_PROGRAM_ACCOUNT 1044 /* * INTEGER TRANSLATIONS diff -u -r radiusd-cistron-1.5.4.3.orig/src/radzap.c radiusd-cistron-1.5.4.3/src/radzap.c --- radiusd-cistron-1.5.4.3.orig/src/radzap.c Fri Jun 19 21:55:56 1998 +++ radiusd-cistron-1.5.4.3/src/radzap.c Fri Nov 6 21:03:43 1998 @@ -139,6 +139,11 @@ return 0; } +int radius_exec_program(char *cmd, VALUE_PAIR *request, VALUE_PAIR *reply, + int exec_wait, char **user_msg) +{ +} + UINT4 findnas(char *nasname) {