After upgrading from Fedora 14 to Fedora 16, my installation of Apache httpd + PHP + Dolibarr + Postgresql doesn't work: the PHP scripts can't connect to the database while I'm able to connect to the database from command line, using psql and various authentication schemes. /var/log/httpd/error_log is filled with lines such as [Wed Jan 04 23:13:57 2012] [error] [client ::1] PHP Warning: pg_connect(): Unable to connect to PostgreSQL server: could not connect to server: Permission denied\n\tIs the server running on host "localhost" (::1) and accepting\n\tTCP/IP connections on port 5432?\ncould not connect to server: Permission denied\n\tIs the server running on host "localhost" (127.0.0.1) and accepting\n\tTCP/IP connections on port 5432? in /usr/share/dolibarr/htdocs/lib/databases/pgsql.lib.php on line 357, referer: http://localhost/dolibarr/install/check.php [Wed Jan 04 23:13:57 2012] [error] [client ::1] PHP Warning: pg_last_error() expects parameter 1 to be resource, boolean given in /usr/share/dolibarr/htdocs/lib/databases/pgsql.lib.php on line 836, referer: http://localhost/dolibarr/install/check.php There's nothing logged in /var/lib/pgsql/data/pg_log/postgresql-*.log regarding connections.
Using strace, I'm getting socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 12 setsockopt(12, SOL_TCP, TCP_NODELAY, [1], 4) = 0 fcntl(12, F_SETFL, O_RDONLY|O_NONBLOCK) = 0 fcntl(12, F_SETFD, FD_CLOEXEC) = 0 setsockopt(12, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0 connect(12, {sa_family=AF_INET6, sin6_port=htons(5432), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EACCES (Permission denied) close(12) = 0 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 12 setsockopt(12, SOL_TCP, TCP_NODELAY, [1], 4) = 0 fcntl(12, F_SETFL, O_RDONLY|O_NONBLOCK) = 0 fcntl(12, F_SETFD, FD_CLOEXEC) = 0 setsockopt(12, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0 connect(12, {sa_family=AF_INET, sin_port=htons(5432), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EACCES (Permission denied) close(12) = 0
But when I'm starting httpd as root using /usr/bin/httpd -k start instead of systemctl start httpd.service, everything works. With strace I'm getting: socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 12 setsockopt(12, SOL_TCP, TCP_NODELAY, [1], 4) = 0 fcntl(12, F_SETFL, O_RDONLY|O_NONBLOCK) = 0 fcntl(12, F_SETFD, FD_CLOEXEC) = 0 setsockopt(12, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0 connect(12, {sa_family=AF_INET6, sin6_port=htons(5432), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = -1 EINPROGRESS (Operation now in progress) poll([{fd=12, events=POLLOUT|POLLERR}], 1, -1) = 1 ([{fd=12, revents=POLLOUT}]) getsockopt(12, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 getsockname(12, {sa_family=AF_INET6, sin6_port=htons(50963), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0 The PHP application is correctly working.
In fact, my problem is related to selinux: When starting httpd with /usr/bin/httpd -k start, error_log reports: SELinux policy enabled; httpd running as context unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 Instead, when started with systemctl start httpd.service, error_log reports: SELinux policy enabled; httpd running as context system_u:system_r:httpd_t:s0
So I think the fix is to try to convince Dolibarr to connect to Postgresql using local Unix socket /tmp/.s.PGSQL.5432 instead of TCP socket 127.0.0.1:5432 or [::1]:5432.
Yeah, that looks like a selinux problem not a postgres problem; httpd_t ought to be allowed to make this connection. Reassigning.
What AVC's are you seeing? in /var/log/audit/audit.log. I think the problem is the Postgesql sockets are in /tmp rather then in /var/run or /run.
(In reply to comment #6) > What AVC's are you seeing? in /var/log/audit/audit.log. > Oh, I thought I would see them with dmesg (or in /var/log/messages). But here they are: type=SERVICE_START msg=audit(1325715234.546:1332): user pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg=': comm="httpd" exe="/bin/systemd" hostname=? addr=? terminal=? res=success' type=AVC msg=audit(1325715237.030:1333): avc: denied { name_connect } for pid=30650 comm="httpd" dest=5432 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:postgresql_port_t:s0 tclass=tcp_socket type=SYSCALL msg=audit(1325715237.030:1333): arch=c000003e syscall=42 success=no exit=-13 a0=b a1=7f2523a7e300 a2=1c a3=7fffbe735a58 items=0 ppid=30648 pid=30650 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null) type=AVC msg=audit(1325715237.030:1334): avc: denied { name_connect } for pid=30650 comm="httpd" dest=5432 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:postgresql_port_t:s0 tclass=tcp_socket type=SYSCALL msg=audit(1325715237.030:1334): arch=c000003e syscall=42 success=no exit=-13 a0=b a1=7f2523a7dcd0 a2=10 a3=7fffbe735a58 items=0 ppid=30648 pid=30650 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="httpd" exe="/usr/sbin/httpd" subj=system_u:system_r:httpd_t:s0 key=(null) etc. > I think the problem is the Postgesql sockets are in /tmp rather then in > /var/run or /run. It's not a problem with Unix domain socket: it seems it's working fine with them. But when using TCP socket to connect to localhost, Apache HTTPd get is denied rights to connect to 127.0.0.1:5432 or [::1]:5432.
audit2allow -i /tmp/t #============= httpd_t ============== #!!!! This avc can be allowed using one of the these booleans: # httpd_can_network_connect, httpd_can_network_connect_db allow httpd_t postgresql_port_t:tcp_socket name_connect; If I looked at the setroubleshoot I see something like: sealert -a /tmp/t 100% donefound 1 alerts in /tmp/t -------------------------------------------------------------------------------- SELinux is preventing /usr/sbin/httpd from name_connect access on the tcp_socket . ***** Plugin catchall_boolean (47.5 confidence) suggests ******************* If you want to allow HTTPD scripts and modules to connect to the network using any TCP port. Then you must tell SELinux about this by enabling the 'httpd_can_network_connect' boolean. Do setsebool -P httpd_can_network_connect 1 ***** Plugin catchall_boolean (47.5 confidence) suggests ******************* If you want to allow HTTPD scripts and modules to connect to databases over the network. Then you must tell SELinux about this by enabling the 'httpd_can_network_connect_db' boolean. Do setsebool -P httpd_can_network_connect_db 1 ***** Plugin catchall (6.38 confidence) suggests *************************** If you believe that httpd should be allowed name_connect access on the tcp_socket by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: # grep httpd /var/log/audit/audit.log | audit2allow -M mypol # semodule -i mypol.pp # semanage boolean -l | grep http | grep database httpd_can_network_connect_db (off , off) Allow HTTPD scripts and modules to connect to databases over the network. Bottom line. Set the httpd_can_network_connect_db boolean and your good to go. # setsebool -P httpd_can_network_connect_db 1
(In reply to comment #8) > Bottom line. Set the httpd_can_network_connect_db boolean and your good to go. > # setsebool -P httpd_can_network_connect_db 1 That will allow httpd to connect to anything at all, right? That's certainly enough to solve the immediate problem, but I wonder whether it would be sensible to provide another, narrower-in-scope boolean that allows connections to only a few "likely" ports, such as 5432 for postgres and 3306 for mysql. In particular I don't like the idea that there's no way to allow database access without also turning httpd into a potential spam engine (ie, with the ability to connect to remote port 25).
(In reply to comment #8) Thanks for the audit.log analysis and suggestions. But I think there's still a bug in the documentation: in the release-notes from F15 to F16 there's nothing about this new restriction. My Apache HTTPd / PHP / PostgreSQL setup was working fine in F14 but not after upgrading which was a bit disturbing. In the meantime, I have reported a bug against dolibarr and fixed it by using the Unix domain socket for local connections https://doliforge.org/tracker/?func=detail&aid=270&group_id=144
httpd_can_network_connect_db only allows you to connect to the "Database ports" not to the mail ports. sesearch -A -s httpd_t -C -c tcp_socket| grep connect_db WARNING: Policy would be downgraded from version 27 to 26. DT allow httpd_t postgresql_port_t : tcp_socket { recv_msg send_msg name_connect } ; [ httpd_can_network_connect_db ] DT allow httpd_t mssql_port_t : tcp_socket name_connect ; [ httpd_can_network_connect_db ] DT allow httpd_t postgresql_t : tcp_socket recvfrom ; [ httpd_can_network_connect_db ] DT allow httpd_t netlabel_peer_t : tcp_socket recvfrom ; [ httpd_can_network_connect_db ] DT allow httpd_t oracle_port_t : tcp_socket name_connect ; [ httpd_can_network_connect_db ] DT allow httpd_t mysqld_port_t : tcp_socket { recv_msg send_msg name_connect } ; [ httpd_can_network_connect_db ] DT allow httpd_t firebird_port_t : tcp_socket name_connect ; [ httpd_can_network_connect_db ] DT allow httpd_t mysqld_t : tcp_socket recvfrom ; [ httpd_can_network_connect_db ]