ICBC Payment Gateway – PHP infosec.so Dynamic Shared Libraries
Beginning
I’m going to write out all of my process in the hopes that it will help some unfortunate soul fix his/her/their problem because I couldn’t find much if anything! on this ICBC payment Integration.
ICBC is the 2nd largest bank in the world (as of this writing) and as such I figured it would be fairly easy to add a b2c payment gateway integration connecting to their system.
Getting the Documentation and assets
After reciving (via email) 电子商务商户开发指南.zip (Translated: e-commerce_business_development_guide.zip
) Problem was, it was incomplete, and didn’t include the Dynamic Libraries (.so
) for PHP to load.
“Failure Is Not An Option” –Al Reinart and Bill Broyles
After flying to Shanghai to meet the VP of ICBC’s e-commerce banking (e-b2c) I got, on a USB drive, another set of Documentation (V1.0.0.6).
A note on extracting .zip’s with Chinese File Names
Ubuntu/Linux does not like this! Simply using $ unzip 电子商务商户开发指南.zip renders folders with chinese names all sorts of messed up, and ‘un-pathable’ folder names: å·¥è¡b2cç¾åæ¥å£_v2.0.0.1_phpapi_RedHat AES V5_64
After trying to determine the encoding and a bunch of other nonsense 7z magically worked:
$ 7z x 电子商务商户开发指南.zip
Try everything first
After hiring a technical translator, we basically found out that they were the same set I had received before, but this time with the .so
files!
We have EC2 AMI AWS servers hosted in the USA and Aliyun Ubuntu servers hosted in inland China:
Ubuntu – Alyune
$ cat /proc/version Linux version 3.13.0-65-generic (buildd@lgw01-26) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #106-Ubuntu SMP Fri Oct 2 22:08:27 UTC 2015 $ php -v PHP 5.6.18-1+deb.sury.org~trusty+1 (cli) Copyright (c) 1997-2016 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies with Xdebug v2.3.2, Copyright (c) 2002-2015, by Derick Rethans with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
AMI – AWS
$ cat /proc/version Linux version 3.14.48-33.39.amzn1.x86_64 (mockbuild@gobi-build-60007) (gcc version 4.8.2 20140120 (Red Hat 4.8.2-16) (GCC) ) #1 SMP Tue Jul 14 23:43:07 UTC 2015 $ php -v PHP 5.6.19 (cli) (built: Apr 1 2016 22:29:27) Copyright (c) 1997-2016 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
“The Amazon Linux AMI is based on RHEL 5.x and parts of RHEL6. One of our goals is binary compatibility with RHEL 5.x, and therefore CentOS5.x. Astute users will note that our kernel is based on 2.6.34…” –Amazon developer forms
Ubuntu – Alyune
$ php -v PHP 5.6.19-1+deb.sury.org~trusty+1 (cli) Copyright (c) 1997-2016 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies with Xdebug v2.3.2, Copyright (c) 2002-2015, by Derick Rethans with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies $ cat /proc/version Linux version 3.13.0-65-generic (buildd@lgw01-26) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #106-Ubuntu SMP Fri Oct 2 22:08:27 UTC 2015
Macbook Pro – Development Enviroment
$ sw_vers ProductName: Mac OS X ProductVersion: 10.11.4 BuildVersion: 15E65 Xcode Version: 7.3 Obtained from: Mac App Store Last Modified: 3/23/16, 2:41 PM Kind: Intel 64-Bit (Intel): Yes Developer Tools: Version: 7.3 (7D175) $ php -v PHP 5.6.19 (cli) (built: Mar 30 2016 22:34:49) Copyright (c) 1997-2016 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
After trying to load all of the .so
…
I wrote a nice little script to just test them all:
#!/bin/bash INI='/abs/path/to/php/conf.d/ext-icbc_infosec.ini' find . -name '*.so*' | while IFS= read -r FILE; do SO_NAME="$(cd "$(dirname "$FILE")" && pwd)/$(basename "$FILE")" # nm -D $FILE > "$(cd "$(dirname "$FILE")" && pwd)/nm-D.$(basename "$FILE")" echo "[-- $SO_NAME --]" >> $LOG > $INI echo "extension="$SO_NAME"" echo "extension="$SO_NAME"" >> $INI echo "$(php -v | grep "Warning")" echo $OUTPUT echo "" done exit 0
And captured the output by running the script in the root of the LIB directory like such:
$ sudo ./test_api_so.sh >& aliyun.ubuntu-script_log.txt
Note the >&
pipe – had to capture stderr output
Which rendered output on the AMI EC2 AWS server as well as my local Macbook:
Warning: PHP Startup: Invalid library (maybe not a PHP library) ‘/var/www/vhosts/scripts/LIB/Linux/v2.0.0.1_phpapi_RedHat AES V5_64/product/libcrypto.so’ in Unknown on line 0
Advertisement
Answer
Solution!
At first I guessed it might have something to do with mcrypt (that bastard – it’s always causing me grief) but:
$ php -m | grep "mcrypt" mcrypt $ grep -Hrv ";" /etc/php5 | grep -i "extension=" | grep "mcrypt" /etc/php5/mods-available/mcrypt.ini:extension=mcrypt.so
Then I noticed an inconsistency the output of the logs only on the Aliyune hosted Ubuntu:
[– /var/www/vhosts/scripts/LIB/Linux/v2.0.0.1_phpapi_RedHat AES V5_64/product/libinfosec_api.so –] PHP Warning: PHP Startup: Invalid library (maybe not a PHP library) ‘/var/www/vhosts/scripts/LIB/Linux/v2.0.0.1_phpapi_RedHat AES V5_64/product/libinfosec_api.so’ in Unknown on line 0
[– /var/www/vhosts/scripts/LIB/Linux/v2.0.0.1_phpapi_RedHat AES V5_64/product/infosec.so –] PHP Warning: PHP Startup: Unable to load dynamic library ‘/var/www/vhosts/scripts/LIB/Linux/v2.0.0.1_phpapi_RedHat AES V5_64/product/infosec.so’ – libinfosec_api.so: cannot open shared object file: No such file or directory in Unknown on line 0
[– /var/www/vhosts/scripts/LIB/Linux/v2.0.0.1_phpapi_RedHat AES V5_64/product/libcrypto.so.1.0.0 –] PHP Warning: PHP Startup: Invalid library (maybe not a PHP library) ‘/var/www/vhosts/scripts/LIB/Linux/v2.0.0.1_phpapi_RedHat AES V5_64/product/libcrypto.so.1.0.0’ in Unknown on line 0
I thought: that’s odd, so I dug into it. This kaizou article was infinatly helpful in producing the following output:
$ readelf -d infosec.so Dynamic section at offset 0x3028 contains 22 entries: Tag Type Name/Value 0x0000000000000001 (NEEDED) Shared library: [libinfosec_api.so] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000000e (SONAME) Library soname: [infosec.so] $ ldd infosec.so linux-vdso.so.1 => (0x00007fffd5fc6000) libinfosec_api.so => not found libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f72ceb09000) /lib64/ld-linux-x86-64.so.2 (0x00007f72ceece000) $ ldd libinfosec_api.so linux-vdso.so.1 => (0x00007ffed7f56000) libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f48ecf77000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f48ecbb2000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f48ec9ae000) /lib64/ld-linux-x86-64.so.2 (0x00007f48ed352000)
Credit: IcePHP cannot open shared object file: No such file or directory in Unknown on line 0
You See it! $ ldd infosec.so … libinfosec_api.so => not found. I was onto something.
Looking into runtime inclusion of Dynamic Libraries
$ sudo ldconfig -v ... /usr/lib:
Credit: https://unix.stackexchange.com/a/210521
Found the problem
So, the problem wasn’t that I wasn’t following the instructions correctly, but that ICBC had linked their Dynamic .so Library wrong! And hadn’t included any documentation about it!
So, I copied v2.0.0.1_phpapi_RedHat AES V5_64/product/libinfosec_api.so
to /usr/lib/
, moved the corrosponding infosec.so
to the php modules directory (was absolutly not going to have problems with permissions or other server shenanigans) and re-added the PHP extension:
extension=”/usr/lib/php5/20131226/infosec.so”
$ php -v Warning: PHP Startup: infosec: Unable to initialize module Module compiled with module API=20100525 PHP compiled with module API=20131226 These options need to match in Unknown on line 0 PHP 5.6.19-1+deb.sury.org~trusty+1 (cli) Copyright (c) 1997-2016 The PHP Group Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies with Xdebug v2.3.2, Copyright (c) 2002-2015, by Derick Rethans with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies
AHHAA!!! — Conclusion
That’s an error that’s been around forever! So the real problem wasn’t that the docs were in a foreign language, or that the 2nd biggest bank in the world has incomplete documentation (but really, missing that your module depends on another custom module… really? Has this ever worked before?) but that the custom module was compiled for a different PHP version.
An appropriate meme:
// #micdrop