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