|
Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com |
From: Alex van den Bogaerdt (alex_at_ergens.op.HET.NET)
Date: Sun Jul 28 2002 - 06:55:13 CDT
All of the following should be parsed as questions in the
form of "is it correct to think ..." and is included as stuff
to discuss about.
I wouldn't be surprised if there is a logic flaw somewhere in
the following. After all, it is just the first try. That of
course doesn't mean I didn't try my best. If there is such
a flaw, please explain so that I can learn from it.
> In this specific case, the purpose is to create a directory that
> is owned by the recipient, with appropriate permissions. Any solution
> is acceptable if it does exactly that and nothing more.
I think there's one more prerequisite: the directory must be
created in a place previously defined by the systems administrator.
$mail_spool_directory seems to be right. If it's not going to
happen there, it's not going to happen with elevated privileges.
Also, $mail_spool_directory needs to be owned by root and there
shouldn't be another way of creating the necessary directory.
For instance: write permissions to group mail or group postfix
indicates postfix should use group privileges. This is not
covered in this mail but using a subset of the logic could
probably do the trick.
> The solution should be safe even when the postfix account (or any
> other non-root account) is compromised.
>
> The solution should not allow a malicious user to trick Postfix
> into creating an object other than the target directory.
>
> The solution should not allow a malicious user to trick Postfix
> into changing the ownership or access permissions of an object
> other than the target directory.
>
> The solution should gracefully handle any errors. For example, two
> different processes may try to perform this operation at the same
> time. Another example: the solution should gracefully deal with
> the case that a process did not fully complete the operation
> because of some software or system failure.
When postfix is trying to deliver mail, we may assume all checks
done by postfix are enough to know it is an account that does
receive mail. The sysadmin/system should have created the directory
and if he/she/it didn't do so, this is an error situation which
postfix can try and recover from.
Compromised accounts:
If postfix, or a part of postfix, is started by another user then
the directory cannot be created -or- the user doesn't need postfix
to create the directory. This is because postfix isn't run suid.
If there currently is a way to talk to postfix from a non-privileged
client and trick postfix into doing something, then this can also be
done from an entirely other program written by an ordinary user.
Only $mail_spool_directory/$user:
This also is something postfix can handle pretty safe. It won't
try and create, for instance, /bin/$user. This doesn't mean there
shouldn't be a check, just in case. We need to be able to rely on
the content of $mail_spool_directory and $user. I think that's the
case anyway with or without the proposed change.
Changing other objects:
I'm not sure if I fully understand what you mean by this. If
postfix is only touching $mail_spool_directory/* then little
should be possible. I will get back to this after the next
paragraph.
Handling errors:
From the mkdir(2) documentation:
EEXIST pathname already exists (not necessarily as a
directory). This includes the case where pathname
is a symbolic link, dangling or not.
This means postfix will know when something bad is happening.
If the call succeeds, a new directory will have been created and
it will have be done by the current process.
Possible problems in $mail_spool_directory:
-1- no directory for the user
-2- directory is present but with wrong permissions
-3- something there, not a directory
(1) is the cause of this discussion and is obvious.
(2) could be the result of a failed attempt by postfix to create
the directory. This because mkdir and surrounding parts will
not be canonical. Clean up or report to postmaster.
(3) could be the result of a migration from mailbox to maildir
without actually migrating the stuff (i.e. only in main.cf).
Move it away and notify the postmaster
-or-
Defer delivery and notify the postmaster
These steps should do the trick, I think:
-1- Check if there is a directory with the right permissions. If
there is, skip to (10). Also check the $mail_spool_directory
for certain other parameters such as owned by root, not world
writable and so on.
-2- use elevated privileges but only if we're in $mail_spool_directory
-3- Try and create a lock file. If this fails, don't bother
creating a directory. skip to (9).
-4- Check if there already is an entry named $user. Whatever it is,
it didn't satisfy (1) so it has to be renamed, for instance into
BOGUS.$user.$inode. Great care is needed to not overwrite
something already there. More on this below.
-5- create a directory with permissions 0. This shouldn't fail
according to (4). If it does fail, something is really wrong and
the postmaster needs to be alerted. Something wrong includes the
NFS case. There's nothing we can do about that. If it fails,
jump to (9).
-6- change the owner and group of the directory entry.
-7- change the permissions of the directory entry.
-8- remove the lock
-9- use normal privileges again
-10- try to deliver the mail by creating $mail_spool_directory/$user/tmp
and so on. If it fails, be smart about what to do. If it is the
user's fault (such as quota exceeded) then bounce, else defer.
(3) should cover the case where two postfix processes try to do the
same thing in parallel.
(4) covers postmaster errors.
(5) makes sure only postfix will access the directory while it is
creating it.
There's one possible problem with this approach (I'm not sure). If
chown(2) doesn't modify quota, the directory $user (and nothing more)
will not be counted until quotacheck(8) is run.
Bogus stuff from (4):
Details are not entirely specified yet. It can be done in several ways,
if at all. Some possibilities:
-1- Have a directory where this bogus stuff is moved into. The
directory is accessible by root only. Appropriate locking is
done in order to accommodate for parallel processes.
-2- First create a directory or file, rename this file to the suggested
name, then rename(2) the bogus entry over the newly created one.
-3- Never create other objects. Delivery will fail due to system
problems and the mail is deferred without further checking.
Please let me know what you think so far.
cheers,
Alex
-
To unsubscribe, send mail to majordomo
postfix.org with content
(not subject): unsubscribe postfix-users
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]