Package: courier-authlib-pipe Version: 0.66.4-9 Severity: important Tags: upstream
Dear Maintainer, * What led up to the situation? I'm using a variant of the example authProg script. The authdaemon starts the external authProg *after* accepting the first connection from the client. accept(5, {sa_family=AF_UNIX}, [16->2]) = 4 <0.000033> fcntl(4, F_SETFL, O_RDONLY) = 0 <0.000151> ... select(5, [4], NULL, NULL, {tv_sec=10, tv_usec=0}) = 1 (in [4], left {tv_sec=9, tv_usec=999996}) <0.000054> read(4, "AUTH 40\nimap\nlogin\n...@dynapic.ne"..., 8192) = 48 <0.000029> clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f62cbd2c9d0) = 4644 <0.000202> This leaks the filedescriptor for the client connection to the forked authProg process. If the authProg doesn't care about file descriptors (as the example Perl script), the client connection FD is open twice: opened by the process which accepted the connection, and open by the process which inherited the FD. After sending the auth results to the client, the authdaemon close()es the client connection. But this doesn't really close the connection, because it is held open by the forked authProg process. The client runs into a timeout. (reproducable using socat -t 5 - /run/courier/authdaemon/socket <...) All connections following that first one do not have this problem, as now the authProg is running already and doesn't the the new FDs created by accepting the new connections. Solution: Either fork the authProg *before* accepting the first connection. Or use CLOSE_ON_EXEC on the FD returned from accepting the connection. Workaround: The example script can use use POSIX; POSIX::close($_) for 3..1024; This workaround solved the problem for me, so I'd consider it as a proof. * What exactly did you do (or not do) that was effective (or ineffective)? Use 'authpipe' as the only module in the authmodulelist. Use the example Perl script as an authProg. systemctl restart courier-authdaemon socat -t5 - /run/courier/authdaemon/socket <<_ AUTH 35 imap login f...@example.com foobar _ * What was the outcome of this action? The first invocation after restarting the daemon leads to a timeout. Every following invocation succeeds. (Given there is only one daemon running, controlled via the daemons setting in authdaemonrc. * What outcome did you expect instead? I think, the bugfix is easy, using fcntl and setting CLOSE_ON_EXEC in authdaemon.c, just after accepting the connection. But as I do not have a good testing environment, I can't do any tests. And as the package seems to be orphaned, I'm not sure if it is worth the effort. I'll need to switch to dovecot, I'm afraid. -- System Information: Debian Release: 9.5 APT prefers stable-updates APT policy: (500, 'stable-updates'), (500, 'stable') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 4.15.9 (SMP w/4 CPU cores) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) Versions of packages courier-authlib-pipe depends on: pn courier-authlib <none> ii libc6 2.24-11+deb9u3 courier-authlib-pipe recommends no packages. courier-authlib-pipe suggests no packages.