Use of non-user readable (null password) private keys
Jim Knoble
jmknoble at jmknoble.cx
Wed Mar 28 08:15:55 EST 2001
Circa 2001-Mar-27 21:09:10 +0100 dixit Piete Brooks:
: I want to be able to give `group' or `other' access to capabilities.
:
: I do not want ACLs.
This is certainly something you ought to be able to do if you know what
you're doing.
Attached is a patch against OpenSSH-2.5.2p2 which implements relaxed
restrictions on key permissions under the following conditions:
(1) You build openssh with ALLOW_RELAXED_KEY_PERMISSIONS defined
(e.g., 'env CFLAGS=-DALLOW_RELAXED_KEY_PERMISSIONS ./configure').
(2) You call ssh with the (new) '-G' option if you want your key to
be group-accessible (ssh allows the key to have permissions up to
0770)
or
You call ssh with the (new) '-W' option if you want your key to
be world-accessible (ssh allows the key to have permissions up to
0775).
Platonic Questioning Session:
Socrates: Why didn't you make a config-file option for this?
Diogenes: I considered making a config-file option (for
/etc/ssh/ssh_config bzw. ~/.ssh/config), but decided
against it because i think the user should have to say
"Yes, i do in fact know what i'm doing" to use this
facility.
Socrates: Why do i have to build with that stupid #define?
Diogenes: So that you don't blame me for the holes in your foot.
Socrates: Why didn't you make ssh emit a warning when the permissions
are relaxed?
Diogenes: OpenSSH doesn't have a suitable warning facility. The
closest available function is error(), which only makes
output appear on stderr if ssh is called with '-v'
(verbose). This should probably be fixed so that the
regular warning (without -G or -W) appears regardless of
whether ssh has been asked to be verbose, so that the user
knows that ssh is going to ignore the key. But fixing that
is beyond the scope of this patch.
Socrates: Why does ssh ask me for my passphrase if it's ignoring my
private key due to relaxed permissions?
Diogenes: Because the granularity of information returned by
authfile.c:load_private_key() is too coarse.
load_private_key() really ought to return a status
which separates failure due to ownership/permissions from
failure due to bad passphrase or whatnot. But fixing that
is beyond the scope of this patch.
Socrates: Why can't i pass a umask to ssh instead of choosing group
or world access only?
Diogenes: Good question. I considered this, but it's more ammunition
for foot-shooting, and i think it requires more thought
than i've been able to give it. Opinions from other folks
are welcome. In the meantime, have some of this
great-tasting herbal tea.
Socrates: Why did you forget to attach the patch to this message?
Are you stupid or something?
Diogenes: Have some more tea.
--
jim knoble | jmknoble at jmknoble.cx | http://www.jmknoble.cx/
-------------- next part --------------
--- ./authfile.c.orig-keyperms Sun Mar 4 23:59:27 2001
+++ ./authfile.c Tue Mar 27 16:44:18 2001
@@ -497,11 +497,12 @@
int
load_private_key(const char *filename, const char *passphrase, Key *key,
- char **comment_return)
+ int allow_relaxed_key_permissions, char **comment_return)
{
int fd;
int ret = 0;
struct stat st;
+ unsigned int mode_mask = 077;
fd = open(filename, O_RDONLY);
if (fd < 0)
@@ -511,9 +512,14 @@
#ifdef HAVE_CYGWIN
if (check_ntsec(filename))
#endif
+ if (1 == allow_relaxed_key_permissions) {
+ mode_mask = 07;
+ } else if (2 == allow_relaxed_key_permissions) {
+ mode_mask = 01;
+ }
if (fstat(fd, &st) < 0 ||
(st.st_uid != 0 && getuid() != 0 && st.st_uid != getuid()) ||
- (st.st_mode & 077) != 0) {
+ (st.st_mode & mode_mask) != 0) {
close(fd);
error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @");
--- ./ssh.c.orig-keyperms Sun Mar 18 17:38:16 2001
+++ ./ssh.c Tue Mar 27 16:44:04 2001
@@ -145,6 +145,11 @@
/* Should we execute a command or invoke a subsystem? */
int subsystem_flag = 0;
+#ifndef ALLOW_RELAXED_KEY_PERMISSIONS
+const
+#endif
+int allow_relaxed_key_permissions = 0;
+
/* Prints a help message to the user. This function never returns. */
void
@@ -163,6 +168,10 @@
fprintf(stderr, " -x Disable X11 connection forwarding.\n");
fprintf(stderr, " -i file Identity for public key authentication "
"(default: ~/.ssh/identity)\n");
+#ifdef ALLOW_RELAXED_KEY_PERMISSIONS
+ fprintf(stderr, " -G Allow private key to be group-accessible.\n");
+ fprintf(stderr, " -W Allow private key to be world-accessible.\n");
+#endif
fprintf(stderr, " -t Tty; allocate a tty even if command is given.\n");
fprintf(stderr, " -T Do not allocate a tty.\n");
fprintf(stderr, " -v Verbose; display verbose debugging messages.\n");
@@ -375,6 +384,14 @@
SSH_MAX_IDENTITY_FILES);
options.identity_files[options.num_identity_files++] = xstrdup(optarg);
break;
+#ifdef ALLOW_RELAXED_KEY_PERMISSIONS
+ case 'G':
+ allow_relaxed_key_permissions = 1;
+ break;
+ case 'W':
+ allow_relaxed_key_permissions = 2;
+ break;
+#endif
case 't':
if (tty_flag)
force_tty_flag = 1;
@@ -635,7 +652,7 @@
host_private_key = RSA_new();
k.type = KEY_RSA1;
k.rsa = host_private_key;
- if (load_private_key(_PATH_HOST_KEY_FILE, "", &k, NULL))
+ if (load_private_key(_PATH_HOST_KEY_FILE, "", &k, 0, NULL))
host_private_key_loaded = 1;
}
/*
--- ./ssh-keygen.c.orig-keyperms Sun Mar 18 17:38:16 2001
+++ ./ssh-keygen.c Tue Mar 27 16:44:04 2001
@@ -115,9 +115,9 @@
try_load_key(char *filename, Key *k)
{
int success = 1;
- if (!load_private_key(filename, "", k, NULL)) {
+ if (!load_private_key(filename, "", k, 0, NULL)) {
char *pass = read_passphrase("Enter passphrase: ", 1);
- if (!load_private_key(filename, pass, k, NULL)) {
+ if (!load_private_key(filename, pass, k, 0, NULL)) {
success = 0;
}
memset(pass, 0, strlen(pass));
@@ -454,12 +454,12 @@
}
/* Try to load the file with empty passphrase. */
private = key_new(type);
- if (!load_private_key(identity_file, "", private, &comment)) {
+ if (!load_private_key(identity_file, "", private, 0, &comment)) {
if (identity_passphrase)
old_passphrase = xstrdup(identity_passphrase);
else
old_passphrase = read_passphrase("Enter old passphrase: ", 1);
- if (!load_private_key(identity_file, old_passphrase, private, &comment)) {
+ if (!load_private_key(identity_file, old_passphrase, private, 0, &comment)) {
memset(old_passphrase, 0, strlen(old_passphrase));
xfree(old_passphrase);
printf("Bad passphrase.\n");
@@ -543,7 +543,7 @@
}
private = key_new(KEY_RSA1);
- if (load_private_key(identity_file, "", private, &comment))
+ if (load_private_key(identity_file, "", private, 0, &comment))
passphrase = xstrdup("");
else {
if (identity_passphrase)
@@ -553,7 +553,7 @@
else
passphrase = read_passphrase("Enter passphrase: ", 1);
/* Try to load using the passphrase. */
- if (!load_private_key(identity_file, passphrase, private, &comment)) {
+ if (!load_private_key(identity_file, passphrase, private, 0, &comment)) {
memset(passphrase, 0, strlen(passphrase));
xfree(passphrase);
printf("Bad passphrase.\n");
--- ./sshconnect1.c.orig-keyperms Thu Mar 8 19:12:23 2001
+++ ./sshconnect1.c Tue Mar 27 16:44:04 2001
@@ -51,6 +51,12 @@
extern Options options;
extern char *__progname;
+extern
+#ifndef ALLOW_RELAXED_KEY_PERMISSIONS
+ const
+#endif
+ int allow_relaxed_key_permissions;
+
/*
* Checks if the user has an authentication agent, and if so, tries to
* authenticate using the agent.
@@ -257,7 +263,8 @@
* Load the private key. Try first with empty passphrase; if it
* fails, ask for a passphrase.
*/
- if (!load_private_key(authfile, "", private, NULL)) {
+ if (!load_private_key(authfile, "", private,
+ allow_relaxed_key_permissions, NULL)) {
char buf[300];
snprintf(buf, sizeof buf, "Enter passphrase for RSA key '%.100s': ",
comment);
@@ -270,7 +277,8 @@
}
/* Load the authentication file using the pasphrase. */
- if (!load_private_key(authfile, passphrase, private, NULL)) {
+ if (!load_private_key(authfile, passphrase, private,
+ allow_relaxed_key_permissions, NULL)) {
memset(passphrase, 0, strlen(passphrase));
xfree(passphrase);
error("Bad passphrase.");
--- ./sshconnect2.c.orig-keyperms Mon Mar 12 23:57:59 2001
+++ ./sshconnect2.c Tue Mar 27 16:44:04 2001
@@ -61,6 +61,12 @@
extern char *server_version_string;
extern Options options;
+extern
+#ifndef ALLOW_RELAXED_KEY_PERMISSIONS
+ const
+#endif
+ int allow_relaxed_key_permissions;
+
/*
* SSH2 key exchange
*/
@@ -906,7 +912,8 @@
return NULL;
}
private = key_new(KEY_UNSPEC);
- if (!load_private_key(filename, "", private, NULL)) {
+ if (!load_private_key(filename, "", private,
+ allow_relaxed_key_permissions, NULL)) {
if (options.batch_mode) {
key_free(private);
return NULL;
@@ -917,7 +924,8 @@
passphrase = read_passphrase(prompt, 0);
if (strcmp(passphrase, "") != 0) {
success = load_private_key(filename,
- passphrase, private, NULL);
+ passphrase, private,
+ allow_relaxed_key_permissions, NULL);
quit = 0;
} else {
debug2("no passphrase given, try next key");
--- ./sshd.c.orig-keyperms Mon Mar 19 06:36:20 2001
+++ ./sshd.c Tue Mar 27 16:44:04 2001
@@ -482,7 +482,7 @@
/* Ok, try key with empty passphrase */
private = key_new(type);
- if (load_private_key(filename, "", private, NULL)) {
+ if (load_private_key(filename, "", private, 0, NULL)) {
debug("load_private_key_autodetect: type %d %s",
private->type, key_type(private));
return private;
--- ./authfile.h.orig-keyperms Sun Nov 5 20:39:34 2000
+++ ./authfile.h Tue Mar 27 16:44:04 2001
@@ -46,6 +46,7 @@
*/
int
load_private_key(const char *filename, const char *passphrase,
- Key * private_key, char **comment_return);
+ Key * private_key, int allow_relaxed_key_permissions,
+ char **comment_return);
#endif
--- ./ssh-add.c.orig-keyperms Mon Mar 12 23:57:59 2001
+++ ./ssh-add.c Tue Mar 27 16:44:04 2001
@@ -172,7 +172,7 @@
/* At first, try empty passphrase */
private = key_new(type);
- success = load_private_key(filename, "", private, &comment);
+ success = load_private_key(filename, "", private, 0, &comment);
if (!success) {
printf("Need passphrase for %.200s\n", filename);
if (!interactive && askpass == NULL) {
@@ -193,7 +193,7 @@
xfree(saved_comment);
return;
}
- success = load_private_key(filename, pass, private, &comment);
+ success = load_private_key(filename, pass, private, 0, &comment);
memset(pass, 0, strlen(pass));
xfree(pass);
if (success)
More information about the openssh-unix-dev
mailing list