精華區beta SetupBBS 關於我們 聯絡資訊
/*-------------------------------------------------------*/ /* xlogin.c ( NTHU CS MapleBBS Ver 2.36 ) */ /*-------------------------------------------------------*/ /* target : replace /bin/login for BBS */ /* create : 95/03/29 */ /* update : 95/12/15 */ /*-------------------------------------------------------*/ #include "config.h" #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <sys/param.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/resource.h> #include <sys/file.h> #include <termios.h> #ifdef HAS_UTMPX #include <utmpx.h> #else /* HAS_UTMPX */ #include <utmp.h> #endif /* HAS_UTMPX */ #ifndef UT_NAMESIZE #define UT_NAMESIZE sizeof(((struct UTMP_STRUCT *)0)->ut_name) #endif /* UT_NAMESIZE */ #include <signal.h> #include <errno.h> #ifndef NO_TTYENT #include <ttyent.h> #endif /* NO_TTYENT */ #include <syslog.h> #include <grp.h> #include <pwd.h> #include <setjmp.h> #include <stdio.h> #include <string.h> #ifndef TIOCSWINSZ #include <sys/ioctl.h> #endif #ifndef O_RDWR #include <fcntl.h> #endif #define TTYGRPNAME "tty" /* name of group to own ttys */ /* HP-UX 9.0 termios doesn't define these */ #ifndef FLUSHO #define FLUSHO 0 #define XTABS 0 #endif #ifndef OXTABS #define OXTABS XTABS #endif #define _PATH_DEFPATH "/usr/local/bin:/bin:/usr/bin:" /* #define _PATH_UTMP "/etc/utmp" */ struct passwd *pwd; char term[64], *hostname, *username, *tty; char xuser[sizeof(BBSUSER)] = BBSUSER; char xdir[sizeof(BBSHOME)] = BBSHOME; char xshell[sizeof(BBSSHELL)] = BBSSHELL; struct termios termios; void login(ut) struct utmp *ut; { register int fd; int tty; off_t lseek(); tty = ttyslot(); if (tty > 0 && (fd = open(_PATH_UTMP, O_WRONLY, 0)) >= 0) { (void) lseek(fd, (long) (tty * sizeof(struct utmp)), L_SET); (void) write(fd, (char *) ut, sizeof(struct utmp)); (void) close(fd); } } main(argc, argv) int argc; char **argv; { extern int optind; extern char *optarg, **environ; struct group *gr; register int ch; register char *p; int hflag, pflag, cnt; int ioctlval; void hungup(); char *salt, *ttyn, *pp = 0; char *ttyname(), *stypeof(); time_t time(); pwd = (struct passwd *) malloc(sizeof(struct passwd)); /* Do this before NIS+ or other library routines open files. */ for (cnt = getdtablesize(); cnt > 2; cnt--) close(cnt); (void) signal(SIGHUP, hungup); (void) signal(SIGQUIT, SIG_IGN); (void) signal(SIGINT, SIG_IGN); (void) setpriority(PRIO_PROCESS, 0, 0); /* * -p is used by getty to tell login not to destroy the environment -h is * used by other servers to pass the name of the remote host to login so * that it may be placed in utmp and wtmp */ hflag = pflag = 0; while ((ch = getopt(argc, argv, "h:p")) != EOF) switch (ch) { case 'h': if (getuid()) { fprintf(stderr, "login: -h for super-user only.\n"); exit(1); } hflag = 1; hostname = optarg; break; #ifndef SYSV_ENV /* System V login never preserves the * environment. */ case 'p': pflag = 1; break; #endif /* SYSV_ENV */ default: if (getuid()) syslog(LOG_ERR, "invalid flag %c", ch); fprintf(stderr, "usage: login [-h | -r] [username]\n"); exit(1); } argc -= optind; argv += optind; if (*argv) { username = *argv; #ifdef SYSV_ENV /* Pick up additional environment stuff after * logging in. */ argc--; argv++; #endif /* SYSV_ENV */ } /* * Finalize the terminal settings. Some systems default to 8 bits, others * to 7, so we should leave that alone. */ tcgetattr(0, &termios); termios.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON | IMAXBEL); termios.c_iflag &= ~IXANY; termios.c_lflag |= (ISIG | IEXTEN | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE); termios.c_lflag &= ~(ECHOPRT | TOSTOP | FLUSHO); termios.c_oflag |= (OPOST | ONLCR); termios.c_oflag &= ~OXTABS; termios.c_cc[VEOF] = 4; (void) tcsetattr(0, TCSANOW, &termios); /* * Determine the tty name. BSD takes the basename, SYSV4 takes whatever * remains after stripping the "/dev/" prefix. The code below should * produce sensible results in either environment. */ ttyn = ttyname(0); if (ttyn == NULL || *ttyn == '\0') ttyn = "/dev/tty??"; if (tty = strchr(ttyn + 1, '/')) ++tty; else tty = ttyn; /* setup pwd struct */ pwd->pw_name = xuser; pwd->pw_uid = 9999; pwd->pw_gid = 99; pwd->pw_dir = xdir; pwd->pw_shell = xshell; /* Update the utmp files, either BSD or SYSV style. */ { struct utmp utmp; memset((char *) &utmp, 0, sizeof(utmp)); (void) time(&utmp.ut_time); #if 0 strncpy(utmp.ut_name, username, sizeof(utmp.ut_name)); if (hostname) strncpy(utmp.ut_host, hostname, sizeof(utmp.ut_host)); strncpy(utmp.ut_line, tty, sizeof(utmp.ut_line)); login(&utmp); #endif } (void) chown(ttyn, pwd->pw_uid, (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); (void) chmod(ttyn, 0620); /* Give up root privileges: no way back from here. */ if (setgid(pwd->pw_gid)) { printf("login: bad gid: %d\n", pwd->pw_gid); sleepexit(0); } #if 0 initgroups(username, pwd->pw_gid); #endif if (setuid(pwd->pw_uid)) { printf("login: bad uid: %d\n", pwd->pw_uid); sleepexit(0); } /* * Now that we have given up root privilege do the stuff that must be done * as the real user: Kerberos or Secure RPC authentication, entering the * (possibly remote) home directory. */ /* Change to home directory */ if (chdir(pwd->pw_dir)) { printf("No directory %s!\n", pwd->pw_dir); sleepexit(0); } /* * Set up a new environment. With SYSV, some variables are always * preserved; some varables are never preserved, and some variables are * always clobbered. With BSD, nothing is always preserved, and some * variables are always clobbered. We add code to make sure that LD_* and * IFS are never preserved. */ #ifdef SYSV_ENV /* set up a somewhat censored environment. */ sysv_newenv(argc, argv, pwd, term); #else /* SYSV_ENV */ /* destroy environment unless user has requested preservation */ if (!pflag) environ[0] = 0; else fixenv(environ); (void) setenv("HOME", pwd->pw_dir, 1); (void) setenv("SHELL", pwd->pw_shell, 1); (void) setenv("REMOTEHOST", hostname, 1); #ifndef NO_TTYENT if (!pflag || !getenv("TERM")) { if (term[0] == 0) strncpy(term, stypeof(tty), sizeof(term)); (void) setenv("TERM", term, 0); } #endif /* NO_TTYENT */ (void) setenv("USER", pwd->pw_name, 1); (void) setenv("PATH", _PATH_DEFPATH, 0); #endif /* SYSV_ENV */ /* * After dropping privileges and after cleaning up the environment, * optionally run, as the user, /bin/passwd. */ (void) signal(SIGALRM, SIG_DFL); (void) signal(SIGHUP, SIG_DFL); (void) signal(SIGQUIT, SIG_DFL); (void) signal(SIGINT, SIG_DFL); (void) signal(SIGTSTP, SIG_IGN); execl(BBSPROG, "bbs", hostname, ttyn, NULL); fprintf(stderr, "login: no shell: "); perror(BBSPROG); sleepexit(0); } void hungup() { close(0); /* force EOF */ } #ifndef NO_TTYENT /* get terminal type from ttytab file */ #undef UNKNOWN #define UNKNOWN "su" char * stypeof(ttyid) char *ttyid; { struct ttyent *t; return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : UNKNOWN); } #endif /* !NO_TTYENT */ sleepexit(eval) int eval; { sleep((u_int) 5); exit(eval); } setenv(name, value, overwrite) #ifdef NETBSD const char *name; const char *value; #else char *name; char *value; #endif int overwrite; { char *p; if (overwrite == 0 && getenv(name) != 0) return (0); if ((p = malloc(strlen(name) + strlen(value) + 2)) == 0) { fprintf(stderr, "out of memory\n"); sleepexit(1); } sprintf(p, "%s=%s", name, value); return (putenv(p)); } fixenv(cpp) char **cpp; { register char **xpp; register char *cp; while (cp = *cpp) { if (strncmp(cp, "LD_", 3) == 0 || strncmp(cp, "IFS=", 4) == 0) { for (xpp = cpp; xpp[0] = xpp[1]; xpp++); /* void */ ; } else { cpp++; } } }