- markus@cvs.openbsd.org 2001/02/12 16:16:23
     [auth-passwd.c auth.c auth.h auth1.c auth2.c servconf.c servconf.h
      ssh-keygen.c sshd.8]
     PermitRootLogin={yes,without-password,forced-commands-only,no}
     (before this change, root could login even if PermitRootLogin==no)
diff --git a/ChangeLog b/ChangeLog
index ec9e00b..14424b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,11 @@
      3) or the 'MACs' keyword in ssh(d)_config
      4) add hmac-{md5,sha1}-96
              ok stevesk@, provos@
+   - markus@cvs.openbsd.org 2001/02/12 16:16:23
+     [auth-passwd.c auth.c auth.h auth1.c auth2.c servconf.c servconf.h
+      ssh-keygen.c sshd.8]
+     PermitRootLogin={yes,without-password,forced-commands-only,no}
+     (before this change, root could login even if PermitRootLogin==no)
 
 20010214
  - (djm) Don't try to close PAM session or delete credentials if the
@@ -3943,4 +3948,4 @@
  - Wrote replacements for strlcpy and mkdtemp
  - Released 1.0pre1
 
-$Id: ChangeLog,v 1.763 2001/02/15 03:01:59 mouring Exp $
+$Id: ChangeLog,v 1.764 2001/02/15 03:08:27 mouring Exp $
diff --git a/auth-passwd.c b/auth-passwd.c
index 9f76326..c849abd 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -36,7 +36,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: auth-passwd.c,v 1.20 2001/01/21 19:05:42 markus Exp $");
+RCSID("$OpenBSD: auth-passwd.c,v 1.21 2001/02/12 16:16:23 markus Exp $");
 
 #if !defined(USE_PAM) && !defined(HAVE_OSF_SIA)
 
@@ -110,7 +110,7 @@
 	if (pw == NULL)
 		return 0;
 #ifndef HAVE_CYGWIN
-	if (pw->pw_uid == 0 && options.permit_root_login == 2)
+       if (pw->pw_uid == 0 && options.permit_root_login != PERMIT_YES)
 		return 0;
 #endif
 #ifdef HAVE_CYGWIN
diff --git a/auth.c b/auth.c
index 204903f..a0a3fb6 100644
--- a/auth.c
+++ b/auth.c
@@ -23,7 +23,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: auth.c,v 1.16 2001/02/04 15:32:22 stevesk Exp $");
+RCSID("$OpenBSD: auth.c,v 1.17 2001/02/12 16:16:23 markus Exp $");
 
 #ifdef HAVE_LOGIN_H
 #include <login.h>
@@ -216,19 +216,26 @@
 }
 
 /*
- * Check if the user is logging in as root and root logins are disallowed.
- * Note that root login is _allways_ allowed for forced commands.
+ * Check whether root logins are disallowed.
  */
 int
-auth_root_allowed(void)
+auth_root_allowed(char *method)
 {
-	if (options.permit_root_login)
+	switch (options.permit_root_login) {
+	case PERMIT_YES:
 		return 1;
-	if (forced_command) {
-		log("Root login accepted for forced command.");
-		return 1;
-	} else {
-		log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
-		return 0;
+		break;
+	case PERMIT_NO_PASSWD:
+		if (strcmp(method, "password") != 0)
+			return 1;
+		break;
+	case PERMIT_FORCED_ONLY:
+		if (forced_command) {
+			log("Root login accepted for forced command.");
+			return 1;
+		}
+		break;
 	}
+	log("ROOT LOGIN REFUSED FROM %.200s", get_remote_ipaddr());
+	return 0;
 }
diff --git a/auth.h b/auth.h
index b604e63..0684f6f 100644
--- a/auth.h
+++ b/auth.h
@@ -21,7 +21,7 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * $OpenBSD: auth.h,v 1.10 2001/01/21 19:05:43 markus Exp $
+ * $OpenBSD: auth.h,v 1.11 2001/02/12 16:16:23 markus Exp $
  */
 #ifndef AUTH_H
 #define AUTH_H
@@ -112,7 +112,7 @@
 Authctxt *authctxt_new(void);
 void	auth_log(Authctxt *authctxt, int authenticated, char *method, char *info);
 void	userauth_reply(Authctxt *authctxt, int authenticated);
-int	auth_root_allowed(void);
+int	auth_root_allowed(char *method);
 
 int	auth2_challenge(Authctxt *authctxt, char *devs);
 
diff --git a/auth1.c b/auth1.c
index 3103426..2649924 100644
--- a/auth1.c
+++ b/auth1.c
@@ -10,7 +10,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: auth1.c,v 1.15 2001/02/07 22:35:45 markus Exp $");
+RCSID("$OpenBSD: auth1.c,v 1.16 2001/02/12 16:16:23 markus Exp $");
 
 #include "xmalloc.h"
 #include "rsa.h"
@@ -316,7 +316,8 @@
 		}
 #else
 		/* Special handling for root */
