const char * stypeof(const char *ttyid) { struct ttyent *t; return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : NULL); }
int login_ttyok(login_cap_t *lc, const char *tty, const char *allowcap, const char *denycap) { int rc = 1; if (lc != NULL && tty != NULL && *tty != '\0') { struct ttyent *te; char *grp; char **ttl; te = getttynam(tty); /* Need group name */ grp = te ? te->ty_group : NULL; ttl = login_getcaplist(lc, allowcap, NULL); if (ttl != NULL && !login_str2inlist(ttl, tty, grp, 0)) rc = 0; /* tty or ttygroup not in allow list */ else { ttl = login_getcaplist(lc, denycap, NULL); if (ttl != NULL && login_str2inlist(ttl, tty, grp, 0)) rc = 0; /* tty or ttygroup in deny list */ } } return rc; }
static int isttystat(const char *tty, int flag) { struct ttyent *t; return ((t = getttynam(tty)) == NULL) ? 0 : !!(t->ty_status & flag); }
int rootterm(char *ttyn) { struct ttyent *t; return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE); }
char * stypeof(char *ttyid) { struct ttyent *t; return (ttyid && (t = getttynam(ttyid)) ? t->ty_type : login_getcapstr(lc, "term", UNKNOWN, UNKNOWN)); }
int rootterm(char *ttyn) { struct ttyent *t; /* XXX - stash output of getttynam() elsewhere */ return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE); }
void testValues() { f = 2; struct ttyent * result = getttynam(anystring()); if (result) { //@ assert valid_read_string_or_null(result->ty_name); } //@ assert f == 2; //@ assert vacuous: \false; }
PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv) { struct options options; struct ttyent *ttyfileinfo; struct passwd *pwd; int retval; const char *user, *ttyname; pam_std_option(&options, NULL, argc, argv); PAM_LOG("Options processed"); retval = pam_get_user(pamh, &user, NULL); if (retval != PAM_SUCCESS) PAM_RETURN(retval); PAM_LOG("Got user: %s", user); retval = pam_get_item(pamh, PAM_TTY, (const void **)&ttyname); if (retval != PAM_SUCCESS) PAM_RETURN(retval); PAM_LOG("Got TTY: %s", ttyname); /* Ignore any "/dev/" on the PAM_TTY item */ if (strncmp(TTY_PREFIX, ttyname, sizeof(TTY_PREFIX) - 1) == 0) ttyname += sizeof(TTY_PREFIX) - 1; /* If the user is not root, secure ttys do not apply */ pwd = getpwnam(user); if (pwd == NULL) PAM_RETURN(PAM_IGNORE); else if (pwd->pw_uid != 0) PAM_RETURN(PAM_SUCCESS); PAM_LOG("User is not root"); ttyfileinfo = getttynam(ttyname); if (ttyfileinfo == NULL) PAM_RETURN(PAM_SERVICE_ERR); PAM_LOG("Got ttyfileinfo"); if (ttyfileinfo->ty_status & TTY_SECURE) PAM_RETURN(PAM_SUCCESS); else { PAM_VERBOSE_ERROR("Not on secure TTY"); PAM_RETURN(PAM_PERM_DENIED); } }
/* * Change the specified ttys' flags. */ static int change_ttys(char **ttylist) { struct ttyent *tep; int rval; rval = 0; for (; *ttylist != NULL; ttylist++) { tep = getttynam(*ttylist); if (tep == NULL) { warnx("couldn't find an entry in %s for \"%s\"", _PATH_TTYS, *ttylist); rval = 1; continue; } if (change_ttyflags(tep)) rval = 1; } return (rval); }
/* * Bring the system up single user. */ static state_func_t single_user(void) { pid_t pid, wpid; int status; sigset_t mask; const char *shell; char *argv[2]; #ifdef SECURE struct ttyent *typ; struct passwd *pp; static const char banner[] = "Enter root password, or ^D to go multi-user\n"; char *clear, *password; #endif #ifdef DEBUGSHELL char altshell[128]; #endif if (Reboot) { /* Instead of going single user, let's reboot the machine */ sync(); reboot(howto); _exit(0); } shell = get_shell(); if ((pid = fork()) == 0) { /* * Start the single user session. */ open_console(); #ifdef SECURE /* * Check the root password. * We don't care if the console is 'on' by default; * it's the only tty that can be 'off' and 'secure'. */ typ = getttynam("console"); pp = getpwnam("root"); if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp && *pp->pw_passwd) { write_stderr(banner); for (;;) { clear = getpass("Password:"******"single-user login failed\n"); } } endttyent(); endpwent(); #endif /* SECURE */ #ifdef DEBUGSHELL { char *cp = altshell; int num; #define SHREQUEST "Enter full pathname of shell or RETURN for " write_stderr(SHREQUEST); write_stderr(shell); write_stderr(": "); while ((num = read(STDIN_FILENO, cp, 1)) != -1 && num != 0 && *cp != '\n' && cp < &altshell[127]) cp++; *cp = '\0'; if (altshell[0] != '\0') shell = altshell; } #endif /* DEBUGSHELL */ /* * Unblock signals. * We catch all the interesting ones, * and those are reset to SIG_DFL on exec. */ sigemptyset(&mask); sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); /* * Fire off a shell. * If the default one doesn't work, try the Bourne shell. */ char name[] = "-sh"; argv[0] = name; argv[1] = 0; execv(shell, argv); emergency("can't exec %s for single user: %m", shell); execv(_PATH_BSHELL, argv); emergency("can't exec %s for single user: %m", _PATH_BSHELL); sleep(STALL_TIMEOUT); _exit(1); } if (pid == -1) { /* * We are seriously hosed. Do our best. */ emergency("can't fork single-user shell, trying again"); while (waitpid(-1, (int *) 0, WNOHANG) > 0) continue; return (state_func_t) single_user; } requested_transition = 0; do { if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) collect_child(wpid); if (wpid == -1) { if (errno == EINTR) continue; warning("wait for single-user shell failed: %m; restarting"); return (state_func_t) single_user; } if (wpid == pid && WIFSTOPPED(status)) { warning("init: shell stopped, restarting\n"); kill(pid, SIGCONT); wpid = -1; } } while (wpid != pid && !requested_transition); if (requested_transition) return (state_func_t) requested_transition; if (!WIFEXITED(status)) { if (WTERMSIG(status) == SIGKILL) { /* * reboot(8) killed shell? */ warning("single user shell terminated."); sleep(STALL_TIMEOUT); _exit(0); } else { warning("single user shell terminated, restarting"); return (state_func_t) single_user; } } runcom_mode = FASTBOOT; return (state_func_t) runcom; }
/* * Figure out what kind of terminal we're dealing with, and then read in * its termcap entry. */ const char * get_termcap_entry(char *userarg, char **tcapbufp) { struct ttyent *t; int rval; char *p, *ttypath; const char *ttype; if (userarg) { ttype = userarg; goto found; } /* Try the environment. */ if ((ttype = getenv("TERM"))) goto map; /* Try ttyname(3); check for dialup or other mapping. */ if ((ttypath = ttyname(STDERR_FILENO))) { if ((p = strrchr(ttypath, '/'))) ++p; else p = ttypath; if ((t = getttynam(p))) { ttype = t->ty_type; goto map; } } /* If still undefined, use "unknown". */ ttype = "unknown"; map: ttype = mapped(ttype); /* * If not a path, remove TERMCAP from the environment so we get a * real entry from /etc/termcap. This prevents us from being fooled * by out of date stuff in the environment. */ found: if ((p = getenv("TERMCAP")) != NULL && *p != '/') unsetenv("TERMCAP"); /* * ttype now contains a pointer to the type of the terminal. * If the first character is '?', ask the user. */ if (ttype[0] == '?') { if (ttype[1] != '\0') ttype = askuser(ttype + 1); else ttype = askuser(NULL); } /* Find the termcap entry. If it doesn't exist, ask the user. */ while ((rval = tgetent(tbuf, ttype)) == 0) { warnx("terminal type %s is unknown", ttype); ttype = askuser(NULL); } if (rval == -1) errx(1, "termcap: %s", strerror(errno ? errno : ENOENT)); *tcapbufp = tbuf; return (ttype); }
/* * Figure out what kind of terminal we're dealing with, and then read in * its termcap entry. */ static const char * get_termcap_entry(char *userarg) { int errret; char *p; const char *ttype; #if HAVE_GETTTYNAM struct ttyent *t; #else FILE *fp; #endif char *ttypath; if (userarg) { ttype = userarg; goto found; } /* Try the environment. */ if ((ttype = getenv("TERM")) != 0) goto map; if ((ttypath = ttyname(STDERR_FILENO)) != 0) { p = _nc_basename(ttypath); #if HAVE_GETTTYNAM /* * We have the 4.3BSD library call getttynam(3); that means * there's an /etc/ttys to look up device-to-type mappings in. * Try ttyname(3); check for dialup or other mapping. */ if ((t = getttynam(p))) { ttype = t->ty_type; goto map; } #else if ((fp = fopen("/etc/ttytype", "r")) != 0 || (fp = fopen("/etc/ttys", "r")) != 0) { char buffer[BUFSIZ]; char *s, *t, *d; while (fgets(buffer, sizeof(buffer), fp) != NULL) { for (s = buffer, t = d = 0; *s; s++) { if (isspace(UChar(*s))) *s = '\0'; else if (t == 0) t = s; else if (d == 0 && s != buffer && s[-1] == '\0') d = s; } if (t != 0 && d != 0 && !strcmp(d, p)) { ttype = strdup(t); fclose(fp); goto map; } } fclose(fp); } #endif /* HAVE_GETTTYNAM */ } /* If still undefined, use "unknown". */ ttype = "unknown"; map:ttype = mapped(ttype); /* * If not a path, remove TERMCAP from the environment so we get a * real entry from /etc/termcap. This prevents us from being fooled * by out of date stuff in the environment. */ found:if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) { /* 'unsetenv("TERMCAP")' is not portable. * The 'environ' array is better. */ int n; for (n = 0; environ[n] != 0; n++) { if (!strncmp("TERMCAP=", environ[n], 8)) { while ((environ[n] = environ[n + 1]) != 0) { n++; } break; } } } /* * ttype now contains a pointer to the type of the terminal. * If the first character is '?', ask the user. */ if (ttype[0] == '?') { if (ttype[1] != '\0') ttype = askuser(ttype + 1); else ttype = askuser(0); } /* Find the terminfo entry. If it doesn't exist, ask the user. */ while (setupterm((NCURSES_CONST char *) ttype, STDOUT_FILENO, &errret) != OK) { if (errret == 0) { (void) fprintf(stderr, "%s: unknown terminal type %s\n", _nc_progname, ttype); ttype = 0; } else { (void) fprintf(stderr, "%s: can't initialize terminal type %s (error %d)\n", _nc_progname, ttype, errret); ttype = 0; } ttype = askuser(ttype); } #if BROKEN_LINKER tgetflag("am"); /* force lib_termcap.o to be linked for 'ospeed' */ #endif return (ttype); }
void runFailure() { getttynam(NULL); }
void runSuccess() { getttynam(anystring()); }
/* * Bring the system up single user. */ state_func_t single_user(void) { pid_t pid, wpid; int status; sigset_t mask; const char *shell; char *argv[2]; #ifdef SECURE struct ttyent *typ; struct passwd *pp; static const char banner[] = "Enter root password, or ^D to go multi-user\n"; char *clear, *password; #endif #ifdef DEBUGSHELL char altshell[128]; #endif if (Reboot) { /* Instead of going single user, let's reboot the machine */ sync(); alarm(2); pause(); reboot(howto); _exit(0); } shell = get_shell(); if ((pid = fork()) == 0) { /* * Start the single user session. */ setctty(_PATH_CONSOLE); #ifdef TESTBED #define TERMCMD "/bootcmd" if (access(TERMCMD, F_OK) == 0) { FILE *fp; char cmd[256], *bp; char *myargv[3]; /* * Very simple; the file contains the path of a * command to run. No arguments supported, sorry. */ if ((fp = fopen(TERMCMD, "r")) == NULL) { /* Lets avoid loops! */ unlink(TERMCMD); goto skip; } if (fgets(cmd, sizeof(cmd), fp) == NULL) { fclose(fp); /* Lets avoid loops! */ unlink(TERMCMD); goto skip; } fclose(fp); /* Lets avoid loops! */ unlink(TERMCMD); if ((bp = rindex(cmd, '\n'))) *bp = '\0'; if (access(cmd, X_OK) != 0) { emergency("%s does not exist!", cmd); goto skip; } /* See comment below */ sigemptyset(&mask); sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); char name[] = "-sh"; myargv[0] = name; myargv[1] = cmd; myargv[2] = 0; execv(_PATH_BSHELL, myargv); stall("can't exec %s for %s: %m", _PATH_BSHELL, cmd); } /* * If something goes wrong, we want to sit in single user mode * so that we might catch the error. Not sure, might have to * do something fancier, like perhaps add a state transition * for this */ skip: #endif #ifdef SECURE /* * Check the root password. * We don't care if the console is 'on' by default; * it's the only tty that can be 'off' and 'secure'. */ typ = getttynam("console"); pp = getpwnam("root"); if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp && *pp->pw_passwd) { write_stderr(banner); for (;;) { clear = getpass("Password:"******"single-user login failed\n"); } } endttyent(); endpwent(); #endif /* SECURE */ #ifdef DEBUGSHELL { char *cp = altshell; int num; #define SHREQUEST "Enter full pathname of shell or RETURN for " write_stderr(SHREQUEST); write_stderr(shell); write_stderr(": "); while ((num = read(STDIN_FILENO, cp, 1)) != -1 && num != 0 && *cp != '\n' && cp < &altshell[127]) cp++; *cp = '\0'; if (altshell[0] != '\0') shell = altshell; } #endif /* DEBUGSHELL */ /* * Unblock signals. * We catch all the interesting ones, * and those are reset to SIG_DFL on exec. */ sigemptyset(&mask); sigprocmask(SIG_SETMASK, &mask, (sigset_t *) 0); /* * Fire off a shell. * If the default one doesn't work, try the Bourne shell. */ char name[] = "-sh"; argv[0] = name; argv[1] = 0; execv(shell, argv); emergency("can't exec %s for single user: %m", shell); execv(_PATH_BSHELL, argv); emergency("can't exec %s for single user: %m", _PATH_BSHELL); sleep(STALL_TIMEOUT); _exit(1); } if (pid == -1) { /* * We are seriously hosed. Do our best. */ emergency("can't fork single-user shell, trying again"); while (waitpid(-1, (int *) 0, WNOHANG) > 0) continue; return (state_func_t) single_user; } requested_transition = 0; do { if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) collect_child(wpid); if (wpid == -1) { if (errno == EINTR) continue; warning("wait for single-user shell failed: %m; restarting"); return (state_func_t) single_user; } if (wpid == pid && WIFSTOPPED(status)) { warning("init: shell stopped, restarting\n"); kill(pid, SIGCONT); wpid = -1; } } while (wpid != pid && !requested_transition); if (requested_transition) return (state_func_t) requested_transition; if (!WIFEXITED(status)) { if (WTERMSIG(status) == SIGKILL) { /* * reboot(8) killed shell? */ warning("single user shell terminated."); sleep(STALL_TIMEOUT); _exit(0); } else { warning("single user shell terminated, restarting"); return (state_func_t) single_user; } } runcom_mode = FASTBOOT; return (state_func_t) runcom; }