@@ -7,9 +7,10 @@ use std::time::{Duration, Instant};
77use pgdog_config:: users:: PasswordKind ;
88use timeouts:: Timeouts ;
99use tokio:: { select, spawn, time:: timeout} ;
10- use tracing:: { debug, enabled, error, info, trace, Level as LogLevel } ;
10+ use tracing:: { debug, enabled, error, info, trace, warn , Level as LogLevel } ;
1111
1212use super :: { ClientRequest , Error , PreparedStatements } ;
13+ use crate :: auth:: AuthResult ;
1314use crate :: auth:: { md5, scram:: Server } ;
1415use crate :: backend:: maintenance_mode;
1516use crate :: backend:: pool:: stats:: MemoryStats ;
@@ -144,12 +145,12 @@ impl Client {
144145 user : & str ,
145146 auth_type : & AuthType ,
146147 passwords : & [ PasswordKind ] ,
147- ) -> Result < bool , Error > {
148+ ) -> Result < AuthResult , Error > {
148149 if passwords. is_empty ( ) {
149- return Ok ( false ) ;
150+ return Ok ( AuthResult :: NoPasswordConfig ) ;
150151 }
151152
152- let ok = match auth_type {
153+ let result = match auth_type {
153154 AuthType :: Md5 => {
154155 let md5 = md5:: Client :: new (
155156 user,
@@ -158,9 +159,13 @@ impl Client {
158159 stream. send_flush ( & md5. challenge ( ) ) . await ?;
159160 let password = Password :: from_bytes ( stream. read ( ) . await ?. to_bytes ( ) ?) ?;
160161 if let Password :: PasswordMessage { response } = password {
161- md5. check ( & response)
162+ if md5. check ( & response) {
163+ AuthResult :: Ok
164+ } else {
165+ AuthResult :: NoPasswordMatch
166+ }
162167 } else {
163- false
168+ AuthResult :: NoPasswordMessage
164169 }
165170 }
166171
@@ -169,7 +174,11 @@ impl Client {
169174
170175 let scram = Server :: new ( passwords) ;
171176 let res = scram. handle ( stream) . await ;
172- matches ! ( res, Ok ( true ) )
177+ if matches ! ( res, Ok ( true ) ) {
178+ AuthResult :: Ok
179+ } else {
180+ AuthResult :: NoPasswordMatch
181+ }
173182 }
174183
175184 AuthType :: Plain => {
@@ -178,15 +187,21 @@ impl Client {
178187 . await ?;
179188 let response = stream. read ( ) . await ?;
180189 let response = Password :: from_bytes ( response. to_bytes ( ) ?) ?;
181- passwords
190+ let is_match = passwords
182191 . iter ( )
183- . any ( |p| Some ( p. as_str ( ) ) == response. password ( ) )
192+ . any ( |p| Some ( p. as_str ( ) ) == response. password ( ) ) ;
193+
194+ if is_match {
195+ AuthResult :: Ok
196+ } else {
197+ AuthResult :: NoPasswordMatch
198+ }
184199 }
185200
186- AuthType :: Trust => true ,
201+ AuthType :: Trust => AuthResult :: Ok ,
187202 } ;
188203
189- Ok ( ok )
204+ Ok ( result )
190205 }
191206
192207 /// Create new frontend client from the given TCP stream.
@@ -210,13 +225,14 @@ impl Client {
210225 let passthrough = config. config . general . passthrough_auth ( ) ;
211226 let id = BackendKeyData :: new_client ( protocol_version) ;
212227 let comms = ClientComms :: new ( & id) ;
228+ let log_connections = config. config . general . log_connections ;
213229
214230 // Check if we need to ask the client for its password in plaintext
215231 // because we don't actually have it configured.
216232 //
217233 // This is likely because passthrough authentication is enabled.
218234 //
219- let auth_ok = if passthrough {
235+ let auth_result = if passthrough {
220236 // Get the password. We always need it because we need to check if
221237 // it's current and hasn't been changed.
222238 stream
@@ -232,7 +248,7 @@ impl Client {
232248 if let Some ( user) = user {
233249 databases:: add ( user) ?
234250 } else {
235- false
251+ AuthResult :: NoPassthroughNoUser
236252 }
237253 } else if admin {
238254 // The admin database is virtual and never present in the cluster
@@ -245,19 +261,29 @@ impl Client {
245261 if let Some ( identity) = cluster. identity ( ) {
246262 // mTLS authentication: the client certificate identity
247263 // must match the configured user identity.
248- stream. tls_identity ( ) == Some ( identity)
264+ if stream. tls_identity ( ) == Some ( identity) {
265+ AuthResult :: Ok
266+ } else {
267+ AuthResult :: NoIdentity
268+ }
249269 } else {
250270 // Password authentication.
251271 Self :: check_password ( & mut stream, user, auth_type, cluster. passwords ( ) )
252272 . await ?
253273 }
254274 }
255275
256- Err ( _) => false ,
276+ Err ( _) => AuthResult :: NoUserOrDatabase ,
257277 }
258278 } ;
259279
260- if !auth_ok {
280+ if !auth_result. is_ok ( ) {
281+ if log_connections {
282+ warn ! (
283+ r#"user "{}" and database "{}" auth error: {}"# ,
284+ user, database, auth_result
285+ ) ;
286+ }
261287 stream. fatal ( ErrorResponse :: auth ( user, database) ) . await ?;
262288 return Ok ( None ) ;
263289 } else {
0 commit comments