PHP ignores ssl certificates when connecting to MySql - php

Using the code from the PHP manual found here and here
<?php
$mysqli = mysqli_init();
if (!$mysqli) {
die('mysqli_init failed');
}
$mysqli->ssl_set('/path/to/client-key.pem',
'/path/to/client-cert.pem',
'/path/to/ca-cert.pem',
NULL,NULL); //<-- Doesn't matter if the paths are right or wrong
if (!$mysqli->options(MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT = 0')) {
die('Setting MYSQLI_INIT_COMMAND failed');
}
if (!$mysqli->options(MYSQLI_OPT_CONNECT_TIMEOUT, 5)) {
die('Setting MYSQLI_OPT_CONNECT_TIMEOUT failed');
}
if (!$mysqli->real_connect('xx.xx.xx.xx', 'my_user', 'my_password', 'my_db')) {
die('Connect Error (' . mysqli_connect_errno() . ') '
. mysqli_connect_error());
}
echo 'Success... ' . $mysqli->host_info . "\n";
$mysqli->close();
?>
I'm unable to connect to MySql. It gives the following error:
Message: SQLSTATE[28000] [1045] Access denied for user 'my_user'#'xx.xx.xx.xx' (using password: YES) <-- the client IP
I have narrowed down the problem to the line $mysqli->ssl_set(...).
When I pass wrong paths to the certificates it should throw a SSL certificate error according to this post where the user suffered from the same problem instead it throws the same previous Access denied error.
I managed to make a connection using Navicat to the server with the help of the database admin by configuring the ssl connection as follows:
Notes:
My PHP version is 5.3.15
MySql version used on the remote database server is 5.5.13-55
Both Navicat and the PHP code are run from the same PC.
The database admin created a ssl_user specially for testing. This user is denied normal access and must connect using ssl.
No proxies are used.
I tried PDO and it suffers from the same problem.
I tried mysql->connect(), but it throws a bad handshake error and according to some comments in the manual it doesn't work.
Open ssl is enabled from phpinfo()
So the question is why PHP isn't complaining about the wrong paths to the certificates? It seems PHP is ignoring the line where I set the certificate paths!!
UPDATE:
I tried changing the line where I make the connection to explicitly set the port and use MYSQLI_CLIENT_SSL:
$mysqli->real_connect('xx.xx.xx.xx', 'my_user', 'my_password', 'my_db','3306',NULL,MYSQLI_CLIENT_SSL)
However, I got this error:
Warning: mysqli::real_connect(): (08S01/1043): Bad handshake in ...
UPDATE 2:
This is the result of tcpdump-ing from the database server:
0x0040: 3142 6164 2068 616e 6473 6861 6b65 1Bad.handshake
13:16:18.133282 IP (tos 0x8, ttl 64, id 40823, offset 0, flags [DF], proto: TCP (6), length: 52) xx.xx.xx.202.mysql > xx.xx.xx.130.42766: F, cksum 0xf15f (correct), 112:112(0) ack 79 win 46 <nop,nop,timestamp 19516376 3465907>
0x0000: 4508 0034 9f77 4000 4006 c8a7 c0a8 28ca E..4.w#.#.....(.
0x0010: c0a8 2882 0cea a70e b36c 7e8b 7b4d a169 ..(......l~.{M.i
0x0020: 8011 002e f15f 0000 0101 080a 0129 cbd8 ....._.......)..
0x0030: 0034 e2b3 .4..
13:16:18.133433 IP (tos 0x8, ttl 64, id 17337, offset 0, flags [DF], proto: TCP (6), length: 52) xx.xx.xx.130.42766 > xx.xx.xx.202.mysql: F, cksum 0xb695 (correct), 79:79(0) ack 113 win 92 <nop,nop,timestamp 3480910 19516376>
0x0000: 4508 0034 43b9 4000 4006 2466 c0a8 2882 E..4C.#.#.$f..(.
0x0010: c0a8 28ca a70e 0cea 7b4d a169 b36c 7e8c ..(.....{M.i.l~.
0x0020: 8011 005c b695 0000 0101 080a 0035 1d4e ...\.........5.N
0x0030: 0129 cbd8 .)..
13:16:18.133452 IP (tos 0x8, ttl 64, id 40824, offset 0, flags [DF], proto: TCP (6), length: 52) xx.xx.xx.202.mysql > xx.xx.xx.130.42766: ., cksum 0xb6c3 (correct), 113:113(0) ack 80 win 46 <nop,nop,timestamp 19516376 3480910>
0x0000: 4508 0034 9f78 4000 4006 c8a6 c0a8 28ca E..4.x#.#.....(.
0x0010: c0a8 2882 0cea a70e b36c 7e8c 7b4d a16a ..(......l~.{M.j
0x0020: 8010 002e b6c3 0000 0101 080a 0129 cbd8 .............)..
0x0030: 0035 1d4e .5.N
xx.xx.xx.202 is the database server ip.
xx.xx.xx.130 is my PC ip.
UPDATE 3:
I checked for the password length using the following code:
mysql> select length(Password) from mysql.user where User='youruser'
And the password length was 41.
UPDATE 4:
There might be a hint in the error message returned when I connect using the command line via ssh on the remote server (I uploaded the whole project to the remote server):
mysql -u test_ssl -password --ssl-key=/usr/local/apache2/htdocs/certs/client-key.pem --ssl-cert=/usr/local/apache2/htdocs/certs/WRONG-CERTIFICATE.pem
I get the following error:
SSL error: Unable to get certificate from '/usr/local/apache2/htdocs/certs/WRONG-CERTIFICATE.pem'
ERROR 2026 (HY000): SSL connection error ---> notice the error here
If I don't supply any certificates at all I get the following message:
-bash-3.2$ mysql -u test_ssl -password
ERROR 1045 (28000): Access denied for user 'test_ssl'#'localhost' (using password: YES)
Which is the same error I get when I connect using PHP using correct or invalid paths to the certificates!!
Maybe this means something?

At a first glance, you did not set MYSQLI_CLIENT_SSL option to connection.
if (!$mysqli->real_connect('localhost', 'my_user', 'my_password', 'my_db', null, MYSQLI_CLIENT_SSL)) { ... }
Update:
You could try adding $mysqli->options(MYSQLI_OPT_SSL_VERIFY_SERVER_CERT, true);
before $mysqli->ssl_set().
Also, this works for me:
<?php
$pdo = new PDO('mysql:host=ip;dbname=dbname', 'username', 'password', array(
PDO::MYSQL_ATTR_SSL_KEY =>'/etc/mysql/ssl/client-key.pem',
PDO::MYSQL_ATTR_SSL_CERT=>'/etc/mysql/ssl/client-cert.pem',
PDO::MYSQL_ATTR_SSL_CA =>'/etc/mysql/ssl/ca-cert.pem'
)
);
$stmt = $pdo->query("SHOW TABLES;");
$row = $stmt->fetch(PDO::FETCH_ASSOC);
print_r($row);
?>
Update 2:
You may receive a bad handshake if you use old style mysql password (16 bytes long). To check, run the following query:
mysql> select length(Password) from mysql.user where User='youruser'
If you receive 16:
// disable old_passwords:
mysql> SET ##session.old_passwords = 0;
// update password for user used in PHP script:
mysql> SET PASSWORD FOR 'existinguser'#'localhost' = PASSWORD('existingpass');
// check if we have a 41 bytes long password:
mysql> select length(Password) from mysql.user where User='youruser'
And check the connection from PHP script again.

Well we were able to solve the problem, but I'm not sure that this is a practical solution.
First of all we were able to locate the source of the problem which was the MySql client libraries, the ones PHP uses to connect using SSL. PHP had to be complied with those libraries to be able to connect using SSL.
Moreover there was a conflict between the MySql client libraries and OpenSSL libraries.
The only solution to our problem was to re-install everything from scratch. We used a new server, fresh Mysql (latest build) install with all libraries, latest PHP build and latest CentOS distribution.

Related

PHP / connection to Sphinx requires username / password

I am currently trying to connect to Sphinx via PDO or MySqli connector in order to use SphinxQL, however, although Sphinx has no username/password settings and I should be able to connect without the use of such, I get a user/pass error:
Warning: mysqli_connect(): (HY000/1045): Access denied for user ''#'localhost' (using password: NO)
My connection try is as follows (mysqli in this case:)
$con = mysqli_connect('localhost', '', '', '', '9306');
localhost above works with Mysql, I also tried 127.0.0.1 without success (this gave me a connection refused error).
My sphinx conf looks as follows:
listen = 9306:mysql41
searchd is running, and connection via shell works as it should:
[root#localhost vagrant]# mysql -h0 -P 9306
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1 Server version: 2.2.11-id64-release (95ae9a6)
As you can see above, I use Sphinx v.2.2.11
Just in case, I also re-checked the port assignments:
[root#localhost vagrant]# netstat -tulpn | grep LISTEN
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1475/master
tcp 0 0 127.0.0.1:9306 0.0.0.0:* LISTEN 21599/searchd
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 4013/mysqld
Any help is appreciated.
Weird things happen sometimes, without a plausible explanation. As mentioned, I am using vagrant (Centos 7.5) on a windows 10 host. The connection would not work no matter what. After putting it to rest for the day, my PC went to "sleep" mode. The next day, after revoking the system everything worked fine. What can I say ¯_(ツ)_/¯ . Problem solved.
I might be late to the party, but I had the same issue and I have the solution :)
Instead of
$con = mysqli_connect('localhost', '', '', '', '9306');
use it this way
$con = mysqli_connect('localhost:9306', '', '', '');
And it will most likely work :)
I had the same issue on Sphinx Search 3.3.1, with mysql 8.0.
The above solved my issue.

Connection error to mssql from Centos7

I have Centos7 installation with nginx/php5.6. MS SQL 2008 R2 is working on another server.
MSSQL definitely has allowed tcp connection, custom (non domain) user, firewall disabled, and I can connect to it using HeidiSQL and that setting from another Windows machine.
I can telnet to MSSQL from Centos (and I see Log error "Length specified in network packet payload did not match number of bytes read; the connection has been closed. Please contact the vendor of the client library." with centos ip address in MSSQL logs, so no errors here).
I couldn't connect to mssql from centos using php_mssql or sqlcmd;
During sqlcmd:
Microsoft (R) SQL Server Command Line Tool
Version 13.1.0007.0 Linux
[root#***]# /opt/mssql-tools/bin/sqlcmd -S *** -U ***
Password:
Sqlcmd: Error: Microsoft ODBC Driver 13 for SQL Server : Login timeout expired.
Sqlcmd: Error: Microsoft ODBC Driver 13 for SQL Server : TCP Provider: Timeout error [258]. .
Sqlcmd: Error: Microsoft ODBC Driver 13 for SQL Server : Unable to complete login process due to delay in prelogin response.
During php interactive:
php > mssql_connect('***:***', '***','***');
PHP Warning: mssql_connect(): Unable to connect to server: *** in php shell code on line 1
I also tried tsql/freetds:
/etc/freetds.conf has section
[myserver]
host = ***
port = ***
client charset = UTF-8
tds version = 8.0 //also tried 7
[root#*]# tsql -S myserver -U ***
Password:
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
5 //begins to count, i could't understand what does it mean
Also tried to clean it all and install php7.0 with sqlsrv extension - the same problem;
There are some network strange - Centos serv and MSSQL are in different networks, I couldnt ping mssql from that server, but can telnet, i'm using ip, not the host name during connection attempts, so don't think it's a big deal.
Now I am out of ideas where to dig, any suggestions, please?
It was caused by misconfiguration in the network, I don't understand exactly how it is possible - to make telnet connection, but fail to connect normally, but our IT guys repaired this problem in less then half an hour.

php dblib, Error: SQLSTATE[HY000] Unknown host machine name (severity 2)

I am using mac computer OSX 10.9. Freetds and unixODBC are already installed on my computer and added as extension to php , trying to connect to a remote MSSQL server. Below is my connection testing:
<?php
$dbh = new PDO('dblib:host=Hostname ;dbname=Dbname', 'user', 'pw');
if (!$dbh) {
die('Something went wrong while connecting to MSSQL');
}
?>
The error logs file show :
[error] [client 127.0.0.1] PHP Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] Unknown host machine name (severity 2)
What could be the problem ? It seems that my freetds and unixODBC are working fine if I use terminal to connect to the same database as below:
$ isql Hostname user pw
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL>
and
$ tsql -S Hostname -U user
Password:
locale is "en_US.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
1>
here is my freetds.conf
[global]
# TDS protocol version
tds version = 8.0
[Hostname]
host = IP
port = 1433
tds version = 8.0
client charset = UTF-8 ##needed on MAC OS X
dump file = /tmp/freetds.log
and my odbc.ini
[Hostname]
#Driver=/usr/local/lib/libtdsodbc.so
Driver = /usr/local/Cellar/freetds/0.91_2/lib/libtdsodbc.so
Trace=No
Server=IP
Port=1433
TDS_Version=8.0
client charset = UTF-8
my phpinfo() shows that the extension has been added, there is dblib in PDO section and pdo_dblib section have driver Flavour enabled freetds.
So what is the problem? Any idea of what I should do ?
Any assistance will be highly appreciated.
here is my odbcinst.ini:
[freetdS]
Description = v0.63 with protocol v8.0
Driver = /usr/local/Cellar/freetds/0.91_2/lib/libtdsodbc.so
I actually solved this question by deleting both mssql.so, pdo_dblib.so in php extension folder, re-download php5.4 , phpize and build both the .so files again and put it back. Then it works.
It seems that the olde pdo_dblib.so file I made pointed to a different freetds.conf somewhere else.
Since it is not possible to debug this by proxy without real files information and you've opted to protect ip addresses and hostnames with dummy text. I am going with the PHP code. The hostname should be a FQDN or an ip address. Not the place holder text from the ini files.
<?php
$dbh = new PDO('dblib:host=[ ip address || example.com || localhost] ;dbname=Dbname', 'user', 'pw');
if (!$dbh)
{
die('Something went wrong while connecting to MSSQL');
}
?>

php 5.4 mssql_connect suddenly stopped working

Environment:
Apache 2.2.9
PHP 5.4.37
freetds 0.91
SQL Server 2008
After last night's round of updates applied from Microsoft my mssql_connect stopped working.
tsql -LH x.x.x.x still shows the server and port correctly
tsql -H x.x.x.x -U user connects fine
I get nothing in the apache log files or the freetds log
Here is the code segment that is failing (critical info changed)
error_reporting(E_ALL); ini_set('display_errors',1);
$con = mssql_connect('server', 'user', 'pass');
var_dump($con);
if (!$con) {
if ( function_exists('error_get_last') ) {
var_dump(error_get_last());
}
die('Could not connect to the server!!'.mssql_get_last_message());
}
And here is the result:
Warning: mssql_connect(): Unable to connect to server: server in /home/....../public_html/states/index.php on line 25
bool(false)array(4) { ["type"]=> int(2) ["message"]=> string(55) "mssql_connect(): Unable to connect to server: server"["file"]=> string(63) "/home/....../public_html/states/index.php"["line"]=> int(25) } Could not connect to the server!!
Please help!
I'm unable to post a comment to ask this, but here is my thoughts.
Obviously it's not connecting to the server outside of the command line, so you'll want to double check its configuration (check the server port, specify the port, etc..)
Is this running from a Win or Unix type OS?
It is Linux. I found a work around for the moment. The problem appears to be on the Windows side where, although a tsql -LH command shows the IP and port, it is not actually answering queries on the port. You get connected to the server via TCP and that is it.
Because the SQL server is multi-homed, I added a secondary connection to the web app server that connects to it over the primary IP.
I'll chase down the IP binding and service issue later. Or maybe just convert it all to mariaDB or Postgres.

Getting a mysql 2002 error only when using localhost (rather than 127.0.0.1) when connecting to mysql with php

I have the following php file:
<?php
function show_error($stage) {
echo "<p>MySql error: " . mysql_error() . '</p>';
echo "<p>ErrorCode: " . mysql_errno() . '</p>';
die($stage);
}
$link = mysql_connect('localhost', 'blog', 'sql-password');
if (!$link) {
show_error('connect');
}
mysql_select_db('blog') or show_error();
$result = mysql_query('select col1 from test_table');
if (!$result) {
show_error('query');
}
$col = mysql_result($result, 0);
echo "<p>Result is: [" . $col . "]</p>";
mysql_close($link);
?>
When I run this, I get error:
MySql error: No such file or directory
ErrorCode: 2002
connect
However, if I change the line
$link = mysql_connect('localhost', 'blog', 'my-password');
to
$link = mysql_connect('127.0.0.1', 'blog', 'my-password');
it all works correctly. How can I fix this so that it works with either localhost or 127.0.0.1, and why does using localhost work differently to 127.0.0.1?
Extra info (some google responses indicated these were important):
the line 127.0.0.1 localhost appears in my /etc/hosts file, and ping localhost works correctly, and hits the 127.0.0.1 address. There are no other lines mentioning localhost in the /etc/hosts file.
I'm running it in Mac OSX Snow Leopard.
Finally, the result of the command stat /tmp/mysql.sock is:
234881044 28829652 srwxrwxrwx 1 _mysql wheel 0 0 "Jul 10 18:29:37 2011" "Jul 10 18:29:37 2011" "Jul 10 18:29:37 2011" "Jul 10 18:29:09 2011" 4096 0 0 /tmp/mysql.sock
The MySQL client magically knows that 'localhost' means the local machine, so it tries to connect to a Unix socket instead of making a network request--which is actually more efficient. The problem here is that you're either not using a Unix socket, or--probably more likely--the MySQL client libraries don't know where to find the Unix socket file.
I wish I could tell you where that configuration lives, but a) I haven't actively used MySQL in over 3 years, and b) I've never used MySQL on OSX.

Categories