1 /*
   2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 /*
   7  * Author: Tatu Ylonen <ylo@cs.hut.fi>
   8  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
   9  *                    All rights reserved
  10  * The authentication agent program.
  11  *
  12  * As far as I am concerned, the code I have written for this software
  13  * can be used freely for any purpose.  Any derived versions of this
  14  * software must be clearly marked as such, and if the derived work is
  15  * incompatible with the protocol description in the RFC file, it must be
  16  * called by a name other than "ssh" or "Secure Shell".
  17  *
  18  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
  19  *
  20  * Redistribution and use in source and binary forms, with or without
  21  * modification, are permitted provided that the following conditions
  22  * are met:
  23  * 1. Redistributions of source code must retain the above copyright
  24  *    notice, this list of conditions and the following disclaimer.
  25  * 2. Redistributions in binary form must reproduce the above copyright
  26  *    notice, this list of conditions and the following disclaimer in the
  27  *    documentation and/or other materials provided with the distribution.
  28  *
  29  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  30  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  31  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  32  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  33  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  34  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  38  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  39  */
  40 
  41 #include "includes.h"
  42 #include "sys-queue.h"
  43 RCSID("$OpenBSD: ssh-agent.c,v 1.159 2008/06/28 14:05:15 djm Exp $");
  44 
  45 #ifdef HAVE_SOLARIS_PRIVILEGE
  46 #include <priv.h>
  47 #endif /* HAVE_SOLARIS_PRIVILEGE */
  48 
  49 #include <openssl/evp.h>
  50 #include <openssl/md5.h>
  51 
  52 #include "ssh.h"
  53 #include "rsa.h"
  54 #include "buffer.h"
  55 #include "bufaux.h"
  56 #include "xmalloc.h"
  57 #include "key.h"
  58 #include "authfd.h"
  59 #include "compat.h"
  60 #include "log.h"
  61 #include "readpass.h"
  62 #include "misc.h"
  63 
  64 typedef enum {
  65         AUTH_UNUSED,
  66         AUTH_SOCKET,
  67         AUTH_CONNECTION
  68 } sock_type;
  69 
  70 typedef struct {
  71         int fd;
  72         sock_type type;
  73         Buffer input;
  74         Buffer output;
  75         Buffer request;
  76 } SocketEntry;
  77 
  78 u_int sockets_alloc = 0;
  79 SocketEntry *sockets = NULL;
  80 
  81 typedef struct identity {
  82         TAILQ_ENTRY(identity) next;
  83         Key *key;
  84         char *comment;
  85         u_int death;
  86         u_int confirm;
  87 } Identity;
  88 
  89 typedef struct {
  90         int nentries;
  91         TAILQ_HEAD(idqueue, identity) idlist;
  92 } Idtab;
  93 
  94 /* private key table, one per protocol version */
  95 Idtab idtable[3];
  96 
  97 int max_fd = 0;
  98 
  99 /* pid of shell == parent of agent */
 100 pid_t parent_pid = -1;
 101 u_int parent_alive_interval = 0;
 102 
 103 /* pathname and directory for AUTH_SOCKET */
 104 char socket_name[MAXPATHLEN];
 105 char socket_dir[MAXPATHLEN];
 106 
 107 /* locking */
 108 int locked = 0;
 109 char *lock_passwd = NULL;
 110 
 111 #ifdef HAVE___PROGNAME
 112 extern char *__progname;
 113 #else
 114 char *__progname;
 115 #endif
 116 
 117 /* Default lifetime (0 == forever) */
 118 static int lifetime = 0;
 119 
 120 static void
 121 close_socket(SocketEntry *e)
 122 {
 123         close(e->fd);
 124         e->fd = -1;
 125         e->type = AUTH_UNUSED;
 126         buffer_free(&e->input);
 127         buffer_free(&e->output);
 128         buffer_free(&e->request);
 129 }
 130 
 131 static void
 132 idtab_init(void)
 133 {
 134         int i;
 135 
 136         for (i = 0; i <=2; i++) {
 137                 TAILQ_INIT(&idtable[i].idlist);
 138                 idtable[i].nentries = 0;
 139         }
 140 }
 141 
 142 /* return private key table for requested protocol version */
 143 static Idtab *
 144 idtab_lookup(int version)
 145 {
 146         if (version < 1 || version > 2)
 147                 fatal("internal error, bad protocol version %d", version);
 148         return &idtable[version];
 149 }
 150 
 151 static void
 152 free_identity(Identity *id)
 153 {
 154         key_free(id->key);
 155         xfree(id->comment);
 156         xfree(id);
 157 }
 158 
 159 /* return matching private key for given public key */
 160 static Identity *
 161 lookup_identity(Key *key, int version)
 162 {
 163         Identity *id;
 164 
 165         Idtab *tab = idtab_lookup(version);
 166         TAILQ_FOREACH(id, &tab->idlist, next) {
 167                 if (key_equal(key, id->key))
 168                         return (id);
 169         }
 170         return (NULL);
 171 }
 172 
 173 /* Check confirmation of keysign request */
 174 static int
 175 confirm_key(Identity *id)
 176 {
 177         char *p;
 178         int ret = -1;
 179 
 180         p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX);
 181         if (ask_permission(
 182             gettext("Allow use of key %s?\nKey fingerprint %s."),
 183             id->comment, p))
 184                 ret = 0;
 185         xfree(p);
 186 
 187         return (ret);
 188 }
 189 
 190 /* send list of supported public keys to 'client' */
 191 static void
 192 process_request_identities(SocketEntry *e, int version)
 193 {
 194         Idtab *tab = idtab_lookup(version);
 195         Identity *id;
 196         Buffer msg;
 197 
 198         buffer_init(&msg);
 199         buffer_put_char(&msg, (version == 1) ?
 200             SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
 201         buffer_put_int(&msg, tab->nentries);
 202         TAILQ_FOREACH(id, &tab->idlist, next) {
 203                 if (id->key->type == KEY_RSA1) {
 204                         buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
 205                         buffer_put_bignum(&msg, id->key->rsa->e);
 206                         buffer_put_bignum(&msg, id->key->rsa->n);
 207                 } else {
 208                         u_char *blob;
 209                         u_int blen;
 210                         key_to_blob(id->key, &blob, &blen);
 211                         buffer_put_string(&msg, blob, blen);
 212                         xfree(blob);
 213                 }
 214                 buffer_put_cstring(&msg, id->comment);
 215         }
 216         buffer_put_int(&e->output, buffer_len(&msg));
 217         buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
 218         buffer_free(&msg);
 219 }
 220 
 221 /* ssh1 only */
 222 static void
 223 process_authentication_challenge1(SocketEntry *e)
 224 {
 225         u_char buf[32], mdbuf[16], session_id[16];
 226         u_int response_type;
 227         BIGNUM *challenge;
 228         Identity *id;
 229         int i, len;
 230         Buffer msg;
 231         MD5_CTX md;
 232         Key *key;
 233 
 234         buffer_init(&msg);
 235         key = key_new(KEY_RSA1);
 236         if ((challenge = BN_new()) == NULL)
 237                 fatal("process_authentication_challenge1: BN_new failed");
 238 
 239         (void) buffer_get_int(&e->request);                      /* ignored */
 240         buffer_get_bignum(&e->request, key->rsa->e);
 241         buffer_get_bignum(&e->request, key->rsa->n);
 242         buffer_get_bignum(&e->request, challenge);
 243 
 244         /* Only protocol 1.1 is supported */
 245         if (buffer_len(&e->request) == 0)
 246                 goto failure;
 247         buffer_get(&e->request, session_id, 16);
 248         response_type = buffer_get_int(&e->request);
 249         if (response_type != 1)
 250                 goto failure;
 251 
 252         id = lookup_identity(key, 1);
 253         if (id != NULL && (!id->confirm || confirm_key(id) == 0)) {
 254                 Key *private = id->key;
 255                 /* Decrypt the challenge using the private key. */
 256                 if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
 257                         goto failure;
 258 
 259                 /* The response is MD5 of decrypted challenge plus session id. */
 260                 len = BN_num_bytes(challenge);
 261                 if (len <= 0 || len > 32) {
 262                         log("process_authentication_challenge: bad challenge length %d", len);
 263                         goto failure;
 264                 }
 265                 memset(buf, 0, 32);
 266                 BN_bn2bin(challenge, buf + 32 - len);
 267                 MD5_Init(&md);
 268                 MD5_Update(&md, buf, 32);
 269                 MD5_Update(&md, session_id, 16);
 270                 MD5_Final(mdbuf, &md);
 271 
 272                 /* Send the response. */
 273                 buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
 274                 for (i = 0; i < 16; i++)
 275                         buffer_put_char(&msg, mdbuf[i]);
 276                 goto send;
 277         }
 278 
 279 failure:
 280         /* Unknown identity or protocol error.  Send failure. */
 281         buffer_put_char(&msg, SSH_AGENT_FAILURE);
 282 send:
 283         buffer_put_int(&e->output, buffer_len(&msg));
 284         buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
 285         key_free(key);
 286         BN_clear_free(challenge);
 287         buffer_free(&msg);
 288 }
 289 
 290 /* ssh2 only */
 291 static void
 292 process_sign_request2(SocketEntry *e)
 293 {
 294         u_char *blob, *data, *signature = NULL;
 295         u_int blen, dlen, slen = 0;
 296         extern uint32_t datafellows;
 297         int odatafellows;
 298         int ok = -1, flags;
 299         Buffer msg;
 300         Key *key;
 301 
 302         datafellows = 0;
 303 
 304         blob = buffer_get_string(&e->request, &blen);
 305         data = buffer_get_string(&e->request, &dlen);
 306 
 307         flags = buffer_get_int(&e->request);
 308         odatafellows = datafellows;
 309         if (flags & SSH_AGENT_OLD_SIGNATURE)
 310                 datafellows = SSH_BUG_SIGBLOB;
 311 
 312         key = key_from_blob(blob, blen);
 313         if (key != NULL) {
 314                 Identity *id = lookup_identity(key, 2);
 315                 if (id != NULL && (!id->confirm || confirm_key(id) == 0))
 316                         ok = key_sign(id->key, &signature, &slen, data, dlen);
 317                 key_free(key);
 318         }
 319         buffer_init(&msg);
 320         if (ok == 0) {
 321                 buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
 322                 buffer_put_string(&msg, signature, slen);
 323         } else {
 324                 buffer_put_char(&msg, SSH_AGENT_FAILURE);
 325         }
 326         buffer_put_int(&e->output, buffer_len(&msg));
 327         buffer_append(&e->output, buffer_ptr(&msg),
 328             buffer_len(&msg));
 329         buffer_free(&msg);
 330         xfree(data);
 331         xfree(blob);
 332         if (signature != NULL)
 333                 xfree(signature);
 334         datafellows = odatafellows;
 335 }
 336 
 337 /* shared */
 338 static void
 339 process_remove_identity(SocketEntry *e, int version)
 340 {
 341         u_int blen, bits;
 342         int success = 0;
 343         Key *key = NULL;
 344         u_char *blob;
 345 
 346         switch (version) {
 347         case 1:
 348                 key = key_new(KEY_RSA1);
 349                 bits = buffer_get_int(&e->request);
 350                 buffer_get_bignum(&e->request, key->rsa->e);
 351                 buffer_get_bignum(&e->request, key->rsa->n);
 352 
 353                 if (bits != key_size(key))
 354                         log("Warning: identity keysize mismatch: actual %u, announced %u",
 355                             key_size(key), bits);
 356                 break;
 357         case 2:
 358                 blob = buffer_get_string(&e->request, &blen);
 359                 key = key_from_blob(blob, blen);
 360                 xfree(blob);
 361                 break;
 362         }
 363         if (key != NULL) {
 364                 Identity *id = lookup_identity(key, version);
 365                 if (id != NULL) {
 366                         /*
 367                          * We have this key.  Free the old key.  Since we
 368                          * don't want to leave empty slots in the middle of
 369                          * the array, we actually free the key there and move
 370                          * all the entries between the empty slot and the end
 371                          * of the array.
 372                          */
 373                         Idtab *tab = idtab_lookup(version);
 374                         if (tab->nentries < 1)
 375                                 fatal("process_remove_identity: "
 376                                     "internal error: tab->nentries %d",
 377                                     tab->nentries);
 378                         TAILQ_REMOVE(&tab->idlist, id, next);
 379                         free_identity(id);
 380                         tab->nentries--;
 381                         success = 1;
 382                 }
 383                 key_free(key);
 384         }
 385         buffer_put_int(&e->output, 1);
 386         buffer_put_char(&e->output,
 387             success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
 388 }
 389 
 390 static void
 391 process_remove_all_identities(SocketEntry *e, int version)
 392 {
 393         Idtab *tab = idtab_lookup(version);
 394         Identity *id;
 395 
 396         /* Loop over all identities and clear the keys. */
 397         for (id = TAILQ_FIRST(&tab->idlist); id;
 398             id = TAILQ_FIRST(&tab->idlist)) {
 399                 TAILQ_REMOVE(&tab->idlist, id, next);
 400                 free_identity(id);
 401         }
 402 
 403         /* Mark that there are no identities. */
 404         tab->nentries = 0;
 405 
 406         /* Send success. */
 407         buffer_put_int(&e->output, 1);
 408         buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
 409 }
 410 
 411 /* removes expired keys and returns number of seconds until the next expiry */
 412 static u_int
 413 reaper(void)
 414 {
 415         u_int deadline = 0, now = time(NULL);
 416         Identity *id, *nxt;
 417         int version;
 418         Idtab *tab;
 419 
 420         for (version = 1; version < 3; version++) {
 421                 tab = idtab_lookup(version);
 422                 for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) {
 423                         nxt = TAILQ_NEXT(id, next);
 424                         if (id->death == 0)
 425                                 continue;
 426                         if (now >= id->death) {
 427                                 debug("expiring key '%s'", id->comment);
 428                                 TAILQ_REMOVE(&tab->idlist, id, next);
 429                                 free_identity(id);
 430                                 tab->nentries--;
 431                         } else
 432                                 deadline = (deadline == 0) ? id->death :
 433                                     MIN(deadline, id->death);
 434                 }
 435         }
 436         if (deadline == 0 || deadline <= now)
 437                 return 0;
 438         else
 439                 return (deadline - now);
 440 }
 441 
 442 static void
 443 process_add_identity(SocketEntry *e, int version)
 444 {
 445         Idtab *tab = idtab_lookup(version);
 446         Identity *id;
 447         int type, success = 0, death = 0, confirm = 0;
 448         char *type_name, *comment;
 449         Key *k = NULL;
 450 
 451         switch (version) {
 452         case 1:
 453                 k = key_new_private(KEY_RSA1);
 454                 (void) buffer_get_int(&e->request);              /* ignored */
 455                 buffer_get_bignum(&e->request, k->rsa->n);
 456                 buffer_get_bignum(&e->request, k->rsa->e);
 457                 buffer_get_bignum(&e->request, k->rsa->d);
 458                 buffer_get_bignum(&e->request, k->rsa->iqmp);
 459 
 460                 /* SSH and SSL have p and q swapped */
 461                 buffer_get_bignum(&e->request, k->rsa->q); /* p */
 462                 buffer_get_bignum(&e->request, k->rsa->p); /* q */
 463 
 464                 /* Generate additional parameters */
 465                 rsa_generate_additional_parameters(k->rsa);
 466                 break;
 467         case 2:
 468                 type_name = buffer_get_string(&e->request, NULL);
 469                 type = key_type_from_name(type_name);
 470                 xfree(type_name);
 471                 switch (type) {
 472                 case KEY_DSA:
 473                         k = key_new_private(type);
 474                         buffer_get_bignum2(&e->request, k->dsa->p);
 475                         buffer_get_bignum2(&e->request, k->dsa->q);
 476                         buffer_get_bignum2(&e->request, k->dsa->g);
 477                         buffer_get_bignum2(&e->request, k->dsa->pub_key);
 478                         buffer_get_bignum2(&e->request, k->dsa->priv_key);
 479                         break;
 480                 case KEY_RSA:
 481                         k = key_new_private(type);
 482                         buffer_get_bignum2(&e->request, k->rsa->n);
 483                         buffer_get_bignum2(&e->request, k->rsa->e);
 484                         buffer_get_bignum2(&e->request, k->rsa->d);
 485                         buffer_get_bignum2(&e->request, k->rsa->iqmp);
 486                         buffer_get_bignum2(&e->request, k->rsa->p);
 487                         buffer_get_bignum2(&e->request, k->rsa->q);
 488 
 489                         /* Generate additional parameters */
 490                         rsa_generate_additional_parameters(k->rsa);
 491                         break;
 492                 default:
 493                         buffer_clear(&e->request);
 494                         goto send;
 495                 }
 496                 break;
 497         }
 498         /* enable blinding */
 499         switch (k->type) {
 500         case KEY_RSA:
 501         case KEY_RSA1:
 502                 if (RSA_blinding_on(k->rsa, NULL) != 1) {
 503                         error("process_add_identity: RSA_blinding_on failed");
 504                         key_free(k);
 505                         goto send;
 506                 }
 507                 break;
 508         }
 509         comment = buffer_get_string(&e->request, NULL);
 510         if (k == NULL) {
 511                 xfree(comment);
 512                 goto send;
 513         }
 514         while (buffer_len(&e->request)) {
 515                 switch ((type = buffer_get_char(&e->request))) {
 516                 case SSH_AGENT_CONSTRAIN_LIFETIME:
 517                         death = time(NULL) + buffer_get_int(&e->request);
 518                         break;
 519                 case SSH_AGENT_CONSTRAIN_CONFIRM:
 520                         confirm = 1;
 521                         break;
 522                 default:
 523                         error("process_add_identity: "
 524                             "Unknown constraint type %d", type);
 525                         xfree(comment);
 526                         key_free(k);
 527                         goto send;
 528                 }
 529         }
 530         success = 1;
 531         if (lifetime && !death)
 532                 death = time(NULL) + lifetime;
 533         if ((id = lookup_identity(k, version)) == NULL) {
 534                 id = xmalloc(sizeof(Identity));
 535                 id->key = k;
 536                 TAILQ_INSERT_TAIL(&tab->idlist, id, next);
 537                 /* Increment the number of identities. */
 538                 tab->nentries++;
 539         } else {
 540                 key_free(k);
 541                 xfree(id->comment);
 542         }
 543         id->comment = comment;
 544         id->death = death;
 545         id->confirm = confirm;
 546 send:
 547         buffer_put_int(&e->output, 1);
 548         buffer_put_char(&e->output,
 549             success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
 550 }
 551 
 552 /* XXX todo: encrypt sensitive data with passphrase */
 553 static void
 554 process_lock_agent(SocketEntry *e, int lock)
 555 {
 556         int success = 0;
 557         char *passwd;
 558 
 559         passwd = buffer_get_string(&e->request, NULL);
 560         if (locked && !lock && strcmp(passwd, lock_passwd) == 0) {
 561                 locked = 0;
 562                 memset(lock_passwd, 0, strlen(lock_passwd));
 563                 xfree(lock_passwd);
 564                 lock_passwd = NULL;
 565                 success = 1;
 566         } else if (!locked && lock) {
 567                 locked = 1;
 568                 lock_passwd = xstrdup(passwd);
 569                 success = 1;
 570         }
 571         memset(passwd, 0, strlen(passwd));
 572         xfree(passwd);
 573 
 574         buffer_put_int(&e->output, 1);
 575         buffer_put_char(&e->output,
 576             success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
 577 }
 578 
 579 static void
 580 no_identities(SocketEntry *e, u_int type)
 581 {
 582         Buffer msg;
 583 
 584         buffer_init(&msg);
 585         buffer_put_char(&msg,
 586             (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ?
 587             SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
 588         buffer_put_int(&msg, 0);
 589         buffer_put_int(&e->output, buffer_len(&msg));
 590         buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
 591         buffer_free(&msg);
 592 }
 593 
 594 /* dispatch incoming messages */
 595 
 596 static void
 597 process_message(SocketEntry *e)
 598 {
 599         u_int msg_len, type;
 600         u_char *cp;
 601 
 602         if (buffer_len(&e->input) < 5)
 603                 return;         /* Incomplete message. */
 604         cp = buffer_ptr(&e->input);
 605         msg_len = get_u32(cp);
 606         if (msg_len > 256 * 1024) {
 607                 close_socket(e);
 608                 return;
 609         }
 610         if (buffer_len(&e->input) < msg_len + 4)
 611                 return;
 612 
 613         /* move the current input to e->request */
 614         buffer_consume(&e->input, 4);
 615         buffer_clear(&e->request);
 616         buffer_append(&e->request, buffer_ptr(&e->input), msg_len);
 617         buffer_consume(&e->input, msg_len);
 618         type = buffer_get_char(&e->request);
 619 
 620         /* check wheter agent is locked */
 621         if (locked && type != SSH_AGENTC_UNLOCK) {
 622                 buffer_clear(&e->request);
 623                 switch (type) {
 624                 case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
 625                 case SSH2_AGENTC_REQUEST_IDENTITIES:
 626                         /* send empty lists */
 627                         no_identities(e, type);
 628                         break;
 629                 default:
 630                         /* send a fail message for all other request types */
 631                         buffer_put_int(&e->output, 1);
 632                         buffer_put_char(&e->output, SSH_AGENT_FAILURE);
 633                 }
 634                 return;
 635         }
 636 
 637         debug("type %d", type);
 638         switch (type) {
 639         case SSH_AGENTC_LOCK:
 640         case SSH_AGENTC_UNLOCK:
 641                 process_lock_agent(e, type == SSH_AGENTC_LOCK);
 642                 break;
 643         /* ssh1 */
 644         case SSH_AGENTC_RSA_CHALLENGE:
 645                 process_authentication_challenge1(e);
 646                 break;
 647         case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
 648                 process_request_identities(e, 1);
 649                 break;
 650         case SSH_AGENTC_ADD_RSA_IDENTITY:
 651         case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED:
 652                 process_add_identity(e, 1);
 653                 break;
 654         case SSH_AGENTC_REMOVE_RSA_IDENTITY:
 655                 process_remove_identity(e, 1);
 656                 break;
 657         case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
 658                 process_remove_all_identities(e, 1);
 659                 break;
 660         /* ssh2 */
 661         case SSH2_AGENTC_SIGN_REQUEST:
 662                 process_sign_request2(e);
 663                 break;
 664         case SSH2_AGENTC_REQUEST_IDENTITIES:
 665                 process_request_identities(e, 2);
 666                 break;
 667         case SSH2_AGENTC_ADD_IDENTITY:
 668         case SSH2_AGENTC_ADD_ID_CONSTRAINED:
 669                 process_add_identity(e, 2);
 670                 break;
 671         case SSH2_AGENTC_REMOVE_IDENTITY:
 672                 process_remove_identity(e, 2);
 673                 break;
 674         case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
 675                 process_remove_all_identities(e, 2);
 676                 break;
 677         default:
 678                 /* Unknown message.  Respond with failure. */
 679                 error("Unknown message %d", type);
 680                 buffer_clear(&e->request);
 681                 buffer_put_int(&e->output, 1);
 682                 buffer_put_char(&e->output, SSH_AGENT_FAILURE);
 683                 break;
 684         }
 685 }
 686 
 687 static void
 688 new_socket(sock_type type, int fd)
 689 {
 690         u_int i, old_alloc, new_alloc;
 691 
 692         set_nonblock(fd);
 693 
 694         if (fd > max_fd)
 695                 max_fd = fd;
 696 
 697         for (i = 0; i < sockets_alloc; i++)
 698                 if (sockets[i].type == AUTH_UNUSED) {
 699                         sockets[i].fd = fd;
 700                         buffer_init(&sockets[i].input);
 701                         buffer_init(&sockets[i].output);
 702                         buffer_init(&sockets[i].request);
 703                         sockets[i].type = type;
 704                         return;
 705                 }
 706         old_alloc = sockets_alloc;
 707         new_alloc = sockets_alloc + 10;
 708         sockets = xrealloc(sockets, new_alloc * sizeof(sockets[0]));
 709         for (i = old_alloc; i < new_alloc; i++)
 710                 sockets[i].type = AUTH_UNUSED;
 711         sockets_alloc = new_alloc;
 712         sockets[old_alloc].fd = fd;
 713         buffer_init(&sockets[old_alloc].input);
 714         buffer_init(&sockets[old_alloc].output);
 715         buffer_init(&sockets[old_alloc].request);
 716         sockets[old_alloc].type = type;
 717 }
 718 
 719 static int
 720 prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp,
 721     struct timeval **tvpp)
 722 {
 723         u_int i, sz, deadline;
 724         int n = 0;
 725         static struct timeval tv;
 726 
 727         for (i = 0; i < sockets_alloc; i++) {
 728                 switch (sockets[i].type) {
 729                 case AUTH_SOCKET:
 730                 case AUTH_CONNECTION:
 731                         n = MAX(n, sockets[i].fd);
 732                         break;
 733                 case AUTH_UNUSED:
 734                         break;
 735                 default:
 736                         fatal("Unknown socket type %d", sockets[i].type);
 737                         break;
 738                 }
 739         }
 740 
 741         sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
 742         if (*fdrp == NULL || sz > *nallocp) {
 743                 if (*fdrp)
 744                         xfree(*fdrp);
 745                 if (*fdwp)
 746                         xfree(*fdwp);
 747                 *fdrp = xmalloc(sz);
 748                 *fdwp = xmalloc(sz);
 749                 *nallocp = sz;
 750         }
 751         if (n < *fdl)
 752                 debug("XXX shrink: %d < %d", n, *fdl);
 753         *fdl = n;
 754         memset(*fdrp, 0, sz);
 755         memset(*fdwp, 0, sz);
 756 
 757         for (i = 0; i < sockets_alloc; i++) {
 758                 switch (sockets[i].type) {
 759                 case AUTH_SOCKET:
 760                 case AUTH_CONNECTION:
 761                         FD_SET(sockets[i].fd, *fdrp);
 762                         if (buffer_len(&sockets[i].output) > 0)
 763                                 FD_SET(sockets[i].fd, *fdwp);
 764                         break;
 765                 default:
 766                         break;
 767                 }
 768         }
 769         deadline = reaper();
 770         if (parent_alive_interval != 0)
 771                 deadline = (deadline == 0) ? parent_alive_interval :
 772                     MIN(deadline, parent_alive_interval);
 773         if (deadline == 0) {
 774                 *tvpp = NULL;
 775         } else {
 776                 tv.tv_sec = deadline;
 777                 tv.tv_usec = 0;
 778                 *tvpp = &tv;
 779         }
 780         return (1);
 781 }
 782 
 783 static void
 784 after_select(fd_set *readset, fd_set *writeset)
 785 {
 786         struct sockaddr_un sunaddr;
 787         socklen_t slen;
 788         char buf[1024];
 789         int len, sock;
 790         u_int i;
 791         uid_t euid;
 792         gid_t egid;
 793 
 794         for (i = 0; i < sockets_alloc; i++)
 795                 switch (sockets[i].type) {
 796                 case AUTH_UNUSED:
 797                         break;
 798                 case AUTH_SOCKET:
 799                         if (FD_ISSET(sockets[i].fd, readset)) {
 800                                 slen = sizeof(sunaddr);
 801                                 sock = accept(sockets[i].fd,
 802                                     (struct sockaddr *)&sunaddr, &slen);
 803                                 if (sock < 0) {
 804                                         error("accept from AUTH_SOCKET: %s",
 805                                             strerror(errno));
 806                                         break;
 807                                 }
 808                                 if (getpeereid(sock, &euid, &egid) < 0) {
 809                                         error("getpeereid %d failed: %s",
 810                                             sock, strerror(errno));
 811                                         close(sock);
 812                                         break;
 813                                 }
 814                                 if ((euid != 0) && (getuid() != euid)) {
 815                                         error("uid mismatch: "
 816                                             "peer euid %u != uid %u",
 817                                             (u_int) euid, (u_int) getuid());
 818                                         close(sock);
 819                                         break;
 820                                 }
 821                                 new_socket(AUTH_CONNECTION, sock);
 822                         }
 823                         break;
 824                 case AUTH_CONNECTION:
 825                         if (buffer_len(&sockets[i].output) > 0 &&
 826                             FD_ISSET(sockets[i].fd, writeset)) {
 827                                 do {
 828                                         len = write(sockets[i].fd,
 829                                             buffer_ptr(&sockets[i].output),
 830                                             buffer_len(&sockets[i].output));
 831                                         if (len == -1 && (errno == EAGAIN ||
 832                                             errno == EINTR ||
 833                                             errno == EWOULDBLOCK))
 834                                                 continue;
 835                                         break;
 836                                 } while (1);
 837                                 if (len <= 0) {
 838                                         close_socket(&sockets[i]);
 839                                         break;
 840                                 }
 841                                 buffer_consume(&sockets[i].output, len);
 842                         }
 843                         if (FD_ISSET(sockets[i].fd, readset)) {
 844                                 do {
 845                                         len = read(sockets[i].fd, buf, sizeof(buf));
 846                                         if (len == -1 && (errno == EAGAIN ||
 847                                             errno == EINTR ||
 848                                             errno == EWOULDBLOCK))
 849                                                 continue;
 850                                         break;
 851                                 } while (1);
 852                                 if (len <= 0) {
 853                                         close_socket(&sockets[i]);
 854                                         break;
 855                                 }
 856                                 buffer_append(&sockets[i].input, buf, len);
 857                                 process_message(&sockets[i]);
 858                         }
 859                         break;
 860                 default:
 861                         fatal("Unknown type %d", sockets[i].type);
 862                 }
 863 }
 864 
 865 static void
 866 cleanup_socket(void)
 867 {
 868         if (socket_name[0])
 869                 unlink(socket_name);
 870         if (socket_dir[0])
 871                 rmdir(socket_dir);
 872 }
 873 
 874 void
 875 cleanup_exit(int i)
 876 {
 877         cleanup_socket();
 878         _exit(i);
 879 }
 880 
 881 /*ARGSUSED*/
 882 static void
 883 cleanup_handler(int sig)
 884 {
 885         cleanup_socket();
 886         _exit(2);
 887 }
 888 
 889 static void
 890 check_parent_exists(void)
 891 {
 892 #ifdef HAVE_SOLARIS_PRIVILEGE
 893         /*
 894          * We can not simply use "kill(ppid, 0) < 0" to detect if the parent
 895          * has exited when the child process no longer has the
 896          * PRIV_PROC_SESSION privilege.
 897          */
 898         if (parent_pid != -1 && getppid() != parent_pid) {
 899 #else
 900         if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
 901 
 902 #endif
 903                 /* printf("Parent has died - Authentication agent exiting.\n"); */
 904                 cleanup_socket();
 905                 _exit(2);
 906         }
 907 }
 908 
 909 static void
 910 usage(void)
 911 {
 912         fprintf(stderr,
 913                 gettext("Usage: %s [options] [command [args ...]]\n"
 914                     "Options:\n"
 915                     "  -c          Generate C-shell commands on stdout.\n"
 916                     "  -s          Generate Bourne shell commands on stdout.\n"
 917                     "  -k          Kill the current agent.\n"
 918                     "  -d          Debug mode.\n"
 919                     "  -a socket   Bind agent socket to given name.\n"
 920                     "  -t life     Default identity lifetime (seconds).\n"),
 921                 __progname);
 922         exit(1);
 923 }
 924 
 925 int
 926 main(int ac, char **av)
 927 {
 928         int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0;
 929         int sock, fd, ch, result, saved_errno;
 930         u_int nalloc;
 931         char *shell, *pidstr, *agentsocket = NULL;
 932         const char *format;
 933         fd_set *readsetp = NULL, *writesetp = NULL;
 934         struct sockaddr_un sunaddr;
 935 #ifdef HAVE_SETRLIMIT
 936         struct rlimit rlim;
 937 #endif
 938         int prev_mask;
 939         extern int optind;
 940         extern char *optarg;
 941         pid_t pid;
 942         char pidstrbuf[1 + 3 * sizeof pid];
 943         struct timeval *tvp = NULL;
 944 #ifdef HAVE_SOLARIS_PRIVILEGE
 945         priv_set_t *myprivs;
 946 #endif /* HAVE_SOLARIS_PRIVILEGE */
 947 
 948         /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
 949         sanitise_stdfd();
 950 
 951         /* drop */
 952         setegid(getgid());
 953         setgid(getgid());
 954 
 955         SSLeay_add_all_algorithms();
 956 
 957         __progname = get_progname(av[0]);
 958         init_rng();
 959         seed_rng();
 960 
 961         while ((ch = getopt(ac, av, "cdksa:t:")) != -1) {
 962                 switch (ch) {
 963                 case 'c':
 964                         if (s_flag)
 965                                 usage();
 966                         c_flag++;
 967                         break;
 968                 case 'k':
 969                         k_flag++;
 970                         break;
 971                 case 's':
 972                         if (c_flag)
 973                                 usage();
 974                         s_flag++;
 975                         break;
 976                 case 'd':
 977                         if (d_flag)
 978                                 usage();
 979                         d_flag++;
 980                         break;
 981                 case 'a':
 982                         agentsocket = optarg;
 983                         break;
 984                 case 't':
 985                         if ((lifetime = convtime(optarg)) == -1) {
 986                                 fprintf(stderr, gettext("Invalid lifetime\n"));
 987                                 usage();
 988                         }
 989                         break;
 990                 default:
 991                         usage();
 992                 }
 993         }
 994         ac -= optind;
 995         av += optind;
 996 
 997         if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
 998                 usage();
 999 
1000         if (ac == 0 && !c_flag && !s_flag) {
1001                 shell = getenv("SHELL");
1002                 if (shell != NULL &&
1003                     strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
1004                         c_flag = 1;
1005         }
1006         if (k_flag) {
1007                 pidstr = getenv(SSH_AGENTPID_ENV_NAME);
1008                 if (pidstr == NULL) {
1009                         fprintf(stderr,
1010                                 gettext("%s not set, cannot kill agent\n"),
1011                                 SSH_AGENTPID_ENV_NAME);
1012                         exit(1);
1013                 }
1014                 pid = atoi(pidstr);
1015                 if (pid < 1) {
1016                         fprintf(stderr,
1017                                 gettext("%s not set, cannot kill agent\n"),
1018                                 SSH_AGENTPID_ENV_NAME);
1019                         exit(1);
1020                 }
1021                 if (kill(pid, SIGTERM) == -1) {
1022                         perror("kill");
1023                         exit(1);
1024                 }
1025                 format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
1026                 printf(format, SSH_AUTHSOCKET_ENV_NAME);
1027                 printf(format, SSH_AGENTPID_ENV_NAME);
1028                 printf("echo ");
1029                 printf(gettext("Agent pid %ld killed;\n"), (long)pid);
1030                 exit(0);
1031         }
1032         parent_pid = getpid();
1033 
1034         if (agentsocket == NULL) {
1035                 /* Create private directory for agent socket */
1036                 strlcpy(socket_dir, "/tmp/ssh-XXXXXXXXXX", sizeof socket_dir);
1037                 if (mkdtemp(socket_dir) == NULL) {
1038                         perror("mkdtemp: private socket dir");
1039                         exit(1);
1040                 }
1041                 snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir,
1042                     (long)parent_pid);
1043         } else {
1044                 /* Try to use specified agent socket */
1045                 socket_dir[0] = '\0';
1046                 strlcpy(socket_name, agentsocket, sizeof socket_name);
1047         }
1048 
1049         /*
1050          * Create socket early so it will exist before command gets run from
1051          * the parent.
1052          */
1053         sock = socket(AF_UNIX, SOCK_STREAM, 0);
1054         if (sock < 0) {
1055                 perror("socket");
1056                 *socket_name = '\0'; /* Don't unlink any existing file */
1057                 cleanup_exit(1);
1058         }
1059         memset(&sunaddr, 0, sizeof(sunaddr));
1060         sunaddr.sun_family = AF_UNIX;
1061         strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
1062         prev_mask = umask(0177);
1063         if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) {
1064                 perror("bind");
1065                 *socket_name = '\0'; /* Don't unlink any existing file */
1066                 umask(prev_mask);
1067                 cleanup_exit(1);
1068         }
1069         umask(prev_mask);
1070         if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
1071                 perror("listen");
1072                 cleanup_exit(1);
1073         }
1074 
1075         /*
1076          * Fork, and have the parent execute the command, if any, or present
1077          * the socket data.  The child continues as the authentication agent.
1078          */
1079         if (d_flag) {
1080                 log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1);
1081                 format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
1082                 printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
1083                     SSH_AUTHSOCKET_ENV_NAME);
1084                 printf("echo ");
1085                 printf(gettext("Agent pid %ld;\n"), (long)parent_pid);
1086                 goto skip;
1087         }
1088         pid = fork();
1089         if (pid == -1) {
1090                 perror("fork");
1091                 cleanup_exit(1);
1092         }
1093         if (pid != 0) {         /* Parent - execute the given command. */
1094                 close(sock);
1095                 snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid);
1096                 if (ac == 0) {
1097                         format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
1098                         printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
1099                             SSH_AUTHSOCKET_ENV_NAME);
1100                         printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
1101                             SSH_AGENTPID_ENV_NAME);
1102                         printf("echo ");
1103                         printf(gettext("Agent pid %ld;\n"), (long)pid);
1104                         exit(0);
1105                 }
1106                 if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
1107                     setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
1108                         perror("setenv");
1109                         exit(1);
1110                 }
1111                 execvp(av[0], av);
1112                 perror(av[0]);
1113                 exit(1);
1114         }
1115         /* child */
1116         log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0);
1117 
1118 #ifdef HAVE_SOLARIS_PRIVILEGE
1119         /*
1120          * Drop unneeded privs, including basic ones like fork/exec.
1121          *
1122          * Idiom: remove from 'basic' privs we know we don't want,
1123          * invert the result and remove the resulting set from P.
1124          *
1125          * None of the priv_delset() calls below, nor the setppriv call
1126          * below can fail, so their return values are not checked.
1127          */
1128         if ((myprivs = priv_str_to_set("basic", ",", NULL)) == NULL)
1129                 fatal("priv_str_to_set failed: %m");
1130         (void) priv_delset(myprivs, PRIV_PROC_EXEC);
1131         (void) priv_delset(myprivs, PRIV_PROC_FORK);
1132         (void) priv_delset(myprivs, PRIV_FILE_LINK_ANY);
1133         (void) priv_delset(myprivs, PRIV_PROC_INFO);
1134         (void) priv_delset(myprivs, PRIV_PROC_SESSION);
1135         priv_inverse(myprivs);
1136         (void) setppriv(PRIV_OFF, PRIV_PERMITTED, myprivs);
1137         (void) priv_freeset(myprivs);
1138 #endif /* HAVE_SOLARIS_PRIVILEGE */
1139 
1140         if (setsid() == -1) {
1141                 error("setsid: %s", strerror(errno));
1142                 cleanup_exit(1);
1143         }
1144 
1145         (void)chdir("/");
1146         if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
1147                 /* XXX might close listen socket */
1148                 (void)dup2(fd, STDIN_FILENO);
1149                 (void)dup2(fd, STDOUT_FILENO);
1150                 (void)dup2(fd, STDERR_FILENO);
1151                 if (fd > 2)
1152                         close(fd);
1153         }
1154 
1155 #ifdef HAVE_SETRLIMIT
1156         /* deny core dumps, since memory contains unencrypted private keys */
1157         rlim.rlim_cur = rlim.rlim_max = 0;
1158         if (setrlimit(RLIMIT_CORE, &rlim) < 0) {
1159                 error("setrlimit RLIMIT_CORE: %s", strerror(errno));
1160                 cleanup_exit(1);
1161         }
1162 #endif
1163 
1164 skip:
1165         new_socket(AUTH_SOCKET, sock);
1166         if (ac > 0)
1167                 parent_alive_interval = 10;
1168         idtab_init();
1169         if (!d_flag)
1170                 signal(SIGINT, SIG_IGN);
1171         signal(SIGPIPE, SIG_IGN);
1172         signal(SIGHUP, cleanup_handler);
1173         signal(SIGTERM, cleanup_handler);
1174         nalloc = 0;
1175 
1176         while (1) {
1177                 prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp);
1178                 result = select(max_fd + 1, readsetp, writesetp, NULL, tvp);
1179                 saved_errno = errno;
1180                 if (parent_alive_interval != 0)
1181                         check_parent_exists();
1182                 (void) reaper();        /* remove expired keys */
1183                 if (result < 0) {
1184                         if (saved_errno == EINTR)
1185                                 continue;
1186                         fatal("select: %s", strerror(saved_errno));
1187                 } else if (result > 0)
1188                         after_select(readsetp, writesetp);
1189         }
1190         /* NOTREACHED */
1191         return (0);     /* keep lint happy */
1192 }