Date: Thu, 18 Nov 1999 14:53:34 -0500 (EST) From: danh@wzrd.com To: FreeBSD-gnats-submit@freebsd.org Subject: ports/14983: OpenSSH, support for login.conf Message-ID: <19991118195334.77F695D00B@mail.wzrd.com>
next in thread | raw e-mail | index | archive | help
>Number: 14983 >Category: ports >Synopsis: OpenSSH, support for login.conf >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Thu Nov 18 12:00:01 PST 1999 >Closed-Date: >Last-Modified: >Originator: Dan Harnett >Release: FreeBSD 3.3-STABLE i386 >Organization: >Environment: OpenSSH-1.2 port as of 11/18/99 running under FreeBSD 3.3-STABLE. >Description: This adds most of the capabilities of login.conf to OpenSSH. I had tried to set 'UseLogin yes' in sshd_config as a fix, since login could use the login capabilities database. That seemed to have broken scp functionality completely, leaving a coredump of my shell in my home directory (the core being owned by root). This patch is pretty clean and provides most of the capabilities provided in /etc/login.conf. This includes using ttys.[deny|allow], host.[deny|allow], and times.[deny|allow] capabilities. It also respects ignorenologin, and requirehome capabilities. >How-To-Repeat: >Fix: --- sshd.c.orig Thu Nov 18 12:41:25 1999 +++ sshd.c Thu Nov 18 14:01:10 1999 @@ -39,6 +39,11 @@ int deny_severity = LOG_WARNING; #endif /* LIBWRAP */ +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) +#include <login_cap.h> +#define DEFAULT_WARN (2L * 7L * 86400L) /* two weeks */ +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ + #ifndef O_NOCTTY #define O_NOCTTY 0 #endif @@ -931,6 +936,10 @@ { struct group *grp; int i; +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + login_cap_t *lc; + time_t now; +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ /* Shouldn't be called if pw is NULL, but better safe than sorry... */ if (!pw) @@ -993,6 +1002,45 @@ } } +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + + now = time(NULL); + + /* Return false if account has expired */ + if (pw->pw_expire) + { + if (pw->pw_expire <= now) + { + log("Account has expired for %s", pw->pw_name); + return 0; + } + } + + lc = login_getpwclass(pw); + + /* Check to see if the account is permitted to login from the + remote host. */ + if (auth_hostok(lc, NULL, get_remote_ipaddr()) == 0) + { + log("Authorization failed for %s from %s", + pw->pw_name, get_remote_ipaddr()); + login_close(lc); + return 0; + } + + /* Check to see if the account is permitted to login during + this time. */ + if (auth_timeok(lc, now) == 0) + { + log("Logins not available right now for %s", pw->pw_name); + login_close(lc); + return 0; + } + + login_close(lc); + +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ + /* We found no reason not to let this user try to log on... */ return 1; } @@ -1005,6 +1053,9 @@ do_authentication(char *user) { struct passwd *pw, pwcopy; +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + login_cap_t *lc; +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ #ifdef AFS /* If machine has AFS, set process authentication group. */ @@ -1027,6 +1078,11 @@ pwcopy.pw_gid = pw->pw_gid; pwcopy.pw_dir = xstrdup(pw->pw_dir); pwcopy.pw_shell = xstrdup(pw->pw_shell); +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + pwcopy.pw_class = xstrdup(pw->pw_class); + pwcopy.pw_expire = pw->pw_expire; + pwcopy.pw_change = pw->pw_change; +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ pw = &pwcopy; /* If we are not running as root, the user must have the same uid as the @@ -1759,6 +1815,11 @@ struct sockaddr_in from; int fromlen; struct pty_cleanup_context cleanup_context; +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + login_cap_t *lc; + char *motd; + char *copyright; +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ /* Get remote host name. */ hostname = get_canonical_hostname(); @@ -1822,6 +1883,12 @@ /* Check if .hushlogin exists. */ snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir); quiet_login = stat(line, &st) >= 0; + +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + lc = login_getpwclass(pw); + + quiet_login = login_getcapbool(lc, "hushlogin", quiet_login); +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ /* If the user has logged in before, display the time of last login. However, don't display anything extra if a command has been @@ -1849,8 +1916,24 @@ if (command == NULL && options.print_motd && !quiet_login && !options.use_login) { +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + copyright = login_getcapstr(lc, "copyright", + "/etc/COPYRIGHT", + "/etc/COPYRIGHT"); + f = fopen(copyright, "r"); + if (f) + { + while (fgets(line, sizeof(line), f)) + fputs(line, stdout); + fclose(f); + } + /* Print /etc/motd if it exists. */ + motd = login_getcapstr(lc, "welcome", "/etc/motd", "/etc/motd"); + f = fopen(motd, "r"); +#else /* FreeBSD && HAVE_LOGIN_CAP_H */ f = fopen("/etc/motd", "r"); +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ if (f) { while (fgets(line, sizeof(line), f)) @@ -1859,6 +1942,10 @@ } } +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + login_close(lc); +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ + /* Do common processing for the child, such as execing the command. */ do_child(command, pw, term, display, auth_proto, auth_data, ttyname); /*NOTREACHED*/ @@ -2010,9 +2097,39 @@ extern char **environ; struct stat st; char *argv[10]; +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + login_cap_t *lc; + char *nologin; + int ignore_nologin; + time_t now; + time_t warntime; +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ + +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + + lc = login_getpwclass(pw); + + /* Check if account is permitted to logon to this tty. */ + if (auth_ttyok(lc, ttyname) == 0) + { + log("Permission denied for %s on %s", pw->pw_name, ttyname); + fprintf(stderr, "Permission denied.\n"); + exit(254); + } + + /* It is possible to ignore nologin under FreeBSD. */ + if (!login_getcapbool(lc, "ignorenologin", 0)) + { + nologin = login_getcapstr(lc, "nologin", _PATH_NOLOGIN, _PATH_NOLOGIN); + f = fopen(nologin, "r"); + +#else /* FreeBSD && HAVE_LOGIN_CAP_H */ /* Check /etc/nologin. */ f = fopen("/etc/nologin", "r"); + +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ + if (f) { /* /etc/nologin exists. Print its contents and exit. */ while (fgets(buf, sizeof(buf), f)) @@ -2022,10 +2139,22 @@ exit(254); } +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + } + + /* Set user context. Will also call setlogin(2). */ + if (setusercontext(lc, pw, pw->pw_uid, + LOGIN_SETALL & ~(LOGIN_SETUSER | LOGIN_SETGROUP | LOGIN_SETENV))) + error("setusercontext failed: %s", strerror(errno)); + +#else /* FreeBSD && HAVE_LOGIN_CAP_H */ + /* Set login name in the kernel. */ if (setlogin(pw->pw_name) < 0) error("setlogin failed: %s", strerror(errno)); +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ + /* Set uid, gid, and groups. */ /* Login(1) does this as well, and it needs uid 0 for the "-h" switch, so we let login(1) to this for us. */ @@ -2053,10 +2182,21 @@ fatal("Failed to set uids to %d.", (int)pw->pw_uid); } +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + + shell = login_getcapstr(lc, "shell", pw->pw_shell, _PATH_BSHELL); + + if (*shell == '\0') + shell = _PATH_BSHELL; + +#else /* FreeBSD && HAVE_LOGIN_CAP_H */ + /* Get the shell from the password data. An empty shell field is legal, and means /bin/sh. */ shell = (pw->pw_shell[0] == '\0') ? _PATH_BSHELL : pw->pw_shell; +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ + #ifdef AFS /* Try to get AFS tokens for the local cell. */ if (k_hasafs()) { @@ -2080,7 +2220,7 @@ child_set_env(&env, &envsize, "USER", pw->pw_name); child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); child_set_env(&env, &envsize, "HOME", pw->pw_dir); - child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); + child_set_env(&env, &envsize, "PATH", _PATH_STDPATH "/usr/local/bin" "/usr/local/bin"); snprintf(buf, sizeof buf, "%.200s/%.50s", _PATH_MAILDIR, pw->pw_name); @@ -2190,8 +2330,19 @@ /* Change current directory to the user\'s home directory. */ if (chdir(pw->pw_dir) < 0) - fprintf(stderr, "Could not chdir to home directory %s: %s\n", + { +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + if (login_getcapbool(lc, "requirehome", 0)) + { + fprintf(stderr, "Home directory %s not available: %s\n", + pw->pw_dir, strerror(errno)); + exit(254); + } +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ + + fprintf(stderr, "Could not chdir to home directory %s: %s\n", pw->pw_dir, strerror(errno)); + } /* Must take new environment into use so that .ssh/rc, /etc/sshrc and xauth are run in the proper environment. */ @@ -2268,6 +2419,36 @@ { if(!options.use_login) { char buf[256]; + +#if (defined(__FreeBSD__) && defined(HAVE_LOGIN_CAP_H)) + now = time(NULL); + + /* Force password change if necessary. */ + if (pw->pw_change && pw->pw_change <= now) + { + fprintf(stderr, "Your password has expired! Change forced... \n"); + system("/usr/bin/passwd"); + } + + /* Warn the user about password expiration. */ + if (pw->pw_change) + { + warntime = login_getcaptime(lc, "warnpassword", DEFAULT_WARN, + DEFAULT_WARN); + if (now >= (pw->pw_change - warntime)) + printf("Your password expires on %s", ctime(&pw->pw_change)); + } + + /* Warn the user about account expiration. */ + if (pw->pw_expire) + { + warntime = login_getcaptime(lc, "warnexpire", DEFAULT_WARN, + DEFAULT_WARN); + if (now >= (pw->pw_expire - warntime)) + printf("Your account expires on %s", ctime(&pw->pw_change)); + } + +#endif /* FreeBSD && HAVE_LOGIN_CAP_H */ /* Check for mail if we have a tty and it was enabled in server options. */ if (ttyname && options.check_mail) { >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19991118195334.77F695D00B>