--- radiusd-livingston-2.1.orig/src/menu.c
+++ radiusd-livingston-2.1/src/menu.c
@@ -65,6 +65,7 @@
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
+#include <string.h>
#include "radius.h"
@@ -72,6 +73,47 @@
extern char *radacct_dir;
extern char *progname;
+/*************************************************************************
+ *
+ * Function: validfilename
+ *
+ * Purpose: Check to make sure a filename is valid
+ * I.e. weed out nasties
+ *
+ *************************************************************************/
+
+/* Valid characters in a filename */
+static char *validfilname_chars =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890#-+ \t/";
+
+int
+validfilename(filename)
+char *filename;
+{
+ /* Not a valid filename if it is NULL or zero length */
+ if(filename==NULL || *filename=='\0'){
+ return(0);
+ }
+
+ /* Check each character in the filename to make sure
+ * it is valid as per validfilname_chars
+ */
+ while(*filename!='\0'){
+ if(strchr(validfilname_chars, *filename)==NULL){
+ return(0);
+ }
+ filename++;
+ }
+
+ /* Not a filename if it ends with a '/' */
+ if(*filename=='/'){
+ return(0);
+ }
+
+ return(1);
+}
+
+
void
process_menu(authreq, activefd, pw_digest)
AUTH_REQ *authreq;
@@ -84,10 +126,10 @@
VALUE_PAIR *get_attribute();
VALUE_PAIR *menu_pairs();
VALUE_PAIR *pairalloc();
- char menu_name[128];
+ char menu_name[256];
char menu_input[32];
int i;
- char state_value[128];
+ char state_value[256];
void send_accept();
void send_reject();
void pairfree();
@@ -96,7 +138,8 @@
if((attr = get_attribute(authreq->request, PW_STATE)) !=
(VALUE_PAIR *)NULL && strncmp(attr->strvalue, "MENU=", 5) == 0){
- strcpy(menu_name, &attr->strvalue[5]);
+ strncpy(menu_name, &attr->strvalue[5], sizeof(menu_name)-1);
+ menu_name[sizeof(menu_name)-1] = '\0';
/* The menu input is in the Password Field */
attr = get_attribute(authreq->request, PW_PASSWORD);
@@ -121,7 +164,8 @@
(VALUE_PAIR *)NULL) {
/* Change this to a menu state */
- sprintf(state_value, "MENU=%s", term_attr->strvalue);
+ snprintf(state_value, sizeof(state_value), "MENU=%s",
+ term_attr->strvalue);
term_attr->attribute = PW_STATE;
strcpy(term_attr->strvalue, state_value);
strcpy(term_attr->name, "Challenge-State");
@@ -168,7 +212,8 @@
int len;
sprintf(menu_buffer, "%s/menus/%s", radius_dir, menu_name);
- if((fd = fopen(menu_buffer, "r")) == (FILE *)NULL) {
+ if(!validfilename(menu_buffer) ||
+ (fd = fopen(menu_buffer, "r")) == (FILE *)NULL) {
return("\r\n*** User Menu is Not Available ***\r\n");
}
@@ -176,7 +221,7 @@
nread = 0;
ptr = menu_buffer;
*ptr = '\0';
- while(fgets(ptr, 4096 - nread, fd) != NULL && nread < 4096) {
+ while(fgets(ptr, 4096 - nread - 4, fd) != NULL && nread < 4096) {
if(mode == 0) {
if(strncmp(ptr, "menu", 4) == 0) {
@@ -221,14 +266,16 @@
int fclose();
sprintf(buffer, "%s/menus/%s", radius_dir, menu_name);
- if((fd = fopen(buffer, "r")) == (FILE *)NULL) {
+ if(!validfilename(buffer) ||
+ (fd = fopen(buffer, "r")) == (FILE *)NULL) {
return((VALUE_PAIR *)NULL);
}
/* Skip past the menu */
mode = 0;
nread = 0;
- while(fgets(buffer, sizeof(buffer), fd) != NULL) {
+ while(fgets(buffer, sizeof(buffer) - 1, fd) != NULL) {
+ buffer[sizeof(buffer)-1]='\0';
if(mode == 0) {
if(strncmp(buffer, "menu", 4) == 0) {
mode = 1;
@@ -251,7 +298,8 @@
reply_first = (VALUE_PAIR *)NULL;
/* Look for a matching menu entry */
- while(fgets(buffer, sizeof(buffer), fd) != NULL) {
+ while(fgets(buffer, sizeof(buffer)-1, fd) != NULL) {
+ buffer[sizeof(buffer)-1]='\0';
/* Terminate the buffer */
ptr = buffer;
@@ -265,7 +313,7 @@
if(strcmp(selection, buffer) == 0 ||
strcmp("DEFAULT", buffer) == 0) {
/* We have a match */
- while(fgets(buffer, sizeof(buffer), fd) != NULL) {
+ while(fgets(buffer, sizeof(buffer)-1, fd) != NULL) {
if(*buffer == ' ' || *buffer == '\t') {
/*
* Parse the reply values