prestogres 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +20 -0
- data/LICENSE +202 -0
- data/NOTICE +22 -0
- data/README.md +217 -0
- data/Rakefile +13 -0
- data/VERSION +1 -0
- data/bin/prestogres +254 -0
- data/config/pcp.conf.sample +28 -0
- data/config/pgpool.conf +678 -0
- data/config/pool_hba.conf +84 -0
- data/config/pool_passwd +0 -0
- data/config/postgresql.conf +2 -0
- data/ext/.gitignore +6 -0
- data/ext/depend +26 -0
- data/ext/extconf.rb +4 -0
- data/ext/prestogres_config.c +12 -0
- data/pgpool2/.gitignore +36 -0
- data/pgpool2/AUTHORS +4 -0
- data/pgpool2/COPYING +12 -0
- data/pgpool2/ChangeLog +1 -0
- data/pgpool2/INSTALL +1 -0
- data/pgpool2/Makefile.am +159 -0
- data/pgpool2/Makefile.in +1187 -0
- data/pgpool2/NEWS +4960 -0
- data/pgpool2/README +1 -0
- data/pgpool2/README.euc_jp +1 -0
- data/pgpool2/README.online-recovery +62 -0
- data/pgpool2/TODO +103 -0
- data/pgpool2/ac_func_accept_argtypes.m4 +85 -0
- data/pgpool2/aclocal.m4 +1088 -0
- data/pgpool2/c-compiler.m4 +134 -0
- data/pgpool2/c-library.m4 +325 -0
- data/pgpool2/child.c +2097 -0
- data/pgpool2/config.guess +1532 -0
- data/pgpool2/config.h.in +332 -0
- data/pgpool2/config.sub +1640 -0
- data/pgpool2/configure +15752 -0
- data/pgpool2/configure.in +392 -0
- data/pgpool2/depcomp +522 -0
- data/pgpool2/doc/basebackup.sh +17 -0
- data/pgpool2/doc/pgpool-de.html +4220 -0
- data/pgpool2/doc/pgpool-en.html +5738 -0
- data/pgpool2/doc/pgpool-fr.html +4118 -0
- data/pgpool2/doc/pgpool-ja.css +198 -0
- data/pgpool2/doc/pgpool-ja.html +11279 -0
- data/pgpool2/doc/pgpool-zh_cn.html +4445 -0
- data/pgpool2/doc/pgpool.css +280 -0
- data/pgpool2/doc/pgpool_remote_start +13 -0
- data/pgpool2/doc/recovery.conf.sample +117 -0
- data/pgpool2/doc/tutorial-en.html +707 -0
- data/pgpool2/doc/tutorial-ja.html +422 -0
- data/pgpool2/doc/tutorial-memqcache-en.html +325 -0
- data/pgpool2/doc/tutorial-memqcache-ja.html +370 -0
- data/pgpool2/doc/tutorial-memqcache-zh_cn.html +322 -0
- data/pgpool2/doc/tutorial-watchdog-en.html +306 -0
- data/pgpool2/doc/tutorial-watchdog-ja.html +343 -0
- data/pgpool2/doc/tutorial-watchdog-zh_cn.html +301 -0
- data/pgpool2/doc/tutorial-zh_cn.html +537 -0
- data/pgpool2/doc/watchdog.png +0 -0
- data/pgpool2/doc/wd-en.html +236 -0
- data/pgpool2/doc/wd-en.jpg +0 -0
- data/pgpool2/doc/wd-ja.html +219 -0
- data/pgpool2/doc/wd-ja.jpg +0 -0
- data/pgpool2/doc/wd-zh_cn.html +201 -0
- data/pgpool2/doc/where_to_send_queries.odg +0 -0
- data/pgpool2/doc/where_to_send_queries.pdf +0 -0
- data/pgpool2/general.m4 +166 -0
- data/pgpool2/getopt_long.c +200 -0
- data/pgpool2/getopt_long.h +44 -0
- data/pgpool2/install-sh +251 -0
- data/pgpool2/ltmain.sh +8406 -0
- data/pgpool2/m4/libtool.m4 +7360 -0
- data/pgpool2/m4/ltoptions.m4 +368 -0
- data/pgpool2/m4/ltsugar.m4 +123 -0
- data/pgpool2/m4/ltversion.m4 +23 -0
- data/pgpool2/m4/lt~obsolete.m4 +92 -0
- data/pgpool2/main.c +2971 -0
- data/pgpool2/md5.c +444 -0
- data/pgpool2/md5.h +28 -0
- data/pgpool2/missing +360 -0
- data/pgpool2/mkinstalldirs +40 -0
- data/pgpool2/parser/Makefile.am +50 -0
- data/pgpool2/parser/Makefile.in +559 -0
- data/pgpool2/parser/copyfuncs.c +3310 -0
- data/pgpool2/parser/gram.c +39100 -0
- data/pgpool2/parser/gram.h +940 -0
- data/pgpool2/parser/gram.y +13408 -0
- data/pgpool2/parser/gramparse.h +74 -0
- data/pgpool2/parser/keywords.c +32 -0
- data/pgpool2/parser/keywords.h +39 -0
- data/pgpool2/parser/kwlist.h +425 -0
- data/pgpool2/parser/kwlookup.c +88 -0
- data/pgpool2/parser/list.c +1156 -0
- data/pgpool2/parser/makefuncs.c +518 -0
- data/pgpool2/parser/makefuncs.h +83 -0
- data/pgpool2/parser/memnodes.h +79 -0
- data/pgpool2/parser/nodes.c +29 -0
- data/pgpool2/parser/nodes.h +609 -0
- data/pgpool2/parser/outfuncs.c +5790 -0
- data/pgpool2/parser/parsenodes.h +2615 -0
- data/pgpool2/parser/parser.c +262 -0
- data/pgpool2/parser/parser.h +46 -0
- data/pgpool2/parser/pg_class.h +158 -0
- data/pgpool2/parser/pg_config_manual.h +273 -0
- data/pgpool2/parser/pg_list.h +352 -0
- data/pgpool2/parser/pg_trigger.h +147 -0
- data/pgpool2/parser/pg_wchar.h +492 -0
- data/pgpool2/parser/pool_memory.c +342 -0
- data/pgpool2/parser/pool_memory.h +77 -0
- data/pgpool2/parser/pool_parser.h +222 -0
- data/pgpool2/parser/pool_string.c +121 -0
- data/pgpool2/parser/pool_string.h +37 -0
- data/pgpool2/parser/primnodes.h +1280 -0
- data/pgpool2/parser/scan.c +4094 -0
- data/pgpool2/parser/scan.l +1451 -0
- data/pgpool2/parser/scanner.h +120 -0
- data/pgpool2/parser/scansup.c +221 -0
- data/pgpool2/parser/scansup.h +28 -0
- data/pgpool2/parser/snprintf.c +1102 -0
- data/pgpool2/parser/stringinfo.c +294 -0
- data/pgpool2/parser/stringinfo.h +178 -0
- data/pgpool2/parser/value.c +78 -0
- data/pgpool2/parser/value.h +62 -0
- data/pgpool2/parser/wchar.c +2048 -0
- data/pgpool2/pcp.conf.sample +28 -0
- data/pgpool2/pcp/Makefile.am +40 -0
- data/pgpool2/pcp/Makefile.in +771 -0
- data/pgpool2/pcp/libpcp_ext.h +250 -0
- data/pgpool2/pcp/md5.c +444 -0
- data/pgpool2/pcp/md5.h +28 -0
- data/pgpool2/pcp/pcp.c +1652 -0
- data/pgpool2/pcp/pcp.h +61 -0
- data/pgpool2/pcp/pcp_attach_node.c +172 -0
- data/pgpool2/pcp/pcp_detach_node.c +185 -0
- data/pgpool2/pcp/pcp_error.c +87 -0
- data/pgpool2/pcp/pcp_node_count.c +160 -0
- data/pgpool2/pcp/pcp_node_info.c +198 -0
- data/pgpool2/pcp/pcp_pool_status.c +166 -0
- data/pgpool2/pcp/pcp_proc_count.c +166 -0
- data/pgpool2/pcp/pcp_proc_info.c +261 -0
- data/pgpool2/pcp/pcp_promote_node.c +185 -0
- data/pgpool2/pcp/pcp_recovery_node.c +172 -0
- data/pgpool2/pcp/pcp_stop_pgpool.c +179 -0
- data/pgpool2/pcp/pcp_stream.c +385 -0
- data/pgpool2/pcp/pcp_stream.h +52 -0
- data/pgpool2/pcp/pcp_systemdb_info.c +194 -0
- data/pgpool2/pcp/pcp_watchdog_info.c +211 -0
- data/pgpool2/pcp_child.c +1493 -0
- data/pgpool2/pg_md5.c +305 -0
- data/pgpool2/pgpool.8.in +121 -0
- data/pgpool2/pgpool.conf +553 -0
- data/pgpool2/pgpool.conf.sample +666 -0
- data/pgpool2/pgpool.conf.sample-master-slave +665 -0
- data/pgpool2/pgpool.conf.sample-replication +664 -0
- data/pgpool2/pgpool.conf.sample-stream +664 -0
- data/pgpool2/pgpool.spec +264 -0
- data/pgpool2/pgpool_adm/TODO +7 -0
- data/pgpool2/pgpool_adm/pgpool_adm--1.0.sql +85 -0
- data/pgpool2/pgpool_adm/pgpool_adm.c +558 -0
- data/pgpool2/pgpool_adm/pgpool_adm.control +5 -0
- data/pgpool2/pgpool_adm/pgpool_adm.h +46 -0
- data/pgpool2/pgpool_adm/pgpool_adm.sql.in +85 -0
- data/pgpool2/pool.h +655 -0
- data/pgpool2/pool_auth.c +1390 -0
- data/pgpool2/pool_config.c +5007 -0
- data/pgpool2/pool_config.h +284 -0
- data/pgpool2/pool_config.l +3281 -0
- data/pgpool2/pool_config_md5.c +29 -0
- data/pgpool2/pool_connection_pool.c +812 -0
- data/pgpool2/pool_error.c +242 -0
- data/pgpool2/pool_globals.c +27 -0
- data/pgpool2/pool_hba.c +1723 -0
- data/pgpool2/pool_hba.conf.sample +67 -0
- data/pgpool2/pool_ip.c +567 -0
- data/pgpool2/pool_ip.h +65 -0
- data/pgpool2/pool_ipc.h +38 -0
- data/pgpool2/pool_lobj.c +242 -0
- data/pgpool2/pool_lobj.h +32 -0
- data/pgpool2/pool_memqcache.c +3818 -0
- data/pgpool2/pool_memqcache.h +268 -0
- data/pgpool2/pool_params.c +163 -0
- data/pgpool2/pool_passwd.c +249 -0
- data/pgpool2/pool_passwd.h +41 -0
- data/pgpool2/pool_path.c +193 -0
- data/pgpool2/pool_path.h +81 -0
- data/pgpool2/pool_process_context.c +247 -0
- data/pgpool2/pool_process_context.h +62 -0
- data/pgpool2/pool_process_query.c +5001 -0
- data/pgpool2/pool_process_reporting.c +1671 -0
- data/pgpool2/pool_process_reporting.h +44 -0
- data/pgpool2/pool_proto2.c +671 -0
- data/pgpool2/pool_proto_modules.c +3524 -0
- data/pgpool2/pool_proto_modules.h +185 -0
- data/pgpool2/pool_query_cache.c +1020 -0
- data/pgpool2/pool_query_context.c +1871 -0
- data/pgpool2/pool_query_context.h +105 -0
- data/pgpool2/pool_relcache.c +284 -0
- data/pgpool2/pool_relcache.h +78 -0
- data/pgpool2/pool_rewrite_outfuncs.c +9060 -0
- data/pgpool2/pool_rewrite_query.c +715 -0
- data/pgpool2/pool_rewrite_query.h +192 -0
- data/pgpool2/pool_select_walker.c +1150 -0
- data/pgpool2/pool_select_walker.h +68 -0
- data/pgpool2/pool_sema.c +161 -0
- data/pgpool2/pool_session_context.c +952 -0
- data/pgpool2/pool_session_context.h +203 -0
- data/pgpool2/pool_shmem.c +185 -0
- data/pgpool2/pool_signal.c +158 -0
- data/pgpool2/pool_signal.h +61 -0
- data/pgpool2/pool_ssl.c +339 -0
- data/pgpool2/pool_stream.c +962 -0
- data/pgpool2/pool_stream.h +61 -0
- data/pgpool2/pool_system.c +659 -0
- data/pgpool2/pool_timestamp.c +1215 -0
- data/pgpool2/pool_timestamp.h +38 -0
- data/pgpool2/pool_type.h +171 -0
- data/pgpool2/pool_worker_child.c +384 -0
- data/pgpool2/ps_status.c +404 -0
- data/pgpool2/recovery.c +435 -0
- data/pgpool2/redhat/pgpool.conf.sample.patch +52 -0
- data/pgpool2/redhat/pgpool.init +201 -0
- data/pgpool2/redhat/pgpool.sysconfig +7 -0
- data/pgpool2/redhat/rpm_installer/basebackup-replication.sh +53 -0
- data/pgpool2/redhat/rpm_installer/basebackup-stream.sh +55 -0
- data/pgpool2/redhat/rpm_installer/config_for_script +17 -0
- data/pgpool2/redhat/rpm_installer/failover.sh +64 -0
- data/pgpool2/redhat/rpm_installer/getsources.sh +141 -0
- data/pgpool2/redhat/rpm_installer/install.sh +1363 -0
- data/pgpool2/redhat/rpm_installer/pgpool_recovery_pitr +47 -0
- data/pgpool2/redhat/rpm_installer/pgpool_remote_start +15 -0
- data/pgpool2/redhat/rpm_installer/recovery.conf +4 -0
- data/pgpool2/redhat/rpm_installer/uninstall.sh +57 -0
- data/pgpool2/sample/dist_def_pgbench.sql +73 -0
- data/pgpool2/sample/pgpool.pam +3 -0
- data/pgpool2/sample/pgpool_recovery +20 -0
- data/pgpool2/sample/pgpool_recovery_pitr +19 -0
- data/pgpool2/sample/pgpool_remote_start +13 -0
- data/pgpool2/sample/replicate_def_pgbench.sql +18 -0
- data/pgpool2/sql/insert_lock.sql +15 -0
- data/pgpool2/sql/pgpool-recovery/pgpool-recovery.c +280 -0
- data/pgpool2/sql/pgpool-recovery/pgpool-recovery.sql.in +19 -0
- data/pgpool2/sql/pgpool-recovery/pgpool_recovery--1.0.sql +24 -0
- data/pgpool2/sql/pgpool-recovery/pgpool_recovery.control +5 -0
- data/pgpool2/sql/pgpool-recovery/uninstall_pgpool-recovery.sql +3 -0
- data/pgpool2/sql/pgpool-regclass/pgpool-regclass.c +206 -0
- data/pgpool2/sql/pgpool-regclass/pgpool-regclass.sql.in +4 -0
- data/pgpool2/sql/pgpool-regclass/pgpool_regclass--1.0.sql +7 -0
- data/pgpool2/sql/pgpool-regclass/pgpool_regclass.control +5 -0
- data/pgpool2/sql/pgpool-regclass/uninstall_pgpool-regclass.sql +1 -0
- data/pgpool2/sql/system_db.sql +38 -0
- data/pgpool2/strlcpy.c +85 -0
- data/pgpool2/test/C/test_extended.c +98 -0
- data/pgpool2/test/jdbc/.cvsignore +2 -0
- data/pgpool2/test/jdbc/AutoCommitTest.java +45 -0
- data/pgpool2/test/jdbc/BatchTest.java +55 -0
- data/pgpool2/test/jdbc/ColumnTest.java +60 -0
- data/pgpool2/test/jdbc/CreateTempTableTest.java +48 -0
- data/pgpool2/test/jdbc/InsertTest.java +34 -0
- data/pgpool2/test/jdbc/LockTest.java +36 -0
- data/pgpool2/test/jdbc/PgpoolTest.java +75 -0
- data/pgpool2/test/jdbc/README.euc_jp +73 -0
- data/pgpool2/test/jdbc/RunTest.java +83 -0
- data/pgpool2/test/jdbc/SelectTest.java +37 -0
- data/pgpool2/test/jdbc/UpdateTest.java +32 -0
- data/pgpool2/test/jdbc/expected/CreateTempTable +1 -0
- data/pgpool2/test/jdbc/expected/autocommit +10 -0
- data/pgpool2/test/jdbc/expected/batch +1 -0
- data/pgpool2/test/jdbc/expected/column +100 -0
- data/pgpool2/test/jdbc/expected/insert +1 -0
- data/pgpool2/test/jdbc/expected/lock +100 -0
- data/pgpool2/test/jdbc/expected/select +2 -0
- data/pgpool2/test/jdbc/expected/update +1 -0
- data/pgpool2/test/jdbc/pgpool.properties +7 -0
- data/pgpool2/test/jdbc/prepare.sql +54 -0
- data/pgpool2/test/jdbc/run.sh +6 -0
- data/pgpool2/test/parser/.cvsignore +6 -0
- data/pgpool2/test/parser/README +32 -0
- data/pgpool2/test/parser/expected/copy.out +17 -0
- data/pgpool2/test/parser/expected/create.out +64 -0
- data/pgpool2/test/parser/expected/cursor.out +37 -0
- data/pgpool2/test/parser/expected/delete.out +10 -0
- data/pgpool2/test/parser/expected/drop.out +12 -0
- data/pgpool2/test/parser/expected/insert.out +13 -0
- data/pgpool2/test/parser/expected/misc.out +28 -0
- data/pgpool2/test/parser/expected/prepare.out +4 -0
- data/pgpool2/test/parser/expected/privileges.out +31 -0
- data/pgpool2/test/parser/expected/scanner.out +30 -0
- data/pgpool2/test/parser/expected/select.out +89 -0
- data/pgpool2/test/parser/expected/transaction.out +38 -0
- data/pgpool2/test/parser/expected/update.out +11 -0
- data/pgpool2/test/parser/expected/v84.out +37 -0
- data/pgpool2/test/parser/expected/v90.out +25 -0
- data/pgpool2/test/parser/expected/var.out +22 -0
- data/pgpool2/test/parser/input/alter.sql +2 -0
- data/pgpool2/test/parser/input/copy.sql +17 -0
- data/pgpool2/test/parser/input/create.sql +64 -0
- data/pgpool2/test/parser/input/cursor.sql +37 -0
- data/pgpool2/test/parser/input/delete.sql +10 -0
- data/pgpool2/test/parser/input/drop.sql +12 -0
- data/pgpool2/test/parser/input/insert.sql +13 -0
- data/pgpool2/test/parser/input/misc.sql +28 -0
- data/pgpool2/test/parser/input/prepare.sql +4 -0
- data/pgpool2/test/parser/input/privileges.sql +31 -0
- data/pgpool2/test/parser/input/scanner.sql +34 -0
- data/pgpool2/test/parser/input/select.sql +89 -0
- data/pgpool2/test/parser/input/transaction.sql +38 -0
- data/pgpool2/test/parser/input/update.sql +11 -0
- data/pgpool2/test/parser/input/v84.sql +37 -0
- data/pgpool2/test/parser/input/v90.sql +38 -0
- data/pgpool2/test/parser/input/var.sql +22 -0
- data/pgpool2/test/parser/main.c +96 -0
- data/pgpool2/test/parser/parse_schedule +16 -0
- data/pgpool2/test/parser/pool.h +13 -0
- data/pgpool2/test/parser/run-test +62 -0
- data/pgpool2/test/pdo-test/README.euc_jp +58 -0
- data/pgpool2/test/pdo-test/SQLlist/test1.sql +3 -0
- data/pgpool2/test/pdo-test/SQLlist/test2.sql +3 -0
- data/pgpool2/test/pdo-test/collections.inc +11 -0
- data/pgpool2/test/pdo-test/def.inc +7 -0
- data/pgpool2/test/pdo-test/log.txt +0 -0
- data/pgpool2/test/pdo-test/mod/database.inc +36 -0
- data/pgpool2/test/pdo-test/mod/def.inc +0 -0
- data/pgpool2/test/pdo-test/mod/errorhandler.inc +27 -0
- data/pgpool2/test/pdo-test/pdotest.php +11 -0
- data/pgpool2/test/pdo-test/regsql.inc +56 -0
- data/pgpool2/test/pgpool_setup +898 -0
- data/pgpool2/test/regression/README +39 -0
- data/pgpool2/test/regression/clean.sh +21 -0
- data/pgpool2/test/regression/libs.sh +16 -0
- data/pgpool2/test/regression/regress.sh +166 -0
- data/pgpool2/test/regression/tests/001.load_balance/test.sh +128 -0
- data/pgpool2/test/regression/tests/002.native_replication/PgTester.java +47 -0
- data/pgpool2/test/regression/tests/002.native_replication/create.sql +6 -0
- data/pgpool2/test/regression/tests/002.native_replication/test.sh +71 -0
- data/pgpool2/test/regression/tests/003.failover/expected.r +6 -0
- data/pgpool2/test/regression/tests/003.failover/expected.s +6 -0
- data/pgpool2/test/regression/tests/003.failover/test.sh +45 -0
- data/pgpool2/test/regression/tests/004.watchdog/master.conf +12 -0
- data/pgpool2/test/regression/tests/004.watchdog/standby.conf +19 -0
- data/pgpool2/test/regression/tests/004.watchdog/test.sh +52 -0
- data/pgpool2/test/regression/tests/050.bug58/test.sh +50 -0
- data/pgpool2/test/regression/tests/051.bug60/bug.sql +12 -0
- data/pgpool2/test/regression/tests/051.bug60/database-clean.sql +6 -0
- data/pgpool2/test/regression/tests/051.bug60/database-setup.sql +28 -0
- data/pgpool2/test/regression/tests/051.bug60/test.sh +79 -0
- data/pgpool2/test/regression/tests/052.do_query/test.sh +44 -0
- data/pgpool2/test/regression/tests/053.insert_lock_hangs/test.sh +81 -0
- data/pgpool2/test/regression/tests/054.postgres_fdw/test.sh +67 -0
- data/pgpool2/test/regression/tests/055.backend_all_down/test.sh +52 -0
- data/pgpool2/test/regression/tests/056.bug63/jdbctest2.java +66 -0
- data/pgpool2/test/regression/tests/056.bug63/test.sh +47 -0
- data/pgpool2/test/regression/tests/057.bug61/test.sh +40 -0
- data/pgpool2/test/regression/tests/058.bug68/jdbctest3.java +45 -0
- data/pgpool2/test/regression/tests/058.bug68/test.sh +47 -0
- data/pgpool2/test/timestamp/expected/insert.out +16 -0
- data/pgpool2/test/timestamp/expected/misc.out +3 -0
- data/pgpool2/test/timestamp/expected/update.out +6 -0
- data/pgpool2/test/timestamp/input/insert.sql +16 -0
- data/pgpool2/test/timestamp/input/misc.sql +3 -0
- data/pgpool2/test/timestamp/input/update.sql +6 -0
- data/pgpool2/test/timestamp/main.c +129 -0
- data/pgpool2/test/timestamp/parse_schedule +3 -0
- data/pgpool2/test/timestamp/run-test +69 -0
- data/pgpool2/version.h +1 -0
- data/pgpool2/watchdog/Makefile.am +17 -0
- data/pgpool2/watchdog/Makefile.in +505 -0
- data/pgpool2/watchdog/test/stab.c +266 -0
- data/pgpool2/watchdog/test/test.c +85 -0
- data/pgpool2/watchdog/test/wd_child_t.c +87 -0
- data/pgpool2/watchdog/test/wd_lifecheck_t.c +87 -0
- data/pgpool2/watchdog/test/wd_packet_t.c +87 -0
- data/pgpool2/watchdog/test/wd_ping_t.c +20 -0
- data/pgpool2/watchdog/watchdog.c +408 -0
- data/pgpool2/watchdog/watchdog.h +209 -0
- data/pgpool2/watchdog/wd_child.c +444 -0
- data/pgpool2/watchdog/wd_ext.h +123 -0
- data/pgpool2/watchdog/wd_heartbeat.c +577 -0
- data/pgpool2/watchdog/wd_if.c +216 -0
- data/pgpool2/watchdog/wd_init.c +126 -0
- data/pgpool2/watchdog/wd_interlock.c +347 -0
- data/pgpool2/watchdog/wd_lifecheck.c +512 -0
- data/pgpool2/watchdog/wd_list.c +429 -0
- data/pgpool2/watchdog/wd_packet.c +1159 -0
- data/pgpool2/watchdog/wd_ping.c +330 -0
- data/pgpool2/ylwrap +223 -0
- data/pgsql/presto_client.py +346 -0
- data/pgsql/prestogres.py +156 -0
- data/pgsql/setup_functions.sql +21 -0
- data/pgsql/setup_language.sql +3 -0
- data/prestogres.gemspec +23 -0
- metadata +496 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/* -*-pgsql-c-*- */
|
|
2
|
+
/*
|
|
3
|
+
* $Header$
|
|
4
|
+
*
|
|
5
|
+
* pgpool: a language independent connection pool server for PostgreSQL
|
|
6
|
+
* written by Tatsuo Ishii
|
|
7
|
+
*
|
|
8
|
+
* Copyright (c) 2003-2012 PgPool Global Development Group
|
|
9
|
+
*
|
|
10
|
+
* Permission to use, copy, modify, and distribute this software and
|
|
11
|
+
* its documentation for any purpose and without fee is hereby
|
|
12
|
+
* granted, provided that the above copyright notice appear in all
|
|
13
|
+
* copies and that both that copyright notice and this permission
|
|
14
|
+
* notice appear in supporting documentation, and that the name of the
|
|
15
|
+
* author not be used in advertising or publicity pertaining to
|
|
16
|
+
* distribution of the software without specific, written prior
|
|
17
|
+
* permission. The author makes no representations about the
|
|
18
|
+
* suitability of this software for any purpose. It is provided "as
|
|
19
|
+
* is" without express or implied warranty.
|
|
20
|
+
*
|
|
21
|
+
* pool_error.c: error and debug messages
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
#include <stdio.h>
|
|
26
|
+
#include <stdarg.h>
|
|
27
|
+
#include <sys/types.h>
|
|
28
|
+
#include <unistd.h>
|
|
29
|
+
#include <stdlib.h>
|
|
30
|
+
|
|
31
|
+
#include "pool.h"
|
|
32
|
+
#include "pool_config.h"
|
|
33
|
+
|
|
34
|
+
#define MAXSTRFTIME 128
|
|
35
|
+
|
|
36
|
+
extern int debug;
|
|
37
|
+
|
|
38
|
+
static char *nowsec(void);
|
|
39
|
+
|
|
40
|
+
void pool_error(const char *fmt,...)
|
|
41
|
+
{
|
|
42
|
+
va_list ap;
|
|
43
|
+
#ifdef HAVE_ASPRINTF
|
|
44
|
+
char *fmt2;
|
|
45
|
+
int len;
|
|
46
|
+
#endif
|
|
47
|
+
|
|
48
|
+
#ifdef HAVE_SIGPROCMASK
|
|
49
|
+
sigset_t oldmask;
|
|
50
|
+
#else
|
|
51
|
+
int oldmask;
|
|
52
|
+
#endif
|
|
53
|
+
POOL_SETMASK2(&BlockSig, &oldmask);
|
|
54
|
+
|
|
55
|
+
/* Write error message to syslog */
|
|
56
|
+
if (pool_config->logsyslog == 1) {
|
|
57
|
+
va_start(ap, fmt);
|
|
58
|
+
vsyslog(pool_config->syslog_facility | LOG_ERR, fmt, ap);
|
|
59
|
+
va_end(ap);
|
|
60
|
+
POOL_SETMASK(&oldmask);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (pool_config->print_timestamp)
|
|
65
|
+
#ifdef HAVE_ASPRINTF
|
|
66
|
+
len = asprintf(&fmt2, "%s ERROR: pid %d: %s\n", nowsec(), (int)getpid(), fmt);
|
|
67
|
+
else
|
|
68
|
+
len = asprintf(&fmt2, "ERROR: pid %d: %s\n", (int)getpid(), fmt);
|
|
69
|
+
|
|
70
|
+
if (len >= 0 && fmt2)
|
|
71
|
+
{
|
|
72
|
+
va_start(ap, fmt);
|
|
73
|
+
vfprintf(stderr, fmt2, ap);
|
|
74
|
+
va_end(ap);
|
|
75
|
+
fflush(stderr);
|
|
76
|
+
free(fmt2);
|
|
77
|
+
}
|
|
78
|
+
#else
|
|
79
|
+
fprintf(stderr, "%s ERROR: pid %d: ", nowsec(), (int)getpid());
|
|
80
|
+
else
|
|
81
|
+
fprintf(stderr, "ERROR: pid %d: ", (int)getpid());
|
|
82
|
+
|
|
83
|
+
va_start(ap, fmt);
|
|
84
|
+
vfprintf(stderr, fmt, ap);
|
|
85
|
+
va_end(ap);
|
|
86
|
+
fprintf(stderr, "\n");
|
|
87
|
+
#endif
|
|
88
|
+
|
|
89
|
+
POOL_SETMASK(&oldmask);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
void pool_debug(const char *fmt,...)
|
|
93
|
+
{
|
|
94
|
+
va_list ap;
|
|
95
|
+
#ifdef HAVE_ASPRINTF
|
|
96
|
+
char *fmt2;
|
|
97
|
+
int len;
|
|
98
|
+
#endif
|
|
99
|
+
|
|
100
|
+
#ifdef HAVE_SIGPROCMASK
|
|
101
|
+
sigset_t oldmask;
|
|
102
|
+
#else
|
|
103
|
+
int oldmask;
|
|
104
|
+
#endif
|
|
105
|
+
|
|
106
|
+
if (run_as_pcp_child)
|
|
107
|
+
{
|
|
108
|
+
if (!debug)
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
else
|
|
112
|
+
{
|
|
113
|
+
if (pool_config->debug_level <= 0)
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
POOL_SETMASK2(&BlockSig, &oldmask);
|
|
118
|
+
|
|
119
|
+
/* Write debug message to syslog */
|
|
120
|
+
if (pool_config->logsyslog == 1) {
|
|
121
|
+
va_start(ap, fmt);
|
|
122
|
+
vsyslog(pool_config->syslog_facility | LOG_DEBUG, fmt, ap);
|
|
123
|
+
va_end(ap);
|
|
124
|
+
POOL_SETMASK(&oldmask);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (pool_config->print_timestamp)
|
|
129
|
+
#ifdef HAVE_ASPRINTF
|
|
130
|
+
len = asprintf(&fmt2, "%s DEBUG: pid %d: %s\n", nowsec(), (int)getpid(), fmt);
|
|
131
|
+
else
|
|
132
|
+
len = asprintf(&fmt2, "DEBUG: pid %d: %s\n", (int)getpid(), fmt);
|
|
133
|
+
|
|
134
|
+
if (len >= 0 && fmt2)
|
|
135
|
+
{
|
|
136
|
+
va_start(ap, fmt);
|
|
137
|
+
vfprintf(stderr, fmt2, ap);
|
|
138
|
+
va_end(ap);
|
|
139
|
+
fflush(stderr);
|
|
140
|
+
free(fmt2);
|
|
141
|
+
}
|
|
142
|
+
#else
|
|
143
|
+
fprintf(stderr, "%s DEBUG: pid %d: ", nowsec(), (int)getpid());
|
|
144
|
+
else
|
|
145
|
+
fprintf(stderr, "DEBUG: pid %d: ", (int)getpid());
|
|
146
|
+
|
|
147
|
+
va_start(ap, fmt);
|
|
148
|
+
vfprintf(stderr, fmt, ap);
|
|
149
|
+
va_end(ap);
|
|
150
|
+
fprintf(stderr, "\n");
|
|
151
|
+
#endif
|
|
152
|
+
|
|
153
|
+
POOL_SETMASK(&oldmask);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
void pool_log(const char *fmt,...)
|
|
157
|
+
{
|
|
158
|
+
va_list ap;
|
|
159
|
+
#ifdef HAVE_ASPRINTF
|
|
160
|
+
char *fmt2;
|
|
161
|
+
int len;
|
|
162
|
+
#endif
|
|
163
|
+
|
|
164
|
+
#ifdef HAVE_SIGPROCMASK
|
|
165
|
+
sigset_t oldmask;
|
|
166
|
+
#else
|
|
167
|
+
int oldmask;
|
|
168
|
+
#endif
|
|
169
|
+
|
|
170
|
+
POOL_SETMASK2(&BlockSig, &oldmask);
|
|
171
|
+
|
|
172
|
+
/* Write log message to syslog */
|
|
173
|
+
if (pool_config->logsyslog == 1) {
|
|
174
|
+
va_start(ap, fmt);
|
|
175
|
+
vsyslog(pool_config->syslog_facility | LOG_NOTICE, fmt, ap);
|
|
176
|
+
va_end(ap);
|
|
177
|
+
POOL_SETMASK(&oldmask);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (pool_config->print_timestamp)
|
|
182
|
+
#ifdef HAVE_ASPRINTF
|
|
183
|
+
len = asprintf(&fmt2, "%s LOG: pid %d: %s\n", nowsec(), (int)getpid(), fmt);
|
|
184
|
+
else
|
|
185
|
+
len = asprintf(&fmt2, "LOG: pid %d: %s\n", (int)getpid(), fmt);
|
|
186
|
+
|
|
187
|
+
if (len >= 0 && fmt2)
|
|
188
|
+
{
|
|
189
|
+
va_start(ap, fmt);
|
|
190
|
+
vfprintf(stderr, fmt2, ap);
|
|
191
|
+
va_end(ap);
|
|
192
|
+
fflush(stderr);
|
|
193
|
+
free(fmt2);
|
|
194
|
+
}
|
|
195
|
+
#else
|
|
196
|
+
fprintf(stderr, "%s LOG: pid %d: ", nowsec(), (int)getpid());
|
|
197
|
+
else
|
|
198
|
+
fprintf(stderr, "LOG: pid %d: ", (int)getpid());
|
|
199
|
+
|
|
200
|
+
va_start(ap, fmt);
|
|
201
|
+
vfprintf(stderr, fmt, ap);
|
|
202
|
+
va_end(ap);
|
|
203
|
+
fprintf(stderr, "\n");
|
|
204
|
+
#endif
|
|
205
|
+
|
|
206
|
+
POOL_SETMASK(&oldmask);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
static char *nowsec(void)
|
|
210
|
+
{
|
|
211
|
+
static char strbuf[MAXSTRFTIME];
|
|
212
|
+
time_t now = time(NULL);
|
|
213
|
+
|
|
214
|
+
strftime(strbuf, MAXSTRFTIME, "%Y-%m-%d %H:%M:%S", localtime(&now));
|
|
215
|
+
return strbuf;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
#ifndef HAVE_VSYSLOG
|
|
219
|
+
void vsyslog (int priority, const char *format, va_list ap)
|
|
220
|
+
{
|
|
221
|
+
#define MAXSYSLOGMSGLEN 1024
|
|
222
|
+
|
|
223
|
+
char *msg = NULL;
|
|
224
|
+
|
|
225
|
+
#ifdef HAVE_VASPRINTF
|
|
226
|
+
vasprintf(&msg, format, ap);
|
|
227
|
+
if (!msg)
|
|
228
|
+
return;
|
|
229
|
+
#else
|
|
230
|
+
msg = malloc(MAXSYSLOGMSGLEN);
|
|
231
|
+
if (!msg)
|
|
232
|
+
return;
|
|
233
|
+
|
|
234
|
+
va_start(ap, format);
|
|
235
|
+
vsnprintf(msg, MAXSYSLOGMSGLEN, format, ap);
|
|
236
|
+
va_end(ap);
|
|
237
|
+
#endif
|
|
238
|
+
|
|
239
|
+
syslog(priority, "%s", msg);
|
|
240
|
+
free(msg);
|
|
241
|
+
}
|
|
242
|
+
#endif /* HAVE_VSYSLOG */
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* -*-pgsql-c-*- */
|
|
2
|
+
/*
|
|
3
|
+
* $Header$
|
|
4
|
+
*
|
|
5
|
+
* pgpool: a language independent connection pool server for PostgreSQL
|
|
6
|
+
* written by Tatsuo Ishii
|
|
7
|
+
*
|
|
8
|
+
* Copyright (c) 2003-2010 PgPool Global Development Group
|
|
9
|
+
*
|
|
10
|
+
* Permission to use, copy, modify, and distribute this software and
|
|
11
|
+
* its documentation for any purpose and without fee is hereby
|
|
12
|
+
* granted, provided that the above copyright notice appear in all
|
|
13
|
+
* copies and that both that copyright notice and this permission
|
|
14
|
+
* notice appear in supporting documentation, and that the name of the
|
|
15
|
+
* author not be used in advertising or publicity pertaining to
|
|
16
|
+
* distribution of the software without specific, written prior
|
|
17
|
+
* permission. The author makes no representations about the
|
|
18
|
+
* suitability of this software for any purpose. It is provided "as
|
|
19
|
+
* is" without express or implied warranty.
|
|
20
|
+
*
|
|
21
|
+
* Global variables. Should be eventually removed.
|
|
22
|
+
*/
|
|
23
|
+
#include "pool.h"
|
|
24
|
+
|
|
25
|
+
int debug = 0; /* non 0 if debug option is given (-d). pcp only */
|
|
26
|
+
pid_t mypid; /* pgpool parent process id */
|
|
27
|
+
bool run_as_pcp_child;
|
data/pgpool2/pool_hba.c
ADDED
|
@@ -0,0 +1,1723 @@
|
|
|
1
|
+
/* -*-pgsql-c-*- */
|
|
2
|
+
/*
|
|
3
|
+
*
|
|
4
|
+
* $Header$
|
|
5
|
+
*
|
|
6
|
+
* pgpool: a language independent connection pool server for PostgreSQL
|
|
7
|
+
* written by Tatsuo Ishii
|
|
8
|
+
*
|
|
9
|
+
* Portions Copyright (c) 2003-2012 PgPool Global Development Group
|
|
10
|
+
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
|
11
|
+
* Portions Copyright (c) 1994, Regents of the University of California *
|
|
12
|
+
* Permission to use, copy, modify, and distribute this software and
|
|
13
|
+
* its documentation for any purpose and without fee is hereby
|
|
14
|
+
* granted, provided that the above copyright notice appear in all
|
|
15
|
+
* copies and that both that copyright notice and this permission
|
|
16
|
+
* notice appear in supporting documentation, and that the name of the
|
|
17
|
+
* author not be used in advertising or publicity pertaining to
|
|
18
|
+
* distribution of the software without specific, written prior
|
|
19
|
+
* permission. The author makes no representations about the
|
|
20
|
+
* suitability of this software for any purpose. It is provided "as
|
|
21
|
+
* is" without express or implied warranty.
|
|
22
|
+
*
|
|
23
|
+
* pool_hba.c.: Routines to handle host based authentication.
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
#include <stdio.h>
|
|
28
|
+
#include <stdlib.h>
|
|
29
|
+
#include <string.h>
|
|
30
|
+
#include <errno.h>
|
|
31
|
+
#include <netdb.h>
|
|
32
|
+
|
|
33
|
+
#include <unistd.h>
|
|
34
|
+
#include <netinet/in.h>
|
|
35
|
+
#include <arpa/inet.h>
|
|
36
|
+
|
|
37
|
+
#include "pool.h"
|
|
38
|
+
#include "pool_path.h"
|
|
39
|
+
#include "pool_ip.h"
|
|
40
|
+
#include "pool_stream.h"
|
|
41
|
+
#include "pool_config.h"
|
|
42
|
+
#include "parser/pool_memory.h"
|
|
43
|
+
#include "parser/pg_list.h"
|
|
44
|
+
#include "pool_passwd.h"
|
|
45
|
+
|
|
46
|
+
#define MULTI_VALUE_SEP "\001" /* delimiter for multi-valued column strings */
|
|
47
|
+
#define MAX_TOKEN 256
|
|
48
|
+
|
|
49
|
+
static List *hba_lines = NIL;
|
|
50
|
+
static List *hba_line_nums = NIL;
|
|
51
|
+
static char *hbaFileName;
|
|
52
|
+
|
|
53
|
+
static POOL_MEMORY_POOL *hba_memory_context = NULL;
|
|
54
|
+
|
|
55
|
+
static void sendAuthRequest(POOL_CONNECTION *frontend, AuthRequest areq);
|
|
56
|
+
static void auth_failed(POOL_CONNECTION *frontend);
|
|
57
|
+
static void close_all_backend_connections(void);
|
|
58
|
+
static bool hba_getauthmethod(POOL_CONNECTION *frontend);
|
|
59
|
+
static bool check_hba(POOL_CONNECTION *frontend);
|
|
60
|
+
static void parse_hba(List *line, int line_num, POOL_CONNECTION *frontend, bool *found_p, bool *error_p);
|
|
61
|
+
static void parse_hba_auth(ListCell **line_item, UserAuth *userauth_p, char **auth_arg_p, bool *error_p);
|
|
62
|
+
static bool check_user(char *user, char *param_str);
|
|
63
|
+
static bool check_db(char *dbname, char *user, char *param_str);
|
|
64
|
+
static void free_lines(List **lines, List **line_nums);
|
|
65
|
+
static void tokenize_file(const char *filename, FILE *file, List **lines, List **line_nums);
|
|
66
|
+
static char *tokenize_inc_file(const char *outer_filename, const char *inc_filename);
|
|
67
|
+
static bool pg_isblank(const char c);
|
|
68
|
+
static void next_token(FILE *fp, char *buf, int bufsz);
|
|
69
|
+
static char * next_token_expand(const char *filename, FILE *file);
|
|
70
|
+
static POOL_STATUS CheckMd5Auth(char *username);
|
|
71
|
+
|
|
72
|
+
const char* presto_server = NULL;
|
|
73
|
+
const char* presto_user = NULL;
|
|
74
|
+
const char* presto_catalog = NULL;
|
|
75
|
+
const char* presto_schema = NULL;
|
|
76
|
+
const char* presto_external_auth_prog = NULL;
|
|
77
|
+
|
|
78
|
+
static bool prestogres_hba_set_session_info(const char* key, const char* value);
|
|
79
|
+
static void prestogres_hba_parse_arg(const char* arg);
|
|
80
|
+
static POOL_STATUS pool_prestogres_hba_auth_md5(POOL_CONNECTION *frontend);
|
|
81
|
+
static POOL_STATUS pool_prestogres_hba_auth_external(POOL_CONNECTION *frontend);
|
|
82
|
+
|
|
83
|
+
static char *recv_password_packet(POOL_CONNECTION *frontend);
|
|
84
|
+
|
|
85
|
+
#ifdef USE_PAM
|
|
86
|
+
#ifdef HAVE_PAM_PAM_APPL_H
|
|
87
|
+
#include <pam/pam_appl.h>
|
|
88
|
+
#endif
|
|
89
|
+
#ifdef HAVE_SECURITY_PAM_APPL_H
|
|
90
|
+
#include <security/pam_appl.h>
|
|
91
|
+
#endif
|
|
92
|
+
|
|
93
|
+
#define PGPOOL_PAM_SERVICE "pgpool" /* Service name passed to PAM */
|
|
94
|
+
|
|
95
|
+
static POOL_STATUS CheckPAMAuth(POOL_CONNECTION *frontend, char *user, char *password);
|
|
96
|
+
static int pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg, struct pam_response ** resp, void *appdata_ptr);
|
|
97
|
+
|
|
98
|
+
static struct pam_conv pam_passw_conv = {
|
|
99
|
+
&pam_passwd_conv_proc,
|
|
100
|
+
NULL
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
static char *pam_passwd = NULL; /* Workaround for Solaris 2.6 brokenness */
|
|
104
|
+
static POOL_CONNECTION *pam_frontend_kludge; /* Workaround for passing
|
|
105
|
+
* POOL_CONNECTION *frontend
|
|
106
|
+
* into pam_passwd_conv_proc */
|
|
107
|
+
#endif /* USE_PAM */
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
/*
|
|
111
|
+
* read in hba config file
|
|
112
|
+
*/
|
|
113
|
+
int load_hba(char *hbapath)
|
|
114
|
+
{
|
|
115
|
+
FILE *file;
|
|
116
|
+
|
|
117
|
+
POOL_MEMORY_POOL *old_context;
|
|
118
|
+
if (hba_memory_context == NULL)
|
|
119
|
+
{
|
|
120
|
+
hba_memory_context = pool_memory_create(PARSER_BLOCK_SIZE);
|
|
121
|
+
if (hba_memory_context == NULL)
|
|
122
|
+
{
|
|
123
|
+
pool_error("load_hba: pool_memory_create() failed");
|
|
124
|
+
return -1;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/* switch memory context */
|
|
128
|
+
old_context = pool_memory_context_switch_to(hba_memory_context);
|
|
129
|
+
|
|
130
|
+
if (hba_lines || hba_line_nums)
|
|
131
|
+
free_lines(&hba_lines, &hba_line_nums);
|
|
132
|
+
|
|
133
|
+
file = fopen(hbapath, "r");
|
|
134
|
+
if (!file)
|
|
135
|
+
{
|
|
136
|
+
pool_error("could not open \"%s\". reason: %s",
|
|
137
|
+
hbapath, strerror(errno));
|
|
138
|
+
pool_memory_delete(hba_memory_context, 0);
|
|
139
|
+
|
|
140
|
+
/* switch to old memory context */
|
|
141
|
+
pool_memory_context_switch_to(old_context);
|
|
142
|
+
|
|
143
|
+
return -1;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
pool_debug("loading \"%s\" for client authentication configuration file",
|
|
147
|
+
hbapath);
|
|
148
|
+
|
|
149
|
+
tokenize_file(hbapath, file, &hba_lines, &hba_line_nums);
|
|
150
|
+
fclose(file);
|
|
151
|
+
|
|
152
|
+
hbaFileName = pstrdup(hbapath);
|
|
153
|
+
|
|
154
|
+
/* switch to old memory context */
|
|
155
|
+
pool_memory_context_switch_to(old_context);
|
|
156
|
+
|
|
157
|
+
return 0;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
/*
|
|
162
|
+
* do frontend <-> pgpool authentication based on pool_hba.conf
|
|
163
|
+
*/
|
|
164
|
+
void ClientAuthentication(POOL_CONNECTION *frontend)
|
|
165
|
+
{
|
|
166
|
+
POOL_STATUS status = POOL_ERROR;
|
|
167
|
+
|
|
168
|
+
if (! hba_getauthmethod(frontend))
|
|
169
|
+
{
|
|
170
|
+
pool_error("missing or erroneous pool_hba.conf file");
|
|
171
|
+
pool_send_error_message(frontend, frontend->protoVersion, "XX000",
|
|
172
|
+
"missing or erroneous pool_hba.conf file", "",
|
|
173
|
+
"See pgpool log for details.", __FILE__, __LINE__);
|
|
174
|
+
close_all_backend_connections();
|
|
175
|
+
/*
|
|
176
|
+
* use exit(2) since this is not so fatal. other entries in
|
|
177
|
+
* pool_hba.conf may be valid, so treat it as reject.
|
|
178
|
+
*/
|
|
179
|
+
child_exit(2);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
switch (frontend->auth_method)
|
|
183
|
+
{
|
|
184
|
+
case uaReject:
|
|
185
|
+
{
|
|
186
|
+
/*
|
|
187
|
+
* This could have come from an explicit "reject" entry in
|
|
188
|
+
* pool_hba.conf, but more likely it means there was no matching
|
|
189
|
+
* entry. Take pity on the poor user and issue a helpful
|
|
190
|
+
* error message. NOTE: this is not a security breach,
|
|
191
|
+
* because all the info reported here is known at the frontend
|
|
192
|
+
* and must be assumed known to bad guys. We're merely helping
|
|
193
|
+
* out the less clueful good guys.
|
|
194
|
+
*/
|
|
195
|
+
char hostinfo[NI_MAXHOST];
|
|
196
|
+
char *errmessage;
|
|
197
|
+
int messagelen;
|
|
198
|
+
|
|
199
|
+
getnameinfo_all(&frontend->raddr.addr, frontend->raddr.salen,
|
|
200
|
+
hostinfo, sizeof(hostinfo),
|
|
201
|
+
NULL, 0,
|
|
202
|
+
NI_NUMERICHOST);
|
|
203
|
+
|
|
204
|
+
messagelen = sizeof(hostinfo) +
|
|
205
|
+
strlen(frontend->username) + strlen(frontend->database) + 80;
|
|
206
|
+
if ((errmessage = (char *)malloc(messagelen+1)) == NULL)
|
|
207
|
+
{
|
|
208
|
+
pool_error("ClientAuthentication: malloc failed: %s", strerror(errno));
|
|
209
|
+
child_exit(1);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
#ifdef USE_SSL
|
|
213
|
+
snprintf(errmessage, messagelen+7, /* +7 is for "SSL off" */
|
|
214
|
+
"no pool_hba.conf entry for host \"%s\", user \"%s\", database \"%s\", %s",
|
|
215
|
+
hostinfo, frontend->username, frontend->database,
|
|
216
|
+
frontend->ssl ? "SSL on" : "SSL off");
|
|
217
|
+
#else
|
|
218
|
+
snprintf(errmessage, messagelen,
|
|
219
|
+
"no pool_hba.conf entry for host \"%s\", user \"%s\", database \"%s\"",
|
|
220
|
+
hostinfo, frontend->username, frontend->database);
|
|
221
|
+
#endif
|
|
222
|
+
pool_error("%s", errmessage);
|
|
223
|
+
pool_send_error_message(frontend, frontend->protoVersion, "XX000", errmessage,
|
|
224
|
+
"", "", __FILE__, __LINE__);
|
|
225
|
+
|
|
226
|
+
free(errmessage);
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* case uaKrb4: */
|
|
231
|
+
/* break; */
|
|
232
|
+
|
|
233
|
+
/* case uaKrb5: */
|
|
234
|
+
/* break; */
|
|
235
|
+
|
|
236
|
+
/* case uaIdent: */
|
|
237
|
+
/* break; */
|
|
238
|
+
|
|
239
|
+
case uaMD5:
|
|
240
|
+
status = CheckMd5Auth(frontend->username);
|
|
241
|
+
break;
|
|
242
|
+
|
|
243
|
+
/* case uaCrypt: */
|
|
244
|
+
/* break; */
|
|
245
|
+
|
|
246
|
+
/* case uaPassword: */
|
|
247
|
+
/* break; */
|
|
248
|
+
|
|
249
|
+
#ifdef USE_PAM
|
|
250
|
+
case uaPAM:
|
|
251
|
+
pam_frontend_kludge = frontend;
|
|
252
|
+
status = CheckPAMAuth(frontend, frontend->username, "");
|
|
253
|
+
break;
|
|
254
|
+
#endif /* USE_PAM */
|
|
255
|
+
case uaPrestogresMD5:
|
|
256
|
+
status = pool_prestogres_hba_auth_md5(frontend);
|
|
257
|
+
break;
|
|
258
|
+
case uaPrestogresExternal:
|
|
259
|
+
status = pool_prestogres_hba_auth_external(frontend);
|
|
260
|
+
break;
|
|
261
|
+
|
|
262
|
+
case uaTrust:
|
|
263
|
+
status = POOL_CONTINUE;
|
|
264
|
+
break;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (status == POOL_CONTINUE)
|
|
268
|
+
sendAuthRequest(frontend, AUTH_REQ_OK);
|
|
269
|
+
else if (status != POOL_CONTINUE)
|
|
270
|
+
auth_failed(frontend);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
static void sendAuthRequest(POOL_CONNECTION *frontend, AuthRequest areq)
|
|
275
|
+
{
|
|
276
|
+
int wsize; /* number of bytes to write */
|
|
277
|
+
int areq_nbo; /* areq in network byte order */
|
|
278
|
+
|
|
279
|
+
/*
|
|
280
|
+
* If AUTH_REQ_OK, then frontend is OK to connect __with_pgpool__.
|
|
281
|
+
* Do not send 'R' to the frontend, he still needs to authenticate
|
|
282
|
+
* himself with the backend.
|
|
283
|
+
*/
|
|
284
|
+
if (areq == AUTH_REQ_OK)
|
|
285
|
+
return;
|
|
286
|
+
|
|
287
|
+
/* request a password */
|
|
288
|
+
pool_write(frontend, "R", 1);
|
|
289
|
+
|
|
290
|
+
if (frontend->protoVersion == PROTO_MAJOR_V3)
|
|
291
|
+
{
|
|
292
|
+
/* if (areq == AUTH_REQ_MD5) */
|
|
293
|
+
/* wsize = htonl(sizeof(int)*2+4); */
|
|
294
|
+
/* else if (areq == AUTH_REQ_CRYPT) */
|
|
295
|
+
/* wsize = htonl(sizeof(int)*2+2); */
|
|
296
|
+
/* else */
|
|
297
|
+
wsize = htonl(sizeof(int)*2);
|
|
298
|
+
pool_write(frontend, &wsize, sizeof(int));
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
areq_nbo = htonl(areq);
|
|
302
|
+
pool_write(frontend, &areq_nbo, sizeof(int));
|
|
303
|
+
|
|
304
|
+
/* Add the salt for encrypted passwords. */
|
|
305
|
+
/* if (areq == AUTH_REQ_MD5) */
|
|
306
|
+
/* pq_sendbytes(&buf, port->md5Salt, 4); */
|
|
307
|
+
/* else if (areq == AUTH_REQ_CRYPT) */
|
|
308
|
+
/* pq_sendbytes(&buf, port->cryptSalt, 2); */
|
|
309
|
+
|
|
310
|
+
pool_flush(frontend);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
/*
|
|
315
|
+
* Collect password response packet from frontend.
|
|
316
|
+
*
|
|
317
|
+
* Returns NULL if couldn't get password, else malloc'd string.
|
|
318
|
+
*/
|
|
319
|
+
static char *recv_password_packet(POOL_CONNECTION *frontend)
|
|
320
|
+
{
|
|
321
|
+
int rsize;
|
|
322
|
+
char *passwd;
|
|
323
|
+
char *returnVal;
|
|
324
|
+
|
|
325
|
+
if (frontend->protoVersion == PROTO_MAJOR_V3)
|
|
326
|
+
{
|
|
327
|
+
/* Expect 'p' message type */
|
|
328
|
+
char kind;
|
|
329
|
+
|
|
330
|
+
if (pool_read(frontend, &kind, 1) < 0)
|
|
331
|
+
return NULL;
|
|
332
|
+
|
|
333
|
+
if (kind != 'p')
|
|
334
|
+
{
|
|
335
|
+
pool_error("expected password response, got message type %c",
|
|
336
|
+
kind);
|
|
337
|
+
return NULL; /* bad message type */
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
/* pre-3.0 protocol does not send a message type */
|
|
341
|
+
|
|
342
|
+
if (pool_read(frontend, &rsize, sizeof(int)) < 0)
|
|
343
|
+
return NULL;
|
|
344
|
+
|
|
345
|
+
rsize = ntohl(rsize) - 4;
|
|
346
|
+
passwd = pool_read2(frontend, rsize); /* retrieve password */
|
|
347
|
+
if (passwd == NULL)
|
|
348
|
+
return NULL;
|
|
349
|
+
|
|
350
|
+
/* Do not echo password to logs, for security. */
|
|
351
|
+
pool_debug("received password packet from frontend for pgpool's HBA");
|
|
352
|
+
|
|
353
|
+
/*
|
|
354
|
+
* Return the received string. Note we do not attempt to do any
|
|
355
|
+
* character-set conversion on it; since we don't yet know the
|
|
356
|
+
* client's encoding, there wouldn't be much point.
|
|
357
|
+
*/
|
|
358
|
+
returnVal = strdup(passwd);
|
|
359
|
+
if (returnVal == NULL)
|
|
360
|
+
{
|
|
361
|
+
pool_error("recv_password_packet: strdup failed: %s", strerror(errno));
|
|
362
|
+
exit(1);
|
|
363
|
+
}
|
|
364
|
+
return returnVal;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/*
|
|
368
|
+
* Tell the user the authentication failed.
|
|
369
|
+
*/
|
|
370
|
+
static void auth_failed(POOL_CONNECTION *frontend)
|
|
371
|
+
{
|
|
372
|
+
bool send_error_to_frontend = true;
|
|
373
|
+
int messagelen;
|
|
374
|
+
char *errmessage;
|
|
375
|
+
|
|
376
|
+
messagelen = strlen(frontend->username) + 100;
|
|
377
|
+
if ((errmessage = (char *)malloc(messagelen+1)) == NULL)
|
|
378
|
+
{
|
|
379
|
+
pool_error("auth_failed: malloc failed: %s", strerror(errno));
|
|
380
|
+
child_exit(1);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
switch (frontend->auth_method)
|
|
384
|
+
{
|
|
385
|
+
case uaReject:
|
|
386
|
+
snprintf(errmessage, messagelen,
|
|
387
|
+
"authentication with pgpool failed for user \"%s\": host rejected",
|
|
388
|
+
frontend->username);
|
|
389
|
+
/*
|
|
390
|
+
* if uaReject, frontend should have received 'E' and disconnected already.
|
|
391
|
+
*/
|
|
392
|
+
send_error_to_frontend = false;
|
|
393
|
+
break;
|
|
394
|
+
/* case uaKrb4: */
|
|
395
|
+
/* snprintf(errmessage, messagelen, */
|
|
396
|
+
/* "Kerberos 4 authentication with pgpool failed for user \"%s\"", */
|
|
397
|
+
/* frontend->username); */
|
|
398
|
+
/* break; */
|
|
399
|
+
/* case uaKrb5: */
|
|
400
|
+
/* snprintf(errmessage, messagelen, */
|
|
401
|
+
/* "Kerberos 5 authentication with pgpool failed for user \"%s\"", */
|
|
402
|
+
/* frontend->username); */
|
|
403
|
+
/* break; */
|
|
404
|
+
case uaTrust:
|
|
405
|
+
snprintf(errmessage, messagelen,
|
|
406
|
+
"\"trust\" authentication with pgpool failed for user \"%s\"",
|
|
407
|
+
frontend->username);
|
|
408
|
+
break;
|
|
409
|
+
/* case uaIdent: */
|
|
410
|
+
/* snprintf(errmessage, messagelen, */
|
|
411
|
+
/* "Ident authentication with pgpool failed for user \"%s\"", */
|
|
412
|
+
/* frontend->username); */
|
|
413
|
+
/* break; */
|
|
414
|
+
case uaMD5:
|
|
415
|
+
snprintf(errmessage, messagelen,
|
|
416
|
+
"\"MD5\" authentication with pgpool failed for user \"%s\"",
|
|
417
|
+
frontend->username);
|
|
418
|
+
break;
|
|
419
|
+
|
|
420
|
+
/* case uaCrypt: */
|
|
421
|
+
/* case uaPassword: */
|
|
422
|
+
/* snprintf(errmessage, messagelen, */
|
|
423
|
+
/* "password authentication with pgpool failed for user \"%s\"", */
|
|
424
|
+
/* frontend->username); */
|
|
425
|
+
/* break; */
|
|
426
|
+
#ifdef USE_PAM
|
|
427
|
+
case uaPAM:
|
|
428
|
+
snprintf(errmessage, messagelen,
|
|
429
|
+
"PAM authentication with pgpool failed for user \"%s\"",
|
|
430
|
+
frontend->username);
|
|
431
|
+
break;
|
|
432
|
+
#endif /* USE_PAM */
|
|
433
|
+
case uaPrestogresMD5:
|
|
434
|
+
snprintf(errmessage, messagelen,
|
|
435
|
+
"\"MD5\" authentication with pgpool failed for user \"%s\"",
|
|
436
|
+
frontend->username);
|
|
437
|
+
break;
|
|
438
|
+
case uaPrestogresExternal:
|
|
439
|
+
snprintf(errmessage, messagelen,
|
|
440
|
+
"\"external\" authentication with pgpool failed for user \"%s\"",
|
|
441
|
+
frontend->username);
|
|
442
|
+
break;
|
|
443
|
+
default:
|
|
444
|
+
snprintf(errmessage, messagelen,
|
|
445
|
+
"authentication with pgpool failed for user \"%s\": invalid authentication method",
|
|
446
|
+
frontend->username);
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
pool_error("%s", errmessage);
|
|
451
|
+
if (send_error_to_frontend)
|
|
452
|
+
pool_send_error_message(frontend, frontend->protoVersion, "XX000", errmessage,
|
|
453
|
+
"", "", __FILE__, __LINE__);
|
|
454
|
+
|
|
455
|
+
/*
|
|
456
|
+
* don't need to free(errmessage). I will just kill myself.
|
|
457
|
+
*/
|
|
458
|
+
close_all_backend_connections();
|
|
459
|
+
child_exit(2);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
/*
|
|
464
|
+
* Close all of the cached backend connections.
|
|
465
|
+
*
|
|
466
|
+
* This is exactly the same as send_frontend_exits() in child.c.
|
|
467
|
+
*/
|
|
468
|
+
static void close_all_backend_connections(void)
|
|
469
|
+
{
|
|
470
|
+
int i;
|
|
471
|
+
POOL_CONNECTION_POOL *p = pool_connection_pool;
|
|
472
|
+
|
|
473
|
+
#ifdef HAVE_SIGPROCMASK
|
|
474
|
+
sigset_t oldmask;
|
|
475
|
+
#else
|
|
476
|
+
int oldmask;
|
|
477
|
+
#endif
|
|
478
|
+
|
|
479
|
+
POOL_SETMASK2(&BlockSig, &oldmask);
|
|
480
|
+
|
|
481
|
+
for (i=0;i<pool_config->max_pool;i++, p++)
|
|
482
|
+
{
|
|
483
|
+
if (!MASTER_CONNECTION(p))
|
|
484
|
+
continue;
|
|
485
|
+
if (MASTER_CONNECTION(p)->sp->user == NULL)
|
|
486
|
+
continue;
|
|
487
|
+
pool_send_frontend_exits(p);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
POOL_SETMASK(&oldmask);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
|
|
494
|
+
/*
|
|
495
|
+
* Determine what authentication method should be used when accessing database
|
|
496
|
+
* "database" from frontend "raddr", user "user". Return the method and
|
|
497
|
+
* an optional argument (stored in fields of *frontend), and true for success.
|
|
498
|
+
*
|
|
499
|
+
* Note that false indicates a problem with the hba config file.
|
|
500
|
+
* If the file is OK but does not contain any entry matching the request,
|
|
501
|
+
* we return true and method = uaReject.
|
|
502
|
+
*/
|
|
503
|
+
static bool hba_getauthmethod(POOL_CONNECTION *frontend)
|
|
504
|
+
{
|
|
505
|
+
if (check_hba(frontend))
|
|
506
|
+
return true;
|
|
507
|
+
else
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
/*
|
|
513
|
+
* Scan the (pre-parsed) hba file line by line, looking for a match
|
|
514
|
+
* to the port's connection request.
|
|
515
|
+
*/
|
|
516
|
+
static bool check_hba(POOL_CONNECTION *frontend)
|
|
517
|
+
{
|
|
518
|
+
bool found_entry = false;
|
|
519
|
+
bool error = false;
|
|
520
|
+
ListCell *line;
|
|
521
|
+
ListCell *line_num;
|
|
522
|
+
|
|
523
|
+
forboth(line, hba_lines, line_num, hba_line_nums)
|
|
524
|
+
{
|
|
525
|
+
parse_hba(lfirst(line), lfirst_int(line_num),
|
|
526
|
+
frontend, &found_entry, &error);
|
|
527
|
+
if (found_entry || error)
|
|
528
|
+
break;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
if (!error)
|
|
532
|
+
{
|
|
533
|
+
/* If no matching entry was found, synthesize 'reject' entry. */
|
|
534
|
+
if (!found_entry)
|
|
535
|
+
frontend->auth_method = uaReject;
|
|
536
|
+
return true;
|
|
537
|
+
}
|
|
538
|
+
else
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
|
|
543
|
+
/*
|
|
544
|
+
* Process one line from the hba config file.
|
|
545
|
+
*
|
|
546
|
+
* See if it applies to a connection from a frontend with IP address
|
|
547
|
+
* frontend->raddr to a database named frontend->database. If so, return
|
|
548
|
+
* *found_p true and fill in the auth arguments into the appropriate
|
|
549
|
+
* frontend fields. If not, leave *found_p as it was. If the record has
|
|
550
|
+
* a syntax error, return *error_p true, after issuing a message to the
|
|
551
|
+
* log. If no error, leave *error_p as it was.
|
|
552
|
+
*/
|
|
553
|
+
static void parse_hba(List *line, int line_num, POOL_CONNECTION *frontend,
|
|
554
|
+
bool *found_p, bool *error_p)
|
|
555
|
+
{
|
|
556
|
+
char *token;
|
|
557
|
+
char *db, *db_tmp;
|
|
558
|
+
char *user, *user_tmp;
|
|
559
|
+
struct addrinfo *gai_result;
|
|
560
|
+
struct addrinfo hints;
|
|
561
|
+
int ret;
|
|
562
|
+
struct sockaddr_storage addr;
|
|
563
|
+
struct sockaddr_storage mask;
|
|
564
|
+
char *cidr_slash;
|
|
565
|
+
ListCell *line_item;
|
|
566
|
+
|
|
567
|
+
line_item = list_head(line);
|
|
568
|
+
/* Check the record type. */
|
|
569
|
+
token = lfirst(line_item);
|
|
570
|
+
if (strcmp(token, "local") == 0)
|
|
571
|
+
{
|
|
572
|
+
/* Get the database. */
|
|
573
|
+
line_item = lnext(line_item);
|
|
574
|
+
if (!line_item)
|
|
575
|
+
goto hba_syntax;
|
|
576
|
+
db = lfirst(line_item);
|
|
577
|
+
|
|
578
|
+
/* Get the user. */
|
|
579
|
+
line_item = lnext(line_item);
|
|
580
|
+
if (!line_item)
|
|
581
|
+
goto hba_syntax;
|
|
582
|
+
user = lfirst(line_item);
|
|
583
|
+
|
|
584
|
+
line_item = lnext(line_item);
|
|
585
|
+
if (!line_item)
|
|
586
|
+
goto hba_syntax;
|
|
587
|
+
|
|
588
|
+
/* Read the rest of the line. */
|
|
589
|
+
parse_hba_auth(&line_item, &frontend->auth_method,
|
|
590
|
+
&frontend->auth_arg, error_p);
|
|
591
|
+
if (*error_p)
|
|
592
|
+
goto hba_syntax;
|
|
593
|
+
|
|
594
|
+
/* Disallow auth methods that always need TCP/IP sockets to work */
|
|
595
|
+
/*
|
|
596
|
+
if (frontend->auth_method == uaKrb4 ||
|
|
597
|
+
frontend->auth_method == uaKrb5)
|
|
598
|
+
goto hba_syntax;
|
|
599
|
+
*/
|
|
600
|
+
|
|
601
|
+
/* Does not match if connection isn't AF_UNIX */
|
|
602
|
+
if (!IS_AF_UNIX(frontend->raddr.addr.ss_family))
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
else if (strcmp(token, "host") == 0
|
|
606
|
+
|| strcmp(token, "hostssl") == 0
|
|
607
|
+
|| strcmp(token, "hostnossl") == 0)
|
|
608
|
+
{
|
|
609
|
+
if (token[4] == 's') /* "hostssl" */
|
|
610
|
+
{
|
|
611
|
+
#ifdef USE_SSL
|
|
612
|
+
/* Record does not match if we are not on an SSL connection */
|
|
613
|
+
if (!frontend->ssl)
|
|
614
|
+
return;
|
|
615
|
+
|
|
616
|
+
/* Placeholder to require specific SSL level, perhaps? */
|
|
617
|
+
/* Or a client certificate */
|
|
618
|
+
|
|
619
|
+
/* Since we were on SSL, proceed as with normal 'host' mode */
|
|
620
|
+
#else
|
|
621
|
+
/* We don't accept this keyword at all if no SSL support */
|
|
622
|
+
goto hba_syntax;
|
|
623
|
+
#endif
|
|
624
|
+
}
|
|
625
|
+
#ifdef USE_SSL
|
|
626
|
+
else if (token[4] == 'n') /* "hostnossl" */
|
|
627
|
+
{
|
|
628
|
+
/* Record does not match if we are on an SSL connection */
|
|
629
|
+
if (frontend->ssl)
|
|
630
|
+
return;
|
|
631
|
+
}
|
|
632
|
+
#endif
|
|
633
|
+
|
|
634
|
+
/* Get the database. */
|
|
635
|
+
line_item = lnext(line_item);
|
|
636
|
+
if (!line_item)
|
|
637
|
+
goto hba_syntax;
|
|
638
|
+
db = lfirst(line_item);
|
|
639
|
+
|
|
640
|
+
/* Get the user. */
|
|
641
|
+
line_item = lnext(line_item);
|
|
642
|
+
if (!line_item)
|
|
643
|
+
goto hba_syntax;
|
|
644
|
+
user = lfirst(line_item);
|
|
645
|
+
|
|
646
|
+
/* Read the IP address field. (with or without CIDR netmask) */
|
|
647
|
+
line_item = lnext(line_item);
|
|
648
|
+
if (!line_item)
|
|
649
|
+
goto hba_syntax;
|
|
650
|
+
token = lfirst(line_item);
|
|
651
|
+
|
|
652
|
+
/* Check if it has a CIDR suffix and if so isolate it */
|
|
653
|
+
cidr_slash = strchr(token, '/');
|
|
654
|
+
if (cidr_slash)
|
|
655
|
+
*cidr_slash = '\0';
|
|
656
|
+
|
|
657
|
+
/* Get the IP address either way */
|
|
658
|
+
hints.ai_flags = AI_NUMERICHOST;
|
|
659
|
+
hints.ai_family = PF_UNSPEC;
|
|
660
|
+
hints.ai_socktype = 0;
|
|
661
|
+
hints.ai_protocol = 0;
|
|
662
|
+
hints.ai_addrlen = 0;
|
|
663
|
+
hints.ai_canonname = NULL;
|
|
664
|
+
hints.ai_addr = NULL;
|
|
665
|
+
hints.ai_next = NULL;
|
|
666
|
+
|
|
667
|
+
ret = getaddrinfo_all(token, NULL, &hints, &gai_result);
|
|
668
|
+
if (ret || !gai_result)
|
|
669
|
+
{
|
|
670
|
+
pool_log("invalid IP address \"%s\" in file \"%s\" line %d: %s",
|
|
671
|
+
token, hbaFileName, line_num, gai_strerror(ret));
|
|
672
|
+
if (cidr_slash)
|
|
673
|
+
*cidr_slash = '/';
|
|
674
|
+
if (gai_result)
|
|
675
|
+
freeaddrinfo_all(hints.ai_family, gai_result);
|
|
676
|
+
goto hba_other_error;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
if (cidr_slash)
|
|
680
|
+
*cidr_slash = '/';
|
|
681
|
+
|
|
682
|
+
memcpy(&addr, gai_result->ai_addr, gai_result->ai_addrlen);
|
|
683
|
+
freeaddrinfo_all(hints.ai_family, gai_result);
|
|
684
|
+
|
|
685
|
+
/* Get the netmask */
|
|
686
|
+
if (cidr_slash)
|
|
687
|
+
{
|
|
688
|
+
if (SockAddr_cidr_mask(&mask, cidr_slash + 1, addr.ss_family) < 0)
|
|
689
|
+
goto hba_syntax;
|
|
690
|
+
}
|
|
691
|
+
else
|
|
692
|
+
{
|
|
693
|
+
/* Read the mask field. */
|
|
694
|
+
line_item = lnext(line_item);
|
|
695
|
+
if (!line_item)
|
|
696
|
+
goto hba_syntax;
|
|
697
|
+
token = lfirst(line_item);
|
|
698
|
+
|
|
699
|
+
ret = getaddrinfo_all(token, NULL, &hints, &gai_result);
|
|
700
|
+
if (ret || !gai_result)
|
|
701
|
+
{
|
|
702
|
+
pool_log("invalid IP mask \"%s\" in file \"%s\" line %d: %s",
|
|
703
|
+
token, hbaFileName, line_num, gai_strerror(ret));
|
|
704
|
+
if (gai_result)
|
|
705
|
+
freeaddrinfo_all(hints.ai_family, gai_result);
|
|
706
|
+
goto hba_other_error;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
memcpy(&mask, gai_result->ai_addr, gai_result->ai_addrlen);
|
|
710
|
+
freeaddrinfo_all(hints.ai_family, gai_result);
|
|
711
|
+
|
|
712
|
+
if (addr.ss_family != mask.ss_family)
|
|
713
|
+
{
|
|
714
|
+
pool_log("IP address and mask do not match in file \"%s\" line %d",
|
|
715
|
+
hbaFileName, line_num);
|
|
716
|
+
goto hba_other_error;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if (addr.ss_family != frontend->raddr.addr.ss_family)
|
|
721
|
+
{
|
|
722
|
+
/*
|
|
723
|
+
* Wrong address family. We allow only one case: if the file
|
|
724
|
+
* has IPv4 and the port is IPv6, promote the file address to
|
|
725
|
+
* IPv6 and try to match that way.
|
|
726
|
+
*/
|
|
727
|
+
#ifdef HAVE_IPV6
|
|
728
|
+
if (addr.ss_family == AF_INET && frontend->raddr.addr.ss_family == AF_INET6)
|
|
729
|
+
{
|
|
730
|
+
promote_v4_to_v6_addr(&addr);
|
|
731
|
+
promote_v4_to_v6_mask(&mask);
|
|
732
|
+
}
|
|
733
|
+
else
|
|
734
|
+
#endif /* HAVE_IPV6 */
|
|
735
|
+
{
|
|
736
|
+
/* Line doesn't match client port, so ignore it. */
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/* Ignore line if client port is not in the matching addr range. */
|
|
742
|
+
if (!rangeSockAddr(&frontend->raddr.addr, &addr, &mask))
|
|
743
|
+
return;
|
|
744
|
+
|
|
745
|
+
/* Read the rest of the line. */
|
|
746
|
+
line_item = lnext(line_item);
|
|
747
|
+
if (!line_item)
|
|
748
|
+
goto hba_syntax;
|
|
749
|
+
parse_hba_auth(&line_item, &frontend->auth_method,
|
|
750
|
+
&frontend->auth_arg, error_p);
|
|
751
|
+
if (*error_p)
|
|
752
|
+
goto hba_syntax;
|
|
753
|
+
}
|
|
754
|
+
else
|
|
755
|
+
goto hba_syntax;
|
|
756
|
+
|
|
757
|
+
/* Does the entry match database and user? */
|
|
758
|
+
/*
|
|
759
|
+
* duplicate db and username since strtok() in check_db() and check_user()
|
|
760
|
+
* will override '\001' with '\0'.
|
|
761
|
+
*/
|
|
762
|
+
db_tmp = strdup(db);
|
|
763
|
+
if (db_tmp == NULL)
|
|
764
|
+
{
|
|
765
|
+
pool_error("parse_hba: strdup failed: %s", strerror(errno));
|
|
766
|
+
exit(1);
|
|
767
|
+
}
|
|
768
|
+
user_tmp = strdup(user);
|
|
769
|
+
if (user_tmp == NULL)
|
|
770
|
+
{
|
|
771
|
+
pool_error("parse_hba: strdup failed: %s", strerror(errno));
|
|
772
|
+
exit(1);
|
|
773
|
+
}
|
|
774
|
+
if (!check_db(frontend->database, frontend->username, db_tmp))
|
|
775
|
+
return;
|
|
776
|
+
if (!check_user(frontend->username, user_tmp))
|
|
777
|
+
return;
|
|
778
|
+
free(db_tmp);
|
|
779
|
+
free(user_tmp);
|
|
780
|
+
|
|
781
|
+
/* Success */
|
|
782
|
+
*found_p = true;
|
|
783
|
+
return;
|
|
784
|
+
|
|
785
|
+
hba_syntax:
|
|
786
|
+
if (line_item)
|
|
787
|
+
pool_log("invalid entry in file \"%s\" at line %d, token \"%s\"",
|
|
788
|
+
hbaFileName, line_num, (char *) lfirst(line_item));
|
|
789
|
+
else
|
|
790
|
+
pool_log("missing field in file \"%s\" at end of line %d",
|
|
791
|
+
hbaFileName, line_num);
|
|
792
|
+
|
|
793
|
+
/* Come here if suitable message already logged */
|
|
794
|
+
hba_other_error:
|
|
795
|
+
*error_p = true;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
/*
|
|
800
|
+
* Scan the rest of a host record (after the mask field)
|
|
801
|
+
* and return the interpretation of it as *userauth_p, *auth_arg_p, and
|
|
802
|
+
* *error_p. *line_item points to the next token of the line, and is
|
|
803
|
+
* advanced over successfully-read tokens.
|
|
804
|
+
*/
|
|
805
|
+
static void parse_hba_auth(ListCell **line_item, UserAuth *userauth_p,
|
|
806
|
+
char **auth_arg_p, bool *error_p)
|
|
807
|
+
{
|
|
808
|
+
char *token;
|
|
809
|
+
|
|
810
|
+
*auth_arg_p = NULL;
|
|
811
|
+
|
|
812
|
+
if (!*line_item)
|
|
813
|
+
{
|
|
814
|
+
*error_p = true;
|
|
815
|
+
return;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
token = lfirst(*line_item);
|
|
819
|
+
if (strcmp(token, "trust") == 0)
|
|
820
|
+
*userauth_p = uaTrust;
|
|
821
|
+
/*
|
|
822
|
+
else if (strcmp(token, "ident") == 0)
|
|
823
|
+
*userauth_p = uaIdent;
|
|
824
|
+
else if (strcmp(token, "password") == 0)
|
|
825
|
+
*userauth_p = uaPassword;
|
|
826
|
+
else if (strcmp(token, "krb4") == 0)
|
|
827
|
+
*userauth_p = uaKrb4;
|
|
828
|
+
else if (strcmp(token, "krb5") == 0)
|
|
829
|
+
*userauth_p = uaKrb5;
|
|
830
|
+
*/
|
|
831
|
+
else if (strcmp(token, "reject") == 0)
|
|
832
|
+
*userauth_p = uaReject;
|
|
833
|
+
else if (strcmp(token, "md5") == 0)
|
|
834
|
+
*userauth_p = uaMD5;
|
|
835
|
+
/*
|
|
836
|
+
else if (strcmp(token, "crypt") == 0)
|
|
837
|
+
*userauth_p = uaCrypt;
|
|
838
|
+
*/
|
|
839
|
+
#ifdef USE_PAM
|
|
840
|
+
else if (strcmp(token, "pam") == 0)
|
|
841
|
+
*userauth_p = uaPAM;
|
|
842
|
+
#endif /* USE_PAM */
|
|
843
|
+
else if (strcmp(token, "prestogres_md5") == 0)
|
|
844
|
+
*userauth_p = uaPrestogresMD5;
|
|
845
|
+
else if (strcmp(token, "prestogres_external") == 0)
|
|
846
|
+
*userauth_p = uaPrestogresExternal;
|
|
847
|
+
else
|
|
848
|
+
{
|
|
849
|
+
*error_p = true;
|
|
850
|
+
return;
|
|
851
|
+
}
|
|
852
|
+
*line_item = lnext(*line_item);
|
|
853
|
+
|
|
854
|
+
/* Get the authentication argument token, if any */
|
|
855
|
+
if (*line_item)
|
|
856
|
+
{
|
|
857
|
+
token = lfirst(*line_item);
|
|
858
|
+
*auth_arg_p = strdup(token);
|
|
859
|
+
if (*auth_arg_p == NULL)
|
|
860
|
+
{
|
|
861
|
+
pool_error("parse_hba_auth: strdup failed: %s", strerror(errno));
|
|
862
|
+
exit(1);
|
|
863
|
+
}
|
|
864
|
+
*line_item = lnext(*line_item);
|
|
865
|
+
/* If there is more on the line, it is an error */
|
|
866
|
+
if (*line_item)
|
|
867
|
+
*error_p = true;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
|
|
872
|
+
/*
|
|
873
|
+
* Check comma user list for a specific user, handle group names.
|
|
874
|
+
*/
|
|
875
|
+
static bool check_user(char *user, char *param_str)
|
|
876
|
+
{
|
|
877
|
+
char *tok;
|
|
878
|
+
|
|
879
|
+
for (tok = strtok(param_str, MULTI_VALUE_SEP);
|
|
880
|
+
tok != NULL; tok = strtok(NULL, MULTI_VALUE_SEP))
|
|
881
|
+
{
|
|
882
|
+
if (tok[0] == '+')
|
|
883
|
+
{
|
|
884
|
+
/*
|
|
885
|
+
* pgpool cannot accept groups. commented lines below are the
|
|
886
|
+
* original code.
|
|
887
|
+
*/
|
|
888
|
+
pool_error("group token \"+\" is not supported in pgpool");
|
|
889
|
+
return false;
|
|
890
|
+
/* if (check_group(tok + 1, user)) */
|
|
891
|
+
/* return true; */
|
|
892
|
+
}
|
|
893
|
+
else if (strcmp(tok, user) == 0 || strcmp(tok, "all\n") == 0)
|
|
894
|
+
return true;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
return false;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
|
|
901
|
+
/*
|
|
902
|
+
* Check to see if db/user combination matches param string.
|
|
903
|
+
*/
|
|
904
|
+
static bool check_db(char *dbname, char *user, char *param_str)
|
|
905
|
+
{
|
|
906
|
+
char *tok;
|
|
907
|
+
|
|
908
|
+
for (tok = strtok(param_str, MULTI_VALUE_SEP);
|
|
909
|
+
tok != NULL; tok = strtok(NULL, MULTI_VALUE_SEP))
|
|
910
|
+
{
|
|
911
|
+
if (strcmp(tok, "all\n") == 0)
|
|
912
|
+
return true;
|
|
913
|
+
else if (strcmp(tok, "sameuser\n") == 0)
|
|
914
|
+
{
|
|
915
|
+
if (strcmp(dbname, user) == 0)
|
|
916
|
+
return true;
|
|
917
|
+
}
|
|
918
|
+
else if (strcmp(tok, "samegroup\n") == 0)
|
|
919
|
+
{
|
|
920
|
+
/*
|
|
921
|
+
* pgpool cannot accept groups. commented lines below are the
|
|
922
|
+
* original code.
|
|
923
|
+
*/
|
|
924
|
+
pool_error("group token \"samegroup\" is not supported in pgpool");
|
|
925
|
+
return false;
|
|
926
|
+
/* if (check_group(dbname, user)) */
|
|
927
|
+
/* return true; */
|
|
928
|
+
}
|
|
929
|
+
else if (strcmp(tok, dbname) == 0)
|
|
930
|
+
return true;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
return false;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
/*
|
|
938
|
+
* tokenize the given file, storing the resulting data into two lists:
|
|
939
|
+
* a list of sublists, each sublist containing the tokens in a line of
|
|
940
|
+
* the file, and a list of line numbers.
|
|
941
|
+
*
|
|
942
|
+
* filename must be the absolute path to the target file.
|
|
943
|
+
*/
|
|
944
|
+
static void tokenize_file(const char *filename, FILE *file,
|
|
945
|
+
List **lines, List **line_nums)
|
|
946
|
+
{
|
|
947
|
+
List *current_line = NIL;
|
|
948
|
+
int line_number = 1;
|
|
949
|
+
char *buf;
|
|
950
|
+
|
|
951
|
+
*lines = *line_nums = NIL;
|
|
952
|
+
|
|
953
|
+
while (!feof(file))
|
|
954
|
+
{
|
|
955
|
+
buf = next_token_expand(filename, file);
|
|
956
|
+
|
|
957
|
+
/* add token to list, unless we are at EOL or comment start */
|
|
958
|
+
if (buf[0])
|
|
959
|
+
{
|
|
960
|
+
if (current_line == NIL)
|
|
961
|
+
{
|
|
962
|
+
/* make a new line List, record its line number */
|
|
963
|
+
current_line = lappend(current_line, buf);
|
|
964
|
+
*lines = lappend(*lines, current_line);
|
|
965
|
+
*line_nums = lappend_int(*line_nums, line_number);
|
|
966
|
+
}
|
|
967
|
+
else
|
|
968
|
+
{
|
|
969
|
+
/* append token to current line's list */
|
|
970
|
+
current_line = lappend(current_line, buf);
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
else
|
|
974
|
+
{
|
|
975
|
+
/* we are at real or logical EOL, so force a new line List */
|
|
976
|
+
current_line = NIL;
|
|
977
|
+
/* Advance line number whenever we reach EOL */
|
|
978
|
+
line_number++;
|
|
979
|
+
/* Don't forget to free the next_token_expand result */
|
|
980
|
+
free(buf);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
static char * tokenize_inc_file(const char *outer_filename,
|
|
987
|
+
const char *inc_filename)
|
|
988
|
+
{
|
|
989
|
+
char *inc_fullname;
|
|
990
|
+
FILE *inc_file;
|
|
991
|
+
List *inc_lines;
|
|
992
|
+
List *inc_line_nums;
|
|
993
|
+
ListCell *line;
|
|
994
|
+
char *comma_str;
|
|
995
|
+
|
|
996
|
+
if (is_absolute_path(inc_filename))
|
|
997
|
+
{
|
|
998
|
+
/* absolute path is taken as-is */
|
|
999
|
+
inc_fullname = strdup(inc_filename);
|
|
1000
|
+
if (inc_fullname == NULL)
|
|
1001
|
+
{
|
|
1002
|
+
pool_error("tokenize_inc_file: strdup failed: %s", strerror(errno));
|
|
1003
|
+
exit(1);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
else
|
|
1007
|
+
{
|
|
1008
|
+
/* relative path is relative to dir of calling file */
|
|
1009
|
+
inc_fullname = (char *)malloc(strlen(outer_filename) + 1 +
|
|
1010
|
+
strlen(inc_filename) + 1);
|
|
1011
|
+
if (inc_fullname == NULL)
|
|
1012
|
+
{
|
|
1013
|
+
pool_error("tokenize_inc_file: malloc failed: %s", strerror(errno));
|
|
1014
|
+
exit(1);
|
|
1015
|
+
}
|
|
1016
|
+
strcpy(inc_fullname, outer_filename);
|
|
1017
|
+
get_parent_directory(inc_fullname);
|
|
1018
|
+
join_path_components(inc_fullname, inc_fullname, inc_filename);
|
|
1019
|
+
canonicalize_path(inc_fullname);
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
inc_file = fopen(inc_fullname, "r");
|
|
1023
|
+
if (inc_file == NULL)
|
|
1024
|
+
{
|
|
1025
|
+
char *returnVal;
|
|
1026
|
+
|
|
1027
|
+
pool_error("could not open secondary authentication file \"@%s\" as \"%s\": reason: %s",
|
|
1028
|
+
inc_filename, inc_fullname, strerror(errno));
|
|
1029
|
+
free(inc_fullname);
|
|
1030
|
+
|
|
1031
|
+
/* return single space, it matches nothing */
|
|
1032
|
+
returnVal = strdup(" ");
|
|
1033
|
+
if (returnVal == NULL)
|
|
1034
|
+
{
|
|
1035
|
+
pool_error("tokenize_inc_file: malloc failed: %s", strerror(errno));
|
|
1036
|
+
exit(1);
|
|
1037
|
+
}
|
|
1038
|
+
return returnVal;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
/* There is possible recursion here if the file contains @ */
|
|
1042
|
+
tokenize_file(inc_fullname, inc_file, &inc_lines, &inc_line_nums);
|
|
1043
|
+
|
|
1044
|
+
/*FreeFile(inc_file);*/
|
|
1045
|
+
fclose(inc_file);
|
|
1046
|
+
free(inc_fullname);
|
|
1047
|
+
|
|
1048
|
+
/* Create comma-separated string from List */
|
|
1049
|
+
comma_str = strdup("");
|
|
1050
|
+
if (comma_str == NULL)
|
|
1051
|
+
{
|
|
1052
|
+
pool_error("tokenize_inc_file: strdup failed: %s", strerror(errno));
|
|
1053
|
+
exit(1);
|
|
1054
|
+
}
|
|
1055
|
+
foreach(line, inc_lines)
|
|
1056
|
+
{
|
|
1057
|
+
List *token_list = (List *) lfirst(line);
|
|
1058
|
+
ListCell *token;
|
|
1059
|
+
|
|
1060
|
+
foreach(token, token_list)
|
|
1061
|
+
{
|
|
1062
|
+
int oldlen = strlen(comma_str);
|
|
1063
|
+
int needed;
|
|
1064
|
+
|
|
1065
|
+
needed = oldlen + strlen(lfirst(token)) + 1;
|
|
1066
|
+
if (oldlen > 0)
|
|
1067
|
+
needed++;
|
|
1068
|
+
comma_str = realloc(comma_str, needed);
|
|
1069
|
+
if (comma_str == NULL)
|
|
1070
|
+
{
|
|
1071
|
+
pool_error("tokenize_inc_file: realloc failed: %s", strerror(errno));
|
|
1072
|
+
exit(1);
|
|
1073
|
+
}
|
|
1074
|
+
if (oldlen > 0)
|
|
1075
|
+
strcat(comma_str, MULTI_VALUE_SEP);
|
|
1076
|
+
strcat(comma_str, lfirst(token));
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
free_lines(&inc_lines, &inc_line_nums);
|
|
1081
|
+
|
|
1082
|
+
/* if file is empty, return single space rather than empty string */
|
|
1083
|
+
if (strlen(comma_str) == 0)
|
|
1084
|
+
{
|
|
1085
|
+
char *returnVal;
|
|
1086
|
+
|
|
1087
|
+
free(comma_str);
|
|
1088
|
+
returnVal = strdup(" ");
|
|
1089
|
+
if (returnVal == NULL)
|
|
1090
|
+
{
|
|
1091
|
+
pool_error("tokenize_inc_file: strdup failed: %s", strerror(errno));
|
|
1092
|
+
exit(1);
|
|
1093
|
+
}
|
|
1094
|
+
return returnVal;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
return comma_str;
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
|
|
1101
|
+
/*
|
|
1102
|
+
* isblank() exists in the ISO C99 spec, but it's not very portable yet,
|
|
1103
|
+
* so provide our own version.
|
|
1104
|
+
*/
|
|
1105
|
+
static bool pg_isblank(const char c)
|
|
1106
|
+
{
|
|
1107
|
+
return c == ' ' || c == '\t' || c == '\r';
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
|
|
1111
|
+
/*
|
|
1112
|
+
* Tokenize file and handle file inclusion and comma lists. We have
|
|
1113
|
+
* to break apart the commas to expand any file names then
|
|
1114
|
+
* reconstruct with commas.
|
|
1115
|
+
*
|
|
1116
|
+
* The result is always a malloc'd string. If it's zero-length then
|
|
1117
|
+
* we have reached EOL.
|
|
1118
|
+
*/
|
|
1119
|
+
static char * next_token_expand(const char *filename, FILE *file)
|
|
1120
|
+
{
|
|
1121
|
+
char buf[MAX_TOKEN];
|
|
1122
|
+
char *comma_str;
|
|
1123
|
+
bool trailing_comma;
|
|
1124
|
+
char *incbuf;
|
|
1125
|
+
int needed;
|
|
1126
|
+
|
|
1127
|
+
comma_str = strdup("");
|
|
1128
|
+
if (comma_str == NULL)
|
|
1129
|
+
{
|
|
1130
|
+
pool_error("next_token_expand: strdup failed: %s", strerror(errno));
|
|
1131
|
+
exit(1);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
do
|
|
1135
|
+
{
|
|
1136
|
+
next_token(file, buf, sizeof(buf));
|
|
1137
|
+
if (!buf[0])
|
|
1138
|
+
break;
|
|
1139
|
+
|
|
1140
|
+
if (buf[strlen(buf) - 1] == ',')
|
|
1141
|
+
{
|
|
1142
|
+
trailing_comma = true;
|
|
1143
|
+
buf[strlen(buf) - 1] = '\0';
|
|
1144
|
+
}
|
|
1145
|
+
else
|
|
1146
|
+
trailing_comma = false;
|
|
1147
|
+
|
|
1148
|
+
/* Is this referencing a file? */
|
|
1149
|
+
if (buf[0] == '@')
|
|
1150
|
+
incbuf = tokenize_inc_file(filename, buf + 1);
|
|
1151
|
+
else
|
|
1152
|
+
{
|
|
1153
|
+
incbuf = strdup(buf);
|
|
1154
|
+
if (incbuf == NULL)
|
|
1155
|
+
{
|
|
1156
|
+
pool_error("next_token_expand: strdup failed: %s", strerror(errno));
|
|
1157
|
+
exit(1);
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
needed = strlen(comma_str) + strlen(incbuf) + 1;
|
|
1162
|
+
if (trailing_comma)
|
|
1163
|
+
needed++;
|
|
1164
|
+
comma_str = realloc(comma_str, needed);
|
|
1165
|
+
if (comma_str == NULL)
|
|
1166
|
+
{
|
|
1167
|
+
pool_error("next_token_expand: realloc failed: %s", strerror(errno));
|
|
1168
|
+
exit(1);
|
|
1169
|
+
}
|
|
1170
|
+
strcat(comma_str, incbuf);
|
|
1171
|
+
if (trailing_comma)
|
|
1172
|
+
strcat(comma_str, MULTI_VALUE_SEP);
|
|
1173
|
+
free(incbuf);
|
|
1174
|
+
} while (trailing_comma);
|
|
1175
|
+
|
|
1176
|
+
return comma_str;
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
|
|
1180
|
+
/*
|
|
1181
|
+
* Grab one token out of fp. Tokens are strings of non-blank
|
|
1182
|
+
* characters bounded by blank characters, beginning of line, and
|
|
1183
|
+
* end of line. Blank means space or tab. Return the token as
|
|
1184
|
+
* *buf. Leave file positioned at the character immediately after the
|
|
1185
|
+
* token or EOF, whichever comes first. If no more tokens on line,
|
|
1186
|
+
* return empty string as *buf and position the file to the beginning
|
|
1187
|
+
* of the next line or EOF, whichever comes first. Allow spaces in
|
|
1188
|
+
* quoted strings. Terminate on unquoted commas. Handle
|
|
1189
|
+
* comments. Treat unquoted keywords that might be user names or
|
|
1190
|
+
* database names specially, by appending a newline to them.
|
|
1191
|
+
*/
|
|
1192
|
+
static void next_token(FILE *fp, char *buf, int bufsz)
|
|
1193
|
+
{
|
|
1194
|
+
int c;
|
|
1195
|
+
char *start_buf = buf;
|
|
1196
|
+
char *end_buf = buf + (bufsz - 2);
|
|
1197
|
+
bool in_quote = false;
|
|
1198
|
+
bool was_quote = false;
|
|
1199
|
+
bool saw_quote = false;
|
|
1200
|
+
|
|
1201
|
+
/*Assert(end_buf > start_buf);*/
|
|
1202
|
+
|
|
1203
|
+
/* Move over initial whitespace and commas */
|
|
1204
|
+
while ((c = getc(fp)) != EOF && (pg_isblank(c) || c == ','))
|
|
1205
|
+
;
|
|
1206
|
+
|
|
1207
|
+
if (c == EOF || c == '\n')
|
|
1208
|
+
{
|
|
1209
|
+
*buf = '\0';
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/*
|
|
1214
|
+
* Build a token in buf of next characters up to EOF, EOL, unquoted
|
|
1215
|
+
* comma, or unquoted whitespace.
|
|
1216
|
+
*/
|
|
1217
|
+
while (c != EOF && c != '\n' &&
|
|
1218
|
+
(!pg_isblank(c) || in_quote == true))
|
|
1219
|
+
{
|
|
1220
|
+
/* skip comments to EOL */
|
|
1221
|
+
if (c == '#' && !in_quote)
|
|
1222
|
+
{
|
|
1223
|
+
while ((c = getc(fp)) != EOF && c != '\n')
|
|
1224
|
+
;
|
|
1225
|
+
/* If only comment, consume EOL too; return EOL */
|
|
1226
|
+
if (c != EOF && buf == start_buf)
|
|
1227
|
+
c = getc(fp);
|
|
1228
|
+
break;
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
if (buf >= end_buf)
|
|
1232
|
+
{
|
|
1233
|
+
*buf = '\0';
|
|
1234
|
+
pool_log("authentication file token too long, skipping: \"%s\"", start_buf);
|
|
1235
|
+
/* Discard remainder of line */
|
|
1236
|
+
while ((c = getc(fp)) != EOF && c != '\n')
|
|
1237
|
+
;
|
|
1238
|
+
break;
|
|
1239
|
+
}
|
|
1240
|
+
|
|
1241
|
+
if (c != '"' || (c == '"' && was_quote))
|
|
1242
|
+
*buf++ = c;
|
|
1243
|
+
|
|
1244
|
+
/* We pass back the comma so the caller knows there is more */
|
|
1245
|
+
if ((pg_isblank(c) || c == ',') && !in_quote)
|
|
1246
|
+
break;
|
|
1247
|
+
|
|
1248
|
+
/* Literal double-quote is two double-quotes */
|
|
1249
|
+
if (in_quote && c == '"')
|
|
1250
|
+
was_quote = !was_quote;
|
|
1251
|
+
else
|
|
1252
|
+
was_quote = false;
|
|
1253
|
+
|
|
1254
|
+
if (c == '"')
|
|
1255
|
+
{
|
|
1256
|
+
in_quote = !in_quote;
|
|
1257
|
+
saw_quote = true;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
c = getc(fp);
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
/*
|
|
1264
|
+
* Put back the char right after the token (critical in case it is
|
|
1265
|
+
* EOL, since we need to detect end-of-line at next call).
|
|
1266
|
+
*/
|
|
1267
|
+
if (c != EOF)
|
|
1268
|
+
ungetc(c, fp);
|
|
1269
|
+
|
|
1270
|
+
*buf = '\0';
|
|
1271
|
+
|
|
1272
|
+
if (!saw_quote &&
|
|
1273
|
+
(strcmp(start_buf, "all") == 0 ||
|
|
1274
|
+
strcmp(start_buf, "sameuser") == 0 ||
|
|
1275
|
+
strcmp(start_buf, "samegroup") == 0))
|
|
1276
|
+
{
|
|
1277
|
+
/* append newline to a magical keyword */
|
|
1278
|
+
*buf++ = '\n';
|
|
1279
|
+
*buf = '\0';
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
/*
|
|
1285
|
+
* free memory used by lines and tokens built by tokenize_file()
|
|
1286
|
+
*/
|
|
1287
|
+
static void free_lines(List **lines, List **line_nums)
|
|
1288
|
+
{
|
|
1289
|
+
if (*lines)
|
|
1290
|
+
{
|
|
1291
|
+
ListCell *line;
|
|
1292
|
+
|
|
1293
|
+
foreach(line, *lines)
|
|
1294
|
+
{
|
|
1295
|
+
List *ln = lfirst(line);
|
|
1296
|
+
ListCell *token;
|
|
1297
|
+
|
|
1298
|
+
foreach(token, ln)
|
|
1299
|
+
free(lfirst(token));
|
|
1300
|
+
|
|
1301
|
+
list_free(ln);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
list_free(*lines);
|
|
1305
|
+
*lines = NIL;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
if (*line_nums)
|
|
1309
|
+
{
|
|
1310
|
+
list_free(*line_nums);
|
|
1311
|
+
*line_nums = NIL;
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
|
|
1315
|
+
|
|
1316
|
+
#ifdef USE_PAM
|
|
1317
|
+
|
|
1318
|
+
/*
|
|
1319
|
+
* PAM conversation function
|
|
1320
|
+
*/
|
|
1321
|
+
static int pam_passwd_conv_proc(int num_msg, const struct pam_message ** msg,
|
|
1322
|
+
struct pam_response ** resp, void *appdata_ptr)
|
|
1323
|
+
{
|
|
1324
|
+
if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF)
|
|
1325
|
+
{
|
|
1326
|
+
switch (msg[0]->msg_style)
|
|
1327
|
+
{
|
|
1328
|
+
case PAM_ERROR_MSG:
|
|
1329
|
+
pool_log("error from underlying PAM layer: %s",
|
|
1330
|
+
msg[0]->msg);
|
|
1331
|
+
return PAM_CONV_ERR;
|
|
1332
|
+
default:
|
|
1333
|
+
pool_log("unsupported PAM conversation %d/%s",
|
|
1334
|
+
msg[0]->msg_style, msg[0]->msg);
|
|
1335
|
+
return PAM_CONV_ERR;
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
if (!appdata_ptr)
|
|
1340
|
+
{
|
|
1341
|
+
/*
|
|
1342
|
+
* Workaround for Solaris 2.6 where the PAM library is broken and
|
|
1343
|
+
* does not pass appdata_ptr to the conversation routine
|
|
1344
|
+
*/
|
|
1345
|
+
appdata_ptr = pam_passwd;
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
/*
|
|
1349
|
+
* Password wasn't passed to PAM the first time around - let's go ask
|
|
1350
|
+
* the client to send a password, which we then stuff into PAM.
|
|
1351
|
+
*/
|
|
1352
|
+
if (strlen(appdata_ptr) == 0)
|
|
1353
|
+
{
|
|
1354
|
+
char *passwd;
|
|
1355
|
+
|
|
1356
|
+
sendAuthRequest(pam_frontend_kludge, AUTH_REQ_PASSWORD);
|
|
1357
|
+
passwd = recv_password_packet(pam_frontend_kludge);
|
|
1358
|
+
|
|
1359
|
+
if (passwd == NULL)
|
|
1360
|
+
return PAM_CONV_ERR; /* client didn't want to send password */
|
|
1361
|
+
|
|
1362
|
+
if (strlen(passwd) == 0)
|
|
1363
|
+
{
|
|
1364
|
+
pool_log("empty password returned by client");
|
|
1365
|
+
return PAM_CONV_ERR;
|
|
1366
|
+
}
|
|
1367
|
+
appdata_ptr = passwd;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
/*
|
|
1371
|
+
* PAM will free this memory in * pam_end()
|
|
1372
|
+
*/
|
|
1373
|
+
*resp = calloc(num_msg, sizeof(struct pam_response));
|
|
1374
|
+
if (!*resp)
|
|
1375
|
+
{
|
|
1376
|
+
/* originally, it was logged as LOG */
|
|
1377
|
+
pool_error("pam_passwd_conv_proc: calloc failed: %s", strerror(errno));
|
|
1378
|
+
return PAM_CONV_ERR;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
(*resp)[0].resp = strdup((char *) appdata_ptr);
|
|
1382
|
+
if ((*resp)[0].resp == NULL)
|
|
1383
|
+
{
|
|
1384
|
+
pool_error("pam_passwd_conv_proc: strdup failed: %s", strerror(errno));
|
|
1385
|
+
exit(1);
|
|
1386
|
+
}
|
|
1387
|
+
(*resp)[0].resp_retcode = 0;
|
|
1388
|
+
|
|
1389
|
+
return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
|
|
1393
|
+
/*
|
|
1394
|
+
* Check authentication against PAM.
|
|
1395
|
+
*/
|
|
1396
|
+
static POOL_STATUS CheckPAMAuth(POOL_CONNECTION *frontend, char *user, char *password)
|
|
1397
|
+
{
|
|
1398
|
+
int retval;
|
|
1399
|
+
pam_handle_t *pamh = NULL;
|
|
1400
|
+
|
|
1401
|
+
/*
|
|
1402
|
+
* Apparently, Solaris 2.6 is broken, and needs ugly static variable
|
|
1403
|
+
* workaround
|
|
1404
|
+
*/
|
|
1405
|
+
pam_passwd = password;
|
|
1406
|
+
|
|
1407
|
+
/*
|
|
1408
|
+
* Set the application data portion of the conversation struct This is
|
|
1409
|
+
* later used inside the PAM conversation to pass the password to the
|
|
1410
|
+
* authentication module.
|
|
1411
|
+
*/
|
|
1412
|
+
pam_passw_conv.appdata_ptr = (char *) password; /* from password above,
|
|
1413
|
+
* not allocated */
|
|
1414
|
+
|
|
1415
|
+
/* Optionally, one can set the service name in pool_hba.conf */
|
|
1416
|
+
if (frontend->auth_arg && frontend->auth_arg[0] != '\0')
|
|
1417
|
+
retval = pam_start(frontend->auth_arg, "pgpool@",
|
|
1418
|
+
&pam_passw_conv, &pamh);
|
|
1419
|
+
else
|
|
1420
|
+
retval = pam_start(PGPOOL_PAM_SERVICE, "pgpool@",
|
|
1421
|
+
&pam_passw_conv, &pamh);
|
|
1422
|
+
|
|
1423
|
+
if (retval != PAM_SUCCESS)
|
|
1424
|
+
{
|
|
1425
|
+
pool_log("could not create PAM authenticator: %s",
|
|
1426
|
+
pam_strerror(pamh, retval));
|
|
1427
|
+
pam_passwd = NULL; /* Unset pam_passwd */
|
|
1428
|
+
return POOL_ERROR;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
retval = pam_set_item(pamh, PAM_USER, user);
|
|
1432
|
+
if (retval != PAM_SUCCESS)
|
|
1433
|
+
{
|
|
1434
|
+
pool_log("pam_set_item(PAM_USER) failed: %s",
|
|
1435
|
+
pam_strerror(pamh, retval));
|
|
1436
|
+
pam_passwd = NULL; /* Unset pam_passwd */
|
|
1437
|
+
return POOL_ERROR;
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
retval = pam_set_item(pamh, PAM_CONV, &pam_passw_conv);
|
|
1441
|
+
if (retval != PAM_SUCCESS)
|
|
1442
|
+
{
|
|
1443
|
+
pool_log("pam_set_item(PAM_CONV) failed: %s",
|
|
1444
|
+
pam_strerror(pamh, retval));
|
|
1445
|
+
pam_passwd = NULL; /* Unset pam_passwd */
|
|
1446
|
+
return POOL_ERROR;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
retval = pam_authenticate(pamh, 0);
|
|
1450
|
+
if (retval != PAM_SUCCESS) /* service name does not exist */
|
|
1451
|
+
{
|
|
1452
|
+
pool_log("pam_authenticate failed: %s",
|
|
1453
|
+
pam_strerror(pamh, retval));
|
|
1454
|
+
pam_passwd = NULL; /* Unset pam_passwd */
|
|
1455
|
+
return POOL_ERROR;
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
retval = pam_acct_mgmt(pamh, 0);
|
|
1459
|
+
if (retval != PAM_SUCCESS)
|
|
1460
|
+
{
|
|
1461
|
+
pool_log("pam_acct_mgmt failed: %s",
|
|
1462
|
+
pam_strerror(pamh, retval));
|
|
1463
|
+
pam_passwd = NULL; /* Unset pam_passwd */
|
|
1464
|
+
return POOL_ERROR;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
retval = pam_end(pamh, retval);
|
|
1468
|
+
if (retval != PAM_SUCCESS)
|
|
1469
|
+
{
|
|
1470
|
+
pool_log("could not release PAM authenticator: %s",
|
|
1471
|
+
pam_strerror(pamh, retval));
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
pam_passwd = NULL; /* Unset pam_passwd */
|
|
1475
|
+
|
|
1476
|
+
return (retval == PAM_SUCCESS ? POOL_CONTINUE : POOL_ERROR);
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
#endif /* USE_PAM */
|
|
1480
|
+
|
|
1481
|
+
static POOL_STATUS CheckMd5Auth(char *username)
|
|
1482
|
+
{
|
|
1483
|
+
char *passwd;
|
|
1484
|
+
|
|
1485
|
+
/* Look for the entry in pool_passwd */
|
|
1486
|
+
passwd = pool_get_passwd(username);
|
|
1487
|
+
|
|
1488
|
+
if (passwd == NULL)
|
|
1489
|
+
{
|
|
1490
|
+
/* Not found. authentication failed */
|
|
1491
|
+
return POOL_ERROR;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
/*
|
|
1495
|
+
* Ok for now. Actual authentication will be performed later.
|
|
1496
|
+
*/
|
|
1497
|
+
return POOL_CONTINUE;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
static bool prestogres_hba_set_session_info(const char* key, const char* value)
|
|
1501
|
+
{
|
|
1502
|
+
pool_debug("presto_external_auth_prog: key:%s value:%s", key, value);
|
|
1503
|
+
|
|
1504
|
+
if (strcmp(key, "server") == 0) {
|
|
1505
|
+
presto_server = value;
|
|
1506
|
+
return true;
|
|
1507
|
+
} else if (strcmp(key, "user") == 0) {
|
|
1508
|
+
presto_user = value;
|
|
1509
|
+
return true;
|
|
1510
|
+
} else if (strcmp(key, "catalog") == 0) {
|
|
1511
|
+
presto_catalog = value;
|
|
1512
|
+
return true;
|
|
1513
|
+
} else if (strcmp(key, "schema") == 0) {
|
|
1514
|
+
presto_schema = value;
|
|
1515
|
+
return true;
|
|
1516
|
+
} else if (strcmp(key, "auth_prog") == 0) {
|
|
1517
|
+
presto_external_auth_prog = value;
|
|
1518
|
+
return true;
|
|
1519
|
+
}
|
|
1520
|
+
|
|
1521
|
+
pool_log("prestogres_hba_set_session_info: found unknown pool_hba config argument '%s'", key);
|
|
1522
|
+
return false;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
static void prestogres_hba_parse_arg(const char* arg)
|
|
1526
|
+
{
|
|
1527
|
+
char *str, *tok;
|
|
1528
|
+
|
|
1529
|
+
if (arg == NULL) {
|
|
1530
|
+
return;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
str = strdup(arg);
|
|
1534
|
+
for (tok = strtok(str, MULTI_VALUE_SEP "\n");
|
|
1535
|
+
tok != NULL; tok = strtok(NULL, MULTI_VALUE_SEP "\n"))
|
|
1536
|
+
{
|
|
1537
|
+
char* p = strchr(tok, ':');
|
|
1538
|
+
if (p == NULL) {
|
|
1539
|
+
break;
|
|
1540
|
+
}
|
|
1541
|
+
*p = '\0';
|
|
1542
|
+
prestogres_hba_set_session_info(tok, p + 1);
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
static POOL_STATUS pool_prestogres_hba_auth_md5(POOL_CONNECTION *frontend)
|
|
1547
|
+
{
|
|
1548
|
+
char *pool_passwd = NULL;
|
|
1549
|
+
static int size;
|
|
1550
|
+
static char password[MAX_PASSWORD_SIZE];
|
|
1551
|
+
static char encbuf[POOL_PASSWD_LEN+1];
|
|
1552
|
+
char salt[4];
|
|
1553
|
+
|
|
1554
|
+
prestogres_hba_parse_arg(frontend->auth_arg);
|
|
1555
|
+
|
|
1556
|
+
pool_passwd = pool_get_passwd(frontend->username);
|
|
1557
|
+
pool_random_salt(salt);
|
|
1558
|
+
|
|
1559
|
+
if (send_md5auth_request(frontend, frontend->protoVersion, salt))
|
|
1560
|
+
{
|
|
1561
|
+
pool_error("pool_prestogres_hba_auth_md5: send_md5auth_request failed");
|
|
1562
|
+
return POOL_ERROR;
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
/* Read password packet */
|
|
1566
|
+
if (read_password_packet(frontend, frontend->protoVersion, password, &size))
|
|
1567
|
+
{
|
|
1568
|
+
pool_debug("pool_prestogres_hba_auth_md5: read_password_packet failed");
|
|
1569
|
+
return POOL_ERROR;
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
pg_md5_encrypt(pool_passwd+strlen("md5"), salt, sizeof(salt), encbuf);
|
|
1573
|
+
if (strcmp(password, encbuf))
|
|
1574
|
+
{
|
|
1575
|
+
/* Password does not match */
|
|
1576
|
+
pool_debug("password does not match: frontend:%s pgpool:%s", password, encbuf);
|
|
1577
|
+
return POOL_ERROR;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
return POOL_CONTINUE;
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
static bool do_external_auth(POOL_CONNECTION* frontend, const char* password)
|
|
1584
|
+
{
|
|
1585
|
+
pid_t pid;
|
|
1586
|
+
int status;
|
|
1587
|
+
|
|
1588
|
+
int stdin_pair[2];
|
|
1589
|
+
int stdout_pair[2];
|
|
1590
|
+
FILE* stdin_writer;
|
|
1591
|
+
FILE* stdout_reader;
|
|
1592
|
+
|
|
1593
|
+
char hostinfo[NI_MAXHOST];
|
|
1594
|
+
char buffer[10*1024];
|
|
1595
|
+
char *pos, *line;
|
|
1596
|
+
|
|
1597
|
+
if (pipe(stdin_pair) < 0) {
|
|
1598
|
+
pool_error("pipe() failed. reason: %s", strerror(errno));
|
|
1599
|
+
exit(1);
|
|
1600
|
+
}
|
|
1601
|
+
if (pipe(stdout_pair) < 0) {
|
|
1602
|
+
pool_error("pipe() failed. reason: %s", strerror(errno));
|
|
1603
|
+
exit(1);
|
|
1604
|
+
}
|
|
1605
|
+
|
|
1606
|
+
pid = fork();
|
|
1607
|
+
if (pid == 0) {
|
|
1608
|
+
close(stdin_pair[1]);
|
|
1609
|
+
close(stdout_pair[0]);
|
|
1610
|
+
if (dup2(stdin_pair[0], 0) < 0) {
|
|
1611
|
+
exit(127);
|
|
1612
|
+
}
|
|
1613
|
+
if (dup2(stdout_pair[1], 1) < 0) {
|
|
1614
|
+
exit(127);
|
|
1615
|
+
}
|
|
1616
|
+
execlp(presto_external_auth_prog, presto_external_auth_prog, NULL);
|
|
1617
|
+
exit(127);
|
|
1618
|
+
} else if (pid == -1) {
|
|
1619
|
+
pool_error("fork() failed. reason: %s", strerror(errno));
|
|
1620
|
+
exit(1);
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
close(stdin_pair[0]);
|
|
1624
|
+
close(stdout_pair[1]);
|
|
1625
|
+
|
|
1626
|
+
stdin_writer = fdopen(stdin_pair[1], "w");
|
|
1627
|
+
if (stdin_writer == NULL) {
|
|
1628
|
+
pool_error("fdopen() failed. reason: %s", strerror(errno));
|
|
1629
|
+
exit(1);
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
stdout_reader = fdopen(stdout_pair[0], "r");
|
|
1633
|
+
if (stdout_pair == NULL) {
|
|
1634
|
+
pool_error("fdopen() failed. reason: %s", strerror(errno));
|
|
1635
|
+
exit(1);
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
fprintf(stdin_writer, "user:%s\n", frontend->username);
|
|
1639
|
+
fprintf(stdin_writer, "password:%s\n", password);
|
|
1640
|
+
fprintf(stdin_writer, "database:%s\n", frontend->database);
|
|
1641
|
+
getnameinfo_all(&frontend->raddr.addr, sizeof(frontend->raddr.addr),
|
|
1642
|
+
hostinfo, sizeof(hostinfo), NULL, 0, NI_NUMERICHOST);
|
|
1643
|
+
fprintf(stdin_writer, "address:%s\n", hostinfo);
|
|
1644
|
+
fprintf(stdin_writer, "\n");
|
|
1645
|
+
fclose(stdin_writer);
|
|
1646
|
+
|
|
1647
|
+
pos = buffer;
|
|
1648
|
+
while (true) {
|
|
1649
|
+
char* const buffer_end = buffer + sizeof(buffer);
|
|
1650
|
+
if (buffer_end <= pos) {
|
|
1651
|
+
break;
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
line = fgets(pos, buffer_end - pos, stdout_reader);
|
|
1655
|
+
if (line == NULL || line[0] == '\n') {
|
|
1656
|
+
break;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
pos += strlen(line);
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
prestogres_hba_parse_arg(buffer);
|
|
1663
|
+
|
|
1664
|
+
if (waitpid(pid, &status, 0) < 0) {
|
|
1665
|
+
pool_error("waitpid() failed. reason: %s", strerror(errno));
|
|
1666
|
+
exit(1);
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
return WIFEXITED(status) && WEXITSTATUS(status) == 0;
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
static POOL_STATUS pool_prestogres_hba_auth_external(POOL_CONNECTION *frontend)
|
|
1673
|
+
{
|
|
1674
|
+
char *passwd;
|
|
1675
|
+
|
|
1676
|
+
prestogres_hba_parse_arg(frontend->auth_arg);
|
|
1677
|
+
|
|
1678
|
+
if (presto_external_auth_prog == NULL) {
|
|
1679
|
+
presto_external_auth_prog = pool_config->presto_external_auth_prog;
|
|
1680
|
+
if (presto_external_auth_prog == NULL) {
|
|
1681
|
+
pool_error("pool_prestogres_hba_auth_external: 'prog:' argument is not set to pool_hba entry for user '%s'", frontend->username);
|
|
1682
|
+
exit(1);
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
sendAuthRequest(frontend, AUTH_REQ_PASSWORD);
|
|
1687
|
+
passwd = recv_password_packet(frontend);
|
|
1688
|
+
|
|
1689
|
+
if (passwd == NULL)
|
|
1690
|
+
return POOL_ERROR; /* client didn't want to send password */
|
|
1691
|
+
|
|
1692
|
+
if (strlen(passwd) == 0) {
|
|
1693
|
+
pool_log("empty password returned by client");
|
|
1694
|
+
return POOL_ERROR;
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
if (!do_external_auth(frontend, passwd)) {
|
|
1698
|
+
return POOL_ERROR;
|
|
1699
|
+
}
|
|
1700
|
+
|
|
1701
|
+
return POOL_CONTINUE;
|
|
1702
|
+
}
|
|
1703
|
+
|
|
1704
|
+
void pool_prestogres_init_session(POOL_CONNECTION *frontend)
|
|
1705
|
+
{
|
|
1706
|
+
if (presto_server == NULL) {
|
|
1707
|
+
presto_server = pool_config->presto_server;
|
|
1708
|
+
}
|
|
1709
|
+
if (presto_user == NULL) {
|
|
1710
|
+
presto_user = frontend->username;
|
|
1711
|
+
}
|
|
1712
|
+
if (presto_catalog == NULL) {
|
|
1713
|
+
presto_catalog = pool_config->presto_catalog;
|
|
1714
|
+
}
|
|
1715
|
+
if (presto_schema == NULL) {
|
|
1716
|
+
presto_schema = pool_config->presto_schema;
|
|
1717
|
+
}
|
|
1718
|
+
pool_debug("pool_prestogres_init_session: presto_server: %s", presto_server);
|
|
1719
|
+
pool_debug("pool_prestogres_init_session: presto_user: %s", presto_user);
|
|
1720
|
+
pool_debug("pool_prestogres_init_session: presto_catalog: %s", presto_catalog);
|
|
1721
|
+
pool_debug("pool_prestogres_init_session: presto_schema: %s", presto_schema);
|
|
1722
|
+
}
|
|
1723
|
+
|