Thread: Logging of PAM Authentication Failure

Logging of PAM Authentication Failure

From
Amit Langote
Date:
Hello,

When client authentication method is set to "pam" in pg_hba.conf,
connecting using psql results in logging of authentication failure
even before a password prompt is provided, nonetheless user is
subsequently able to connect by providing a password. Following is
what is logged:

Password: LOG:  pam_authenticate failed: Conversation error
FATAL:  PAM authentication failed for user "amit"

To see what's going on I debugged psql and found that without a -W
option, this is bound to happen, since psql first attempts to connect
and without a password (which it doesn't know is required for the
first time), it fails and subsequently prompts for password. Correct
password then leads to successful connection.

I tried to observe the behavior with md5 method (without -W) and
observed that no authentication failure is logged, since server
probably behaves differently in response to the psql's first
connection request in that case. But, pam method leads to it being
logged.

Is this a problem?

--

Amit Langote



Re: Logging of PAM Authentication Failure

From
Robert Haas
Date:
On Wed, May 8, 2013 at 10:40 PM, Amit Langote <amitlangote09@gmail.com> wrote:
> When client authentication method is set to "pam" in pg_hba.conf,
> connecting using psql results in logging of authentication failure
> even before a password prompt is provided, nonetheless user is
> subsequently able to connect by providing a password. Following is
> what is logged:
>
> Password: LOG:  pam_authenticate failed: Conversation error
> FATAL:  PAM authentication failed for user "amit"
>
> To see what's going on I debugged psql and found that without a -W
> option, this is bound to happen, since psql first attempts to connect
> and without a password (which it doesn't know is required for the
> first time), it fails and subsequently prompts for password. Correct
> password then leads to successful connection.
>
> I tried to observe the behavior with md5 method (without -W) and
> observed that no authentication failure is logged, since server
> probably behaves differently in response to the psql's first
> connection request in that case. But, pam method leads to it being
> logged.
>
> Is this a problem?

Not really.  We could potentially fix it by extending the wire
protocol to allow the server to respond to the client's startup packet
with a further challenge, and extend libpq to report that challenge
back to the user and allow sending a response.  But that would break
on-the-wire compatibility, which we haven't done in a good 10 years,
and certainly wouldn't be worthwhile just for this.

We'd also need to be careful not to create information leaks.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: Logging of PAM Authentication Failure

From
Tom Lane
Date:
Robert Haas <robertmhaas@gmail.com> writes:
> On Wed, May 8, 2013 at 10:40 PM, Amit Langote <amitlangote09@gmail.com> wrote:
>> I tried to observe the behavior with md5 method (without -W) and
>> observed that no authentication failure is logged, since server
>> probably behaves differently in response to the psql's first
>> connection request in that case. But, pam method leads to it being
>> logged.

auth_failed() in src/backend/libpq/auth.c intentionally logs nothing for
STATUS_EOF status (ie, client closed the connection without responding).
But it looks like the PAM code path doesn't have a way to return that
status code, even when pam_passwd_conv_proc() knows that that's what
happened, and intentionally printed no log message itself (around line
1870 in HEAD).  If there's another response code we could return through
the PAM layer, this could be fixed, and I think it should be.

>> Is this a problem?

> Not really.  We could potentially fix it by extending the wire
> protocol to allow the server to respond to the client's startup packet
> with a further challenge, and extend libpq to report that challenge
> back to the user and allow sending a response.  But that would break
> on-the-wire compatibility, which we haven't done in a good 10 years,
> and certainly wouldn't be worthwhile just for this.

It's not the wire protocol that's the problem; it's that libpq's client
API doesn't provide a way to ask the calling application for a password
in the midst of a connection attempt.
        regards, tom lane



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
> auth_failed() in src/backend/libpq/auth.c intentionally logs nothing for
> STATUS_EOF status (ie, client closed the connection without responding).
> But it looks like the PAM code path doesn't have a way to return that
> status code, even when pam_passwd_conv_proc() knows that that's what
> happened, and intentionally printed no log message itself (around line
> 1870 in HEAD).  If there's another response code we could return through
> the PAM layer, this could be fixed, and I think it should be.

So if I get this correctly, does this mean the only thing that needs
to be fixed is unnecessary logging or is there a problem with
authentication exchange itself in case of PAM? Also, when you say PAM
layer, is that pam_passwd_conv_proc() that needs to be able to return
an alternative status code?


--
Amit Langote



Re: Logging of PAM Authentication Failure

From
Kyotaro HORIGUCHI
Date:
Hello,

> > auth_failed() in src/backend/libpq/auth.c intentionally logs nothing for
> > STATUS_EOF status (ie, client closed the connection without responding).
> > But it looks like the PAM code path doesn't have a way to return that
> > status code, even when pam_passwd_conv_proc() knows that that's what
> > happened, and intentionally printed no log message itself (around line
> > 1870 in HEAD).  If there's another response code we could return through
> > the PAM layer, this could be fixed, and I think it should be.
> 
> So if I get this correctly, does this mean the only thing that needs
> to be fixed is unnecessary logging or is there a problem with
> authentication exchange itself in case of PAM? Also, when you say PAM
> layer, is that pam_passwd_conv_proc() that needs to be able to return
> an alternative status code?

Following is the point server requests psql to send password when
PAM is enabled.

