1d059297112922cabb0c674840589be8db821fd9aAdam Langley/* $OpenBSD: ssh-pkcs11-helper.c,v 1.10 2015/01/20 23:14:00 deraadt Exp $ */ 2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 2010 Markus Friedl. All rights reserved. 4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Permission to use, copy, modify, and distribute this software for any 6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * purpose with or without fee is hereby granted, provided that the above 7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * copyright notice and this permission notice appear in all copies. 8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h" 19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/types.h> 21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_SYS_TIME_H 22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# include <sys/time.h> 23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "openbsd-compat/sys-queue.h" 26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdarg.h> 28bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h> 29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <unistd.h> 30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <errno.h> 31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 32bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "xmalloc.h" 33bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "buffer.h" 34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "log.h" 35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "misc.h" 36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "key.h" 37bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "authfd.h" 38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "ssh-pkcs11.h" 39bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef ENABLE_PKCS11 41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* borrows code from sftp-server and ssh-agent */ 43bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstruct pkcs11_keyinfo { 45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Key *key; 46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *providername; 47bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_ENTRY(pkcs11_keyinfo) next; 48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}; 49bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 50bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanTAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist; 51bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 52bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define MAX_MSG_LENGTH 10240 /*XXX*/ 53bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 54bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* helper */ 55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define get_int() buffer_get_int(&iqueue); 56bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#define get_string(lenp) buffer_get_string(&iqueue, lenp); 57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* input and output queue */ 59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanBuffer iqueue; 60bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanBuffer oqueue; 61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanadd_key(Key *k, char *name) 64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 65bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct pkcs11_keyinfo *ki; 66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ki = xcalloc(1, sizeof(*ki)); 68bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ki->providername = xstrdup(name); 69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ki->key = k; 70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next); 71bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 72bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 73bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 74bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmandel_keys_by_name(char *name) 75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 76bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct pkcs11_keyinfo *ki, *nxt; 77bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 78bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (ki = TAILQ_FIRST(&pkcs11_keylist); ki; ki = nxt) { 79bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman nxt = TAILQ_NEXT(ki, next); 80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!strcmp(ki->providername, name)) { 81bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_REMOVE(&pkcs11_keylist, ki, next); 82d059297112922cabb0c674840589be8db821fd9aAdam Langley free(ki->providername); 83bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman key_free(ki->key); 84bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman free(ki); 85bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 86bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 87bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 89bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* lookup matching 'private' key */ 90bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic Key * 91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanlookup_key(Key *k) 92bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct pkcs11_keyinfo *ki; 94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_FOREACH(ki, &pkcs11_keylist, next) { 96bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("check %p %s", ki, ki->providername); 97bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (key_equal(k, ki->key)) 98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (ki->key); 99bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (NULL); 101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansend_msg(Buffer *m) 105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int mlen = buffer_len(m); 107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_put_int(&oqueue, mlen); 109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_append(&oqueue, buffer_ptr(m), mlen); 110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_consume(m, mlen); 111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_add(void) 115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *name, *pin; 117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Key **keys; 118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int i, nkeys; 119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *blob; 120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int blen; 121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Buffer msg; 122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_init(&msg); 124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman name = get_string(NULL); 125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pin = get_string(NULL); 126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((nkeys = pkcs11_add_provider(name, pin, &keys)) > 0) { 127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_put_char(&msg, SSH2_AGENT_IDENTITIES_ANSWER); 128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_put_int(&msg, nkeys); 129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < nkeys; i++) { 130d059297112922cabb0c674840589be8db821fd9aAdam Langley if (key_to_blob(keys[i], &blob, &blen) == 0) 131d059297112922cabb0c674840589be8db821fd9aAdam Langley continue; 132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_put_string(&msg, blob, blen); 133bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_put_cstring(&msg, name); 134d059297112922cabb0c674840589be8db821fd9aAdam Langley free(blob); 135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman add_key(keys[i], name); 136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 137d059297112922cabb0c674840589be8db821fd9aAdam Langley free(keys); 138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_put_char(&msg, SSH_AGENT_FAILURE); 140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 141d059297112922cabb0c674840589be8db821fd9aAdam Langley free(pin); 142d059297112922cabb0c674840589be8db821fd9aAdam Langley free(name); 143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman send_msg(&msg); 144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_free(&msg); 145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_del(void) 149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *name, *pin; 151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Buffer msg; 152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_init(&msg); 154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman name = get_string(NULL); 155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pin = get_string(NULL); 156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman del_keys_by_name(name); 157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pkcs11_del_provider(name) == 0) 158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_put_char(&msg, SSH_AGENT_SUCCESS); 159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_put_char(&msg, SSH_AGENT_FAILURE); 161d059297112922cabb0c674840589be8db821fd9aAdam Langley free(pin); 162d059297112922cabb0c674840589be8db821fd9aAdam Langley free(name); 163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman send_msg(&msg); 164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_free(&msg); 165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_sign(void) 169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *blob, *data, *signature = NULL; 171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int blen, dlen, slen = 0; 172d059297112922cabb0c674840589be8db821fd9aAdam Langley int ok = -1; 173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Key *key, *found; 174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Buffer msg; 175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman blob = get_string(&blen); 177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman data = get_string(&dlen); 178d059297112922cabb0c674840589be8db821fd9aAdam Langley (void)get_int(); /* XXX ignore flags */ 179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((key = key_from_blob(blob, blen)) != NULL) { 181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((found = lookup_key(key)) != NULL) { 182d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 183d059297112922cabb0c674840589be8db821fd9aAdam Langley int ret; 184d059297112922cabb0c674840589be8db821fd9aAdam Langley 185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman slen = RSA_size(key->rsa); 186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signature = xmalloc(slen); 187bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((ret = RSA_private_encrypt(dlen, data, signature, 188bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman found->rsa, RSA_PKCS1_PADDING)) != -1) { 189bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman slen = ret; 190bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ok = 0; 191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 192d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* WITH_OPENSSL */ 193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman key_free(key); 195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_init(&msg); 197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ok == 0) { 198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); 199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_put_string(&msg, signature, slen); 200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_put_char(&msg, SSH_AGENT_FAILURE); 202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 203d059297112922cabb0c674840589be8db821fd9aAdam Langley free(data); 204d059297112922cabb0c674840589be8db821fd9aAdam Langley free(blob); 205d059297112922cabb0c674840589be8db821fd9aAdam Langley free(signature); 206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman send_msg(&msg); 207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_free(&msg); 208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess(void) 212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int msg_len; 214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int buf_len; 215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int consumed; 216bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int type; 217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *cp; 218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 219bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buf_len = buffer_len(&iqueue); 220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buf_len < 5) 221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; /* Incomplete message. */ 222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cp = buffer_ptr(&iqueue); 223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman msg_len = get_u32(cp); 224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (msg_len > MAX_MSG_LENGTH) { 225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("bad message len %d", msg_len); 226bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_exit(11); 227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buf_len < msg_len + 4) 229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_consume(&iqueue, 4); 231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buf_len -= 4; 232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman type = buffer_get_char(&iqueue); 233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (type) { 234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_ADD_SMARTCARD_KEY: 235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("process_add"); 236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_add(); 237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_REMOVE_SMARTCARD_KEY: 239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("process_del"); 240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_del(); 241bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 242bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH2_AGENTC_SIGN_REQUEST: 243bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("process_sign"); 244bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_sign(); 245bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 246bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 247bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("Unknown message %d", type); 248bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 249bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 250bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* discard the remaining bytes from the current packet */ 251bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buf_len < buffer_len(&iqueue)) { 252bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("iqueue grew unexpectedly"); 253bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_exit(255); 254bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 255bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman consumed = buf_len - buffer_len(&iqueue); 256bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (msg_len < consumed) { 257bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("msg_len %d < consumed %d", msg_len, consumed); 258bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_exit(255); 259bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 260bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (msg_len > consumed) 261bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_consume(&iqueue, msg_len - consumed); 262bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 263bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 264bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 265bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancleanup_exit(int i) 266bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 267bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* XXX */ 268bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman _exit(i); 269bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 270bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 271bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 272bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanmain(int argc, char **argv) 273bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 274bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fd_set *rset, *wset; 275bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int in, out, max, log_stderr = 0; 276bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ssize_t len, olen, set_size; 277bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; 278bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman LogLevel log_level = SYSLOG_LEVEL_ERROR; 279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char buf[4*4096]; 280bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 281bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman extern char *__progname; 282bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 283bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_INIT(&pkcs11_keylist); 284bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pkcs11_init(0); 285bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 286bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman seed_rng(); 287bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman __progname = ssh_get_progname(argv[0]); 288bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 289bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman log_init(__progname, log_level, log_facility, log_stderr); 290bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 291bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman in = STDIN_FILENO; 292bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman out = STDOUT_FILENO; 293bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 294bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman max = 0; 295bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (in > max) 296bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman max = in; 297bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (out > max) 298bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman max = out; 299bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 300bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_init(&iqueue); 301bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_init(&oqueue); 302bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 303bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); 304bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman rset = (fd_set *)xmalloc(set_size); 305bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman wset = (fd_set *)xmalloc(set_size); 306bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 307bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (;;) { 308bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(rset, 0, set_size); 309bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(wset, 0, set_size); 310bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 311bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 312bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Ensure that we can read a full buffer and handle 313bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * the worst-case length packet it can generate, 314bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * otherwise apply backpressure by stopping reads. 315bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 316bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buffer_check_alloc(&iqueue, sizeof(buf)) && 317bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_check_alloc(&oqueue, MAX_MSG_LENGTH)) 318bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman FD_SET(in, rset); 319bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 320bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman olen = buffer_len(&oqueue); 321bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (olen > 0) 322bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman FD_SET(out, wset); 323bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 324bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (select(max+1, rset, wset, NULL, NULL) < 0) { 325bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errno == EINTR) 326bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 327bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("select: %s", strerror(errno)); 328bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_exit(2); 329bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 330bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 331bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* copy stdin to iqueue */ 332bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (FD_ISSET(in, rset)) { 333bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman len = read(in, buf, sizeof buf); 334bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (len == 0) { 335bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("read eof"); 336bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_exit(0); 337bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (len < 0) { 338bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("read: %s", strerror(errno)); 339bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_exit(1); 340bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 341bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_append(&iqueue, buf, len); 342bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 343bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 344bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* send oqueue to stdout */ 345bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (FD_ISSET(out, wset)) { 346bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman len = write(out, buffer_ptr(&oqueue), olen); 347bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (len < 0) { 348bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("write: %s", strerror(errno)); 349bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_exit(1); 350bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 351bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman buffer_consume(&oqueue, len); 352bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 353bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 354bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 355bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 356bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Process requests from client if we can fit the results 357bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * into the output buffer, otherwise stop processing input 358bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * and let the output queue drain. 359bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 360bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (buffer_check_alloc(&oqueue, MAX_MSG_LENGTH)) 361bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process(); 362bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 363bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 364bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#else /* ENABLE_PKCS11 */ 365bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 366bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanmain(int argc, char **argv) 367bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 368bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman extern char *__progname; 369bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 370bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman __progname = ssh_get_progname(argv[0]); 371bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman log_init(__progname, SYSLOG_LEVEL_ERROR, SYSLOG_FACILITY_AUTH, 0); 372bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("PKCS#11 support disabled at compile time"); 373bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 374bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* ENABLE_PKCS11 */ 375