summaryrefslogtreecommitdiff
path: root/ssh-pkcs11-helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssh-pkcs11-helper.c')
-rw-r--r--ssh-pkcs11-helper.c106
1 files changed, 70 insertions, 36 deletions
diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c
index 6301033c5..97fb1212c 100644
--- a/ssh-pkcs11-helper.c
+++ b/ssh-pkcs11-helper.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11-helper.c,v 1.14 2018/01/08 15:18:46 markus Exp $ */ 1/* $OpenBSD: ssh-pkcs11-helper.c,v 1.17 2019/01/23 02:01:10 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * 4 *
@@ -24,10 +24,11 @@
24 24
25#include "openbsd-compat/sys-queue.h" 25#include "openbsd-compat/sys-queue.h"
26 26
27#include <errno.h>
28#include <poll.h>
27#include <stdarg.h> 29#include <stdarg.h>
28#include <string.h> 30#include <string.h>
29#include <unistd.h> 31#include <unistd.h>
30#include <errno.h>
31 32
32#include "xmalloc.h" 33#include "xmalloc.h"
33#include "sshbuf.h" 34#include "sshbuf.h"
@@ -110,7 +111,7 @@ static void
110process_add(void) 111process_add(void)
111{ 112{
112 char *name, *pin; 113 char *name, *pin;
113 struct sshkey **keys; 114 struct sshkey **keys = NULL;
114 int r, i, nkeys; 115 int r, i, nkeys;
115 u_char *blob; 116 u_char *blob;
116 size_t blen; 117 size_t blen;
@@ -139,11 +140,13 @@ process_add(void)
139 free(blob); 140 free(blob);
140 add_key(keys[i], name); 141 add_key(keys[i], name);
141 } 142 }
142 free(keys);
143 } else { 143 } else {
144 if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) 144 if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
145 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 145 fatal("%s: buffer error: %s", __func__, ssh_err(r));
146 if ((r = sshbuf_put_u32(msg, -nkeys)) != 0)
147 fatal("%s: buffer error: %s", __func__, ssh_err(r));
146 } 148 }
149 free(keys);
147 free(pin); 150 free(pin);
148 free(name); 151 free(name);
149 send_msg(msg); 152 send_msg(msg);
@@ -192,15 +195,33 @@ process_sign(void)
192 else { 195 else {
193 if ((found = lookup_key(key)) != NULL) { 196 if ((found = lookup_key(key)) != NULL) {
194#ifdef WITH_OPENSSL 197#ifdef WITH_OPENSSL
198 u_int xslen;
195 int ret; 199 int ret;
196 200
197 slen = RSA_size(key->rsa); 201 if (key->type == KEY_RSA) {
198 signature = xmalloc(slen); 202 slen = RSA_size(key->rsa);
199 if ((ret = RSA_private_encrypt(dlen, data, signature, 203 signature = xmalloc(slen);
200 found->rsa, RSA_PKCS1_PADDING)) != -1) { 204 ret = RSA_private_encrypt(dlen, data, signature,
201 slen = ret; 205 found->rsa, RSA_PKCS1_PADDING);
202 ok = 0; 206 if (ret != -1) {
203 } 207 slen = ret;
208 ok = 0;
209 }
210 } else if (key->type == KEY_ECDSA) {
211 xslen = ECDSA_size(key->ecdsa);
212 signature = xmalloc(xslen);
213 /* "The parameter type is ignored." */
214 ret = ECDSA_sign(-1, data, dlen, signature,
215 &xslen, found->ecdsa);
216 if (ret != 0)
217 ok = 0;
218 else
219 error("%s: ECDSA_sign"
220 " returns %d", __func__, ret);
221 slen = xslen;
222 } else
223 error("%s: don't know how to sign with key "
224 "type %d", __func__, (int)key->type);
204#endif /* WITH_OPENSSL */ 225#endif /* WITH_OPENSSL */
205 } 226 }
206 sshkey_free(key); 227 sshkey_free(key);
@@ -287,27 +308,44 @@ cleanup_exit(int i)
287 _exit(i); 308 _exit(i);
288} 309}
289 310
311
290int 312int
291main(int argc, char **argv) 313main(int argc, char **argv)
292{ 314{
293 fd_set *rset, *wset; 315 int r, ch, in, out, max, log_stderr = 0;
294 int r, in, out, max, log_stderr = 0; 316 ssize_t len;
295 ssize_t len, olen, set_size;
296 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; 317 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
297 LogLevel log_level = SYSLOG_LEVEL_ERROR; 318 LogLevel log_level = SYSLOG_LEVEL_ERROR;
298 char buf[4*4096]; 319 char buf[4*4096];
299
300 extern char *__progname; 320 extern char *__progname;
321 struct pollfd pfd[2];
301 322
302 ssh_malloc_init(); /* must be called before any mallocs */ 323 ssh_malloc_init(); /* must be called before any mallocs */
324 __progname = ssh_get_progname(argv[0]);
325 seed_rng();
303 TAILQ_INIT(&pkcs11_keylist); 326 TAILQ_INIT(&pkcs11_keylist);
304 pkcs11_init(0);
305 327
306 seed_rng(); 328 log_init(__progname, log_level, log_facility, log_stderr);
307 __progname = ssh_get_progname(argv[0]); 329
330 while ((ch = getopt(argc, argv, "v")) != -1) {
331 switch (ch) {
332 case 'v':
333 log_stderr = 1;
334 if (log_level == SYSLOG_LEVEL_ERROR)
335 log_level = SYSLOG_LEVEL_DEBUG1;
336 else if (log_level < SYSLOG_LEVEL_DEBUG3)
337 log_level++;
338 break;
339 default:
340 fprintf(stderr, "usage: %s [-v]\n", __progname);
341 exit(1);
342 }
343 }
308 344
309 log_init(__progname, log_level, log_facility, log_stderr); 345 log_init(__progname, log_level, log_facility, log_stderr);
310 346
347 pkcs11_init(0);
348
311 in = STDIN_FILENO; 349 in = STDIN_FILENO;
312 out = STDOUT_FILENO; 350 out = STDOUT_FILENO;
313 351
@@ -322,13 +360,10 @@ main(int argc, char **argv)
322 if ((oqueue = sshbuf_new()) == NULL) 360 if ((oqueue = sshbuf_new()) == NULL)
323 fatal("%s: sshbuf_new failed", __func__); 361 fatal("%s: sshbuf_new failed", __func__);
324 362
325 set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); 363 while (1) {
326 rset = xmalloc(set_size); 364 memset(pfd, 0, sizeof(pfd));
327 wset = xmalloc(set_size); 365 pfd[0].fd = in;
328 366 pfd[1].fd = out;
329 for (;;) {
330 memset(rset, 0, set_size);
331 memset(wset, 0, set_size);
332 367
333 /* 368 /*
334 * Ensure that we can read a full buffer and handle 369 * Ensure that we can read a full buffer and handle
@@ -337,23 +372,21 @@ main(int argc, char **argv)
337 */ 372 */
338 if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 && 373 if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
339 (r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0) 374 (r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
340 FD_SET(in, rset); 375 pfd[0].events = POLLIN;
341 else if (r != SSH_ERR_NO_BUFFER_SPACE) 376 else if (r != SSH_ERR_NO_BUFFER_SPACE)
342 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 377 fatal("%s: buffer error: %s", __func__, ssh_err(r));
343 378
344 olen = sshbuf_len(oqueue); 379 if (sshbuf_len(oqueue) > 0)
345 if (olen > 0) 380 pfd[1].events = POLLOUT;
346 FD_SET(out, wset);
347 381
348 if (select(max+1, rset, wset, NULL, NULL) < 0) { 382 if ((r = poll(pfd, 2, -1 /* INFTIM */)) <= 0) {
349 if (errno == EINTR) 383 if (r == 0 || errno == EINTR)
350 continue; 384 continue;
351 error("select: %s", strerror(errno)); 385 fatal("poll: %s", strerror(errno));
352 cleanup_exit(2);
353 } 386 }
354 387
355 /* copy stdin to iqueue */ 388 /* copy stdin to iqueue */
356 if (FD_ISSET(in, rset)) { 389 if ((pfd[0].revents & (POLLIN|POLLERR)) != 0) {
357 len = read(in, buf, sizeof buf); 390 len = read(in, buf, sizeof buf);
358 if (len == 0) { 391 if (len == 0) {
359 debug("read eof"); 392 debug("read eof");
@@ -367,8 +400,9 @@ main(int argc, char **argv)
367 } 400 }
368 } 401 }
369 /* send oqueue to stdout */ 402 /* send oqueue to stdout */
370 if (FD_ISSET(out, wset)) { 403 if ((pfd[1].revents & (POLLOUT|POLLHUP)) != 0) {
371 len = write(out, sshbuf_ptr(oqueue), olen); 404 len = write(out, sshbuf_ptr(oqueue),
405 sshbuf_len(oqueue));
372 if (len < 0) { 406 if (len < 0) {
373 error("write: %s", strerror(errno)); 407 error("write: %s", strerror(errno));
374 cleanup_exit(1); 408 cleanup_exit(1);