1d059297112922cabb0c674840589be8db821fd9aAdam Langley/* $OpenBSD: ssh-agent.c,v 1.199 2015/03/04 21:12:59 djm Exp $ */ 2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* 3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Author: Tatu Ylonen <ylo@cs.hut.fi> 4bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * All rights reserved 6bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * The authentication agent program. 7bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * As far as I am concerned, the code I have written for this software 9bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * can be used freely for any purpose. Any derived versions of this 10bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * software must be clearly marked as such, and if the derived work is 11bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * incompatible with the protocol description in the RFC file, it must be 12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * called by a name other than "ssh" or "Secure Shell". 13bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 14bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 15bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 16bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Redistribution and use in source and binary forms, with or without 17bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * modification, are permitted provided that the following conditions 18bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * are met: 19bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 1. Redistributions of source code must retain the above copyright 20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer. 21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 2. Redistributions in binary form must reproduce the above copyright 22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * notice, this list of conditions and the following disclaimer in the 23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * documentation and/or other materials provided with the distribution. 24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * 25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 37bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h" 38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 39d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <sys/param.h> /* MIN MAX */ 40bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/types.h> 41bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/param.h> 42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/resource.h> 43bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/stat.h> 44bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/socket.h> 45bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_SYS_TIME_H 46bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# include <sys/time.h> 47bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_SYS_UN_H 49bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# include <sys/un.h> 50bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 51bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "openbsd-compat/sys-queue.h" 52bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 53d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 54bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <openssl/evp.h> 55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "openbsd-compat/openssl-compat.h" 56d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 57bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 58bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <errno.h> 59bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <fcntl.h> 60d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <limits.h> 61bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_PATHS_H 62bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman# include <paths.h> 63bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 64bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <signal.h> 65bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdarg.h> 66bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdio.h> 67bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <stdlib.h> 68bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <time.h> 69bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <string.h> 70bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <unistd.h> 71bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 72d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "key.h" /* XXX for typedef */ 73d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "buffer.h" /* XXX for typedef */ 74d059297112922cabb0c674840589be8db821fd9aAdam Langley 75bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "xmalloc.h" 76bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "ssh.h" 77bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "rsa.h" 78d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "sshbuf.h" 79d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "sshkey.h" 80bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "authfd.h" 81bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "compat.h" 82bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "log.h" 83bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "misc.h" 84d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "digest.h" 85d059297112922cabb0c674840589be8db821fd9aAdam Langley#include "ssherr.h" 86bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 87bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef ENABLE_PKCS11 88bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "ssh-pkcs11.h" 89bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 90bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 91bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#if defined(HAVE_SYS_PRCTL_H) 92bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/prctl.h> /* For prctl() and PR_SET_DUMPABLE */ 93bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 94bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 95bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantypedef enum { 96bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman AUTH_UNUSED, 97bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman AUTH_SOCKET, 98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman AUTH_CONNECTION 99bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} sock_type; 100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantypedef struct { 102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int fd; 103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sock_type type; 104d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshbuf *input; 105d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshbuf *output; 106d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshbuf *request; 107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} SocketEntry; 108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanu_int sockets_alloc = 0; 110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanSocketEntry *sockets = NULL; 111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantypedef struct identity { 113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_ENTRY(identity) next; 114d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshkey *key; 115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *comment; 116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *provider; 117d059297112922cabb0c674840589be8db821fd9aAdam Langley time_t death; 118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int confirm; 119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} Identity; 120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmantypedef struct { 122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int nentries; 123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_HEAD(idqueue, identity) idlist; 124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} Idtab; 125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* private key table, one per protocol version */ 127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg HartmanIdtab idtable[3]; 128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint max_fd = 0; 130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* pid of shell == parent of agent */ 132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanpid_t parent_pid = -1; 133d059297112922cabb0c674840589be8db821fd9aAdam Langleytime_t parent_alive_interval = 0; 134d059297112922cabb0c674840589be8db821fd9aAdam Langley 135d059297112922cabb0c674840589be8db821fd9aAdam Langley/* pid of process for which cleanup_socket is applicable */ 136d059297112922cabb0c674840589be8db821fd9aAdam Langleypid_t cleanup_pid = 0; 137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* pathname and directory for AUTH_SOCKET */ 139d059297112922cabb0c674840589be8db821fd9aAdam Langleychar socket_name[PATH_MAX]; 140d059297112922cabb0c674840589be8db821fd9aAdam Langleychar socket_dir[PATH_MAX]; 141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 142bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* locking */ 143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint locked = 0; 144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar *lock_passwd = NULL; 145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanextern char *__progname; 147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 148d059297112922cabb0c674840589be8db821fd9aAdam Langley/* Default lifetime in seconds (0 == forever) */ 149d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic long lifetime = 0; 150d059297112922cabb0c674840589be8db821fd9aAdam Langley 151d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int fingerprint_hash = SSH_FP_HASH_DEFAULT; 152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanclose_socket(SocketEntry *e) 155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(e->fd); 157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman e->fd = -1; 158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman e->type = AUTH_UNUSED; 159d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_free(e->input); 160d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_free(e->output); 161d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_free(e->request); 162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 163bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanidtab_init(void) 166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int i; 168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i <=2; i++) { 170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_INIT(&idtable[i].idlist); 171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman idtable[i].nentries = 0; 172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* return private key table for requested protocol version */ 176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic Idtab * 177bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanidtab_lookup(int version) 178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 179bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (version < 1 || version > 2) 180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("internal error, bad protocol version %d", version); 181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return &idtable[version]; 182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 184bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanfree_identity(Identity *id) 186bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 187d059297112922cabb0c674840589be8db821fd9aAdam Langley sshkey_free(id->key); 188d059297112922cabb0c674840589be8db821fd9aAdam Langley free(id->provider); 189d059297112922cabb0c674840589be8db821fd9aAdam Langley free(id->comment); 190d059297112922cabb0c674840589be8db821fd9aAdam Langley free(id); 191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* return matching private key for given public key */ 194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic Identity * 195d059297112922cabb0c674840589be8db821fd9aAdam Langleylookup_identity(struct sshkey *key, int version) 196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Identity *id; 198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Idtab *tab = idtab_lookup(version); 200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_FOREACH(id, &tab->idlist, next) { 201d059297112922cabb0c674840589be8db821fd9aAdam Langley if (sshkey_equal(key, id->key)) 202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (id); 203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (NULL); 205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Check confirmation of keysign request */ 208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic int 209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanconfirm_key(Identity *id) 210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *p; 212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int ret = -1; 213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 214d059297112922cabb0c674840589be8db821fd9aAdam Langley p = sshkey_fingerprint(id->key, fingerprint_hash, SSH_FP_DEFAULT); 215d059297112922cabb0c674840589be8db821fd9aAdam Langley if (p != NULL && 216d059297112922cabb0c674840589be8db821fd9aAdam Langley ask_permission("Allow use of key %s?\nKey fingerprint %s.", 217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id->comment, p)) 218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ret = 0; 219d059297112922cabb0c674840589be8db821fd9aAdam Langley free(p); 220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (ret); 222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 224d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic void 225d059297112922cabb0c674840589be8db821fd9aAdam Langleysend_status(SocketEntry *e, int success) 226d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 227d059297112922cabb0c674840589be8db821fd9aAdam Langley int r; 228d059297112922cabb0c674840589be8db821fd9aAdam Langley 229d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_u32(e->output, 1)) != 0 || 230d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_put_u8(e->output, success ? 231d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0) 232d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 233d059297112922cabb0c674840589be8db821fd9aAdam Langley} 234d059297112922cabb0c674840589be8db821fd9aAdam Langley 235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* send list of supported public keys to 'client' */ 236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_request_identities(SocketEntry *e, int version) 238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Idtab *tab = idtab_lookup(version); 240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Identity *id; 241d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshbuf *msg; 242d059297112922cabb0c674840589be8db821fd9aAdam Langley int r; 243d059297112922cabb0c674840589be8db821fd9aAdam Langley 244d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((msg = sshbuf_new()) == NULL) 245d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: sshbuf_new failed", __func__); 246d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_u8(msg, (version == 1) ? 247d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH_AGENT_RSA_IDENTITIES_ANSWER : 248d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || 249d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_put_u32(msg, tab->nentries)) != 0) 250d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 251bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_FOREACH(id, &tab->idlist, next) { 252bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (id->key->type == KEY_RSA1) { 253d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_SSH1 254d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_u32(msg, 255d059297112922cabb0c674840589be8db821fd9aAdam Langley BN_num_bits(id->key->rsa->n))) != 0 || 256d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_put_bignum1(msg, 257d059297112922cabb0c674840589be8db821fd9aAdam Langley id->key->rsa->e)) != 0 || 258d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_put_bignum1(msg, 259d059297112922cabb0c674840589be8db821fd9aAdam Langley id->key->rsa->n)) != 0) 260d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", 261d059297112922cabb0c674840589be8db821fd9aAdam Langley __func__, ssh_err(r)); 262d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 263bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 264bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *blob; 265d059297112922cabb0c674840589be8db821fd9aAdam Langley size_t blen; 266d059297112922cabb0c674840589be8db821fd9aAdam Langley 267d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshkey_to_blob(id->key, &blob, &blen)) != 0) { 268d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: sshkey_to_blob: %s", __func__, 269d059297112922cabb0c674840589be8db821fd9aAdam Langley ssh_err(r)); 270d059297112922cabb0c674840589be8db821fd9aAdam Langley continue; 271d059297112922cabb0c674840589be8db821fd9aAdam Langley } 272d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_string(msg, blob, blen)) != 0) 273d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", 274d059297112922cabb0c674840589be8db821fd9aAdam Langley __func__, ssh_err(r)); 275d059297112922cabb0c674840589be8db821fd9aAdam Langley free(blob); 276bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 277d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_cstring(msg, id->comment)) != 0) 278d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 280d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_stringb(e->output, msg)) != 0) 281d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 282d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_free(msg); 283bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 284bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 285d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_SSH1 286bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* ssh1 only */ 287bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 288bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_authentication_challenge1(SocketEntry *e) 289bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 290bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char buf[32], mdbuf[16], session_id[16]; 291bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int response_type; 292bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BIGNUM *challenge; 293bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Identity *id; 294d059297112922cabb0c674840589be8db821fd9aAdam Langley int r, len; 295d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshbuf *msg; 296d059297112922cabb0c674840589be8db821fd9aAdam Langley struct ssh_digest_ctx *md; 297d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshkey *key; 298d059297112922cabb0c674840589be8db821fd9aAdam Langley 299d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((msg = sshbuf_new()) == NULL) 300d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: sshbuf_new failed", __func__); 301d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((key = sshkey_new(KEY_RSA1)) == NULL) 302d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: sshkey_new failed", __func__); 303bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((challenge = BN_new()) == NULL) 304d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: BN_new failed", __func__); 305bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 306d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_u32(e->request, NULL)) != 0 || /* ignored */ 307d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 || 308d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0 || 309d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_bignum1(e->request, challenge))) 310d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 311bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 312bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Only protocol 1.1 is supported */ 313d059297112922cabb0c674840589be8db821fd9aAdam Langley if (sshbuf_len(e->request) == 0) 314bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto failure; 315d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get(e->request, session_id, sizeof(session_id))) != 0 || 316d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_u32(e->request, &response_type)) != 0) 317d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 318bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (response_type != 1) 319bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto failure; 320bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 321bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id = lookup_identity(key, 1); 322bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { 323d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshkey *private = id->key; 324bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Decrypt the challenge using the private key. */ 325d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = rsa_private_decrypt(challenge, challenge, 326d059297112922cabb0c674840589be8db821fd9aAdam Langley private->rsa) != 0)) { 327d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: rsa_public_encrypt: %s", __func__, 328d059297112922cabb0c674840589be8db821fd9aAdam Langley ssh_err(r)); 329d059297112922cabb0c674840589be8db821fd9aAdam Langley goto failure; /* XXX ? */ 330d059297112922cabb0c674840589be8db821fd9aAdam Langley } 331bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 332d059297112922cabb0c674840589be8db821fd9aAdam Langley /* The response is MD5 of decrypted challenge plus session id */ 333bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman len = BN_num_bytes(challenge); 334bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (len <= 0 || len > 32) { 335d059297112922cabb0c674840589be8db821fd9aAdam Langley logit("%s: bad challenge length %d", __func__, len); 336bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto failure; 337bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 338bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(buf, 0, 32); 339bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BN_bn2bin(challenge, buf + 32 - len); 340d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || 341d059297112922cabb0c674840589be8db821fd9aAdam Langley ssh_digest_update(md, buf, 32) < 0 || 342d059297112922cabb0c674840589be8db821fd9aAdam Langley ssh_digest_update(md, session_id, 16) < 0 || 343d059297112922cabb0c674840589be8db821fd9aAdam Langley ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0) 344d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: md5 failed", __func__); 345d059297112922cabb0c674840589be8db821fd9aAdam Langley ssh_digest_free(md); 346bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 347bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Send the response. */ 348d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_u8(msg, SSH_AGENT_RSA_RESPONSE)) != 0 || 349d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_put(msg, mdbuf, sizeof(mdbuf))) != 0) 350d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 351bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto send; 352bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 353bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 354d059297112922cabb0c674840589be8db821fd9aAdam Langley failure: 355bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Unknown identity or protocol error. Send failure. */ 356d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) 357d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 358d059297112922cabb0c674840589be8db821fd9aAdam Langley send: 359d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_stringb(e->output, msg)) != 0) 360d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 361d059297112922cabb0c674840589be8db821fd9aAdam Langley sshkey_free(key); 362bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman BN_clear_free(challenge); 363d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_free(msg); 364bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 365d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 366bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 367bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* ssh2 only */ 368bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 369bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_sign_request2(SocketEntry *e) 370bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 371bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *blob, *data, *signature = NULL; 372d059297112922cabb0c674840589be8db821fd9aAdam Langley size_t blen, dlen, slen = 0; 373d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int compat = 0, flags; 374d059297112922cabb0c674840589be8db821fd9aAdam Langley int r, ok = -1; 375d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshbuf *msg; 376d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshkey *key; 377d059297112922cabb0c674840589be8db821fd9aAdam Langley struct identity *id; 378d059297112922cabb0c674840589be8db821fd9aAdam Langley 379d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((msg = sshbuf_new()) == NULL) 380d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: sshbuf_new failed", __func__); 381d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0 || 382d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_string(e->request, &data, &dlen)) != 0 || 383d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_u32(e->request, &flags)) != 0) 384d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 385bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (flags & SSH_AGENT_OLD_SIGNATURE) 386d059297112922cabb0c674840589be8db821fd9aAdam Langley compat = SSH_BUG_SIGBLOB; 387d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshkey_from_blob(blob, blen, &key)) != 0) { 388d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: cannot parse key blob: %s", __func__, ssh_err(ok)); 389d059297112922cabb0c674840589be8db821fd9aAdam Langley goto send; 390bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 391d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((id = lookup_identity(key, 2)) == NULL) { 392d059297112922cabb0c674840589be8db821fd9aAdam Langley verbose("%s: %s key not found", __func__, sshkey_type(key)); 393d059297112922cabb0c674840589be8db821fd9aAdam Langley goto send; 394d059297112922cabb0c674840589be8db821fd9aAdam Langley } 395d059297112922cabb0c674840589be8db821fd9aAdam Langley if (id->confirm && confirm_key(id) != 0) { 396d059297112922cabb0c674840589be8db821fd9aAdam Langley verbose("%s: user refused key", __func__); 397d059297112922cabb0c674840589be8db821fd9aAdam Langley goto send; 398d059297112922cabb0c674840589be8db821fd9aAdam Langley } 399d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshkey_sign(id->key, &signature, &slen, 400d059297112922cabb0c674840589be8db821fd9aAdam Langley data, dlen, compat)) != 0) { 401d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: sshkey_sign: %s", __func__, ssh_err(ok)); 402d059297112922cabb0c674840589be8db821fd9aAdam Langley goto send; 403bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 404d059297112922cabb0c674840589be8db821fd9aAdam Langley /* Success */ 405d059297112922cabb0c674840589be8db821fd9aAdam Langley ok = 0; 406d059297112922cabb0c674840589be8db821fd9aAdam Langley send: 407d059297112922cabb0c674840589be8db821fd9aAdam Langley sshkey_free(key); 408d059297112922cabb0c674840589be8db821fd9aAdam Langley if (ok == 0) { 409d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 || 410d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_put_string(msg, signature, slen)) != 0) 411d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 412d059297112922cabb0c674840589be8db821fd9aAdam Langley } else if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0) 413d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 414d059297112922cabb0c674840589be8db821fd9aAdam Langley 415d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_stringb(e->output, msg)) != 0) 416d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 417d059297112922cabb0c674840589be8db821fd9aAdam Langley 418d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_free(msg); 419d059297112922cabb0c674840589be8db821fd9aAdam Langley free(data); 420d059297112922cabb0c674840589be8db821fd9aAdam Langley free(blob); 421d059297112922cabb0c674840589be8db821fd9aAdam Langley free(signature); 422bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 423bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 424bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* shared */ 425bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 426bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_remove_identity(SocketEntry *e, int version) 427bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 428d059297112922cabb0c674840589be8db821fd9aAdam Langley size_t blen; 429d059297112922cabb0c674840589be8db821fd9aAdam Langley int r, success = 0; 430d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshkey *key = NULL; 431bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_char *blob; 432d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_SSH1 433d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int bits; 434d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* WITH_SSH1 */ 435bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 436bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (version) { 437d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_SSH1 438bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 1: 439d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((key = sshkey_new(KEY_RSA1)) == NULL) { 440d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: sshkey_new failed", __func__); 441d059297112922cabb0c674840589be8db821fd9aAdam Langley return; 442d059297112922cabb0c674840589be8db821fd9aAdam Langley } 443d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_u32(e->request, &bits)) != 0 || 444d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_bignum1(e->request, key->rsa->e)) != 0 || 445d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_bignum1(e->request, key->rsa->n)) != 0) 446d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 447d059297112922cabb0c674840589be8db821fd9aAdam Langley 448d059297112922cabb0c674840589be8db821fd9aAdam Langley if (bits != sshkey_size(key)) 449d059297112922cabb0c674840589be8db821fd9aAdam Langley logit("Warning: identity keysize mismatch: " 450d059297112922cabb0c674840589be8db821fd9aAdam Langley "actual %u, announced %u", 451d059297112922cabb0c674840589be8db821fd9aAdam Langley sshkey_size(key), bits); 452bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 453d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* WITH_SSH1 */ 454bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 2: 455d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_string(e->request, &blob, &blen)) != 0) 456d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 457d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshkey_from_blob(blob, blen, &key)) != 0) 458d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: sshkey_from_blob failed: %s", 459d059297112922cabb0c674840589be8db821fd9aAdam Langley __func__, ssh_err(r)); 460d059297112922cabb0c674840589be8db821fd9aAdam Langley free(blob); 461bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 462bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 463bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (key != NULL) { 464bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Identity *id = lookup_identity(key, version); 465bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (id != NULL) { 466bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 467bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * We have this key. Free the old key. Since we 468bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * don't want to leave empty slots in the middle of 469bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * the array, we actually free the key there and move 470bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * all the entries between the empty slot and the end 471bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * of the array. 472bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 473bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Idtab *tab = idtab_lookup(version); 474bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (tab->nentries < 1) 475bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("process_remove_identity: " 476bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "internal error: tab->nentries %d", 477bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tab->nentries); 478bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_REMOVE(&tab->idlist, id, next); 479bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman free_identity(id); 480bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tab->nentries--; 481bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman success = 1; 482bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 483d059297112922cabb0c674840589be8db821fd9aAdam Langley sshkey_free(key); 484bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 485d059297112922cabb0c674840589be8db821fd9aAdam Langley send_status(e, success); 486bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 487bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 488bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 489bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_remove_all_identities(SocketEntry *e, int version) 490bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 491bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Idtab *tab = idtab_lookup(version); 492bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Identity *id; 493bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 494bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Loop over all identities and clear the keys. */ 495bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (id = TAILQ_FIRST(&tab->idlist); id; 496bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id = TAILQ_FIRST(&tab->idlist)) { 497bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_REMOVE(&tab->idlist, id, next); 498bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman free_identity(id); 499bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 500bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 501bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Mark that there are no identities. */ 502bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tab->nentries = 0; 503bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 504bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Send success. */ 505d059297112922cabb0c674840589be8db821fd9aAdam Langley send_status(e, 1); 506bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 507bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 508bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* removes expired keys and returns number of seconds until the next expiry */ 509d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic time_t 510bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanreaper(void) 511bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 512d059297112922cabb0c674840589be8db821fd9aAdam Langley time_t deadline = 0, now = monotime(); 513bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Identity *id, *nxt; 514bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int version; 515bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Idtab *tab; 516bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 517bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (version = 1; version < 3; version++) { 518bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tab = idtab_lookup(version); 519bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { 520bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman nxt = TAILQ_NEXT(id, next); 521bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (id->death == 0) 522bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 523bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (now >= id->death) { 524bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("expiring key '%s'", id->comment); 525bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_REMOVE(&tab->idlist, id, next); 526bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman free_identity(id); 527bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tab->nentries--; 528bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else 529bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman deadline = (deadline == 0) ? id->death : 530bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman MIN(deadline, id->death); 531bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 532bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 533bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (deadline == 0 || deadline <= now) 534bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return 0; 535bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 536bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (deadline - now); 537bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 538bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 539d059297112922cabb0c674840589be8db821fd9aAdam Langley/* 540d059297112922cabb0c674840589be8db821fd9aAdam Langley * XXX this and the corresponding serialisation function probably belongs 541d059297112922cabb0c674840589be8db821fd9aAdam Langley * in key.c 542d059297112922cabb0c674840589be8db821fd9aAdam Langley */ 543d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_SSH1 544d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int 545d059297112922cabb0c674840589be8db821fd9aAdam Langleyagent_decode_rsa1(struct sshbuf *m, struct sshkey **kp) 546d059297112922cabb0c674840589be8db821fd9aAdam Langley{ 547d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshkey *k = NULL; 548d059297112922cabb0c674840589be8db821fd9aAdam Langley int r = SSH_ERR_INTERNAL_ERROR; 549d059297112922cabb0c674840589be8db821fd9aAdam Langley 550d059297112922cabb0c674840589be8db821fd9aAdam Langley *kp = NULL; 551d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((k = sshkey_new_private(KEY_RSA1)) == NULL) 552d059297112922cabb0c674840589be8db821fd9aAdam Langley return SSH_ERR_ALLOC_FAIL; 553d059297112922cabb0c674840589be8db821fd9aAdam Langley 554d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_u32(m, NULL)) != 0 || /* ignored */ 555d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_bignum1(m, k->rsa->n)) != 0 || 556d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_bignum1(m, k->rsa->e)) != 0 || 557d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_bignum1(m, k->rsa->d)) != 0 || 558d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_bignum1(m, k->rsa->iqmp)) != 0 || 559d059297112922cabb0c674840589be8db821fd9aAdam Langley /* SSH1 and SSL have p and q swapped */ 560d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_bignum1(m, k->rsa->q)) != 0 || /* p */ 561d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_bignum1(m, k->rsa->p)) != 0) /* q */ 562d059297112922cabb0c674840589be8db821fd9aAdam Langley goto out; 563d059297112922cabb0c674840589be8db821fd9aAdam Langley 564d059297112922cabb0c674840589be8db821fd9aAdam Langley /* Generate additional parameters */ 565d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = rsa_generate_additional_parameters(k->rsa)) != 0) 566d059297112922cabb0c674840589be8db821fd9aAdam Langley goto out; 567d059297112922cabb0c674840589be8db821fd9aAdam Langley /* enable blinding */ 568d059297112922cabb0c674840589be8db821fd9aAdam Langley if (RSA_blinding_on(k->rsa, NULL) != 1) { 569d059297112922cabb0c674840589be8db821fd9aAdam Langley r = SSH_ERR_LIBCRYPTO_ERROR; 570d059297112922cabb0c674840589be8db821fd9aAdam Langley goto out; 571d059297112922cabb0c674840589be8db821fd9aAdam Langley } 572d059297112922cabb0c674840589be8db821fd9aAdam Langley 573d059297112922cabb0c674840589be8db821fd9aAdam Langley r = 0; /* success */ 574d059297112922cabb0c674840589be8db821fd9aAdam Langley out: 575d059297112922cabb0c674840589be8db821fd9aAdam Langley if (r == 0) 576d059297112922cabb0c674840589be8db821fd9aAdam Langley *kp = k; 577d059297112922cabb0c674840589be8db821fd9aAdam Langley else 578d059297112922cabb0c674840589be8db821fd9aAdam Langley sshkey_free(k); 579d059297112922cabb0c674840589be8db821fd9aAdam Langley return r; 580d059297112922cabb0c674840589be8db821fd9aAdam Langley} 581d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* WITH_SSH1 */ 582d059297112922cabb0c674840589be8db821fd9aAdam Langley 583bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 584bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_add_identity(SocketEntry *e, int version) 585bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 586bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Idtab *tab = idtab_lookup(version); 587bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Identity *id; 588d059297112922cabb0c674840589be8db821fd9aAdam Langley int success = 0, confirm = 0; 589d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int seconds; 590d059297112922cabb0c674840589be8db821fd9aAdam Langley char *comment = NULL; 591d059297112922cabb0c674840589be8db821fd9aAdam Langley time_t death = 0; 592d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshkey *k = NULL; 593d059297112922cabb0c674840589be8db821fd9aAdam Langley u_char ctype; 594d059297112922cabb0c674840589be8db821fd9aAdam Langley int r = SSH_ERR_INTERNAL_ERROR; 595bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 596bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (version) { 597d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_SSH1 598bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 1: 599d059297112922cabb0c674840589be8db821fd9aAdam Langley r = agent_decode_rsa1(e->request, &k); 600bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 601d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif /* WITH_SSH1 */ 602bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 2: 603d059297112922cabb0c674840589be8db821fd9aAdam Langley r = sshkey_private_deserialize(e->request, &k); 604bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 605bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 606d059297112922cabb0c674840589be8db821fd9aAdam Langley if (r != 0 || k == NULL || 607d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { 608d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: decode private key: %s", __func__, ssh_err(r)); 609d059297112922cabb0c674840589be8db821fd9aAdam Langley goto err; 610bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 611d059297112922cabb0c674840589be8db821fd9aAdam Langley 612d059297112922cabb0c674840589be8db821fd9aAdam Langley while (sshbuf_len(e->request)) { 613d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_u8(e->request, &ctype)) != 0) { 614d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: buffer error: %s", __func__, ssh_err(r)); 615d059297112922cabb0c674840589be8db821fd9aAdam Langley goto err; 616d059297112922cabb0c674840589be8db821fd9aAdam Langley } 617d059297112922cabb0c674840589be8db821fd9aAdam Langley switch (ctype) { 618bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENT_CONSTRAIN_LIFETIME: 619d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) { 620d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: bad lifetime constraint: %s", 621d059297112922cabb0c674840589be8db821fd9aAdam Langley __func__, ssh_err(r)); 622d059297112922cabb0c674840589be8db821fd9aAdam Langley goto err; 623d059297112922cabb0c674840589be8db821fd9aAdam Langley } 624d059297112922cabb0c674840589be8db821fd9aAdam Langley death = monotime() + seconds; 625bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 626bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENT_CONSTRAIN_CONFIRM: 627bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman confirm = 1; 628bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 629bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 630d059297112922cabb0c674840589be8db821fd9aAdam Langley error("%s: Unknown constraint %d", __func__, ctype); 631d059297112922cabb0c674840589be8db821fd9aAdam Langley err: 632d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_reset(e->request); 633d059297112922cabb0c674840589be8db821fd9aAdam Langley free(comment); 634d059297112922cabb0c674840589be8db821fd9aAdam Langley sshkey_free(k); 635bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto send; 636bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 637bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 638d059297112922cabb0c674840589be8db821fd9aAdam Langley 639bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman success = 1; 640bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (lifetime && !death) 641d059297112922cabb0c674840589be8db821fd9aAdam Langley death = monotime() + lifetime; 642bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((id = lookup_identity(k, version)) == NULL) { 643bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id = xcalloc(1, sizeof(Identity)); 644bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id->key = k; 645bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_INSERT_TAIL(&tab->idlist, id, next); 646bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Increment the number of identities. */ 647bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tab->nentries++; 648bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 649d059297112922cabb0c674840589be8db821fd9aAdam Langley sshkey_free(k); 650d059297112922cabb0c674840589be8db821fd9aAdam Langley free(id->comment); 651bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 652bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id->comment = comment; 653bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id->death = death; 654bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id->confirm = confirm; 655bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansend: 656d059297112922cabb0c674840589be8db821fd9aAdam Langley send_status(e, success); 657bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 658bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 659bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* XXX todo: encrypt sensitive data with passphrase */ 660bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 661bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_lock_agent(SocketEntry *e, int lock) 662bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 663d059297112922cabb0c674840589be8db821fd9aAdam Langley int r, success = 0; 664bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *passwd; 665bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 666d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_cstring(e->request, &passwd, NULL)) != 0) 667d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 668bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (locked && !lock && strcmp(passwd, lock_passwd) == 0) { 669bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman locked = 0; 670d059297112922cabb0c674840589be8db821fd9aAdam Langley explicit_bzero(lock_passwd, strlen(lock_passwd)); 671d059297112922cabb0c674840589be8db821fd9aAdam Langley free(lock_passwd); 672bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman lock_passwd = NULL; 673bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman success = 1; 674bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (!locked && lock) { 675bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman locked = 1; 676bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman lock_passwd = xstrdup(passwd); 677bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman success = 1; 678bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 679d059297112922cabb0c674840589be8db821fd9aAdam Langley explicit_bzero(passwd, strlen(passwd)); 680d059297112922cabb0c674840589be8db821fd9aAdam Langley free(passwd); 681d059297112922cabb0c674840589be8db821fd9aAdam Langley send_status(e, success); 682bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 683bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 684bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 685bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanno_identities(SocketEntry *e, u_int type) 686bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 687d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshbuf *msg; 688d059297112922cabb0c674840589be8db821fd9aAdam Langley int r; 689bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 690d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((msg = sshbuf_new()) == NULL) 691d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: sshbuf_new failed", __func__); 692d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put_u8(msg, 693bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ? 694d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH_AGENT_RSA_IDENTITIES_ANSWER : 695d059297112922cabb0c674840589be8db821fd9aAdam Langley SSH2_AGENT_IDENTITIES_ANSWER)) != 0 || 696d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_put_u32(msg, 0)) != 0 || 697d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_put_stringb(e->output, msg)) != 0) 698d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 699d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_free(msg); 700bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 701bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 702bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef ENABLE_PKCS11 703bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 704bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_add_smartcard_key(SocketEntry *e) 705bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 706bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *provider = NULL, *pin; 707d059297112922cabb0c674840589be8db821fd9aAdam Langley int r, i, version, count = 0, success = 0, confirm = 0; 708d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int seconds; 709d059297112922cabb0c674840589be8db821fd9aAdam Langley time_t death = 0; 710d059297112922cabb0c674840589be8db821fd9aAdam Langley u_char type; 711d059297112922cabb0c674840589be8db821fd9aAdam Langley struct sshkey **keys = NULL, *k; 712bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Identity *id; 713bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Idtab *tab; 714bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 715d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || 716d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) 717d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 718bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 719d059297112922cabb0c674840589be8db821fd9aAdam Langley while (sshbuf_len(e->request)) { 720d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_u8(e->request, &type)) != 0) 721d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 722d059297112922cabb0c674840589be8db821fd9aAdam Langley switch (type) { 723bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENT_CONSTRAIN_LIFETIME: 724d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_u32(e->request, &seconds)) != 0) 725d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", 726d059297112922cabb0c674840589be8db821fd9aAdam Langley __func__, ssh_err(r)); 727d059297112922cabb0c674840589be8db821fd9aAdam Langley death = monotime() + seconds; 728bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 729bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENT_CONSTRAIN_CONFIRM: 730bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman confirm = 1; 731bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 732bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 733bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("process_add_smartcard_key: " 734bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "Unknown constraint type %d", type); 735bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto send; 736bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 737bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 738bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (lifetime && !death) 739d059297112922cabb0c674840589be8db821fd9aAdam Langley death = monotime() + lifetime; 740bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 741bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman count = pkcs11_add_provider(provider, pin, &keys); 742bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < count; i++) { 743bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman k = keys[i]; 744bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman version = k->type == KEY_RSA1 ? 1 : 2; 745bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tab = idtab_lookup(version); 746bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (lookup_identity(k, version) == NULL) { 747bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id = xcalloc(1, sizeof(Identity)); 748bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id->key = k; 749bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id->provider = xstrdup(provider); 750bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id->comment = xstrdup(provider); /* XXX */ 751bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id->death = death; 752bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman id->confirm = confirm; 753bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_INSERT_TAIL(&tab->idlist, id, next); 754bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tab->nentries++; 755bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman success = 1; 756bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 757d059297112922cabb0c674840589be8db821fd9aAdam Langley sshkey_free(k); 758bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 759bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman keys[i] = NULL; 760bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 761bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmansend: 762d059297112922cabb0c674840589be8db821fd9aAdam Langley free(pin); 763d059297112922cabb0c674840589be8db821fd9aAdam Langley free(provider); 764d059297112922cabb0c674840589be8db821fd9aAdam Langley free(keys); 765d059297112922cabb0c674840589be8db821fd9aAdam Langley send_status(e, success); 766bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 767bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 768bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 769bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_remove_smartcard_key(SocketEntry *e) 770bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 771bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *provider = NULL, *pin = NULL; 772d059297112922cabb0c674840589be8db821fd9aAdam Langley int r, version, success = 0; 773bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Identity *id, *nxt; 774bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman Idtab *tab; 775bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 776d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_cstring(e->request, &provider, NULL)) != 0 || 777d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_cstring(e->request, &pin, NULL)) != 0) 778d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 779d059297112922cabb0c674840589be8db821fd9aAdam Langley free(pin); 780bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 781bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (version = 1; version < 3; version++) { 782bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tab = idtab_lookup(version); 783bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { 784bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman nxt = TAILQ_NEXT(id, next); 785d059297112922cabb0c674840589be8db821fd9aAdam Langley /* Skip file--based keys */ 786d059297112922cabb0c674840589be8db821fd9aAdam Langley if (id->provider == NULL) 787d059297112922cabb0c674840589be8db821fd9aAdam Langley continue; 788bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (!strcmp(provider, id->provider)) { 789bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman TAILQ_REMOVE(&tab->idlist, id, next); 790bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman free_identity(id); 791bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tab->nentries--; 792bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 793bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 794bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 795bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pkcs11_del_provider(provider) == 0) 796bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman success = 1; 797bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman else 798bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("process_remove_smartcard_key:" 799bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman " pkcs11_del_provider failed"); 800d059297112922cabb0c674840589be8db821fd9aAdam Langley free(provider); 801d059297112922cabb0c674840589be8db821fd9aAdam Langley send_status(e, success); 802bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 803bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* ENABLE_PKCS11 */ 804bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 805bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* dispatch incoming messages */ 806bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 807bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 808bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprocess_message(SocketEntry *e) 809bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 810d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int msg_len; 811d059297112922cabb0c674840589be8db821fd9aAdam Langley u_char type; 812d059297112922cabb0c674840589be8db821fd9aAdam Langley const u_char *cp; 813d059297112922cabb0c674840589be8db821fd9aAdam Langley int r; 814bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 815d059297112922cabb0c674840589be8db821fd9aAdam Langley if (sshbuf_len(e->input) < 5) 816bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; /* Incomplete message. */ 817d059297112922cabb0c674840589be8db821fd9aAdam Langley cp = sshbuf_ptr(e->input); 818d059297112922cabb0c674840589be8db821fd9aAdam Langley msg_len = PEEK_U32(cp); 819bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (msg_len > 256 * 1024) { 820bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close_socket(e); 821bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 822bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 823d059297112922cabb0c674840589be8db821fd9aAdam Langley if (sshbuf_len(e->input) < msg_len + 4) 824bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 825bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 826bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* move the current input to e->request */ 827d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_reset(e->request); 828d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_get_stringb(e->input, e->request)) != 0 || 829d059297112922cabb0c674840589be8db821fd9aAdam Langley (r = sshbuf_get_u8(e->request, &type)) != 0) 830d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", __func__, ssh_err(r)); 831bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 832bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* check wheter agent is locked */ 833bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (locked && type != SSH_AGENTC_UNLOCK) { 834d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_reset(e->request); 835bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (type) { 836bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_REQUEST_RSA_IDENTITIES: 837bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH2_AGENTC_REQUEST_IDENTITIES: 838bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* send empty lists */ 839bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman no_identities(e, type); 840bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 841bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 842bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* send a fail message for all other request types */ 843d059297112922cabb0c674840589be8db821fd9aAdam Langley send_status(e, 0); 844bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 845bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 846bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 847bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 848bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("type %d", type); 849bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (type) { 850bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_LOCK: 851bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_UNLOCK: 852bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_lock_agent(e, type == SSH_AGENTC_LOCK); 853bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 854d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_SSH1 855bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* ssh1 */ 856bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_RSA_CHALLENGE: 857bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_authentication_challenge1(e); 858bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 859bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_REQUEST_RSA_IDENTITIES: 860bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_request_identities(e, 1); 861bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 862bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_ADD_RSA_IDENTITY: 863bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED: 864bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_add_identity(e, 1); 865bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 866bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_REMOVE_RSA_IDENTITY: 867bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_remove_identity(e, 1); 868bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 869d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 870bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: 871d059297112922cabb0c674840589be8db821fd9aAdam Langley process_remove_all_identities(e, 1); /* safe for !WITH_SSH1 */ 872bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 873bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* ssh2 */ 874bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH2_AGENTC_SIGN_REQUEST: 875bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_sign_request2(e); 876bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 877bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH2_AGENTC_REQUEST_IDENTITIES: 878bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_request_identities(e, 2); 879bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 880bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH2_AGENTC_ADD_IDENTITY: 881bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH2_AGENTC_ADD_ID_CONSTRAINED: 882bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_add_identity(e, 2); 883bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 884bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH2_AGENTC_REMOVE_IDENTITY: 885bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_remove_identity(e, 2); 886bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 887bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: 888bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_remove_all_identities(e, 2); 889bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 890bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef ENABLE_PKCS11 891bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_ADD_SMARTCARD_KEY: 892bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED: 893bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_add_smartcard_key(e); 894bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 895bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case SSH_AGENTC_REMOVE_SMARTCARD_KEY: 896bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_remove_smartcard_key(e); 897bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 898bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* ENABLE_PKCS11 */ 899bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 900bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Unknown message. Respond with failure. */ 901bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("Unknown message %d", type); 902d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_reset(e->request); 903d059297112922cabb0c674840589be8db821fd9aAdam Langley send_status(e, 0); 904bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 905bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 906bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 907bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 908bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 909bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmannew_socket(sock_type type, int fd) 910bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 911bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int i, old_alloc, new_alloc; 912bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 913bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman set_nonblock(fd); 914bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 915bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fd > max_fd) 916bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman max_fd = fd; 917bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 918bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < sockets_alloc; i++) 919bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (sockets[i].type == AUTH_UNUSED) { 920bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sockets[i].fd = fd; 921d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((sockets[i].input = sshbuf_new()) == NULL) 922d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: sshbuf_new failed", __func__); 923d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((sockets[i].output = sshbuf_new()) == NULL) 924d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: sshbuf_new failed", __func__); 925d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((sockets[i].request = sshbuf_new()) == NULL) 926d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: sshbuf_new failed", __func__); 927bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sockets[i].type = type; 928bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return; 929bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 930bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman old_alloc = sockets_alloc; 931bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman new_alloc = sockets_alloc + 10; 932bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sockets = xrealloc(sockets, new_alloc, sizeof(sockets[0])); 933bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = old_alloc; i < new_alloc; i++) 934bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sockets[i].type = AUTH_UNUSED; 935bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sockets_alloc = new_alloc; 936bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sockets[old_alloc].fd = fd; 937d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((sockets[old_alloc].input = sshbuf_new()) == NULL) 938d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: sshbuf_new failed", __func__); 939d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((sockets[old_alloc].output = sshbuf_new()) == NULL) 940d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: sshbuf_new failed", __func__); 941d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((sockets[old_alloc].request = sshbuf_new()) == NULL) 942d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: sshbuf_new failed", __func__); 943bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sockets[old_alloc].type = type; 944bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 945bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 946bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic int 947bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanprepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, 948bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct timeval **tvpp) 949bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 950d059297112922cabb0c674840589be8db821fd9aAdam Langley u_int i, sz; 951bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int n = 0; 952bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman static struct timeval tv; 953d059297112922cabb0c674840589be8db821fd9aAdam Langley time_t deadline; 954bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 955bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < sockets_alloc; i++) { 956bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (sockets[i].type) { 957bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case AUTH_SOCKET: 958bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case AUTH_CONNECTION: 959bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman n = MAX(n, sockets[i].fd); 960bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 961bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case AUTH_UNUSED: 962bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 963bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 964bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("Unknown socket type %d", sockets[i].type); 965bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 966bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 967bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 968bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 969bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sz = howmany(n+1, NFDBITS) * sizeof(fd_mask); 970bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (*fdrp == NULL || sz > *nallocp) { 971d059297112922cabb0c674840589be8db821fd9aAdam Langley free(*fdrp); 972d059297112922cabb0c674840589be8db821fd9aAdam Langley free(*fdwp); 973bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *fdrp = xmalloc(sz); 974bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *fdwp = xmalloc(sz); 975bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *nallocp = sz; 976bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 977bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (n < *fdl) 978bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman debug("XXX shrink: %d < %d", n, *fdl); 979bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *fdl = n; 980bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(*fdrp, 0, sz); 981bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman memset(*fdwp, 0, sz); 982bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 983bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0; i < sockets_alloc; i++) { 984bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (sockets[i].type) { 985bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case AUTH_SOCKET: 986bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case AUTH_CONNECTION: 987bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman FD_SET(sockets[i].fd, *fdrp); 988d059297112922cabb0c674840589be8db821fd9aAdam Langley if (sshbuf_len(sockets[i].output) > 0) 989bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman FD_SET(sockets[i].fd, *fdwp); 990bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 991bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 992bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 993bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 994bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 995bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman deadline = reaper(); 996bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (parent_alive_interval != 0) 997bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman deadline = (deadline == 0) ? parent_alive_interval : 998bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman MIN(deadline, parent_alive_interval); 999bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (deadline == 0) { 1000bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *tvpp = NULL; 1001bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 1002bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tv.tv_sec = deadline; 1003bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman tv.tv_usec = 0; 1004bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *tvpp = &tv; 1005bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1006bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman return (1); 1007bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1008bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1009bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 1010bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanafter_select(fd_set *readset, fd_set *writeset) 1011bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1012bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct sockaddr_un sunaddr; 1013bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman socklen_t slen; 1014bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char buf[1024]; 1015d059297112922cabb0c674840589be8db821fd9aAdam Langley int len, sock, r; 1016bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int i, orig_alloc; 1017bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman uid_t euid; 1018bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman gid_t egid; 1019bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1020bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman for (i = 0, orig_alloc = sockets_alloc; i < orig_alloc; i++) 1021bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (sockets[i].type) { 1022bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case AUTH_UNUSED: 1023bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1024bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case AUTH_SOCKET: 1025bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (FD_ISSET(sockets[i].fd, readset)) { 1026bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman slen = sizeof(sunaddr); 1027bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sock = accept(sockets[i].fd, 1028bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (struct sockaddr *)&sunaddr, &slen); 1029bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (sock < 0) { 1030bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("accept from AUTH_SOCKET: %s", 1031bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strerror(errno)); 1032bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1033bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1034bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (getpeereid(sock, &euid, &egid) < 0) { 1035bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("getpeereid %d failed: %s", 1036bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sock, strerror(errno)); 1037bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(sock); 1038bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1039bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1040bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((euid != 0) && (getuid() != euid)) { 1041bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("uid mismatch: " 1042bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "peer euid %u != uid %u", 1043bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (u_int) euid, (u_int) getuid()); 1044bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(sock); 1045bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1046bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1047bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman new_socket(AUTH_CONNECTION, sock); 1048bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1049bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1050bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case AUTH_CONNECTION: 1051d059297112922cabb0c674840589be8db821fd9aAdam Langley if (sshbuf_len(sockets[i].output) > 0 && 1052bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman FD_ISSET(sockets[i].fd, writeset)) { 1053bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman len = write(sockets[i].fd, 1054d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_ptr(sockets[i].output), 1055d059297112922cabb0c674840589be8db821fd9aAdam Langley sshbuf_len(sockets[i].output)); 1056bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (len == -1 && (errno == EAGAIN || 1057bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno == EWOULDBLOCK || 1058bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno == EINTR)) 1059bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 1060bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (len <= 0) { 1061bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close_socket(&sockets[i]); 1062bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1063bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1064d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_consume(sockets[i].output, 1065d059297112922cabb0c674840589be8db821fd9aAdam Langley len)) != 0) 1066d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", 1067d059297112922cabb0c674840589be8db821fd9aAdam Langley __func__, ssh_err(r)); 1068bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1069bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (FD_ISSET(sockets[i].fd, readset)) { 1070bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman len = read(sockets[i].fd, buf, sizeof(buf)); 1071bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (len == -1 && (errno == EAGAIN || 1072bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno == EWOULDBLOCK || 1073bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman errno == EINTR)) 1074bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 1075bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (len <= 0) { 1076bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close_socket(&sockets[i]); 1077bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1078bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1079d059297112922cabb0c674840589be8db821fd9aAdam Langley if ((r = sshbuf_put(sockets[i].input, 1080d059297112922cabb0c674840589be8db821fd9aAdam Langley buf, len)) != 0) 1081d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("%s: buffer error: %s", 1082d059297112922cabb0c674840589be8db821fd9aAdam Langley __func__, ssh_err(r)); 1083d059297112922cabb0c674840589be8db821fd9aAdam Langley explicit_bzero(buf, sizeof(buf)); 1084bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman process_message(&sockets[i]); 1085bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1086bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1087bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 1088bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("Unknown type %d", sockets[i].type); 1089bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1090bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1091bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1092bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 1093bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancleanup_socket(void) 1094bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1095d059297112922cabb0c674840589be8db821fd9aAdam Langley if (cleanup_pid != 0 && getpid() != cleanup_pid) 1096d059297112922cabb0c674840589be8db821fd9aAdam Langley return; 1097d059297112922cabb0c674840589be8db821fd9aAdam Langley debug("%s: cleanup", __func__); 1098bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (socket_name[0]) 1099bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman unlink(socket_name); 1100bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (socket_dir[0]) 1101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman rmdir(socket_dir); 1102bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1103bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1104bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanvoid 1105bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancleanup_exit(int i) 1106bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1107bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_socket(); 1108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman _exit(i); 1109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1110bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1111bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*ARGSUSED*/ 1112bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 1113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancleanup_handler(int sig) 1114bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_socket(); 1116bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef ENABLE_PKCS11 1117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pkcs11_terminate(); 1118bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 1119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman _exit(2); 1120bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1121bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 1123bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmancheck_parent_exists(void) 1124bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 1126bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * If our parent has exited then getppid() will return (pid_t)1, 1127bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * so testing for that should be safe. 1128bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 1129bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (parent_pid != -1 && getppid() != parent_pid) { 1130bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* printf("Parent has died - Authentication agent exiting.\n"); */ 1131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_socket(); 1132bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman _exit(2); 1133bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1134bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1135bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanstatic void 1137bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanusage(void) 1138bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1139d059297112922cabb0c674840589be8db821fd9aAdam Langley fprintf(stderr, 1140d059297112922cabb0c674840589be8db821fd9aAdam Langley "usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-E fingerprint_hash]\n" 1141d059297112922cabb0c674840589be8db821fd9aAdam Langley " [-t life] [command [arg ...]]\n" 1142d059297112922cabb0c674840589be8db821fd9aAdam Langley " ssh-agent [-c | -s] -k\n"); 1143bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1144bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1145bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1146bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanint 1147bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanmain(int ac, char **av) 1148bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{ 1149bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0; 1150bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman int sock, fd, ch, result, saved_errno; 1151bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman u_int nalloc; 1152bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char *shell, *format, *pidstr, *agentsocket = NULL; 1153bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fd_set *readsetp = NULL, *writesetp = NULL; 1154bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_SETRLIMIT 1155bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct rlimit rlim; 1156bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 1157bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman extern int optind; 1158bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman extern char *optarg; 1159bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pid_t pid; 1160bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman char pidstrbuf[1 + 3 * sizeof pid]; 1161bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman struct timeval *tvp = NULL; 1162bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman size_t len; 1163d059297112922cabb0c674840589be8db821fd9aAdam Langley mode_t prev_mask; 1164bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1165bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 1166bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman sanitise_stdfd(); 1167bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1168bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* drop */ 1169bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman setegid(getgid()); 1170bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman setgid(getgid()); 1171bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1172bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) 1173bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Disable ptrace on Linux without sgid bit */ 1174bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman prctl(PR_SET_DUMPABLE, 0); 1175bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 1176bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1177d059297112922cabb0c674840589be8db821fd9aAdam Langley#ifdef WITH_OPENSSL 1178bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman OpenSSL_add_all_algorithms(); 1179d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif 1180bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1181bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman __progname = ssh_get_progname(av[0]); 1182bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman seed_rng(); 1183bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1184d059297112922cabb0c674840589be8db821fd9aAdam Langley while ((ch = getopt(ac, av, "cdksE:a:t:")) != -1) { 1185bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman switch (ch) { 1186d059297112922cabb0c674840589be8db821fd9aAdam Langley case 'E': 1187d059297112922cabb0c674840589be8db821fd9aAdam Langley fingerprint_hash = ssh_digest_alg_by_name(optarg); 1188d059297112922cabb0c674840589be8db821fd9aAdam Langley if (fingerprint_hash == -1) 1189d059297112922cabb0c674840589be8db821fd9aAdam Langley fatal("Invalid hash algorithm \"%s\"", optarg); 1190d059297112922cabb0c674840589be8db821fd9aAdam Langley break; 1191bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'c': 1192bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (s_flag) 1193bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman usage(); 1194bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman c_flag++; 1195bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1196bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'k': 1197bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman k_flag++; 1198bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1199bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 's': 1200bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (c_flag) 1201bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman usage(); 1202bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman s_flag++; 1203bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1204bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'd': 1205bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (d_flag) 1206bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman usage(); 1207bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman d_flag++; 1208bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1209bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 'a': 1210bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman agentsocket = optarg; 1211bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1212bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman case 't': 1213bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((lifetime = convtime(optarg)) == -1) { 1214bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, "Invalid lifetime\n"); 1215bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman usage(); 1216bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1217bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman break; 1218bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman default: 1219bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman usage(); 1220bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1221bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1222bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman ac -= optind; 1223bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman av += optind; 1224bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1225bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ac > 0 && (c_flag || k_flag || s_flag || d_flag)) 1226bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman usage(); 1227bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1228bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ac == 0 && !c_flag && !s_flag) { 1229bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman shell = getenv("SHELL"); 1230bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (shell != NULL && (len = strlen(shell)) > 2 && 1231bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strncmp(shell + len - 3, "csh", 3) == 0) 1232bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman c_flag = 1; 1233bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1234bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (k_flag) { 1235bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman const char *errstr = NULL; 1236bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1237bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pidstr = getenv(SSH_AGENTPID_ENV_NAME); 1238bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pidstr == NULL) { 1239bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, "%s not set, cannot kill agent\n", 1240bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SSH_AGENTPID_ENV_NAME); 1241bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1242bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1243bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr); 1244bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (errstr) { 1245bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fprintf(stderr, 1246bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman "%s=\"%s\", which is not a good PID: %s\n", 1247bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SSH_AGENTPID_ENV_NAME, pidstr, errstr); 1248bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1249bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1250bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (kill(pid, SIGTERM) == -1) { 1251bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman perror("kill"); 1252bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1253bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1254bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman format = c_flag ? "unsetenv %s;\n" : "unset %s;\n"; 1255bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman printf(format, SSH_AUTHSOCKET_ENV_NAME); 1256bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman printf(format, SSH_AGENTPID_ENV_NAME); 1257bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman printf("echo Agent pid %ld killed;\n", (long)pid); 1258bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(0); 1259bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1260bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman parent_pid = getpid(); 1261bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1262bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (agentsocket == NULL) { 1263bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Create private directory for agent socket */ 1264bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman mktemp_proto(socket_dir, sizeof(socket_dir)); 1265bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (mkdtemp(socket_dir) == NULL) { 1266bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman perror("mkdtemp: private socket dir"); 1267bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1268bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1269bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir, 1270bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (long)parent_pid); 1271bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else { 1272bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* Try to use specified agent socket */ 1273bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman socket_dir[0] = '\0'; 1274bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman strlcpy(socket_name, agentsocket, sizeof socket_name); 1275bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1276bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1277bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 1278bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Create socket early so it will exist before command gets run from 1279bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * the parent. 1280bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 1281bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman prev_mask = umask(0177); 1282d059297112922cabb0c674840589be8db821fd9aAdam Langley sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0); 1283d059297112922cabb0c674840589be8db821fd9aAdam Langley if (sock < 0) { 1284d059297112922cabb0c674840589be8db821fd9aAdam Langley /* XXX - unix_listener() calls error() not perror() */ 1285bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *socket_name = '\0'; /* Don't unlink any existing file */ 1286bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_exit(1); 1287bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1288bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman umask(prev_mask); 1289bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1290bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* 1291bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * Fork, and have the parent execute the command, if any, or present 1292bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman * the socket data. The child continues as the authentication agent. 1293bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */ 1294bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (d_flag) { 1295bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1); 1296bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; 1297bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, 1298bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SSH_AUTHSOCKET_ENV_NAME); 1299bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman printf("echo Agent pid %ld;\n", (long)parent_pid); 1300bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman goto skip; 1301bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1302bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pid = fork(); 1303bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pid == -1) { 1304bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman perror("fork"); 1305bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_exit(1); 1306bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1307bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (pid != 0) { /* Parent - execute the given command. */ 1308bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(sock); 1309bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid); 1310bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ac == 0) { 1311bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; 1312bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, 1313bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SSH_AUTHSOCKET_ENV_NAME); 1314bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, 1315bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman SSH_AGENTPID_ENV_NAME); 1316bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman printf("echo Agent pid %ld;\n", (long)pid); 1317bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(0); 1318bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1319bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 || 1320bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) { 1321bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman perror("setenv"); 1322bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1323bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1324bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman execvp(av[0], av); 1325bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman perror(av[0]); 1326bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman exit(1); 1327bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1328bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* child */ 1329bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); 1330bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1331bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (setsid() == -1) { 1332bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("setsid: %s", strerror(errno)); 1333bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_exit(1); 1334bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1335bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1336bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)chdir("/"); 1337bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { 1338bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* XXX might close listen socket */ 1339bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)dup2(fd, STDIN_FILENO); 1340bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)dup2(fd, STDOUT_FILENO); 1341bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void)dup2(fd, STDERR_FILENO); 1342bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (fd > 2) 1343bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman close(fd); 1344bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1345bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1346bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef HAVE_SETRLIMIT 1347bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* deny core dumps, since memory contains unencrypted private keys */ 1348bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman rlim.rlim_cur = rlim.rlim_max = 0; 1349bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (setrlimit(RLIMIT_CORE, &rlim) < 0) { 1350bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman error("setrlimit RLIMIT_CORE: %s", strerror(errno)); 1351bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman cleanup_exit(1); 1352bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1353bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 1354bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1355bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanskip: 1356bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1357d059297112922cabb0c674840589be8db821fd9aAdam Langley cleanup_pid = getpid(); 1358d059297112922cabb0c674840589be8db821fd9aAdam Langley 1359bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#ifdef ENABLE_PKCS11 1360bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman pkcs11_init(0); 1361bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif 1362bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman new_socket(AUTH_SOCKET, sock); 1363bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (ac > 0) 1364bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman parent_alive_interval = 10; 1365bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman idtab_init(); 1366bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGPIPE, SIG_IGN); 1367d059297112922cabb0c674840589be8db821fd9aAdam Langley signal(SIGINT, d_flag ? cleanup_handler : SIG_IGN); 1368bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGHUP, cleanup_handler); 1369bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman signal(SIGTERM, cleanup_handler); 1370bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman nalloc = 0; 1371bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman 1372bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman while (1) { 1373bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp); 1374bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman result = select(max_fd + 1, readsetp, writesetp, NULL, tvp); 1375bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman saved_errno = errno; 1376bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (parent_alive_interval != 0) 1377bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman check_parent_exists(); 1378bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman (void) reaper(); /* remove expired keys */ 1379bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (result < 0) { 1380bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman if (saved_errno == EINTR) 1381bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman continue; 1382bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman fatal("select: %s", strerror(saved_errno)); 1383bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } else if (result > 0) 1384bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman after_select(readsetp, writesetp); 1385bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman } 1386bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman /* NOTREACHED */ 1387bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman} 1388