From ced9dffda28f1ec2b060f3e419cf3c6b964b03a1 Mon Sep 17 00:00:00 2001 From: Erik Troan Date: Tue, 16 Sep 1997 14:12:05 +0000 Subject: Initial revision --- src/Makefile | 26 +++++++++++ src/doexec.1 | 12 +++++ src/doexec.c | 6 +++ src/netreport.1 | 22 ++++++++++ src/netreport.c | 45 +++++++++++++++++++ src/testd.c | 7 +++ src/testdinit | 44 +++++++++++++++++++ src/usernetctl.1 | 18 ++++++++ src/usernetctl.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/usleep.1 | 20 +++++++++ src/usleep.c | 37 ++++++++++++++++ 11 files changed, 367 insertions(+) create mode 100644 src/Makefile create mode 100644 src/doexec.1 create mode 100644 src/doexec.c create mode 100644 src/netreport.1 create mode 100644 src/netreport.c create mode 100644 src/testd.c create mode 100755 src/testdinit create mode 100644 src/usernetctl.1 create mode 100644 src/usernetctl.c create mode 100644 src/usleep.1 create mode 100644 src/usleep.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 00000000..b3324ef6 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,26 @@ +CFLAGS+=-Wall + +PROGS=usernetctl doexec netreport testd usleep + +all: $(PROGS) + +clean: + rm -f $(PROGS) + +install: + mkdir -p $(ROOT)/bin $(ROOT)/usr/sbin $(ROOT)/usr/man/man1 + install -o 0 -g 0 -s -m 755 doexec $(ROOT)/bin/doexec + install -o 0 -g 0 -s -m 755 usleep $(ROOT)/bin/usleep + install -o 0 -g 0 -s -m 4755 usernetctl $(ROOT)/usr/sbin/usernetctl + install -o 0 -g 0 -s -m 2755 netreport $(ROOT)/sbin/netreport + install -m 644 doexec.1 $(ROOT)/usr/man/man1 + install -m 644 netreport.1 $(ROOT)/usr/man/man1 + install -m 644 usleep.1 $(ROOT)/usr/man/man1 + install -m 644 usernetctl.1 $(ROOT)/usr/man/man1 + +# this daemon and initscript are useful for testing the up/down/status stuff +# not installed by default, only comes from sources. +install-test: + install -o 0 -g 0 -s -m 755 testd $(ROOT)/usr/sbin/testd + install -o 0 -g 0 -m 755 testdinit $(ROOT)/etc/rc.d/init.d/testd + diff --git a/src/doexec.1 b/src/doexec.1 new file mode 100644 index 00000000..59b8b91e --- /dev/null +++ b/src/doexec.1 @@ -0,0 +1,12 @@ +.TH DOEXEC 1 "Red Hat Software" "RHS" \" -*- nroff -*- +.SH NAME +doexec \- run an executable with an arbitrary argv[0] +.SH SYNOPSIS +.B doexec +\fI/path/to/executable\fP \fIargv[0]\fP [\fIargv[1-n]\fP] +.SH DESCRIPTION +.B doexec +simply runs the executable with the argv list provided. It allows you +to specify an argv[0] other than the name of the executable. +.SH OPTIONS +All options are passed in the argv list to the executable being run. diff --git a/src/doexec.c b/src/doexec.c new file mode 100644 index 00000000..a488be13 --- /dev/null +++ b/src/doexec.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char ** argv) { + execvp(argv[1], argv + 2); + return 1; +} diff --git a/src/netreport.1 b/src/netreport.1 new file mode 100644 index 00000000..ff52e91b --- /dev/null +++ b/src/netreport.1 @@ -0,0 +1,22 @@ +.TH USERNETCTL 1 "Red Hat Software" "RHS" \" -*- nroff -*- +.SH NAME +netreport \- request notification of network interface changes +.SH SYNOPSIS +.B netreport +\fI[\fP-r\fI]\fP +.SH DESCRIPTION +.B netreport +tells the network management scripts to send a SIGIO signal +to the process which called netreport when any network interface +status changes occur. +.SH OPTIONS +.TP +.B -r +Remove the current request (if any) for the calling process. +.PP +.SH NOTES +If a program does not call netreport with the +.B -r +option before it exits, and another process is created with the +same PID before any changes take place in interface status, it +is possible that the new process will receive a spurious SIGIO. diff --git a/src/netreport.c b/src/netreport.c new file mode 100644 index 00000000..56088ec1 --- /dev/null +++ b/src/netreport.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include + +/* this will be running setgid root, so be careful! */ + +void usage(void) { + fprintf(stderr, "usage: netreport [-r]\n"); + exit(1); +} + +#define ADD 1 +#define DEL 0 +int main(int argc, char ** argv) { + int action = ADD; + /* more than long enough for "/var/run/netreport/\0" */ + char netreport_name[64]; + int netreport_file; + + if (argc > 2) usage(); + + if ((argc > 1) && !strcmp(argv[1], "-r")) { + action = DEL; + } + + sprintf(netreport_name, "/var/run/netreport/%d", getppid()); + if (action == ADD) { + netreport_file = creat(netreport_name, 0); + if (netreport_file < 0) { + if (errno != EEXIST) { + perror("Could not create netreport file"); + exit (1); + } + } else { + close(netreport_file); + } + } else { + /* ignore errors; not much we can do, won't hurt anything */ + unlink(netreport_name); + } + + exit(0); +} diff --git a/src/testd.c b/src/testd.c new file mode 100644 index 00000000..f512cec9 --- /dev/null +++ b/src/testd.c @@ -0,0 +1,7 @@ +#include +#include + +void main() { + signal(SIGTERM, SIG_IGN); + while (1) sleep(20); +} diff --git a/src/testdinit b/src/testdinit new file mode 100755 index 00000000..f2f4a85b --- /dev/null +++ b/src/testdinit @@ -0,0 +1,44 @@ +#!/bin/sh +# +# lpd This shell script takes care of starting and stopping +# lpd (printer daemon). +# + +# Source function library. +. /etc/rc.d/init.d/functions + +# See how we were called. +case "$1" in + start) + # Start daemons. + echo -n "Starting testd: " + testd & + echo + touch /var/lock/subsys/testd + ;; + stop) + # Stop daemons. + echo -n "Shutting down testd: " + killproc testd + echo + rm -f /var/lock/subsys/testd + ;; + status) + # Am I alive? + status testd + exit $? + ;; + restart) + echo -n "Shutting down testd: " + killproc testd + echo + echo -n "Starting testd: " + testd & + echo + ;; + *) + echo "Usage: testd {start|stop|status|restart}" + exit 1 +esac + +exit 0 diff --git a/src/usernetctl.1 b/src/usernetctl.1 new file mode 100644 index 00000000..1602f7b5 --- /dev/null +++ b/src/usernetctl.1 @@ -0,0 +1,18 @@ +.TH USERNETCTL 1 "Red Hat Software" "RHS" \" -*- nroff -*- +.SH NAME +usernetctl \- allow a user to manipulate a network interface if permitted +.SH SYNOPSIS +.B usernetctl +\fIconfig-file-name\fP up\fI|\fPdown +.SH DESCRIPTION +.B usernetctl +checks to see if users are allowed to manipulate the network interface +specified by \fIconfig-file-name\fP, and then tries to bring the network +interface up or down, as specified. +.SH OPTIONS +.TP +.I "\fIconfig-file-name" +The name of the network configuration file to read; for example, ifcfg-ppp0 +.TP +up\fI|\fPdown +Attempt to bring the interface up or down. diff --git a/src/usernetctl.c b/src/usernetctl.c new file mode 100644 index 00000000..1139a8c5 --- /dev/null +++ b/src/usernetctl.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* this will be running setuid root, so be careful! */ + +void usage(void) { + fprintf(stderr, "usage: usernetctl \n"); + exit(1); +} + +static char * safeEnviron[] = { + "PATH=/bin:/sbin:/usr/bin:/usr/sbin", + "HOME=/root", + NULL +}; + +int userCtl(char * file, int size) { + char * contents; + char * chptr; + char * end; + int fd; + + contents = alloca(size + 2); + + if ((fd = open(file, O_RDONLY)) < 0) { + fprintf(stderr, "failed to open %s: %s\n", file, strerror(errno)); + exit(1); + } + + if (read(fd, contents, size) != size) { + perror("error reading device configuration"); + exit(1); + } + close(fd); + + contents[size] = '\n'; + contents[size + 1] = '\0'; + + /* each pass parses a single line (until an answer is found), contents + itself points to the beginning of the current line */ + while (*contents) { + chptr = contents; + while (*chptr != '\n') chptr++; + end = chptr + 1; + while (chptr > contents && isspace(*chptr)) chptr--; + *(++chptr) = '\0'; + + if (!strcmp(contents, "USERCTL=yes")) return 1; + + contents = end; + } + + return 0; +} + +int main(int argc, char ** argv) { + char * ifaceConfig; + char * chptr; + struct stat sb; + char * cmd; + + if (argc != 3) usage(); + + if (!strcmp(argv[2], "up")) { + cmd = "./ifup"; + } else if (!strcmp(argv[2], "down")) { + cmd = "./ifdown"; + } else { + usage(); + } + + if (chdir("/etc/sysconfig/network-scripts")) { + fprintf(stderr, "error switching to /etc/sysconfig/network-scripts: " + "%s\n", strerror(errno)); + exit(1); + } + + /* force the interface configuration to be in the current directory */ + chptr = ifaceConfig = argv[1]; + while (*chptr) { + if (*chptr == '/') + ifaceConfig = chptr + 1; + chptr++; + } + + /* these shouldn't be symbolic links -- anal, but that's fine w/ me */ + if (lstat(ifaceConfig, &sb)) { + fprintf(stderr, "failed to stat %s: %s\n", ifaceConfig, + strerror(errno)); + exit(1); + } + + /* safety checks */ + if (!S_ISREG(sb.st_mode)) { + fprintf(stderr, "%s is not a normal file\n", ifaceConfig); + exit(1); + } + + if (sb.st_uid) { + fprintf(stderr, "%s should be owned by root\n", ifaceConfig); + exit(1); + } + + if (sb.st_mode & S_IWOTH) { + fprintf(stderr, "%s should not be world writeable\n", ifaceConfig); + exit(1); + } + + if (!userCtl(ifaceConfig, sb.st_size)) { + fprintf(stderr, "Users are not allowed to control this interface.\n"); + exit(1); + } + + /* looks good to me -- let's go for it */ + + /* pppd wants the real uid to be the same as the effective (god only + knows why when it works fine setuid out of the box) */ + setuid(geteuid()); + + execle(cmd, cmd, ifaceConfig, NULL, safeEnviron); + fprintf(stderr, "exec of %s failed: %s\n", cmd, strerror(errno)); + + exit(1); +} diff --git a/src/usleep.1 b/src/usleep.1 new file mode 100644 index 00000000..f1e19025 --- /dev/null +++ b/src/usleep.1 @@ -0,0 +1,20 @@ +.TH USLEEP 1 "Red Hat Software" "RHS" \" -*- nroff -*- +.SH NAME +usleep \- sleep some number of microseconds +.SH SYNOPSIS +.B usleep +[\fInumber\fP] +.SH DESCRIPTION +.B usleep +sleeps some number of microseconds. The default is 1. +.SH OPTIONS +\fI--help\fP +Print help information. +.TP +\fI-v\fP +Print version information. +.SH BUGS +Probably not accurate on many machines down to the microsecond. Count +on precision only to -4 or maybe -5. +.SH AUTHOR +Donald Barnes diff --git a/src/usleep.c b/src/usleep.c new file mode 100644 index 00000000..dbffc850 --- /dev/null +++ b/src/usleep.c @@ -0,0 +1,37 @@ +/* + * usleep + * + * Written by Donald Barnes for Red Hat Software. + * + */ + + +#include +#include +#include +#include + +void main(int argc, char **argv) +{ + + double count; + + if (argc == 1) count=1; + else if (!strcmp(argv[1], "--help")) + { + printf("usleep [number]\n sleep [number] of microseconds\n the default number to sleep is 1 microsecond\n"); + exit(0); + } + else if (!strcmp(argv[1], "-v")) + { + printf("usleep version 1.0 by Donald Barnes \n usleep --help for more info\n"); + exit(0); + } + else + count = strtod(argv[1], NULL); + + usleep(count); + exit(0); + + +} -- cgit v1.2.1