Connection string query parameters aren't decoded correctly

Description

The parse-properties-uri function uses uri.getQuery(), which decodes the entire query string. This means that any query string parameters that include the characters = or & (even when properly encoded) will be lost in the subsequent steps to split apart the k/v pairs.

Instead, it should split the raw query string on "&", then the raw key-value pairs on "=". Then, decode each name or value independently using e.g. URLDecoder.

My use case is that I am passing a CA certificate in PEM format to Postgres in the connection string. Since the PEM data is base64, it sometimes ends with = padding, for example:

The parameter in the connection string is properly encoded:

When I use this connection string with clojure.java.jdbc, I receive an exception (java.security.cert.CertificateException: java.io.IOException: Incomplete data) because the equals padding and everything after it was truncated by this split.

Perhaps a more compelling use case for most folks is passwords. Postgres accepts passwords as connection string query parameters. If the password contains an equals sign or ampersand, you will receive baffling authentication failures:

First, set up a few users. (This also requires altering pg_hba.conf from the default.)

Now try connecting with clojure.java.jdbc:

Environment

clojure 1.9.0, clojure.java.jdbc 0.7.7

Activity

Show:
Sean Corfield
February 15, 2021, 11:20 PM

If that works then, yes, that’s probably a reasonable workaround.

Daniel Sutton
February 15, 2021, 9:50 PM

just ran into this issue. it seems a workaround is to pass the connection-uri in as a map {:connection-uri my-url-encoded-connection-string}. Is that correct? It seems to work for me locally and the docstring of get-connection

Raw:
:connection-uri (required) a String
Passed directly to DriverManager/getConnection
(both :user and :password may be specified as well, rather
than passing them as part of the connection string)

Is this a correct assumption?

Sean Corfield
June 6, 2019, 6:27 PM

Given that the hash map form of db-spec works and that changing the URI parsing may break existing code, I'm not going to try to fix this in clojure.java.jdbc.

Note that next.jdbc only supports the hash map form of db-spec and a raw JDBC connection string which is passed directly to the driver with no parsing so it would not suffer from this issue.

Sean Corfield
October 29, 2018, 5:59 PM

Updated link to lines containing the split calls https://github.com/clojure/java.jdbc/blob/master/src/main/clojure/clojure/java/jdbc.clj#L211-L213

I'm a bit concerned that this might break URI handling where the separating & and = are themselves encoded – I'm not sure whether that's a real-world concern or not but it would be a breaking behavior change if anyone is taking advantage of that.

I've never been particularly happy with the idea of parsing a connection URI like this in clojure.java.jdbc, which is why I always encourage using the dbtype / dbname format instead for the db-spec.

I'll have to give this more thought.

import
August 11, 2018, 3:55 PM

Comment made by: pgarrett

@seancorfield Yes, it works. It just means I have to parse the connection string correctly in my application.

Won't Fix

Assignee

Sean Corfield

Reporter

import