mirror of https://github.com/sysown/proxysql
docs/passthrough-auth-spec
feature/aws-rds-monitor
v3.0_fix_ci-mysqlx-cache-and-soak
GH-Actions
v3.0
v3.0_fix_codecov-coverage-path-prefix
issue-1288-load-mysql-variables-feedback
ci/fix-pgsql-socket-g1-cache-key
v3.0_fix_ci-mysqlx-fetch-depth
cleanup/drop-unreachable-port-defaults
feature/pgsql-native-backend-protocol
fix/pgsql-unix-socket
ci-pgsql-socket-g1
v3.0_fix_coverage-gcov-prefix-strip
fix/pgsql-omit-port-zero
aws-rds-bg
fix/jemalloc-page-size-auto-detect
feature/ci-codecov-tap-all-groups-callers
fix/run-tests-backtick-leak
ci/zstd-level-15
feature/ci-codecov-tap-all-groups-callees
v3.0_partition-fairness
feature/ci-codecov-tap-legacy-g2
v3.0_partition-gate
fix/ci-cache-restore-path
v3.0_fix-stale-pause-until
feature/perf-improvements-test2
fix/kill-proxysqlgenai-build-flag
feat/passthrough-auth
ci-trigger-tolerate-cleanup-401
fix/5790-mariadb-collation-255
fix/parsersql-1.0.3-pg-set-fixes
issue_5639
pgsql_dns_cache
fix/5755-followup-typecast-digest-fixtures
v3.0_merge-5776-5784
v3.0_latency_consistency_improvement
fix/galera-g5-cluster-start
fix/ghcr-pull-retry
v3.0_cap_violation_5767
ci-mariadb10-galera-GH-Actions
ci/fix-gr-g5-cluster-start
ci-mysql84-gr-g1-g9-GH-Actions
perf/pull-ci-base-from-ghcr
fix/split-test-groups
fix/rename-set-parser-workflow
gh-actions/add-set-parser-algorithm-3-g1
fix/4760-advertise-lenenc-auth-capability
feature/mysqlx-stack-consolidated
feature/mysqlx-asan-coverage-docker-isolation
fix/ci-unit-tests-tsan-project-name
feature/mysqlx-tsan-v3-companion
feature/ci-builds-add-tsan-matrix
ci-reduce-polling-interval
feature/mysqlx-tsan-workflow-only
feature/mysqlx-ci-validation-workflows
feature/mysqlx-test-leak-cleanup
feature/mysqlx-behavioural-tap
feature/mysqlx-parity-cleanup
ci-g5-enable-cluster
feature/mysqlx-tls-passthrough
feature/mysqlx-asymmetric-tls
feature/mysqlx-state-machines
feature/build-tsan-plumbing
feature/mysqlx-observability-p0
fix/mysqlx-review-findings
v3.0-test-ci
ci/fix-mysql-apt-key-expired-v2
ci/fix-mysql-apt-key-expired
mariadb-rpl-helper
fix-fc-parsing
ci/fix-upload-artifact-eacces
ci/fix-cache-prune-permissions
ci/shrink-test-cache
ci/fix-tap-build-target
ci/gh-actions-readme-pointer
ci/fix-mysql84-infradb-label
ci/add-missing-group-reusables
infra-mysql57-binlog
feature/pgbouncer-compat
v3.0_pgsql_sslkeylog_5281
fix/5554-resolution-family-limitation
fix/3p-ci-error-handling
v3.0-5493
v3.0-ci260322_cluster
copilot/extract-server-selection-algorithm
copilot/extract-health-state-logic
copilot/extract-query-rule-matching-logic
copilot/extract-connection-pool-logic
v3.0-set_parser_v3
feature/arm-builds
release-notes-3.0.6-4.0.6-draft
v3.0.6-add-tap-test_stats_table_check
v2.7.3-test260221
v4.0-mcp-stats
copilot/uninstall-amazon-linux-2023
fix-prometheus-labels-test
tap-mcp-client
agent-skill-tap-test
v4.0-tsdb1
v3.0-fix_5256
gh-pages
feature/modern-docs
v4.0
v4.0-fix-vec-search
v4.0_rag_sys_prompt
v4.0_rag_mcp
v4.0-tsdb
feature/v4-docs-init
otel_system_libs
otel_clean
v3.0-5288
otel
otel_2
fix/postgresql-cluster-sync
v3.0-releate_notes_scripts_fixes
test_gh-actions_triggers
postgresql-digest-testing-improvement
v3.0_select_auto_commit
v3.0-5218
fix-5221
fix/5186-proxysql-stop-admin-crash
v3.0-4951
add-claude-github-actions-1763877527835
fix-rpm
v3.0-DS_crash
add-claude-github-actions-1763663272333
add-claude-github-actions-1763663091346
add-claude-github-actions-1763663091411
add-claude-github-actions-1763476725261
add-claude-github-actions-1763476725489
v3.0_optimizations_and_stability
v2.7.3.1
v3.0.3-upgrade_json
v3.0.sonar-cli
v3.0.sonar-config
otel-tracepoint
v3.0.2-merge-upgrade_deps-add_new_distros
v3.0.2-upgrade_deps
v3.0.2-add_new_distros
v3.0-add_more_testing_groups
v3.0-upgrade_prometheus-cpp
v3.0-upgrade_json
v3.0-upgrade_sqlite3
v3.0-upgrade_libmicrohttpd
v3.0-upgrade_curl
v3.0-add_centos10_builds
v3.0-add_fedora42_builds
v3.0_PG_PrepStmt
v3.0-sliced_groups
v3.0_auth_negotiation
v2.7
v2.7-fix_run_name
v3.0_4799_4827
v3.0-3687
v2.7-pmm_runtime_servers_metrics
v2.7-4839
v2.7-4841
v2.7-bump_version_to_2.7.3
2.6.6-4841
v2.x_pg_PrepStmtBase_240714
v3.0-4803-4817
v3.0-4803
v2.7-minorBugs
v3.0-privates
v2.x-logging_mem_2
v2.7_fix
v2.7_amd64_build_fix
v2.7-fix_aux_threads_ssl_leaks
v2.7-fix_ssl_params_leak
v2.7-rm_malloc_conf_on_version
v2.7_compression
v2.7-actions-add-3p-tests-parameter
none
v2.7-fix_hang_on_resume
v2.x-logging_mem
v2.7_servers_defaults
v2.7-mariadb_column_metadata_integrity_check
ssl_optimization
v2.7_reg_test_4716_single_semicolon
v2.7_issue_4707_threshold_resultset_size
v2.7_reg_test_4723_query_cache_stores_empty_result
2.7_randomized_cache_ttl
v3.0_fix_multiple_builds
v3.0_servers_defaults
v2.7-update_actions_triggers_v2
v2.7-update_actions_triggers
v2.6
v2.6.x-update_triggers
v2.6-4646
v2.7.1-update_actions
v2.x
v2.6.x-testing-global-multiplexing-disabled
use-wrlock-in-dns-cache-empty
v2.6.x-fix-darwin
v2.x-admin_list_ciphers
v2.x-sqlite3_pass_exts
v2.x-tap_tests_opt_ssl
v2.6.0-update_to_libhttpserver_v0.19
v2.x_router_2ports
v2.6.0-update_to_openssl_v3.1.5
v2.x-2411025
v2.x-profiling_poc1
v2.x_sha2pass_draft2
v2.x-webui_fixes
v2.6.0-more-makefile-fixes
v2.x-20230914_test
v2.x-20230913_test
v2.5.5-branch
v2.5.5-branch_255_patches
v2.x-aurora_autodiscovery-refactor_cluster_mysql_servers-gr_bootstrap_mode_2
v2.x_mysql_connector_j_fixes
v2.6-deprecate_old_clickhouse
v2.x_refactor_cluster_mysql_servers
v2.x-aurora_autodiscovery
v2.x-zd70545
v2.x-aurora_autodiscovery_shunned_promotion
v2.x-tap20230609
v2.x-test20230530
v2.x_sha2pass_draft2-TEST
v2.x-session_track_system_variables_v2
v2.x-status-variables-for-set-stmts
v2.x-enable_session_state_trackers
v2.x-increase-logging-eof_fast_forward-t
v2.x-3863-special-query
v2.x-session_track_system_variables
v2.x_refactor_read_only_action
v2.x_sha2pass_draft1
v2.2.0-sqliteserver_read_only
v2.x-digest_umap_aux-comparison
v2.4.8
v2.x-4105_4114
v2.x-3583-server_closed_conn
v2.x-group_replication_rework-SHUNNED_promotion
v2.1.0-var-global-multiplex
v2.x-CI-hostname-tap-test-fixes
v2.x-limit-version-check
v2.x-fix_deprecate_eof_warning
v2.x-3698
v2.x_tidb_replica_read
v2.x-HostGroups_attributes
v2.0.18.221009
v2.x-ci_reg_test_3273_ssl_con
TAP_test_restapi
v2.x-tap_tests_groups
v2.x-tap_test_sqlite3_server-t
PRS_3888_3903_2
PRS_3888_3903
v2.x_code_refactor_2206
v2.x-multipacket_poc_1
v2.x-impr_hg_latency_obsv
v2.x-gcc-warnings
v2.x-hg_lock_session_id
v2.x-3768
v2.x-3371
v2.x-ci_verifications
v2.x-thread_local_qps_limit
v2.x-parser_table
v2.1.1-3207
v2.x-qps_limits
v2.x-3711
v2.x-3642
v2.x-3674
v2.x-ssl3_warnings
V2
v2.3.2
v2.3.2_3646_3647
v2.x-client_err_limit_conn_timeout
v2.x-keep_multiplexing_regression_fix
v2.3.2-3628
v2.2.2-to-v2.3.0-7
v2.2.2-to-v2.3.0-7_merge
v2.2.2-to-v2.3.0-6
v2.2.2-to-v2.3.0-6_merge
v2.2.2-to-v2.3.0-5
v2.2.2-to-v2.3.0-4
v2.2.2-to-v2.3.0-3
v2.2.2-to-v2.3.0-2
v2.2.2-to-v2.3.0-1
v2.3.1
v2.0.14-70226
v2.3.0
v2.x-client_err_limit-gr_replication_lag_action
v2.2.2
v2.2.1-3603
v2.2.1-centos7-ASAN
v2.2.1
v2.2.1-3601
v2.2.1-3599
v2.2.1-3597
v2.2.1-3595
v2.2.0-restapi_server_exc_log
v2.x-3574
v2.x-3558
v2.2.0-3546-centos-7-gcc-8
v2.x-3549
v2.x-cluster_large_mysql_users
v2.x-cov_ci_verification
v2.0.14-tb1
v2.0.14-tb1-3494
v2.0.14-tb1-3488
v2.0.14-tb1-3117
v2.0.14-tb1-2762
v2.0.14-2762
v1.4.13-arm
v2.1.1-3296
v2.2.0
v2.0.18
v2.1.1
v2.0.18-3342
v2.0.18-3182
v2.1.1-3184
v2.1.0-revert-da7fdfe14
v2.0.18-revert-da7fdfe14
v1.4.13-70160
v2.0.18-3354
v2.0.18-3350
v2.0.14-3339
1.4.13-70160
v2.0.18-3339
v2.1.1-3317
v2.1.1-3319
v2.0.18-3317
v2.1.2-LBalgo
v2.0.18-1574
v2.1.2-hgman
v2.0.17
v2.1.0
v2.0.17-3288
v2.0.17-3276
v2.0.17-3273
v2.0.16
v2.0.16-3267
v2.0.16-3265
v2.0.16-3262
v2.0.16-3261
v2.1.1-3252
v2.1.1-collation
v2.0.16-3252
v2.0.16-collation
v2.1.0-parser
v2.0.16-3219
v2.0.16-3216
v2.0.16-3201
v2.0.16-2330
revert-3191-v2.0.16-3190
v2.0.16-3204
v2.0.16-3177
v2.0.16-2619
v2.0.16-3190
v2.0.16-3187
v2.1.0-70118
v2.0.16-3133
v2.0.16-3133_ci_verification
v2.0.16-3150
v2.0.16-change_user
v2.0.15
v2.0.15_amd64_fix
v2.0.15_arm64_packages
v1.4.14-ssl
v2.0.15_arm64
v2.1.0-2820
v2.0.15-sslbug
v2.0.15-KillTrx
v2.0.14
v2.0.14-ch_build_fix
v2.0.14-focal
v2.0.14-valgrind20200904
v2.1.0-3042
v2.0.14-3035
v2.0.14-3036
v2.0.14-2955
v2.0.14-vars
v2.0.14-3005
v2.0.14-3003
v2.0.14_2970_2979
v2.0.14-NOTSOCK
v2.1.0'
v2.0.14-2958
v1.4.10-zd
v2.0.13
v2.0.13-autocommit_fix
v2.1.0-2892
v2.0.13-2711
v2.0.13-duplicated_variables
v2.0.13-duplicated_variables_for_2.1.0
v2.0.12-deprecate_eof
v2.1.0-1377
v2.1.0-admin_queries
v2.0.12-var-global-multiplex
v2.1.0-var-foreign-key
v2.0.12
v2.0.12-tab-small-log
v2.0.12-var-foreign-key
v2.0.12-var-long-query-time
v2.0.12-galera-shunned
v2.1.0-admin_queries_2
v2.1.0-tap-rm-config
v2.0.12-tap-rm-config-test
v2.1.0-QP_stmt_3
v2.0.11-fix-multi-2-ci
v2.0.11-fix-multi
v2.0.11-266_0-3
2.1.0
v2.0.11
v2.1.0-track-vars
v2.1.0-track-variables
v2.0.11-track-variables
v2.0.11-2526
v2.0.11-tap-tests
v2.0.13-2698-commit1
v2.0.10-galera-pxc-maint-mode
v2.0.11-track-vars
v2.0.10-2647
v2.0.11-track
v2.0.11-track-session-vars
v2.0.9-var-array-review
v2.0.11-stats
v2.0.10
v2.0.10-centos67
v1.4.14.2
1.4.14.2
v1.4.14-show-warnings
v2.0.9
v2.0.9-var-array_2
v2.0.9-var-array
v1.4.16
v2.0.8
val214-changing_charset
v2.0.6
v1.4.16-1922_2
v1.4.13.2
v2.0.4-charset248
v2.0.5
v1.4.10-67841
v2.0.4
v2.0.4-sqlite327
v2.0.3
v2.0.2
v1.4.15
v2.0.1
v1.4.14
v2.0.0
v1.4.14-ping_shun
v1.4.14-1828
v1.4.14-latency_awareness
v1.4.12
v1.4.13-admin_deadlock
v2.0.0-improve_speed
v1.4.13
v1.4.13-autocommit_revert
v1.4.11.2
v1.4.13-ps
v2.0.0_bionic_deb_fix
v2_962
v1.4.12-1640
v1.4.11-names_tz
v1.4.12-1693
master
v1.4.11
v1.4.10
v1.4.6
v1.3.10
jenkins_test
v2.0.0-cachegrind
v1.4.9
v2.0-lab
v149_1511
v149_1382
v1.4.7-f2
v1.4.7-f1
v149_1491
v1.4.5-kub
v1.4.8
v2.0-web2
v1.4.3
v1.4.7
bsd_install_update
v1.4.2
v1.4.1-ch2
v1.4.1
v1.3.9
v1.4.1-ch
v1.3.8
v1.3.8-dev
v1.3.7
v1.3.7-dev
v1.3.6-dev
v1.4.0-clickhouse
v1.4.0
v1.3.6
v1.3.5
v1.3.5-dev
v1.4.0-955
v1.3.4
v1.3.4-dev
v1.3.3
v1.3.3-dev
v1.3.2
v1.3.2-dev
v1.3.2-766
v1.3.0h
v1.3.1-utf8mb4
1.4.0-840
v1.3.1
v1.2.6
v1.3.0
v1.4.0-797
v1.2.5-715
v1.2.5
v1.2.4-lowmem
v1.3.1-dev-mem
v1.2.0
connleak
lab-1.2.0
v1.1.2
T107_add_proxysql_consul_requirements
T89_write_consul_integration_doc
T98_consul_multi_table_config
mongoose
evhttp
SQLiteServer
1.0
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
2.7.3
2.6.6.1
3.0.1
2.7.2
3.0.0
2.6.6
2.7.1
2.7.0
2.6.5
2.6.4
2.6.3
2.6.2
2.6.1
2.5.5
2.6.0
2.5.4
2.5.3
2.5.2
2.5.1
2.4.8
2.5.0
2.4.7
2.4.6
2.4.5
2.4.4
2.4.3
2.4.2
2.4.1
2.4.0
2.3.2
2.3.1
2.3.0
2.2.2
2.2.1
2.2.0
2.0.18
2.1.1
2.0.17
2.0.16
2.0.15
2.0.14
2.0.13
2.0.12
2.0.11
2.1.0
2.0.10
2.0.9
2.0.8
2.0.7
2.0.6
2.0.5
2.0.4
2.0.3
2.0.2
1.4.16
1.4.15
2.0.1
1.4.14
1.4.13
1.4.12
1.4.11
1.4.10
1.3.10
1.4.9
2.0.0
1.4.8
1.4.7
1.4.6
1.4.4
1.4.3
1.4.2
1.3.9
1.3.8
1.4.1
1.3.7
1.4.0
1.3.6
1.3.5
1.3.4
1.3.3
1.3.2
1.3.1
1.3.0h
1.3.0g
1.3.0f
1.3.0e
1.3.0d
1.3.0c
v1.3.0b
1.4.5
v1.1.0
v1.1.0-rc
v1.1.1-beta
v1.1.1-beta.1
v1.1.1-beta.2
v1.1.1-beta.3
v1.1.1-beta.4
v1.1.1-beta.5
v1.1.1-beta.6
v1.1.2
v1.2.0a
v1.2.0b
v1.2.0c
v1.2.0d
v1.2.0e
v1.2.0f
v1.2.0g
v1.2.0h
v1.2.0i
v1.2.0j
v1.2.0k
v1.2.1
v1.2.2
v1.2.3
v1.2.4
v1.2.4.0923
v1.2.5
v1.2.6
v1.3.0
v1.3.0a
v1.3.0g
v1.3.0h
v1.3.1
v1.3.10
v1.3.2
v1.3.2-1
v1.3.3
v1.3.4
v1.3.5
v1.3.6
v1.3.7
v1.3.8
v1.3.9
v1.3.9-prev.1
v1.4.0
v1.4.1
v1.4.10
v1.4.11
v1.4.12
v1.4.13
v1.4.14
v1.4.15
v1.4.16
v1.4.2
v1.4.3
v1.4.4
v1.4.5
v1.4.6
v1.4.7
v1.4.8
v1.4.9
v2.0.0-beta.1
v2.0.0-rc1
v2.0.0-rc2
v2.0.1
v2.0.10
v2.0.11
v2.0.12
v2.0.13
v2.0.14
v2.0.15
v2.0.16
v2.0.17
v2.0.18
v2.0.2
v2.0.3
v2.0.4
v2.0.5
v2.0.6
v2.0.7
v2.0.8
v2.0.9
v2.1.0
v2.1.1
v2.2.0
v2.2.1
v2.2.2
v2.3.0
v2.3.1
v2.3.2
v2.4.0
v2.4.1
v2.4.2
v2.4.3
v2.4.4
v2.4.5
v2.4.6
v2.4.7
v2.4.8
v2.5.0
v2.5.1
v2.5.2
v2.5.3
v2.5.4
v2.5.5
v2.6.0
v2.6.1
v2.6.2
v2.6.3
v2.6.4
v2.6.5
v2.6.6
v2.7.0
v2.7.1
v2.7.2
v2.7.3
v3.0.0-alpha
v3.0.1
v3.0.2
v3.0.3
v3.0.4
v3.0.5
v3.0.6
v3.0.7
v3.0.8
v3.0.9
v3.1.6
v3.1.7
v3.1.8
v3.1.9
v4.0.6
v4.0.7
v4.0.8
${ item.name }
${ noResults }
237 Commits (feature/pgsql-native-backend-protocol)
| Author | SHA1 | Message | Date |
|---|---|---|---|
|
|
4e90372ef4 |
feat(pgsql): native SCRAM-SHA-256 client exchange over libscram with proof-correctness test
|
3 weeks ago |
|
|
ad31ded2fb |
feat(pgsql): native md5 password auth builder with known-vector unit test
|
3 weeks ago |
|
|
6ed54c51bf |
feat(pgsql): native startup + SSLRequest encoders with unit tests
|
3 weeks ago |
|
|
6874b5a9a2 |
fix(pgsql): harden backend framer (msg-length cap, realloc/overflow checks, noncopyable)
|
3 weeks ago |
|
|
544799257c |
feat(pgsql): native backend message framer with partial-message handling + unit tests
Add PgSQL_Backend_Msg_Framer: a pure wire-message framer for the native PostgreSQL backend protocol. It accepts fed bytes (possibly partial) and yields complete messages (type byte + 4-byte big-endian length-prefixed body), signaling FRAME_NEED_MORE on incomplete trailing bytes and FRAME_ERROR on a malformed length. Header stays light (cstdint/cstddef only). Destructor frees the realloc'd buffer to avoid a leak on long-lived connections. Wire it into libproxysql.a via _OBJ_CXX in lib/Makefile. Also fix a pre-existing duplicate vec.o on the unit-test link line: the test/tap/tests/unit/Makefile appended SQLITE3_LDIR/vec.o to STATIC_LIBS in two separate PROXYSQL40 blocks, producing ~98 duplicate-symbol errors that broke every unit test under PROXYSQL40. Keep the single append after the autodetection block. |
3 weeks ago |
|
|
46ab989adb
|
Merge commit from fork
fix(security): reject addresses after PROXY UNKNOWN (CVE-2026-48772 / GHSA-gw94-85m2-x8v2) |
1 month ago |
|
|
0d39ac6991 |
build: kill PROXYSQLGENAI flag, PROXYSQL40=1 builds all plugins
PROXYSQLGENAI was a leftover from before the genai plugin carve-out. All genai/MCP/AI/RAG code now lives in plugins/genai/ as a runtime loadable .so. Since the plugin chassis (PROXYSQL40=1) already builds and loads the genai .so, a separate flag serves no purpose. Entrypoint changes (all three -- rhel, suse, deb): - Build: pass PROXYSQL40=1 (not PROXYSQLGENAI=1) to make. - Packaging: copy genai .so alongside mysqlx when PROXYSQL40=1. - protobuf-devel install: gate on PROXYSQL40=1 (needed for mysqlx). Automated packaging verification added to all entrypoints: rpm -qpl / dpkg -c confirms both .so files are in the package. ELF smoke test: validates .so is a valid shared object exporting proxysql_plugin_descriptor_v1 symbol. Fails build on mismatch. Test Makefiles: PROXYSQLGENAI -> PROXYSQL40 for the vec.o link gate (test/tap/tests/Makefile and test/deps/cluster_simulator/Makefile). Updated remaining PROXYSQLGENAI references to PROXYSQL40 in: CLAUDE.md, include/cpp.h, lib/proxy_sqlite3_symbols.cpp, src/main.cpp (3x comments), proxysql.spec, test/infra/control/start-proxysql-isolated.bash, test/infra/control/run-unit-tests-asan-coverage.bash, and 14 genai test file comments. |
1 month ago |
|
|
778958b03d |
test(security): regression tests for PP1 UNKNOWN address spoof (GHSA-gw94-85m2-x8v2)
Cover the GHSA-gw94-85m2-x8v2 fix at two layers: Unit tests (test/tap/tests/unit/proxy_protocol_unit-t.cpp): - "PROXY UNKNOWN\\r\\n" returns false and sets header_was_unknown, source_address stays empty. - The advisory PoC payload "PROXY UNKNOWN 10.0.0.5 1.2.3.4 12345 3306\\r\\n" must NOT write "10.0.0.5" into source_address. - "PROXY UNKNOWNFOO ..." is rejected outright (not treated as UNKNOWN). - "PROXY TCP4xyz ..." is rejected — the protocol token must be followed by a single space. - Sanity check: a legitimate "PROXY TCP4 192.168.1.1 ..." still parses source_address correctly. Integration test (test/tap/tests/reg_test_pp1_unknown_spoof-t.cpp): - Mirrors the reporter's PoC end-to-end with MARIADB_OPT_PROXY_HEADER. Sets mysql-proxy_protocol_networks='*' and connects with "PROXY UNKNOWN 10.0.0.5 ...". Asserts that PROXYSQL INTERNAL SESSION's client.client_addr.address and client.PROXY_V1.source_address are NOT the forged "10.0.0.5". - Asserts "PROXY TCP4xyz ..." is not recorded as PROXY_V1 and does not spoof client_addr. - Positive control: legitimate TCP4 frame is still accepted and records the expected source IP. Wired the integration test into the same TAP groups as test_PROXY_Protocol-t so it runs everywhere PP1 is exercised. |
1 month ago |
|
|
2c2cfa59bb
|
Merge branch 'v3.0' into genai_5534
|
2 months ago |
|
|
43d3ee7cd2
|
Merge branch 'v3.0' into test/cluster-simulator
|
2 months ago |
|
|
421604d553
|
Merge branch 'v3.0' into genai_5534
|
2 months ago |
|
|
afb1510b98 |
test(genai): fix plan count off-by-one in genai_config_query_unit-t
CI-unit-tests-asan-coverage failed with "30 tests planned but 31 executed" The helper expect_query_value() emits 5 ok() calls and is invoked twice (10 assertions), plus 21 inline ok() calls in main(), for 31 assertions total. plan(30) -> plan(31) so the harness exit status reflects the real assertion count. |
2 months ago |
|
|
e6bef5c585 |
fix(pgsql): typecast handler swallows the rest of the query (#5755)
`process_pg_typecast()` in lib/pgsql_tokenizer.cpp had two related
bugs that made any `::TYPENAME` cast in the middle of a PostgreSQL
query silently truncate the digest from the cast onward.
## Bug 1: incorrect exit condition
After consuming the type name (and optional modifiers / array
brackets) the function tested whether the next char was in an
enumerated delimiter list (`)`, `(`, `;`, `,`, `+`, `-`, ...) and
returned `st_no_mark_found` only if so. For any other char (the
common case: a letter starting the next SQL keyword, e.g. the `F`
of `FROM`), it returned `st_pg_typecast`, which the dispatcher
then handled by:
1. advancing the cursor by one extra char via `inc_proc_pos()`
2. re-entering `process_pg_typecast()` on the next outer-loop
iteration
Because `tc->started` was already `true`, the re-entry skipped the
`::` skip and started "parsing" a new type name from the middle of
the next clause — silently consuming `FROM "Inventory" AS i WHERE
((i."TenantId" = $1) AND NOT (i."IsDeleted"))` and producing
digests like `SELECT COUNT(*) AND ((((i."State" ...` that drop
~65 chars of FROM/WHERE structure.
Fix: the function unconditionally returns `st_no_mark_found` after
consuming the typecast. The earlier delimiter check was
attempting to distinguish "this is the end of the typecast" from
"this is a continuation", but no continuation case actually
reaches that point — type modifiers and array brackets are already
handled inline above the check, and PG does not allow the cast
itself to span a non-modifier/bracket character.
## Bug 2: `tc->started` never reset
`pg_typecast_st::started` is a one-shot guard for the `::`-skip
entry block. It was set to `true` on first entry but never reset,
so a second `::cast` later in the same query (`SELECT 1::int,
2::text`) re-entered with `started=true` and skipped the `::`
skip, eating two characters from the wrong position.
Fix: reset `started=false` when exiting via the new unconditional
`st_no_mark_found` return.
## Side-effect: trailing-whitespace handling
The post-type-name "skip whitespace" loop existed to handle modifier
forms like `::int (10)` and `::int []` where PG allows whitespace
before the modifier/bracket. But it also ate the legitimate
separator space in the common form `::int FROM ...`, which would
then glue the two tokens together in the digest (`int` consumed,
`FROM` glued to the previous token). The new lookahead-conditional
skip preserves the trailing space unless the very next non-space
character is a modifier `(` or array bracket `[`.
## Test
Added 3 regression tests (5 ok() assertions) to
`test/tap/tests/unit/pgsql_tokenizer_unit-t.cpp` registered in
`unit-tests-g1`:
- `test_digest_typecast_followed_by_clause` — full repro from the
issue, asserts `from` and `where` survive, asserts the
double-quoted identifier survives.
- `test_digest_typecast_then_identifier` — bisected minimal
`SELECT a::int FROM t`.
- `test_digest_typecast_multiple_in_same_query` — covers Bug 2 by
using two `::cast` instances followed by a `FROM` clause.
The existing 6 typecast tests (typecast_simple, _varchar,
_with_modifier, _array, _in_where, _quoted) and the
`digest_2_with_typecast` thread-local-wrapper test continue to pass
verbatim. Modifier edge cases (`::varchar (255)` with space,
`::numeric(10,2)`, `::int[][]`, `::"my type" FROM t`) verified
manually with a standalone reproducer.
Closes #5755
|
2 months ago |
|
|
66820fc176 |
chore(lint): Make `SQLite3DB` table helpers const-correct
- `check_table_structure`, `build_table` and `check_and_build_table` never mutate their string arguments, so widen the parameter types from `char *` to `const char *`. - Drop the matching C-style casts at every call site that stripped const from string literals. Signed-off-by: Wazir Ahmed <wazir@proxysql.com> |
2 months ago |
|
|
9aee6d639e |
Implement real RAG source fetch
Replace the rag.fetch_from_source stub with a real backend read path for MySQL and PostgreSQL sources. The handler now looks up document metadata from the RAG vector database, resolves the configured source backend, validates identifiers, builds a safe source query, and returns a per-document result row that includes either the authoritative source row or a fetch error. Unsupported backend types are rejected explicitly, and the source query is capped to a single-row result. Add a focused unit test that seeds the RAG metadata tables, exercises the tool entry point, and verifies backend failure propagation plus missing-document handling without requiring a live external database. Also document /mcp/rag and the fetch semantics in the MCP architecture guide. |
2 months ago |
|
|
cd33ea1113 |
Document and test config query restrictions
Add end-user documentation for the /mcp/config query tool, including the SQL allowlist/denylist model, the single-statement requirement, and the structured response fields returned by the handler. Expand the TAP coverage to verify allowed SELECT/WITH/UPDATE paths, explicit rejection of PRAGMA/DDL/ATTACH, and false-positive resistance when forbidden tokens appear inside strings or comments. This keeps the config endpoint useful for controlled admin writes while preventing multi-statement and dangerous SQL execution. |
2 months ago |
|
|
520c4e4ec5 |
Fix genai config query unit test includes
|
2 months ago |
|
|
9a7058d879 |
Fix Darwin debug link for ParserSQL
|
2 months ago |
|
|
0c798fabbb |
Add config query tool
|
2 months ago |
|
|
ce365ad2ab
|
Merge branch 'v3.0' into feature/parsersql-integration
|
2 months ago |
|
|
a4d9318dce |
fix(build): add explicit build rule for genai_llm_clients_unit-t
After the GenAI plugin carve-out (Step 7), is_retryable_error() and LLM_WriteCallback() were moved from core to plugins/genai/src/LLM_Clients.cpp. The genai_llm_clients_unit-t test had no explicit build rule, falling through to the generic pattern rule that only links libproxysql.a. The linker failed with undefined references, causing make build_tap_tests_debug to exit with Error 2 before any unit tests (including all 26 mysqlx-tsan-g1 tests) could be built. Move genai_fts_string_unit-t and genai_llm_clients_unit-t into the ifeq ($(PROXYSQL40),1) conditional block and add an explicit rule for genai_llm_clients_unit-t that compiles LLM_Clients.cpp directly. |
2 months ago |
|
|
44c33cd2d3
|
Merge branch 'v3.0' into feature/parsersql-integration
|
2 months ago |
|
|
82d89444c4 |
fix: add genai include path and explicit build rules for genai unit tests
Genai unit tests (stats_parsing, query_handler, mcp_endpoint, mcp_thread, thread, discovery_schema, mysql_catalog) include genai headers from plugins/genai/include/ and instantiate genai types. The default pattern rule only has core include paths and links libproxysql.a (which has no genai symbols). Added: - genai include path to $(IDIRS) when PROXYSQL40 is set - moved 7 genai tests from unconditional to PROXYSQL40 conditional list - explicit rules compiling all genai sources into each test binary (deep transitive deps require the full genai source tree) |
2 months ago |
|
|
a9f2eaaa13 |
feat: remove PROXYSQLGENAI flag, genai now builds under PROXYSQL40 (issue #5722)
PROXYSQLGENAI flag eliminated entirely. PROXYSQL40=1 now unconditionally builds the genai plugin alongside core. All #ifdef PROXYSQLGENAI replaced with #ifdef PROXYSQL40 in source, Makefiles, and 61 CI workflows. |
2 months ago |
|
|
c68f60f04b |
merge: merge v3.0 into feature/parsersql-integration
Resolve conflict in test/tap/tests/unit/Makefile: keep v3.0's refactored linking (WHOLE_LIBPROXYSQL to avoid double-link under ASAN) and add -lsqlparser for parsersql integration. |
2 months ago |
|
|
a99d16ad27 |
Merge remote-tracking branch 'origin/v3.0' into issue-5729-stats-projection-abi
|
2 months ago |
|
|
88db9fd10f |
fix: resolve PR #5741 review findings (issue #5729)
- Fix groups.json sort order (CI lint failure) - Add sqlite3_mprintf null check in Anomaly_Detector (Gemini high) - Add ROLLBACK on DELETE/COMMIT error in 5 plugin_tables.cpp callbacks - Fix TAP plan count in test_stats_mcp_tables-t (12→11) - Fix TAP plan count in genai_plugin_anomaly_unit-t (24→25) - Fix ABI.md: register_runtime_view is ABI 3+, not ABI 4 - Update plan/spec docs: db_kind at struct tail (ABI backward compat) - Add Darwin -force_load fallback in src/Makefile - Add mkdir() error handling in AI_Features_Manager Verified: build clean, 30/30 unit tests pass, lint passes. |
2 months ago |
|
|
8a6540e816 |
fix: link libsqlparser and libprometheus in unit test Makefile
The unit test Makefile was missing: 1. -lsqlparser - resolves sql_parser::Parser symbols from Query_Processor_ParserSQL.cpp linked into libproxysql.a 2. -lprometheus-cpp-pull -lprometheus-cpp-core - resolves ~2700 prometheus symbols (pre-existing omission, always broken but masked by the parsersql link failure) 3. -I and -L for the parsersql include/library paths |
2 months ago |
|
|
b8cfa32c63 |
fix: address all critical and important code review findings (issue #5729)
Critical fixes: - Move db_kind to end of ProxySQL_PluginRuntimeView (tail-append = free ABI-3 compat) - Add mutex to protect Anomaly_Detector::user_statistics from concurrent session threads - Replace system(mkdir -p) with pure mkdir() loop (command injection fix) - Replace 77 std::stoi/stoll with non-throwing parse_int_or_zero/parse_ll_or_zero - Fix proxysql.cnf filename: Mysqlx -> MySQLX - Add --whole-archive to non-ClickHouse link path (plugin symbol resolution) Important fixes: - Add default: case with warning to db_kind switch in ProxySQL_PluginManager.cpp - Add config_db dispatch and null-handle tests to plugin_runtime_views_unit-t (6 new tests) - Update CLAUDE.md with sqlite-vec PROXYSQLGENAI exception - Remove stale anomaly_detection-t Makefile target - Replace fixed 1024-byte buffer with dynamic sqlite3_mprintf in Anomaly_Detector Minor: update ABI.md, PLUGIN_API.md, stale comments, unit test plan counts |
2 months ago |
|
|
c124cc4f6e |
fix(test): repair libproxysql.a double-link in unit-test asan-coverage build
The unit-test pattern rule (and per-test explicit rules) link libproxysql.a
twice: once via $(LIBPROXYSQLAR_FULL) (file path) and once via -lproxysql
inside MYLIBS. The MYLIBS reference was wrapped in --whole-archive in
commit
|
2 months ago |
|
|
d34aae155d |
test: fix runtime view unit test - use non-null DB handle sentinel (issue #5729)
|
2 months ago |
|
|
97649b5005 |
test: update genai plugin load unit test for 3-handle refresh (issue #5729)
|
2 months ago |
|
|
e91a831807 |
test: update runtime view unit tests for db_kind dispatch (issue #5729)
|
2 months ago |
|
|
54844df0bb
|
Merge branch 'v3.0' into v3.0-genai-plugin
|
2 months ago |
|
|
6f2b69d2eb |
test(mysqlx): align unit tests with new variable + response-state contracts
Two tests that the rebase onto v3.0 surfaced as failing under ASAN-coverage CI. Both are real test/code drift introduced by earlier commits in this stack, not pre-existing baseline issues. mysqlx_admin_commands_unit-t (test 24) Commit |
2 months ago |
|
|
960eeab8d2 |
feat(mysqlx): wire per-route tls_mode through handler_capabilities_set entry path
PR #5709 landed the splice mechanics for tls_mode='passthrough' plus the per-route tls_mode column on mysqlx_routes, but no code consulted the route's tls_mode to actually drive the session into X_PASSTHROUGH_FORWARD from real client traffic — a route configured as `tls_mode='passthrough'` behaved identically to `'inherit'`. This commit closes the gap (issue #5710): (1) Advertise gating in send_capabilities() ----------------------------------------- A new helper, MysqlxSession::effective_route_tls_mode(), reads listener_route_name_ + the thread's MysqlxConfigStore and returns the per-route tls_mode (or `inherit` when listener route is empty / config store is unwired — preserving historical behaviour for tests and unconfigured deployments). send_capabilities() now suppresses the `tls` capability from the advertised set when route_tls_mode == disabled. Other modes (inherit / preferred / required / passthrough) advertise TLS the same way as before — passthrough MUST advertise so the client even thinks to upgrade. (2) Symmetric refusal in handler_capabilities_set() ------------------------------------------------ A client that sends CapabilitiesSet(tls=true) on a disabled-mode route is refused with X-Protocol error 5052 ("TLS is not enabled on this route"). Symmetric with the advertise gate; we never told the client TLS was available, so accepting it would be a silent policy bypass. (3) Passthrough entry from handler_capabilities_set() -------------------------------------------------- When CapabilitiesSet(tls=true) lands on a passthrough-mode route: a. resolve_passthrough_backend_target() picks the endpoint from the route's destination_hostgroup (no identity_ — passthrough authenticates end-to-end); b. the original CapabilitiesSet frame bytes are buffered in passthrough_pending_capset_frame_ for verbatim forwarding; c. tls_mode_ flips to TLS_PASSTHROUGH and status_ to the new X_PASSTHROUGH_BACKEND_CONNECTING state. (4) X_PASSTHROUGH_BACKEND_CONNECTING handler ----------------------------------------- handler_passthrough_backend_connecting() drives the four-step sequence: 1. allocate / pick up backend_conn_, start non-blocking TCP connect; 2. poll check_connect() to completion; 3. write the buffered CapabilitiesSet bytes verbatim to the backend (with EAGAIN/partial-write retries); 4. read exactly one X-Protocol frame from the backend (the LAST X-Protocol parse this session does); on Ok forward to the client and transition to X_PASSTHROUGH_FORWARD; on Error propagate to the client and close. The handler is registered both in the early fast-path branch of MysqlxSession::handler() (so the X-Protocol read on client_ds_ is skipped — the client's next bytes are the TLS ClientHello which is not parseable as an X frame) and in the main dispatch switch. Tests (test/tap/tests/unit/mysqlx_session_unit-t.cpp, +11 ok()s): * test_route_tls_mode_disabled_no_tls_in_advertise: drives CapabilitiesGet on a tls_mode='disabled' route, parses the response, asserts the advertised set has no `tls` capability. * test_capabilities_set_tls_refused_on_disabled_route: drives CapabilitiesSet(tls=true) on the same route, asserts session becomes unhealthy and the client receives a Mysqlx::Error. * test_route_passthrough_full_entry_path: end-to-end exercise. Stands up a loopback TCP listener as the "backend"; configures a passthrough route pointing at the listener; drives CapabilitiesGet -> CapabilitiesSet(tls=true); asserts the proxy forwards the CapabilitiesSet bytes verbatim, transitions through X_PASSTHROUGH_BACKEND_CONNECTING into X_PASSTHROUGH_FORWARD on the backend's Ok response, and stays healthy. Plan count: 87 -> 98 (after Fix B) -> 109. Closes #5710. |
2 months ago |
|
|
b7c5a08b96 |
feat(mysqlx): backlog and resume EAGAIN'd writes in passthrough splice
Previously, the passthrough splice loop's pump_one_direction helper
treated EAGAIN/EWOULDBLOCK on write() as fatal — the session
transitioned to X_SESSION_CLOSING and the connection was dropped. In
practice this turned any transient destination back-pressure (slow
client, slow backend, kernel send-buffer drained more slowly than the
proxy reads from the source side) into a connection drop. End-to-end
encrypted sessions (the whole point of tls_mode='passthrough') would
RST mid-stream under bursty load.
Fix: per-direction write backlog, drained before the next read.
* Add MysqlxSession::passthrough_c2b_backlog_ and
passthrough_b2c_backlog_ — std::vector<uint8_t> buffers for
bytes that read() from the source side could not be immediately
flushed to the destination side. Cleared on init() / reset().
* handler_passthrough_forward() now runs a drain pass over the
backlog BEFORE the read pass. drain_backlog() loops on write(),
EAGAIN means "not now, leave it for the next tick"; any other
write error fails the session.
* On a partial-write inside the read pass, the unwritten tail is
appended to the backlog (append_to_backlog) and the read pass
yields. A future pump tick (driven by either the libev EV_READ
wakeup on the source or the buffered-work re-arm via
`to_process = true`) drains the backlog and resumes reading.
* Backlog cap: 1 MiB per direction
(PASSTHROUGH_BACKLOG_CAP). Above the cap, append_to_backlog
refuses and the session is killed (X_SESSION_CLOSING) — slow-
consumer DoS protection. The drain-first contract limits the
backlog organically to BURST_BYTES (64 KiB), so the cap is
purely defensive against a future logic bug or a larger burst.
* to_process = true on a non-empty backlog so the outer dispatch
loop re-enters us on the next tick rather than waiting for a
new fd-readable event on the source — without this, a long
stall on the destination side could let the backlog grow on
each new source byte before the previous backlog was drained.
Tests (test/tap/tests/unit/mysqlx_session_unit-t.cpp):
* test_passthrough_eagain_backlog_drains_across_ticks: drives
256 KiB through a backend leg with SO_SNDBUF/RCVBUF shrunk to
4 KiB so write() returns EAGAIN early and often. Asserts
session stays healthy in X_PASSTHROUGH_FORWARD across the
repeated EAGAIN events; all 256 KiB are eventually delivered;
no byte-level corruption.
* test_passthrough_backlog_cap_kills_session: uses the
MYSQLX_TEST_BUILD-only seed_passthrough_c2b_backlog_for_test
+ try_append_to_passthrough_c2b_backlog_for_test helpers to
drive the cap branch directly. Asserts within-cap append is
accepted, over-cap append is refused, and the session
transitions to X_SESSION_CLOSING with healthy=false.
Plan count moves from 87 to 98.
|
2 months ago |
|
|
e855ba37c8 |
fix(mysqlx): decode backend TLS error code before falling back to plaintext (preferred mode)
Previously, when a session was in `preferred` TLS mode (try TLS, fall
back to plaintext on Error) and the backend responded with ANY
Mysqlx::Error to the client's CapabilitiesSet(tls=true), the code
silently dropped TLS and proceeded plaintext. Non-TLS errors
("internal server error", "out of memory", "permission denied", etc.)
were therefore swallowed and the auth flow proceeded against a backend
that just told us it was unhealthy — masking real failures and
encouraging brittle deployments.
The upstream MySQL X client at plugin/x/client/xsession_impl.cc gates
the same fallback exactly on `ER_X_CAPABILITIES_PREPARE_FAILED` (5001),
which is the only code that the X plugin's `Capability_tls::set_impl`
emits when the server has no SSL context (see
plugin/x/src/capabilities/handler_tls.cc — code 5001 is what
`ngs::Error(ER_X_CAPABILITIES_PREPARE_FAILED, ...)` produces). Mirror
that policy here:
* Parse the Mysqlx::Error body's `code` field.
* Fall back to plaintext only when the code is exactly 5001.
* Any other code (or a code-less / unparseable Error body) is fatal —
transition to BACKEND_AUTH_ERROR and return -1.
The existing `preferred-mode fallback` unit test (which already injects
code 5001) still passes. Two new tests cover the new gate:
* preferred-mode + non-TLS error code 1045 (Access denied): no
fallback, auth_state=ER, rc=-1.
* preferred-mode + Error frame with no decodable code (empty body):
no fallback, auth_state=ER, rc=-1.
The pre-existing required-mode test (no fallback regardless of code) is
unchanged.
|
2 months ago |
|
|
352455d79c |
test(mysqlx): free fixture allocations leaked under LeakSanitizer
Closes #5703. Phase 1 of the ASAN sanitizer pass on PR #5651 surfaced two test-side leaks: 1. mysqlx_admin_commands_unit-t.cpp:210 — the SQLite3_result* returned by execute_statement was wrapped in a unique_ptr with a custom no-op deleter, with the comment "leaked intentionally for test scope". The "intentionally" was test-author convenience, not a real reason — the default unique_ptr<SQLite3_result> deleter calls ~SQLite3_result(), which the type supports. Drop the no-op deleter. 2. mysqlx_message_dispatch_unit-t.cpp::test_connection_pool_matching — two MysqlxConnection* allocations (c1 at line ~551, c2 at line ~566) are inserted into the per-thread cache and then extracted via get_connection_from_cache(). Extraction transfers ownership to the caller (the cache erases the entry); the test never re- pools or deletes them, so they leak. Add explicit `delete found; delete f2;` at end of test with a comment explaining the ownership transfer. Verified locally under ASAN with detect_leaks=1: both tests now report 0 LeakSanitizer findings. The pre-existing failure of test 24 in mysqlx_admin_commands_unit-t ("mysqlx_variables has 4 rows after save (all known variables)") is unrelated to this PR — it predates the parity-cleanup branch and exists on parent. |
2 months ago |
|
|
bd906167fb |
fix(mysqlx): place NOSONAR(cpp:S4423) on the same line as TLS_method()
SonarCloud's NOSONAR annotation only suppresses when it appears on the same source line as the rule trigger; preceding comment blocks don't count. The previous attempt put the rationale in a 5-line block comment above the SSL_CTX_new call, which SonarCloud ignored — quality gate stayed red on PR #5711 / #5713 / #5714 because the S4423 vulnerability finding still landed. Move the rationale into the function-level doc comment and put a short `// NOSONAR(cpp:S4423)` trailer on the SSL_CTX_new line itself. That's the syntactic shape SonarCloud's parser actually recognizes. |
2 months ago |
|
|
8566d93df9 |
fix(mysqlx): suppress SonarCloud S4423 false positive on TLS_method() in classifier test
The cpp:S4423 rule flags TLS_method() as a 'weak protocol' constructor. That was true for SSLv23_method() — TLS_method() is the OpenSSL 1.1+ recommended replacement and defaults to TLS 1.2+. Protocol-version floor is set via SSL_CTX_set_min_proto_version where the test runs real handshakes (e.g. create_test_ssl_ctx at line 64 sets TLS1_2_VERSION). The classifier test fixture in make_synthetic_ssl (line 292) never runs a handshake — it stages SSL_set_verify_result state and feeds the SSL* directly to the classifier under test. Version negotiation is not exercised, so a min_proto_version setter would be cargo-cult. Rather than introduce a no-op call, suppress the false positive with NOSONAR + a comment explaining why. This was the lone VULNERABILITY on PR #5711's SonarCloud report; with it suppressed, new_security_rating drops from 4 (D) to 1 (A) and the quality gate flips green. |
2 months ago |
|
|
0ccf3615f1 |
fix(mysqlx): classify backend TLS handshake failures into specific error codes
Closes #5698 (P3 — meaningful TLS error messages on backend failures). Background: prior to this commit, backend TLS handshake failures all emitted a single generic "Backend TLS handshake failed" with code 3152; frontend TLS failures all emitted "TLS handshake failed" code 3151. Operators debugging TLS issues had to attach with `openssl s_client` or run the proxy under SSL_TRACE / SSLKEYLOGFILE to figure out whether the underlying cause was an expired cert, a hostname mismatch, an untrusted CA, or a protocol-version mismatch. MySQL Router translates each of these into a distinct X-Protocol error code and shortcuts the debug session. Implementation: 1. New MysqlxTlsErrorClass enum (HANDSHAKE_FAILED, CERT_VERIFY_FAILED, CERT_EXPIRED, HOSTNAME_MISMATCH, PROTOCOL_MISMATCH, UNKNOWN_CA, NO_SSL_CTX, UNKNOWN). Lives in mysqlx_protocol.h alongside the per-class X-Protocol error code constants. 2. New mysqlx_classify_tls_error(SSL*, peek_err_queue) helper. Classification logic in order: a. SSL == nullptr -> NO_SSL_CTX b. SSL_get_verify_result() != X509_V_OK -> chain class (CERT_EXPIRED for expired/not-yet-valid; HOSTNAME_MISMATCH; UNKNOWN_CA for self-signed-in-chain or unable-to-get-issuer; CERT_VERIFY_FAILED for everything else cert-chain) c. ERR_get_error() walked for SSL_R_UNSUPPORTED_PROTOCOL / TLSV1_ALERT_PROTOCOL_VERSION / WRONG_VERSION_NUMBER / UNKNOWN_PROTOCOL -> PROTOCOL_MISMATCH d. Fallback -> HANDSHAKE_FAILED Cert-chain reasons take precedence because the OpenSSL queue sometimes carries both, and the chain reason is more actionable. 3. Backend codes (5+ distinct, 3152-3157): 3152 BACKEND_TLS_ERR_HANDSHAKE_FAILED (was: only existing code) 3153 BACKEND_TLS_ERR_CERT_VERIFY_FAILED (NEW) 3154 BACKEND_TLS_ERR_CERT_EXPIRED (NEW) 3155 BACKEND_TLS_ERR_HOSTNAME_MISMATCH (NEW) 3156 BACKEND_TLS_ERR_PROTOCOL_MISMATCH (NEW) 3157 BACKEND_TLS_ERR_UNKNOWN_CA (NEW) Backend messages name the OpenSSL reason in operationally-useful terms ("certificate hostname mismatch") but do NOT include the raw OpenSSL queue string in the wire frame — that is logged to stderr separately for the operator's benefit. 4. Frontend codes (3 distinct): 3150 FRONTEND_TLS_ERR_NOT_CONFIGURED (existing — NO_SSL_CTX) 3151 FRONTEND_TLS_ERR_HANDSHAKE_FAILED (existing — every other class) 3158 FRONTEND_TLS_ERR_PROTOCOL_MISMATCH (NEW — operationally useful for legitimate clients hitting a too-old/too-new TLS version) Frontend collapses CERT_*/HOSTNAME_MISMATCH/UNKNOWN_CA onto HANDSHAKE_FAILED specifically to avoid leaking attacker-supplied cert info into the response (asymmetric threat model — the frontend client may be the attacker). 5. New MysqlxConnection::tls_error_class_ member + accessors. Set by step_auth_tls_handshake() at the failure site (the OpenSSL error queue is thread-local FIFO and must be drained while fresh; we can't defer the classification to the session). Read by the session's BACKEND_AUTH_ERROR branch in handler_connecting_server when emitting send_error(). 6. Frontend handler_tls_accept_init() also runs the classifier and emits via the frontend code/message helpers. Logs the OpenSSL queue to stderr (operator-side only). Tests (in mysqlx_tls_unit-t): - test_classify_null_ssl: nullptr -> NO_SSL_CTX (1 ok) - test_classify_cert_expired_via_verify_result (1 ok) - test_classify_hostname_mismatch_via_verify_result (1 ok) - test_classify_unknown_ca_via_verify_result: 2 sub-cases (UNABLE_TO_GET_ISSUER + SELF_SIGNED_IN_CHAIN) (2 ok) - test_classify_generic_cert_verify_failed: SIGNATURE_FAILURE -> generic (1 ok) - test_classify_handshake_failed_default (1 ok) - test_classify_code_message_round_trip_backend: 7 classes * 2 (msg + code-range) + 1 distinct-codes assertion (15 ok) - test_classify_code_message_round_trip_frontend: collapse + 3 distinct-code asserts (4 ok) The cert-fixture-driven tests (real expired/hostname-mismatched/ self-signed cert chains) are explicitly punted per the issue's "don't generate cert fixtures in this PR" guidance. The classifier accepts SSL_set_verify_result-staged synthetic state, which exercises the same code paths as a real cert failure (since the only thing the classifier reads off SSL is the verify_result long); a follow-up issue covers wiring an end-to-end TAP test against a fixture-driven backend. Build: NOJEMALLOC=1 WITHASAN=1 PROXYSQLGENAI=1 plugin .so + build_tap_test_debug all green. Pre-existing RSA_new deprecation warnings unchanged. Tests: mysqlx_tls_unit-t (44/44, was 18 — +26 from 8 new tests). Other suites unchanged. ASAN-clean. |
2 months ago |
|
|
767f808309 |
fix(mysqlx): mark post-Session::Reset connections non-cacheable
Closes #5697 (P3 — Session Reset pool invalidation). Background: X-Protocol's Session::Reset frame asks the server to wipe session state (current schema, isolation level, charset, prepared statements, session vars) without reauthenticating. ProxySQL forwards the frame and dispatches the backend Ok response correctly — but until this commit, the connection was returned to the per-thread cache as a regular IDLE entry afterwards. The cache key (hostgroup, user, schema, tls_active) doesn't capture session-state-version, so a subsequent reuse from the same identity could pick up the post-reset connection and silently inherit blank state instead of the per-identity defaults. The pool-leak scenario in practice: - Client A issues Session::Reset on backend B. - Backend B is returned to the per-thread cache as IDLE. - Client A2 (same user/schema/hostgroup/tls posture) next request pulls B from the cache. - Client A2 sees blank session state, even though it expected the per-identity defaults a fresh-auth connection would provide. MySQL Router treats Session::Reset as pool-terminating; this commit brings ProxySQL in line. Implementation: - New MysqlxConnection::needs_post_reset_rehandshake_ bool member + accessor pair (set/get). Default false. - is_reusable() returns false when the flag is set, so Mysqlx_Thread::return_connection_to_cache deletes the connection instead of pooling it. - reset() defensively clears the flag too. Production path doesn't rely on this (the cache deletes non-reusable conns instead of resetting them), but the invariant matters for any future code path that calls reset() directly (e.g. retry-on-error). - handler_session_reset_waiting() sets the flag on the Mysqlx.Ok branch — the only path where Session::Reset succeeded. The Error branch already marks the connection non-reusable for unrelated reasons (the Reset itself failed), so no change needed there. We do NOT implement the rehandshake path itself in this commit; the simpler "drop on reset" semantic matches Router's behaviour and is strictly safer than the pre-fix "silently pool blank state". Tests: - mysqlx_connection_unit-t::test_connection_post_reset_rehandshake_flag asserts the flag's defaults, set/get round-trip, is_reusable() interaction, and reset() defensive-clear behaviour (6 ok()). - mysqlx_message_dispatch_unit-t::test_dispatch_sess_reset_marks_non_cacheable drives the full SESS_RESET → backend-Ok → return-to-pool flow with a fake backend and asserts the connection is non-cacheable afterwards. Strengthens the existing test_dispatch_sess_reset which only proved the dispatch reached the backend (5 ok() — pre-flag/state, post-dispatch status, post-condition observed via backend_conn being deleted on the non-reusable path). - mysqlx_connection_unit-t plan switched to plan(0) so future additions don't require re-counting. Build: NOJEMALLOC=1 WITHASAN=1 PROXYSQLGENAI=1 plugin .so + build_tap_test_debug all green, no compile warnings. Tests: mysqlx_connection_unit-t (16/16, was 10), mysqlx_message_dispatch_unit-t (114/114, was 109). Other suites unchanged. ASAN-clean. |
2 months ago |
|
|
31a3934014 |
fix(mysqlx): explicit auth-phase notice forwarding policy in step_auth
Closes #5695 part 2 (P2 — explicit per-state policy for backend NOTICE frames during the backend auth handshake; data-plane validation landed in the previous commit). Background: prior to this commit, MysqlxConnection::read_auth_frame() silently drained ALL backend NOTICE frames during the BACKEND_AUTH_* state machine. The drain was needed (MySQL backends commonly emit a SESSION_STATE_CHANGED notice before AuthenticateContinue / Ok, and returning nullopt on a NOTICE caused auth to spin until the 10s handshake timeout) but it was indiscriminate — a malformed/unknown-type NOTICE would be drained as silently as a legitimate one. This commit adds an explicit per-state policy: - New helper auth_phase_notice_is_drainable(body, body_len). Parses the NOTICE as a Mysqlx::Notice::Frame and applies a per-type decision: WARNING / SESSION_VARIABLE_CHANGED / SESSION_STATE_CHANGED / GROUP_REPLICATION_STATE_CHANGED / SERVER_HELLO -> drain malformed / empty / unknown enum value -> fail auth WARNING and GROUP_REPLICATION_STATE_CHANGED are also logged on the drain path: WARNING during auth typically signals a server-side misconfig (deprecated auth method, etc.); GROUP_REPLICATION_* during auth is operationally out-of-place (cluster-membership notices belong on data-plane connections, not handshakes). Both are drained to preserve compatibility with over-eager backends but surfaced for operator triage. - Wired into read_auth_frame() between the MAX_LEADING_NOTICES cap and the type==NOTICE branch. On a fail-auth result, the helper has already set auth_state_=BACKEND_AUTH_ERROR and logged; the caller propagates std::nullopt and step_auth fails the connection. - Frontend forwarding during auth: explicitly NEVER allowed. The frontend client has no context to interpret a backend NOTICE before it sees AuthenticateOk; surfacing them would also leak server-side state mid-handshake (the load-bearing concern in issue #5695). The proxy terminates ALL backend NOTICEs on the backend leg during the backend auth phase — even legitimate ones. - Test-only hooks under MYSQLX_TEST_BUILD: a public auth_phase_notice_is_drainable_for_test() and a set_auth_state_for_test() so unit tests can drive the per-type decision matrix directly without running the full step_auth state machine. Tests (in mysqlx_backend_auth_unit-t): - test_auth_phase_notice_known_types_drained: all five spec types are drainable and don't perturb auth_state_ (5*2=10 ok()). - test_auth_phase_notice_unknown_type_fails_auth: type=99 fails auth and sets BACKEND_AUTH_ERROR (2 ok()). - test_auth_phase_notice_malformed_fails_auth: garbage protobuf bytes fail auth (2 ok()). - test_auth_phase_notice_empty_fails_auth: empty body fails auth (2 ok()). - Switched the existing plan(42) to plan(0) so future additions don't require re-counting; existing test_backend_auth_notice_skip (which uses Frame_Type_WARNING) continues to pass under the new policy because WARNING is still on the drainable list. Build: NOJEMALLOC=1 WITHASAN=1 PROXYSQLGENAI=1 plugin .so + build_tap_test_debug all green, no compile warnings. Tests: mysqlx_backend_auth_unit-t (58/58, was 42 — +16 from the 4 new tests), other suites unchanged. ASAN-clean. |
2 months ago |
|
|
6ef8cf3f1f |
fix(mysqlx): validate Mysqlx::Notice::Frame::type before forwarding
Closes #5695 part 1 (P2 — explicit notice forwarding awareness; auth-phase per-state policy is the next commit; per-notice metric remains under #5691 follow-up scope). Background: X-Protocol NOTICE frames are non-terminal informational messages a backend can emit at essentially any state transition (warnings, session-state changes, generated-doc-id notifications, group-replication membership changes, etc.). Prior to this commit the proxy forwarded NOTICE frames uncritically; a buggy or hostile backend (or an MITM that bypassed TLS) could ship a NOTICE frame with an unknown `type` enum value and confuse a strict client. The risk is bounded — info disclosure, no auth bypass — but it's unhardened territory MySQL Router handles explicitly. This commit adds a per-frame validation hook on the data plane: - New MysqlxSession::is_notice_frame_valid(body, body_len). Pure query — no session-state mutation. Parses the body as a Mysqlx::Notice::Frame and verifies the outer `type` field is in the spec range (1..5: WARNING, SESSION_VARIABLE_CHANGED, SESSION_STATE_CHANGED, GROUP_REPLICATION_STATE_CHANGED, SERVER_HELLO) using the protoc-generated Frame_Type_IsValid(). Empty body, malformed protobuf, missing required `type` field, and out-of-range enum values all return false. - Wired into handler_waiting_server_msg() and handler_session_reset_waiting() before forwarding NOTICE to the client. Invalid notices are dropped with a stderr log line tagged with route+hostgroup+body_len for operator triage; the response sequence continues (NOTICE is non-terminal in every state). - Test-only hook is_notice_frame_valid_for_test() exposed under MYSQLX_TEST_BUILD so unit tests can drive the predicate directly with synthetic bodies without setting up a fake backend. Tests (in mysqlx_message_dispatch_unit-t): - test_notice_validation_known_types_accepted: all five spec types pass (5 ok()). - test_notice_validation_unknown_type_rejected: types 0, 99, and 100000 are rejected (3 ok()). - test_notice_validation_empty_body_rejected: nullptr body and zero-length body both rejected (2 ok()). - test_notice_validation_malformed_protobuf_rejected: garbage bytes that fail ParseFromArray are rejected (1 ok()). We deliberately do NOT validate the inner `payload` bytes — that's a type-specific protobuf the client parses, and the proxy has no business reaching into it. The outer `type` is the load-bearing field for client-side branching, so that's where we focus. Build: NOJEMALLOC=1 WITHASAN=1 PROXYSQLGENAI=1 make build_lib + plugin .so + build_tap_test_debug all green. Tests: mysqlx_session_unit-t (87/87), mysqlx_message_dispatch_unit-t (109/109, was 98 — +11 from the 4 new tests), mysqlx_compression_unit-t (64/64), mysqlx_tls_unit-t (18/18), mysqlx_thread_unit-t (25/25), mysqlx_concurrent_unit-t (6/6). All ASAN-clean. |
2 months ago |
|
|
9ea2b31bf5 |
fix(mysqlx): match upstream X-Protocol error code for compression-without-algorithm
Closes #5696 (P2 — MySQL Router parity gap, compression error code). Before this change the mysqlx plugin emitted error code 5008 for every compression-related failure ("Compression frame received without negotiated algorithm", parse failures, decompression failures, etc.). That code does not match upstream MySQL X plugin: 5008 in plugin/x/src/xpl_error.h is ER_X_BAD_CONNECTION_SESSION_ATTRIBUTE_TYPE — a totally unrelated session-attribute error. A client written specifically against the upstream X-Protocol error contract would see the wrong error class entirely. Authoritative source for the canonical codes: plugin/x/src/xpl_error.h in the MySQL 8.4 source tree (deps/mysql-connector-c-8.4.0/.../xpl_error.h in this repo). Mapping: - 5170 ER_X_FRAME_COMPRESSION_DISABLED — compression frame received when the client did not negotiate compression. Upstream message: "Client didn't enable the compression." Reproduced verbatim. - 5174 ER_X_BAD_COMPRESSED_FRAME — structural problem with the Compression envelope (empty body, malformed protobuf, bogus uncompressed_size hint, decompressed payload that doesn't reframe into valid X messages). - 5171 ER_X_DECOMPRESSION_FAILED — algorithm-side failure (lz4/zstd error, OOM, stall, decompressed payload exceeds cap). - 5000 ER_X_BAD_MESSAGE — server-direction compression on the client→server path; treated as a wrong-direction message rather than a compression-specific failure. The pre-auth capability replay-cap error (also previously emitting 5008) is a ProxySQL-specific guardrail with no upstream analogue and is left untouched in this commit — the parity fix is scoped to the genuine compression error sites. Test updates: - mysqlx_message_dispatch_unit-t::test_dispatch_compression_rejected: asserts 5170 (was 5008). - mysqlx_compression_unit-t: oversize/garbage rejections assert 5171, no-negotiation rejection asserts 5170, "no error frame" tests accept any of 5170/5171/5174 (renamed got_5008 → got_compression_err). - test_compression_without_negotiation_still_5008 → test_compression_without_negotiation_still_5170. Build: NOJEMALLOC=1 WITHASAN=1 PROXYSQLGENAI=1 make build_lib + plugin .so + build_tap_test_debug all green. Tests: mysqlx_session_unit-t (87/87), mysqlx_message_dispatch_unit-t (98/98), mysqlx_compression_unit-t (64/64), mysqlx_tls_unit-t (18/18), mysqlx_thread_unit-t (25/25), mysqlx_concurrent_unit-t (6/6) — all ASAN-clean. |
2 months ago |
|
|
2e7e532050 |
feat(mysqlx): X_PASSTHROUGH_FORWARD session state — raw byte splice
Implements the data-plane half of the per-route TLS passthrough mode (issue #5692). Once a session enters this state the proxy stops parsing X-Protocol frames; bytes are read from one side and written to the other verbatim using read(2)/write(2). Used cases: end-to-end TLS where operator policy forbids proxy MITM (compliance, original cert/SNI/ALPN preservation). Session machine additions: * `MysqlxSession::Status::X_PASSTHROUGH_FORWARD` — terminal state for passthrough sessions. Once entered, the session never returns to any X-Protocol parsing state. handler() short-circuits past client_ds_.read_from_net()/parse so the bytes are not interpreted as frames. * `MysqlxTlsMode::TLS_PASSTHROUGH` — added back to the per-session TLS posture enum. The previous prototype carried the value without a real implementation; that was removed in the asymmetric-TLS series and is now reintroduced as a real feature. * `handler_passthrough_forward()` — pumps both directions per call up to a 64 KiB burst, then yields so other sessions on the thread are not starved. EAGAIN/EWOULDBLOCK is the normal "no more bytes right now" exit. EOF on either side or any other I/O error transitions to X_SESSION_CLOSING. Listener-route propagation: * New `MysqlxSession::init(fd, thread, listener_route)` overload. The base init(fd, thread) overload calls it with an empty route name, preserving existing test harnesses that construct sessions directly. * `Mysqlx_Thread::accept_new_connection()` looks up the listener fd in the parallel `listener_route_names_` vector and propagates the route name to the new session at accept time. This is the hook that lets per-route policies fire before any X-Protocol message is received — most importantly, before any local handshake decision so a passthrough route can splice from the very first byte. Test-only entry path: * `enter_passthrough_for_test(int backend_fd)` (gated behind MYSQLX_TEST_BUILD) drops a session straight into the splice state with a caller-supplied backend fd. Bypasses CapabilitiesSet / auth / resolve_backend_target so the splice mechanics can be asserted in isolation. set_reusable(false) is set on the stub backend connection to mirror the production-side invariant that a passthrough connection never returns to the pool. Tests (mysqlx_session_unit-t, +22 assertions, plan 65 -> 87): * listener_route_propagation: init() captures, reset() clears * forward_client_to_backend / forward_backend_to_client: bytes survive the splice unchanged in both directions * close_on_client_eof / close_on_backend_eof: peer half-close transitions to X_SESSION_CLOSING and marks the session unhealthy * disables_backend_reuse: backend_conn() exists but is_reusable()=false, and tls_mode_ reports TLS_PASSTHROUGH * handler_dispatch_skips_xprotocol: bytes that would parse as a fake X frame in a non-passthrough state survive the splice unconsumed — proves handler() takes the fast path before the X frame parser sees the buffer Production wiring of the entry path (CapabilitiesSet on a passthrough route -> connect to backend, splice the TLS handshake) lands in a follow-up. This commit is intentionally limited to the splice mechanics plus the listener-route plumbing the entry path will need. |
2 months ago |
|
|
09c42d4fba |
feat(mysqlx): add per-route tls_mode column with passthrough enum value
Adds the schema and config-store plumbing needed to express MySQL Router's
TLS-Passthrough mode as a per-route attribute on `mysqlx_routes`. The actual
data-plane forwarding is implemented in a follow-up commit; this commit only
wires the config so the operator can set / round-trip / project the value.
Schema additions:
* `mysqlx_routes.tls_mode VARCHAR NOT NULL DEFAULT 'inherit'` plus a CHECK
constraint on the canonical lowercase spellings ('inherit', 'disabled',
'preferred', 'required', 'passthrough'). Same column added to
`runtime_mysqlx_routes`.
* Default 'inherit' means "use the deployment-wide `mysqlx_tls_mode`",
preserving existing behaviour for every row that was loaded before this
commit. Operators wanting compliance-pinned passthrough can override one
route at a time without flipping the global mode.
Config store additions:
* `MysqlxRouteTlsMode` enum class (inherit / disabled / preferred / required
/ passthrough) plus matching `mysqlx_route_tls_mode_from_string` (case-
insensitive, empty/NULL -> inherit, unknown -> nullopt) and `_to_string`
helpers — same shape as the existing `mysqlx_backend_tls_mode_*` family.
* `MysqlxRoute::tls_mode` field with a default of `inherit`.
* `MysqlxConfigStore::route_tls_mode(name)` accessor; unknown routes report
`inherit` (matching how `route_hostgroup` returns 0 for unknown routes).
LOAD / SAVE / project paths:
* `install_routes_from_admin` first PRAGMA-probes for the `tls_mode` column
so a pre-upgrade admin DB without it loads cleanly (column treated as
NULL -> inherit). A malformed value (e.g. operator typo) fails the install
with a descriptive `err` rather than silently coercing.
* `save_routes_to_admin_table` and `project_routes_to_runtime_view` write
the column using `mysqlx_route_tls_mode_to_string`.
Tests:
* mysqlx_config_store_unit-t gains nine assertions covering parser
case-insensitivity, the empty-string / unknown-value contract, the
canonical render, the legacy-schema fallback path, and a full
install / parse-failure round-trip against a schema that has the column.
* All previously-passing unit tests remain green.
This commit is intentionally behaviour-preserving: passthrough is parsed
and stored but not yet enforced. Resolving a route with tls_mode=passthrough
still goes through the proxy-terminated path until the follow-up commit
adds the X_PASSTHROUGH_FORWARD session state.
|
2 months ago |
|
|
744fb0bf36 |
feat(mysqlx): preferred-mode backend TLS fallback to plaintext + docs
Closes the loop on issue #5693 (P1: asymmetric TLS / AsClient mode). The previous two commits added the runtime variable and the per- session decision; this commit wires the actual `preferred`-mode fallback path in the backend auth state machine and updates the operator-facing documentation to describe the full four-mode model. What changes: * MysqlxConnection::step_auth_capabilities_set_sent now treats a Mysqlx::Error response from CapabilitiesSet(tls=true) as a fall-back trigger when backend_tls_fallback_allowed_ is set (set by the session for mode=preferred). The connection silently downgrades on the same TCP socket — backend_tls_required_ is cleared so subsequent steps don't re-attempt TLS, tls_active_ stays false (which keeps the connection out of the encrypted half of the per-thread pool), and step_auth proceeds straight into AuthenticateStart on plaintext. Under mode=required (and AsClient + frontend-TLS), the same Error is still fatal — the operator's policy demands encryption. The pre-existing `Frame is not OK` rejection branch is preserved for malformed / unexpected response types. * doc/mysqlx/README.md §8 rewritten: * §8.1 frontend TLS modes (mysqlx_tls_mode, unchanged behaviour). * §8.2 backend TLS modes (mysqlx_tls_backend_mode, full table of the four documented values, migration notes from MySQL Router AsClient, and a connection-pool partitioning note explaining that the cache key now includes tls_active. * §8.3 configuration example showing the asymmetric pattern (frontend REQUIRED + backend preferred). The §3.1 variables table gains the new variable. * doc/mysqlx/MYSQL_ROUTER_PARITY.md updated: * Feature comparison row 4 (TLS modes) now lists 4-frontend x 4-backend with explicit mention of mysqlx_tls_backend_mode and issue #5693. * Asymmetric TLS row marked implemented. * Architecture section §TLS rewritten to describe both the frontend mysqlx_tls_mode and backend mysqlx_tls_backend_mode models; identifies passthrough as the remaining gap. * Feature gaps table marks "Asymmetric TLS / AsClient" and "Per-message response state machines" as implemented. * Summary updated. Tests: test/tap/tests/unit/mysqlx_backend_auth_unit-t (was 34): adds 7 new ok lines covering both branches of the fallback decision: * test_backend_auth_preferred_mode_fallback_to_plaintext: 5 assertions across the wire-level transition (state on entry, rc=1 on Error, AUTHENTICATE_START_SENT after fallback, backend_tls_required_ cleared, tls_active false, AuthStart frame on the wire). * test_backend_auth_required_mode_no_fallback_on_error: 2 assertions confirming the same Error is fatal when fallback_allowed=false. Total 42. All 8 (mode x frontend_tls) acceptance combinations from the issue are now covered: 6 by the decision-function tests in mysqlx_message_dispatch_unit-t (commit 2), and the remaining 2 mode=preferred + backend Error cases by the wire-level fallback tests added here. Tested under NOJEMALLOC=1 WITHASAN=1 PROXYSQLGENAI=1. Closes #5693. Stacks on #5706 / #5704. |
2 months ago |
|
|
167a896c16 |
feat(mysqlx): mode-driven backend TLS decision + tls_active conn-cache key
Implements the per-session decision side of issue #5693 (P1: asymmetric TLS / AsClient mode parity gap with MySQL Router 8.0). The previous commit added the runtime variable; this commit wires it through to the actual backend-connect path and partitions the connection pool by encryption posture so AsClient/required-TLS sessions never reuse plaintext-pooled backends (and vice versa). What changes: * Lifts the per-session decision out of an inline switch in MysqlxSession::handler_connecting_server() into a pure helper `mysqlx_resolve_backend_tls_decision(mode, endpoint_override, frontend_is_encrypted) -> {require_tls, fallback_allowed}`. The helper lives at file scope (not in the anonymous namespace) so the unit test can exercise the 8 (mode x frontend_tls) combinations called out in the issue acceptance criteria directly, without driving the full session state machine. The decision itself replaces the legacy `target_use_ssl_ || client_ds_.is_encrypted()` expression. * Adds two fields on MysqlxConnection: * tls_active_ -- set true by step_auth_tls_handshake() once the OpenSSL handshake completes successfully on the backend leg. Read by the connection cache to partition encrypted-pooled connections from plaintext-pooled ones. * backend_tls_fallback_allowed_ -- carries the `preferred` mode's "downgrade-to-plaintext-on-error" intent through to the auth state machine. Read-only metadata in this commit; the actual fallback path lands in the next commit. * Mysqlx_Thread::get_connection_from_cache now takes a `bool tls_active` parameter and matches on it. Without this, an AsClient TLS session pulling a pooled connection could land on a plaintext backend (or vice versa), corrupting the wire protocol when the next dispatched frame goes out over a socket in the wrong encryption posture. * Endpoint-override semantics (mysqlx_backend_endpoints.use_ssl=1) preserved exactly: it can promote plaintext to TLS regardless of mode, but cannot demote a TLS-required mode to plaintext. Under mode=preferred, the override leaves fallback_allowed=true so the operator's best-effort "preferred" intent isn't silently upgraded to "required". Tests: test/tap/tests/unit/mysqlx_message_dispatch_unit-t (was 86): adds 8 combinations (mode x frontend_tls) + 4 endpoint-override cases = 12 new ok lines, total 98. test/tap/tests/unit/mysqlx_thread_unit-t (was 22): adds test_connection_cache_tls_partition with 3 ok lines exercising the (plaintext, encrypted) hard partition, total 25. Known limitation (TODO addressed in next commit): mode=preferred currently fails the backend connect on Mysqlx::Error from CapabilitiesSet(tls=true) because the fallback-to-plaintext branch isn't wired in step_auth_capabilities_set_sent yet. The metadata (`backend_tls_fallback_allowed_` on the connection) is in place; only the state machine branch is missing. Two of the 8 documented test combinations (mode=preferred + Error from backend) are validated against the metadata only in this commit; the end-to-end fallback behaviour follows. Tested under NOJEMALLOC=1 WITHASAN=1 PROXYSQLGENAI=1. Refs #5693. Stacks on #5706 / #5704. |
2 months ago |