-		if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed())
+		if (authenticated && authctxt->pw->pw_uid == 0 &&
+		    !auth_root_allowed(get_authname(type)))
 			authenticated = 0;
 #endif
 #ifdef USE_PAM
diff --git a/auth2.c b/auth2.c
index b749205..3cd9468 100644
--- a/auth2.c
+++ b/auth2.c
@@ -23,7 +23,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: auth2.c,v 1.40 2001/02/10 12:52:02 markus Exp $");
+RCSID("$OpenBSD: auth2.c,v 1.41 2001/02/12 16:16:23 markus Exp $");
 
 #include <openssl/evp.h>
 
@@ -230,7 +230,8 @@
 		    authctxt->user);
 
 	/* Special handling for root */
-	if (authenticated && authctxt->pw->pw_uid == 0 && !auth_root_allowed())
+	if (authenticated && authctxt->pw->pw_uid == 0 &&
+	    !auth_root_allowed(method))
 		authenticated = 0;
 
 #ifdef USE_PAM
diff --git a/servconf.c b/servconf.c
index 43a2c11..27c8671 100644
--- a/servconf.c
+++ b/servconf.c
@@ -10,7 +10,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: servconf.c,v 1.66 2001/02/11 12:59:25 markus Exp $");
+RCSID("$OpenBSD: servconf.c,v 1.67 2001/02/12 16:16:23 markus Exp $");
 
 #ifdef KRB4
 #include <krb.h>
@@ -51,7 +51,7 @@
 	options->server_key_bits = -1;
 	options->login_grace_time = -1;
 	options->key_regeneration_time = -1;
-	options->permit_root_login = -1;
+	options->permit_root_login = PERMIT_NOT_SET;
 	options->ignore_rhosts = -1;
 	options->ignore_user_known_hosts = -1;
 	options->print_motd = -1;
@@ -122,8 +122,8 @@
 		options->login_grace_time = 600;
 	if (options->key_regeneration_time == -1)
 		options->key_regeneration_time = 3600;
-	if (options->permit_root_login == -1)
-		options->permit_root_login = 1;			/* yes */
+	if (options->permit_root_login == PERMIT_NOT_SET)
+		options->permit_root_login = PERMIT_YES;
 	if (options->ignore_rhosts == -1)
 		options->ignore_rhosts = 1;
 	if (options->ignore_user_known_hosts == -1)
@@ -453,14 +453,17 @@
 				exit(1);
 			}
 			if (strcmp(arg, "without-password") == 0)
-				value = 2;
+				value = PERMIT_NO_PASSWD;
+			else if (strcmp(arg, "forced-commands-only") == 0)
+				value = PERMIT_FORCED_ONLY;
 			else if (strcmp(arg, "yes") == 0)
-				value = 1;
+				value = PERMIT_YES;
 			else if (strcmp(arg, "no") == 0)
