Обсуждение: "Optional ident" authentication

Поиск
Список
Период
Сортировка

"Optional ident" authentication

От
"Jeroen T. Vermeulen"
Дата:
Is there a reason other than existing code why HBA should not allow
"ident" to be combined with other authentication methods?

Right now there's no fall-back mechanism for when an ident map doesn't
cover a particular login attempt.  The code isn't really structured to
allow one, and I've assumed that that is the only real reason it isn't
there.

My personal itch is that I'd like to have an "ident sameuser"
authentication that falls back on, say, PAM authentication when system
user A wants to log into postgres under a different username B.

To scratch that itch I've made a patch that adds a new authentication
method called optident.  It behaves like ident except that it continues
walking down the HBA configuration on failure.  AFAICS the patch should
allow you, for example, to grant a web application or daemon passwordless
login to its database while other users still need a password.  That seems
a bit safer than storing plaintext passwords in config files (and more
often than not, forget to make them non-readable to untrusted users) like
PHP/MySQL applications tend to do.

It's a fairly radical patch in that it changes struct Port (from hba.h). 
The auth_method is replaced with a function pointer, and the UserAuth enum
is replaced with a function-pointer typedef.  I think I may also add a new
enum for the corresponding password encryption algorithms, which crypt.c
currently special-cases based on authentication method.  That wasn't very
pretty in the first place, I think.

Some dead bits of code and text disappear ("trust authentication failed",
"unknown authentication method failed") and no new translatable strings
are added.  Another side effect is that the message for "no matching hba
line" is given only when it applies, rather than for every connection that
hits the "reject" method.

Most of the work went into making fallbacks possible in the first place. 
One alternative was to allow multiple arguments to authentication methods
in pg_hba.conf, but that would have been just as radical a change.  As it
is, the changes are nicely contained--apart from changing the type of that
one field in struct Port.

Before I go any further with this, am I barking up the wrong tree?  Am I
missing something?  Or is it worth doing?


Jeroen




Re: "Optional ident" authentication

От
Tom Lane
Дата:
"Jeroen T. Vermeulen" <jtv@xs4all.nl> writes:
> Is there a reason other than existing code why HBA should not allow
> "ident" to be combined with other authentication methods?

How about that it's a bad idea?  A combo method seems ideally suited
to security holes, in the form of letting through unintended logins.

> To scratch that itch I've made a patch that adds a new authentication
> method called optident.  It behaves like ident except that it continues
> walking down the HBA configuration on failure.

... and this particular approach would break more installations'
security than I really want to think about.  It's not really a new ident
method, it's a very fundamental change in the semantics of pg_hba.conf.
As an example of how much it would change things, the "reject" auth
option would become a useless no-op.
        regards, tom lane


Re: "Optional ident" authentication

От
"Jeroen T. Vermeulen"
Дата:
On Sun, November 26, 2006 23:51, Tom Lane wrote:
>> Is there a reason other than existing code why HBA should not allow
>> "ident" to be combined with other authentication methods?
>
> How about that it's a bad idea?  A combo method seems ideally suited
> to security holes, in the form of letting through unintended logins.

Well, that's why I'm asking.  But I was hoping for something more concrete
than "it could possibly be misconfigured."  Especially when we still
generate default configs that say "trust" for all local logins!

The Debian package does come with a safer default config using "ident
sameuser."  For a packager-maintained setup like that, where you know
beforehand that both the backend and the system do PAM, it might make
sense to have that passwordless "ident sameuser" login on local
connections but use e.g. "pam login" for the rest--including cross-user
local logins.

As far as I can make out, the only way to make "optident" unsafe is to
have  a matching rule following that it either (1) is a "trust" rule or
(2) demands a plaintext password login on a non-local, unencrypted
connection (and actually gets used while someone is intercepting the
packets).  If you configure either of those, I'd say you're on thin ice
anyway.  It certainly goes right against the "increasingly strict,
decreasingly specific" guideline.


