summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2003-01-24 11:36:23 +1100
committerDamien Miller <djm@mindrot.org>2003-01-24 11:36:23 +1100
commit6c71179f6839ab49e4e8a91209eef85dc190d5f1 (patch)
tree199fd690f2933dc18a687d5b86be467a2250f2d1
parent5a93add673a68d9ef67504b17913254498f4deb9 (diff)
- markus@cvs.openbsd.org 2003/01/23 13:50:27
[authfd.c authfd.h readpass.c ssh-add.1 ssh-add.c ssh-agent.c] 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--ChangeLog7
-rw-r--r--authfd.c10
-rw-r--r--authfd.h6
-rw-r--r--readpass.c16
-rw-r--r--ssh-add.112
-rw-r--r--ssh-add.c17
-rw-r--r--ssh-agent.c54
7 files changed, 98 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index 7ecd2f7fa..2fb0b941e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,6 +3,11 @@
3 - jmc@cvs.openbsd.org 2003/01/23 08:58:47 3 - jmc@cvs.openbsd.org 2003/01/23 08:58:47
4 [sshd_config.5] 4 [sshd_config.5]
5 typos; ok millert@ 5 typos; ok millert@
6 - markus@cvs.openbsd.org 2003/01/23 13:50:27
7 [authfd.c authfd.h readpass.c ssh-add.1 ssh-add.c ssh-agent.c]
8 ssh-add -c, prompt user for confirmation (using ssh-askpass) when
9 private agent key is used; with djm@; test by dugsong@, djm@;
10 ok deraadt@
6 11
720030123 1220030123
8 - (djm) OpenBSD CVS Sync 13 - (djm) OpenBSD CVS Sync
@@ -1062,4 +1067,4 @@
1062 save auth method before monitor_reset_key_state(); bugzilla bug #284; 1067 save auth method before monitor_reset_key_state(); bugzilla bug #284;
1063 ok provos@ 1068 ok provos@
1064 1069
1065$Id: ChangeLog,v 1.2583 2003/01/24 00:34:52 djm Exp $ 1070$Id: ChangeLog,v 1.2584 2003/01/24 00:36:23 djm Exp $
diff --git a/authfd.c b/authfd.c
index f04e0858b..a186e0117 100644
--- a/authfd.c
+++ b/authfd.c
@@ -35,7 +35,7 @@
35 */ 35 */
36 36
37#include "includes.h" 37#include "includes.h"
38RCSID("$OpenBSD: authfd.c,v 1.57 2002/09/11 18:27:26 stevesk Exp $"); 38RCSID("$OpenBSD: authfd.c,v 1.58 2003/01/23 13:50:27 markus Exp $");
39 39
40#include <openssl/evp.h> 40#include <openssl/evp.h>
41 41
@@ -499,10 +499,10 @@ ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
499 499
500int 500int
501ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key, 501ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
502 const char *comment, u_int life) 502 const char *comment, u_int life, u_int confirm)
503{ 503{
504 Buffer msg; 504 Buffer msg;
505 int type, constrained = (life != 0); 505 int type, constrained = (life || confirm);
506 506
507 buffer_init(&msg); 507 buffer_init(&msg);
508 508
@@ -532,6 +532,8 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
532 buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME); 532 buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME);
533 buffer_put_int(&msg, life); 533 buffer_put_int(&msg, life);
534 } 534 }
535 if (confirm != 0)
536 buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM);
535 } 537 }
536 if (ssh_request_reply(auth, &msg, &msg) == 0) { 538 if (ssh_request_reply(auth, &msg, &msg) == 0) {
537 buffer_free(&msg); 539 buffer_free(&msg);
@@ -545,7 +547,7 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
545int 547int
546ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment) 548ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
547{ 549{
548 return ssh_add_identity_constrained(auth, key, comment, 0); 550 return ssh_add_identity_constrained(auth, key, comment, 0, 0);
549} 551}
550 552
551/* 553/*
diff --git a/authfd.h b/authfd.h
index 38ee49e88..2a8751ec1 100644
--- a/authfd.h
+++ b/authfd.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfd.h,v 1.31 2002/09/11 18:27:25 stevesk Exp $ */ 1/* $OpenBSD: authfd.h,v 1.32 2003/01/23 13:50:27 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -51,6 +51,7 @@
51#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25 51#define SSH2_AGENTC_ADD_ID_CONSTRAINED 25
52 52
53#define SSH_AGENT_CONSTRAIN_LIFETIME 1 53#define SSH_AGENT_CONSTRAIN_LIFETIME 1
54#define SSH_AGENT_CONSTRAIN_CONFIRM 2
54 55
55/* extended failure messages */ 56/* extended failure messages */
56#define SSH2_AGENT_FAILURE 30 57#define SSH2_AGENT_FAILURE 30
@@ -76,7 +77,8 @@ int ssh_get_num_identities(AuthenticationConnection *, int);
76Key *ssh_get_first_identity(AuthenticationConnection *, char **, int); 77Key *ssh_get_first_identity(AuthenticationConnection *, char **, int);
77Key *ssh_get_next_identity(AuthenticationConnection *, char **, int); 78Key *ssh_get_next_identity(AuthenticationConnection *, char **, int);
78int ssh_add_identity(AuthenticationConnection *, Key *, const char *); 79int ssh_add_identity(AuthenticationConnection *, Key *, const char *);
79int ssh_add_identity_constrained(AuthenticationConnection *, Key *, const char *, u_int); 80int ssh_add_identity_constrained(AuthenticationConnection *, Key *,
81 const char *, u_int, u_int);
80int ssh_remove_identity(AuthenticationConnection *, Key *); 82int ssh_remove_identity(AuthenticationConnection *, Key *);
81int ssh_remove_all_identities(AuthenticationConnection *, int); 83int ssh_remove_all_identities(AuthenticationConnection *, int);
82int ssh_lock_agent(AuthenticationConnection *, int, const char *); 84int ssh_lock_agent(AuthenticationConnection *, int, const char *);
diff --git a/readpass.c b/readpass.c
index 96b7e84b4..95ec5d873 100644
--- a/readpass.c
+++ b/readpass.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: readpass.c,v 1.27 2002/03/26 15:58:46 markus Exp $"); 26RCSID("$OpenBSD: readpass.c,v 1.28 2003/01/23 13:50:27 markus Exp $");
27 27
28#include "xmalloc.h" 28#include "xmalloc.h"
29#include "readpass.h" 29#include "readpass.h"
@@ -46,11 +46,11 @@ ssh_askpass(char *askpass, const char *msg)
46 fatal("internal error: askpass undefined"); 46 fatal("internal error: askpass undefined");
47 if (pipe(p) < 0) { 47 if (pipe(p) < 0) {
48 error("ssh_askpass: pipe: %s", strerror(errno)); 48 error("ssh_askpass: pipe: %s", strerror(errno));
49 return xstrdup(""); 49 return NULL;
50 } 50 }
51 if ((pid = fork()) < 0) { 51 if ((pid = fork()) < 0) {
52 error("ssh_askpass: fork: %s", strerror(errno)); 52 error("ssh_askpass: fork: %s", strerror(errno));
53 return xstrdup(""); 53 return NULL;
54 } 54 }
55 if (pid == 0) { 55 if (pid == 0) {
56 seteuid(getuid()); 56 seteuid(getuid());
@@ -79,6 +79,11 @@ ssh_askpass(char *askpass, const char *msg)
79 if (errno != EINTR) 79 if (errno != EINTR)
80 break; 80 break;
81 81
82 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
83 memset(buf, 0, sizeof(buf));
84 return NULL;
85 }
86
82 buf[strcspn(buf, "\r\n")] = '\0'; 87 buf[strcspn(buf, "\r\n")] = '\0';
83 pass = xstrdup(buf); 88 pass = xstrdup(buf);
84 memset(buf, 0, sizeof(buf)); 89 memset(buf, 0, sizeof(buf));
@@ -115,7 +120,10 @@ read_passphrase(const char *prompt, int flags)
115 askpass = getenv(SSH_ASKPASS_ENV); 120 askpass = getenv(SSH_ASKPASS_ENV);
116 else 121 else
117 askpass = _PATH_SSH_ASKPASS_DEFAULT; 122 askpass = _PATH_SSH_ASKPASS_DEFAULT;
118 return ssh_askpass(askpass, prompt); 123 if ((ret = ssh_askpass(askpass, prompt)) == NULL)
124 if (!(flags & RP_ALLOW_EOF))
125 return xstrdup("");
126 return ret;
119 } 127 }
120 128
121 if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) { 129 if (readpassphrase(prompt, buf, sizeof buf, rppflags) == NULL) {
diff --git a/ssh-add.1 b/ssh-add.1
index 2a34a5133..66a8f9715 100644
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: ssh-add.1,v 1.35 2002/06/19 00:27:55 deraadt Exp $ 1.\" $OpenBSD: ssh-add.1,v 1.36 2003/01/23 13:50:27 markus Exp $
2.\" 2.\"
3.\" -*- nroff -*- 3.\" -*- nroff -*-
4.\" 4.\"
@@ -45,7 +45,7 @@
45.Nd adds RSA or DSA identities to the authentication agent 45.Nd adds RSA or DSA identities to the authentication agent
46.Sh SYNOPSIS 46.Sh SYNOPSIS
47.Nm ssh-add 47.Nm ssh-add
48.Op Fl lLdDxX 48.Op Fl lLdDxXc
49.Op Fl t Ar life 49.Op Fl t Ar life
50.Op Ar 50.Op Ar
51.Nm ssh-add 51.Nm ssh-add
@@ -93,6 +93,14 @@ Set a maximum lifetime when adding identities to an agent.
93The lifetime may be specified in seconds or in a time format 93The lifetime may be specified in seconds or in a time format
94specified in 94specified in
95.Xr sshd 8 . 95.Xr sshd 8 .
96.It Fl c
97Indicates that added identities should be subject to confirmation before
98being used for authentication. Confirmation is performed by the
99.Ev SSH_ASKPASS
100program mentioned below. Successful confirmation is signaled by a zero
101exit status from the
102.Ev SSH_ASKPASS
103program, rather than text entered into the requester.
96.It Fl s Ar reader 104.It Fl s Ar reader
97Add key in smartcard 105Add key in smartcard
98.Ar reader . 106.Ar reader .
diff --git a/ssh-add.c b/ssh-add.c
index 4f4ab3a06..0c2ce163c 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -35,7 +35,7 @@
35 */ 35 */
36 36
37#include "includes.h" 37#include "includes.h"
38RCSID("$OpenBSD: ssh-add.c,v 1.64 2002/11/21 23:03:51 deraadt Exp $"); 38RCSID("$OpenBSD: ssh-add.c,v 1.65 2003/01/23 13:50:27 markus Exp $");
39 39
40#include <openssl/evp.h> 40#include <openssl/evp.h>
41 41
@@ -70,6 +70,9 @@ static char *default_files[] = {
70/* Default lifetime (0 == forever) */ 70/* Default lifetime (0 == forever) */
71static int lifetime = 0; 71static int lifetime = 0;
72 72
73/* User has to confirm key use */
74static int confirm = 0;
75
73/* we keep a cache of one passphrases */ 76/* we keep a cache of one passphrases */
74static char *pass = NULL; 77static char *pass = NULL;
75static void 78static void
@@ -165,12 +168,16 @@ add_file(AuthenticationConnection *ac, const char *filename)
165 } 168 }
166 } 169 }
167 170
168 if (ssh_add_identity_constrained(ac, private, comment, lifetime)) { 171 if (ssh_add_identity_constrained(ac, private, comment, lifetime,
172 confirm)) {
169 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); 173 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
170 ret = 0; 174 ret = 0;
171 if (lifetime != 0) 175 if (lifetime != 0)
172 fprintf(stderr, 176 fprintf(stderr,
173 "Lifetime set to %d seconds\n", lifetime); 177 "Lifetime set to %d seconds\n", lifetime);
178 if (confirm != 0)
179 fprintf(stderr,
180 "The user has to confirm each use of the key\n");
174 } else if (ssh_add_identity(ac, private, comment)) { 181 } else if (ssh_add_identity(ac, private, comment)) {
175 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); 182 fprintf(stderr, "Identity added: %s (%s)\n", filename, comment);
176 ret = 0; 183 ret = 0;
@@ -292,6 +299,7 @@ usage(void)
292 fprintf(stderr, " -x Lock agent.\n"); 299 fprintf(stderr, " -x Lock agent.\n");
293 fprintf(stderr, " -X Unlock agent.\n"); 300 fprintf(stderr, " -X Unlock agent.\n");
294 fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n"); 301 fprintf(stderr, " -t life Set lifetime (in seconds) when adding identities.\n");
302 fprintf(stderr, " -c Require confirmation to sign using identities\n");
295#ifdef SMARTCARD 303#ifdef SMARTCARD
296 fprintf(stderr, " -s reader Add key in smartcard reader.\n"); 304 fprintf(stderr, " -s reader Add key in smartcard reader.\n");
297 fprintf(stderr, " -e reader Remove key in smartcard reader.\n"); 305 fprintf(stderr, " -e reader Remove key in smartcard reader.\n");
@@ -319,7 +327,7 @@ main(int argc, char **argv)
319 fprintf(stderr, "Could not open a connection to your authentication agent.\n"); 327 fprintf(stderr, "Could not open a connection to your authentication agent.\n");
320 exit(2); 328 exit(2);
321 } 329 }
322 while ((ch = getopt(argc, argv, "lLdDxXe:s:t:")) != -1) { 330 while ((ch = getopt(argc, argv, "lLcdDxXe:s:t:")) != -1) {
323 switch (ch) { 331 switch (ch) {
324 case 'l': 332 case 'l':
325 case 'L': 333 case 'L':
@@ -333,6 +341,9 @@ main(int argc, char **argv)
333 ret = 1; 341 ret = 1;
334 goto done; 342 goto done;
335 break; 343 break;
344 case 'c':
345 confirm = 1;
346 break;
336 case 'd': 347 case 'd':
337 deleting = 1; 348 deleting = 1;
338 break; 349 break;
diff --git a/ssh-agent.c b/ssh-agent.c
index 554f8942a..b18dd980c 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -35,7 +35,7 @@
35 35
36#include "includes.h" 36#include "includes.h"
37#include "openbsd-compat/sys-queue.h" 37#include "openbsd-compat/sys-queue.h"
38RCSID("$OpenBSD: ssh-agent.c,v 1.106 2003/01/21 18:14:36 marc Exp $"); 38RCSID("$OpenBSD: ssh-agent.c,v 1.107 2003/01/23 13:50:27 markus Exp $");
39 39
40#include <openssl/evp.h> 40#include <openssl/evp.h>
41#include <openssl/md5.h> 41#include <openssl/md5.h>
@@ -50,6 +50,8 @@ RCSID("$OpenBSD: ssh-agent.c,v 1.106 2003/01/21 18:14:36 marc Exp $");
50#include "authfd.h" 50#include "authfd.h"
51#include "compat.h" 51#include "compat.h"
52#include "log.h" 52#include "log.h"
53#include "readpass.h"
54#include "misc.h"
53 55
54#ifdef SMARTCARD 56#ifdef SMARTCARD
55#include "scard.h" 57#include "scard.h"
@@ -77,6 +79,7 @@ typedef struct identity {
77 Key *key; 79 Key *key;
78 char *comment; 80 char *comment;
79 u_int death; 81 u_int death;
82 u_int confirm;
80} Identity; 83} Identity;
81 84
82typedef struct { 85typedef struct {
@@ -162,6 +165,30 @@ lookup_identity(Key *key, int version)
162 return (NULL); 165 return (NULL);
163} 166}
164 167
168/* Check confirmation of keysign request */
169static int
170confirm_key(Identity *id)
171{
172 char *p, prompt[1024];
173 int ret = -1;
174
175 p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
176 snprintf(prompt, sizeof(prompt), "Allow use of key %s?\n"
177 "Key fingerprint %s.", id->comment, p);
178 xfree(p);
179 p = read_passphrase(prompt, RP_ALLOW_EOF);
180 if (p != NULL) {
181 /*
182 * Accept empty responses and responses consisting
183 * of the word "yes" as affirmative.
184 */
185 if (*p == '\0' || *p == '\n' || strcasecmp(p, "yes") == 0)
186 ret = 0;
187 xfree(p);
188 }
189 return (ret);
190}
191
165/* send list of supported public keys to 'client' */ 192/* send list of supported public keys to 'client' */
166static void 193static void
167process_request_identities(SocketEntry *e, int version) 194process_request_identities(SocketEntry *e, int version)
@@ -225,7 +252,7 @@ process_authentication_challenge1(SocketEntry *e)
225 goto failure; 252 goto failure;
226 253
227 id = lookup_identity(key, 1); 254 id = lookup_identity(key, 1);
228 if (id != NULL) { 255 if (id != NULL && (!id->confirm || confirm_key(id) == 0)) {
229 Key *private = id->key; 256 Key *private = id->key;
230 /* Decrypt the challenge using the private key. */ 257 /* Decrypt the challenge using the private key. */
231 if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0) 258 if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
@@ -285,7 +312,7 @@ process_sign_request2(SocketEntry *e)
285 key = key_from_blob(blob, blen); 312 key = key_from_blob(blob, blen);
286 if (key != NULL) { 313 if (key != NULL) {
287 Identity *id = lookup_identity(key, 2); 314 Identity *id = lookup_identity(key, 2);
288 if (id != NULL) 315 if (id != NULL && (!id->confirm || confirm_key(id) == 0))
289 ok = key_sign(id->key, &signature, &slen, data, dlen); 316 ok = key_sign(id->key, &signature, &slen, data, dlen);
290 } 317 }
291 key_free(key); 318 key_free(key);
@@ -405,7 +432,7 @@ static void
405process_add_identity(SocketEntry *e, int version) 432process_add_identity(SocketEntry *e, int version)
406{ 433{
407 Idtab *tab = idtab_lookup(version); 434 Idtab *tab = idtab_lookup(version);
408 int type, success = 0, death = 0; 435 int type, success = 0, death = 0, confirm = 0;
409 char *type_name, *comment; 436 char *type_name, *comment;
410 Key *k = NULL; 437 Key *k = NULL;
411 438
@@ -467,6 +494,9 @@ process_add_identity(SocketEntry *e, int version)
467 case SSH_AGENT_CONSTRAIN_LIFETIME: 494 case SSH_AGENT_CONSTRAIN_LIFETIME:
468 death = time(NULL) + buffer_get_int(&e->request); 495 death = time(NULL) + buffer_get_int(&e->request);
469 break; 496 break;
497 case SSH_AGENT_CONSTRAIN_CONFIRM:
498 confirm = 1;
499 break;
470 default: 500 default:
471 break; 501 break;
472 } 502 }
@@ -478,6 +508,7 @@ process_add_identity(SocketEntry *e, int version)
478 id->key = k; 508 id->key = k;
479 id->comment = comment; 509 id->comment = comment;
480 id->death = death; 510 id->death = death;
511 id->confirm = confirm;
481 TAILQ_INSERT_TAIL(&tab->idlist, id, next); 512 TAILQ_INSERT_TAIL(&tab->idlist, id, next);
482 /* Increment the number of identities. */ 513 /* Increment the number of identities. */
483 tab->nentries++; 514 tab->nentries++;
@@ -562,6 +593,7 @@ process_add_smartcard_key (SocketEntry *e)
562 id->key = k; 593 id->key = k;
563 id->comment = xstrdup("smartcard key"); 594 id->comment = xstrdup("smartcard key");
564 id->death = 0; 595 id->death = 0;
596 id->confirm = 0;
565 TAILQ_INSERT_TAIL(&tab->idlist, id, next); 597 TAILQ_INSERT_TAIL(&tab->idlist, id, next);
566 tab->nentries++; 598 tab->nentries++;
567 success = 1; 599 success = 1;
@@ -942,7 +974,8 @@ usage(void)
942int 974int
943main(int ac, char **av) 975main(int ac, char **av)
944{ 976{
945 int sock, c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, ch, nalloc; 977 int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0;
978 int sock, fd, ch, nalloc;
946 char *shell, *format, *pidstr, *agentsocket = NULL; 979 char *shell, *format, *pidstr, *agentsocket = NULL;
947 fd_set *readsetp = NULL, *writesetp = NULL; 980 fd_set *readsetp = NULL, *writesetp = NULL;
948 struct sockaddr_un sunaddr; 981 struct sockaddr_un sunaddr;
@@ -1128,9 +1161,14 @@ main(int ac, char **av)
1128 } 1161 }
1129 1162
1130 (void)chdir("/"); 1163 (void)chdir("/");
1131 close(0); 1164 if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
1132 close(1); 1165 /* XXX might close listen socket */
1133 close(2); 1166 (void)dup2(fd, STDIN_FILENO);
1167 (void)dup2(fd, STDOUT_FILENO);
1168 (void)dup2(fd, STDERR_FILENO);
1169 if (fd > 2)
1170 close(fd);
1171 }
1134 1172
1135#ifdef HAVE_SETRLIMIT 1173#ifdef HAVE_SETRLIMIT
1136 /* deny core dumps, since memory contains unencrypted private keys */ 1174 /* deny core dumps, since memory contains unencrypted private keys */