|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 18613 (0x48b5)
Types: TextFile
Names: »system.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/unaxcess/system.c«
/*
* @(#)system.c 1.2 (TDI) 2/3/87
* @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
* @(#)This file is part of UNaXcess version 1.0.2.
*
* Permission is hereby granted to copy and distribute this program
* freely. Permission is NOT given to modify this program or distribute
* it at cost, except for charging a reasonable media/copying fee.
*/
#ifndef lint
static char _FileID_[] = "@(#)system.c 1.2 (TDI) 2/3/87";
static char _UAID_[] = "@(#)UNaXcess version 1.0.2";
#endif lint
#include "ua.h"
struct sys parms = {
#ifdef NOAUTOPATH
NOAUTOPATH,
#else
"/usr/unaxcess",
#endif NOAUTOPATH
1,
0,
"/bin/sh",
1,
"unaxcess",
30,
"sysop",
1,
0,
"",
"",
3,
"trap '' 2; stty -echo; echo 'Begin sending your file. End with a CONTROL-D.'; cat - > %s; stty echo",
"trap '' 2; cat %s",
"umodem -rbld",
"umodem -sbld",
"kermit -iwr ;:",
"kermit -iws",
A_GUEST,
};
#define NUM 0
#define STR 1
#define BOOL 2
struct rparm {
char *parmname;
char parmtype;
char *parmval;
} sysparms[] = {
"bbs-directory",STR, parms.ua_home,
"readonly", BOOL, &parms.ua_roc,
"restricted", BOOL, &parms.ua_xrc,
"shell", STR, parms.ua_shell,
"read-env", BOOL, &parms.ua_env,
"bbs-user", STR, parms.ua_bbs,
"time-limit", NUM, &parms.ua_tlimit,
"sysop", STR, parms.ua_sysop,
"private-msgs", BOOL, &parms.ua_pm,
"logging", BOOL, &parms.ua_log,
"banner", STR, parms.ua_bnr,
"login-msg", STR, parms.ua_login,
"login-tries", NUM, &parms.ua_nla,
"ascii-upload", STR, parms.ua_auc,
"ascii-download",STR, parms.ua_adc,
"xmodem-upload",STR, parms.ua_xuc,
"xmodem-download",STR, parms.ua_xdc,
"kermit-upload",STR, parms.ua_kuc,
"kermit-download",STR, parms.ua_kdc,
"validation-level",NUM, &parms.ua_vaxs,
0, 0, 0,
};
static FILE *lfp;
static int __tlog = 0;
short critical = 0;
short quitc = 0;
short intr = 0;
short alrm = 0;
short warned = 0;
logon() {
struct stat sb;
char *cp;
if (!parms.ua_log || stat(LOG, &sb) < 0) { /* no logfile => no logging */
lfp = NULL;
return;
}
if ((lfp = fopen(LOG, "a")) == NULL) {
io_off();
perror(LOG);
fprintf(stderr, "panic: log\n");
exit(2);
}
}
log(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
char *fmt, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9; {
char buf[1024];
static char lockfile[] = "logfile.lock";
if (lfp == NULL) /* logging not enabled */
return;
CRIT();
sprintf(buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
mklock(lockfile);
fprintf(lfp, "%s (%05d) %s\n", date(), getpid(), visible(buf));
fflush(lfp);
rmlock(lockfile);
NOCRIT();
}
logsig(sig)
int sig; {
static int dbl = 0; /* OOPS! 9 lines added 2/3/87 ++bsa */
if (dbl++) {
fprintf(stderr, "\r\n\r\nDOUBLE PANIC: SIG %d\r\n\r\n", sig);
setuid(getuid());
chdir("/tmp");
signal(SIGIOT, SIG_DFL);
kill(getpid(), SIGIOT);
}
dolog();
log("Received signal %d.", sig);
fprintf(stderr, "\r\n\r\nUNaXcess internal error: %d.\r\n\r\n", sig);
unlink(RIndex(ttyname(fileno(stdin)), '/') + 1);
io_off();
signal(SIGIOT, SIG_DFL);
setuid(getuid()); /* OOPS! 2 lines added */
chdir(getpwuid(getuid())->pw_dir); /* 2/3/87 ++bsa */
kill(getpid(), SIGIOT);
}
panic(s)
char *s; {
static int dbl = 0; /* OOPS! 9 lines added 2/3/87 ++bsa */
if (dbl++) {
fprintf(stderr, "\r\n\r\nDOUBLE PANIC: %s\r\n\r\n", s);
setuid(getuid());
chdir("/tmp");
signal(SIGIOT, SIG_DFL);
kill(getpid(), SIGIOT);
}
dolog();
log("panic: %s", s);
fprintf(stderr, "\r\n\r\nUNaXcess internal error: %s\r\n\r\n", s);
io_off();
unlink(RIndex(ttyname(2), '/') + 1);
setuid(getuid());
chdir(getpwuid(getuid())->pw_dir);
signal(SIGIOT, SIG_DFL);
kill(getpid(), SIGIOT);
}
quit() {
char line[256];
if (critical) {
quitc++;
return;
}
writes("\n\nFast logout\n");
signal(SIGQUIT, quit);
log("Signalled QUIT.");
writef("\nDo you really want to leave UNaXcess? N\b");
line[0] = readc();
if (line[0] == 'Y') {
writef("OK");
if (user.u_name[0] != '\0')
writef(", %s", upstr(user.u_name));
writef(". See you later!\n\n\n");
cleanup();
}
}
intrp() {
if (critical) {
intr++;
return;
}
writes("\n\nAborted.");
log("Command aborted.");
signal(SIGINT, intrp);
longjmp(cmdloop, 1);
}
char *visible(s)
char *s; {
static char vs[256];
char *sp, *vp;
vp = vs;
for (sp = s; *sp != '\0'; sp++)
if (!iscntrl(*sp))
*vp++ = *sp;
else {
*vp++ = '^';
*vp++ = uncntrl(*sp);
}
*vp = '\0';
return vs;
}
shell() {
short sig;
if (user.u_access == A_GUEST || user.u_access == A_USER || parms.ua_shell[0] == '\0') {
writes("You don't have shell access privileges.");
log("Security violation: Unauthorized SHELL");
return 1;
}
switch (fork()) {
case -1:
log("Error %d forking shell", errno);
writes("Sorry, the system's full. Try again later.");
return 1;
case 0:
for (sig = SIGINT; sig <= SIGTERM; sig++)
signal(sig, SIG_DFL);
setuid(getuid());
chdir(getpwuid(getuid())->pw_dir);
run(parms.ua_shell, 0);
log("Error %d exec'ing %s", errno, parms.ua_shell);
writes("Couldn't run the shell.");
exit(1);
default:
CRIT();
io_off();
for (sig = SIGINT; sig <= SIGTERM; sig++)
signal(sig, SIG_IGN);
signal(SIGALRM, thatsall); /* trapped by the CRIT() */
wait(NULL);
signal(SIGINT, intrp);
signal(SIGQUIT, quit);
for (sig = SIGIOT; sig < SIGTERM; sig++)
signal(sig, logsig);
signal(SIGALRM, thatsall);
io_on(0);
NOCRIT();
}
return 1;
}
thatsall() {
if (critical) {
alrm++;
return;
}
if (warned) {
log("Timeout.");
writes("\nI'm sorry, but you're out of time.\n\n");
cleanup();
}
else {
log("5-minute warning.");
writes("\nYou have only five minutes left in this session.\n\n");
warned = 1;
alarm(5 * 60);
}
}
mklock(lockfile)
char *lockfile; {
char lockpath[50];
int lock_fd;
struct stat statbuf;
long now;
strcpy(lockpath, "lock/");
strcat(lockpath, lockfile);
while (stat(lockpath, &statbuf) == 0) {
time(&now);
if (now - statbuf.st_mtime > 90) { /* OOPS! 2/3/87 ++bsa */
unlink(lockpath);
break;
}
sleep(5); /* OOPS! 1 line added 2/3/87 ++bsa */
}
if ((lock_fd = creat(lockpath, 0600)) < 0) {
fprintf(stderr, "Errno = %d creating lockfile %s\n", errno, lockpath);
/* OOPS! 1 line deleted 2/3/87 ++bsa */
panic(lockpath);
}
close(lock_fd);
sync(); /* insure disk files are updated! */
}
rmlock(lockfile)
char *lockfile; {
char lockpath[50];
struct stat statbuf;
sync();
strcpy(lockpath, "lock/");
strcat(lockpath, lockfile);
if (stat(lockpath, &statbuf) < 0) {
log("Lockfile %s deleted???", lockpath);
writef("\n\nSomeone futzed with the lockfile. Please tell %s IMMEDIATELY!!!\nSorry, but this means I have to log you out now.\n\n", parms.ua_sysop);
panic("LOCKFILE DELETED");
}
if (unlink(lockpath) < 0) {
log("Errno = %d, can't unlink lockfile %s", errno, lockpath);
writes("\nI've got a lockfile problem. You won't be able to do some\nthings until it's fixed. Sorry...\n");
}
}
CRIT() {
alrm = 0;
quitc = 0;
intr = 0;
if (critical)
return; /* clears pending signals */
critical = 1;
}
NOCRIT() {
if (!critical)
return;
critical = 0;
if (alrm)
thatsall(14);
if (quitc)
quit(3);
if (intr)
intrp(2);
alrm = 0;
quitc = 0;
intr = 0;
}
run(cmd, arg)
char *cmd, *arg; {
char cmdbuf[5120];
sprintf(cmdbuf, "%s %s", cmd, (arg? arg: ""));
execl("/bin/sh", "sh", "-c", cmdbuf, 0);
return -1;
}
copylink(src, dest)
char *src, *dest; {
int srcp, destp, cnt;
char buf[1024];
if (link(src, dest) == 0) {
unlink(src);
return 0;
}
if ((srcp = open(src, 0)) < 0) {
perror(src);
return -1;
}
unlink(dest);
if ((destp = creat(dest, 0600)) < 0) {
perror(dest);
return -1;
}
while ((cnt = read(srcp, buf, sizeof buf)) > 0)
write(destp, buf, cnt);
close(destp);
close(srcp);
return 0;
}
s_cmp(s1, s2)
char *s1, *s2; {
for (; *s1 != '\0' && ToLower(*s1) == ToLower(*s2); s1++, s2++)
;
return (!(*s1 == '\0' && *s2 == '\0'));
}
char *upstr(s)
char *s; {
static char sbuf[512];
register char *cp, *dp;
for (cp = s, dp = sbuf; *cp != '\0'; cp++, dp++)
*dp = ToUpper(*cp);
*dp = '\0';
return sbuf;
}
ismember(word, list)
char *word, *list; {
char *cp;
char oldch;
while (*list != '\0') {
while (*list == ' ' || *list == '\t')
list++;
for (cp = list; *cp != '\0' && *cp != ',' && *cp != ' ' && *cp != '\t'; cp++)
;
oldch = '\0';
if (*cp != '\0') {
oldch = *cp;
*cp++ = '\0';
}
if (strcmp(word, list) == 0) {
*(cp - 1) = oldch;
return 1;
}
*(cp - 1) = oldch;
list = cp;
}
return 0;
}
dolog() {
if (lfp != (FILE *) 0 || __tlog)
return;
logon();
__tlog = 1;
}
nolog() {
if (!__tlog || lfp == (FILE *) 0)
return;
fclose(lfp);
__tlog = 0;
}
alter() {
char line[256], uname[256];
char *p, *q, *okcmds;
struct user ubuf;
short crypted, not_FW;
char cmd;
if (user.u_access == A_MKUSER) {
log("An A_MKUSER got into alter()???");
panic("newalter");
}
if (user.u_access != A_WITNESS) {
not_FW = 1;
log("Alter by non-Witness; restricting control modes.");
strcpy(line, user.u_name);
}
else {
line[0] = '\0';
not_FW = 0;
writef("Examine which user: ");
reads(line);
log("User: %s", line);
if (line[0] == '\0')
return 1;
for (p = line; *p != '\0'; p++)
*p = ToLower(*p);
line[32] = '\0';
}
if (!getuser(line, &ubuf))
if (not_FW) {
log("Can't locate current user in the userfile.");
panic("user");
}
else {
writef("No such user. Create him ? N\b");
strcpy(ubuf.u_name, line);
line[0] = readc();
log("New user? %c", line[0]);
if (line[0] != 'Y')
return 1;
ubuf.u_pass[0] = '\0';
ubuf.u_access = A_USER;
ubuf.u_llen = 80;
ubuf.u_nbull = 0;
strcpy(ubuf.u_lconf, "general");
ubuf.u_lines = 24;
crypted = 0;
}
else if (strlen(ubuf.u_pass) == 0)
crypted = 0;
else
crypted = 1;
strcpy(uname, ubuf.u_name);
for (;;) {
writec('\n');
writef("Name: %s\n", ubuf.u_name);
writef("Password: %s%s\n", ubuf.u_pass, (crypted? " (encrypted)": ""));
writef("Access level: %s\n", ua_acl(ubuf.u_access));
if (ubuf.u_access == A_MKUSER) {
writef("Default access level: %s\n", ua_acl(ubuf.u_llen));
okcmds = "NPADKQF";
}
else {
writef("UNIX(R) login name: %s\n", ubuf.u_login);
writef("Login conference: %s\n", ubuf.u_lconf);
writef("Line size: %d\n", ubuf.u_llen);
writef("Screen lines: %d\n", ubuf.u_lines);
if (ubuf.u_access == A_WITNESS && s_cmp(user.u_name, parms.ua_sysop) != 0 && s_cmp(user.u_name, uname) != 0)
okcmds = "Q";
else if (user.u_access < A_WITNESS)
okcmds = "PUCSLQF";
else if (s_cmp(user.u_name, uname) == 0)
okcmds = "NPUCSLQF";
else
okcmds = "NPAUCLSKQF";
}
writef("\nAlter command (");
for (p = okcmds; *p != '\0'; p++)
switch (*p) {
case 'N':
writef("Name, ");
break;
case 'P':
writef("Password, ");
break;
case 'A':
writef("Access, ");
break;
case 'U':
writef("UNIX(R) login, ");
break;
case 'C':
writef("Conference, ");
break;
case 'L':
writef("Lines, ");
break;
case 'S':
writef("Size, ");
break;
case 'D':
writef("Default access, ");
break;
case 'K':
writef("Kill, ");
break;
case 'Q':
writef("Quit, ");
break;
case 'F':
writef("Finished, ");
break;
default:
log("Invalid internal alter() command: '%c'", *p);
panic("altercmd");
}
writef("or ? for help): ");
cmd = readc();
log("Change: %c", cmd);
if (cmd != '?' && Index(okcmds, cmd) == (char *) 0)
cmd = ' ';
switch (cmd) {
case 'K':
writef("Kill user -- are you sure? N\b");
cmd = readc();
log("Kill user? %c", cmd);
if (cmd != 'Y')
break;
putuser(uname, (struct user *) 0);
writef("User %s killed.\n", upstr(uname));
return 1;
case 'N':
writef("Enter new name: ");
reads(line);
log("Name: %s", line);
if (line[0] == '\0')
break;
for (p = line; *p != '\0'; p++)
if (*p == ':') {
log("Illegal colon in name.");
writes("Can't put a colon in a user name.");
break;
}
for (p = line, q = ubuf.u_name; *p != '\0'; p++, q++)
*q = ToLower(*p);
*q = '\0';
break;
case 'P':
strcpy(line, getpass("Enter new password: "));
if (line[0] == '\0')
break;
strcpy(ubuf.u_pass, line);
crypted = 0; /* it's not encrypted now */
break;
case 'A':
writef("Access level: Deny access, Guest, Messages, Files, System, Witness, Newuser? ");
cmd = readc();
log("Access: %c", cmd);
if (cmd == 'A' && s_cmp(user.u_name, parms.ua_sysop) != 0) {
writes("Sorry, only the sysop can administer Witness privileges.");
log("Security violation: WITNESS administering WITNESS");
break;
}
switch (cmd) {
case 'G':
ubuf.u_access = A_GUEST;
break;
case 'D':
ubuf.u_access = A_NONE;
break;
case ' ':
break;
case 'M':
ubuf.u_access = A_USER;
break;
case 'S':
ubuf.u_access = A_SYSTEM;
break;
case 'W':
ubuf.u_access = A_WITNESS;
break;
case 'N':
ubuf.u_access = A_MKUSER;
break;
case 'F':
ubuf.u_access = A_FILES;
break;
default:
writes("What? Valid commands are D, G, M, F, S, W, and N. Access unchanged.");
}
break;
case 'C':
writef("Enter the default login conference: ");
reads(line);
log("Login conference: %s", line);
if (line[0] =='\0')
break;
if (!isconf(line))
writes("That conference doesn't exist.");
else if (uisunsub(ubuf.u_name, line))
writef("%s isn't subscribed to %s.\n", upstr(ubuf.u_name), line);
else if (!isrcmem(ubuf.u_name, line))
writef("%s isn't a member of that conference.\n", upstr(ubuf.u_name));
else
strcpy(ubuf.u_lconf, line);
break;
case 'S':
writef("Enter new line size, 32-132: ");
reads(line);
log("Line length: %s", line);
if (line[0] == '\0')
break;
ubuf.u_llen = atoi(line);
if (ubuf.u_llen < 32 || ubuf.u_llen > 132) {
ubuf.u_llen = 80;
writes("Garbage line size; using 80.");
}
break;
case 'U':
writef("UNIX(R) login name? ");
reads(line);
log("Login name: %s", line);
if (strlen(line) > 8) {
writes("That name is too long.");
break;
}
strcpy(ubuf.u_login, line);
break;
case 'D':
writef("Default Access: Deny access, Guest, Messages, Files, System? ");
cmd = readc();
log("Dft Access: %c", cmd);
switch (cmd) {
case 'G':
ubuf.u_llen = A_GUEST;
break;
case 'D':
ubuf.u_llen = A_NONE;
break;
case ' ':
break;
case 'M':
ubuf.u_llen = A_USER;
break;
case 'S':
ubuf.u_access = A_SYSTEM;
break;
case 'F':
ubuf.u_access = A_FILES;
break;
default:
writes("What? Valid commands are D, G, M, F, or S. Default access unchanged.");
}
break;
case 'Q':
if (okcmds[1] != '\0') {
writef("Abort user examine, are you sure? N\b");
cmd = readc();
log("Abort? %c", cmd);
if (cmd != 'Y')
break;
}
return 1;
case 'F':
if (!crypted) {
writes("Encrypting password, please wait...");
strcpy(ubuf.u_pass, crypt(ubuf.u_pass, ubuf.u_pass) + 2);
}
putuser(uname, &ubuf);
if (s_cmp(uname, user.u_name) == 0)
user = ubuf;
return 1;
case 'L':
writef("Enter new lines/screen, 0-66: ");
reads(line);
log("Lines/screen: %s", line);
if (line[0] == '\0')
break;
ubuf.u_lines = atoi(line);
if (ubuf.u_lines < 0 || ubuf.u_lines > 66) {
ubuf.u_lines = 24;
writes("Garbage lines/screen; using 24.");
}
break;
case '?':
writef("\nThe commands are self-documenting. If you don't see a command, it's because you can't perform that command on the current user.\n");
break;
default:
writef("What? Please enter one of ");
for (p = okcmds; *p != '\0'; p++) {
writec(*p);
writec(',');
writec(' ');
}
writes("or ? for help.");
}
}
}
getparms() {
char home[512], line[512], var[20], sval[50];
FILE *cfp;
short cnt, pos, scnt, canon;
#ifdef NOAUTOPATH
strcpy(home, NOAUTOPATH);
#else
strcpy(home, getpwuid(geteuid())->pw_dir);
#endif NOAUTOPATH
strcpy(parms.ua_home, home);
strcpy(line, home);
strcat(line, "/");
strcat(line, CONFIG);
if ((cfp = fopen(line, "r")) == NULL) {
fprintf(stderr, "panic: param get, %s\n", line);
exit(1);
}
while (fgets(line, 512, cfp) != NULL) {
line[strlen(line) - 1] = '\0';
if (Index(line, '#') != NULL)
*(Index(line, '#')) = '\0';
scnt = 0;
pos = 0;
while (line[pos] != '\0' && line[pos] != ' ' && line[pos] != '\t')
var[scnt++] = line[pos++];
var[scnt] = '\0';
if (var[0] == '\0')
continue;
for (cnt = 0; sysparms[cnt].parmname != NULL; cnt++)
if (strcmp(sysparms[cnt].parmname, var) == 0)
break;
if (sysparms[cnt].parmname == NULL) {
fprintf(stderr, "Please inform the sysop that there is an invalid parameter\n%s in the setup file.\n", var);
continue;
}
while (line[pos] == ' ' || line[pos] == '\t')
pos++;
switch (sysparms[cnt].parmtype) {
case NUM:
*((char *) sysparms[cnt].parmval) = atoi(&line[pos]) & 0xff;
break;
case BOOL:
if (line[pos] == '\0' || ToLower(line[pos]) == 'y')
*((char *) sysparms[cnt].parmval) = 1;
else
*((char *) sysparms[cnt].parmval) = 0;
break;
case STR:
canon = 0;
if (line[pos] == '"') {
canon = 1;
pos++;
}
for (scnt = 0; (canon? line[pos] != '"': line[pos] != '\0' && line[pos] != ' ' && line[pos] != '\t'); pos++, scnt++) {
if (canon && line[pos] == '\\') {
switch (line[++pos]) {
case 'n':
sval[scnt] = '\n';
break;
case 't':
sval[scnt] = '\t';
break;
case 'r':
sval[scnt] = '\r';
break;
case 'b':
sval[scnt] = '\b';
break;
case 'f':
sval[scnt] = '\f';
break;
case 'e':
case 'E':
sval[scnt] = '\033';
break;
case 'a':
sval[scnt] = '\7'; /* proposed extension of C string metasyntax */
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
sval[scnt] = 0;
while (Index("01234567", line[pos]) != NULL)
sval[scnt] = sval[scnt] * 8 + (line[pos++] - '0');
pos--;
break;
default:
sval[scnt] = line[pos];
}
}
else
sval[scnt] = line[pos];
}
sval[scnt] = '\0';
strcpy(sysparms[cnt].parmval, sval);
}
}
}