backend/libpq/auth.c:1861
>   if (strlen(passwd) == 0)
>   {
>     /*
>      * Password wasn't passed to PAM the first time around -
>      * let's go ask the client to send a password, which we
>      * then stuff into PAM.
>      */
>     sendAuthRequest(pam_port_cludge, AUTH_REQ_PASSWORD);
>     passwd = recv_password_packet(pam_port_cludge);
>     if (passwd == NULL)
>     {
>       /*
>        * Client didn't want to send password.  We
>        * intentionally do not log anything about this.
>        */
>       goto fail;
...
>    return PAM_CONV_ERR;


This code seems to me expecting for psql to send password without
closing current connnection.On the other hand psql does as
follows.

bin/psql/startup.c: 227
>    pset.db = PQconnectdbParams(keywords, values, true);
>    free(keywords);
>    free(values);
>
>    if (PQstatus(pset.db) == CONNECTION_BAD &&
>      PQconnectionNeedsPassword(pset.db) &&
>      password == NULL &&
>      pset.getPassword != TRI_NO)
>    {
>      PQfinish(pset.db);
>      password = simple_prompt(password_prompt, 100, false);
>      new_pass = true;
>    }

psql at once disconnects the current connection and reconnects
with this new password, so pam_conv_err is observed in server.

It seems to be a kind of protocol-mimatching. Client should'nt
disconnect for password request or server should fit to what psql
does. Is this wrong?

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
> This code seems to me expecting for psql to send password without
> closing current connnection.On the other hand psql does as
> follows.
>
> bin/psql/startup.c: 227
>>    pset.db = PQconnectdbParams(keywords, values, true);
>>    free(keywords);
>>    free(values);
>>
>>    if (PQstatus(pset.db) == CONNECTION_BAD &&
>>      PQconnectionNeedsPassword(pset.db) &&
>>      password == NULL &&
>>      pset.getPassword != TRI_NO)
>>    {
>>      PQfinish(pset.db);
>>      password = simple_prompt(password_prompt, 100, false);
>>      new_pass = true;
>>    }
>
> psql at once disconnects the current connection and reconnects
> with this new password, so pam_conv_err is observed in server.
>
> It seems to be a kind of protocol-mimatching. Client should'nt
> disconnect for password request or server should fit to what psql
> does. Is this wrong?

In fact, this is the behavior with all the authentication methods that
require a password. But, it is only in the case of PAM authentication
that auth_failed() logs error when first connection attempt is made
(without password), since the STATUS_EOF is not passed to it in that
case.
If we did not drop the connection (unlike what we do now) and
re-attempted connection with the password added to conn, would the
backend's authentication state still be waiting for the password? Can
we do away without having to create a second connection?
--
Amit Langote



Re: Logging of PAM Authentication Failure

From
Kyotaro HORIGUCHI
Date:
> In fact, this is the behavior with all the authentication methods that
> require a password. But, it is only in the case of PAM authentication
> that auth_failed() logs error when first connection attempt is made
> (without password), since the STATUS_EOF is not passed to it in that
> case.

Well, if we are allowed to use a bit ugry way, the attached patch
seems to cope with this issue. As far as I can see there's no
problem since pg_fe_sendauth() refueses to send empty password.

Any suggestions?

> If we did not drop the connection (unlike what we do now) and
> re-attempted connection with the password added to conn, would the
> backend's authentication state still be waiting for the password? Can
> we do away without having to create a second connection?

Sorry, I've read there incorrectly. I had understood the code
after sendAuthRequest in pam_passwd_conv_proc but it is used
indeed.

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index 3a041d9..304df03 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -1816,6 +1816,7 @@ auth_peer(hbaPort *port) * PAM conversation function */
+static int pam_auth_eof = false;static intpam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
         struct pam_response ** resp, void *appdata_ptr)
 
@@ -1824,6 +1825,8 @@ pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,    struct pam_response *reply;
  int            i;
 
+    pam_auth_eof = false;
+    if (appdata_ptr)        passwd = (char *) appdata_ptr;    else
@@ -1872,6 +1875,7 @@ pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,                         *
Clientdidn't want to send password.  We                         * intentionally do not log anything about this.
               */
 
+                        pam_auth_eof = true;                        goto fail;                    }
if(strlen(passwd) == 0)
 
