]> andersk Git - openssh.git/blob - ssh-agent.c
ce283c8ccdb69cca3e5e529c082f0ffd97a6d082
[openssh.git] / ssh-agent.c
1 /*      $OpenBSD: ssh-agent.c,v 1.79 2002/01/18 18:14:17 stevesk Exp $  */
2
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
38 #include "includes.h"
39 RCSID("$OpenBSD: ssh-agent.c,v 1.79 2002/01/18 18:14:17 stevesk Exp $");
40
41 #if defined(HAVE_SYS_QUEUE_H) && !defined(HAVE_BOGUS_SYS_QUEUE_H)
42 #include <sys/queue.h>
43 #else
44 #include "openbsd-compat/fake-queue.h"
45 #endif
46
47
48 #include <openssl/evp.h>
49 #include <openssl/md5.h>
50
51 #include "ssh.h"
52 #include "rsa.h"
53 #include "buffer.h"
54 #include "bufaux.h"
55 #include "xmalloc.h"
56 #include "packet.h"
57 #include "getput.h"
58 #include "mpaux.h"
59 #include "key.h"
60 #include "authfd.h"
61 #include "cipher.h"
62 #include "kex.h"
63 #include "compat.h"
64 #include "log.h"
65
66 #ifdef SMARTCARD
67 #include <openssl/engine.h>
68 #include "scard.h"
69 #endif
70
71 typedef enum {
72         AUTH_UNUSED,
73         AUTH_SOCKET,
74         AUTH_CONNECTION
75 } sock_type;
76
77 typedef struct {
78         int fd;
79         sock_type type;
80         Buffer input;
81         Buffer output;
82 } SocketEntry;
83
84 u_int sockets_alloc = 0;
85 SocketEntry *sockets = NULL;
86
87 typedef struct identity {
88         TAILQ_ENTRY(identity) next;
89         Key *key;
90         char *comment;
91 } Identity;
92
93 typedef struct {
94         int nentries;
95         TAILQ_HEAD(idqueue, identity) idlist;
96 } Idtab;
97
98 /* private key table, one per protocol version */
99 Idtab idtable[3];
100
101 int max_fd = 0;
102
103 /* pid of shell == parent of agent */
104 pid_t parent_pid = -1;
105
106 /* pathname and directory for AUTH_SOCKET */
107 char socket_name[1024];
108 char socket_dir[1024];
109
110 #ifdef HAVE___PROGNAME
111 extern char *__progname;
112 #else
113 char *__progname;
114 #endif
115
116 static void
117 idtab_init(void)
118 {
119         int i;
120         for (i = 0; i <=2; i++) {
121                 TAILQ_INIT(&idtable[i].idlist);
122                 idtable[i].nentries = 0;
123         }
124 }
125
126 /* return private key table for requested protocol version */
127 static Idtab *
128 idtab_lookup(int version)
129 {
130         if (version < 1 || version > 2)
131                 fatal("internal error, bad protocol version %d", version);
132         return &idtable[version];
133 }
134
135 /* return matching private key for given public key */
136 static Identity *
137 lookup_identity(Key *key, int version)
138 {
139         Identity *id;
140
141         Idtab *tab = idtab_lookup(version);
142         TAILQ_FOREACH(id, &tab->idlist, next) {
143                 if (key_equal(key, id->key))
144                         return (id);
145         }
146         return (NULL);
147 }
148
149 static void
150 free_identity(Identity *id)
151 {
152         key_free(id->key);
153         xfree(id->comment);
154         xfree(id);
155 }
156
157 /* send list of supported public keys to 'client' */
158 static void
159 process_request_identities(SocketEntry *e, int version)
160 {
161         Idtab *tab = idtab_lookup(version);
162         Buffer msg;
163         Identity *id;
164
165         buffer_init(&msg);
166         buffer_put_char(&msg, (version == 1) ?
167             SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER);
168         buffer_put_int(&msg, tab->nentries);
169         TAILQ_FOREACH(id, &tab->idlist, next) {
170                 if (id->key->type == KEY_RSA1) {
171                         buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
172                         buffer_put_bignum(&msg, id->key->rsa->e);
173                         buffer_put_bignum(&msg, id->key->rsa->n);
174                 } else {
175                         u_char *blob;
176                         u_int blen;
177                         key_to_blob(id->key, &blob, &blen);
178                         buffer_put_string(&msg, blob, blen);
179                         xfree(blob);
180                 }
181                 buffer_put_cstring(&msg, id->comment);
182         }
183         buffer_put_int(&e->output, buffer_len(&msg));
184         buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
185         buffer_free(&msg);
186 }
187
188 /* ssh1 only */
189 static void
190 process_authentication_challenge1(SocketEntry *e)
191 {
192         Identity *id;
193         Key *key;
194         BIGNUM *challenge;
195         int i, len;
196         Buffer msg;
197         MD5_CTX md;
198         u_char buf[32], mdbuf[16], session_id[16];
199         u_int response_type;
200
201         buffer_init(&msg);
202         key = key_new(KEY_RSA1);
203         if ((challenge = BN_new()) == NULL)
204                 fatal("process_authentication_challenge1: BN_new failed");
205
206         buffer_get_int(&e->input);                              /* ignored */
207         buffer_get_bignum(&e->input, key->rsa->e);
208         buffer_get_bignum(&e->input, key->rsa->n);
209         buffer_get_bignum(&e->input, challenge);
210
211         /* Only protocol 1.1 is supported */
212         if (buffer_len(&e->input) == 0)
213                 goto failure;
214         buffer_get(&e->input, session_id, 16);
215         response_type = buffer_get_int(&e->input);
216         if (response_type != 1)
217                 goto failure;
218
219         id = lookup_identity(key, 1);
220         if (id != NULL) {
221                 Key *private = id->key;
222                 /* Decrypt the challenge using the private key. */
223                 if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0)
224                         goto failure;
225
226                 /* The response is MD5 of decrypted challenge plus session id. */
227                 len = BN_num_bytes(challenge);
228                 if (len <= 0 || len > 32) {
229                         log("process_authentication_challenge: bad challenge length %d", len);
230                         goto failure;
231                 }
232                 memset(buf, 0, 32);
233                 BN_bn2bin(challenge, buf + 32 - len);
234                 MD5_Init(&md);
235                 MD5_Update(&md, buf, 32);
236                 MD5_Update(&md, session_id, 16);
237                 MD5_Final(mdbuf, &md);
238
239                 /* Send the response. */
240                 buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
241                 for (i = 0; i < 16; i++)
242                         buffer_put_char(&msg, mdbuf[i]);
243                 goto send;
244         }
245
246 failure:
247         /* Unknown identity or protocol error.  Send failure. */
248         buffer_put_char(&msg, SSH_AGENT_FAILURE);
249 send:
250         buffer_put_int(&e->output, buffer_len(&msg));
251         buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
252         key_free(key);
253         BN_clear_free(challenge);
254         buffer_free(&msg);
255 }
256
257 /* ssh2 only */
258 static void
259 process_sign_request2(SocketEntry *e)
260 {
261         extern int datafellows;
262         Key *key;
263         u_char *blob, *data, *signature = NULL;
264         u_int blen, dlen, slen = 0;
265         int flags;
266         Buffer msg;
267         int ok = -1;
268
269         datafellows = 0;
270
271         blob = buffer_get_string(&e->input, &blen);
272         data = buffer_get_string(&e->input, &dlen);
273
274         flags = buffer_get_int(&e->input);
275         if (flags & SSH_AGENT_OLD_SIGNATURE)
276                 datafellows = SSH_BUG_SIGBLOB;
277
278         key = key_from_blob(blob, blen);
279         if (key != NULL) {
280                 Identity *id = lookup_identity(key, 2);
281                 if (id != NULL)
282                         ok = key_sign(id->key, &signature, &slen, data, dlen);
283         }
284         key_free(key);
285         buffer_init(&msg);
286         if (ok == 0) {
287                 buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE);
288                 buffer_put_string(&msg, signature, slen);
289         } else {
290                 buffer_put_char(&msg, SSH_AGENT_FAILURE);
291         }
292         buffer_put_int(&e->output, buffer_len(&msg));
293         buffer_append(&e->output, buffer_ptr(&msg),
294             buffer_len(&msg));
295         buffer_free(&msg);
296         xfree(data);
297         xfree(blob);
298         if (signature != NULL)
299                 xfree(signature);
300 }
301
302 /* shared */
303 static void
304 process_remove_identity(SocketEntry *e, int version)
305 {
306         Key *key = NULL;
307         u_char *blob;
308         u_int blen;
309         u_int bits;
310         int success = 0;
311
312         switch (version) {
313         case 1:
314                 key = key_new(KEY_RSA1);
315                 bits = buffer_get_int(&e->input);
316                 buffer_get_bignum(&e->input, key->rsa->e);
317                 buffer_get_bignum(&e->input, key->rsa->n);
318
319                 if (bits != key_size(key))
320                         log("Warning: identity keysize mismatch: actual %d, announced %d",
321                             key_size(key), bits);
322                 break;
323         case 2:
324                 blob = buffer_get_string(&e->input, &blen);
325                 key = key_from_blob(blob, blen);
326                 xfree(blob);
327                 break;
328         }
329         if (key != NULL) {
330                 Identity *id = lookup_identity(key, version);
331                 if (id != NULL) {
332                         /*
333                          * We have this key.  Free the old key.  Since we
334                          * don\'t want to leave empty slots in the middle of
335                          * the array, we actually free the key there and move
336                          * all the entries between the empty slot and the end
337                          * of the array.
338                          */
339                         Idtab *tab = idtab_lookup(version);
340                         if (tab->nentries < 1)
341                                 fatal("process_remove_identity: "
342                                     "internal error: tab->nentries %d",
343                                     tab->nentries);
344                         TAILQ_REMOVE(&tab->idlist, id, next);
345                         free_identity(id);
346                         tab->nentries--;
347                         success = 1;
348                 }
349                 key_free(key);
350         }
351         buffer_put_int(&e->output, 1);
352         buffer_put_char(&e->output,
353             success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
354 }
355
356 static void
357 process_remove_all_identities(SocketEntry *e, int version)
358 {
359         Idtab *tab = idtab_lookup(version);
360         Identity *id;
361
362         /* Loop over all identities and clear the keys. */
363         for (id = TAILQ_FIRST(&tab->idlist); id;
364             id = TAILQ_FIRST(&tab->idlist)) {
365                 TAILQ_REMOVE(&tab->idlist, id, next);
366                 free_identity(id);
367         }
368
369         /* Mark that there are no identities. */
370         tab->nentries = 0;
371
372         /* Send success. */
373         buffer_put_int(&e->output, 1);
374         buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
375         return;
376 }
377
378 static void
379 process_add_identity(SocketEntry *e, int version)
380 {
381         Key *k = NULL;
382         char *type_name;
383         char *comment;
384         int type, success = 0;
385         Idtab *tab = idtab_lookup(version);
386
387         switch (version) {
388         case 1:
389                 k = key_new_private(KEY_RSA1);
390                 buffer_get_int(&e->input);                      /* ignored */
391                 buffer_get_bignum(&e->input, k->rsa->n);
392                 buffer_get_bignum(&e->input, k->rsa->e);
393                 buffer_get_bignum(&e->input, k->rsa->d);
394                 buffer_get_bignum(&e->input, k->rsa->iqmp);
395
396                 /* SSH and SSL have p and q swapped */
397                 buffer_get_bignum(&e->input, k->rsa->q);        /* p */
398                 buffer_get_bignum(&e->input, k->rsa->p);        /* q */
399
400                 /* Generate additional parameters */
401                 rsa_generate_additional_parameters(k->rsa);
402                 break;
403         case 2:
404                 type_name = buffer_get_string(&e->input, NULL);
405                 type = key_type_from_name(type_name);
406                 xfree(type_name);
407                 switch (type) {
408                 case KEY_DSA:
409                         k = key_new_private(type);
410                         buffer_get_bignum2(&e->input, k->dsa->p);
411                         buffer_get_bignum2(&e->input, k->dsa->q);
412                         buffer_get_bignum2(&e->input, k->dsa->g);
413                         buffer_get_bignum2(&e->input, k->dsa->pub_key);
414                         buffer_get_bignum2(&e->input, k->dsa->priv_key);
415                         break;
416                 case KEY_RSA:
417                         k = key_new_private(type);
418                         buffer_get_bignum2(&e->input, k->rsa->n);
419                         buffer_get_bignum2(&e->input, k->rsa->e);
420                         buffer_get_bignum2(&e->input, k->rsa->d);
421                         buffer_get_bignum2(&e->input, k->rsa->iqmp);
422                         buffer_get_bignum2(&e->input, k->rsa->p);
423                         buffer_get_bignum2(&e->input, k->rsa->q);
424
425                         /* Generate additional parameters */
426                         rsa_generate_additional_parameters(k->rsa);
427                         break;
428                 default:
429                         buffer_clear(&e->input);
430                         goto send;
431                 }
432                 break;
433         }
434         comment = buffer_get_string(&e->input, NULL);
435         if (k == NULL) {
436                 xfree(comment);
437                 goto send;
438         }
439         success = 1;
440         if (lookup_identity(k, version) == NULL) {
441                 Identity *id = xmalloc(sizeof(Identity));
442                 id->key = k;
443                 id->comment = comment;
444                 TAILQ_INSERT_TAIL(&tab->idlist, id, next);
445                 /* Increment the number of identities. */
446                 tab->nentries++;
447         } else {
448                 key_free(k);
449                 xfree(comment);
450         }
451 send:
452         buffer_put_int(&e->output, 1);
453         buffer_put_char(&e->output,
454             success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
455 }
456
457
458 #ifdef SMARTCARD
459 static void
460 process_add_smartcard_key (SocketEntry *e)
461 {
462         Idtab *tab;
463         Key *n = NULL, *k = NULL;
464         char *sc_reader_id = NULL;
465         int success = 0;
466
467         sc_reader_id = buffer_get_string(&e->input, NULL);
468         k = sc_get_key(sc_reader_id);
469         xfree(sc_reader_id);
470
471         if (k == NULL) {
472                 error("sc_get_pubkey failed");
473                 goto send;
474         }
475         success = 1;
476
477         tab = idtab_lookup(1);
478         k->type = KEY_RSA1;
479         if (lookup_identity(k, 1) == NULL) {
480                 Identity *id = xmalloc(sizeof(Identity));
481                 n = key_new(KEY_RSA1);
482                 BN_copy(n->rsa->n, k->rsa->n);
483                 BN_copy(n->rsa->e, k->rsa->e);
484                 RSA_set_method(n->rsa, sc_get_engine());
485                 id->key = n;
486                 id->comment = xstrdup("rsa1 smartcard");
487                 TAILQ_INSERT_TAIL(&tab->idlist, id, next);
488                 tab->nentries++;
489         }
490         k->type = KEY_RSA;
491         tab = idtab_lookup(2);
492         if (lookup_identity(k, 2) == NULL) {
493                 Identity *id = xmalloc(sizeof(Identity));
494                 n = key_new(KEY_RSA);
495                 BN_copy(n->rsa->n, k->rsa->n);
496                 BN_copy(n->rsa->e, k->rsa->e);
497                 RSA_set_method(n->rsa, sc_get_engine());
498                 id->key = n;
499                 id->comment = xstrdup("rsa smartcard");
500                 TAILQ_INSERT_TAIL(&tab->idlist, id, next);
501                 tab->nentries++;
502         }
503         key_free(k);
504 send:
505         buffer_put_int(&e->output, 1);
506         buffer_put_char(&e->output,
507             success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
508 }
509
510 static void
511 process_remove_smartcard_key(SocketEntry *e)
512 {
513         Key *k = NULL;
514         int success = 0;
515         char *sc_reader_id = NULL;
516
517         sc_reader_id = buffer_get_string(&e->input, NULL);
518         k = sc_get_key(sc_reader_id);
519         xfree(sc_reader_id);
520
521         if (k == NULL) {
522                 error("sc_get_pubkey failed");
523         } else {
524                 Identity *id;
525                 k->type = KEY_RSA1;
526                 id = lookup_identity(k, 1);
527                 if (id != NULL) {
528                         Idtab *tab = idtab_lookup(1);
529                         TAILQ_REMOVE(&tab->idlist, id, next);
530                         free_identity(id);
531                         tab->nentries--;
532                         success = 1;
533                 }
534                 k->type = KEY_RSA;
535                 id = lookup_identity(k, 2);
536                 if (id != NULL) {
537                         Idtab *tab = idtab_lookup(2);
538                         TAILQ_REMOVE(&tab->idlist, id, next);
539                         free_identity(id);
540                         tab->nentries--;
541                         success = 1;
542                 }
543                 key_free(k);
544         }
545
546         buffer_put_int(&e->output, 1);
547         buffer_put_char(&e->output,
548             success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE);
549 }
550 #endif /* SMARTCARD */
551
552 /* dispatch incoming messages */
553
554 static void
555 process_message(SocketEntry *e)
556 {
557         u_int msg_len;
558         u_int type;
559         u_char *cp;
560         if (buffer_len(&e->input) < 5)
561                 return;         /* Incomplete message. */
562         cp = buffer_ptr(&e->input);
563         msg_len = GET_32BIT(cp);
564         if (msg_len > 256 * 1024) {
565                 shutdown(e->fd, SHUT_RDWR);
566                 close(e->fd);
567                 e->type = AUTH_UNUSED;
568                 return;
569         }
570         if (buffer_len(&e->input) < msg_len + 4)
571                 return;
572         buffer_consume(&e->input, 4);
573         type = buffer_get_char(&e->input);
574
575         debug("type %d", type);
576         switch (type) {
577         /* ssh1 */
578         case SSH_AGENTC_RSA_CHALLENGE:
579                 process_authentication_challenge1(e);
580                 break;
581         case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
582                 process_request_identities(e, 1);
583                 break;
584         case SSH_AGENTC_ADD_RSA_IDENTITY:
585                 process_add_identity(e, 1);
586                 break;
587         case SSH_AGENTC_REMOVE_RSA_IDENTITY:
588                 process_remove_identity(e, 1);
589                 break;
590         case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
591                 process_remove_all_identities(e, 1);
592                 break;
593         /* ssh2 */
594         case SSH2_AGENTC_SIGN_REQUEST:
595                 process_sign_request2(e);
596                 break;
597         case SSH2_AGENTC_REQUEST_IDENTITIES:
598                 process_request_identities(e, 2);
599                 break;
600         case SSH2_AGENTC_ADD_IDENTITY:
601                 process_add_identity(e, 2);
602                 break;
603         case SSH2_AGENTC_REMOVE_IDENTITY:
604                 process_remove_identity(e, 2);
605                 break;
606         case SSH2_AGENTC_REMOVE_ALL_IDENTITIES:
607                 process_remove_all_identities(e, 2);
608                 break;
609 #ifdef SMARTCARD
610         case SSH_AGENTC_ADD_SMARTCARD_KEY:
611                 process_add_smartcard_key(e);
612                 break;
613         case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
614                 process_remove_smartcard_key(e);
615                 break;
616 #endif /* SMARTCARD */
617         default:
618                 /* Unknown message.  Respond with failure. */
619                 error("Unknown message %d", type);
620                 buffer_clear(&e->input);
621                 buffer_put_int(&e->output, 1);
622                 buffer_put_char(&e->output, SSH_AGENT_FAILURE);
623                 break;
624         }
625 }
626
627 static void
628 new_socket(sock_type type, int fd)
629 {
630         u_int i, old_alloc;
631         if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
632                 error("fcntl O_NONBLOCK: %s", strerror(errno));
633
634         if (fd > max_fd)
635                 max_fd = fd;
636
637         for (i = 0; i < sockets_alloc; i++)
638                 if (sockets[i].type == AUTH_UNUSED) {
639                         sockets[i].fd = fd;
640                         sockets[i].type = type;
641                         buffer_init(&sockets[i].input);
642                         buffer_init(&sockets[i].output);
643                         return;
644                 }
645         old_alloc = sockets_alloc;
646         sockets_alloc += 10;
647         if (sockets)
648                 sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0]));
649         else
650                 sockets = xmalloc(sockets_alloc * sizeof(sockets[0]));
651         for (i = old_alloc; i < sockets_alloc; i++)
652                 sockets[i].type = AUTH_UNUSED;
653         sockets[old_alloc].type = type;
654         sockets[old_alloc].fd = fd;
655         buffer_init(&sockets[old_alloc].input);
656         buffer_init(&sockets[old_alloc].output);
657 }
658
659 static int
660 prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, int *nallocp)
661 {
662         u_int i, sz;
663         int n = 0;
664
665         for (i = 0; i < sockets_alloc; i++) {
666                 switch (sockets[i].type) {
667                 case AUTH_SOCKET:
668                 case AUTH_CONNECTION:
669                         n = MAX(n, sockets[i].fd);
670                         break;
671                 case AUTH_UNUSED:
672                         break;
673                 default:
674                         fatal("Unknown socket type %d", sockets[i].type);
675                         break;
676                 }
677         }
678
679         sz = howmany(n+1, NFDBITS) * sizeof(fd_mask);
680         if (*fdrp == NULL || sz > *nallocp) {
681                 if (*fdrp)
682                         xfree(*fdrp);
683                 if (*fdwp)
684                         xfree(*fdwp);
685                 *fdrp = xmalloc(sz);
686                 *fdwp = xmalloc(sz);
687                 *nallocp = sz;
688         }
689         if (n < *fdl)
690                 debug("XXX shrink: %d < %d", n, *fdl);
691         *fdl = n;
692         memset(*fdrp, 0, sz);
693         memset(*fdwp, 0, sz);
694
695         for (i = 0; i < sockets_alloc; i++) {
696                 switch (sockets[i].type) {
697                 case AUTH_SOCKET:
698                 case AUTH_CONNECTION:
699                         FD_SET(sockets[i].fd, *fdrp);
700                         if (buffer_len(&sockets[i].output) > 0)
701                                 FD_SET(sockets[i].fd, *fdwp);
702                         break;
703                 default:
704                         break;
705                 }
706         }
707         return (1);
708 }
709
710 static void
711 after_select(fd_set *readset, fd_set *writeset)
712 {
713         u_int i;
714         int len, sock;
715         socklen_t slen;
716         char buf[1024];
717         struct sockaddr_un sunaddr;
718
719         for (i = 0; i < sockets_alloc; i++)
720                 switch (sockets[i].type) {
721                 case AUTH_UNUSED:
722                         break;
723                 case AUTH_SOCKET:
724                         if (FD_ISSET(sockets[i].fd, readset)) {
725                                 slen = sizeof(sunaddr);
726                                 sock = accept(sockets[i].fd,
727                                     (struct sockaddr *) &sunaddr, &slen);
728                                 if (sock < 0) {
729                                         perror("accept from AUTH_SOCKET");
730                                         break;
731                                 }
732                                 new_socket(AUTH_CONNECTION, sock);
733                         }
734                         break;
735                 case AUTH_CONNECTION:
736                         if (buffer_len(&sockets[i].output) > 0 &&
737                             FD_ISSET(sockets[i].fd, writeset)) {
738                                 do {
739                                         len = write(sockets[i].fd,
740                                             buffer_ptr(&sockets[i].output),
741                                             buffer_len(&sockets[i].output));
742                                         if (len == -1 && (errno == EAGAIN ||
743                                             errno == EINTR))
744                                                 continue;
745                                         break;
746                                 } while (1);
747                                 if (len <= 0) {
748                                         shutdown(sockets[i].fd, SHUT_RDWR);
749                                         close(sockets[i].fd);
750                                         sockets[i].type = AUTH_UNUSED;
751                                         buffer_free(&sockets[i].input);
752                                         buffer_free(&sockets[i].output);
753                                         break;
754                                 }
755                                 buffer_consume(&sockets[i].output, len);
756                         }
757                         if (FD_ISSET(sockets[i].fd, readset)) {
758                                 do {
759                                         len = read(sockets[i].fd, buf, sizeof(buf));
760                                         if (len == -1 && (errno == EAGAIN ||
761                                             errno == EINTR))
762                                                 continue;
763                                         break;
764                                 } while (1);
765                                 if (len <= 0) {
766                                         shutdown(sockets[i].fd, SHUT_RDWR);
767                                         close(sockets[i].fd);
768                                         sockets[i].type = AUTH_UNUSED;
769                                         buffer_free(&sockets[i].input);
770                                         buffer_free(&sockets[i].output);
771                                         break;
772                                 }
773                                 buffer_append(&sockets[i].input, buf, len);
774                                 process_message(&sockets[i]);
775                         }
776                         break;
777                 default:
778                         fatal("Unknown type %d", sockets[i].type);
779                 }
780 }
781
782 static void
783 cleanup_socket(void)
784 {
785         if (socket_name[0])
786                 unlink(socket_name);
787         if (socket_dir[0])
788                 rmdir(socket_dir);
789 }
790
791 static void
792 cleanup_exit(int i)
793 {
794         cleanup_socket();
795         exit(i);
796 }
797
798 static void
799 cleanup_handler(int sig)
800 {
801         cleanup_socket();
802         _exit(2);
803 }
804
805 static void
806 check_parent_exists(int sig)
807 {
808         int save_errno = errno;
809
810         if (parent_pid != -1 && kill(parent_pid, 0) < 0) {
811                 /* printf("Parent has died - Authentication agent exiting.\n"); */
812                 cleanup_handler(sig); /* safe */
813         }
814         signal(SIGALRM, check_parent_exists);
815         alarm(10);
816         errno = save_errno;
817 }
818
819 static void
820 usage(void)
821 {
822         fprintf(stderr, "Usage: %s [options] [command [args ...]]\n",
823             __progname);
824         fprintf(stderr, "Options:\n");
825         fprintf(stderr, "  -c          Generate C-shell commands on stdout.\n");
826         fprintf(stderr, "  -s          Generate Bourne shell commands on stdout.\n");
827         fprintf(stderr, "  -k          Kill the current agent.\n");
828         fprintf(stderr, "  -d          Debug mode.\n");
829         exit(1);
830 }
831
832 int
833 main(int ac, char **av)
834 {
835         int sock, c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, ch, nalloc;
836         struct sockaddr_un sunaddr;
837 #ifdef HAVE_SETRLIMIT
838         struct rlimit rlim;
839 #endif
840 #ifdef HAVE_CYGWIN
841         int prev_mask;
842 #endif
843         pid_t pid;
844         char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
845         extern int optind;
846         fd_set *readsetp = NULL, *writesetp = NULL;
847
848         SSLeay_add_all_algorithms();
849
850         __progname = get_progname(av[0]);
851         init_rng();
852         seed_rng();
853
854 #ifdef __GNU_LIBRARY__
855         while ((ch = getopt(ac, av, "+cdks")) != -1) {
856 #else /* __GNU_LIBRARY__ */
857         while ((ch = getopt(ac, av, "cdks")) != -1) {
858 #endif /* __GNU_LIBRARY__ */
859                 switch (ch) {
860                 case 'c':
861                         if (s_flag)
862                                 usage();
863                         c_flag++;
864                         break;
865                 case 'k':
866                         k_flag++;
867                         break;
868                 case 's':
869                         if (c_flag)
870                                 usage();
871                         s_flag++;
872                         break;
873                 case 'd':
874                         if (d_flag)
875                                 usage();
876                         d_flag++;
877                         break;
878                 default:
879                         usage();
880                 }
881         }
882         ac -= optind;
883         av += optind;
884
885         if (ac > 0 && (c_flag || k_flag || s_flag || d_flag))
886                 usage();
887
888         if (ac == 0 && !c_flag && !k_flag && !s_flag && !d_flag) {
889                 shell = getenv("SHELL");
890                 if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
891                         c_flag = 1;
892         }
893         if (k_flag) {
894                 pidstr = getenv(SSH_AGENTPID_ENV_NAME);
895                 if (pidstr == NULL) {
896                         fprintf(stderr, "%s not set, cannot kill agent\n",
897                             SSH_AGENTPID_ENV_NAME);
898                         exit(1);
899                 }
900                 pid = atoi(pidstr);
901                 if (pid < 1) {
902                         fprintf(stderr, "%s=\"%s\", which is not a good PID\n",
903                             SSH_AGENTPID_ENV_NAME, pidstr);
904                         exit(1);
905                 }
906                 if (kill(pid, SIGTERM) == -1) {
907                         perror("kill");
908                         exit(1);
909                 }
910                 format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
911                 printf(format, SSH_AUTHSOCKET_ENV_NAME);
912                 printf(format, SSH_AGENTPID_ENV_NAME);
913                 printf("echo Agent pid %d killed;\n", pid);
914                 exit(0);
915         }
916         parent_pid = getpid();
917
918         /* Create private directory for agent socket */
919         strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
920         if (mkdtemp(socket_dir) == NULL) {
921                 perror("mkdtemp: private socket dir");
922                 exit(1);
923         }
924         snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
925             parent_pid);
926
927         /*
928          * Create socket early so it will exist before command gets run from
929          * the parent.
930          */
931         sock = socket(AF_UNIX, SOCK_STREAM, 0);
932         if (sock < 0) {
933                 perror("socket");
934                 cleanup_exit(1);
935         }
936         memset(&sunaddr, 0, sizeof(sunaddr));
937         sunaddr.sun_family = AF_UNIX;
938         strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
939 #ifdef HAVE_CYGWIN
940         prev_mask = umask(0177);
941 #endif
942         if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
943                 perror("bind");
944 #ifdef HAVE_CYGWIN
945                 umask(prev_mask);
946 #endif
947                 cleanup_exit(1);
948         }
949 #ifdef HAVE_CYGWIN
950         umask(prev_mask);
951 #endif
952         if (listen(sock, 5) < 0) {
953                 perror("listen");
954                 cleanup_exit(1);
955         }
956
957         /*
958          * Fork, and have the parent execute the command, if any, or present
959          * the socket data.  The child continues as the authentication agent.
960          */
961         if (d_flag) {
962                 log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1);
963                 format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
964                 printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
965                     SSH_AUTHSOCKET_ENV_NAME);
966                 printf("echo Agent pid %d;\n", parent_pid);
967                 goto skip;
968         }
969         pid = fork();
970         if (pid == -1) {
971                 perror("fork");
972                 exit(1);
973         }
974         if (pid != 0) {         /* Parent - execute the given command. */
975                 close(sock);
976                 snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
977                 if (ac == 0) {
978                         format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
979                         printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
980                             SSH_AUTHSOCKET_ENV_NAME);
981                         printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
982                             SSH_AGENTPID_ENV_NAME);
983                         printf("echo Agent pid %d;\n", pid);
984                         exit(0);
985                 }
986                 if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 ||
987                     setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) {
988                         perror("setenv");
989                         exit(1);
990                 }
991                 execvp(av[0], av);
992                 perror(av[0]);
993                 exit(1);
994         }
995
996         if (setsid() == -1) {
997                 perror("setsid");
998                 cleanup_exit(1);
999         }
1000
1001         (void)chdir("/");
1002         close(0);
1003         close(1);
1004         close(2);
1005
1006 #ifdef HAVE_SETRLIMIT
1007         /* deny core dumps, since memory contains unencrypted private keys */
1008         rlim.rlim_cur = rlim.rlim_max = 0;
1009         if (setrlimit(RLIMIT_CORE, &rlim) < 0) {
1010                 perror("setrlimit rlimit_core failed");
1011                 cleanup_exit(1);
1012         }
1013 #endif
1014
1015 skip:
1016         if (atexit(cleanup_socket) < 0) {
1017                 perror("atexit");
1018                 cleanup_exit(1);
1019         }
1020         new_socket(AUTH_SOCKET, sock);
1021         if (ac > 0) {
1022                 signal(SIGALRM, check_parent_exists);
1023                 alarm(10);
1024         }
1025         idtab_init();
1026         if (!d_flag)
1027                 signal(SIGINT, SIG_IGN);
1028         signal(SIGPIPE, SIG_IGN);
1029         signal(SIGHUP, cleanup_handler);
1030         signal(SIGTERM, cleanup_handler);
1031         nalloc = 0;
1032
1033         while (1) {
1034                 prepare_select(&readsetp, &writesetp, &max_fd, &nalloc);
1035                 if (select(max_fd + 1, readsetp, writesetp, NULL, NULL) < 0) {
1036                         if (errno == EINTR)
1037                                 continue;
1038                         exit(1);
1039                 }
1040                 after_select(readsetp, writesetp);
1041         }
1042         /* NOTREACHED */
1043 }
This page took 0.483758 seconds and 3 git commands to generate.