Skip site navigation (1)Skip section navigation (2)
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>