@@ -1986,6 +1990,16 @@ CheckPAMAuth(Port *port, char *user, char *password)    retval = pam_authenticate(pamh, 0);
+    /*
+     * pam_auth_eof is true when the client disconnected for password request
+     * in pam_passw_conv().
+     */
+    if (pam_auth_eof)
+    {
+        pam_passwd = NULL;        /* Unset pam_passwd */
+        return STATUS_EOF;
+    }
+    if (retval != PAM_SUCCESS)    {        ereport(LOG,

Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
> Well, if we are allowed to use a bit ugry way, the attached patch
> seems to cope with this issue. As far as I can see there's no
> problem since pg_fe_sendauth() refueses to send empty password.
>
> Any suggestions?

That seems to do the trick. This probably solves the problem that I
originally posted.

> Sorry, I've read there incorrectly. I had understood the code
> after sendAuthRequest in pam_passwd_conv_proc but it is used
> indeed.

Though, I am still not sure why we drop the existing connection and
start all over again but now with the newly entered password. This
kind of seems to leave the protocol state machine (as in
PQconnectPoll() ) halfway (after pg_fe_sendauth() failed) in the first
connection attempt for the auth requests requiring the password (or
others, too?). Although, sticking to this design may have to do with
the problems of doing otherwise that I am unaware of.


--
Amit Langote



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
Hello,

Is it right that it is only in the case a password prompt is needed
that a new connection is created after dropping the just-failed
connection?
I created a patch which enables it to use the existing connection in
such a case (unlike what we currently do). It modifies
connectDBComplete() and PQconnectPoll() to also include states
pertaining to password being accepted from the user. That is, the
state machine in PQconnectPoll() is further extended to include a
connection state called CONNECTION_ASKING_PASSWORD which is entered
when server sends AUTH_REQ_MD5 or AUTH_REQ_PASSWORD auth requests.
These two request types require a password to be entered by the user.
There is a new PostgresPollingStatusType value called
PGRES_POLLING_WAITING_PASSWORD which is the polling status while a
password is being entered by the user.

When user enters the password the PQconnectPoll() continues forward in
CONNECTION_ASKING_PASSWORD wherein it sends the password to the server
(by calling pg_fe_sendauth() and this time with a potentially correct
password) and later goes back to CONNECTION_AWAITING_RESPONSE to read
server's response to the password just entered where it either
receives authorization OK or error response thus completing the
connection start-up process.

The backend waits for the password until authentication timeout
happens in which case the client can not send the password anymore
since the backend has exited due to authentication timeout. I wonder
if this is one of the reasons why this has not already been
implemented?

Comments?

On Tue, May 14, 2013 at 11:22 AM, Amit Langote <amitlangote09@gmail.com> wrote:
>> Well, if we are allowed to use a bit ugry way, the attached patch
>> seems to cope with this issue. As far as I can see there's no
>> problem since pg_fe_sendauth() refueses to send empty password.
>>
>> Any suggestions?
>
> That seems to do the trick. This probably solves the problem that I
> originally posted.
>
>> Sorry, I've read there incorrectly. I had understood the code
>> after sendAuthRequest in pam_passwd_conv_proc but it is used
>> indeed.
>
> Though, I am still not sure why we drop the existing connection and
> start all over again but now with the newly entered password. This
> kind of seems to leave the protocol state machine (as in
> PQconnectPoll() ) halfway (after pg_fe_sendauth() failed) in the first
> connection attempt for the auth requests requiring the password (or
> others, too?). Although, sticking to this design may have to do with
> the problems of doing otherwise that I am unaware of.
>
>
> --
> Amit Langote



--

Amit Langote

Attachment

Re: Logging of PAM Authentication Failure

From
Robert Haas
Date:
On Tue, May 14, 2013 at 11:20 AM, Amit Langote <amitlangote09@gmail.com> wrote:
> Hello,
>
> Is it right that it is only in the case a password prompt is needed
> that a new connection is created after dropping the just-failed
> connection?
> I created a patch which enables it to use the existing connection in
> such a case (unlike what we currently do). It modifies
> connectDBComplete() and PQconnectPoll() to also include states
> pertaining to password being accepted from the user. That is, the
> state machine in PQconnectPoll() is further extended to include a
> connection state called CONNECTION_ASKING_PASSWORD which is entered
> when server sends AUTH_REQ_MD5 or AUTH_REQ_PASSWORD auth requests.
> These two request types require a password to be entered by the user.
> There is a new PostgresPollingStatusType value called
> PGRES_POLLING_WAITING_PASSWORD which is the polling status while a
> password is being entered by the user.
>
> When user enters the password the PQconnectPoll() continues forward in
> CONNECTION_ASKING_PASSWORD wherein it sends the password to the server
> (by calling pg_fe_sendauth() and this time with a potentially correct
> password) and later goes back to CONNECTION_AWAITING_RESPONSE to read
> server's response to the password just entered where it either
> receives authorization OK or error response thus completing the
> connection start-up process.
>
> The backend waits for the password until authentication timeout
> happens in which case the client can not send the password anymore
> since the backend has exited due to authentication timeout. I wonder
> if this is one of the reasons why this has not already been
> implemented?
>
> Comments?

Please add patches here so they don't get forgotten:

https://commitfest.postgresql.org/action/commitfest_view/open

Do we really need to add *2* new libpq functions just to support this?

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
> Please add patches here so they don't get forgotten:
>
> https://commitfest.postgresql.org/action/commitfest_view/open
>
> Do we really need to add *2* new libpq functions just to support this?

I will add the patches to commitfest after reviewing it a bit to see
if we can do away without having to create more new functions than
necessary and make appropriate changes.

--
Amit Langote



Re: Logging of PAM Authentication Failure

From
Kyotaro HORIGUCHI
Date:
> Is it right that it is only in the case a password prompt is needed
> that a new connection is created after dropping the just-failed
> connection?

It's quite doubtful.\:-p The sequense seems fragile to say the
least. Inserting password request state into the client-side state
machine looks quite reasonable.

> I created a patch which enables it to use the existing connection in
> such a case (unlike what we currently do). It modifies
> connectDBComplete() and PQconnectPoll() to also include states
> pertaining to password being accepted from the user. That is, the
> state machine in PQconnectPoll() is further extended to include a
> connection state called CONNECTION_ASKING_PASSWORD which is entered
> when server sends AUTH_REQ_MD5 or AUTH_REQ_PASSWORD auth requests.

Great! The new client state seems to be effective also for MD5.  But
it seems to break existing libpq client doing the same authentication
sequence as current psql. Some means would be necessary to switch the
behavior when password is not previously provided but needed by the
server, or make the first half of the connection sequence to be
compatible to the current sequence - in other words - It should be
that when the user finds stauts is CONNECTION_BAD and
PQconnectionNeedsPassword() == true, the user can throw away the
connection and make new connection providing password, and also can
send password on existing connection.

the old style

|   db = PQconnectXXXX();
|   if (PQstatus(db) == CONNECTION_BAD && PQconnectionNeedsPassword(db))
|   {
|     PQfinish(db);
|     value[..] = password = <some means to read password>;
|     db = PQconnectXXXX();
|     if (PQstatus(db) == CONNECTION_BAD)
|        <error>

and the new style

|   db = PQconnectXXXX();
|   if (PQconnectionNeedsPassword(db))
|      PQsendPassword(db, password);
|   if (PQstatus(db) == CONNECTION_BAD)
|      <error>

should be standing together.

Where, PQsendPassword is combined function of PQcopyPassword and
PQcontinuedbConnect. If the only porpose of these functions is sending
password then these functions are needed to be separately.

What do you think for the compatibility and simpler API.

> These two request types require a password to be entered by the user.
> There is a new PostgresPollingStatusType value called
> PGRES_POLLING_WAITING_PASSWORD which is the polling status while a
> password is being entered by the user.
>
> When user enters the password the PQconnectPoll() continues forward in
> CONNECTION_ASKING_PASSWORD wherein it sends the password to the server
> (by calling pg_fe_sendauth() and this time with a potentially correct
> password) and later goes back to CONNECTION_AWAITING_RESPONSE to read
> server's response to the password just entered where it either
> receives authorization OK or error response thus completing the
> connection start-up process.
>
> The backend waits for the password until authentication timeout
> happens in which case the client can not send the password anymore
> since the backend has exited due to authentication timeout. I wonder
> if this is one of the reasons why this has not already been
> implemented?
>
> Comments?

Hmmm. On current implement, server is not running while the client is
reading password so the authentication timeout is provided only for
hostile clients.  Conversely, the new sequence can enforce true
authentication timeout. It results in error after leaving the password
prompt for 60 seconds. I suppose that more desirable behavior in spite of
the poor message..

| Password: <waiting over 60 seconds and ENTER RETURN>
| psql: fe_sendauth: error sending password authentication

The point at issue now seems how to inform the timeout to the client
under reading password, especially prohibiting using thread nor
SIGALRM.

Providing password input function in libpq like below might make it
viable using select(2).

PQsendPassword(prompt="Passowrd: ", in_fd = stdin)

Any thoughts?

regareds,

--
Kyotaro Horiguchi



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
On Wed, May 15, 2013 at 11:04 PM, Kyotaro HORIGUCHI
<kyota.horiguchi@gmail.com> wrote:
>> Is it right that it is only in the case a password prompt is needed
>> that a new connection is created after dropping the just-failed
>> connection?
>
> It's quite doubtful.\:-p The sequense seems fragile to say the
> least. Inserting password request state into the client-side state
> machine looks quite reasonable.

Looking at current code (well, pseudo-code!) :

do
{
new_pass = false;
<create a new connection>
if (CONNECTION_BAD && NEEDS_PASSWORD && password == NULL && ! FORCE_NO_PASSOWRD)
{
PQfinish(<current_connection>);
password = simple_prompt() ;
new_pass = true;
}
}while(new_pass)

So, it looks like the loop will be repeated only if an authentication
method requiring the user to enter password is encountered in the
PQconnectPoll() which are AUTH_REQ_MD5 & AUTH_REQ_PASSWORD. As you can
see in the following code fragment from pg_fe_sendauth() which
apparently sets conn->password_needed:
       case AUTH_REQ_MD5:       case AUTH_REQ_PASSWORD:           conn->password_needed = true;           if
(conn->pgpass== NULL || conn->pgpass[0] == '\0')           {               printfPQExpBuffer(&conn->errorMessage,
                         PQnoPasswordSupplied);               return STATUS_ERROR;           }           if
(pg_password_sendauth(conn,conn->pgpass, areq) != STATUS_OK)           {
printfPQExpBuffer(&conn->errorMessage,                   "fe_sendauth: error sending password authentication\n");
       return STATUS_ERROR;           }           break;
 

this seems to be the only code path that causes conn->password_needed
to be set to true. So, these seem to be only cases when a prompt will
be provided and new_pass would become true causing the
drop-and-reconnect by repetition of the loop. Am I missing some other
case when this might happen?

>> I created a patch which enables it to use the existing connection in
>> such a case (unlike what we currently do). It modifies
>> connectDBComplete() and PQconnectPoll() to also include states
>> pertaining to password being accepted from the user. That is, the
>> state machine in PQconnectPoll() is further extended to include a
>> connection state called CONNECTION_ASKING_PASSWORD which is entered
>> when server sends AUTH_REQ_MD5 or AUTH_REQ_PASSWORD auth requests.
>
> Great! The new client state seems to be effective also for MD5.  But
> it seems to break existing libpq client doing the same authentication
> sequence as current psql. Some means would be necessary to switch the
> behavior when password is not previously provided but needed by the
> server, or make the first half of the connection sequence to be
> compatible to the current sequence - in other words - It should be
> that when the user finds stauts is CONNECTION_BAD and
> PQconnectionNeedsPassword() == true, the user can throw away the
> connection and make new connection providing password, and also can
> send password on existing connection.

The first half of connection sequence remains same except for one
change: in PQconnectPoll(), when in case CONNECTION_AWAITING_RESPONSE,
if server sends md5/password authentication request, it returns
PGRES_POLLING_WAITING_PASSWORD, which, back in connectDBComplete()
sets conn->password = true and conn->status =
CONNECTION_ASKING_PASSWORD. Back in main(), this causes a password
prompt and then the second half of the connection sequence. Hence
pg_fe_sendauth() is not called in this first half unless it's a
different authentication method than md5 and password.

>
> the old style
>
> |   db = PQconnectXXXX();
> |   if (PQstatus(db) == CONNECTION_BAD && PQconnectionNeedsPassword(db))
> |   {
> |     PQfinish(db);
> |     value[..] = password = <some means to read password>;
> |     db = PQconnectXXXX();
> |     if (PQstatus(db) == CONNECTION_BAD)
> |        <error>
>
> and the new style
>
> |   db = PQconnectXXXX();
> |   if (PQconnectionNeedsPassword(db))
> |      PQsendPassword(db, password);
> |   if (PQstatus(db) == CONNECTION_BAD)
> |      <error>
>
> should be standing together.

I see this accounts for CONNECTION_BAD (if any) in the first half. But
this CONNECTION_BAD has other reasons than conn->password_needed as
far as I can imagine since conn->password_needed would only be set in
connectDBComplete() in PGRES_POLLING_WAITING_PASSWORD. So, this
CONNECTION_BAD would require some different processing. Thoughts?

> Where, PQsendPassword is combined function of PQcopyPassword and
> PQcontinuedbConnect. If the only porpose of these functions is sending
> password then these functions are needed to be separately.
>
> What do you think for the compatibility and simpler API.

I think one function PQsendPassword(PGconn*, char *) would be
sufficient which would contain the code of both PQcopyPassword() and
PQcontinuedbConnect(). I would complete the connection sequence by
running its second half.

>> The backend waits for the password until authentication timeout
>> happens in which case the client can not send the password anymore
>> since the backend has exited due to authentication timeout. I wonder
>> if this is one of the reasons why this has not already been
>> implemented?
>>
>> Comments?
>
> Hmmm. On current implement, server is not running while the client is
> reading password so the authentication timeout is provided only for
> hostile clients.  Conversely, the new sequence can enforce true
> authentication timeout. It results in error after leaving the password
> prompt for 60 seconds. I suppose that more desirable behavior in spite of
> the poor message..
>
> | Password: <waiting over 60 seconds and ENTER RETURN>
> | psql: fe_sendauth: error sending password authentication
>
> The point at issue now seems how to inform the timeout to the client
> under reading password, especially prohibiting using thread nor
> SIGALRM.
>
> Providing password input function in libpq like below might make it
> viable using select(2).
>
> PQsendPassword(prompt="Passowrd: ", in_fd = stdin)
>
> Any thoughts?

So, do you here propose to change simple_prompt() that would be able
to detect an authentication timeout on server and exit with an
appropriate message? I think that should be done.

I will try to revise the patch to incorporate these considerations and
post a revised patch.

--
Amit Langote



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
>>> I created a patch which enables it to use the existing connection in
>>> such a case (unlike what we currently do). It modifies
>>> connectDBComplete() and PQconnectPoll() to also include states
>>> pertaining to password being accepted from the user. That is, the
>>> state machine in PQconnectPoll() is further extended to include a
>>> connection state called CONNECTION_ASKING_PASSWORD which is entered
>>> when server sends AUTH_REQ_MD5 or AUTH_REQ_PASSWORD auth requests.
>>
>> Great! The new client state seems to be effective also for MD5.  But
>> it seems to break existing libpq client doing the same authentication
>> sequence as current psql. Some means would be necessary to switch the
>> behavior when password is not previously provided but needed by the
>> server, or make the first half of the connection sequence to be
>> compatible to the current sequence - in other words - It should be
>> that when the user finds stauts is CONNECTION_BAD and
>> PQconnectionNeedsPassword() == true, the user can throw away the
>> connection and make new connection providing password, and also can
>> send password on existing connection.
>
> The first half of connection sequence remains same except for one
> change: in PQconnectPoll(), when in case CONNECTION_AWAITING_RESPONSE,
> if server sends md5/password authentication request, it returns
> PGRES_POLLING_WAITING_PASSWORD, which, back in connectDBComplete()
> sets conn->password = true and conn->status =
> CONNECTION_ASKING_PASSWORD. Back in main(), this causes a password
> prompt and then the second half of the connection sequence. Hence
> pg_fe_sendauth() is not called in this first half unless it's a
> different authentication method than md5 and password.

One more thing that I forgot to mention is that connection sequence
would enter CONNECTION_ASKING_PASSWORD in the first half, only if
password is currently not set to a non-empty value that is (
conn->pgpass ==NULL || conn->pgpass[0] = '\0' ) is true. I was
wondering what would be the case for other applications using libpq
when they return from connectionDBComplete() with conn->status set to
CONNECTION_ASKING_PASSWORD, provided they have not set conn->pgpass to
a non-empty value.If they are currently handling this based on
CONNECTION_BAD, then this change does no good to them. In fact there
needs to be a way for them to get CONNECTION_BAD.
Since, this whole patch is about not having to drop-and-reconnect *in
case of password prompt*, how it changes libpq for other applications
also needs to be addressed here. especially for md5/password
authentication cases. Currently, any attempt to connect using empty or
NULL password results in CONNECTION_BAD for all libpq based clients.
Thoughts?



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
Sorry that I am writing separate emails on the same topic.
I seem to have a solution that allows us to accomplish what we are
trying to without much change to the existing libpq interface
(especially what to expect about return values and connection state
that we are in when we return from connectDBComplete() and
PQconnectPoll() ).

Following are required changes roughly:

1] in src/bin/psql/startup.c, main()
       if (PQstatus(pset.db) == CONNECTION_BAD &&               PQconnectionNeedsPassword(pset.db) &&
password== NULL &&               pset.getPassword != TRI_NO)       {               password =
simple_prompt(password_prompt,100, false);       /* How would this detect authentication_timeoue and exit
 
accordingly ?*/               PQsendPassword(pset.db, password);       }

And there is no do{...}while(new_pass); unlike current code.

2] in src/interfaces/libpq/fe-connect.c, new function: void
PQsendPassword(PGconn *conn, char *password)    /*suggest better name?
*/

void PQsendPassword(PGconn *conn, char *password)
{      conn->pgpass = password;      conn->status = CONNECTION_SENDING_PASSWORD;   /*suggest better
name for the status? */
      (void) connectDBComplete(conn);

}


3] in src/interfaces/libpq/fe-connect.c, connectDBComplete(PGconn
*conn), No change required. :-)

