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