Import Upstream version 0.69.0
[hcoop/debian/courier-authlib.git] / authdaemond.c
CommitLineData
d9898ee8 1/*
0e333c05 2** Copyright 2000-2018 Double Precision, Inc. See COPYING for
d9898ee8 3** distribution information.
4*/
5
6#include "courier_auth_config.h"
7#include <sys/types.h>
8#include <sys/stat.h>
9#include <sys/socket.h>
10#include <sys/un.h>
11#include <sys/time.h>
12#include <sys/wait.h>
13#include <unistd.h>
14#include <stdlib.h>
15#include <stdio.h>
16#include <errno.h>
17#include <signal.h>
18#include <fcntl.h>
19#include <ctype.h>
20#include "numlib/numlib.h"
d9898ee8 21#include "liblock/liblock.h"
22#include "auth.h"
23#include "authdaemonrc.h"
24#include "courierauthdebug.h"
25#include "pkglibdir.h"
0e333c05 26#include "courierauth.h"
b0322a85 27#include "courierauthstaticlist.h"
ac40fd9e 28#include "libhmac/hmac.h"
d9898ee8 29#include <ltdl.h>
30
d9898ee8 31
32#ifndef SOMAXCONN
33#define SOMAXCONN 5
34#endif
35
b0322a85 36#include "courierauthstaticlist.h"
d9898ee8 37
38static unsigned ndaemons;
39
40struct authstaticinfolist {
41 struct authstaticinfolist *next;
42 struct authstaticinfo *info;
43 lt_dlhandle h;
44};
45
46static struct authstaticinfolist *modulelist=NULL;
47
48static int mksocket()
49{
50int fd=socket(PF_UNIX, SOCK_STREAM, 0);
51struct sockaddr_un skun;
52
53 if (fd < 0) return (-1);
54 skun.sun_family=AF_UNIX;
55 strcpy(skun.sun_path, AUTHDAEMONSOCK);
56 strcat(skun.sun_path, ".tmp");
57 unlink(skun.sun_path);
58 if (bind(fd, (const struct sockaddr *)&skun, sizeof(skun)) ||
0e333c05
CE
59 listen(fd, SOMAXCONN) ||
60 chmod(skun.sun_path, 0777) ||
61 rename(skun.sun_path, AUTHDAEMONSOCK) ||
62 fcntl(fd, F_SETFD, FD_CLOEXEC) < 0 ||
63 fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
d9898ee8 64 {
65 perror(AUTHDAEMONSOCK);
66 close(fd);
67 return (-1);
68 }
69 return (fd);
70}
71
72
73static int initmodules(const char *p)
74{
75 char buf[100];
76 char buf2[100];
77 struct authstaticinfolist **modptr= &modulelist;
78 struct authstaticinfolist *m;
79
80 if (ndaemons <= 0)
81 {
82 ndaemons=1;
83
84 fprintf(stderr, "ERR: Configuration error - missing 'daemons' setting, using %u\n",
85 ndaemons);
86 }
87
88 while ((m=modulelist) != NULL)
89 {
90 modulelist=m->next;
91 fprintf(stderr, "INFO: Uninstalling %s\n",
92 m->info->auth_name);
93 lt_dlclose(m->h);
94 free(m);
95 }
96
97 while (p && *p)
98 {
99 size_t i;
100 lt_dlhandle h;
101 lt_ptr pt;
102 struct authstaticinfo *a;
103
104 if (isspace((int)(unsigned char)*p))
105 {
106 ++p;
107 continue;
108 }
109
110 for (i=0; p[i] && !isspace((int)(unsigned char)p[i]); ++i)
111 ;
112
113 strcpy(buf, "lib");
114 strncat(buf, p, i>40 ? 40:i);
115
116 fprintf(stderr, "INFO: Installing %s\n", buf);
117 p += i;
118 h=lt_dlopenext(buf);
119
120 if (h == NULL)
121 {
122 fprintf(stderr, "INFO: %s\n", lt_dlerror());
123 continue;
124 }
125
126 sprintf(buf2, "courier_%s_init", buf+3);
127
128 pt=lt_dlsym(h, buf2);
129 if (pt == NULL)
130 {
131 fprintf(stderr,
132 "ERR: Can't locate init function %s.\n",
133 buf2);
134 fprintf(stderr, "ERR: %s\n", lt_dlerror());
135 continue;
136 }
137
138 a= (*(struct authstaticinfo *(*)(void))pt)();
139
140 if ((m=malloc(sizeof(*modulelist))) == NULL)
141 {
142 perror("ERR");
143 lt_dlclose(h);
144 continue;
145 }
146 *modptr=m;
147 m->next=NULL;
148 m->info=a;
149 m->h=h;
150 modptr= &m->next;
151 fprintf(stderr, "INFO: Installation complete: %s\n",
152 a->auth_name);
153 }
154 return (0);
155}
156
157static int readconfig()
158{
159 char buf[BUFSIZ];
160 FILE *fp;
161 char *modlist=0;
162 unsigned daemons=0;
163
164 if ((fp=fopen(AUTHDAEMONRC, "r")) == NULL)
165 {
166 perror(AUTHDAEMONRC);
167 return (-1);
168 }
169
170 while (fgets(buf, sizeof(buf), fp))
171 {
172 char *p=strchr(buf, '\n'), *q;
173
174 if (!p)
175 {
176 int c;
177
178 while ((c=getc(fp)) >= 0 && c != '\n')
179 ;
180 }
181 else *p=0;
182 if ((p=strchr(buf, '#')) != 0) *p=0;
183
184 for (p=buf; *p; p++)
185 if (!isspace((int)(unsigned char)*p))
186 break;
187 if (*p == 0) continue;
188
189 if ((p=strchr(buf, '=')) == 0)
190 {
191 fprintf(stderr, "ERR: Bad line in %s: %s\n",
192 AUTHDAEMONRC, buf);
193 fclose(fp);
194 if (modlist)
195 free(modlist);
196 return (-1);
197 }
198 *p++=0;
199 while (*p && isspace((int)(unsigned char)*p))
200 ++p;
201 if (*p == '"')
202 {
203 ++p;
204 q=strchr(p, '"');
205 if (q) *q=0;
206 }
207 if (strcmp(buf, "authmodulelist") == 0)
208 {
209 if (modlist)
210 free(modlist);
211 modlist=strdup(p);
212 if (!modlist)
213 {
214 perror("malloc");
215 fclose(fp);
216 return (-1);
217 }
218 continue;
219 }
220 if (strcmp(buf, "daemons") == 0)
221 {
222 daemons=atoi(p);
223 continue;
224 }
225 }
226 fclose(fp);
227
228 fprintf(stderr, "INFO: modules=\"%s\", daemons=%u\n",
229 modlist ? modlist:"(none)",
230 daemons);
231 ndaemons=daemons;
232 return (initmodules(modlist));
233}
234
235static char buf[BUFSIZ];
236static char *readptr;
237static int readleft;
238static char *writeptr;
239static int writeleft;
240
241static int getauthc(int fd)
242{
243fd_set fds;
244struct timeval tv;
245
246 if (readleft--)
247 return ( (int)(unsigned char)*readptr++ );
248
249 readleft=0;
250 FD_ZERO(&fds);
251 FD_SET(fd, &fds);
252 tv.tv_sec=10;
253 tv.tv_usec=0;
254 if (select(fd+1, &fds, 0, 0, &tv) <= 0 ||
255 !FD_ISSET(fd, &fds))
256 return (EOF);
257 readleft=read(fd, buf, sizeof(buf));
258 readptr=buf;
259 if (readleft <= 0)
260 {
261 readleft=0;
262 return (EOF);
263 }
264 --readleft;
265 return ( (int)(unsigned char)*readptr++ );
266}
267
268static int writeauth(int fd, const char *p, unsigned pl)
269{
270fd_set fds;
271struct timeval tv;
272
273 while (pl)
274 {
275 int n;
276
277 FD_ZERO(&fds);
278 FD_SET(fd, &fds);
279 tv.tv_sec=30;
280 tv.tv_usec=0;
281 if (select(fd+1, 0, &fds, 0, &tv) <= 0 ||
282 !FD_ISSET(fd, &fds))
283 return (-1);
284 n=write(fd, p, pl);
285 if (n <= 0) return (-1);
286 p += n;
287 pl -= n;
288 }
289 return (0);
290}
291
292static int writeauthflush(int fd)
293{
294 if (writeptr > buf)
295 {
296 if (writeauth(fd, buf, writeptr - buf))
297 return (-1);
298 }
299 writeptr=buf;
300 writeleft=sizeof(buf);
301 return (0);
302}
303
304static int writeauthbuf(int fd, const char *p, unsigned pl)
305{
306unsigned n;
307
308 while (pl)
309 {
310 if (pl < writeleft)
311 {
312 memcpy(writeptr, p, pl);
313 writeptr += pl;
314 writeleft -= pl;
315 return (0);
316 }
317
318 if (writeauthflush(fd)) return (-1);
319
320 n=pl;
321 if (n > writeleft) n=writeleft;
322 memcpy(writeptr, p, n);
323 p += n;
324 writeptr += n;
325 writeleft -= n;
326 pl -= n;
327 }
328 return (0);
329}
330
331static int writeenvval(int fd, const char *env, const char *val)
332{
333 if (writeauthbuf(fd, env, strlen(env)) ||
334 writeauthbuf(fd, "=", 1) ||
335 writeauthbuf(fd, val, strlen(val)) ||
336 writeauthbuf(fd, "\n", 1))
337 return (-1);
338 return (0);
339}
340
341static const char *findopt(const char *options, const char *keyword)
342{
343 size_t keyword_l=strlen(keyword);
344
345 while (options)
346 {
347 if (strncmp(options, keyword, keyword_l) == 0)
348 {
349 switch (options[keyword_l])
350 {
351 case '=':
352 return options + keyword_l + 1;
353 case ',': case '\0':
354 return options + keyword_l;
355 }
356 }
357 options=strchr(options, ',');
358 if (options)
359 ++options;
360 }
361 return NULL;
362}
363
364/* Returns a malloc'd string containing the merge of the options string
365 and any default options which apply, or NULL if no options at all */
366static char *mergeoptions(const char *options)
367{
368 char *defoptions = getenv("DEFAULTOPTIONS");
369 char *p;
370
371 if (options && *options && defoptions && *defoptions)
372 {
373 char *result = malloc(strlen(options) +
374 strlen(defoptions) + 2);
375 if (!result)
376 {
377 perror("malloc");
378 return NULL;
379 }
380 strcpy(result, options);
381
382 defoptions = strdup(defoptions);
383 if (!defoptions)
384 {
385 perror("malloc");
386 free(result);
387 return NULL;
388 }
389
390 for (p = strtok(defoptions, ","); p; p = strtok(0, ","))
391 {
392 char *q = strchr(p, '=');
393 if (q) *q = '\0';
394 if (findopt(result, p)) continue;
395 if (q) *q = '=';
396 strcat(result, ",");
397 strcat(result, p);
398 }
399 free(defoptions);
400 return result;
401 }
402 else if (options && *options)
403 {
404 return strdup(options);
405 }
406 else if (defoptions && *defoptions)
407 {
408 return strdup(defoptions);
409 }
410 else
411 return 0;
412}
413
414static int printauth(struct authinfo *authinfo, void *vp)
415{
416 int fd= *(int *)vp;
417 char buf2[NUMBUFSIZE];
418 char *fullopt;
419
420 writeptr=buf;
421 writeleft=sizeof(buf);
422
423 courier_authdebug_authinfo("Authenticated: ", authinfo,
424 authinfo->clearpasswd,
425 authinfo->passwd);
426
427 if (authinfo->sysusername)
428 if (writeenvval(fd, "USERNAME", authinfo->sysusername))
429 return (1);
430 if (authinfo->sysuserid)
431 if (writeenvval(fd, "UID", libmail_str_uid_t(*authinfo->sysuserid,
432 buf2)))
433 return (1);
434 if (writeenvval(fd, "GID", libmail_str_uid_t(authinfo->sysgroupid, buf2)))
435 return (1);
436
437 if (writeenvval(fd, "HOME", authinfo->homedir))
438 return (1);
439 if (authinfo->address)
440 if (writeenvval(fd, "ADDRESS", authinfo->address))
441 return (1);
442 if (authinfo->fullname)
443 {
0e333c05
CE
444 /*
445 * Only the first field of the comma-seperated GECOS field is the
446 * full username.
d9898ee8 447 */
448 char *fullname;
449 char *p;
450 int retval;
451
452 fullname=strdup(authinfo->fullname);
453 if(fullname == NULL)
454 {
455 perror("strdup");
456 return (1);
457 }
458
459 p = fullname;
460 while (*p != ',' && *p != '\0')
461 p++;
0e333c05 462 *p=0;
d9898ee8 463 retval = writeenvval(fd, "NAME", fullname);
464 free(fullname);
465 if(retval)
466 return (1);
467 }
468 if (authinfo->maildir)
469 if (writeenvval(fd, "MAILDIR", authinfo->maildir))
470 return (1);
471 if (authinfo->quota)
472 if (writeenvval(fd, "QUOTA", authinfo->quota))
473 return (1);
474 if (authinfo->passwd)
475 if (writeenvval(fd, "PASSWD", authinfo->passwd))
476 return (1);
477 if (authinfo->clearpasswd)
478 if (writeenvval(fd, "PASSWD2", authinfo->clearpasswd))
479 return (1);
480 fullopt = mergeoptions(authinfo->options);
481 if (fullopt)
482 {
483 int rc = writeenvval(fd, "OPTIONS", fullopt);
484 free(fullopt);
485 if (rc)
486 return (1);
487 }
488 if (writeauthbuf(fd, ".\n", 2) || writeauthflush(fd))
489 return (1);
490 return (0);
491}
492
493static void pre(int fd, char *prebuf)
494{
495char *p=strchr(prebuf, ' ');
496char *service;
497struct authstaticinfolist *l;
498
499 if (!p) return;
500 *p++=0;
501 while (*p == ' ') ++p;
502 service=p;
503 p=strchr(p, ' ');
504 if (!p) return;
505 *p++=0;
506 while (*p == ' ') ++p;
507
508 DPRINTF("received userid lookup request: %s", p);
509
510 for (l=modulelist; l; l=l->next)
511 {
512 struct authstaticinfo *auth=l->info;
513 const char *modname = auth->auth_name;
514 int rc;
515
516 if (strcmp(prebuf, ".") && strcmp(prebuf, modname))
517 continue;
518
519 DPRINTF("%s: trying this module", modname);
520
521
522 rc=(*auth->auth_prefunc)(p, service,
523 &printauth, &fd);
524
525 if (rc == 0)
526 return;
527
528 if (rc > 0)
529 {
530 DPRINTF("%s: TEMPFAIL - no more modules will be tried",
531 modname);
532 return; /* Temporary error */
533 }
534 DPRINTF("%s: REJECT - try next module", modname);
535 }
536 writeauth(fd, "FAIL\n", 5);
537 DPRINTF("FAIL, all modules rejected");
538}
539
540struct enumerate_info {
541 int fd;
542 char *buf_ptr;
543 size_t buf_left;
544 char buffer[BUFSIZ];
545 int enumerate_ok;
546};
547
548static void enumflush(struct enumerate_info *ei)
549{
550 if (ei->buf_ptr > ei->buffer)
551 writeauth(ei->fd, ei->buffer, ei->buf_ptr - ei->buffer);
552 ei->buf_ptr=ei->buffer;
553 ei->buf_left=sizeof(ei->buffer);
554}
555
556static void enumwrite(struct enumerate_info *ei, const char *s)
557{
558 while (s && *s)
559 {
560 size_t l;
561
562 if (ei->buf_left == 0)
563 enumflush(ei);
564
565 l=strlen(s);
566 if (l > ei->buf_left)
567 l=ei->buf_left;
568 memcpy(ei->buf_ptr, s, l);
569 ei->buf_ptr += l;
570 ei->buf_left -= l;
571 s += l;
572 }
573}
574
575static void enum_cb(const char *name,
576 uid_t uid,
577 gid_t gid,
578 const char *homedir,
579 const char *maildir,
580 const char *options,
581 void *void_arg)
582{
583 struct enumerate_info *ei=(struct enumerate_info *)void_arg;
584 char buf[NUMBUFSIZE];
585 char *fullopt;
586
587 if (name == NULL)
588 {
589 ei->enumerate_ok=1;
590 return;
591 }
592
593 enumwrite(ei, name);
594 enumwrite(ei, "\t");
595 enumwrite(ei, libmail_str_uid_t(uid, buf));
596 enumwrite(ei, "\t");
597 enumwrite(ei, libmail_str_gid_t(gid, buf));
598 enumwrite(ei, "\t");
599 enumwrite(ei, homedir);
600 enumwrite(ei, "\t");
601 enumwrite(ei, maildir ? maildir : "");
602 enumwrite(ei, "\t");
603 fullopt = mergeoptions(options);
604 if (fullopt)
605 {
606 enumwrite(ei, fullopt);
607 free (fullopt);
608 }
609 enumwrite(ei, "\n");
610}
611
612static void enumerate(int fd)
613{
614 struct enumerate_info ei;
615 struct authstaticinfolist *l;
616
617 ei.fd=fd;
0e333c05 618 ei.buf_ptr=ei.buffer;
d9898ee8 619 ei.buf_left=0;
620
621 for (l=modulelist; l; l=l->next)
622 {
623 struct authstaticinfo *auth=l->info;
624
625 if (auth->auth_enumerate == NULL)
626 continue;
627
628 enumwrite(&ei, "# ");
629 enumwrite(&ei, auth->auth_name);
630 enumwrite(&ei, "\n\n");
631 ei.enumerate_ok=0;
632 (*auth->auth_enumerate)(enum_cb, &ei);
633 if (!ei.enumerate_ok)
634 {
635 enumflush(&ei);
636 DPRINTF("enumeration terminated prematurely in module %s",
637 auth->auth_name);
638 return;
639 }
640 }
641 enumwrite(&ei, ".\n");
642 enumflush(&ei);
643}
644
645static void dopasswd(int, const char *, const char *, const char *,
646 const char *);
647
648static void passwd(int fd, char *prebuf)
649{
650 char *p;
651 const char *service;
652 const char *userid;
653 const char *opwd;
654 const char *npwd;
655
656 for (p=prebuf; *p; p++)
657 {
658 if (*p == '\t')
659 continue;
660 if ((int)(unsigned char)*p < ' ')
661 {
662 writeauth(fd, "FAIL\n", 5);
663 return;
664 }
665 }
666
667 service=prebuf;
668
669 if ((p=strchr(service, '\t')) != 0)
670 {
671 *p++=0;
672 userid=p;
673 if ((p=strchr(p, '\t')) != 0)
674 {
675 *p++=0;
676 opwd=p;
677 if ((p=strchr(p, '\t')) != 0)
678 {
679 *p++=0;
680 npwd=p;
681 if ((p=strchr(p, '\t')) != 0)
682 *p=0;
683 dopasswd(fd, service, userid, opwd, npwd);
684 return;
685 }
686 }
687 }
688}
689
690static void dopasswd(int fd,
691 const char *service,
692 const char *userid,
693 const char *opwd,
694 const char *npwd)
695{
696struct authstaticinfolist *l;
697
698
699 for (l=modulelist; l; l=l->next)
700 {
701 struct authstaticinfo *auth=l->info;
702 int rc;
703
704 int (*f)(const char *, const char *, const char *,
705 const char *)=
706 auth->auth_changepwd;
707
708 if (!f)
709 continue;
710
711 rc= (*f)(service, userid, opwd, npwd);
712
713 if (rc == 0)
714 {
715 writeauth(fd, "OK\n", 3);
716 return;
717 }
718 if (rc > 0)
719 break;
720 }
721 writeauth(fd, "FAIL\n", 5);
722}
723
724static void auth(int fd, char *p)
725{
726 char *service;
727 char *authtype;
728 char *pp;
729 struct authstaticinfolist *l;
730
731 service=p;
732 if ((p=strchr(p, '\n')) == 0) return;
733 *p++=0;
734 authtype=p;
735 if ((p=strchr(p, '\n')) == 0) return;
736 *p++=0;
737
738 pp=malloc(strlen(p)+1);
739 if (!pp)
740 {
741 perror("CRIT: malloc() failed");
742 return;
743 }
744
745 DPRINTF("received auth request, service=%s, authtype=%s", service, authtype);
746 for (l=modulelist; l; l=l->next)
747 {
748 struct authstaticinfo *auth=l->info;
749 const char *modname = auth->auth_name;
750 int rc;
751
752 DPRINTF("%s: trying this module", modname);
753
754 rc=(*auth->auth_func)(service, authtype,
755 strcpy(pp, p),
756 &printauth, &fd);
757
758 if (rc == 0)
759 {
760 free(pp);
761 return;
762 }
763
764 if (rc > 0)
765 {
766 DPRINTF("%s: TEMPFAIL - no more modules will be tried", modname);
767 free(pp);
768 return; /* Temporary error */
769 }
770 DPRINTF("%s: REJECT - try next module", modname);
771 }
772 DPRINTF("FAIL, all modules rejected");
773 writeauth(fd, "FAIL\n", 5);
774 free(pp);
775}
776
777static void idlefunc()
778{
779 struct authstaticinfolist *l;
780
781 for (l=modulelist; l; l=l->next)
782 {
783 struct authstaticinfo *auth=l->info;
784
785 if (auth->auth_idle)
786 (*auth->auth_idle)();
787 }
788}
789
790static void doauth(int fd)
791{
792char buf[BUFSIZ];
793int i, ch;
794char *p;
795
796 readleft=0;
797 for (i=0; (ch=getauthc(fd)) != '\n'; i++)
798 {
799 if (ch < 0 || i >= sizeof(buf)-2)
800 return;
801 buf[i]=ch;
802 }
803 buf[i]=0;
804
805 for (p=buf; *p; p++)
806 {
807 if (*p == ' ')
808 {
809 *p++=0;
810 while (*p == ' ') ++p;
811 break;
812 }
813 }
814
815 if (strcmp(buf, "PRE") == 0)
816 {
817 pre(fd, p);
818 return;
819 }
820
821 if (strcmp(buf, "PASSWD") == 0)
822 {
823 passwd(fd, p);
824 return;
825 }
826
827 if (strcmp(buf, "AUTH") == 0)
828 {
829 int j;
830
831 i=atoi(p);
832 if (i < 0 || i >= sizeof(buf)) return;
833 for (j=0; j<i; j++)
834 {
835 ch=getauthc(fd);
836 if (ch < 0) return;
837 buf[j]=ch;
838 }
839 buf[j]=0;
840 auth(fd, buf);
841 }
842
843 if (strcmp(buf, "ENUMERATE") == 0)
844 {
845 enumerate(fd);
846 }
847}
848
849static int sighup_pipe= -1;
850
8d138742 851static void sighup(int n)
d9898ee8 852{
853 if (sighup_pipe >= 0)
854 {
855 close(sighup_pipe);
856 sighup_pipe= -1;
857 }
858 signal(SIGHUP, sighup);
d9898ee8 859}
860
861static int sigterm_received=0;
862
8d138742 863static void sigterm(int n)
d9898ee8 864{
865 sigterm_received=1;
866 if (sighup_pipe >= 0)
867 {
868 close(sighup_pipe);
869 sighup_pipe= -1;
870 }
871 else
872 {
873 kill(0, SIGTERM);
874 _exit(0);
875 }
d9898ee8 876}
877
878static int startchildren(int *pipefd)
879{
880unsigned i;
881pid_t p;
882
883 signal(SIGCHLD, sighup);
884 for (i=0; i<ndaemons; i++)
885 {
886 p=fork();
887 while (p == -1)
888 {
889 perror("CRIT: fork() failed");
890 sleep(5);
891 p=fork();
892 }
893 if (p == 0)
894 {
895 sighup_pipe= -1;
896 close(pipefd[1]);
897 signal(SIGHUP, SIG_DFL);
898 signal(SIGTERM, SIG_DFL);
899 signal(SIGCHLD, SIG_DFL);
900 return (1);
901 }
902 }
903 return (0);
904}
905
906static int killchildren(int *pipefd)
907{
908int waitstat;
909
910 while (wait(&waitstat) >= 0 || errno != ECHILD)
911 ;
912
913 if (pipe(pipefd))
914 {
915 perror("CRIT: pipe() failed");
916 return (-1);
917 }
918
919 return (0);
920}
921
922int start()
923{
924 int s;
925 int fd;
926 int pipefd[2];
927 int do_child;
928
929 for (fd=3; fd<256; fd++)
930 close(fd);
931
932 if (pipe(pipefd))
933 {
934 perror("pipe");
935 return (1);
936 }
937
938 if (lt_dlinit())
939 {
940 fprintf(stderr, "ERR: lt_dlinit() failed: %s\n",
941 lt_dlerror());
942 exit(1);
943 }
944
945 if (lt_dlsetsearchpath(PKGLIBDIR))
946 {
947 fprintf(stderr, "ERR: lt_dlsetsearchpath() failed: %s\n",
948 lt_dlerror());
949 exit(1);
950 }
951
952 if (readconfig())
953 {
954 close(pipefd[0]);
955 close(pipefd[1]);
956 return (1);
957 }
958
959 s=mksocket();
960 if (s < 0)
961 {
962 perror(AUTHDAEMONSOCK);
963 close(pipefd[0]);
964 close(pipefd[1]);
965 return (1);
966 }
967
968 signal(SIGPIPE, SIG_IGN);
969 signal(SIGHUP, sighup);
970 signal(SIGTERM, sigterm);
971
972 close(0);
973 if (open("/dev/null", O_RDWR) != 0)
974 {
975 perror("open");
976 exit(1);
977 }
978 dup2(0, 1);
979 sighup_pipe= pipefd[1];
980
981 do_child=startchildren(pipefd);
982
983 for (;;)
984 {
985 struct sockaddr saddr;
986 socklen_t saddr_len;
987 fd_set fds;
988 struct timeval tv;
989
990 FD_ZERO(&fds);
991 FD_SET(pipefd[0], &fds);
992
993 if (do_child)
994 FD_SET(s, &fds);
995
996 tv.tv_sec=300;
997 tv.tv_usec=0;
998
999 if (select( (s > pipefd[0] ? s:pipefd[0])+1,
1000 &fds, 0, 0, &tv) < 0)
1001 continue;
1002 if (FD_ISSET(pipefd[0], &fds))
1003 {
1004 close(pipefd[0]);
1005 if (do_child)
1006 return (0); /* Parent died */
1007 fprintf(stderr, "INFO: stopping authdaemond children\n");
1008 while (killchildren(pipefd))
1009 sleep(5);
1010 if (sigterm_received)
1011 return (0);
1012 fprintf(stderr, "INFO: restarting authdaemond children\n");
1013 readconfig();
1014 sighup_pipe=pipefd[1];
1015 do_child=startchildren(pipefd);
1016 continue;
1017 }
1018
1019 if (!FD_ISSET(s, &fds))
1020 {
1021 idlefunc();
1022 continue;
1023 }
1024
1025 saddr_len=sizeof(saddr);
1026 if ((fd=accept(s, &saddr, &saddr_len)) < 0)
1027 continue;
0e333c05
CE
1028 if (fcntl(fd, F_SETFL, 0) < 0 ||
1029 fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
d9898ee8 1030 {
1031 perror("CRIT: fcntl() failed");
1032 }
1033 else
1034 doauth(fd);
1035 close(fd);
1036 }
1037}