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.

Reply via email to