running postfix as an unprivileged user

93 views
Skip to first unread message

Gurusamy Sarathy

unread,
Dec 29, 2003, 10:01:26 PM12/29/03
to
I'm trying to set up an automated test harness that involves
Postfix, and have hit what appears to be a brick wall.

The existing test harness works by launching sendmail (the one
from sendmail.org) with the simple configuration changes needed
to run as some arbitrary test user (viz., DaemonPortOptions set
to a port greater than 1024, and LOCAL_MAILER_PATH overridden to
point to a tiny script that just delivers the mail to file names
that correspond to the user names, without attempting to do any
privileged stuff like chown()--the test harness is only really
interested in whether the email content gets through in a
well-defined form, so this suits my purposes just fine).

My preliminary attempt to do this with Postfix has failed
utterly, since the 'master' process refuses to run as anything
but root, and I can't really require the test harness be
run with root privileges just so it can start a postfix
instance that shouldn't really need root privileges (for what
it is doing) to begin with.

Now for the questions:

1. Is there any way to do the above with Postfix? (Note that
I'm not interested in local delivery or listening on privileged
ports. Think of the mail as being routed through a Postfix
instance listening on an unprivileged port, and on to another
SMTP listener that handles all of the privileged delivery
shenanigans.)

2. If not, why not, and is this inflexibility considered a
feature?

Any information/suggestions gratefully received.


Sarathy
gs...@ActiveState.com

Wietse Venema

unread,
Dec 29, 2003, 10:54:44 PM12/29/03
to
Gurusamy Sarathy:

> I'm trying to set up an automated test harness that involves
> Postfix, and have hit what appears to be a brick wall.
>
> The existing test harness works by launching sendmail (the one
> from sendmail.org) with the simple configuration changes needed
> to run as some arbitrary test user (viz., DaemonPortOptions set
> to a port greater than 1024, and LOCAL_MAILER_PATH overridden to
> point to a tiny script that just delivers the mail to file names
> that correspond to the user names, without attempting to do any
> privileged stuff like chown()--the test harness is only really
> interested in whether the email content gets through in a
> well-defined form, so this suits my purposes just fine).
>
> My preliminary attempt to do this with Postfix has failed
> utterly, since the 'master' process refuses to run as anything
> but root, and I can't really require the test harness be
> run with root privileges just so it can start a postfix
> instance that shouldn't really need root privileges (for what
> it is doing) to begin with.

That may be so, but UNIX still REQUIRES privileges in order to
REVOKE privileges:

1) Assume a dedicated user and group ID, to isolate postfix processes
from a large number of attacks by other process on the same system.

2) Revoke Postfix access to a large portion of the file system, to
isolate the system from some attacks by a compromised Postfix.

Remember, one of the goals of Postfix is to handle mail while
MINIMIZING the opportunity for system compromise.

You could try to configure master.cf to run all daemons with full
system privilege; you still would have to LD_PRELOAD a shared object
that causes getuid() to return zero.

Non-root mode will, however, not be a supported mode of operation
until 1) and 2) can be done by an unprivileged process.

Wietse

Gurusamy Sarathy

unread,
Dec 30, 2003, 4:09:26 AM12/30/03
to
On Mon, 29 Dec 2003 22:54:31 EST, Wietse Venema wrote:
>Gurusamy Sarathy:

>> My preliminary attempt to do this with Postfix has failed
>> utterly, since the 'master' process refuses to run as anything
>> but root, and I can't really require the test harness be
>> run with root privileges just so it can start a postfix
>> instance that shouldn't really need root privileges (for what
>> it is doing) to begin with.
>
>That may be so, but UNIX still REQUIRES privileges in order to
>REVOKE privileges:

I may not know enough about Postfix internals yet to understand
what privileges are being revoked and why they need to be revoked.
I wish to treat Postfix like a black box that exposes an input end
and an output end. The input end accepts messages via SMTP and
the output end forwards them on via SMTP to a sink. I hope this
is a supported configuration, because my test harness only ever
needs this absolutely minimal setup.

Given that particular context, I'm expecting to run the Postfix
"black box" (incidentally as some unprivileged random user) to
verify that the output is an acceptable transformation/faithful
reproduction of the output. Is this a reasonable expectation?

>1) Assume a dedicated user and group ID, to isolate postfix processes
>from a large number of attacks by other process on the same system.
>
>2) Revoke Postfix access to a large portion of the file system, to
>isolate the system from some attacks by a compromised Postfix.
>
>Remember, one of the goals of Postfix is to handle mail while
>MINIMIZING the opportunity for system compromise.
>
>You could try to configure master.cf to run all daemons with full
>system privilege; you still would have to LD_PRELOAD a shared object
>that causes getuid() to return zero.
>
>Non-root mode will, however, not be a supported mode of operation
>until 1) and 2) can be done by an unprivileged process.

Apologies if I completely missed your points, but what I'm trying to
do has nothing to do with security. I can understand that Postfix
needs to be capable of dealing with a hostile environment, but
_my particular application_ does not need to worry about any of
that, since all it is trying to achieve is to verify that the data
stream makes it in and out in a proper form, under a carefully
controlled environment.

