11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: ssh-pkcs11-helper.c,v 1.3 2010/02/24 06:12:53 djm Exp $ */ 21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2010 Markus Friedl. All rights reserved. 41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permission to use, copy, modify, and distribute this software for any 61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * purpose with or without fee is hereby granted, provided that the above 71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * copyright notice and this permission notice appear in all copies. 81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h" 191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h> 211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_SYS_TIME_H 221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood# include <sys/time.h> 231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif 241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "openbsd-compat/sys-queue.h" 261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h> 281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h> 291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <unistd.h> 301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <errno.h> 311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h" 331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h" 341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h" 351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h" 361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "key.h" 371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "authfd.h" 381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "ssh-pkcs11.h" 391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef ENABLE_PKCS11 411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* borrows code from sftp-server and ssh-agent */ 431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct pkcs11_keyinfo { 451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *key; 461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *providername; 471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood TAILQ_ENTRY(pkcs11_keyinfo) next; 481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}; 491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 501305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodTAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist; 511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define MAX_MSG_LENGTH 10240 /*XXX*/ 531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* helper */ 551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define get_int() buffer_get_int(&iqueue); 561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define get_string(lenp) buffer_get_string(&iqueue, lenp); 571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* input and output queue */ 591305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodBuffer iqueue; 601305e95ba6ff9fa202d0818caf10405df4b0f648Mike LockwoodBuffer oqueue; 611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodadd_key(Key *k, char *name) 641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_keyinfo *ki; 661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ki = xcalloc(1, sizeof(*ki)); 681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ki->providername = xstrdup(name); 691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ki->key = k; 701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next); 711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwooddel_keys_by_name(char *name) 751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_keyinfo *ki, *nxt; 771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (ki = TAILQ_FIRST(&pkcs11_keylist); ki; ki = nxt) { 791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood nxt = TAILQ_NEXT(ki, next); 801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (!strcmp(ki->providername, name)) { 811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood TAILQ_REMOVE(&pkcs11_keylist, ki, next); 821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(ki->providername); 831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(ki->key); 841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood free(ki); 851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* lookup matching 'private' key */ 901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic Key * 911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodlookup_key(Key *k) 921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood struct pkcs11_keyinfo *ki; 941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood TAILQ_FOREACH(ki, &pkcs11_keylist, next) { 961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("check %p %s", ki, ki->providername); 971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (key_equal(k, ki->key)) 981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (ki->key); 991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return (NULL); 1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodsend_msg(Buffer *m) 1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int mlen = buffer_len(m); 1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_int(&oqueue, mlen); 1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(&oqueue, buffer_ptr(m), mlen); 1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_consume(m, mlen); 1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_add(void) 1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *name, *pin; 1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key **keys; 1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int i, nkeys; 1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char *blob; 1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int blen; 1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer msg; 1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&msg); 1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood name = get_string(NULL); 1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pin = get_string(NULL); 1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((nkeys = pkcs11_add_provider(name, pin, &keys)) > 0) { 1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_char(&msg, SSH2_AGENT_IDENTITIES_ANSWER); 1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_int(&msg, nkeys); 1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (i = 0; i < nkeys; i++) { 1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_to_blob(keys[i], &blob, &blen); 1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_string(&msg, blob, blen); 1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_cstring(&msg, name); 1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(blob); 1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood add_key(keys[i], name); 1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(keys); 1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_char(&msg, SSH_AGENT_FAILURE); 1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(pin); 1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(name); 1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood send_msg(&msg); 1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&msg); 1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_del(void) 1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char *name, *pin; 1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer msg; 1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&msg); 1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood name = get_string(NULL); 1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pin = get_string(NULL); 1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood del_keys_by_name(name); 1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (pkcs11_del_provider(name) == 0) 1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_char(&msg, SSH_AGENT_SUCCESS); 1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood else 1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_char(&msg, SSH_AGENT_FAILURE); 1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(pin); 1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(name); 1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood send_msg(&msg); 1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&msg); 1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess_sign(void) 1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char *blob, *data, *signature = NULL; 1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int blen, dlen, slen = 0; 1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int ok = -1, flags, ret; 1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Key *key, *found; 1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood Buffer msg; 1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood blob = get_string(&blen); 1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood data = get_string(&dlen); 1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood flags = get_int(); /* XXX ignore */ 1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((key = key_from_blob(blob, blen)) != NULL) { 1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((found = lookup_key(key)) != NULL) { 1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood slen = RSA_size(key->rsa); 1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood signature = xmalloc(slen); 1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((ret = RSA_private_encrypt(dlen, data, signature, 1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood found->rsa, RSA_PKCS1_PADDING)) != -1) { 1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood slen = ret; 1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ok = 0; 1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood key_free(key); 1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&msg); 1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (ok == 0) { 1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); 1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_string(&msg, signature, slen); 1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_char(&msg, SSH_AGENT_FAILURE); 1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(data); 1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(blob); 2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (signature != NULL) 2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(signature); 2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood send_msg(&msg); 2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_free(&msg); 2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic void 2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodprocess(void) 2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int msg_len; 2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int buf_len; 2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int consumed; 2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int type; 2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char *cp; 2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buf_len = buffer_len(&iqueue); 2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buf_len < 5) 2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; /* Incomplete message. */ 2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cp = buffer_ptr(&iqueue); 2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood msg_len = get_u32(cp); 2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (msg_len > MAX_MSG_LENGTH) { 2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("bad message len %d", msg_len); 2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(11); 2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buf_len < msg_len + 4) 2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return; 2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_consume(&iqueue, 4); 2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buf_len -= 4; 2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood type = buffer_get_char(&iqueue); 2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood switch (type) { 2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case SSH_AGENTC_ADD_SMARTCARD_KEY: 2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("process_add"); 2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood process_add(); 2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case SSH_AGENTC_REMOVE_SMARTCARD_KEY: 2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("process_del"); 2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood process_del(); 2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood case SSH2_AGENTC_SIGN_REQUEST: 2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("process_sign"); 2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood process_sign(); 2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood default: 2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("Unknown message %d", type); 2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood break; 2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* discard the remaining bytes from the current packet */ 2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buf_len < buffer_len(&iqueue)) { 2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("iqueue grew unexpectedly"); 2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(255); 2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood consumed = buf_len - buffer_len(&iqueue); 2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (msg_len < consumed) { 2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("msg_len %d < consumed %d", msg_len, consumed); 2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(255); 2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (msg_len > consumed) 2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_consume(&iqueue, msg_len - consumed); 2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodcleanup_exit(int i) 2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* XXX */ 2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood _exit(i); 2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmain(int argc, char **argv) 2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fd_set *rset, *wset; 2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int in, out, max, log_stderr = 0; 2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ssize_t len, olen, set_size; 2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; 2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood LogLevel log_level = SYSLOG_LEVEL_ERROR; 2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood char buf[4*4096]; 2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood extern char *optarg; 2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood extern char *__progname; 2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood TAILQ_INIT(&pkcs11_keylist); 2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood pkcs11_init(0); 2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood seed_rng(); 2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood __progname = ssh_get_progname(argv[0]); 2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood log_init(__progname, log_level, log_facility, log_stderr); 2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood in = STDIN_FILENO; 2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood out = STDOUT_FILENO; 2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max = 0; 2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (in > max) 2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max = in; 2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (out > max) 2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood max = out; 2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&iqueue); 2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_init(&oqueue); 2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); 3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood rset = (fd_set *)xmalloc(set_size); 3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood wset = (fd_set *)xmalloc(set_size); 3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood for (;;) { 3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(rset, 0, set_size); 3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood memset(wset, 0, set_size); 3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Ensure that we can read a full buffer and handle 3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * the worst-case length packet it can generate, 3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * otherwise apply backpressure by stopping reads. 3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buffer_check_alloc(&iqueue, sizeof(buf)) && 3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_check_alloc(&oqueue, MAX_MSG_LENGTH)) 3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FD_SET(in, rset); 3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood olen = buffer_len(&oqueue); 3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (olen > 0) 3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood FD_SET(out, wset); 3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (select(max+1, rset, wset, NULL, NULL) < 0) { 3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (errno == EINTR) 3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood continue; 3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("select: %s", strerror(errno)); 3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(2); 3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* copy stdin to iqueue */ 3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (FD_ISSET(in, rset)) { 3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = read(in, buf, sizeof buf); 3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len == 0) { 3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood debug("read eof"); 3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(0); 3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else if (len < 0) { 3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("read: %s", strerror(errno)); 3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(1); 3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_append(&iqueue, buf, len); 3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* send oqueue to stdout */ 3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (FD_ISSET(out, wset)) { 3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = write(out, buffer_ptr(&oqueue), olen); 3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len < 0) { 3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("write: %s", strerror(errno)); 3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood cleanup_exit(1); 3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } else { 3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_consume(&oqueue, len); 3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* 3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Process requests from client if we can fit the results 3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * into the output buffer, otherwise stop processing input 3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * and let the output queue drain. 3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buffer_check_alloc(&oqueue, MAX_MSG_LENGTH)) 3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood process(); 3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#else /* ENABLE_PKCS11 */ 3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmain(int argc, char **argv) 3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood extern char *__progname; 3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood __progname = ssh_get_progname(argv[0]); 3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood log_init(__progname, SYSLOG_LEVEL_ERROR, SYSLOG_FACILITY_AUTH, 0); 3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("PKCS#11 support disabled at compile time"); 3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* ENABLE_PKCS11 */ 372