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