> ... and this particular approach would break more installations'
> security than I really want to think about.  It's not really a new ident
> method, it's a very fundamental change in the semantics of pg_hba.conf.

Sure.  But only when people use it, and then it can be used for good or
for evil like anything else.  A new authentication method that's not in
the default config doesn't affect anyone's installation all by itself.


> As an example of how much it would change things, the "reject" auth
> option would become a useless no-op.

How?  Why?  Naturally I tested it in combination with "reject" and it
still rejected just as it should: "optident X" plus "reject" matching the
same login add up to a regular "ident X."  Same for "optident X" when it's
not followed by another matching rule: if you're mapped you're in, if
you're not mapped you're out.  It just gives you the ability to follow up
with a fallback rule that actually authenticates.

The simplest way to keep optident secure is by pairing it with a second
rule that has the same fields to the left of the authentication method,
but gives a stricter authentication method.  Second-simplest way: don't
use plaintext passwords on unencrypted, non-local connections across
unsafe networks and don't do "trust" anywhere.  Third-simplest way: follow
the existing guideline of starting with specific, permissive rules and
working your way towards broad, strict rules.

If there are any problems with that, of course I'd like to hear about them.


Jeroen




Re: "Optional ident" authentication

От
Andrew Dunstan
Дата:

Jeroen T. Vermeulen wrote:
> On Sun, November 26, 2006 23:51, Tom Lane wrote:
>   
>>> Is there a reason other than existing code why HBA should not allow
>>> "ident" to be combined with other authentication methods?
>>>       
>> How about that it's a bad idea?  A combo method seems ideally suited
>> to security holes, in the form of letting through unintended logins.
>>     
>
> Well, that's why I'm asking.  But I was hoping for something more concrete
> than "it could possibly be misconfigured."  Especially when we still
> generate default configs that say "trust" for all local logins!
>
> The Debian package does come with a safer default config using "ident
> sameuser."  For a packager-maintained setup like that, where you know
> beforehand that both the backend and the system do PAM, it might make
> sense to have that passwordless "ident sameuser" login on local
> connections but use e.g. "pam login" for the rest--including cross-user
> local logins.
>
> As far as I can make out, the only way to make "optident" unsafe is to
> have  a matching rule following that it either (1) is a "trust" rule or
> (2) demands a plaintext password login on a non-local, unencrypted
> connection (and actually gets used while someone is intercepting the
> packets).  If you configure either of those, I'd say you're on thin ice
> anyway.  It certainly goes right against the "increasingly strict,
> decreasingly specific" guideline.
>
>
>   
>> ... and this particular approach would break more installations'
>> security than I really want to think about.  It's not really a new ident
>> method, it's a very fundamental change in the semantics of pg_hba.conf.
>>     
>
> Sure.  But only when people use it, and then it can be used for good or
> for evil like anything else.  A new authentication method that's not in
> the default config doesn't affect anyone's installation all by itself.
>
>
>   
>> As an example of how much it would change things, the "reject" auth
>> option would become a useless no-op.
>>     
>
> How?  Why?  Naturally I tested it in combination with "reject" and it
> still rejected just as it should: "optident X" plus "reject" matching the
> same login add up to a regular "ident X."  Same for "optident X" when it's
> not followed by another matching rule: if you're mapped you're in, if
> you're not mapped you're out.  It just gives you the ability to follow up
> with a fallback rule that actually authenticates.
>
> The simplest way to keep optident secure is by pairing it with a second
> rule that has the same fields to the left of the authentication method,
> but gives a stricter authentication method.  Second-simplest way: don't
> use plaintext passwords on unencrypted, non-local connections across
> unsafe networks and don't do "trust" anywhere.  Third-simplest way: follow
> the existing guideline of starting with specific, permissive rules and
> working your way towards broad, strict rules.
>
> If there are any problems with that, of course I'd like to hear about them.
>
>
>
>   

