2 ** Copyright 2000-2008 Double Precision, Inc. See COPYING for
3 ** distribution information.
6 #include "courier_auth_config.h"
9 #include <sys/socket.h>
20 #include "numlib/numlib.h"
21 #include "liblock/liblock.h"
23 #include "authdaemonrc.h"
24 #include "courierauthdebug.h"
25 #include "pkglibdir.h"
26 #include "courierauthstaticlist.h"
27 #include "libhmac/hmac.h"
36 #include "courierauthstaticlist.h"
38 static unsigned ndaemons
;
40 struct authstaticinfolist
{
41 struct authstaticinfolist
*next
;
42 struct authstaticinfo
*info
;
46 static struct authstaticinfolist
*modulelist
=NULL
;
50 int fd
=socket(PF_UNIX
, SOCK_STREAM
, 0);
51 struct sockaddr_un skun
;
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
)) ||
59 listen(fd
, SOMAXCONN
) ||
60 chmod(skun
.sun_path
, 0777) ||
61 rename(skun
.sun_path
, AUTHDAEMONSOCK
) ||
62 fcntl(fd
, F_SETFL
, O_NONBLOCK
) < 0)
64 perror(AUTHDAEMONSOCK
);
72 static int initmodules(const char *p
)
76 struct authstaticinfolist
**modptr
= &modulelist
;
77 struct authstaticinfolist
*m
;
83 fprintf(stderr
, "ERR: Configuration error - missing 'daemons' setting, using %u\n",
87 while ((m
=modulelist
) != NULL
)
90 fprintf(stderr
, "INFO: Uninstalling %s\n",
101 struct authstaticinfo
*a
;
103 if (isspace((int)(unsigned char)*p
))
109 for (i
=0; p
[i
] && !isspace((int)(unsigned char)p
[i
]); ++i
)
113 strncat(buf
, p
, i
>40 ? 40:i
);
115 fprintf(stderr
, "INFO: Installing %s\n", buf
);
121 fprintf(stderr
, "INFO: %s\n", lt_dlerror());
125 sprintf(buf2
, "courier_%s_init", buf
+3);
127 pt
=lt_dlsym(h
, buf2
);
131 "ERR: Can't locate init function %s.\n",
133 fprintf(stderr
, "ERR: %s\n", lt_dlerror());
137 a
= (*(struct authstaticinfo
*(*)(void))pt
)();
139 if ((m
=malloc(sizeof(*modulelist
))) == NULL
)
150 fprintf(stderr
, "INFO: Installation complete: %s\n",
156 static int readconfig()
163 if ((fp
=fopen(AUTHDAEMONRC
, "r")) == NULL
)
165 perror(AUTHDAEMONRC
);
169 while (fgets(buf
, sizeof(buf
), fp
))
171 char *p
=strchr(buf
, '\n'), *q
;
177 while ((c
=getc(fp
)) >= 0 && c
!= '\n')
181 if ((p
=strchr(buf
, '#')) != 0) *p
=0;
184 if (!isspace((int)(unsigned char)*p
))
186 if (*p
== 0) continue;
188 if ((p
=strchr(buf
, '=')) == 0)
190 fprintf(stderr
, "ERR: Bad line in %s: %s\n",
198 while (*p
&& isspace((int)(unsigned char)*p
))
206 if (strcmp(buf
, "authmodulelist") == 0)
219 if (strcmp(buf
, "daemons") == 0)
227 fprintf(stderr
, "INFO: modules=\"%s\", daemons=%u\n",
228 modlist
? modlist
:"(none)",
231 return (initmodules(modlist
));
234 static char buf
[BUFSIZ
];
235 static char *readptr
;
237 static char *writeptr
;
238 static int writeleft
;
240 static int getauthc(int fd
)
246 return ( (int)(unsigned char)*readptr
++ );
253 if (select(fd
+1, &fds
, 0, 0, &tv
) <= 0 ||
256 readleft
=read(fd
, buf
, sizeof(buf
));
264 return ( (int)(unsigned char)*readptr
++ );
267 static int writeauth(int fd
, const char *p
, unsigned pl
)
280 if (select(fd
+1, 0, &fds
, 0, &tv
) <= 0 ||
284 if (n
<= 0) return (-1);
291 static int writeauthflush(int fd
)
295 if (writeauth(fd
, buf
, writeptr
- buf
))
299 writeleft
=sizeof(buf
);
303 static int writeauthbuf(int fd
, const char *p
, unsigned pl
)
311 memcpy(writeptr
, p
, pl
);
317 if (writeauthflush(fd
)) return (-1);
320 if (n
> writeleft
) n
=writeleft
;
321 memcpy(writeptr
, p
, n
);
330 static int writeenvval(int fd
, const char *env
, const char *val
)
332 if (writeauthbuf(fd
, env
, strlen(env
)) ||
333 writeauthbuf(fd
, "=", 1) ||
334 writeauthbuf(fd
, val
, strlen(val
)) ||
335 writeauthbuf(fd
, "\n", 1))
340 static const char *findopt(const char *options
, const char *keyword
)
342 size_t keyword_l
=strlen(keyword
);
346 if (strncmp(options
, keyword
, keyword_l
) == 0)
348 switch (options
[keyword_l
])
351 return options
+ keyword_l
+ 1;
353 return options
+ keyword_l
;
356 options
=strchr(options
, ',');
363 /* Returns a malloc'd string containing the merge of the options string
364 and any default options which apply, or NULL if no options at all */
365 static char *mergeoptions(const char *options
)
367 char *defoptions
= getenv("DEFAULTOPTIONS");
370 if (options
&& *options
&& defoptions
&& *defoptions
)
372 char *result
= malloc(strlen(options
) +
373 strlen(defoptions
) + 2);
379 strcpy(result
, options
);
381 defoptions
= strdup(defoptions
);
389 for (p
= strtok(defoptions
, ","); p
; p
= strtok(0, ","))
391 char *q
= strchr(p
, '=');
393 if (findopt(result
, p
)) continue;
401 else if (options
&& *options
)
403 return strdup(options
);
405 else if (defoptions
&& *defoptions
)
407 return strdup(defoptions
);
413 static int printauth(struct authinfo
*authinfo
, void *vp
)
416 char buf2
[NUMBUFSIZE
];
420 writeleft
=sizeof(buf
);
422 courier_authdebug_authinfo("Authenticated: ", authinfo
,
423 authinfo
->clearpasswd
,
426 if (authinfo
->sysusername
)
427 if (writeenvval(fd
, "USERNAME", authinfo
->sysusername
))
429 if (authinfo
->sysuserid
)
430 if (writeenvval(fd
, "UID", libmail_str_uid_t(*authinfo
->sysuserid
,
433 if (writeenvval(fd
, "GID", libmail_str_uid_t(authinfo
->sysgroupid
, buf2
)))
436 if (writeenvval(fd
, "HOME", authinfo
->homedir
))
438 if (authinfo
->address
)
439 if (writeenvval(fd
, "ADDRESS", authinfo
->address
))
441 if (authinfo
->fullname
)
444 * Only the first field of the comma-seperated GECOS field is the
451 fullname
=strdup(authinfo
->fullname
);
459 while (*p
!= ',' && *p
!= '\0')
462 retval
= writeenvval(fd
, "NAME", fullname
);
467 if (authinfo
->maildir
)
468 if (writeenvval(fd
, "MAILDIR", authinfo
->maildir
))
471 if (writeenvval(fd
, "QUOTA", authinfo
->quota
))
473 if (authinfo
->passwd
)
474 if (writeenvval(fd
, "PASSWD", authinfo
->passwd
))
476 if (authinfo
->clearpasswd
)
477 if (writeenvval(fd
, "PASSWD2", authinfo
->clearpasswd
))
479 fullopt
= mergeoptions(authinfo
->options
);
482 int rc
= writeenvval(fd
, "OPTIONS", fullopt
);
487 if (writeauthbuf(fd
, ".\n", 2) || writeauthflush(fd
))
492 static void pre(int fd
, char *prebuf
)
494 char *p
=strchr(prebuf
, ' ');
496 struct authstaticinfolist
*l
;
500 while (*p
== ' ') ++p
;
505 while (*p
== ' ') ++p
;
507 DPRINTF("received userid lookup request: %s", p
);
509 for (l
=modulelist
; l
; l
=l
->next
)
511 struct authstaticinfo
*auth
=l
->info
;
512 const char *modname
= auth
->auth_name
;
515 if (strcmp(prebuf
, ".") && strcmp(prebuf
, modname
))
518 DPRINTF("%s: trying this module", modname
);
521 rc
=(*auth
->auth_prefunc
)(p
, service
,
529 DPRINTF("%s: TEMPFAIL - no more modules will be tried",
531 return; /* Temporary error */
533 DPRINTF("%s: REJECT - try next module", modname
);
535 writeauth(fd
, "FAIL\n", 5);
536 DPRINTF("FAIL, all modules rejected");
539 struct enumerate_info
{
547 static void enumflush(struct enumerate_info
*ei
)
549 if (ei
->buf_ptr
> ei
->buffer
)
550 writeauth(ei
->fd
, ei
->buffer
, ei
->buf_ptr
- ei
->buffer
);
551 ei
->buf_ptr
=ei
->buffer
;
552 ei
->buf_left
=sizeof(ei
->buffer
);
555 static void enumwrite(struct enumerate_info
*ei
, const char *s
)
561 if (ei
->buf_left
== 0)
565 if (l
> ei
->buf_left
)
567 memcpy(ei
->buf_ptr
, s
, l
);
574 static void enum_cb(const char *name
,
582 struct enumerate_info
*ei
=(struct enumerate_info
*)void_arg
;
583 char buf
[NUMBUFSIZE
];
594 enumwrite(ei
, libmail_str_uid_t(uid
, buf
));
596 enumwrite(ei
, libmail_str_gid_t(gid
, buf
));
598 enumwrite(ei
, homedir
);
600 enumwrite(ei
, maildir
? maildir
: "");
602 fullopt
= mergeoptions(options
);
605 enumwrite(ei
, fullopt
);
611 static void enumerate(int fd
)
613 struct enumerate_info ei
;
614 struct authstaticinfolist
*l
;
619 for (l
=modulelist
; l
; l
=l
->next
)
621 struct authstaticinfo
*auth
=l
->info
;
623 if (auth
->auth_enumerate
== NULL
)
626 enumwrite(&ei
, "# ");
627 enumwrite(&ei
, auth
->auth_name
);
628 enumwrite(&ei
, "\n\n");
630 (*auth
->auth_enumerate
)(enum_cb
, &ei
);
631 if (!ei
.enumerate_ok
)
634 DPRINTF("enumeration terminated prematurely in module %s",
639 enumwrite(&ei
, ".\n");
643 static void dopasswd(int, const char *, const char *, const char *,
646 static void passwd(int fd
, char *prebuf
)
654 for (p
=prebuf
; *p
; p
++)
658 if ((int)(unsigned char)*p
< ' ')
660 writeauth(fd
, "FAIL\n", 5);
667 if ((p
=strchr(service
, '\t')) != 0)
671 if ((p
=strchr(p
, '\t')) != 0)
675 if ((p
=strchr(p
, '\t')) != 0)
679 if ((p
=strchr(p
, '\t')) != 0)
681 dopasswd(fd
, service
, userid
, opwd
, npwd
);
688 static void dopasswd(int fd
,
694 struct authstaticinfolist
*l
;
697 for (l
=modulelist
; l
; l
=l
->next
)
699 struct authstaticinfo
*auth
=l
->info
;
702 int (*f
)(const char *, const char *, const char *,
704 auth
->auth_changepwd
;
709 rc
= (*f
)(service
, userid
, opwd
, npwd
);
713 writeauth(fd
, "OK\n", 3);
719 writeauth(fd
, "FAIL\n", 5);
722 static void auth(int fd
, char *p
)
727 struct authstaticinfolist
*l
;
730 if ((p
=strchr(p
, '\n')) == 0) return;
733 if ((p
=strchr(p
, '\n')) == 0) return;
736 pp
=malloc(strlen(p
)+1);
739 perror("CRIT: malloc() failed");
743 DPRINTF("received auth request, service=%s, authtype=%s", service
, authtype
);
744 for (l
=modulelist
; l
; l
=l
->next
)
746 struct authstaticinfo
*auth
=l
->info
;
747 const char *modname
= auth
->auth_name
;
750 DPRINTF("%s: trying this module", modname
);
752 rc
=(*auth
->auth_func
)(service
, authtype
,
764 DPRINTF("%s: TEMPFAIL - no more modules will be tried", modname
);
766 return; /* Temporary error */
768 DPRINTF("%s: REJECT - try next module", modname
);
770 DPRINTF("FAIL, all modules rejected");
771 writeauth(fd
, "FAIL\n", 5);
775 static void idlefunc()
777 struct authstaticinfolist
*l
;
779 for (l
=modulelist
; l
; l
=l
->next
)
781 struct authstaticinfo
*auth
=l
->info
;
784 (*auth
->auth_idle
)();
788 static void doauth(int fd
)
795 for (i
=0; (ch
=getauthc(fd
)) != '\n'; i
++)
797 if (ch
< 0 || i
>= sizeof(buf
)-2)
808 while (*p
== ' ') ++p
;
813 if (strcmp(buf
, "PRE") == 0)
819 if (strcmp(buf
, "PASSWD") == 0)
825 if (strcmp(buf
, "AUTH") == 0)
830 if (i
< 0 || i
>= sizeof(buf
)) return;
841 if (strcmp(buf
, "ENUMERATE") == 0)
847 static int sighup_pipe
= -1;
849 static void sighup(int n
)
851 if (sighup_pipe
>= 0)
856 signal(SIGHUP
, sighup
);
859 static int sigterm_received
=0;
861 static void sigterm(int n
)
864 if (sighup_pipe
>= 0)
876 static int startchildren(int *pipefd
)
881 signal(SIGCHLD
, sighup
);
882 for (i
=0; i
<ndaemons
; i
++)
887 perror("CRIT: fork() failed");
895 signal(SIGHUP
, SIG_DFL
);
896 signal(SIGTERM
, SIG_DFL
);
897 signal(SIGCHLD
, SIG_DFL
);
904 static int killchildren(int *pipefd
)
908 while (wait(&waitstat
) >= 0 || errno
!= ECHILD
)
913 perror("CRIT: pipe() failed");
927 for (fd
=3; fd
<256; fd
++)
938 fprintf(stderr
, "ERR: lt_dlinit() failed: %s\n",
943 if (lt_dlsetsearchpath(PKGLIBDIR
))
945 fprintf(stderr
, "ERR: lt_dlsetsearchpath() failed: %s\n",
960 perror(AUTHDAEMONSOCK
);
966 signal(SIGPIPE
, SIG_IGN
);
967 signal(SIGHUP
, sighup
);
968 signal(SIGTERM
, sigterm
);
971 if (open("/dev/null", O_RDWR
) != 0)
977 sighup_pipe
= pipefd
[1];
979 do_child
=startchildren(pipefd
);
983 struct sockaddr saddr
;
989 FD_SET(pipefd
[0], &fds
);
997 if (select( (s
> pipefd
[0] ? s
:pipefd
[0])+1,
998 &fds
, 0, 0, &tv
) < 0)
1000 if (FD_ISSET(pipefd
[0], &fds
))
1004 return (0); /* Parent died */
1005 fprintf(stderr
, "INFO: stopping authdaemond children\n");
1006 while (killchildren(pipefd
))
1008 if (sigterm_received
)
1010 fprintf(stderr
, "INFO: restarting authdaemond children\n");
1012 sighup_pipe
=pipefd
[1];
1013 do_child
=startchildren(pipefd
);
1017 if (!FD_ISSET(s
, &fds
))
1023 saddr_len
=sizeof(saddr
);
1024 if ((fd
=accept(s
, &saddr
, &saddr_len
)) < 0)
1026 if (fcntl(fd
, F_SETFL
, 0) < 0)
1028 perror("CRIT: fcntl() failed");
1036 int main(int argc
, char **argv
)
1038 courier_authdebug_login_init();
1042 fprintf(stderr
, "Error: authdaemond no longer handles its own daemonizing.\n"
1043 "Use new startup script.\n");