0

I am working with Dovecot 2.3.4.1 and EncFS (encfs version 1.9.5) encrypted mailboxes on Debian 10 (no SELinux)

Basic setup is:

EncFS mounted with

encfs --public /var/encrypted-mail /var/decrypted-mail -o nonempty --verbose

Mailbox-Setup:

/var/decrypted-mail/domain.com/foo@domain.com/[cur,new...]

drwx------ 8 mail mail 4096 Dec 29 2019 /var/decrypted-mail (those permissions are recursive)

All dovecot processes run as mail user:

mail 5194 0.0 0.0 6308 4312 ? S 14:52 0:00 dovecot/imap

Despite everything seemingly being configured correctly, I can not create new folders or rename existing ones.

I get this error in the /var/log/dovecot.log:

Jan 24 14:59:04 imap(foo@domain.com)<6010><Us21sxWS5OZaC6Ex>: Error: Couldn't create mailbox list lock /var/decrypted-mail/domain.com/foo@domain.com/mailboxes.lock: file_create_locked(/var/decrypted-mail/domain.com/foo@domain.com/mailboxes.lock) failed: link(/var/decrypted-mail/domain.com/foo@domain.com/mailboxes.lockba53af3795974a32, /var/decrypted-mail/domain.com/foo@domain.com/mailboxes.lock) failed: Operation not permitted

The source code for that error message resides here: https://github.com/dovecot/core/blob/4d09884528e592a0fa5d38bf479b3ddab1a4a0ef/src/lib/file-create-locked.c#L109-L123

If I read that correctly, it can not use a 'regular locking' mechanisem and tries to symlink a temporary file to mailboxes.lock. This indicates, that it COULD create the temporary file mailboxes.lockba53af3795974a32 and is just not able to symlink it.

When I run this command in the shell: sudo -u mail bash -c 'touch mailboxes.lockba53af3795974a32 && ln -s mailboxes.lockba53af3795974a32 mailboxes.lock'

It works properly and I get no errors.

How is it possible that dovecot behaves so differently from a normal shell?

The only explanation I would have is a timing problem (temp file is accessed before, but why does this not appear in the bash reproduction?).

I also tried chmod -R g+rwx /var/decrypted-mail, to make sure that all those gids are not the problem, but that was just a desperate attempt to find a fix.

func0der
  • 154
  • 4
  • 15
  • Is this a system with SELinux in enforcing mode? Then check the security logging. – Gerrit Jan 24 '21 at 14:27
  • I do not use SELinux. `sestatus` does not exist as a command, so I think that it is not enabled by accident. The only other thing I can think about with Debian 10 is `apparmour`, but I did not touch that. – func0der Jan 24 '21 at 14:42
  • 1
    You could check `aa-status` and look in /var/log/syslog for apparmor messages if there is no audit log. – Gerrit Jan 25 '21 at 08:18

1 Answers1

0

Turns out this is known limitation of encfs under certain circumstances.

If you enable External IV Chaining hard links are disabled.

External IV Chaining

New in 1.1.3. This option is closely related to Per-File Initialization Vectors and Filename Initialization Vector Chaining. Basically it extends the initialization vector chaining from filenames to the per-file initialization vector.

When this option is enabled, the per-file initialization vector is encoded using the initialization vector derived from the filename initialization vector chaining code. This means that the data in a file becomes tied to the filename. If an encrypted file is renamed outside of encfs, it will no longer be decodable within encfs. Note that unless Block MAC headers are enabled, the decoding error will not be detected and will result in reading random looking data.

There is a cost associated with this. When External IV Chaining is enabled, hard links will not be allowed within the filesystem, as there would be no way to properly decode two different filenames pointing to the same data.

Also, renaming a file requires modifying the file header. So renames will only be allowed when the user has write access to the file.

Because of these limits, this option is disabled by default for standard mode (and enabled by default for paranoia mode).

Source: the encfs(1) man page.

It also turns out, that I misread the man page of link. It clearly states the it creates a new *hard-link by default. I created a soft-link with my posted code snippet:

sudo -u mail bash -c 'touch mailboxes.lockba53af3795974a32 && ln -s mailboxes.lockba53af3795974a32 mailboxes.lock'

If I had ran:

sudo -u mail bash -c 'touch mailboxes.lockba53af3795974a32 && ln mailboxes.lockba53af3795974a32 mailboxes.lock'

instead, I would have gotten the exact same error messages as the dovecot code got:

ln: failed to create hard link 'mailboxes.lock' => 'mailboxes.lockba53af3795974a32': Operation not permitted


Extra knowledge

A neat trick I found along the way was, that you can enable debugging for fuse filesystems with -f -d.

Implementations like encfs or cryfs allow you to parse those options to fuse like so:

encfs enc dec -- -f -d

Fuse will run in the foreground then and show you everything that is happening in the mount filesystem. :)

func0der
  • 154
  • 4
  • 15