Quite apart from security concerns, I find this design awkward. If we 
have a fallback mechanism, shouldn't it be available for all auth 
methods (except, as Tom rightly points out, for reject)? ISTM that the 
fallback behaviour of a rule should be specified separately from the 
auth method.

cheers

andrew


Re: "Optional ident" authentication

От
Tom Lane
Дата:
Andrew Dunstan <andrew@dunslane.net> writes:
> Quite apart from security concerns, I find this design awkward.

That's really the basis of my objection to it: having an auth method
that changes the basic semantics of the surrounding logical structure
is, at best, awkward and confusing.  When it's in a security-critical
context, those attributes get triple demerits because of the risk of
unforeseen consequences at the implementation level (eg, clients not
being prepared for two successive login challenges of different kinds),
not to mention the likelihood of an admin writing a pg_hba.conf file
that doesn't do what he expected because he didn't understand what would
happen.

The examples given at the top of the thread don't seem to me to justify
any new contortions anyway:

>> My personal itch is that I'd like to have an "ident sameuser"
>> authentication that falls back on, say, PAM authentication when system
>> user A wants to log into postgres under a different username B.

You can accomplish that with
local    sameuser    all    ident sameuserlocal    all        all    pam

>> ... to grant a web application or daemon passwordless
>> login to its database while other users still need a password.
local    webapp,daemon    all    ident sameuserlocal    all        all    pam
        regards, tom lane


Re: "Optional ident" authentication

От
"Jeroen T. Vermeulen"
Дата:
On Mon, November 27, 2006 09:05, Tom Lane wrote:
> Andrew Dunstan <andrew@dunslane.net> writes:
>> Quite apart from security concerns, I find this design awkward.

It is.  I've considered adding a field, but that was a radical change to
the configuration file format and to the parsing code, which may also be
re-used for other purposes.


> That's really the basis of my objection to it: having an auth method
> that changes the basic semantics of the surrounding logical structure
> is, at best, awkward and confusing.  When it's in a security-critical
> context, those attributes get triple demerits because of the risk of
> unforeseen consequences at the implementation level (eg, clients not
> being prepared for two successive login challenges of different kinds),

Oh, I agree.  That's why I chose the solution that guaranteed at most one
interactive authentication method per login attempt.  Prompting the user
for, say, an LDAP password and then for a postgres password as an
alternative is confusing and unpleasant.

So I reasoned like this: when you stack authentication rules, only the
last one should ever be interactive.  Only one authentication method is
provably noninteractive: ident.  (Actually, ident already prompts for a
password if it fails--the password just doesn't go anywhere and that is
the part you can change with optident).

There is one other authentication method that *can* be noninteractive:
PAM.  Whether it is interactive depends on its own configuration.  PAM is
nicely flexible, but there is one thing it can't do.  It can't skip the
interaction when the client is already running under the right user
identity.  It can't do that because PAM is running in the client's process
context, which may be compromised.  There's just no reliable way for PAM
or any other client-side authentication library to know that it's really
running under the user id it thinks it is.

But ident, on the server side, does have reliable information in the form
of the client socket.  That makes "ident" a perfect complement to PAM or
other (interactive) authentication methods.

What I documented in my patch is "only noninteractive authentication
methods may fall through."  How that translates into a configuration file
format is a separate issue, but I figured it was better to introduce a new
authentication method than to change the configuration file format and
introduce an option to all authentication methods that really only makes
sense with one of them.


>>> My personal itch is that I'd like to have an "ident sameuser"
>>> authentication that falls back on, say, PAM authentication when system
>>> user A wants to log into postgres under a different username B.
>
> You can accomplish that with
>
>     local    sameuser    all    ident sameuser
>     local    all        all    pam

Yes, but I wouldn't call it more elegant or harder to misconfigure.  The
behaviour I'm looking for (and I think it's a fairly basic and useful
thing) is a combination of (1) coupling system user names to database user
names and (2) forgoing interaction when it's not needed.  What you suggest
here draws the database name into the equation, which to me is
counterintuitive and makes the solution less generic.