-				value = 0;
+				value = PERMIT_NO;
 			else {
-				fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n",
-					filename, linenum, arg);
+				fprintf(stderr, "%s line %d: Bad yes/"
+				    "without-password/forced-commands-only/no "
+				    "argument: %s\n", filename, linenum, arg);
 				exit(1);
 			}
 			if (*intptr == -1)
diff --git a/servconf.h b/servconf.h
index 8236a63..1009ce2 100644
--- a/servconf.h
+++ b/servconf.h
@@ -11,7 +11,7 @@
  * called by a name other than "ssh" or "Secure Shell".
  */
 
-/* RCSID("$OpenBSD: servconf.h,v 1.37 2001/02/11 12:59:25 markus Exp $"); */
+/* RCSID("$OpenBSD: servconf.h,v 1.38 2001/02/12 16:16:23 markus Exp $"); */
 
 #ifndef SERVCONF_H
 #define SERVCONF_H
@@ -25,6 +25,14 @@
 #define MAX_SUBSYSTEMS		256	/* Max # subsystems. */
 #define MAX_HOSTKEYS		256	/* Max # hostkeys. */
 
+/* permit_root_login */
+#define	PERMIT_NOT_SET		-1
+#define	PERMIT_NO		0
+#define	PERMIT_FORCED_ONLY	1
+#define	PERMIT_NO_PASSWD	2
+#define	PERMIT_YES		3
+
+
 typedef struct {
 	u_int num_ports;
 	u_int ports_from_cmdline;
@@ -38,7 +46,7 @@
 	int     login_grace_time;	/* Disconnect if no auth in this time
 					 * (sec). */
 	int     key_regeneration_time;	/* Server key lifetime (seconds). */
-	int     permit_root_login;	/* If true, permit root login. */
+	int     permit_root_login;	/* PERMIT_*, see above */
 	int     ignore_rhosts;	/* Ignore .rhosts and .shosts. */
 	int     ignore_user_known_hosts;	/* Ignore ~/.ssh/known_hosts
 						 * for RhostsRsaAuth */
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 3b5d22f..f573db4 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -12,7 +12,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: ssh-keygen.c,v 1.42 2001/02/04 15:32:26 stevesk Exp $");
+RCSID("$OpenBSD: ssh-keygen.c,v 1.43 2001/02/12 16:16:23 markus Exp $");
 
 #include <openssl/evp.h>
 #include <openssl/pem.h>
@@ -532,6 +532,7 @@
 	public = key_new(KEY_RSA1);
 	if (!load_public_key(identity_file, public, NULL)) {
 		printf("%s is not a valid key file.\n", identity_file);
+		printf("Comments are only supported in RSA1 keys\n");
 		exit(1);
 	}
 
diff --git a/sshd.8 b/sshd.8
index 1b1e964..79c1843 100644
--- a/sshd.8
+++ b/sshd.8
@@ -34,7 +34,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.\" $OpenBSD: sshd.8,v 1.93 2001/02/11 12:59:25 markus Exp $
+.\" $OpenBSD: sshd.8,v 1.94 2001/02/12 16:16:24 markus Exp $
 .Dd September 25, 1999
 .Dt SSHD 8
 .Os
@@ -552,21 +552,26 @@
 .Xr ssh 1 .
 The argument must be
 .Dq yes ,
-.Dq without-password
+.Dq without-password ,
+.Dq forced-commands-only
 or
 .Dq no .
 The default is
 .Dq yes .
-If this options is set to
-.Dq without-password
-only password authentication is disabled for root.
 .Pp
-Root login with RSA authentication when the
+If this option is set to
+.Dq without-password
+password authentication is disabled for root.
+.Pp
+If this option is set to
+.Dq forced-commands-only
+root login with public key authentication will be allowed,
+but only if the
 .Ar command
-option has been
-specified will be allowed regardless of the value of this setting
+option has been specified
 (which may be useful for taking remote backups even if root login is
-normally not allowed).
+normally not allowed). All other authentication methods are disabled
+for root.
 .It Cm PidFile
 Specifies the file that contains the process identifier of the
 .Nm