Repository navigation
Conversation
An invalid sslmode or gssencmode passed parse_dsn and was only rejected when connecting, and the sslmode check ran in _connect_tls!, after the GSS branch had already returned: gssencmode=require with an invalid sslmode connected over GSS encryption. The accepted values now live in one place, Postgres.SSLMODES and Postgres.GSSENCMODES. parse_dsn and validate_dsn check them, after environment defaults are applied, in the slot the malformed-UTF-8 check already used, with the same message. The ConnectionParams and Connection keyword constructors check them too and throw the same ArgumentError. The connect path keeps its checks as a backstop, both before any dial, and cancel_request gets the same backstop. Values stay case-insensitive and no value is added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
An invalid
sslmodeorgssencmodepassesparse_dsnand is only rejected when connecting. Thesslmodecheck also runs late: it is in_connect_tls!, after the TCP connect, and when GSS encryption is negotiatedAPI.connectreturns before reaching it. Sogssencmode=require sslmode=bogusconnects on a machine with a Kerberos ticket and fails on one without (#28, item 3).This validates both values before connecting, in one place:
Postgres.SSLMODES(disable,prefer,require,verify-full) andPostgres.GSSENCMODES(disable,prefer,require). The parser, the constructors, and the connect and cancel paths all read them, and the error message is built from them.parse_dsnandvalidate_dsncheck them after environment defaults are applied, soPGSSLMODEandPGGSSENCMODEare covered. The check runs where Add validate_dsn for structured connection-parameter errors #33 already rejected malformed UTF-8, betweenconnect_timeoutandgssdelegation, so the order in which errors are reported does not change otherwise. The message is the one Add validate_dsn for structured connection-parameter errors #33 introduced:invalid value "verfy-full" for connection parameter "sslmode"; expected one of disable, prefer, require, verify-full.validate_dsnreportskey = "sslmode"or"gssencmode"andreason = :invalid_value.ConnectionParamsandConnectionkeyword constructors check them too, as they already checknumeric_overflow, and throw anArgumentErrorwith the same message. A keyword caller never goes through the parser.API.connectchecks both at the top, before any dial, so no negotiation path skips thesslmodecheck. These checks stayPostgres.Errors as before. The constructors make them unreachable, so they are a backstop for direct callers.cancel_requestgets the same backstop, since an unknown mode there would take the branches that may send the cancel key in cleartext.Values stay case-insensitive (
Verify-Fullis accepted), no value is added, and the constructors store the value as given, as before.Behavior change. Inputs that connect today are unaffected, apart from case 3 below. Configurations that would fail to connect now fail earlier, with an
ArgumentErrorinstead of aPostgres.Error(directAPI.connectandAPI.cancel_requestcallers still get thePostgres.Error):ArgumentErrorfromparse_dsnwhere it got aConnectionParams, and an error fromvalidate_dsnwhere it gotnothing. This also applies when the value comes fromPGSSLMODEorPGGSSENCMODE, and to an empty value such as an unexpanded${PGSSLMODE}. The same applies toConnectionParams(; sslmode = …).Postgres.Errorforinvalid sslmode/invalid gssencmodeat connect time now gets anArgumentError, earlier, fromparse_dsnor from the constructor. A keyword value with malformed UTF-8 now also gets thisArgumentError, wherelowercaseused to throwInvalidCharErrorwhile connecting.gssencmode=require(orprefer) with an invalidsslmodeno longer connects over GSS encryption.I'd suggest a minor-version bump and a release note for this. Adds the two constants (not exported or
public). Happy to mark thempublicif that is useful to callers. No runtime dependency changes.Closes #28.
Validation:
PGSSLMODE/PGGSSENCMODE, andConnectionParams. ThroughConnectionagainst a fake server,disableandpreferconnect, andrequire,verify-fullandgssencmode=requireget past validation to their usual connect errors. These tests pass on the previous code too; they guard against rejecting a value that used to be accepted.validate_dsnandparse_dsnagree. The error-order test now includes both modes, and theConnectionconstructor's NUL andsslcert/sslkeychecks are still reported before a mode error.gssencmode=require sslmode=bogusgets theArgumentErrorfrom the constructor and the DSN, andPostgres.Error("invalid sslmode: bogus")fromAPI.connectdirectly. The server never sees a connection. The same configuration with a validsslmodeconnects over GSS.API.cancel_requestwith everysslmodeandgssencmodevalue in mixed case against a fake server:disable/prefersend the CancelRequest,require/verify-fullrefuse to send it over a server without TLS, and GSS encryption is used forprefer/require. An invalid value is refused before any dial.PGSSLMODE=""now fails inparse_dsn(runtests.jl), a surrogatesslmodeis no longer accepted byvalidate_dsn, andConnection(gssencmode = "bogus")throwsArgumentError(gssapi.jl).cancel_requestbackstop; moving thesslmodecheck back into_connect_tls!(the directAPI.connecttest connects over GSS); listing the values again inAPI.connect, as a tuple or as the old==chain (a source test finds the duplicate list); and moving the constructor's mode check above its NUL checks.PGSSLMODE/PGGSSENCMODE/PGPORT/PGGSSDELEGATION. Input that both accept parses to the same fields (61,165). Input that both reject gets the same error (157,253).parse_dsnnewly rejects 51,837 inputs, each because of a mode that v2.6.0's connect path would have refused. Where an input has several problems and the first error changed (29,745), the new first error is always an invalid mode, reported in its slot before a later parameter, or an invalidsslmodebefore a malformedgssencmode(312). Nothing newly accepted,validate_dsnnever threw, and it always agreed withparse_dsn. 12kConnectionParamscalls matched the old connect path's accept/reject exactly.Pkg.test()with Docker integration (POSTGRES_REQUIRE_INTEGRATION=true, PostgreSQL 16, Linux x64), including the trim compile test (no verifier errors): 9919 checks pass on Julia 1.13.2, 9890 on Julia 1.10.12, and 9919 with-t 2.Drafted with Claude Code (Claude Opus 5.5) and reviewed by me before posting.
🤖 Generated with Claude Code