I'll agree that your example is harder to configure _unsafely_.  But when
people cannot get exactly the authentication scheme they want, they'll
usually end up with a more permissive one.  In that sense I don't see your
trick as inherently safer than optident.


>>> ... to grant a web application or daemon passwordless
>>> login to its database while other users still need a password.
>
>     local    webapp,daemon    all    ident sameuser
>     local    all        all    pam

Wait...  Tom, are you switching the database and user fields around? 
AFAICS this allows _all_ users passwordless access to databases called
"webapp" or "daemon."  Probably not what you want, but you might not
notice because your application kept running and people rarely complain
that they're not being prompted for a password.

If you're just doing this to prove your point about the risks of
misconfiguration, here's how you could do a similar thing with optident,
for all databases and users:

local    all    all        optident sameuser
local    all    all        pam

I think that's less error-prone, not more so.

Also, what if you want to grant specific system users passwordless login
under specific role names?  AFAICS you'd end up writing the username in
both the usermap *and* the user field of pg_hba.conf.  Let's say you have
a usermap that looked like this:

custommap  jack  webapp
custommap  jill  daemon

Now you can grant that access like this:

local    all    webapp,daemon  ident custommap
local    all    all            pam

With optident, you don't need the double listing of usernames:

local    all    webapp,daemon  ident custommap
local    all    all            pam

If you want to combine custommap with sameuser and still allow PAM login
for all other local connections:

local    all    all            optident custommap
local    all    all            optident sameuser
local    all    all            pam

You've shown that you can simulate this with the existing HBA, but at what
cost?  You're restricted to the case where database names match user
names.  You must remember to duplicate the usernames in your usermaps
exactly to the corresponding places in pg_hba.conf.  You still can't grant
system user jack passwordless login as "postgres" on two or more databases
while requiring passwords from everyone else who wants to do that.  And
you've shown us a dangerous mistake in just 4 lines using the existing
system.

All of this is easy with optident, AFAICS.  So what if my patch changes
the way HBA works?  The existing HBA may be good and simple, but it's not
perfect.  The patch gives you more flexibility in improving it: you can
add a "required but not sufficient" ident in the future, if you want, or
do other checks based on dynamic criteria.  You can have fallbacks from
mechanisms that aren't always available.  You get all of this without any
changes or incompatibilities to existing configuration files.  Any risk
happens when people choose to use it, and if they do, that probably means
that it's useful.


Jeroen




Re: "Optional ident" authentication

От
"Florian G. Pflug"
Дата:
Tom Lane wrote:
>>> My personal itch is that I'd like to have an "ident sameuser"
>>> authentication that falls back on, say, PAM authentication when system
>>> user A wants to log into postgres under a different username B.
> 
> You can accomplish that with
> 
>     local    sameuser    all    ident sameuser
>     local    all        all    pam

You put "sameuser" in the database column instead of the "user" column -
was the intentional? I've just tried this with "sameuser" in the user 
column, and it didn't work for me. I've also searched the docs, and I
only found three references to "sameuser". One described "ident 
sameuser", while the other two were in the changelog, and told me that
"sameuser" support in the _database_ column was introduced in 6.4, and
that quoting removes the special meaning of sameuser since 8.0.

Should sameuser work instead of all in the user column?

greetings, Florian Pflug


Re: "Optional ident" authentication

От
Tom Lane
Дата:
"Florian G. Pflug" <fgp@phlo.org> writes:
> Tom Lane wrote:
>> You can accomplish that with
>> 
>> local    sameuser    all    ident sameuser
>> local    all        all    pam

> You put "sameuser" in the database column instead of the "user" column -
> was the intentional? I've just tried this with "sameuser" in the user 
> column, and it didn't work for me.

