Connecting to a db that fails authentication doesn't give any debugging help whatsoever #4

Closed
tcrayford opened this Issue Sep 21, 2011 · 17 comments

Comments

Projects
None yet
2 participants

Could you at least print/throw the message back from postgres? This is very frustrating for me, I'm trying to connect to a heroku database, and all I get as an error is "AuthenticationFailed".

Are there some docs about what postgres returns from the auth stuff somewhere? I don't really know enough haskell/postgres to fix this problem myself (yet), but I guess I can have a go.

Owner

chrisdone commented Sep 21, 2011

Looking at it now…

Owner

chrisdone commented Sep 21, 2011

Maybe this helps? I have to write the parser for error messages. For some reason I'm currently finding it difficult to trigger an authentication failure, instead Postgres just closes my connection. Meanwhile I just dump the bytes from Postgres into the exception.

For me, authenticating with a user that doesn't exist gives a decent error message. Obviously if the port/host is wrong postgres will just close the connection.

I haven't tried with a password that doesn't match yet.

Hmm, I now get a very weird chunk back: AuthenticationFailed "Chunk "\NUL\NUL\NUL\ENQ\246QQ\STX" Empty". Could this be something to do with md5 auth?

If so, I might have a look at implementing it, now that I'm understanding more of pgsql-simple.

Owner

chrisdone commented Sep 21, 2011

Possibly. On line 216 is where the typ of the message is, perhaps printing that out to determine what type the response is. Probably ErrorResponse. But yeah, for implementing MD5 I would probably move some stuff here

-- | Run the connectInfoentication procedure.
authenticate :: Connection -> ConnectInfo -> IO ()
authenticate conn@Connection{..} connectInfo = do
  withConnection conn $ \h -> do
    sendStartUp h connectInfo
    getConnectInfoResponse h

like, put a call before sendStartUp like getAuthneticationType that reads the auth type message

http://www.postgresql.org/docs/current/static/protocol-message-formats.html

because right now I just send auth plain text immediately, rather than inspecting the type expected. MD5 shouldn't be hard, I just didn't need it yet.

Overview of the flow is here: http://www.postgresql.org/docs/current/static/protocol-flow.html#AEN91326

getMessage will be useful, it reads a message from the handle and returns the type and the payload which you can then decode according to the type.

I have yet to write the parser for the ErrorResponse command (see other ticket) (and see parseErr in the code which is commented out) which is why it shows junk. So probably

  • Read authentication type.
  • Send auth info.
  • Get connect info response.

Done. Good luck. :-)

Owner

chrisdone commented Sep 21, 2011

FWIW you can test trivially by loading Base.hs and running

connect defaultConnectInfo { connectUser="trololo",connectPassword="lolo",connectDatabase="blah" }

in GHCi.

Related: I was thinking about writing some integration tests around some of the stuff in pgsql-simple (they would probably be connecting to a database on whoever's running the tests' machine). Interested?

Owner

chrisdone commented Sep 21, 2011

Sure, sounds good. Tests making hacking on a library much more pleasant. :-)

I've just talked to heroku. Apparently it's not an md5 issue, but an ssl one. I think that is somewhat similar (you ask it if it accepts ssl right at the start). However, then all the traffic after that requires ssl.

There are a couple of ways of doing that. Looking at the code, it seems that most of the sending/receiving stuff would need to be wrapped by an ssl encode/decode function. I'm not sure I'm confident in my haskell skills enough to know how to do that cleanly, any suggestions?

Owner

chrisdone commented Sep 21, 2011

All postgres connections must be SSL? Eek. There is an open-ssl library but I don't think it's very good. One way would be to use an SSL wrapper. For servers there's stunnel. But you need a client. I'm sure there are SSL client wrappers out there. If you're up to using openssl the library, or the pure haskell ssl library, maybe you can just wrap the socket in it. But I dunno how stable they are. Worth looking at, I guess.

I'll look at it more later, going to bed.

Ok, thanks. I'm going to have a look at the yseod guys stuff, apparently they have Persistent running against a heroku database.

It seemed that way from heroku (that you have to use ssl for everything). I might be wrong on that though.

Guess I might just give up and use hdbc (though it's api is much worse than pgsql-simple, from what I can see).

Ah so yseod persistent uses hdbc. Think I'll be switching to that then (unfortunately). I might pull some of the query params stuff out into its own package, as it seems like that'll be similar between this, brian's and the thing I'll be using on top of hdbc.

@chrisdone chrisdone closed this Sep 21, 2011

@chrisdone chrisdone reopened this Sep 22, 2011

Owner

chrisdone commented Sep 22, 2011

Oh.

case typ of
  AuthenticationOk | param == 0 -> waitForReady h
      where param = decode block :: Int32
  _ -> E.throw $ AuthenticationFailed (show $ typ ++ block)

Probably because the param isn't 0.

λ> L.length (L.fromString "\NUL\NUL\NUL\ENQ\246QQ\STX")
9

λ> runGet (do typ <- getInt32; hash <- getWord8; return (typ,hash)) (L.fromString "\NUL\NUL\NUL\ENQ\246QQ\STX")
(5,195)

which looks like md5 auth:

http://www.postgresql.org/docs/current/static/protocol-message-formats.html

Owner

chrisdone commented Sep 22, 2011

So this is a duplicate of #1.

@chrisdone chrisdone closed this Sep 22, 2011

Yeah, makes sense. If you ever get round to adding the md5 stuff, I can probably try it out pretty trivially (my app is really small right now).

Alternatively, what about basing Database.PostgreSQL.Base off of the postgres client bindings? As I understand it, that's what mysql-simple does, and it seems like it gets round of a lot of the hassles of md5/ssl auth.

Owner

chrisdone commented Sep 22, 2011

That kind of misses the point of writing a pure Haskell library. I will not be doing that.

True. I do enjoy the lack of dependence on the C libs. I just don't think haskell has ssl sorted out properly yet, and that bothers me a bunch (seeing as it means I can't use this lib in my preferred hosting env)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment