--- radiusd.h.orig Wed Nov 4 07:39:25 1998 +++ radiusd.h Sun Dec 13 13:53:17 1998 @@ -63,4 +63,5 @@ int attribute; int type; + int exec; int length; /* of strvalue */ UINT4 lvalue; @@ -226,4 +227,5 @@ int user_find(char *name, VALUE_PAIR *, VALUE_PAIR **, VALUE_PAIR **); +int userparse(char *buffer, VALUE_PAIR **first_pair); void presuf_setup(VALUE_PAIR *request_pairs); int hints_setup(VALUE_PAIR *request_pairs); @@ -264,3 +266,3 @@ /* exec.c */ char *radius_xlate(char *, VALUE_PAIR *req, VALUE_PAIR *reply); - +int radius_exec_list(VALUE_PAIR *request, VALUE_PAIR *reply, VALUE_PAIR *first_pair); --- files.c.orig Sat Oct 31 16:27:40 1998 +++ files.c Sun Dec 13 14:10:56 1998 @@ -55,5 +55,4 @@ #include "radiusd.h" -static int userparse(char *buffer, VALUE_PAIR **first_pair); static int huntgroup_match(VALUE_PAIR *, char *); #ifdef NDBM @@ -1026,4 +1025,15 @@ check_tmp = paircopy(pl->check); reply_tmp = paircopy(pl->reply); + /* + * Backtick support by Alan DeKok + * For example: + * + * Session-Timeout = `echo 5` + * + * FIXME: check error codes! + * What do we do if there's a problem? + */ + radius_exec_list(request_pairs, *reply_pairs, reply_tmp); + pairmove(reply_pairs, &reply_tmp); pairmove(check_pairs, &check_tmp); @@ -1078,12 +1088,14 @@ * past the data field. */ -static void fieldcpy(char *string, int len, char **uptr) +static int fieldcpy(char *string, int len, char **uptr) { char *ptr; + char c; ptr = *uptr; - if(*ptr == '"') { + c = *ptr; + if (c == '"' || c == '`') { ptr++; - while(*ptr != '"' && *ptr != '\0' && *ptr != '\n') { + while(*ptr != c && *ptr != '\0' && *ptr != '\n') { if (len-- > 0) *string++ = *ptr++; @@ -1092,9 +1104,9 @@ } *string = '\0'; - if(*ptr == '"') { + if(*ptr == c) { ptr++; } *uptr = ptr; - return; + return (c == '"' ? 1 : 2); } @@ -1108,5 +1120,5 @@ *string = '\0'; *uptr = ptr; - return; + return 0; /* not a quoted string */ } @@ -1119,5 +1131,5 @@ * Parse the buffer to extract the attribute-value pairs. */ -static int userparse(char *buffer, VALUE_PAIR **first_pair) +int userparse(char *buffer, VALUE_PAIR **first_pair) { int mode; @@ -1168,5 +1180,5 @@ case PARSE_MODE_VALUE: /* Value */ - fieldcpy(valstr, sizeof(valstr), &buffer); + x = fieldcpy(valstr, sizeof(valstr), &buffer); if((pair = (VALUE_PAIR *)malloc(sizeof(VALUE_PAIR))) == (VALUE_PAIR *)NULL) { @@ -1177,4 +1189,17 @@ pair->attribute = attr->value; pair->type = attr->type; + + /* + * Check for `foo` as value + */ + if (x == 2) { + pair->exec = 1; + strcpy(pair->strvalue, valstr); + pairadd(first_pair, pair); + mode = PARSE_MODE_NAME; + break; + } else { + pair->exec = 0; + } switch(pair->type) { --- exec.c.orig Sun Dec 13 13:09:34 1998 +++ exec.c Sun Dec 13 14:18:37 1998 @@ -301,2 +301,60 @@ } +/* + * Backtick support by Alan DeKok + * + * Loop over the given list, parsing any backtick commands. + * For each backtick'd attribute, a 'Exec-Program-Wait' is done, + * and the output is used as a value string to the userparse() routine. + * + * Some of the translations are taken from the PREVIOUS reply attributes + * + * %f Framed IP address + * %c Callback-Number + * %t MTU + * %a Protocol (SLIP/PPP) + * + * That is, the following will NOT work: + * + * DEFAULT Framed-Protocol = PPP + * Framed-MTU = `/find/mtu/for/protocol/ %a` + * + * NO error checking is done. This is bad. :( + */ +int radius_exec_list(VALUE_PAIR *request, VALUE_PAIR *reply, VALUE_PAIR *first_pair) +{ + int rcode; + char buffer[1024]; + char *user_msg; + VALUE_PAIR *pair, *parsed, *next; + + for (pair = first_pair; pair; pair = pair->next) { + if (!pair->exec) continue; + + DEBUG("Backticks: %s = `%s`", pair->name, pair->strvalue); + + /* + * Exec the program + */ + rcode = radius_exec_program(pair->strvalue, request, reply, 1, &user_msg); + + if (pair->type != PW_TYPE_STRING) { + sprintf(buffer, "%s = %s", pair->name, user_msg); + } else { + sprintf(buffer, "%s = \"%s\"", pair->name, user_msg); + } + parsed = NULL; + if (userparse(buffer, &parsed) != 0) { + DEBUG("error parsing %s", buffer); + return -1; + } + + next = pair->next; + memcpy(pair, parsed, sizeof(VALUE_PAIR)); + parsed->next = NULL; + pairfree(parsed); + pair->next = next; + } + + return 0; +}