You're right, I was confusing the database-column feature with what's
involved here.  There isn't really any way for "sameuser" to work in the
user column, since that would require a way to identify the user's
non-database username, which is exactly the province of the auth method.
So never mind :-(.

But I still question whether Jeroen's got any real use case that can't
be handled the other way, viz
local    webapp,etc    all    ident sameuser
        regards, tom lane


Re: "Optional ident" authentication

От
"Florian G. Pflug"
Дата:
Tom Lane wrote:
> "Florian G. Pflug" <fgp@phlo.org> writes:
>> Tom Lane wrote:
>>> You can accomplish that with
>>>
>>> local    sameuser    all    ident sameuser
>>> local    all        all    pam
> 
>> You put "sameuser" in the database column instead of the "user" column -
>> was the intentional? I've just tried this with "sameuser" in the user 
>> column, and it didn't work for me.
> 
> You're right, I was confusing the database-column feature with what's
> involved here.  There isn't really any way for "sameuser" to work in the
> user column, since that would require a way to identify the user's
> non-database username, which is exactly the province of the auth method.
> So never mind :-(.
> 
> But I still question whether Jeroen's got any real use case that can't
> be handled the other way, viz

While I agree that the original proposal was a bit hackish, I'd love
to be able to specifiy "First try this auth method, and fall back to
another if the first didn't succeed".

I, for example, have a large ldap directory that contains one posixAccount
entry for each of my customers. Postgres on my database server authenticates
against that directory via pam, and my webservers are set up to run each
customers cgi-scripts under his own account. To make things easier
for customers, the webserver is running gidentd, and my database server uses
ident authentication for connections from the webserver. Thus you only need
to specify the database name and the hostname of my db server in cgi-scripts -
no need for passwords (or usernames).

Now, sometimes a customers cgi-scripts needs to be able to connect to another
customers database. Currently, I need to change pg_hba.conf to let him do that.
If I could chain authentication methods, I could just tell my customers they need
a password to connect to a foreign database, but don't one one to connect to their
own database.

I believe it would be sufficient to add an additional column to pg_hba.conf
called "On Failure". The value could either be "Continue" or "Abort", with
the default being "Abort" to match the current behaviour.

If there is a chance that a patch like that would be accepted I could try to
modify Jeroen's patch to support that - but I have very little free time at
the moment, so it might take me a while to get it done...

greetings, Florian Pflug



Re: "Optional ident" authentication

От
Tom Lane
Дата:
"Florian G. Pflug" <fgp@phlo.org> writes:
> I believe it would be sufficient to add an additional column to pg_hba.conf
> called "On Failure". The value could either be "Continue" or "Abort", with
> the default being "Abort" to match the current behaviour.

Then you get into the problem that it has to work for *all* auth
methods, which in general it will not, because the client probably isn't
prepared for multiple auth challenges.  Jeroen's kluge avoids that by
only working for an auth method that doesn't involve a client challenge.

The example you cited is easily implemented without any new features,
anyway, using "samegroup":
local    all    samegroup    ident sameuserlocal    all    all        md5

where users are made members of the group/role named after the database
they are allowed to log into without a password.
        regards, tom lane


Re: "Optional ident" authentication

От
Andrew Dunstan
Дата:
Tom Lane wrote:
> "Florian G. Pflug" <fgp@phlo.org> writes:
>   
>> I believe it would be sufficient to add an additional column to pg_hba.conf
>> called "On Failure". The value could either be "Continue" or "Abort", with
>> the default being "Abort" to match the current behaviour.
>>     
>
> Then you get into the problem that it has to work for *all* auth
> methods, which in general it will not, because the client probably isn't
> prepared for multiple auth challenges.  Jeroen's kluge avoids that by
> only working for an auth method that doesn't involve a client challenge.
>   

Yes, if we did that we'd probably have to fix libpq to allow for it (and 
any native protocol implementations such as JDBC). Can the wire protocol 
handle it?

> The example you cited is easily implemented without any new features,
> anyway, using "samegroup":
>
>     local    all    samegroup    ident sameuser
>     local    all    all        md5
>
> where users are made members of the group/role named after the database
> they are allowed to log into without a password.
>
>             
>   

I was just composing almost this identical example ;-)