If you are saying that Postfix cannot support my use case because
doing so is not possible/desirable due to reason X, Y and Z, I can
accept that. However, my interest here is in understanding what X,
Y and Z are, and perhaps even attempt to supply patches to address
them, if that is desirable. (From my potentially imperfect reading
of your points 1 and 2, they seem to be explaining why Postfix is
the way it is, instead of explaining why what I'm looking for is
not supported/allowed, meaning 1 and 2 are not the X, Y and Z I
was trying to come to grips with. Feel free to correct me if
needed.)

Let me make that somewhat more concrete. Would you accept a patch
to add an option to Postfix (one that will be disabled by default)
to allow Postfix to run (to the extent possible) as a non-privileged
user? Based on a quick study of the 2.0.16 sources, it would seem
to largely be a matter of delaying the failures due to lack of
privileges until some operation that actually needs those privileges
is attempted (i.e., fail as-late-as-possible instead of the current
fail as-soon-as-possible regimen). My use case will not hit any
of the code paths that require additional privileges, so such a
patch should do what I'm looking for.

If anyone has a better approach to a patch that will meet my goal,
I welcome and thank you for your thoughts.


Sarathy
gs...@ActiveState.com

Wietse Venema

unread,
Dec 30, 2003, 10:02:38 AM12/30/03
to
Gurusamy Sarathy:

> On Mon, 29 Dec 2003 22:54:31 EST, Wietse Venema wrote:
> >Gurusamy Sarathy:
> >> My preliminary attempt to do this with Postfix has failed
> >> utterly, since the 'master' process refuses to run as anything
> >> but root, and I can't really require the test harness be
> >> run with root privileges just so it can start a postfix
> >> instance that shouldn't really need root privileges (for what
> >> it is doing) to begin with.
> >
> >That may be so, but UNIX still REQUIRES privileges in order to
> >REVOKE privileges:
>
> I may not know enough about Postfix internals yet to understand
> what privileges are being revoked and why they need to be revoked.

It's anwsered a few lines later in my reply:

Remember, one of the goals of Postfix is to handle mail while
MINIMIZING the opportunity for system compromise.

This minimization is implemented by privilege separation. It is
a basic element of the Postfix architecture. Postfix runs in
its own privilege compartment; when Postfix executes non-Postfix
commands, those must not run with the same privileges as Postfix.

> Let me make that somewhat more concrete. Would you accept a patch
> to add an option to Postfix (one that will be disabled by default)
> to allow Postfix to run (to the extent possible) as a non-privileged
> user? Based on a quick study of the 2.0.16 sources, it would seem
> to largely be a matter of delaying the failures due to lack of
> privileges until some operation that actually needs those privileges
> is attempted (i.e., fail as-late-as-possible instead of the current
> fail as-soon-as-possible regimen). My use case will not hit any
> of the code paths that require additional privileges, so such a
> patch should do what I'm looking for.

Why not LD_PRELOAD override a few system system calls and be done
with it? It's a dozen or so lines of code, and avoids messing around
in Postfix source code.

> If anyone has a better approach to a patch that will meet my goal,
> I welcome and thank you for your thoughts.

I suppose that the word LD_PRELOAD didn't ring a bell.

You are asking me for a supported way to disable everything security
related in Postfix, and that this dual mode of operation be supported
forever into the future.

This is not just a matter of adding a configuration parameter that
disables a few system calls here and there. It breaks a large
number of programs that make up Postfix, and that has to be
documented: every feature that is broken by this change, in the
context of that feature (not in some README file that no-one sees).
That includes documenting that it renders unusable the "chroot"
and "unprivileged" features in master.cf, documenting the impact
it has on the mail_owner and default_privs features in main.cf,
documenting that it renders unusable the pipe(8), virtual(8) and
local(8) delivery agents, or anything else that needs to maintain
separation of postfix privileges when non-Postfix commands are to
be executed.

Such a change puts a high burden on future development. It doubles
the documentation, testing and maintenance load. Everything now
needs to be tested in both privileged and unprivileged mode, and
everything that is added to Postfix needs a dual personality in
code and in documentation for privileged/unprivileged operation.

Wietse

Gurusamy Sarathy

unread,
Dec 30, 2003, 12:16:18 PM12/30/03
to
On Tue, 30 Dec 2003 10:02:20 EST, Wietse Venema wrote:
>Gurusamy Sarathy:
>> Let me make that somewhat more concrete. Would you accept a patch
>> to add an option to Postfix (one that will be disabled by default)
>> to allow Postfix to run (to the extent possible) as a non-privileged
>> user? Based on a quick study of the 2.0.16 sources, it would seem
>> to largely be a matter of delaying the failures due to lack of
>> privileges until some operation that actually needs those privileges
>> is attempted (i.e., fail as-late-as-possible instead of the current
>> fail as-soon-as-possible regimen). My use case will not hit any
>> of the code paths that require additional privileges, so such a
>> patch should do what I'm looking for.
>
>Why not LD_PRELOAD override a few system system calls and be done
>with it? It's a dozen or so lines of code, and avoids messing around
>in Postfix source code.