4] in in src/interfaces/libpq/fe-connect.c, PQconnectPoll(PGconn *conn)

a) add a new case for both switch's (one before and after keep_going: )

/* These are writing states, so we just proceed. */               case CONNECTION_STARTED:               case
CONNECTION_MADE:              case CONNECTION_SENDING_PASSWORD:                       break;
 
...
...
keep_going:
...
...
case CONNECTION_SENDING_PASSWORD:                        {                                /*
   ** Note that conn->pghost must be
 
non-NULL if we are going to                                ** avoid the Kerberos code doing a
hostname look-up.                                **/                               if (pg_fe_sendauth(areq, conn) !=
STATUS_OK)                              {                                       conn->errorMessage.len =
 
strlen(conn->errorMessage.data);                                       goto error_return;
}                              conn->errorMessage.len =
 
strlen(conn->errorMessage.data);
                               /*                                ** Just make sure that any data sent
by pg_fe_sendauth is                                ** flushed out.  Although this
theoretically could block, it                                ** really shouldn't since we don't
send large auth responses.                                **/                               if (pqFlush(conn))
                            goto error_return;
 
                               /*                                * Now go to read the server's
response to password just sent                                * */                               conn->status =
CONNECTION_AWAITING_RESPONSE;                              return PGRES_POLLING_READING;                       }
 