'samegroup' is a much overlooked feature, I believe, and should be 
extremely useful for hosting providers especially.

cheers

andrew



Re: "Optional ident" authentication

От
Tom Lane
Дата:
Andrew Dunstan <andrew@dunslane.net> writes:
> Tom Lane wrote:
>> Then you get into the problem that it has to work for *all* auth
>> methods, which in general it will not, because the client probably isn't
>> prepared for multiple auth challenges.

> Yes, if we did that we'd probably have to fix libpq to allow for it (and 
> any native protocol implementations such as JDBC). Can the wire protocol 
> handle it?

Not really --- the problem is what does a client do if faced with an
unanswerable challenge, eg password requested when it has no password.
libpq currently just disconnects.  You could maybe kluge it to send back
an empty password or some such, but it'd be better if the protocol had
an explicit "fail" response.  In any case, "let's fix all the clients"
isn't very practical --- what of clients running older copies of libpq?
        regards, tom lane


Re: "Optional ident" authentication

От
"Jeroen T. Vermeulen"
Дата:
On Tue, November 28, 2006 22:21, Tom Lane wrote:
> "Florian G. Pflug" <fgp@phlo.org> writes:
>> I believe it would be sufficient to add an additional column to
>> pg_hba.conf
>> called "On Failure". The value could either be "Continue" or "Abort",
>> with
>> the default being "Abort" to match the current behaviour.
>
> Then you get into the problem that it has to work for *all* auth
> methods, which in general it will not, because the client probably isn't
> prepared for multiple auth challenges.  Jeroen's kluge avoids that by
> only working for an auth method that doesn't involve a client challenge.

...Or more precisely, by specifying that interactive auth methods
shouldn't ever fall through.  I think ident is fundamentally different
from all the other auth methods, and frankly I think the real problem is
that it doesn't quite fit in as one.

Adding an "on failure" field to the config file isn't perfect either,
IMHO, because it only works for failures.  With ident, it might also make
sense to stack auth methods in a restrictive way: "this particular login
must be allowed by this ident map *and* authenticate through LDAP as
usual."

I think HBA configuration would work better if more arguments were
possible on the *matching* side of pg_hba.conf, alongside "database" and
"user."  Things are already ugly because "ssl" didn't quite fit in there:
that looks like it should've been an optional argument in matching
connections to HBA rules.

If we had optional matching arguments, I think ident would be a matching
option by nature--not an authentication method at all.  The existing
"ident sameuser" would be shorthand for a "trust" rule matching on the
ident map, followed by a "reject" rule for the same connections but
without the ident argument.  If you left out the "reject," you'd have the
"ident sameuser" behaviour but with fallback to regular authentication.

You could also have separate authentication methods based on what the
system wants for a particular user, without requiring any coupling to
databases or roles.  Most of that job should probably be left to PAM where
available, but it just so happens that "ident" does a job that PAM isn't
able to.

But I'll admit that all of that is making things a bit complex and
therefore error-prone.


> The example you cited is easily implemented without any new features,
> anyway, using "samegroup":
>
>     local    all    samegroup    ident sameuser
>     local    all    all        md5
>
> where users are made members of the group/role named after the database
> they are allowed to log into without a password.

Nice one--at least that way you're not tying database names to user names
(on a side note, I see that "samegroup" is obsolescent--it's "samerole"
now).  But AFAICS it still doesn't allow you to fall back to interactive
authentication for "cross-identity" logins: those will just fail even if
you would want the user on the other end to be able to log in, assuming he
knows the password.  Yes, you've shown that you can simulate that with the
existing HBA format but I wouldn't want to maintain a configuration like
that!


Jeroen