Skip to content

Commit 3815d03

Browse files
yoshihikouenoarp242
authored andcommitted
Remove assumption that the auth response is AuthenticateOk
pq currently assumes the message sent from the server after sending PasswordMessage to be AuthenticationOk. However, this assumption doesn't always stand as the server may send some other messages other than AuthenticationOk such as another authentication request. That occurs when lib/pq is trying to connect to a PgPool-II server, where the following procedure is required as PgPool-II wants to have the password in both Cleartext and MD5 formats: [Client -> Server] StartupMessage [Server -> Client] AuthenticationCleartextPassword [Client -> Server] PasswordMessage [Server -> Client] AuthenticationMD5Password [Client -> Server] PasswordMessage [Server -> Client] AuthenticationOk [Server -> Client] ReadyForQuery Current implementation of auth function of pq will fail if the message after sending credentials is not AuthenticationOk, but we can just return before checking it and let another loop of auth check it instead. libpq does support handling multiple authentication requests, thus it can connect to PgPool-II just fine with the procedure above. So making pq check the message sent from the server after PasswordMessage will solve the described issue and align its behavior with the official client.
1 parent 589ad43 commit 3815d03

2 files changed

Lines changed: 9 additions & 33 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ newer. Previously PostgreSQL 8.4 and newer were supported.
8383

8484
- Treat nil []byte in query parameters as nil/NULL rather than `""` ([#838]).
8585

86+
- Accept multiple authentication methods before checking AuthOk, which improves
87+
compatibility with PgPool-II ([#1188]).
88+
8689
[`sslnegotiation`]: https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNECT-SSLNEGOTIATION
8790
[#595]: https://github.com/lib/pq/pull/595
8891
[#745]: https://github.com/lib/pq/pull/745
@@ -99,6 +102,7 @@ newer. Previously PostgreSQL 8.4 and newer were supported.
99102
[#1179]: https://github.com/lib/pq/pull/1179
100103
[#1180]: https://github.com/lib/pq/pull/1180
101104
[#1184]: https://github.com/lib/pq/pull/1184
105+
[#1188]: https://github.com/lib/pq/pull/1188
102106
[#1211]: https://github.com/lib/pq/pull/1211
103107
[#1212]: https://github.com/lib/pq/pull/1212
104108
[#1214]: https://github.com/lib/pq/pull/1214

conn.go

Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,50 +1227,22 @@ func (cn *conn) auth(r *readBuf, cfg Config) error {
12271227
return fmt.Errorf("pq: unknown authentication response: %s", code)
12281228
case proto.AuthReqKrb4, proto.AuthReqKrb5, proto.AuthReqCrypt, proto.AuthReqSSPI:
12291229
return fmt.Errorf("pq: unsupported authentication method: %s", code)
1230-
12311230
case proto.AuthReqOk:
12321231
return nil
12331232

12341233
case proto.AuthReqPassword:
12351234
w := cn.writeBuf(proto.PasswordMessage)
12361235
w.string(cfg.Password)
1237-
err := cn.send(w)
1238-
if err != nil {
1239-
return err
1240-
}
1241-
1242-
t, r, err := cn.recv()
1243-
if err != nil {
1244-
return err
1245-
}
1246-
if t != proto.AuthenticationRequest {
1247-
return fmt.Errorf("pq: unexpected password response: %q", t)
1248-
}
1249-
if r.int32() != int(proto.AuthReqOk) {
1250-
return fmt.Errorf("pq: unexpected authentication response: %q", t)
1251-
}
1252-
return nil
1236+
// Don't need to check AuthOk response here; auth() is called in a loop,
1237+
// which catches the errors and AuthReqOk responses.
1238+
return cn.send(w)
12531239

12541240
case proto.AuthReqMD5:
12551241
s := string(r.next(4))
12561242
w := cn.writeBuf(proto.PasswordMessage)
12571243
w.string("md5" + md5s(md5s(cfg.Password+cfg.User)+s))
1258-
err := cn.send(w)
1259-
if err != nil {
1260-
return err
1261-
}
1262-
1263-
t, r, err := cn.recv()
1264-
if err != nil {
1265-
return err
1266-
}
1267-
if t != proto.AuthenticationRequest {
1268-
return fmt.Errorf("pq: unexpected password response: %q", t)
1269-
}
1270-
if r.int32() != int(proto.AuthReqOk) {
1271-
return fmt.Errorf("pq: unexpected authentication response: %q", t)
1272-
}
1273-
return nil
1244+
// Same here.
1245+
return cn.send(w)
12741246

12751247
case proto.AuthReqGSS: // GSSAPI, startup
12761248
if newGss == nil {

0 commit comments

Comments
 (0)