5] in src/interfaces/libpq/libpq-fe.h, add a new intermediate connection state

/** Although it is okay to add to these lists, values which become unused* should never be removed, nor should
constantsbe redefined - that would* break compatibility with existing code.*/
 

typedef enum
{       CONNECTION_OK,       CONNECTION_BAD,       /* Non-blocking mode only below here */
       /*        * The existence of these should never be relied upon - they should only        * be used for user
feedbackor similar purposes.        */       CONNECTION_STARTED,                     /* Waiting for
 
connection to be made.  */       CONNECTION_MADE,                        /* Connection OK;
waiting to send.         */       CONNECTION_AWAITING_RESPONSE,           /* Waiting for a
response from the
         * postmaster.            */       CONNECTION_AUTH_OK,                     /* Received
authentication; waiting for                                                                *
backend startup. */       CONNECTION_SETENV,                      /* Negotiating environment. */
CONNECTION_SSL_STARTUP,        /* Negotiating SSL. */       CONNECTION_NEEDED,                      /* Internal state:
 
connect() needed */       CONNECTION_SENDING_PASSWORD
} ConnStatusType;



As you can probably see this requires minimum libpq changes:

1] Add one more connection state: CONNECTION_SENDING_PASSWORD
2] Add one more function: PQsendPassword(PGconn*, char*)
3] Modify PQconnectPoll() to allow to handle an intermediate
CONNECTION_SENDING_PASSWORD state for the clients which use
PQsendPassword() to send a password that user entered in between a
connection sequence over an existing connection.

Comments?



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
Attached herewith is a patch based on description in my previous mail.
This patch would need revision since the error situation in case of
authentication timeout on the server needs to be handled; probably in
simple_prompt()?


--
Amit Langote



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
On Thu, May 16, 2013 at 3:53 PM, Amit Langote <amitlangote09@gmail.com> wrote:
> Attached herewith is a patch based on description in my previous mail.
> This patch would need revision since the error situation in case of
> authentication timeout on the server needs to be handled; probably in
> simple_prompt()?

Forgot attaching the patch in the last mail; find it with this one.


--
Amit Langote

Attachment

Re: Logging of PAM Authentication Failure

From
Andres Freund
Date:
On 2013-05-16 17:35:10 +0900, Amit Langote wrote:
> On Thu, May 16, 2013 at 3:53 PM, Amit Langote <amitlangote09@gmail.com> wrote:
> > Attached herewith is a patch based on description in my previous mail.
> > This patch would need revision since the error situation in case of
> > authentication timeout on the server needs to be handled; probably in
> > simple_prompt()?
> 
> Forgot attaching the patch in the last mail; find it with this one.

The patch seems to have windows line endings...

> --- a/src/interfaces/libpq/libpq-fe.h
> +++ b/src/interfaces/libpq/libpq-fe.h
> @@ -62,7 +62,11 @@ typedef enum
>                                   * backend startup. */
>      CONNECTION_SETENV,            /* Negotiating environment. */
>      CONNECTION_SSL_STARTUP,        /* Negotiating SSL. */
> -    CONNECTION_NEEDED            /* Internal state: connect() needed */
> +    CONNECTION_NEEDED,            /* Internal state: connect() needed */
> +    CONNECTION_SENDING_PASSWORD        /* An intermediate state to help client send a password
> +                         * over an existing connection    
> +                         */
> +                        
>  } ConnStatusType;
>  
>  typedef enum
> @@ -258,6 +262,9 @@ extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
>  #define PQsetdb(M_PGHOST,M_PGPORT,M_PGOPT,M_PGTTY,M_DBNAME)  \
>      PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, NULL, NULL)
>  
> +/* send a password that the server asked for halfway between a connection sequence */
> +extern void PQsendPassword(PGconn *conn, char *password);
> +

I unfortunately have to say I don't really see the point of this. The
cost of the additional connection attempt is rather low and we have to
deal with the superflous attempts anyway since there will be old libpqs
around for years. Why is this worth the effort?

Greetings,

Andres Freund

-- Andres Freund                       http://www.2ndQuadrant.com/PostgreSQL Development, 24x7 Support, Training &
Services



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
On Thu, May 16, 2013 at 8:01 PM, Andres Freund <andres@2ndquadrant.com> wrote:
> On 2013-05-16 17:35:10 +0900, Amit Langote wrote:
>> On Thu, May 16, 2013 at 3:53 PM, Amit Langote <amitlangote09@gmail.com> wrote:
>> > Attached herewith is a patch based on description in my previous mail.
>> > This patch would need revision since the error situation in case of
>> > authentication timeout on the server needs to be handled; probably in
>> > simple_prompt()?
>>
>> Forgot attaching the patch in the last mail; find it with this one.
>
> The patch seems to have windows line endings...

My bad. I will reupload the proper patch later.

