blob: 296bb4c762739147e8f9ae3e9e8054e8a5e3039d [file] [log] [blame]
Damien Miller23b78391999-11-19 08:25:48 +11001/* $OpenBSD: ssh-agent.c,v 1.19 1999/11/18 14:00:49 markus Exp $ */
Damien Miller792c5111999-10-29 09:47:09 +10002
Damien Millerd4a8b7e1999-10-27 13:42:43 +10003/*
4
5ssh-agent.c
6
7Author: Tatu Ylonen <ylo@cs.hut.fi>
8
9Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
10 All rights reserved
11
12Created: Wed Mar 29 03:46:59 1995 ylo
13
14The authentication agent program.
15
16*/
17
18#include "includes.h"
Damien Miller23b78391999-11-19 08:25:48 +110019RCSID("$OpenBSD: ssh-agent.c,v 1.19 1999/11/18 14:00:49 markus Exp $");
Damien Millerd4a8b7e1999-10-27 13:42:43 +100020
21#include "ssh.h"
22#include "rsa.h"
23#include "authfd.h"
24#include "buffer.h"
25#include "bufaux.h"
26#include "xmalloc.h"
27#include "packet.h"
28#include "getput.h"
29#include "mpaux.h"
30
Damien Miller7f6ea021999-10-28 13:25:17 +100031#ifdef HAVE_OPENSSL
Damien Millerd4a8b7e1999-10-27 13:42:43 +100032#include <openssl/md5.h>
Damien Miller7f6ea021999-10-28 13:25:17 +100033#endif
34#ifdef HAVE_SSL
35#include <ssl/md5.h>
36#endif
Damien Millerd4a8b7e1999-10-27 13:42:43 +100037
Damien Miller3f905871999-11-15 17:10:57 +110038#ifdef HAVE___PROGNAME
39extern char *__progname;
40#else /* HAVE___PROGNAME */
41const char *__progname = "ssh-agent";
42#endif /* HAVE___PROGNAME */
43
Damien Millerd4a8b7e1999-10-27 13:42:43 +100044typedef struct
45{
46 int fd;
47 enum { AUTH_UNUSED, AUTH_SOCKET, AUTH_CONNECTION } type;
48 Buffer input;
49 Buffer output;
50} SocketEntry;
51
52unsigned int sockets_alloc = 0;
53SocketEntry *sockets = NULL;
54
55typedef struct
56{
57 RSA *key;
58 char *comment;
59} Identity;
60
61unsigned int num_identities = 0;
62Identity *identities = NULL;
63
64int max_fd = 0;
65
66/* pid of shell == parent of agent */
67int parent_pid = -1;
68
69/* pathname and directory for AUTH_SOCKET */
70char socket_name[1024];
71char socket_dir[1024];
72
73void
74process_request_identity(SocketEntry *e)
75{
76 Buffer msg;
77 int i;
78
79 buffer_init(&msg);
80 buffer_put_char(&msg, SSH_AGENT_RSA_IDENTITIES_ANSWER);
81 buffer_put_int(&msg, num_identities);
82 for (i = 0; i < num_identities; i++)
83 {
84 buffer_put_int(&msg, BN_num_bits(identities[i].key->n));
85 buffer_put_bignum(&msg, identities[i].key->e);
86 buffer_put_bignum(&msg, identities[i].key->n);
87 buffer_put_string(&msg, identities[i].comment,
88 strlen(identities[i].comment));
89 }
90 buffer_put_int(&e->output, buffer_len(&msg));
91 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg));
92 buffer_free(&msg);
93}
94
95void
96process_authentication_challenge(SocketEntry *e)
97{
98 int i, pub_bits, len;
99 BIGNUM *pub_e, *pub_n, *challenge;
100 Buffer msg;
101 MD5_CTX md;
102 unsigned char buf[32], mdbuf[16], session_id[16];
103 unsigned int response_type;
104
105 buffer_init(&msg);
106 pub_e = BN_new();
107 pub_n = BN_new();
108 challenge = BN_new();
109 pub_bits = buffer_get_int(&e->input);
110 buffer_get_bignum(&e->input, pub_e);
111 buffer_get_bignum(&e->input, pub_n);
112 buffer_get_bignum(&e->input, challenge);
113 if (buffer_len(&e->input) == 0)
114 {
115 /* Compatibility code for old servers. */
116 memset(session_id, 0, 16);
117 response_type = 0;
118 }
119 else
120 {
121 /* New code. */
122 buffer_get(&e->input, (char *)session_id, 16);
123 response_type = buffer_get_int(&e->input);
124 }
125 for (i = 0; i < num_identities; i++)
126 if (pub_bits == BN_num_bits(identities[i].key->n) &&
127 BN_cmp(pub_e, identities[i].key->e) == 0 &&
128 BN_cmp(pub_n, identities[i].key->n) == 0)
129 {
130 /* Decrypt the challenge using the private key. */
131 rsa_private_decrypt(challenge, challenge, identities[i].key);
132
133 /* Compute the desired response. */
134 switch (response_type)
135 {
136 case 0: /* As of protocol 1.0 */
137 /* This response type is no longer supported. */
138 log("Compatibility with ssh protocol 1.0 no longer supported.");
139 buffer_put_char(&msg, SSH_AGENT_FAILURE);
140 goto send;
141
142 case 1: /* As of protocol 1.1 */
143 /* The response is MD5 of decrypted challenge plus session id. */
144 len = BN_num_bytes(challenge);
Damien Millerfd7c9111999-11-08 16:15:55 +1100145
146 if (len <= 0 || len > 32) {
147 fatal("process_authentication_challenge: "
148 "bad challenge length %d", len);
149 }
150
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000151 memset(buf, 0, 32);
152 BN_bn2bin(challenge, buf + 32 - len);
153 MD5_Init(&md);
154 MD5_Update(&md, buf, 32);
155 MD5_Update(&md, session_id, 16);
156 MD5_Final(mdbuf, &md);
157 break;
158
159 default:
160 fatal("process_authentication_challenge: bad response_type %d",
161 response_type);
162 break;
163 }
164
165 /* Send the response. */
166 buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE);
167 for (i = 0; i < 16; i++)
168 buffer_put_char(&msg, mdbuf[i]);
169
170 goto send;
171 }
172 /* Unknown identity. Send failure. */
173 buffer_put_char(&msg, SSH_AGENT_FAILURE);
174 send:
175 buffer_put_int(&e->output, buffer_len(&msg));
176 buffer_append(&e->output, buffer_ptr(&msg),
177 buffer_len(&msg));
178 buffer_free(&msg);
179 BN_clear_free(pub_e);
180 BN_clear_free(pub_n);
181 BN_clear_free(challenge);
182}
183
184void
185process_remove_identity(SocketEntry *e)
186{
187 unsigned int bits;
188 unsigned int i;
189 BIGNUM *dummy, *n;
190
191 dummy = BN_new();
192 n = BN_new();
193
194 /* Get the key from the packet. */
195 bits = buffer_get_int(&e->input);
196 buffer_get_bignum(&e->input, dummy);
197 buffer_get_bignum(&e->input, n);
Damien Miller7e8e8201999-11-16 13:37:16 +1100198
199 if (bits != BN_num_bits(n))
Damien Miller23b78391999-11-19 08:25:48 +1100200 error("Warning: keysize mismatch: actual %d, announced %d",
Damien Miller7e8e8201999-11-16 13:37:16 +1100201 BN_num_bits(n), bits);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000202
203 /* Check if we have the key. */
204 for (i = 0; i < num_identities; i++)
205 if (BN_cmp(identities[i].key->n, n) == 0)
206 {
207 /* We have this key. Free the old key. Since we don\'t want to leave
208 empty slots in the middle of the array, we actually free the
209 key there and copy data from the last entry. */
210 RSA_free(identities[i].key);
211 xfree(identities[i].comment);
212 if (i < num_identities - 1)
213 identities[i] = identities[num_identities - 1];
214 num_identities--;
215 BN_clear_free(dummy);
216 BN_clear_free(n);
217
218 /* Send success. */
219 buffer_put_int(&e->output, 1);
220 buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
221 return;
222 }
223 /* We did not have the key. */
224 BN_clear(dummy);
225 BN_clear(n);
226
227 /* Send failure. */
228 buffer_put_int(&e->output, 1);
229 buffer_put_char(&e->output, SSH_AGENT_FAILURE);
230}
231
232/* Removes all identities from the agent. */
233
234void
235process_remove_all_identities(SocketEntry *e)
236{
237 unsigned int i;
238
239 /* Loop over all identities and clear the keys. */
240 for (i = 0; i < num_identities; i++)
241 {
242 RSA_free(identities[i].key);
243 xfree(identities[i].comment);
244 }
245
246 /* Mark that there are no identities. */
247 num_identities = 0;
248
249 /* Send success. */
250 buffer_put_int(&e->output, 1);
251 buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
252 return;
253}
254
255/* Adds an identity to the agent. */
256
257void
258process_add_identity(SocketEntry *e)
259{
260 RSA *k;
261 int i;
262 BIGNUM *aux;
263 BN_CTX *ctx;
264
265 if (num_identities == 0)
266 identities = xmalloc(sizeof(Identity));
267 else
268 identities = xrealloc(identities, (num_identities + 1) * sizeof(Identity));
269
270 identities[num_identities].key = RSA_new();
271 k = identities[num_identities].key;
272 buffer_get_int(&e->input); /* bits */
273 k->n = BN_new();
274 buffer_get_bignum(&e->input, k->n);
275 k->e = BN_new();
276 buffer_get_bignum(&e->input, k->e);
277 k->d = BN_new();
278 buffer_get_bignum(&e->input, k->d);
279 k->iqmp = BN_new();
280 buffer_get_bignum(&e->input, k->iqmp);
281 /* SSH and SSL have p and q swapped */
282 k->q = BN_new();
283 buffer_get_bignum(&e->input, k->q); /* p */
284 k->p = BN_new();
285 buffer_get_bignum(&e->input, k->p); /* q */
286
287 /* Generate additional parameters */
288 aux = BN_new();
289 ctx = BN_CTX_new();
290
291 BN_sub(aux, k->q, BN_value_one());
292 k->dmq1 = BN_new();
293 BN_mod(k->dmq1, k->d, aux, ctx);
294
295 BN_sub(aux, k->p, BN_value_one());
296 k->dmp1 = BN_new();
297 BN_mod(k->dmp1, k->d, aux, ctx);
298
299 BN_clear_free(aux);
300 BN_CTX_free(ctx);
301
302 identities[num_identities].comment = buffer_get_string(&e->input, NULL);
303
304 /* Check if we already have the key. */
305 for (i = 0; i < num_identities; i++)
306 if (BN_cmp(identities[i].key->n, k->n) == 0)
307 {
308 /* We already have this key. Clear and free the new data and
309 return success. */
310 RSA_free(k);
311 xfree(identities[num_identities].comment);
312
313 /* Send success. */
314 buffer_put_int(&e->output, 1);
315 buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
316 return;
317 }
318
319 /* Increment the number of identities. */
320 num_identities++;
321
322 /* Send a success message. */
323 buffer_put_int(&e->output, 1);
324 buffer_put_char(&e->output, SSH_AGENT_SUCCESS);
325}
326
327void
328process_message(SocketEntry *e)
329{
330 unsigned int msg_len;
331 unsigned int type;
332 unsigned char *cp;
333 if (buffer_len(&e->input) < 5)
334 return; /* Incomplete message. */
335 cp = (unsigned char *)buffer_ptr(&e->input);
336 msg_len = GET_32BIT(cp);
337 if (msg_len > 256 * 1024)
338 {
339 shutdown(e->fd, SHUT_RDWR);
340 close(e->fd);
341 e->type = AUTH_UNUSED;
342 return;
343 }
344 if (buffer_len(&e->input) < msg_len + 4)
345 return;
346 buffer_consume(&e->input, 4);
347 type = buffer_get_char(&e->input);
348
349 switch (type)
350 {
351 case SSH_AGENTC_REQUEST_RSA_IDENTITIES:
352 process_request_identity(e);
353 break;
354 case SSH_AGENTC_RSA_CHALLENGE:
355 process_authentication_challenge(e);
356 break;
357 case SSH_AGENTC_ADD_RSA_IDENTITY:
358 process_add_identity(e);
359 break;
360 case SSH_AGENTC_REMOVE_RSA_IDENTITY:
361 process_remove_identity(e);
362 break;
363 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
364 process_remove_all_identities(e);
365 break;
366 default:
367 /* Unknown message. Respond with failure. */
368 error("Unknown message %d", type);
369 buffer_clear(&e->input);
370 buffer_put_int(&e->output, 1);
371 buffer_put_char(&e->output, SSH_AGENT_FAILURE);
372 break;
373 }
374}
375
376void
377new_socket(int type, int fd)
378{
379 unsigned int i, old_alloc;
380 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
381 error("fcntl O_NONBLOCK: %s", strerror(errno));
382
383 if (fd > max_fd)
384 max_fd = fd;
385
386 for (i = 0; i < sockets_alloc; i++)
387 if (sockets[i].type == AUTH_UNUSED)
388 {
389 sockets[i].fd = fd;
390 sockets[i].type = type;
391 buffer_init(&sockets[i].input);
392 buffer_init(&sockets[i].output);
393 return;
394 }
395 old_alloc = sockets_alloc;
396 sockets_alloc += 10;
397 if (sockets)
398 sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0]));
399 else
400 sockets = xmalloc(sockets_alloc * sizeof(sockets[0]));
401 for (i = old_alloc; i < sockets_alloc; i++)
402 sockets[i].type = AUTH_UNUSED;
403 sockets[old_alloc].type = type;
404 sockets[old_alloc].fd = fd;
405 buffer_init(&sockets[old_alloc].input);
406 buffer_init(&sockets[old_alloc].output);
407}
408
409void
410prepare_select(fd_set *readset, fd_set *writeset)
411{
412 unsigned int i;
413 for (i = 0; i < sockets_alloc; i++)
414 switch (sockets[i].type)
415 {
416 case AUTH_SOCKET:
417 case AUTH_CONNECTION:
418 FD_SET(sockets[i].fd, readset);
419 if (buffer_len(&sockets[i].output) > 0)
420 FD_SET(sockets[i].fd, writeset);
421 break;
422 case AUTH_UNUSED:
423 break;
424 default:
425 fatal("Unknown socket type %d", sockets[i].type);
426 break;
427 }
428}
429
430void after_select(fd_set *readset, fd_set *writeset)
431{
432 unsigned int i;
433 int len, sock;
434 char buf[1024];
435 struct sockaddr_un sunaddr;
436
437 for (i = 0; i < sockets_alloc; i++)
438 switch (sockets[i].type)
439 {
440 case AUTH_UNUSED:
441 break;
442 case AUTH_SOCKET:
443 if (FD_ISSET(sockets[i].fd, readset))
444 {
445 len = sizeof(sunaddr);
446 sock = accept(sockets[i].fd, (struct sockaddr *)&sunaddr, &len);
447 if (sock < 0)
448 {
449 perror("accept from AUTH_SOCKET");
450 break;
451 }
452 new_socket(AUTH_CONNECTION, sock);
453 }
454 break;
455 case AUTH_CONNECTION:
456 if (buffer_len(&sockets[i].output) > 0 &&
457 FD_ISSET(sockets[i].fd, writeset))
458 {
459 len = write(sockets[i].fd, buffer_ptr(&sockets[i].output),
460 buffer_len(&sockets[i].output));
461 if (len <= 0)
462 {
463 shutdown(sockets[i].fd, SHUT_RDWR);
464 close(sockets[i].fd);
465 sockets[i].type = AUTH_UNUSED;
466 break;
467 }
468 buffer_consume(&sockets[i].output, len);
469 }
470 if (FD_ISSET(sockets[i].fd, readset))
471 {
472 len = read(sockets[i].fd, buf, sizeof(buf));
473 if (len <= 0)
474 {
475 shutdown(sockets[i].fd, SHUT_RDWR);
476 close(sockets[i].fd);
477 sockets[i].type = AUTH_UNUSED;
478 break;
479 }
480 buffer_append(&sockets[i].input, buf, len);
481 process_message(&sockets[i]);
482 }
483 break;
484 default:
485 fatal("Unknown type %d", sockets[i].type);
486 }
487}
488
489void
490check_parent_exists(int sig)
491{
492 if (kill(parent_pid, 0) < 0)
493 {
494 /* printf("Parent has died - Authentication agent exiting.\n"); */
495 exit(1);
496 }
497 signal(SIGALRM, check_parent_exists);
498 alarm(10);
499}
500
Damien Miller792c5111999-10-29 09:47:09 +1000501void
502cleanup_socket(void)
503{
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000504 remove(socket_name);
505 rmdir(socket_dir);
506}
507
Damien Miller792c5111999-10-29 09:47:09 +1000508void
509cleanup_exit(int i)
510{
511 cleanup_socket();
512 exit(i);
513}
514
515void
516usage()
517{
Damien Miller792c5111999-10-29 09:47:09 +1000518 fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION);
519 fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n",
520 __progname);
521 exit(1);
522}
523
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000524int
525main(int ac, char **av)
526{
527 fd_set readset, writeset;
Damien Miller792c5111999-10-29 09:47:09 +1000528 int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000529 struct sockaddr_un sunaddr;
Damien Miller792c5111999-10-29 09:47:09 +1000530 pid_t pid;
531 char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid];
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000532
533 /* check if RSA support exists */
534 if (rsa_alive() == 0) {
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000535 fprintf(stderr,
536 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n",
537 __progname);
538 exit(1);
539 }
540
Damien Millerb77870f1999-11-10 12:48:08 +1100541#if defined(__GNU_LIBRARY__)
542 while ((ch = getopt(ac, av, "+cks")) != -1)
543#else
Damien Miller792c5111999-10-29 09:47:09 +1000544 while ((ch = getopt(ac, av, "cks")) != -1)
Damien Millerb77870f1999-11-10 12:48:08 +1100545#endif /* defined(__GNU_LIBRARY__) */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000546 {
Damien Miller792c5111999-10-29 09:47:09 +1000547 switch (ch)
548 {
549 case 'c':
550 if (s_flag)
551 usage();
552 c_flag++;
553 break;
554 case 'k':
555 k_flag++;
556 break;
557 case 's':
558 if (c_flag)
559 usage();
560 s_flag++;
561 break;
562 default:
563 usage();
564 }
565 }
566 ac -= optind;
567 av += optind;
568
569 if (ac > 0 && (c_flag || k_flag || s_flag))
570 usage();
571
572 if (ac == 0 && !c_flag && !k_flag && !s_flag)
573 {
574 shell = getenv("SHELL");
575 if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0)
576 c_flag = 1;
577 }
578
579 if (k_flag)
580 {
581 pidstr = getenv(SSH_AGENTPID_ENV_NAME);
582 if (pidstr == NULL)
583 {
584 fprintf(stderr, "%s not set, cannot kill agent\n",
585 SSH_AGENTPID_ENV_NAME);
586 exit(1);
587 }
588 pid = atoi(pidstr);
589 if (pid < 1) /* XXX PID_MAX check too */
590 {
591 fprintf(stderr, "%s=\"%s\", which is not a good PID\n",
592 SSH_AGENTPID_ENV_NAME, pidstr);
593 exit(1);
594 }
595 if (kill(pid, SIGTERM) == -1)
596 {
597 perror("kill");
598 exit(1);
599 }
600 format = c_flag ? "unsetenv %s;\n" : "unset %s;\n";
601 printf(format, SSH_AUTHSOCKET_ENV_NAME);
602 printf(format, SSH_AGENTPID_ENV_NAME);
603 printf("echo Agent pid %d killed;\n", pid);
604 exit(0);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000605 }
606
607 parent_pid = getpid();
608
609 /* Create private directory for agent socket */
610 strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir);
611 if (mkdtemp(socket_dir) == NULL) {
612 perror("mkdtemp: private socket dir");
613 exit(1);
614 }
Damien Miller792c5111999-10-29 09:47:09 +1000615 snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir,
616 parent_pid);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000617
Damien Miller792c5111999-10-29 09:47:09 +1000618 /* Create socket early so it will exist before command gets run from
619 the parent. */
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000620 sock = socket(AF_UNIX, SOCK_STREAM, 0);
621 if (sock < 0)
622 {
623 perror("socket");
Damien Miller792c5111999-10-29 09:47:09 +1000624 cleanup_exit(1);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000625 }
626 memset(&sunaddr, 0, sizeof(sunaddr));
627 sunaddr.sun_family = AF_UNIX;
628 strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
629 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0)
630 {
631 perror("bind");
Damien Miller792c5111999-10-29 09:47:09 +1000632 cleanup_exit(1);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000633 }
634 if (listen(sock, 5) < 0)
635 {
636 perror("listen");
Damien Miller792c5111999-10-29 09:47:09 +1000637 cleanup_exit(1);
638 }
639
640 /* Fork, and have the parent execute the command, if any, or present the
641 socket data. The child continues as the authentication agent. */
642 pid = fork();
643 if (pid == -1)
644 {
645 perror("fork");
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000646 exit(1);
647 }
Damien Miller792c5111999-10-29 09:47:09 +1000648 if (pid != 0)
649 { /* Parent - execute the given command. */
650 close(sock);
651 snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid);
652 if (ac == 0)
653 {
654 format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n";
655 printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name,
656 SSH_AUTHSOCKET_ENV_NAME);
657 printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf,
658 SSH_AGENTPID_ENV_NAME);
659 printf("echo Agent pid %d;\n", pid);
660 exit(0);
661 }
662
663 setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1);
664 setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1);
665 execvp(av[0], av);
666 perror(av[0]);
667 exit(1);
668 }
669
670 close(0);
671 close(1);
672 close(2);
673
Damien Miller1e4772c1999-10-30 11:39:56 +1000674 if (setsid() == -1)
675 {
676 perror("setsid");
677 cleanup_exit(1);
678 }
Damien Miller792c5111999-10-29 09:47:09 +1000679
680 if (atexit(cleanup_socket) < 0)
Damien Miller1e4772c1999-10-30 11:39:56 +1000681 {
682 perror("atexit");
683 cleanup_exit(1);
684 }
Damien Miller792c5111999-10-29 09:47:09 +1000685
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000686 new_socket(AUTH_SOCKET, sock);
Damien Miller792c5111999-10-29 09:47:09 +1000687 if (ac > 0)
688 {
689 signal(SIGALRM, check_parent_exists);
690 alarm(10);
691 }
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000692
693 signal(SIGINT, SIG_IGN);
Damien Miller792c5111999-10-29 09:47:09 +1000694 signal(SIGPIPE, SIG_IGN);
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000695 while (1)
696 {
697 FD_ZERO(&readset);
698 FD_ZERO(&writeset);
699 prepare_select(&readset, &writeset);
700 if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0)
701 {
702 if (errno == EINTR)
703 continue;
Damien Millerd4a8b7e1999-10-27 13:42:43 +1000704 exit(1);
705 }
706 after_select(&readset, &writeset);
707 }
708 /*NOTREACHED*/
709}