2 ** Copyright 2000-2018 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 "courierauth.h"
27 #include "courierauthstaticlist.h"
28 #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_SETFD
, FD_CLOEXEC
) < 0 ||
63 fcntl(fd
, F_SETFL
, O_NONBLOCK
) < 0)
65 perror(AUTHDAEMONSOCK
);
73 static int initmodules(const char *p
)
77 struct authstaticinfolist
**modptr
= &modulelist
;
78 struct authstaticinfolist
*m
;
84 fprintf(stderr
, "ERR: Configuration error - missing 'daemons' setting, using %u\n",
88 while ((m
=modulelist
) != NULL
)
91 fprintf(stderr
, "INFO: Uninstalling %s\n",
102 struct authstaticinfo
*a
;
104 if (isspace((int)(unsigned char)*p
))
110 for (i
=0; p
[i
] && !isspace((int)(unsigned char)p
[i
]); ++i
)
114 strncat(buf
, p
, i
>40 ? 40:i
);
116 fprintf(stderr
, "INFO: Installing %s\n", buf
);
122 fprintf(stderr
, "INFO: %s\n", lt_dlerror());
126 sprintf(buf2
, "courier_%s_init", buf
+3);
128 pt
=lt_dlsym(h
, buf2
);
132 "ERR: Can't locate init function %s.\n",
134 fprintf(stderr
, "ERR: %s\n", lt_dlerror());
138 a
= (*(struct authstaticinfo
*(*)(void))pt
)();
140 if ((m
=malloc(sizeof(*modulelist
))) == NULL
)
151 fprintf(stderr
, "INFO: Installation complete: %s\n",
157 static int readconfig()
164 if ((fp
=fopen(AUTHDAEMONRC
, "r")) == NULL
)
166 perror(AUTHDAEMONRC
);
170 while (fgets(buf
, sizeof(buf
), fp
))
172 char *p
=strchr(buf
, '\n'), *q
;
178 while ((c
=getc(fp
)) >= 0 && c
!= '\n')
182 if ((p
=strchr(buf
, '#')) != 0) *p
=0;
185 if (!isspace((int)(unsigned char)*p
))
187 if (*p
== 0) continue;
189 if ((p
=strchr(buf
, '=')) == 0)
191 fprintf(stderr
, "ERR: Bad line in %s: %s\n",
199 while (*p
&& isspace((int)(unsigned char)*p
))
207 if (strcmp(buf
, "authmodulelist") == 0)
220 if (strcmp(buf
, "daemons") == 0)
228 fprintf(stderr
, "INFO: modules=\"%s\", daemons=%u\n",
229 modlist
? modlist
:"(none)",
232 return (initmodules(modlist
));
235 static char buf
[BUFSIZ
];
236 static char *readptr
;
238 static char *writeptr
;
239 static int writeleft
;
241 static int getauthc(int fd
)
247 return ( (int)(unsigned char)*readptr
++ );
254 if (select(fd
+1, &fds
, 0, 0, &tv
) <= 0 ||
257 readleft
=read(fd
, buf
, sizeof(buf
));
265 return ( (int)(unsigned char)*readptr
++ );
268 static int writeauth(int fd
, const char *p
, unsigned pl
)
281 if (select(fd
+1, 0, &fds
, 0, &tv
) <= 0 ||
285 if (n
<= 0) return (-1);
292 static int writeauthflush(int fd
)
296 if (writeauth(fd
, buf
, writeptr
- buf
))
300 writeleft
=sizeof(buf
);
304 static int writeauthbuf(int fd
, const char *p
, unsigned pl
)
312 memcpy(writeptr
, p
, pl
);
318 if (writeauthflush(fd
)) return (-1);
321 if (n
> writeleft
) n
=writeleft
;
322 memcpy(writeptr
, p
, n
);
331 static int writeenvval(int fd
, const char *env
, const char *val
)
333 if (writeauthbuf(fd
, env
, strlen(env
)) ||
334 writeauthbuf(fd
, "=", 1) ||
335 writeauthbuf(fd
, val
, strlen(val
)) ||
336 writeauthbuf(fd
, "\n", 1))
341 static const char *findopt(const char *options
, const char *keyword
)
343 size_t keyword_l
=strlen(keyword
);
347 if (strncmp(options
, keyword
, keyword_l
) == 0)
349 switch (options
[keyword_l
])
352 return options
+ keyword_l
+ 1;
354 return options
+ keyword_l
;
357 options
=strchr(options
, ',');
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 */
366 static char *mergeoptions(const char *options
)
368 char *defoptions
= getenv("DEFAULTOPTIONS");
371 if (options
&& *options
&& defoptions
&& *defoptions
)
373 char *result
= malloc(strlen(options
) +
374 strlen(defoptions
) + 2);
380 strcpy(result
, options
);
382 defoptions
= strdup(defoptions
);
390 for (p
= strtok(defoptions
, ","); p
; p
= strtok(0, ","))
392 char *q
= strchr(p
, '=');
394 if (findopt(result
, p
)) continue;
402 else if (options
&& *options
)
404 return strdup(options
);
406 else if (defoptions
&& *defoptions
)
408 return strdup(defoptions
);
414 static int printauth(struct authinfo
*authinfo
, void *vp
)
417 char buf2
[NUMBUFSIZE
];
421 writeleft
=sizeof(buf
);
423 courier_authdebug_authinfo("Authenticated: ", authinfo
,
424 authinfo
->clearpasswd
,
427 if (authinfo
->sysusername
)
428 if (writeenvval(fd
, "USERNAME", authinfo
->sysusername
))
430 if (authinfo
->sysuserid
)
431 if (writeenvval(fd
, "UID", libmail_str_uid_t(*authinfo
->sysuserid
,
434 if (writeenvval(fd
, "GID", libmail_str_uid_t(authinfo
->sysgroupid
, buf2
)))
437 if (writeenvval(fd
, "HOME", authinfo
->homedir
))
439 if (authinfo
->address
)
440 if (writeenvval(fd
, "ADDRESS", authinfo
->address
))
442 if (authinfo
->fullname
)
445 * Only the first field of the comma-seperated GECOS field is the
452 fullname
=strdup(authinfo
->fullname
);
460 while (*p
!= ',' && *p
!= '\0')
463 retval
= writeenvval(fd
, "NAME", fullname
);
468 if (authinfo
->maildir
)
469 if (writeenvval(fd
, "MAILDIR", authinfo
->maildir
))
472 if (writeenvval(fd
, "QUOTA", authinfo
->quota
))
474 if (authinfo
->passwd
)
475 if (writeenvval(fd
, "PASSWD", authinfo
->passwd
))
477 if (authinfo
->clearpasswd
)
478 if (writeenvval(fd
, "PASSWD2", authinfo
->clearpasswd
))
480 fullopt
= mergeoptions(authinfo
->options
);
483 int rc
= writeenvval(fd
, "OPTIONS", fullopt
);
488 if (writeauthbuf(fd
, ".\n", 2) || writeauthflush(fd
))
493 static void pre(int fd
, char *prebuf
)
495 char *p
=strchr(prebuf
, ' ');
497 struct authstaticinfolist
*l
;
501 while (*p
== ' ') ++p
;
506 while (*p
== ' ') ++p
;
508 DPRINTF("received userid lookup request: %s", p
);
510 for (l
=modulelist
; l
; l
=l
->next
)
512 struct authstaticinfo
*auth
=l
->info
;
513 const char *modname
= auth
->auth_name
;
516 if (strcmp(prebuf
, ".") && strcmp(prebuf
, modname
))
519 DPRINTF("%s: trying this module", modname
);
522 rc
=(*auth
->auth_prefunc
)(p
, service
,
530 DPRINTF("%s: TEMPFAIL - no more modules will be tried",
532 return; /* Temporary error */
534 DPRINTF("%s: REJECT - try next module", modname
);
536 writeauth(fd
, "FAIL\n", 5);
537 DPRINTF("FAIL, all modules rejected");
540 struct enumerate_info
{
548 static void enumflush(struct enumerate_info
*ei
)
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
);
556 static void enumwrite(struct enumerate_info
*ei
, const char *s
)
562 if (ei
->buf_left
== 0)
566 if (l
> ei
->buf_left
)
568 memcpy(ei
->buf_ptr
, s
, l
);
575 static void enum_cb(const char *name
,
583 struct enumerate_info
*ei
=(struct enumerate_info
*)void_arg
;
584 char buf
[NUMBUFSIZE
];
595 enumwrite(ei
, libmail_str_uid_t(uid
, buf
));
597 enumwrite(ei
, libmail_str_gid_t(gid
, buf
));
599 enumwrite(ei
, homedir
);
601 enumwrite(ei
, maildir
? maildir
: "");
603 fullopt
= mergeoptions(options
);
606 enumwrite(ei
, fullopt
);
612 static void enumerate(int fd
)
614 struct enumerate_info ei
;
615 struct authstaticinfolist
*l
;
618 ei
.buf_ptr
=ei
.buffer
;
621 for (l
=modulelist
; l
; l
=l
->next
)
623 struct authstaticinfo
*auth
=l
->info
;
625 if (auth
->auth_enumerate
== NULL
)
628 enumwrite(&ei
, "# ");
629 enumwrite(&ei
, auth
->auth_name
);
630 enumwrite(&ei
, "\n\n");
632 (*auth
->auth_enumerate
)(enum_cb
, &ei
);
633 if (!ei
.enumerate_ok
)
636 DPRINTF("enumeration terminated prematurely in module %s",
641 enumwrite(&ei
, ".\n");
645 static void dopasswd(int, const char *, const char *, const char *,
648 static void passwd(int fd
, char *prebuf
)
656 for (p
=prebuf
; *p
; p
++)
660 if ((int)(unsigned char)*p
< ' ')
662 writeauth(fd
, "FAIL\n", 5);
669 if ((p
=strchr(service
, '\t')) != 0)
673 if ((p
=strchr(p
, '\t')) != 0)
677 if ((p
=strchr(p
, '\t')) != 0)
681 if ((p
=strchr(p
, '\t')) != 0)
683 dopasswd(fd
, service
, userid
, opwd
, npwd
);
690 static void dopasswd(int fd
,
696 struct authstaticinfolist
*l
;
699 for (l
=modulelist
; l
; l
=l
->next
)
701 struct authstaticinfo
*auth
=l
->info
;
704 int (*f
)(const char *, const char *, const char *,
706 auth
->auth_changepwd
;
711 rc
= (*f
)(service
, userid
, opwd
, npwd
);
715 writeauth(fd
, "OK\n", 3);
721 writeauth(fd
, "FAIL\n", 5);
724 static void auth(int fd
, char *p
)
729 struct authstaticinfolist
*l
;
732 if ((p
=strchr(p
, '\n')) == 0) return;
735 if ((p
=strchr(p
, '\n')) == 0) return;
738 pp
=malloc(strlen(p
)+1);
741 perror("CRIT: malloc() failed");
745 DPRINTF("received auth request, service=%s, authtype=%s", service
, authtype
);
746 for (l
=modulelist
; l
; l
=l
->next
)
748 struct authstaticinfo
*auth
=l
->info
;
749 const char *modname
= auth
->auth_name
;
752 DPRINTF("%s: trying this module", modname
);
754 rc
=(*auth
->auth_func
)(service
, authtype
,
766 DPRINTF("%s: TEMPFAIL - no more modules will be tried", modname
);
768 return; /* Temporary error */
770 DPRINTF("%s: REJECT - try next module", modname
);
772 DPRINTF("FAIL, all modules rejected");
773 writeauth(fd
, "FAIL\n", 5);
777 static void idlefunc()
779 struct authstaticinfolist
*l
;
781 for (l
=modulelist
; l
; l
=l
->next
)
783 struct authstaticinfo
*auth
=l
->info
;
786 (*auth
->auth_idle
)();
790 static void doauth(int fd
)
797 for (i
=0; (ch
=getauthc(fd
)) != '\n'; i
++)
799 if (ch
< 0 || i
>= sizeof(buf
)-2)
810 while (*p
== ' ') ++p
;
815 if (strcmp(buf
, "PRE") == 0)
821 if (strcmp(buf
, "PASSWD") == 0)
827 if (strcmp(buf
, "AUTH") == 0)
832 if (i
< 0 || i
>= sizeof(buf
)) return;
843 if (strcmp(buf
, "ENUMERATE") == 0)
849 static int sighup_pipe
= -1;
851 static void sighup(int n
)
853 if (sighup_pipe
>= 0)
858 signal(SIGHUP
, sighup
);
861 static int sigterm_received
=0;
863 static void sigterm(int n
)
866 if (sighup_pipe
>= 0)
878 static int startchildren(int *pipefd
)
883 signal(SIGCHLD
, sighup
);
884 for (i
=0; i
<ndaemons
; i
++)
889 perror("CRIT: fork() failed");
897 signal(SIGHUP
, SIG_DFL
);
898 signal(SIGTERM
, SIG_DFL
);
899 signal(SIGCHLD
, SIG_DFL
);
906 static int killchildren(int *pipefd
)
910 while (wait(&waitstat
) >= 0 || errno
!= ECHILD
)
915 perror("CRIT: pipe() failed");
929 for (fd
=3; fd
<256; fd
++)
940 fprintf(stderr
, "ERR: lt_dlinit() failed: %s\n",
945 if (lt_dlsetsearchpath(PKGLIBDIR
))
947 fprintf(stderr
, "ERR: lt_dlsetsearchpath() failed: %s\n",
962 perror(AUTHDAEMONSOCK
);
968 signal(SIGPIPE
, SIG_IGN
);
969 signal(SIGHUP
, sighup
);
970 signal(SIGTERM
, sigterm
);
973 if (open("/dev/null", O_RDWR
) != 0)
979 sighup_pipe
= pipefd
[1];
981 do_child
=startchildren(pipefd
);
985 struct sockaddr saddr
;
991 FD_SET(pipefd
[0], &fds
);
999 if (select( (s
> pipefd
[0] ? s
:pipefd
[0])+1,
1000 &fds
, 0, 0, &tv
) < 0)
1002 if (FD_ISSET(pipefd
[0], &fds
))
1006 return (0); /* Parent died */
1007 fprintf(stderr
, "INFO: stopping authdaemond children\n");
1008 while (killchildren(pipefd
))
1010 if (sigterm_received
)
1012 fprintf(stderr
, "INFO: restarting authdaemond children\n");
1014 sighup_pipe
=pipefd
[1];
1015 do_child
=startchildren(pipefd
);
1019 if (!FD_ISSET(s
, &fds
))
1025 saddr_len
=sizeof(saddr
);
1026 if ((fd
=accept(s
, &saddr
, &saddr_len
)) < 0)
1028 if (fcntl(fd
, F_SETFL
, 0) < 0 ||
1029 fcntl(fd
, F_SETFD
, FD_CLOEXEC
) < 0)
1031 perror("CRIT: fcntl() failed");