>> --- a/src/interfaces/libpq/libpq-fe.h
>> +++ b/src/interfaces/libpq/libpq-fe.h
>> @@ -62,7 +62,11 @@ typedef enum
>>                                                                * backend startup. */
>>       CONNECTION_SETENV,                      /* Negotiating environment. */
>>       CONNECTION_SSL_STARTUP,         /* Negotiating SSL. */
>> -     CONNECTION_NEEDED                       /* Internal state: connect() needed */
>> +     CONNECTION_NEEDED,                      /* Internal state: connect() needed */
>> +     CONNECTION_SENDING_PASSWORD             /* An intermediate state to help client send a password
>> +                                              * over an existing connection
>> +                                              */
>> +
>>  } ConnStatusType;
>>
>>  typedef enum
>> @@ -258,6 +262,9 @@ extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport,
>>  #define PQsetdb(M_PGHOST,M_PGPORT,M_PGOPT,M_PGTTY,M_DBNAME)  \
>>       PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, NULL, NULL)
>>
>> +/* send a password that the server asked for halfway between a connection sequence */
>> +extern void PQsendPassword(PGconn *conn, char *password);
>> +
>
> I unfortunately have to say I don't really see the point of this. The
> cost of the additional connection attempt is rather low and we have to
> deal with the superflous attempts anyway since there will be old libpqs
> around for years. Why is this worth the effort?

While full connection sequence (with proper authentication exchanges)
appears  to go smoothly for other cases (authentication methods), it
doesn't quite in this case probably because accounting for such a case
was not considered to be as important. But while investigating about
the PAM issue (original subject of this thread), it turned out that
the occurrence of that minor issue was due to this behavior in libpq.
Addition of this one more state (viz. input password in between an
ongoing connect sequence) to the possible connection states helps
account for such instances where this kind of password exchange has to
happen (as in psql for md5 and password). Also, others using libpq can
either use it if they wish to or just do away without having to worry
about this state. This patch does not introduce any change as to what
connection state applications can expect to be in after they return
from connectDBComplete() or PQconnectPoll(). On the other hand, we can
now enter these functions with one more possible connection state
which PQconnectPoll() is now able to handle. As a side effect, it also
helps avoid drop-and-reconnect occurrences at times.

Albeit, it is up to application (using libpq) whether to go via this
new alternate path or stick to drop-and-reconnect, should a need to
input password in between connect sequence arise. We can consider
having such an option, probably just for the sake of completeness
(even if to account for a possibly rare method of authentication
exchange)


--
Amit Langote



Re: Logging of PAM Authentication Failure

From
Tom Lane
Date:
Amit Langote <amitlangote09@gmail.com> writes:
> On Thu, May 16, 2013 at 8:01 PM, Andres Freund <andres@2ndquadrant.com> wrote:
>> I unfortunately have to say I don't really see the point of this. The
>> cost of the additional connection attempt is rather low and we have to
>> deal with the superflous attempts anyway since there will be old libpqs
>> around for years. Why is this worth the effort?

> While full connection sequence (with proper authentication exchanges)
> appears  to go smoothly for other cases (authentication methods), it
> doesn't quite in this case probably because accounting for such a case
> was not considered to be as important. But while investigating about
> the PAM issue (original subject of this thread), it turned out that
> the occurrence of that minor issue was due to this behavior in libpq.

I have to agree with Andres that it's not clear this is a reasonable
fix.  To get rid of extra reconnections this way will require not merely
upgrading libpq, but upgrading every single application that uses libpq
and is capable of prompting its user for a password.  The odds are
pretty good that that won't ever happen.

The real complaint here is that the server-side PAM auth code path is
losing the information that the client chose to disconnect rather than
offer a password, and thus logging a message that we could do without.
What's wrong with just fixing that?
        regards, tom lane



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
On Fri, May 17, 2013 at 1:05 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Amit Langote <amitlangote09@gmail.com> writes:
>> On Thu, May 16, 2013 at 8:01 PM, Andres Freund <andres@2ndquadrant.com> wrote:
>>> I unfortunately have to say I don't really see the point of this. The
>>> cost of the additional connection attempt is rather low and we have to
>>> deal with the superflous attempts anyway since there will be old libpqs
>>> around for years. Why is this worth the effort?
>
>> While full connection sequence (with proper authentication exchanges)
>> appears  to go smoothly for other cases (authentication methods), it
>> doesn't quite in this case probably because accounting for such a case
>> was not considered to be as important. But while investigating about
>> the PAM issue (original subject of this thread), it turned out that
>> the occurrence of that minor issue was due to this behavior in libpq.
>
> I have to agree with Andres that it's not clear this is a reasonable
> fix.  To get rid of extra reconnections this way will require not merely
> upgrading libpq, but upgrading every single application that uses libpq
> and is capable of prompting its user for a password.  The odds are
> pretty good that that won't ever happen.

Can this stay in the future releases for new users of libpq to
consider using it (saving them a reconnection, however small a benefit
that is) or at least psql which is being changed to use it anyway? I
only think it makes libpq take into account a connection state that
could be used.

> The real complaint here is that the server-side PAM auth code path is
> losing the information that the client chose to disconnect rather than
> offer a password, and thus logging a message that we could do without.
> What's wrong with just fixing that?

Back in this thread, Horiguchi-san has posted a fix. It seems to fix
the original issue. Attaching his patch here again.

--
Amit Langote

Attachment

Re: Logging of PAM Authentication Failure

From
Andres Freund
Date:
On 2013-05-17 01:29:25 +0900, Amit Langote wrote:
> On Fri, May 17, 2013 at 1:05 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> > Amit Langote <amitlangote09@gmail.com> writes:
> >> On Thu, May 16, 2013 at 8:01 PM, Andres Freund <andres@2ndquadrant.com> wrote:
> >>> I unfortunately have to say I don't really see the point of this. The
> >>> cost of the additional connection attempt is rather low and we have to
> >>> deal with the superflous attempts anyway since there will be old libpqs
> >>> around for years. Why is this worth the effort?
> >
> >> While full connection sequence (with proper authentication exchanges)
> >> appears  to go smoothly for other cases (authentication methods), it
> >> doesn't quite in this case probably because accounting for such a case
> >> was not considered to be as important. But while investigating about
> >> the PAM issue (original subject of this thread), it turned out that
> >> the occurrence of that minor issue was due to this behavior in libpq.
> >
> > I have to agree with Andres that it's not clear this is a reasonable
> > fix.  To get rid of extra reconnections this way will require not merely
> > upgrading libpq, but upgrading every single application that uses libpq
> > and is capable of prompting its user for a password.  The odds are
> > pretty good that that won't ever happen.
> 
> Can this stay in the future releases for new users of libpq to
> consider using it (saving them a reconnection, however small a benefit
> that is) or at least psql which is being changed to use it anyway? I
> only think it makes libpq take into account a connection state that
> could be used.

