[1557] in linux-security and linux-alert archive
[linux-security] an anti-overflow wrapper
daemon@ATHENA.MIT.EDU (Thomas Roessler)
Tue May 27 05:51:22 1997
Date: Mon, 26 May 1997 19:53:51 +0200
From: Thomas Roessler <roessler@guug.de>
To: linux-security@redhat.com
Resent-From: linux-security@redhat.com
Reply-To: linux-security@redhat.com
The following code is a first attempt at a simple but flexible
suid wrapper which checks argv[] and environment. It might
introduce new security holes or have other bugs; using 1 as a
general failure exit value may be the wrong thing to do. The
wrapper reads a configuration file named /etc/wrapper.cfg; see
the comments in wrapper.c for the file's format.
Flame, comment, or use at will.
tlr
------------------------------ wrapper.c ------------------------------
/*
* wrapper.c (c) 1997 Thomas Roessler <roessler@guug.de>
* $Id: wrapper.c,v 1.2 1997/05/26 17:39:09 roessler Exp $
*
* This program is free software. You may use, modify or distribute it
* at will as long as you give credit to the original author.
*
* format of /etc/wrapper.cfg:
* - leading white space is ignored.
* - lines starting with a hash sign (#) are ignored.
* - empty lines are ignored.
*
* Each line consists of three whitespace-separated fields:
* <program> <what> <size>
*
* <program> is the real path name as compiled into the wrapper as REALPROG,
* <what> can either be the string "argv", a $ sign followed by the name
* of an environment variable or a $ sign followed by an asterisk
* to match all environment variables passed to the program.
*
* Sample:
*
* /usr/X11R6/bin/xterm argv 1024
* /usr/X11R6/bin/xterm $HOME 1024
* /usr/X11R6/bin/xterm $* 2048
*
* To wrap, e.g., xterm, move /usr/X11R6/bin/xterm to
* /usr/X11R6/bin/xterm.wrapped, compile this wrapper by typing
* cc -DREALPROG=\"/usr/X11R6/bin/xterm\" wrapper.c -o xterm,
* and move it to /usr/X11R6/bin/xterm. Don't forget to remove
* the suid bits from the wrapped program and to add them to the
* wrapper!
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <syslog.h>
#include <unistd.h>
#define BUFFSIZE 1024
#define CFGFILE "/etc/wrapper.cfg"
extern char **environ;
void syntax(const char *s)
{
syslog(LOG_ERR, "WRAPPER: error in %s: %s.", CFGFILE, s);
fprintf(stderr, "Syntax error in %s. Please notify the system\n"
"administration.\n", CFGFILE);
}
int main(int argc, char *argv[])
{
FILE *cfgfile;
char buff[BUFFSIZE];
char *f = NULL;
char *s;
char *t;
char *u;
char *key;
char *value;
char **e;
size_t len;
int i;
openlog(argv[0], 0, LOG_AUTHPRIV);
if(!(cfgfile = fopen(CFGFILE, "r"))) {
syslog(LOG_ERR, "WRAPPER: Can't open %s: %m.", CFGFILE);
exit(1);
}
while(fgets(buff, sizeof(buff), cfgfile)) {
if(!(s = strchr(buff, '\n'))) {
syntax("Long line.");
exit(1);
}
*s = '\0';
/* ignore leading whitespace */
for(s = buff; *s && isspace(*s); s++)
;
if(*s == '\0' || *s == '#')
continue;
if(!(s = strtok(s, " \t"))) {
syntax("Syntax error.");
exit(1);
}
if(!strcmp(s, REALPROG)) {
if(!(s = strtok(NULL, " \t")) || !(t = strtok(NULL, " \t"))) {
syntax("Syntax error.");
exit(1);
}
len = strtoul(t, NULL, 0);
if(!len) {
syntax("Bad number.");
exit(1);
}
if(*s == '$') { /* environment variable */
s++;
for(e = environ; *e; e++) {
if((f = strdup(*e)) == NULL) {
syslog(LOG_ERR, "WRAPPER: Out of memory. %m.");
fprintf(stderr, "Out of memory.\n");
exit(1);
}
if(!(u = strchr(f, '='))) {
syslog(LOG_ALERT, "WRAPPER: Insane environment entry: %s.",
f);
exit(1);
}
key = f;
*u++ = '\0';
value = u;
if((*s == '*' || !strcmp(s, key)) && strlen(value) > len) {
syslog(LOG_ALERT, "WRAPPER: $%s is too long.",
key);
exit(1);
}
free(f);
}
} else if(!strcasecmp(s, "argv")) { /* argument vector */
for(i = 0; i < argc; i++) {
if(strlen(argv[i]) > len) {
syslog(LOG_ALERT, "WRAPPER: Security violation: argument too long."
"(uid = %d, euid = %d)",
(int) getuid(), (int) geteuid());
exit(1);
}
}
} else { /* syntax error */
syntax("Unknown check.");
exit(1);
}
}
}
fclose(cfgfile);
closelog();
execv(REALPROG ".wrapped", argv);
syslog(LOG_ERR, "WRAPPER: can't exec %s: %m.",
REALPROG ".wrapped");
exit(1);
}
------------------------------ Makefile ------------------------------
SUID_PROGS=/usr/X11R6/bin/xterm
CFLAGS=-Wall -Wstrict-prototypes -pedantic
all: $(SUID_PROGS)
clean:
rm -f *~ *.o
for i in $(SUID_PROGS) ; do rm -f `basename $$i` ; done
$(SUID_PROGS): wrapper.c
$(CC) $(CFLAGS) -DREALPROG=\"$@\" -o `basename $@` $^
------------------------------ The End ------------------------------