summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2003-01-23 13:50:28 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2003-01-23 13:50:28 +0000
commitdad96236271dcb55963b9fe8385f7812e71e67f7 (patch)
treee5f132c5bfac1bd8b1021dcf28da0ab1f891deea
parent83e2cc85d4daade319c04b409b8a95ae7f59cb20 (diff)
ssh-add -c, prompt user for confirmation (using ssh-askpass) when
private agent key is used; with djm@; test by dugsong@, djm@; ok deraadt@
-rw-r--r--usr.bin/ssh/authfd.c10
-rw-r--r--usr.bin/ssh/authfd.h6
-rw-r--r--usr.bin/ssh/readpass.c16
-rw-r--r--usr.bin/ssh/ssh-add.112
-rw-r--r--usr.bin/ssh/ssh-add.c17
-rw-r--r--usr.bin/ssh/ssh-agent.c54
6 files changed, 92 insertions, 23 deletions
diff --git a/usr.bin/ssh/authfd.c b/usr.bin/ssh/authfd.c
index f04e0858b04..a186e01175b 100644
--- a/usr.bin/ssh/authfd.c
+++ b/usr.bin/ssh/authfd.c
@@ -35,7 +35,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: authfd.c,v 1.57 2002/09/11 18:27:26 stevesk Exp $");
+RCSID("$OpenBSD: authfd.c,v 1.58 2003/01/23 13:50:27 markus Exp $");
#include <openssl/evp.h>
@@ -499,10 +499,10 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
int
ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
- const char *comment, u_int life)
+ const char *comment, u_int life, u_int confirm)
{
Buffer msg;
- int type, constrained = (life != 0);
+ int type, constrained = (life || confirm);
buffer_init(&msg);
@@ -532,6 +532,8 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
buffer_put_int(&msg, life);
}
+ if (confirm != 0)
+ buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM);
}
if (ssh_request_reply(auth, &msg, &msg) == 0) {
buffer_free(&msg);
@@ -545,7 +547,7 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
int
ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
{
- return ssh_add_identity_constrained(auth, key, comment, 0);
+ return ssh_add_identity_constrained(auth, key, comment, 0, 0);
}
/*
diff --git a/usr.bin/ssh/authfd.h b/usr.bin/ssh/authfd.h
index 38ee49e8852..2a8751ec18b 100644
--- a/usr.bin/ssh/authfd.h
+++ b/usr.bin/ssh/authfd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfd.h,v 1.31 2002/09/11 18:27:25 stevesk Exp $ */
+/* $OpenBSD: authfd.h,v 1.32 2003/01/23 13:50:27 markus Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -51,6 +51,7 @@
#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
#define SSH_AGENT_CONSTRAIN_LIFETIME 1
+#define SSH_AGENT_CONSTRAIN_CONFIRM 2
/* extended failure messages */
#define SSH2_AGENT_FAILURE 30
@@ -76,7 +77,8 @@ int ssh_get_num_identities(AuthenticationConnection *, int);
Key *ssh_get_first_identity(AuthenticationConnection *, char **, int);
Key *ssh_get_next_identity(AuthenticationConnection *, char **, int);
int ssh_add_identity(AuthenticationConnection *, Key *, const char *);
-int ssh_add_identity_constrained(AuthenticationConnection *, Key *, const char *, u_int);
+int ssh_add_identity_constrained(AuthenticationConnection *, Key *,
+ const char *, u_int, u_int);
int ssh_remove_identity(AuthenticationConnection *, Key *);
int ssh_remove_all_identities(AuthenticationConnection *, int);
int ssh_lock_agent(AuthenticationConnection *, int, const char *);
diff --git a/usr.bin/ssh/readpass.c b/usr.bin/ssh/readpass.c
index dc1b11f3f5f..0e1fd78073f 100644
--- a/usr.bin/ssh/readpass.c
+++ b/usr.bin/ssh/readpass.c
@@ -23,7 +23,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: readpass.c,v 1.27 2002/03/26 15:58:46 markus Exp $");
+RCSID("$OpenBSD: readpass.c,v 1.28 2003/01/23 13:50:27 markus Exp $");
#include <readpassphrase.h>
@@ -48,11 +48,11 @@ ssh_askpass(char *askpass, const char *msg)
fatal("internal error: askpass undefined");
if (pipe(p) < 0) {
error("ssh_askpass: pipe: %s", strerror(errno));
- return xstrdup("");
+ return NULL;
}
if ((pid = fork()) < 0) {
error("ssh_askpass: fork: %s", strerror(errno));
- return xstrdup("");
+ return NULL;
}
if (pid == 0) {
seteuid(getuid());
@@ -81,6 +81,11 @@ ssh_askpass(char *askpass, const char *msg)
if (errno != EINTR)
break;
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+ memset(buf, 0, sizeof(buf));
+ return NULL;
+ }
+
buf[strcspn(buf, "\r\n")] = '\0';
pass = xstrdup(buf);
memset(buf, 0, sizeof(buf));
@@ -117,7 +122,10 @@ read_passphrase(const char *prompt, int flags)
askpass = getenv(SSH_ASKPASS_ENV);
else
askpass = _PATH_SSH_ASKPASS_DEFAULT;
- return ssh_askpass(askpass, prompt);
+ if ((ret = ssh_askpass(askpass, prompt)) == NULL)
+ if (!(flags & RP_ALLOW_EOF))
+ return xstrdup("");
+ return ret;
}
if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) {
diff --git a/usr.bin/ssh/ssh-add.1 b/usr.bin/ssh/ssh-add.1
index 2a34a513317..66a8f9715ae 100644
--- a/usr.bin/ssh/ssh-add.1
+++ b/usr.bin/ssh/ssh-add.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ssh-add.1,v 1.35 2002/06/19 00:27:55 deraadt Exp $
+.\" $OpenBSD: ssh-add.1,v 1.36 2003/01/23 13:50:27 markus Exp $
.\"
.\" -*- nroff -*-
.\"
@@ -45,7 +45,7 @@
.Nd adds RSA or DSA identities to the authentication agent
.Sh SYNOPSIS
.Nm ssh-add
-.Op Fl lLdDxX
+.Op Fl lLdDxXc
.Op Fl t Ar life
.Op Ar
.Nm ssh-add
@@ -93,6 +93,14 @@ Set a maximum lifetime when adding identities to an agent.
The lifetime may be specified in seconds or in a time format
specified in
.Xr sshd 8 .
+.It Fl c
+Indicates that added identities should be subject to confirmation before
+being used for authentication. Confirmation is performed by the
+.Ev SSH_ASKPASS
+program mentioned below. Successful confirmation is signaled by a zero
+exit status from the
+.Ev SSH_ASKPASS
+program, rather than text entered into the requester.
.It Fl s Ar reader
Add key in smartcard
.Ar reader .
diff --git a/usr.bin/ssh/ssh-add.c b/usr.bin/ssh/ssh-add.c
index 1a5be9bd9de..a371751f567 100644
--- a/usr.bin/ssh/ssh-add.c
+++ b/usr.bin/ssh/ssh-add.c
@@ -35,7 +35,7 @@
*/
#include "includes.h"
-RCSID("$OpenBSD: ssh-add.c,v 1.64 2002/11/21 23:03:51 deraadt Exp $");
+RCSID("$OpenBSD: ssh-add.c,v 1.65 2003/01/23 13:50:27 markus Exp $");
#include <openssl/evp.h>
@@ -64,6 +64,9 @@ static char *default_files[] = {
/* Default lifetime (0 == forever) */
static int lifetime = 0;
+/* User has to confirm key use */
+static int confirm = 0;
+
/* we keep a cache of one passphrases */
static char *pass = NULL;
static void
@@ -159,12 +162,16 @@ add_file(AuthenticationConnection *ac, const char *filename)
}
}
- if (ssh_add_identity_constrained(ac, private, comment, lifetime)) {
+ if (ssh_add_identity_constrained(ac, private, comment, lifetime,
+ confirm)) {
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
ret = 0;
if (lifetime != 0)
fprintf(stderr,
"Lifetime set to %d seconds\n", lifetime);
+ if (confirm != 0)
+ fprintf(stderr,
+ "The user has to confirm each use of the key\n");
} else if (ssh_add_identity(ac, private, comment)) {
fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
ret = 0;
@@ -286,6 +293,7 @@ usage(void)
fprintf(stderr, " -x Lock agent.\n");
fprintf(stderr, " -X Unlock agent.\n");
fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
+ fprintf(stderr, " -c Require confirmation to sign using identities\n");
#ifdef SMARTCARD
fprintf(stderr, " -s reader Add key in smartcard reader.\n");
fprintf(stderr, " -e reader Remove key in smartcard reader.\n");
@@ -309,7 +317,7 @@ main(int argc, char **argv)
fprintf(stderr, "Could not open a connection to your authentication agent.\n");
exit(2);
}
- while ((ch = getopt(argc, argv, "lLdDxXe:s:t:")) != -1) {
+ while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) {
switch (ch) {
case 'l':
case 'L':
@@ -323,6 +331,9 @@ main(int argc, char **argv)
ret = 1;
goto done;
break;
+ case 'c':
+ confirm = 1;
+ break;
case 'd':
deleting = 1;
break;
diff --git a/usr.bin/ssh/ssh-agent.c b/usr.bin/ssh/ssh-agent.c
index bbe9ae0b8ac..49ed36b12ae 100644
--- a/usr.bin/ssh/ssh-agent.c
+++ b/usr.bin/ssh/ssh-agent.c
@@ -35,7 +35,7 @@
#include "includes.h"
#include <sys/queue.h>
-RCSID("$OpenBSD: ssh-agent.c,v 1.106 2003/01/21 18:14:36 marc Exp $");
+RCSID("$OpenBSD: ssh-agent.c,v 1.107 2003/01/23 13:50:27 markus Exp $");
#include <openssl/evp.h>
#include <openssl/md5.h>
@@ -50,6 +50,8 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.106 2003/01/21 18:14:36 marc Exp $");
#include "authfd.h"
#include "compat.h"
#include "log.h"
+#include "readpass.h"
+#include "misc.h"
#ifdef SMARTCARD
#include "scard.h"
@@ -77,6 +79,7 @@ typedef struct identity {
Key *key;
char *comment;
u_int death;
+ u_int confirm;
} Identity;
typedef struct {
@@ -158,6 +161,30 @@ lookup_identity(Key *key, int version)
return (NULL);
}
+/* Check confirmation of keysign request */
+static int
+confirm_key(Identity *id)
+{
+ char *p, prompt[1024];
+ int ret = -1;
+
+ p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
+ snprintf(prompt, sizeof(prompt), "Allow use of key %s?\n"
+ "Key fingerprint %s.", id->comment, p);
+ xfree(p);
+ p = read_passphrase(prompt, RP_ALLOW_EOF);
+ if (p != NULL) {
+ /*
+ * Accept empty responses and responses consisting
+ * of the word "yes" as affirmative.
+ */
+ if (*p == '\0' || *p == '\n' || strcasecmp(p, "yes") == 0)
+ ret = 0;
+ xfree(p);
+ }
+ return (ret);
+}
+
/* send list of supported public keys to 'client' */
static void
process_request_identities(SocketEntry *e, int version)
@@ -221,7 +248,7 @@ process_authentication_challenge1(SocketEntry *e)
goto failure;
id = lookup_identity(key, 1);
- if (id != NULL) {
+ if (id != NULL && (!id->confirm || confirm_key(id) == 0)) {
Key *private = id->key;
/* Decrypt the challenge using the private key. */
if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
@@ -281,7 +308,7 @@ process_sign_request2(SocketEntry *e)
key = key_from_blob(blob, blen);
if (key != NULL) {
Identity *id = lookup_identity(key, 2);
- if (id != NULL)
+ if (id != NULL && (!id->confirm || confirm_key(id) == 0))
ok = key_sign(id->key, &signature, &slen, data, dlen);
}
key_free(key);
@@ -401,7 +428,7 @@ static void
process_add_identity(SocketEntry *e, int version)
{
Idtab *tab = idtab_lookup(version);
- int type, success = 0, death = 0;
+ int type, success = 0, death = 0, confirm = 0;
char *type_name, *comment;
Key *k = NULL;
@@ -463,6 +490,9 @@ process_add_identity(SocketEntry *e, int version)
case SSH_AGENT_CONSTRAIN_LIFETIME:
death = time(NULL) + buffer_get_int(&e->request);
break;
+ case SSH_AGENT_CONSTRAIN_CONFIRM:
+ confirm = 1;
+ break;
default:
break;
}
@@ -474,6 +504,7 @@ process_add_identity(SocketEntry *e, int version)
id->key = k;
id->comment = comment;
id->death = death;
+ id->confirm = confirm;
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
/* Increment the number of identities. */
tab->nentries++;
@@ -558,6 +589,7 @@ process_add_smartcard_key (SocketEntry *e)
id->key = k;
id->comment = xstrdup("smartcard key");
id->death = 0;
+ id->confirm = 0;
TAILQ_INSERT_TAIL(&tab->idlist, id, next);
tab->nentries++;
success = 1;
@@ -938,7 +970,8 @@ usage(void)
int
main(int ac, char **av)
{
- int sock, c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, ch, nalloc;
+ int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0;
+ int sock, fd, ch, nalloc;
char *shell, *format, *pidstr, *agentsocket = NULL;
fd_set *readsetp = NULL, *writesetp = NULL;
struct sockaddr_un sunaddr;
@@ -1106,9 +1139,14 @@ main(int ac, char **av)
}
(void)chdir("/");
- close(0);
- close(1);
- close(2);
+ if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+ /* XXX might close listen socket */
+ (void)dup2(fd, STDIN_FILENO);
+ (void)dup2(fd, STDOUT_FILENO);
+ (void)dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ close(fd);
+ }
/* deny core dumps, since memory contains unencrypted private keys */
rlim.rlim_cur = rlim.rlim_max = 0;