Which basically is an API & ABI break since its not handled in existing
callers. So you would need to make it conditional. At that point the
complexity really doesn't seem warranted.

Greetings,

Andres Freund

-- Andres Freund                       http://www.2ndQuadrant.com/PostgreSQL Development, 24x7 Support, Training &
Services



Re: Logging of PAM Authentication Failure

From
Tom Lane
Date:
Andres Freund <andres@2ndquadrant.com> writes:
> On 2013-05-17 01:29:25 +0900, Amit Langote wrote:
>> Can this stay in the future releases for new users of libpq to
>> consider using it (saving them a reconnection, however small a benefit
>> that is) or at least psql which is being changed to use it anyway? I
>> only think it makes libpq take into account a connection state that
>> could be used.

> Which basically is an API & ABI break since its not handled in existing
> callers. So you would need to make it conditional.

Yeah, there would need to be a way for the caller to indicate that it's
prepared to handle this new connection state; else you risk actively
breaking existing code that doesn't know it needs to do something here.

Another point worth considering is that, if you assume that what's going
to happen is manual entry of a password (probably requiring at least a
couple of seconds), the actual benefit of avoiding a second fork() is
really completely negligible.  It could even be argued that the benefit
is negative, since we're tying up a postmaster child process slot that
might be better used for something else.

So, while I wouldn't have objected to this if it'd been included in the
original design for PQconnectPoll-style connections, it's really unclear
that it's worth the work to add it now.
        regards, tom lane



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
On Fri, May 17, 2013 at 1:46 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Andres Freund <andres@2ndquadrant.com> writes:
>> On 2013-05-17 01:29:25 +0900, Amit Langote wrote:
>>> Can this stay in the future releases for new users of libpq to
>>> consider using it (saving them a reconnection, however small a benefit
>>> that is) or at least psql which is being changed to use it anyway? I
>>> only think it makes libpq take into account a connection state that
>>> could be used.
>
>> Which basically is an API & ABI break since its not handled in existing
>> callers. So you would need to make it conditional.
>
> Yeah, there would need to be a way for the caller to indicate that it's
> prepared to handle this new connection state; else you risk actively
> breaking existing code that doesn't know it needs to do something here.
>
> Another point worth considering is that, if you assume that what's going
> to happen is manual entry of a password (probably requiring at least a
> couple of seconds), the actual benefit of avoiding a second fork() is
> really completely negligible.  It could even be argued that the benefit
> is negative, since we're tying up a postmaster child process slot that
> might be better used for something else.

I agree it's a pretty valid point. We'd better just fix the original
issue and leave it to that. :)

--
Amit Langote



Re: Logging of PAM Authentication Failure

From
Robert Haas
Date:
On Thu, May 16, 2013 at 7:01 AM, Andres Freund <andres@2ndquadrant.com> wrote:
> I unfortunately have to say I don't really see the point of this. The
> cost of the additional connection attempt is rather low and we have to
> deal with the superflous attempts anyway since there will be old libpqs
> around for years. Why is this worth the effort?

I have always considered this a wart, and I think we've had customers
complain about these kinds of things, too.  So +1 from me for fixing
it.  If not everyone updates their client to take advantage of the new
APIs, so be it.  If psql and pgAdmin do, it'll solve 90% of the
problem.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Fwd: Logging of PAM Authentication Failure

From
Amit Langote
Date:
Hello,

The attached patch by Kyotaro Horiguchi-san fixes a PAM authentication
error logging issue which is that when using PAM authentication,
connection attempts by clients (like psql) result in an unnecessary
logging of failed authentication.

---------- Forwarded message ----------
From: Amit Langote <amitlangote09@gmail.com>
Date: Fri, May 17, 2013 at 1:29 AM
Subject: Re: [HACKERS] Logging of PAM Authentication Failure
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: Andres Freund <andres@2ndquadrant.com>, Kyotaro HORIGUCHI
<kyota.horiguchi@gmail.com>, Kyotaro HORIGUCHI
<horiguchi.kyotaro@lab.ntt.co.jp>, Robert Haas
<robertmhaas@gmail.com>, PostgreSQL-development
<pgsql-hackers@postgresql.org>


On Fri, May 17, 2013 at 1:05 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Amit Langote <amitlangote09@gmail.com> writes:
>> On Thu, May 16, 2013 at 8:01 PM, Andres Freund <andres@2ndquadrant.com> wrote:
>>> I unfortunately have to say I don't really see the point of this. The
>>> cost of the additional connection attempt is rather low and we have to
>>> deal with the superflous attempts anyway since there will be old libpqs
>>> around for years. Why is this worth the effort?
>
>> While full connection sequence (with proper authentication exchanges)
>> appears  to go smoothly for other cases (authentication methods), it
>> doesn't quite in this case probably because accounting for such a case
>> was not considered to be as important. But while investigating about
>> the PAM issue (original subject of this thread), it turned out that
>> the occurrence of that minor issue was due to this behavior in libpq.
>
> I have to agree with Andres that it's not clear this is a reasonable
> fix.  To get rid of extra reconnections this way will require not merely
> upgrading libpq, but upgrading every single application that uses libpq
> and is capable of prompting its user for a password.  The odds are
> pretty good that that won't ever happen.

Can this stay in the future releases for new users of libpq to
consider using it (saving them a reconnection, however small a benefit
that is) or at least psql which is being changed to use it anyway? I
only think it makes libpq take into account a connection state that
could be used.

> The real complaint here is that the server-side PAM auth code path is
> losing the information that the client chose to disconnect rather than
> offer a password, and thus logging a message that we could do without.
> What's wrong with just fixing that?

Back in this thread, Horiguchi-san has posted a fix. It seems to fix
the original issue. Attaching his patch here again.

--
Amit Langote


--
Amit Langote

Attachment

Re: Logging of PAM Authentication Failure

From
Craig Ringer
Date:
On 05/11/2013 03:25 AM, Robert Haas wrote:
> Not really.  We could potentially fix it by extending the wire
> protocol to allow the server to respond to the client's startup packet
> with a further challenge, and extend libpq to report that challenge
> back to the user and allow sending a response.  But that would break
> on-the-wire compatibility, which we haven't done in a good 10 years,
> and certainly wouldn't be worthwhile just for this.
We were just talking about "things we'd like to do in wire protocol 4".

Allowing multi-stage authentication has come up repeatedly and should
perhaps go on that list. The most obvious case being "ident auth failed,
demand md5".

-- Craig Ringer                   http://www.2ndQuadrant.com/PostgreSQL Development, 24x7 Support, Training & Services




Re: Logging of PAM Authentication Failure

From
Jeff Janes
Date:
On 5/27/13, Craig Ringer <craig@2ndquadrant.com> wrote:

> We were just talking about "things we'd like to do in wire protocol 4".
>
> Allowing multi-stage authentication has come up repeatedly and should
> perhaps go on that list. The most obvious case being "ident auth failed,
> demand md5".

