1<<if: ZXIDBOOK>> 2<<else: >>PHP Interface to ZXID 3##################### 4<<author: Sampo Kellom�ki (sampo@iki.fi)>> 5<<cvsid: $Id: zxid-php.pd,v 1.7 2010-01-08 02:10:09 sampo Exp $>> 6<<class: article!a4paper!!ZXID-PHP 01>> 7<<define: ZXDOC=ZXID PHP Interface>> 8 9<<abstract: 10 11ZXID.org Identity Management toolkit implements standalone SAML 2.0 and 12Liberty ID-WSF 2.0 stacks. This document describes the PHP glue. 13 14>> 15 16<<maketoc: 1>> 17 181 Introduction 19============== 20 21The PHP glue for ZXID was generated using swig(1), however, the swig 22interface is not a retrofit: the whole ZXID API was designed to 23be easily swiggifiable. 24 25The main aim of the glue is supporting the easy and simple API, see 26<<link:zxid-simple.html: zxid_simple()>> for general 27reference. Only differences and language specifics are covered in this 28document. 29 301.1 Other documents 31------------------- 32 33<<doc-inc.pd>> 34 357 PHP extension php_zxid.so 36=========================== 37 38<<fi: >> 39 40The PHP integration is incomplete due to incomplete support in SWIG 41for php5. However, enough interface exists to get most high level API 42working and thus successfully run an SP. 43 447.1 Installing Binaries or from Package 45--------------------------------------- 46 47TBD (*** WIP) 48 497.2 Building and Installing ZXID PHP extension 50---------------------------------------------- 51 52After building main zxid distribution, say 53 54 make phpzxid 55 56You MUST have php-config(1) in path. If not, try 57 58 make phpzxid PHP_CONFIG=/path/to/php-config 59 60If the extension built successfully, you can use it by copying 61it to a suitable place, e.g. 62 63 make phpzxid_install 64 65The install again uses the php-config(1) to figure out where 66php(1) can find the module. 67 68Next you need to decide whether to run under Apache mod_php 69setup (apache), or as CGI (any web server). 70 71We have tested ZXID with php-5.1.6 and php-5.3.6 (current development 72target as of 20110707). For mod_php operation, the Apache httpd 2.2.3 73and 2.2.19 (current development target as of 20110707) have been 74tested. 75 767.2.1 Running PHP as Apache mod_php 77~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 78 79See <<link:apache.html: Apache recipe>> for how 80to compile Apache to support mod_php. 81 827.2.2 Running PHP as CGI (any web server) 83~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 84 85In the CGI case you generally make sure your CGI script starts like 86 87 #!/usr/bin/php 88 <? 89 dl("php_zxid.so"); # These three lines can go to initialization: they only need to run once 90 $conf = "PATH=/var/zxid/&URL=https://sp1.zxidsp.org:8443/zxidhlo.php"; 91 $cf = zxid_new_conf_to_cf($conf); 92 ?> 93 94The first line makes sure the file is executed with php interpreter. You should 95change it to match the path where your php is installed. You also need to 96make your CGI script executable, e.g: 97 98 chmod a+x mycgi.php 99 100Then you place the CGI script in a directory in the document tree 101of the web site and make sure your http server is configured (permitted) 102to execute CGI scripts in that directory. 103 104One tricky thing that can go wrong is dynamic linking. When you compiled 105the php_zxid.so module, some linking dependencies are usually created. 106Problem arises if some of the dependencies are not in the paths 107allowed for dynamic linking by your web server. The paths allowed 108by web server can easily be different than in your shell and some 109web servers even ignore ~LD_LIBRARY_PATH~ environment variable. Sometimes 110you just have to copy the dependency libraries to one of the allowed 111directories. This is "dirty", but works. See ldconfig(8) and 112section <<see: ZXID-Installing-CannedTutorialRunningZXIDasCGIundermini_httpd-AccessingZXID>> for further information. 113 114You can easily see the dependencies using ldd(1) 115 116 ldd /apps/php/5.1.6/lib/php/extensions/no-debug-non-zts-20050922/php_zxid.so 117 linux-gate.so.1 => (0xffffe000) 118 libpthread.so.0 => /lib/libpthread.so.0 (0xb7796000) 119 libdl.so.2 => /lib/libdl.so.2 (0xb7792000) 120 libcurl.so.3 => /apps/lib/libcurl.so.3 (0xb7611000) 121 libz.so.1 => /apps/lib/libz.so.1 (0xb75fe000) 122 libc.so.6 => /lib/libc.so.6 (0xb74dd000) 123 /lib/ld-linux.so.2 (0x80000000) 124 125In this example the suspect library dependencies are 126/apps/lib/libcurl.so.3 and /apps/lib/libz.so.1 because they are 127outside normal places, i.e. /lib and /usr/lib. 128 129Another thing to remember is that CGI specification requires that the 130~Content-Type~ header and an empty line (to separate headers from 131content) is emitted before the actual page. If this fails to happen, the 132page will mysteriously not appear although your script ran successfully. 133 134Sometimes the debug output can end up in stdout (e.g. somewhere stderr 135was redirected to stdout) and this will garble the returned web page. 136Easy fix is to disable debug output by not supplying ~ZXID_AUTO_DEBUG~. 137See section <<see: ZXID-ZXID_simpleAPI-HelloWorld-AUTOoptions>>. 138 1397.3 Programming with ZXID PHP Extension 140--------------------------------------- 141 142To use the ZXID PHP extension you must add near beginning of your script 143 144 dl("php_zxid.so"); // Load the module 145 146You may need to tweak the paths, or ~LD_LIBRARY_PATH~, to get this to work. 147 148After this, you can use the PHP interface much the same way as you 149would use the C interface. See the distributed zxid.php and 150zxidhlo.php for further usage examples. 151 1527.4 Simple API Using PHP 153------------------------ 154 155(*** also in zxid-php.pd) 156 157The simplest APIs are easy to use and suitable for CGIs where the 158program is restarted anew every time. However in situations where the 159script engine stays alive persistently, it is wasteful to reparse (and 160reallocate) the configuration every time. Consider following PHP 161snippet designed to be used with mod_php: 162 163 01 # Put this in the PHP initialization (it only needs to run once) 164 02 dl("php_zxid.so"); 165 03 $conf = "PATH=/var/zxid/&URL=https://sp1.zxidsp.org:8443/zxiddemo.php"; 166 04 $cf = zxid_new_conf_to_cf($conf); 167 05 <? # For every page that is accessed 168 06 $qs = $_SERVER['REQUEST_METHOD'] == 'GET' 169 07 ? $_SERVER['QUERY_STRING'] 170 08 : file_get_contents('php://input'); 171 09 $res = zxid_simple_cf($cf, -1, $qs, null, 0x1800); 172 10 switch (substr($res, 0, 1)) { 173 11 case 'L': header($res); exit; # Redirect 174 12 case 'n': exit; # already handled 175 13 case 'b': my_send_metadata(); 176 14 case 'e': my_render_login_screen(); 177 15 case 'd': break; # Logged in case -- fall through 178 16 default: error_log("Unknown zxid_simple() res(%s)", res); exit; 179 17 } 180 18 # *** Parse the LDIF in $res into a hash of attributes (see zxidhlo.php) 181 19 182 20 ?> 183 21 <html><title>Protected content, logged in as <$=$attr['cn']$></title> 184 22 ... 185 23 </html> 186 24 <? 187 25 function my_render_login_screen() 188 26 { 189 27 ?> 190 28 <html><title>Please Login Using IdP</title> 191 29 ... 192 30 <?=zxid_idp_select_cf($cf, 0, 0x1800)?> 193 31 ...</html> 194 32 <? exit; }?> 195 196Notes 197 1981. Line 4 creates a system-wide configuration object that is later 199 used by the other API calls 2002. On line 9 we call zxid_simple_cf() with the created object. The 201 second and third argument specify a buffer or string that contains 202 the CGI form data to parse. This may come from ~QUERY_STRING~ of a 203 GET request or from HTTP body of a POST request, as determined 204 on line 8. The -1 means the length of the data should be 205 determined using strlen(3), i.e. C string nul termination. 206 The ~auto_flags == 0x1800~ enables form tag wrapping and debug 207 prints, but otherwise automation is disabled. 2083. Since automation was disabled, we need to handle several 209 cases of possible outcomes from zxid_simple_cf(), on lines 10-17. 2104. From line 18 onwards we handle the login successful or already 211 logged in case. First we split the LDIF entry into a hash 212 so that we can access the attributes easily (e.g. ~cn~ on line 20). 2135. On line 30 we call zxid_idp_list_cf() to create the form 214 for choosing which IdP to use for login (remember that 215 ~auto_flags == 0xc0~ enabled the form wrapper). As can be 216 seen the same configuration object, ~$cf~, is used through out. 217 21814 Integration of Other Libraries with ZXID PHP 219=============================================== 220 22114.2 Pat Patterson's php module 222------------------------------- 223 224(*** this section appears in README.zxid) 225 226Pat Patterson of Sun distributes a pure PHP module (not to be confused 227with Sun's OpenSSO open source effort, with which Pat has some 228contact) that implements some aspects of SAML 2.0. As of May 2007, his 229library provides functionality that, by and large, parallels that of the 230php_zxid module. A major advatage of his module is that it does not have 231C shared library dependency, but beware that he still depends on XML 232parsing and popular crypto libraries (openssl) to be available. These 233assumptions are not onerous, but you should be aware of them in case 234your system differs from main stream deployments. 235 236Overall, Pat's PHP implementation, as of May 2007, is still lacking 237in metadata generation and loading (it does not implement Auto-CoT 238or Well Known Location) and has some rough edges around less frequently 239used parts of the SAML specification. No doubt matters will improve 240over the time. 241 242Pat's library handles only SSO and not ID Web Services. It would be 243possible to extract the discovery bootstrap from SSO using his library 244after which you can use ZXID WSC API to actually call the services. 245 24614.3 Sun OpenSSO 247---------------- 248 249Sun Microsystems distributes an open source implementation of SAML 2.0. 250Their implementation is of primary interest as it provides a freely available 251IdP implementation (as of May 2007 IMNSHO the ZXID SP interface is 252superior to the OpenSSO SP - and since both implement an open standard, 253you can mix ZXID SP with OpenSSO IdP). 254 255Thus, the ZXID to OpenSSO integration reduces to each one acting in its 256role using standard wire protocol - SAML 2.0. 257 25895 FAQ 259====== 260 26195.1 Build and Linking Problems 262------------------------------- 263 26495.1.1 Dry run test 265~~~~~~~~~~~~~~~~~~~ 266 267A good way to test whether php is able to run at all is to simulate 268running of a CGI script by setting few environment variables and 269then invoking the script from command line: 270 271 QUERY_STRING=o=E REQUEST_METHOD=GET php ./zxidhlo.php 272 273The result should be the IdP selection page as HTML. Another test is 274to run o=B to obtain the metadata. 275 27695.1.1 Duplicate symbols 277~~~~~~~~~~~~~~~~~~~~~~~~ 278 279Following types of error messages 280 281 Warning: Function registration failed - duplicate name - hexdec in /a/d/sampo/zxid/zxidhlo.php on line 16 282 283 Warning: zxid: Unable to register functions, unable to load in Unknown on line 0 284 285 Fatal error: Call to undefined function zxid_new_conf_to_cf() in /a/d/sampo/zxid/zxidhlo.php on line 22 286 287Theory: the zxid library has already been loaded in some other way, such as part 288of mod_auth_saml or Net::SAML loading. 289 290<<if: ZXIDBOOK>> 291<<else: >> 292 29396 License 294========== 295 296Copyright (c) 2006-2009 Symlabs (symlabs@symlabs.com), All Rights Reserved. 297Author: Sampo Kellom�ki (sampo@iki.fi) 298 299See file COPYING for complete information. 300 301<<references: 302 303[SAML2core] "Assertions and Protocols for the OASIS Security Assertion Markup Language (SAML) V2.0", Oasis Standard, 15.3.2005, saml-core-2.0-os 304 305>> 306 307<<doc-end.pd>> 308<<notapath: TCP/IP a.k.a xBSD/Unix n/a Perl/mod_perl PHP/mod_php Java/Tomcat>> 309<<EOF: >> 310<<fi: >>