diff -ruN radius/README.security.patch radius.mark/README.security.patch
--- radius/README.security.patch	Thu Jan  1 10:00:00 1970
+++ radius.mark/README.security.patch	Thu Jul  5 14:17:13 2001
@@ -0,0 +1,27 @@
+
+5th July 2001
+Horms (Simon Horman) <horms@valinux.com>, <horms@vergenet.net>
+VA Linux Systems, Pty., Ltd.
+
+Mark Dowd <mark@vergenet.net>
+
+This package includes patches in response to a vulnerability published by
+Internet Security Systems, Inc. (http://www.iss.net) on the 5th July 2001,
+relating to buffer overflows.
+
+This patch addresses immediate risks raised by this vulnerability and
+is intended as a minimal set of changes to secure systems.
+
+This patch and a more comprehensive patch is available from:
+
+ftp://ftp.vergenet.net/pub/lucent_radius/
+
+
+This patch has been prepared with the assistance of:
+
+Wichert Akkerman <wichert@valinux.com>, <wakkerma@debian.org>
+VA Linux Systems, BV
+
+Andrew Tridgell <tridge@valinux.com>, <tridge@samba.org>
+VA Linux Systems, Pty., Ltd.
+
diff -ruN radius/src/log.c radius.mark/src/log.c
--- radius/src/log.c	Thu Jun 24 09:40:39 1999
+++ radius.mark/src/log.c	Thu Jul  5 13:26:21 2001
@@ -98,6 +98,24 @@
 
 /*************************************************************************
  *
+ *	Function: log_info
+ *
+ *	Purpose: Log the debug message
+ *
+ *************************************************************************/
+
+void
+log_info(char * fmt, ...)
+{
+	va_list	args;
+	
+	va_start(args, fmt);
+	log_msg(LOG_INFO, fmt, args);
+	va_end(args);
+}
+
+/*************************************************************************
+ *
  *	Function: log_msg
  *
  *	Purpose: Log the priority message
@@ -145,8 +163,8 @@
 		 */
 		openlog("radius", LOG_PID | LOG_CONS | LOG_NOWAIT, LOG_AUTH);
 #ifdef VSYSLOG
-		vsprintf(buffer, fmt, args);
-		syslog(priority, buffer);
+		vsnprintf(buffer, sizeof(buffer), fmt, args);
+		syslog(priority, "%s", buffer);
 #else /* not VSYSLOG */
 		vsyslog(priority, fmt, args);
 #endif /* not VSYSLOG */
@@ -154,3 +172,5 @@
 	}
 	return;
 }
+
+
diff -ruN radius/src/menu.c radius.mark/src/menu.c
--- radius/src/menu.c	Thu Jun 24 09:40:40 1999
+++ radius.mark/src/menu.c	Thu Jul  5 00:32:08 2001
@@ -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
diff -ruN radius/src/radiusd.c radius.mark/src/radiusd.c
--- radius/src/radiusd.c	Thu Jun 24 09:40:42 1999
+++ radius.mark/src/radiusd.c	Thu Jul  5 00:18:25 2001
@@ -1588,7 +1588,8 @@
 	if (callpair == (VALUE_PAIR *)NULL || callpair->lvalue > 20) {
 		callfrom[0] = '\0';
 	} else {
-		sprintf(callfrom," at %s",callpair->strvalue);
+		snprintf(callfrom, sizeof(callfrom), " at %s",
+                        callpair->strvalue);
 	}
 
 	/*
@@ -2044,7 +2045,8 @@
 	/* Check to see if the response is a menu */
 	if((menu_attr = get_attribute(reply, PW_MENU)) != (VALUE_PAIR *)NULL) {
 		msg = get_menu(menu_attr->strvalue);
-		sprintf(state_value, "MENU=%s", menu_attr->strvalue);
+		snprintf(state_value, sizeof(state_value), "MENU=%s", 
+                        menu_attr->strvalue);
 		send_challenge(authreq, msg, state_value, activefd);
 		return;
 	}
diff -ruN radius/src/users.c radius.mark/src/users.c
--- radius/src/users.c	Thu Jun 24 09:40:44 1999
+++ radius.mark/src/users.c	Thu Jul  5 00:19:21 2001
@@ -407,7 +407,7 @@
 
 		case PARSE_MODE_NAME:
 			/* Attribute Name */
-			fieldcpy(attrstr, &buffer);
+			fieldcpy(attrstr, &buffer, sizeof(attrstr)-1);
 			if((attr = dict_attrfind(attrstr)) ==
 						(DICT_ATTR *)NULL) {
 				return(-1);
@@ -428,7 +428,7 @@
 
 		case PARSE_MODE_VALUE:
 			/* Value */
-			fieldcpy(valstr, &buffer);
+			fieldcpy(valstr, &buffer, sizeof(valstr)-1);
 
 			pair = pairalloc("userparse");
 
@@ -514,17 +514,19 @@
  *************************************************************************/
 
 static	void
-fieldcpy(string, uptr)
+fieldcpy(string, uptr, len)
 char	*string;
 char	**uptr;
+int len;
 {
 	char	*ptr;
 
 	ptr = *uptr;
 	if(*ptr == '"') {
 		ptr++;
-		while(*ptr != '"' && *ptr != '\0' && *ptr != '\n') {
+		while(*ptr != '"' && *ptr != '\0' && *ptr != '\n' && len > 0) {
 			*string++ = *ptr++;
+                        len--;
 		}
 		*string = '\0';
 		if(*ptr == '"') {
@@ -535,8 +537,9 @@
 	}
 
 	while(*ptr != ' ' && *ptr != '\t' && *ptr != '\0' && *ptr != '\n' &&
-						*ptr != '=' && *ptr != ',') {
+						*ptr != '=' && *ptr != ',' && len > 0) {
 			*string++ = *ptr++;
+                        len--;
 	}
 	*string = '\0';
 	*uptr = ptr;
diff -ruN radius/src/version.c radius.mark/src/version.c
--- radius/src/version.c	Thu Jun 24 09:40:45 1999
+++ radius.mark/src/version.c	Thu Jul  5 11:24:21 2001
@@ -87,20 +87,21 @@
 {
 	char buffer[1024];
 	void build_version();
-	void log_msg();
+	void log_info();
 
-	build_version(buffer);
-	log_msg(LOG_INFO, buffer);
+	build_version(buffer, sizeof(buffer));
+	log_info("%s", buffer);
 }
 
 void
-build_version(bp)
+build_version(bp, bp_len)
 char * bp;
+const size_t bp_len;
 {
 	extern int accept_zero;
 	extern int radius_dbm;
 
-	sprintf(bp, "%s: %s ", progname, VERSION);
+	snprintf(bp, bp_len-48, "%s: %s ", progname, VERSION);
 
 	/* here are all the conditional feature flags */
 