I'd like to use LDAP with pg_ident

Cheers,

Jeff



Re: Logging of PAM Authentication Failure

From
David Fetter
Date:
On Tue, May 28, 2013 at 01:32:53PM +0800, Craig Ringer wrote:
> On 05/11/2013 03:25 AM, Robert Haas wrote:
> > Not really.  We could potentially fix it by extending the wire
> > protocol to allow the server to respond to the client's startup packet
> > with a further challenge, and extend libpq to report that challenge
> > back to the user and allow sending a response.  But that would break
> > on-the-wire compatibility, which we haven't done in a good 10 years,
> > and certainly wouldn't be worthwhile just for this.
> We were just talking about "things we'd like to do in wire protocol 4".
> 
> Allowing multi-stage authentication has come up repeatedly and should
> perhaps go on that list. The most obvious case being "ident auth failed,
> demand md5".

+1

The configuration would need to be thought though, as no fixed
ordering could cover all cases.

Maybe lines like
   local   all postgres peer,md5

in pg_hba.conf would be the way to do this, where the list gets
evaluated in the order it's read.

Cheers,
David.
-- 
David Fetter <david@fetter.org> http://fetter.org/
Phone: +1 415 235 3778  AIM: dfetter666  Yahoo!: dfetter
Skype: davidfetter      XMPP: david.fetter@gmail.com
iCal: webcal://www.tripit.com/feed/ical/people/david74/tripit.ics

Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
On Tue, May 28, 2013 at 2:32 PM, Craig Ringer <craig@2ndquadrant.com> wrote:
> On 05/11/2013 03:25 AM, Robert Haas wrote:
>> Not really.  We could potentially fix it by extending the wire
>> protocol to allow the server to respond to the client's startup packet
>> with a further challenge, and extend libpq to report that challenge
>> back to the user and allow sending a response.  But that would break
>> on-the-wire compatibility, which we haven't done in a good 10 years,
>> and certainly wouldn't be worthwhile just for this.
> We were just talking about "things we'd like to do in wire protocol 4".
>
> Allowing multi-stage authentication has come up repeatedly and should
> perhaps go on that list. The most obvious case being "ident auth failed,
> demand md5".
>

I wonder what you think about continuing to use the already
established connection to the server while you move onto perform
authentication using next method in the list. Earlier in this thread,
I had proposed to make changes to PGconnectPoll() to introduce an
additional connection state which is kind of an intermediate state in
the authentication sequence. For example, server might ask for a
password (md5, password methods) and client might want to send the
password over the existing connection by leveraging this new
connection state. This is unlike what we do, for example, in psql,
where we drop the connection (upon CONNECTION_BAD due to password
required), get password using a prompt and then create a new
connection with password included in the request.

--
Amit Langote



Re: Logging of PAM Authentication Failure

From
Amit Langote
Date:
On Tue, May 28, 2013 at 5:04 PM, Amit Langote <amitlangote09@gmail.com> wrote:
> On Tue, May 28, 2013 at 2:32 PM, Craig Ringer <craig@2ndquadrant.com> wrote:
>> On 05/11/2013 03:25 AM, Robert Haas wrote:
>>> Not really.  We could potentially fix it by extending the wire
>>> protocol to allow the server to respond to the client's startup packet
>>> with a further challenge, and extend libpq to report that challenge
>>> back to the user and allow sending a response.  But that would break
>>> on-the-wire compatibility, which we haven't done in a good 10 years,
>>> and certainly wouldn't be worthwhile just for this.
>> We were just talking about "things we'd like to do in wire protocol 4".
>>
>> Allowing multi-stage authentication has come up repeatedly and should
>> perhaps go on that list. The most obvious case being "ident auth failed,
>> demand md5".
>>
>
> I wonder what you think about continuing to use the already
> established connection to the server while you move onto perform
> authentication using next method in the list. Earlier in this thread,
> I had proposed to make changes to PGconnectPoll() to introduce an
> additional connection state which is kind of an intermediate state in
> the authentication sequence. For example, server might ask for a
> password (md5, password methods) and client might want to send the
> password over the existing connection by leveraging this new
> connection state. This is unlike what we do, for example, in psql,
> where we drop the connection (upon CONNECTION_BAD due to password
> required), get password using a prompt and then create a new
> connection with password included in the request.
>
> --
> Amit Langote

Sorry, *PQconnectPoll()

--
Amit Langote



Re: Logging of PAM Authentication Failure

From
Bruce Momjian
Date:
On Tue, May 28, 2013 at 01:32:53PM +0800, Craig Ringer wrote:
> On 05/11/2013 03:25 AM, Robert Haas wrote:
> > Not really.  We could potentially fix it by extending the wire
> > protocol to allow the server to respond to the client's startup packet
> > with a further challenge, and extend libpq to report that challenge
> > back to the user and allow sending a response.  But that would break
> > on-the-wire compatibility, which we haven't done in a good 10 years,
> > and certainly wouldn't be worthwhile just for this.
> We were just talking about "things we'd like to do in wire protocol 4".
> 
> Allowing multi-stage authentication has come up repeatedly and should
> perhaps go on that list. The most obvious case being "ident auth failed,
> demand md5".

Added to TODO.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + It's impossible for everything to be true. +



Re: Logging of PAM Authentication Failure

From
Craig Ringer
Date:
On 05/28/2013 04:04 PM, Amit Langote wrote:
> On Tue, May 28, 2013 at 2:32 PM, Craig Ringer <craig@2ndquadrant.com> wrote:
>> On 05/11/2013 03:25 AM, Robert Haas wrote:
>>> Not really.  We could potentially fix it by extending the wire
>>> protocol to allow the server to respond to the client's startup packet
>>> with a further challenge, and extend libpq to report that challenge
>>> back to the user and allow sending a response.  But that would break
>>> on-the-wire compatibility, which we haven't done in a good 10 years,
>>> and certainly wouldn't be worthwhile just for this.
>> We were just talking about "things we'd like to do in wire protocol 4".
>>
>> Allowing multi-stage authentication has come up repeatedly and should
>> perhaps go on that list. The most obvious case being "ident auth failed,
>> demand md5".
>>
> I wonder what you think about continuing to use the already
> established connection to the server while you move onto perform
> authentication using next method in the list.
That's precisely what I'm talking about. It'd be nice to avoid the ugly
two-connection approach for SSL too, by allowing STARTTLS or similar
within the protocol.

Being able to negotiate connections - client says "peer?", server says
"failed, peer id doesn't match postgresql username", client says "md5
<password>?" server says "yup, that's ok" - would be nice. For example,
use Kerberos or SSPI where clients are suitably enabled, then fall back
to MD5 where Kerberos or SSPI single-sign-on isn't available.


-- Craig Ringer                   http://www.2ndQuadrant.com/PostgreSQL Development, 24x7 Support, Training & Services