I'm well aware of LD_PRELOAD, and had assumed you meant overriding
getuid(), chown() et al to pretend as though they had sufficient
privileges.

But that isn't what I'm after though! I _do_ want Postfix to fail
if any privileged operations must be attempted and it is running
without the necessary privileges (as determined by the return
value from the syscall when the operation is attempted). I just
don't want Postfix to fail until it must actually do such an
operation, and finds out the OS doesn't let it do so.

>> If anyone has a better approach to a patch that will meet my goal,
>> I welcome and thank you for your thoughts.
>
>I suppose that the word LD_PRELOAD didn't ring a bell.
>
>You are asking me for a supported way to disable everything security
>related in Postfix, and that this dual mode of operation be supported
>forever into the future.

Again, I suggested the option merely as a means to enable the
fail-as-late-as-possible behavior, not as a way to disable all
security. If not having the option is a better way to approach
it, that would be fine by me--Postfix would still fail when it
can't do those operations that require privileges, so I see no
security implications from the change.

Anyway, I hope I'm not flogging a dead horse. If you don't see
this as an acceptable change (though I haven't heard any good
reasons yet as to why not), I don't mind giving up trying to
force-fit Postfix into my test harness.

Thanks,


Sarathy
gs...@ActiveState.com

Wietse Venema

unread,
Dec 30, 2003, 1:40:02 PM12/30/03
to
Gurusamy Sarathy:

> >You are asking me for a supported way to disable everything security
> >related in Postfix, and that this dual mode of operation be supported
> >forever into the future.
>
> Again, I suggested the option merely as a means to enable the
> fail-as-late-as-possible behavior, not as a way to disable all
> security. If not having the option is a better way to approach
> it, that would be fine by me--Postfix would still fail when it
> can't do those operations that require privileges, so I see no
> security implications from the change.

Turning off the "am I root" tests in postfix(1) and master(8) merely
causes Postfix to produce hard to understand error messages; since
this behavior would be off by default I could live with it.

But this alone gets you nowhere. In order to get away with this,
Postfix would either 1) have to support master.cf configurations
that turn off all security (both chroot and privilege separation),
or 2) uid/gid manipulating operations would have to figure out what
mode of operation it's in: either fixed postfix privilege mode, or
root->postfix privilege mode. Option 1) is not acceptable, and I
have yet to see the impact of 2) on code complexity.

> Anyway, I hope I'm not flogging a dead horse. If you don't see
> this as an acceptable change (though I haven't heard any good
> reasons yet as to why not), I don't mind giving up trying to
> force-fit Postfix into my test harness.

If a test method requires architectural changes to the system being
tested, then that casts doubt on the validity of the method.

Wietse

Gurusamy Sarathy

unread,
Dec 30, 2003, 3:46:40 PM12/30/03
to
On Tue, 30 Dec 2003 13:39:55 EST, Wietse Venema wrote:
>Turning off the "am I root" tests in postfix(1) and master(8) merely
>causes Postfix to produce hard to understand error messages; since
>this behavior would be off by default I could live with it.
>
>But this alone gets you nowhere. In order to get away with this,
>Postfix would either 1) have to support master.cf configurations
>that turn off all security (both chroot and privilege separation),
>or 2) uid/gid manipulating operations would have to figure out what
>mode of operation it's in: either fixed postfix privilege mode, or
>root->postfix privilege mode. Option 1) is not acceptable, and I
>have yet to see the impact of 2) on code complexity.

Sounds like my approach will not work, then. Thanks for the
explanation.

>If a test method requires architectural changes to the system being
>tested, then that casts doubt on the validity of the method.

Perhaps so. But from my vantage point, Postfix appears to have a
complicated security model, and my goal was to prevent that
complexity from leaking into my test harness if I could. You will
agree that test harnesses by their very nature should be as
uncomplicated as possible--otherwise one risks introducing bugs
in the harness that invalidates all the test results.


Sarathy
gs...@ActiveState.com

Wietse Venema

unread,
Dec 30, 2003, 4:10:22 PM12/30/03
to
Gurusamy Sarathy:

> On Tue, 30 Dec 2003 13:39:55 EST, Wietse Venema wrote:
> >Turning off the "am I root" tests in postfix(1) and master(8) merely
> >causes Postfix to produce hard to understand error messages; since
> >this behavior would be off by default I could live with it.
> >
> >But this alone gets you nowhere. In order to get away with this,
> >Postfix would either 1) have to support master.cf configurations
> >that turn off all security (both chroot and privilege separation),
> >or 2) uid/gid manipulating operations would have to figure out what
> >mode of operation it's in: either fixed postfix privilege mode, or
> >root->postfix privilege mode. Option 1) is not acceptable, and I
> >have yet to see the impact of 2) on code complexity.
>
> Sounds like my approach will not work, then. Thanks for the
> explanation.

To make it "work" requires careful adjustment of the code inside
and surrounding set_eugid().

That is, if the idea is preserve the existing privilege model and
to fail any operations that require root privilege.

In any case, my cycles are better spent on things that benefit more
people than the two folks who asked for unprivileged Postfix in
the past five years.

Wietse

Reply all
Reply to author
Forward
0 new messages