<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>www.devco.net</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/" />
    <link rel="self" type="application/atom+xml" href="http://www.devco.net/fb-rss2.0.xml" />
    <id>tag:www.devco.net,2008-08-23://1</id>
    <updated>2008-10-13T08:27:53Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.21-en</generator>

<entry>
    <title>Devolo dLAN Homeplug Networking</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/10/11/devolo_dlan_homeplug_networking.php" />
    <id>tag:www.devco.net,2008://1.438</id>

    <published>2008-10-11T21:20:14Z</published>
    <updated>2008-10-13T08:27:53Z</updated>

    <summary><![CDATA[I live in a pretty typical for London double story house, my study is upstairs with TV etc downstairs. &nbsp; Till now I just use a Wireless N router to get connectivity downstairs but it's proven to be less than reliable.&nbsp; Additionally my ADSL router was upstairs - but on an extension and not on the main plug, it's a recipe for disaster.I've considered many options, long cables and all sorts of things like this.&nbsp; Today while wandering through PC shops trying to find a decent USB reader I again noticed the Homeplug devices and thought I'll give them a try.I bought 3 units of the Devolo dLAN 200 AVeasy units, they are 200Mbps maximum devices and support all sorts of fancy things like AES Encryption and basically an ACL of sorts to only allow certain devices to talk to each other.&nbsp; You can essentially create a VLAN by giving groups of devices different passwords etc.At first I was fairly sceptical but figured it's worth a shot, I am glad to say the devices totally exceeded my wildest expectations.Installation was a breeze, pop them into the wall, plug in cables and it all just work.&nbsp; Of course it is not secured by default so I went digging through their site, the docs and so forth is pretty crap to say the least but I found software for Linux, Windows and OS X to manage them.&nbsp; Each device has a security id on the back and you just type the keys for all your devices into the app and provide a password.&nbsp; This gets used to secure the network with AES.I have now moved my router and firewall machine downstairs to the main socket - ADSL is now much stabler - and have moved the Wifi router downstairs too via the Devolo units.&nbsp; Overall the whole setup just works great, even my Xbox is working great again after my old Wireless Bridge died.I use a 1GB switch on my LAN and get around 0.3ms ping times in general, if I ping a device on the other end of the Devolo units ping times are around 4ms, transfer speeds over the units are around 7MB/sec when using scp, these figures are very respectable and much better than I had hoped for in the past while considering them.At +- 50 GBP per unit and the sacrifice of a wall socket its a pretty expensive solution (other manufacturers apparently have ones that act as a network and power adapter so you don't waste a port) but for me this has proven to be an excellent solution and completely sorted out my network reliability issues. ]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Usefull Things" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="networking" label="networking" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[I live in a pretty typical for London double story house, my study is upstairs with TV etc downstairs. &nbsp; Till now I just use a Wireless N router to get connectivity downstairs but it's proven to be less than reliable.&nbsp; Additionally my ADSL router was upstairs - but on an extension and not on the main plug, it's a recipe for disaster.<br /><br />I've considered many options, long cables and all sorts of things like this.&nbsp; Today while wandering through PC shops trying to find a decent USB reader I again noticed the Homeplug devices and thought I'll give them a try.<br /><br />I bought 3 units of the <a href="http://www.devolo.co.uk/uk_EN/produkte/dLAN/dlan200aveasy.html">Devolo dLAN 200 AVeasy</a> units, they are 200Mbps maximum devices and support all sorts of fancy things like AES Encryption and basically an ACL of sorts to only allow certain devices to talk to each other.&nbsp; You can essentially create a VLAN by giving groups of devices different passwords etc.<br /><br />At first I was fairly sceptical but figured it's worth a shot, I am glad to say the devices totally exceeded my wildest expectations.<br /><br />Installation was a breeze, pop them into the wall, plug in cables and it all just work.&nbsp; Of course it is not secured by default so I went digging through their site, the docs and so forth is pretty crap to say the least but I found software for Linux, Windows and OS X to manage them.&nbsp; Each device has a security id on the back and you just type the keys for all your devices into the app and provide a password.&nbsp; This gets used to secure the network with AES.<br /><br />I have now moved my router and firewall machine downstairs to the main socket - ADSL is now much stabler - and have moved the Wifi router downstairs too via the Devolo units.&nbsp; Overall the whole setup just works great, even my Xbox is working great again after my old Wireless Bridge died.<br /><br />I use a 1GB switch on my LAN and get around 0.3ms ping times in general, if I ping a device on the other end of the Devolo units ping times are around 4ms, transfer speeds over the units are around 7MB/sec when using scp, these figures are very respectable and much better than I had hoped for in the past while considering them.<br /><br />At +- 50 GBP per unit and the sacrifice of a wall socket its a pretty expensive solution (other manufacturers apparently have ones that act as a network and power adapter so you don't waste a port) but for me this has proven to be an excellent solution and completely sorted out my network reliability issues.<br /> ]]>
        
    </content>
</entry>

<entry>
    <title>Layeredtech&apos;s thanks to old customers</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/10/01/layeredtechs_thanks_to_old_customers.php" />
    <id>tag:www.devco.net,2008://1.437</id>

    <published>2008-10-01T20:52:05Z</published>
    <updated>2008-10-01T21:02:18Z</updated>

    <summary><![CDATA[I have been a customer of Layeredtech for years, at present I have only 2 machines there but at times I've had 7 or 8.&nbsp; My one machine is pretty old, I think I got it circa 2002 or so and it's been doing well, same hardware etc.Yesterday I received the following email from them:Layered Tech is committed to being the leader of the Hosted
Infrastructure market by providing our customers with the best products
backed by the best service. &nbsp;In an effort to improve our customer
experience, we have determined that a small number of existing servers
will need to be relocated from their current data center. &nbsp;As you are
receiving this message, we have identified that you have one or more
servers in the in area of the Savvis facility that will need to be
moved. &nbsp;It is our intention to minimize any interruption in service and
we will do our best to work within predetermined time frames that are
convenient to you.Due to the form factor (chassis type) of
this server, we will need to migrate your data to a new server. We will
work with you so that the impact is as minimal as possible. &nbsp; Below
are the servers that are affected by this migration. &nbsp;Please respond to
this message acknowledging the need to relocate your server(s). &nbsp;At
that point, we will move this ticket to our Operations Department where
we will work with you on a migration schedule. From reading this you might assume they will assist you with the migrate and this is a notice of an impending change, perhaps a month or two from now?In reality the situation is that no, they will not help you migrate your data.&nbsp; They want you to take out a contract for a new machine and then migrate your data yourself - something which even at best will take 5 to 10 hours on oldish machines like this.They do not offer any compensation, and when pressed on that point only offer 1 month...the cherry on the cake is that all this has to be done for 18 days from now, in effect they are terminating your old machine forcing you to take a new one and doing it with less than the agreed 30 days notice.&nbsp; Like it or not. The sales person who has been coordinating this from their side is incredibly unhelpful and frankly useless, only after much pushing back by me do I even get a hint that anything other than do-it-yourself migration is an option, at this point still waiting for details.This kind of disregard for customers is typical of large hosting centres, they have thousands of customers and their hard handed handling of their customers is acceptable because at worse they'll loose a fraction of a percentage of customers, so being unhelpful really does pay off for them since most people will probably just take this crap.This is shockingly poor service, if you value your data, avoid Layeredtech. ]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Front Page" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Rantings" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="hosting" label="hosting" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="layeredtech" label="layeredtech" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[I have been a customer of <a href="http://www.layeredtech.com/">Layeredtech</a> for years, at present I have only 2 machines there but at times I've had 7 or 8.&nbsp; My one machine is pretty old, I think I got it circa 2002 or so and it's been doing well, same hardware etc.<br /><br />Yesterday I received the following email from them:<br /><br /><blockquote>Layered Tech is committed to being the leader of the Hosted
Infrastructure market by providing our customers with the best products
backed by the best service. &nbsp;In an effort to improve our customer
experience, we have determined that a small number of existing servers
will need to be relocated from their current data center. &nbsp;As you are
receiving this message, we have identified that you have one or more
servers in the in area of the Savvis facility that will need to be
moved. &nbsp;It is our intention to minimize any interruption in service and
we will do our best to work within predetermined time frames that are
convenient to you.<br /><br /><br />Due to the form factor (chassis type) of
this server, we will need to migrate your data to a new server. We will
work with you so that the impact is as minimal as possible. &nbsp; <br /><br />Below
are the servers that are affected by this migration. &nbsp;Please respond to
this message acknowledging the need to relocate your server(s). &nbsp;At
that point, we will move this ticket to our Operations Department where
we will work with you on a migration schedule. <br /></blockquote>From reading this you might assume they will assist you with the migrate and this is a notice of an impending change, perhaps a month or two from now?<br /><br />In reality the situation is that no, they will not help you migrate your data.&nbsp; They want you to take out a contract for a new machine and then migrate your data yourself - something which even at best will take 5 to 10 hours on oldish machines like this.<br /><br />They do not offer any compensation, and when pressed on that point only offer 1 month...the cherry on the cake is that all this has to be done for 18 days from now, in effect they are terminating your old machine forcing you to take a new one and doing it with less than the agreed 30 days notice.&nbsp; Like it or not. <br /><br />The sales person who has been coordinating this from their side is incredibly unhelpful and frankly useless, only after much pushing back by me do I even get a hint that anything other than do-it-yourself migration is an option, at this point still waiting for details.<br /><br />This kind of disregard for customers is typical of large hosting centres, they have thousands of customers and their hard handed handling of their customers is acceptable because at worse they'll loose a fraction of a percentage of customers, so being unhelpful really does pay off for them since most people will probably just take this crap.<br /><br />This is shockingly poor service, if you value your data, avoid Layeredtech.<br /><br /> ]]>
        
    </content>
</entry>

<entry>
    <title>flashpolicyd 2.0</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/06/27/flashpolicyd_20.php" />
    <id>tag:www.devco.net,2008://1.434</id>

    <published>2008-06-27T17:57:59Z</published>
    <updated>2008-06-27T18:14:10Z</updated>

    <summary><![CDATA[I wrote a multi threaded server for Adobe Flash Policy requests, some background from Adobe:Since policy files were first introduced, Flash Player has
		    recognized /crossdomain.xml as a master location for URL policy files. However, prior to version 9,0,115,0,
		    Flash Player did not recognize a fixed master location for socket policy files.
		    Flash Player 9,0,115,0 introduces a concept of socket master policy files,
		    which are served from the fixed TCP port number 843. If your application currently requires /crossdomain.xml files to work properly while making Socket requests you should pay close attention to this, as of the current latest version of Flash Player your application will STOP working if you do not run a policy server.&nbsp; You need to read this link and take appropriate action.The servers that Adobe provides are not full featured so I set out to write one, the resulting server can be found on my wiki at http://www.devco.net/pubwiki/FlashPolicyd I will regularly post updates here.A quick feature list:Serves XML files on port 834 using the Adobe protocolMulti Threaded for performance, but limited due to Ruby's green threads, testing did not find this to be a problem thoughSupports logging to a log file, debug mode can be toggled on the fly via Unix signalsDebugging information such as thread lists can be dumped using Unix signalsAdjustable frequency of status messages showing amount of connections, problematic ones and current connection countsThe tar ball includes the main daemon, a Red Hat compatible init script, a standard Nagios monitoring script and a Puppet module for installation on a Red Hat machine.You need just the basic Ruby installed, I suggest Ruby newer than 1.8.1 due to bugs in the Logger class on 1.8.1.Version 2 can be downloaded at http://www.devco.net/code/flashpolicyd-2.0.tgz ]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Code" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="code" label="code" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="flashpolicyd" label="flashpolicyd" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="programming" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[I wrote a multi threaded server for <a href="http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_04.html">Adobe Flash Policy</a> requests, some background from Adobe:<br /><br /><blockquote>Since policy files were first introduced, Flash Player has
		    recognized <kbd>/crossdomain.xml</kbd> as a master location for URL policy files. However, prior to version 9,0,115,0,
		    Flash Player did not recognize a fixed master location for socket policy files.
		    Flash Player 9,0,115,0 introduces a concept of <em>socket master policy files</em>,
		    which are served from the fixed TCP port number 843. <br /></blockquote>If your application currently requires <i>/crossdomain.xml</i> files to work properly while making Socket requests you should pay close attention to this, as of the current latest version of Flash Player your application will <b>STOP</b> working if you do not run a policy server.&nbsp; You need to <a href="http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_04.html">read this link</a> and take appropriate action.<br /><br />The servers that Adobe provides are not full featured so I set out to write one, the resulting server can be found on my wiki at <a href="http://www.devco.net/pubwiki/FlashPolicyd">http://www.devco.net/pubwiki/FlashPolicyd</a> I will regularly post updates here.<br /><br />A quick feature list:<br /><br /><ul><li>Serves XML files on port 834 using the Adobe protocol</li><li>Multi Threaded for performance, but limited due to Ruby's green threads, testing did not find this to be a problem though<br /></li><li>Supports logging to a log file, debug mode can be toggled on the fly via Unix signals</li><li>Debugging information such as thread lists can be dumped using Unix signals</li><li>Adjustable frequency of status messages showing amount of connections, problematic ones and current connection counts</li></ul>The tar ball includes the main daemon, a Red Hat compatible init script, a standard Nagios monitoring script and a Puppet module for installation on a Red Hat machine.<br /><br />You need just the basic Ruby installed, I suggest Ruby newer than 1.8.1 due to bugs in the Logger class on 1.8.1.<br /><br />Version 2 can be downloaded at <a href="http://www.devco.net/code/flashpolicyd-2.0.tgz">http://www.devco.net/code/flashpolicyd-2.0.tgz</a><br /> ]]>
        
    </content>
</entry>

<entry>
    <title>Adventures with Ruby</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/06/26/adventures_with_ruby.php" />
    <id>tag:www.devco.net,2008://1.433</id>

    <published>2008-06-26T21:27:46Z</published>
    <updated>2008-06-26T22:35:24Z</updated>

    <summary><![CDATA[Some more about my continuing experiences with ruby, in my last post I saidthe language does what you'd expect and as you'll see in my next post
spending a week with it on and off is enough to write a capable multi
threaded socket server.As it turns out I quickly lived to regret saying that.&nbsp; Soon after I hit publish I started running into some problems with the very same socket server.A bit of background, Adobe has made a change to how things work moving away from their previous crossdomain.xml file served over HTTP for cross domain authorization to a new model that requires you to run a special TCP server on port 834 serving up XML over a special protocol.&nbsp; I won't go into how brain dead I think this is, suffice to say I needed to run one of those for a client.&nbsp; Adobe of course does provide a server for this, but it has some issues, I chose the simplest of their examples - Perl under xinetd - and quickly discovered that it has no concept of timeouts, or anything that doesn't speak it's protocol.&nbsp; The end result is that you just end up with a ever growing number of perl stuff running waiting around for ages.I took this as a challenge to write something real under Ruby using it as a learning experience as well, so set out to write a multi threaded server for this.&nbsp; At first glance it looks almost laughably trivial:&nbsp; The Ruby STL includes GServer - a very nice class that does the hard work of thread management for you, you just inherit from it and supply the logic for your protocol and let it do the rest, awesome.I wrote this, put in logging, options parsing and all the various bits I needed, tested it locally - 10 concurrent workers doing 200,000 requests and it served it in no time at all with limited CPU impact. I then wrote RC scripts, config files and all that and deployed it at my client.Real soon after deploying it I noticed the wheels came off a bit.&nbsp; I, out of curiosity, put in some regular logging that would print lines like:Jun 23 08:23:37 xmpp1 flashpolicyd[7610]: Had 10042 clients of which 285 were bogus. Uptime 0 days 14 hours 2 min. 23 client(s) connected now.Note in that line how it claims to have 23 connections at present? That's complete b/s, I added the ability to dump actual created threads and there just weren't enough threads for 23 clients and the TCP stack agreed...Turns out gserver has issues handling bad network connections - my clients are over GPRS, Modems, and all sorts - and it seems threads die without GServer removing them from it's list of active connections.This is a small problem except that GServer uses the connection count towards figuring out if you've hit its max connections setting.&nbsp; So while I could just set that to some huge figure, it does indicate theres a memory leak - array grows for ever.&nbsp; Not to mention it just leaving me with a bad taste in my mouth over the quality of my new and improved solution.Naturally I gave up on GServer I didn't feel like installing all sorts of Gems on the servers so figured I'll just write my own thread handling.&nbsp; While it's not trivial its by far not the most complex thing I've ever done.&nbsp; Happy in this case with a bit of wheel reinventing for the sake of learning.&nbsp; I chose to use the Ruby STL Logger Library for logging and even added the ability to alter log level on the fly through sending signals to the process, very nice and I were able to re-use much of the option parsing code etc from my previous attempt so this only took a few hours.I did the development on my Mac using TextMate - the really kick arse Mac text editor that has nice Ruby support - the Mac is on Ruby 1.8.6.&nbsp; I intended to run this on RHEL 4 and 5, they have Ruby 1.8.1 and 1.8.5 respectively, so I was really setting myself up for problems all of my own making.Turn out Logger has a bug, fixed here in revision 6262 without any useful svn log, that only bit me on the RHEL 4 machine.&nbsp; It would open the initial log correctly with line buffering enabled, but once it rotates the log the new log and subsequent ones wouldn't have line buffering.&nbsp; Which in my case means I get log lines showing up once every 5 hours!This sux a lot, and it's unlikely that RedHat will backport such a small little thing, and since RedHat 4 will be here till 2012 I guess I'll just have to patch it myself or move to RedHat 5 on this server, something I planned to do anyway.So something that should have been fairly trivial has turned into a bit of a pain, not really Ruby's fault that I am using 1.8.1 when much newer versions are out, but not nice regardless.&nbsp; At the end of it all my flash server is working really well and handling clients perfectly with no leaking or anything badI, [2008-06-26T23:02:36.607920 #22532]&nbsp; INFO -- : -604398464: Had 15611 clients of which 423 were bogus. Uptime 0 days 13 hours 41 min. 0 connection(s) in use now.Those bogus clients are ones that timeout or just otherwise never complete a request, these were the ones that would trip up GServer in the past.Once I've done documenting it I'll be releasing the flash server here ]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Code" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Front Page" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="adobe" label="adobe" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="programming" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[Some more about my continuing experiences with ruby, in my last post I said<br /><br /><blockquote>the language does what you'd expect and as you'll see in my next post
spending a week with it on and off is enough to write a capable multi
threaded socket server.<br /><br /></blockquote>As it turns out I quickly lived to regret saying that.&nbsp; Soon after I hit publish I started running into some problems with the very same socket server.<br /><br />A bit of background, <a href="http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_04.html">Adobe has made a change</a> to how things work moving away from their previous <i>crossdomain.xml</i> file served over HTTP for cross domain authorization to a new model that requires you to run a special TCP server on port 834 serving up XML over a special protocol.&nbsp; I won't go into how brain dead I think this is, suffice to say I needed to run one of those for a client.&nbsp; Adobe of course does provide a server for this, but it has some issues, I chose the simplest of their examples - Perl under xinetd - and quickly discovered that it has no concept of timeouts, or anything that doesn't speak it's protocol.&nbsp; The end result is that you just end up with a ever growing number of perl stuff running waiting around for ages.<br /><br />I took this as a challenge to write something real under Ruby using it as a learning experience as well, so set out to write a multi threaded server for this.&nbsp; At first glance it looks almost laughably trivial:&nbsp; The Ruby STL includes <a href="http://www.ruby-doc.org/stdlib/libdoc/gserver/rdoc/index.html">GServer</a> - a very nice class that does the hard work of thread management for you, you just inherit from it and supply the logic for your protocol and let it do the rest, awesome.<br /><br />I wrote this, put in logging, options parsing and all the various bits I needed, tested it locally - 10 concurrent workers doing 200,000 requests and it served it in no time at all with limited CPU impact. I then wrote RC scripts, config files and all that and deployed it at my client.<br /><br />Real soon after deploying it I noticed the wheels came off a bit.&nbsp; I, out of curiosity, put in some regular logging that would print lines like:<br /><br /><blockquote>Jun 23 08:23:37 xmpp1 flashpolicyd[7610]: Had 10042 clients of which 285 were bogus. Uptime 0 days 14 hours 2 min. 23 client(s) connected now.<br /></blockquote><br />Note in that line how it claims to have 23 connections at present? That's complete b/s, I added the ability to dump actual created threads and there just weren't enough threads for 23 clients and the TCP stack agreed...Turns out gserver has issues handling bad network connections - my clients are over GPRS, Modems, and all sorts - and it seems threads die without GServer removing them from it's list of active connections.<br /><br />This is a small problem except that GServer uses the connection count towards figuring out if you've hit its max connections setting.&nbsp; So while I could just set that to some huge figure, it does indicate theres a memory leak - array grows for ever.&nbsp; Not to mention it just leaving me with a bad taste in my mouth over the quality of my new and improved solution.<br /><br />Naturally I gave up on GServer I didn't feel like installing all sorts of Gems on the servers so figured I'll just write my own thread handling.&nbsp; While it's not trivial its by far not the most complex thing I've ever done.&nbsp; Happy in this case with a bit of wheel reinventing for the sake of learning.&nbsp; <br /><br />I chose to use the <a href="http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/">Ruby STL Logger Library</a> for logging and even added the ability to alter log level on the fly through sending signals to the process, very nice and I were able to re-use much of the option parsing code etc from my previous attempt so this only took a few hours.<br /><br />I did the development on my Mac using TextMate - the really kick arse Mac text editor that has nice Ruby support - the Mac is on Ruby 1.8.6.&nbsp; I intended to run this on RHEL 4 and 5, they have Ruby 1.8.1 and 1.8.5 respectively, so I was really setting myself up for problems all of my own making.<br /><br />Turn out Logger has a bug, <a href="http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/lib/logger.rb?view=diff&amp;r1=6262&amp;r2=6178&amp;diff_format=h">fixed here in revision 6262 without any useful svn log</a>, that only bit me on the RHEL 4 machine.&nbsp; It would open the initial log correctly with line buffering enabled, but once it rotates the log the new log and subsequent ones wouldn't have line buffering.&nbsp; Which in my case means I get log lines showing up once every 5 hours!<br /><br />This sux a lot, and it's unlikely that RedHat will backport such a small little thing, and since <a href="http://dag.wieers.com/blog/rhel-backported-one-additional-year">RedHat 4 will be here till 2012</a> I guess I'll just have to patch it myself or move to RedHat 5 on this server, something I planned to do anyway.<br /><br />So something that should have been fairly trivial has turned into a bit of a pain, not really Ruby's fault that I am using 1.8.1 when much newer versions are out, but not nice regardless.&nbsp; At the end of it all my flash server is working really well and handling clients perfectly with no leaking or anything bad<br /><br /><blockquote>I, [2008-06-26T23:02:36.607920 #22532]&nbsp; INFO -- : -604398464: Had 15611 clients of which 423 were bogus. Uptime 0 days 13 hours 41 min. 0 connection(s) in use now.<br /></blockquote><br />Those bogus clients are ones that timeout or just otherwise never complete a request, these were the ones that would trip up GServer in the past.<br /><br />Once I've done documenting it I'll be releasing the flash server here<br /> ]]>
        
    </content>
</entry>

<entry>
    <title>New programming language of choice - Ruby</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/06/21/new_programming_language_of_choice_-_ruby.php" />
    <id>tag:www.devco.net,2008://1.432</id>

    <published>2008-06-21T12:37:24Z</published>
    <updated>2008-06-26T22:35:47Z</updated>

    <summary><![CDATA[I have fallen out of love with Perl some time ago, I cannot point to one specific thing about it that put me off, I think it's just a general un-sexyness about it now.I have been doing some Java and PHP development that was very OOP heavy and have been doing OO coding since school in the Pascal 6 days, I find it's almost become the natural way of thinking when thinking about problems.&nbsp; OO though does not generally translate well to scripting tasks which is what I generally use Perl for so it's not been too bad.I am however a Perl 4 coder, Perl 5's OO syntax really puts me off, I've used it, have written some pluggable systems in the past where plugins were Perl Ojbects, but I've never liked them...with Perl 6 coming (or not) having to relearn a large chunk of Perl is becoming inevitable so I figured I might as well switch.&nbsp; This is a decision I've made ages ago.I could however not decide on where to go from here?&nbsp; There are several contenders out there for scripting languages thesedays and weighing up their merits is a time consuming business for sure.&nbsp; So along came Puppet, I am doing massive amount of Puppet work now for 3 clients and my own systems.&nbsp; Puppet is extendible using Ruby code as it's written in Ruby itself so I think the decision has been made.&nbsp; I still have no interest in using it on the web, but for scripting I've found my new love.I wont go into long examples and discussions about the Ruby Language, but I'll say I have learned in the space of a week on the train and have found it incredibly friendly and usable.&nbsp; The Core and Standard Libraries are rich and modern including out of the box XML, YAML, SOAP, XML-RPC and very powerful networking libraries such as GServer.Documentation has been generally good but I did buy a copy of Beginning Ruby From Novice to Professional which I believe is a awesome introduction to the language, I followed that up with The Ruby Way 2nd Edition and Ruby Cookbook.Beginning Ruby takes you on a gentle stroll through a lot of the major features of the language, shows you Strings, Arrays, Numbers, OO, Threads, Sockets and RPC.&nbsp; It doesn't go too deep into any of these subjects, for instance it does not show much about Mutexes or any locking methods inside threads, but it puts down a very solid framework to go from.The Ruby Way is more task based and goes into more detail about the tasks, returning to the threads example, The Ruby Way discusses Mutexes and shows some of the concurrency issues you can expect, it has a whole chapter devoted to Threading.&nbsp; These two books more than put you in a position to quickly and effectively use any of the online documentation resources so I would greatly recommend this combination.I have skimmed through the Cookbook, it's your typical O'Reilly Cookbook - I mostly bought it because I have 6 or 7 other Cookbook titles and they are all invaluable, I spent an hour with it so far and it looks to live up to this reputation.If you've programmed before in any serious way picking up Ruby should be a walk in the park, the syntax is great, the language does what you'd expect and as you'll see in my next post spending a week with it on and off is enough to write a capable multi threaded socket server. ]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Code" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="programming" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[I have fallen out of love with Perl some time ago, I cannot point to one specific thing about it that put me off, I think it's just a general un-sexyness about it now.<br /><br />I have been doing some Java and PHP development that was very OOP heavy and have been doing OO coding since school in the Pascal 6 days, I find it's almost become the natural way of thinking when thinking about problems.&nbsp; OO though does not generally translate well to scripting tasks which is what I generally use Perl for so it's not been too bad.<br /><br />I am however a Perl 4 coder, Perl 5's OO syntax really puts me off, I've used it, have written some pluggable systems in the past where plugins were Perl Ojbects, but I've never liked them...with Perl 6 coming (or not) having to relearn a large chunk of Perl is becoming inevitable so I figured I might as well switch.&nbsp; This is a decision I've made ages ago.<br /><br />I could however not decide on where to go from here?&nbsp; There are several contenders out there for scripting languages thesedays and weighing up their merits is a time consuming business for sure.&nbsp; <br /><br />So along came Puppet, I am doing massive amount of Puppet work now for 3 clients and my own systems.&nbsp; Puppet is extendible using Ruby code as it's written in Ruby itself so I think the decision has been made.&nbsp; I still have no interest in using it on the web, but for scripting I've found my new love.<br /><br />I wont go into long examples and discussions about the Ruby Language, but I'll say I have learned in the space of a week on the train and have found it incredibly friendly and usable.&nbsp; The Core and Standard Libraries are rich and modern including out of the box XML, YAML, SOAP, XML-RPC and very powerful networking libraries such as <a href="http://www.ruby-doc.org/stdlib/libdoc/gserver/rdoc/classes/GServer.html">GServer</a>.<br /><br />Documentation has been generally good but I did buy a copy of <a href="http://www.amazon.co.uk/Beginning-Ruby-Experts-Voice-Source/dp/1590597664/">Beginning Ruby From Novice to Professional</a> which I believe is a awesome introduction to the language, I followed that up with <a href="http://www.amazon.co.uk/Ruby-Way-Programming-Addison-Wesley-Professional/dp/0672328844/">The Ruby Way 2nd Edition</a> and <a href="http://www.amazon.co.uk/Cookbook-Cookbooks-OReilly-Lucas-Carlson/dp/0596523696">Ruby Cookbook</a>.<br /><br />Beginning Ruby takes you on a gentle stroll through a lot of the major features of the language, shows you Strings, Arrays, Numbers, OO, Threads, Sockets and RPC.&nbsp; It doesn't go too deep into any of these subjects, for instance it does not show much about Mutexes or any locking methods inside threads, but it puts down a very solid framework to go from.<br /><br />The Ruby Way is more task based and goes into more detail about the tasks, returning to the threads example, The Ruby Way discusses Mutexes and shows some of the concurrency issues you can expect, it has a whole chapter devoted to Threading.&nbsp; <br /><br />These two books more than put you in a position to quickly and effectively use any of the online documentation resources so I would greatly recommend this combination.<br /><br />I have skimmed through the Cookbook, it's your typical O'Reilly Cookbook - I mostly bought it because I have 6 or 7 other Cookbook titles and they are all invaluable, I spent an hour with it so far and it looks to live up to this reputation.<br /><br />If you've programmed before in any serious way picking up Ruby should be a walk in the park, the syntax is great, the language does what you'd expect and as you'll see in my next post spending a week with it on and off is enough to write a capable multi threaded socket server.<br /> ]]>
        
    </content>
</entry>

<entry>
    <title>On working from home</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/06/21/on_working_from_home.php" />
    <id>tag:www.devco.net,2008://1.431</id>

    <published>2008-06-21T12:29:46Z</published>
    <updated>2008-06-26T22:36:26Z</updated>

    <summary><![CDATA[I've not been posting much here, work has been incredibly manic the last while, especially I need to still finish off my SSO posts with the last installment, for now though, some thoughts on my work arrangement and freelancing.&nbsp;I have been working from home as self employed since around December (self employed for longer) and as before when I've done many months of home working it has started to get to me.In the past I generally had an office to go to but didn't unless I had to, worked from home when I could, home is nearer to the Data Center than the office and generally home has better workstations.Now as I am self employed I do not have an office to go to and I've also realised that all the reading I have done in the past were generally on the train while commuting, and this is something that I cannot let slip but just do not get around to reading while at home.So I now have an office in London Soho, it is just a desk in a shared office full of other freelancers and startups but for the last 2 weeks I have been pretty happy, I have learned Ruby (more about that in my next post) and I am finding I really enjoy the ritual of going to an office again, but an office where there aren't project managers and other people waiting to harass you, I think that is the main ingredient.I will probably stay at this office till the clocks change for winter time, then I'll be working from home again till the summer.&nbsp; The main thing is I have the freedom to choose now and that more than anything is what I love about self employment. ]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Front Page" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="freelancing" label="freelancing" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="work" label="work" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[I've not been posting much here, work has been incredibly manic the last while, especially I need to still finish off my SSO posts with the last installment, for now though, some thoughts on my work arrangement and freelancing.<br />&nbsp;<br />I have been working from home as self employed since around December (self employed for longer) and as before when I've done many months of home working it has started to get to me.<br /><br />In the past I generally had an office to go to but didn't unless I had to, worked from home when I could, home is nearer to the Data Center than the office and generally home has better workstations.<br /><br />Now as I am self employed I do not have an office to go to and I've also realised that all the reading I have done in the past were generally on the train while commuting, and this is something that I cannot let slip but just do not get around to reading while at home.<br /><br />So I now have an office in London Soho, it is just a desk in a shared office full of other freelancers and startups but for the last 2 weeks I have been pretty happy, I have learned Ruby (more about that in my next post) and I am finding I really enjoy the ritual of going to an office again, but an office where there aren't project managers and other people waiting to harass you, I think that is the main ingredient.<br /><br />I will probably stay at this office till the clocks change for winter time, then I'll be working from home again till the summer.&nbsp; The main thing is I have the freedom to choose now and that more than anything is what I love about self employment.<br /> ]]>
        
    </content>
</entry>

<entry>
    <title>Rework of puppet facts for /etc/facts.txt</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/06/16/rework_of_puppet_facts_for_etcfactstxt.php" />
    <id>tag:www.devco.net,2008://1.430</id>

    <published>2008-06-16T10:47:31Z</published>
    <updated>2008-06-26T22:36:49Z</updated>

    <summary><![CDATA[Previously I blogged a custom fact that reads /etc/facts.txt to build up some custom facts for use in Puppet manifests, well I've since learned a thing or two about Ruby and have improved the code, new code below:if File.exists?("/etc/facts.txt")        File.open("/etc/facts.txt").each do |line|                var = nil                value = nil                var = $1 and val = $2 if line =~ /^(.+)=(.+)$/                if var != nil &amp;&amp; val != nil                        Facter.add(var) do                                setcode { val }                        end                end        endendAs I mentioned previously I knew the code was horrible and had a whole redundant loop in it but couldn't get it going otherwise.&nbsp; The big change is in choice of variable names to use inside the setcode, sees value must be a reserved word or something, so now the code is much cleaner.]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Code" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[Previously <a href="http://www.devco.net/archives/2008/04/17/easy_permachine_custom_facts_for_puppet.php">I blogged a custom fact</a> that reads /etc/facts.txt to build up some custom facts for use in Puppet manifests, well I've since learned a thing or two about Ruby and have improved the code, new code below:<br /><br /><blockquote><pre>if File.exists?("/etc/facts.txt")<br /><span class="anchor" id="line-9"></span>        File.open("/etc/facts.txt").each do |line|<br /><span class="anchor" id="line-10"></span>                var = nil<br /><span class="anchor" id="line-11"></span>                value = nil<br /><span class="anchor" id="line-12"></span><br /><span class="anchor" id="line-13"></span>                var = $1 and val = $2 if line =~ /^(.+)=(.+)$/<br /><span class="anchor" id="line-14"></span><br /><span class="anchor" id="line-15"></span>                if var != nil &amp;&amp; val != nil<br /><span class="anchor" id="line-16"></span>                        Facter.add(var) do<br /><span class="anchor" id="line-17"></span>                                setcode { val }<br /><span class="anchor" id="line-18"></span>                        end<br /><span class="anchor" id="line-19"></span>                end<br /><span class="anchor" id="line-20"></span>        end<br /></pre></blockquote><blockquote><pre><span class="anchor" id="line-21"></span>end<br /><br /></pre></blockquote>As I mentioned previously I knew the code was horrible and had a whole redundant loop in it but couldn't get it going otherwise.&nbsp; The big change is in choice of variable names to use inside the setcode, sees <i>value</i> must be a reserved word or something, so now the code is much cleaner.<br /><br /><pre></pre>]]>
        
    </content>
</entry>

<entry>
    <title>Designing a Single Sign On system - part 3</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/05/04/designing_a_single_sign_on_system_-_part_3.php" />
    <id>tag:www.devco.net,2008://1.429</id>

    <published>2008-05-04T10:55:50Z</published>
    <updated>2008-05-04T15:49:04Z</updated>

    <summary><![CDATA[This is the 3rd part of my ongoing series of posts about designing a
simple Single Signon System for PHP, you should read part 1 and 2 first.Today we look a bit more about the general information flow between browser, target web site and the SSO Server.&nbsp; We will use the term Secure Site for the target site, lets say a corporate intranet.The following diagram shows the flow of information, the information flows via the browser using redirects etc.First a few words on the requierd bits of information before this exchange can happen.The
Secure Site has a pre-shared key (PSK) that the SSO Server assigns,
this key gets hardcoded in the Secure Site and kept private, it never
gets passed between the parties during normal authentication requests.The Secure Site has a siteid
that is simply a number that uniquely identifies it to the SSO Server.&nbsp;
This too gets assigned by the SSO Server and does not change for the
life time of the site.Encryption gets done using a simple symmetrical algorithm, the PSK is the passphrase.The
SSO server knows what domain name a site is in, the SSO Server will use
this to validate auth requests and generate redirects based on this
domain name only.Now on to the actual information flow, this demonstrates the flow for a first time visit of an unauthenticated user, future visits will be exactly like any cookie based auth system where the user will not interact with the SSO server at all:The user tries to access the Secure SiteSecure Site generate a unique single use token, and saves it in a SessionThe Secure Site redirect the browser to the SSO server with a request that has the siteid unencrypted and a encrypted string containing the URL the browser should go to if he is authenticated correctly by the SSO Server and also the Token generated in step 2.The SSO Server validates the request, checking Next URL against that stored for siteid after using the PSK stored for siteid to decrypt the packet.The user is presented with a login form.&nbsp; The login form shows detail about the Secure Site such as its URL, a description of the site and who to contact with any support requests about this site.&nbsp; The user is warned that his personal details will be shared with the site.&nbsp; The user logs in with a username and password and gets redirected to the Secure Site.The Secure Site gets a authentication packet in the redirect that has - encrypted using the PSK - the username, email address, real name, time zone and the previously generated token.&nbsp; In unencrypted form is a md5 hash of all the private information concatenated with the PSK, this is signature for the request and could be used as a cryptographic digital signature if the SSO Server is configured to not encrypt the private data.&nbsp; The Token gets removed from the session and the user gets marked as Logged In using a cookie or existing session.At this point the user is logged in and can access the Secure Site, the Secure Site knows his private details and can associate his data with him.&nbsp; From this point on it's a standard cookie based auth and the Secure Site can decide how long the login session is valid for etc.I think we'll keep it at that for today, in the next part I'll explain some of the choices made in designing this protocol and what security exploits it tries to prevent (replay attacks), what it is vulnerable too (man in the middle attacks) and how to mitigate those risks.]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Code" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="code" label="code" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="php" label="php" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="security" label="security" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[This is the 3rd part of my ongoing series of posts about designing a
simple Single Signon System for PHP, you should read part <a href="http://www.devco.net/archives/2008/04/13/designing_a_single_sign_on_system_part_1.php">1</a> and <a href="http://www.devco.net/archives/2008/04/17/designing_a_single_sign_on_system_part_2.php">2</a> first.<br /><br />Today we look a bit more about the general information flow between browser, target web site and the SSO Server.&nbsp; We will use the term Secure Site for the target site, lets say a corporate intranet.<br /><br />The following diagram shows the flow of information, the information flows via the browser using redirects etc.<br /><br />First a few words on the requierd bits of information before this exchange can happen.<br /><br /><ul><li>The
Secure Site has a pre-shared key (PSK) that the SSO Server assigns,
this key gets hardcoded in the Secure Site and kept private, it never
gets passed between the parties during normal authentication requests.</li><li>The Secure Site has a <i>siteid</i>
that is simply a number that uniquely identifies it to the SSO Server.&nbsp;
This too gets assigned by the SSO Server and does not change for the
life time of the site.<br /></li><li>Encryption gets done using a simple symmetrical algorithm, the PSK is the passphrase.</li><li>The
SSO server knows what domain name a site is in, the SSO Server will use
this to validate auth requests and generate redirects based on this
domain name only.</li></ul><center><img src="http://www.devco.net/images/SSO_Flow.jpg" /></center><br /><br />Now on to the actual information flow, this demonstrates the flow for a first time visit of an unauthenticated user, future visits will be exactly like any cookie based auth system where the user will not interact with the SSO server at all:<br /><br /><ol><li>The user tries to access the Secure Site</li><li>Secure Site generate a unique single use token, and saves it in a Session</li><li>The Secure Site redirect the browser to the SSO server with a request that has the <i>siteid</i> unencrypted and a encrypted string containing the URL the browser should go to if he is authenticated correctly by the SSO Server and also the Token generated in step 2.</li><li>The SSO Server validates the request, checking Next URL against that stored for <i>siteid</i> after using the PSK stored for <i>siteid</i> to decrypt the packet.</li><li>The user is presented with a login form.&nbsp; The login form shows detail about the Secure Site such as its URL, a description of the site and who to contact with any support requests about this site.&nbsp; The user is warned that his personal details will be shared with the site.&nbsp; The user logs in with a username and password and gets redirected to the Secure Site.</li><li>The Secure Site gets a authentication packet in the redirect that has - encrypted using the PSK - the username, email address, real name, time zone and the previously generated token.&nbsp; In unencrypted form is a md5 hash of all the private information concatenated with the PSK, this is signature for the request and could be used as a cryptographic digital signature if the SSO Server is configured to not encrypt the private data.&nbsp; The Token gets removed from the session and the user gets marked as Logged In using a cookie or existing session.<br /></li><li>At this point the user is logged in and can access the Secure Site, the Secure Site knows his private details and can associate his data with him.&nbsp; From this point on it's a standard cookie based auth and the Secure Site can decide how long the login session is valid for etc.</li></ol>I think we'll keep it at that for today, in the next part I'll explain some of the choices made in designing this protocol and what security exploits it tries to prevent (replay attacks), what it is vulnerable too (man in the middle attacks) and how to mitigate those risks.<br />]]>
        
    </content>
</entry>

<entry>
    <title>Designing a Single Sign On system - part 2</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/04/17/designing_a_single_sign_on_system_-_part_2.php" />
    <id>tag:www.devco.net,2008://1.428</id>

    <published>2008-04-17T18:06:57Z</published>
    <updated>2008-04-17T16:01:40Z</updated>

    <summary><![CDATA[This is the 2nd part of my ongoing series of posts about designing a simple Single Signon System for PHP, you should read part 1 first.I am often annoyed about series of blog posts that don't make it clear what the end goal is early on, so you end up wasting time reading through loads of stuff only to realise at the end its a bad fit.&nbsp; So below you'll see some sample bits of code using my Single Sign On system in PHP and Apache after this you can easily decide to just ignore the rest of the posts or to keep paying attention.First as I said the authentication should be pluggable, I want to be able to fetch users from LDAP, MySQL, and any number of other things, towards this goal I made the actual code that does the hard work pluggable by using a simple OO module and an interface.&nbsp; Below is a bit of code to just always allow a user 'john' in with the password 'secret', the values for name etc is hardcoded and you can't change the settings, but you'll get the basic idea!
&lt;?class&nbsp;StupidAuth&nbsp;implements&nbsp;pSSO_Authenticator&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;_authenticate($username,&nbsp;$password)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($username&nbsp;==&nbsp;"john"&nbsp;&amp;&amp;&nbsp;$password&nbsp;==&nbsp;"secret")&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(0);&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;_getEmailAddress()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return("john@doe.net");&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;_getRealName()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return("John Doe");&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;_getUsername()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return("john");&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;_getTimeZone()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return("Europe/London");&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;_setEmailAddress()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;_setRealName()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;_setUsername()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;_setTimeZone()&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;}}?&gt;

It doesn't really come simpler than that, within this framework you really should be able to do almost any form of authentication, if PHP can talk to it and auth then so should the SSO system.&nbsp; This code will live in the server, I won't go much into the server here, it's just a really a system to wrap the code above into a well defined protocol between client and server, more on this some other day.&nbsp; For now just assume there is a config file on the server and you tell it what Class implements the actual auth - StupidAuth in this case.Now for a quick client, remember the client can run anywhere on any domain, and I want my clients to be registered with me before they can use the SSO system.&nbsp; To this end each client has a Pre Shared Key (PSK) and a unique ID.&nbsp; The PSK is used to encrypt the communications from the SSO server to the SSO client as the reply will have real names, email addresses and such in it, you don't want this to show up in proxy logs and such!Here's a quick client:
&lt;?&nbsp;&nbsp;&nbsp;&nbsp;require("pSSO_Client.class.php");&nbsp;&nbsp;&nbsp;&nbsp;$psk&nbsp;=&nbsp;"goG4mUrJeacE7VyidEfd";&nbsp;&nbsp;&nbsp;&nbsp;$siteid&nbsp;=&nbsp;1;&nbsp;&nbsp;&nbsp;&nbsp;$ssoServer&nbsp;=&nbsp;"http://sso.yourcompany.com/";&nbsp;&nbsp;&nbsp; $thisURL&nbsp;=&nbsp;"http://"&nbsp;.&nbsp;$_SERVER["HTTP_HOST"]&nbsp;.&nbsp;$_SERVER['SCRIPT_NAME'];&nbsp;&nbsp;&nbsp;&nbsp;session_start();&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;the&nbsp;SSO&nbsp;server&nbsp;sent&nbsp;us&nbsp;back&nbsp;a&nbsp;token,&nbsp;validate&nbsp;it&nbsp;and&nbsp;set&nbsp;cookies&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(isSet($_GET['authdata'])&nbsp;&amp;&amp;&nbsp;($_GET['v']))&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$psso&nbsp;=&nbsp;new&nbsp;pSSO_Client($_GET['authdata'],&nbsp;$_GET['v'],&nbsp;$psk, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $siteid,&nbsp;$ssoServer);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($psso-&gt;authenticate())&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;The&nbsp;user&nbsp;is&nbsp;logged&nbsp;in, send him back to this same url&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// except without any GET params etc, so he'll be a normal&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // returning logged in user.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; header("Location:&nbsp;"&nbsp;.$thisURL);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;else&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;login&nbsp;failed,&nbsp;eventhough&nbsp;it&nbsp;shouldn't&nbsp;have,&nbsp;bail&nbsp;out&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Throw&nbsp;new&nbsp;Exception&nbsp;("Login&nbsp;failed:"&nbsp;.&nbsp;$psso-&gt;getError());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;We&nbsp;didn't&nbsp;get&nbsp;a&nbsp;token,&nbsp;either&nbsp;its&nbsp;a&nbsp;guest&nbsp;or&nbsp;he&nbsp;already&nbsp;has&nbsp;cookies &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // from&nbsp;a&nbsp;previous&nbsp;visit&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$psso&nbsp;=&nbsp;new&nbsp;pSSO_Client("",&nbsp;"",&nbsp;$psk,&nbsp;$siteid,&nbsp;$ssoServer);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;($psso-&gt;isLoggedIn())&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("You&nbsp;are&nbsp;logged&nbsp;in:&lt;br&gt;&lt;br&gt;");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("Your&nbsp;username&nbsp;is:&nbsp;"&nbsp;.&nbsp;$psso-&gt;getUserName()&nbsp;.&nbsp;"&lt;br&gt;");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("Your&nbsp;real&nbsp;name&nbsp;is:&nbsp;"&nbsp;.&nbsp;$psso-&gt;getRealName()&nbsp;.&nbsp;"&lt;br&gt;");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("Your&nbsp;email&nbsp;address&nbsp;is:&nbsp;"&nbsp;.&nbsp;$psso-&gt;getEmailAddress()&nbsp;.&nbsp;"&lt;br&gt;");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("Your&nbsp;timezone&nbsp;is:&nbsp;"&nbsp;.&nbsp;$psso-&gt;getTimeZone()&nbsp;.&nbsp;"&lt;br&gt;");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print("Welcome&nbsp;guest,&nbsp;you&nbsp;can&nbsp;login&nbsp;&lt;a&nbsp;href='"&nbsp;.&nbsp;$psso-&gt;getAuthURL($thisURL) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp;"'&gt;here&lt;/a&gt;");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;}?&gt;A quick run through the code:Define the PSK, SSO Server URL and your unique ID, all of this will be supplied by the SSO server when you register your site.Start a session - this is used to associate a one-time-use token that travels between the SSO client and Server, more on this later but it helps prevent session replay attacks.Check if we got the data that the SSO server will typically pass us $_GET['authdata'] and $_GET['v'], if we did get it, start up a SSO client and authenticate.&nbsp; Showing the protected page on success or an error message if it failed.If the GET parameters aren't present it is either a first visit or a returning visit, the SSO Client lib gets used to find out if its a returning visit and shows some personal information if the user is logged in, else presents the user with a bit of guest info and a link to the login form.&nbsp; Again here the SSO client library generate all the needed URLs and encryption and what not.I think this very simple use case should demonstrate the ease of use, you could now easily decide to either just not have a local user database at all, just perhaps ACL's based on username or some local cached user data that has additional information your app provides in a local database perhaps referenced by username, so relying simply on the SSO for auth. You'll remember I also wanted to do HTTP Authentication, I have a beta stage Apache mod_perl module to do this, below you'll see a bit of Apache config to protect my Nagios installation using the SSO:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Directory "/usr/share/nagios"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthType Apache::Auth_pSSO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthName pSSO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PerlAuthenHandler Apache::Auth_pSSO-&gt;authenticate&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; require valid-user&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PerlSetVar pSSO_PSK "goG4mUrJeacE7VyidEfd"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/Directory&gt;Again notice the PSK in there, at the moment site id and SSO server URLs are hardcoded, but like I said, its beta code :)With both of the samples above, instead of a pop-up HTTP Auth dialog, you will simply see the SSO login form if you've not authenticated already, else you will just see the protected resource or nagios no questions asked.So that's it, a quick run through what can be achieved with the SSO libraries on both server and client, in the next post I'll get into some details of the protocol between server and client.]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Code" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="code" label="code" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="php" label="php" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="security" label="security" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[This is the 2nd part of my ongoing series of posts about designing a simple Single Signon System for PHP, you should <a href="http://www.devco.net/archives/2008/04/13/designing_a_single_sign_on_system_part_1.php">read part 1 first</a>.<br /><br />I am often annoyed about series of blog posts that don't make it clear what the end goal is early on, so you end up wasting time reading through loads of stuff only to realise at the end its a bad fit.&nbsp; So below you'll see some sample bits of code using my Single Sign On system in PHP and Apache after this you can easily decide to just ignore the rest of the posts or to keep paying attention.<br /><br />First as I said the authentication should be pluggable, I want to be able to fetch users from LDAP, MySQL, and any number of other things, towards this goal I made the actual code that does the hard work pluggable by using a simple OO module and an interface.&nbsp; Below is a bit of code to just always allow a user 'john' in with the password 'secret', the values for name etc is hardcoded and you can't change the settings, but you'll get the basic idea!<br /><br /><code><span style="color: rgb(0, 0, 0);">
<span style="color: rgb(0, 0, 187);">&lt;?<br /></span><span style="color: rgb(0, 119, 0);">class&nbsp;</span><span style="color: rgb(0, 0, 187);">StupidAuth&nbsp;</span><span style="color: rgb(0, 119, 0);">implements&nbsp;</span><span style="color: rgb(0, 0, 187);">pSSO_Authenticator&nbsp;</span><span style="color: rgb(0, 119, 0);">{<br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">_authenticate</span><span style="color: rgb(0, 119, 0);">(</span><span style="color: rgb(0, 0, 187);">$username</span><span style="color: rgb(0, 119, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 187);">$password</span><span style="color: rgb(0, 119, 0);">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: rgb(0, 0, 187);">$username&nbsp;</span><span style="color: rgb(0, 119, 0);">==&nbsp;</span><span style="color: rgb(221, 0, 0);">"john"&nbsp;</span><span style="color: rgb(0, 119, 0);">&amp;&amp;&nbsp;</span><span style="color: rgb(0, 0, 187);">$password&nbsp;</span><span style="color: rgb(0, 119, 0);">==&nbsp;</span><span style="color: rgb(221, 0, 0);">"secret"</span><span style="color: rgb(0, 119, 0);">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(</span><span style="color: rgb(0, 0, 187);">1</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(</span><span style="color: rgb(0, 0, 187);">0</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">_getEmailAddress</span><span style="color: rgb(0, 119, 0);">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(</span><span style="color: rgb(221, 0, 0);">"john@doe.net"</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">_getRealName</span><span style="color: rgb(0, 119, 0);">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(</span><span style="color: rgb(221, 0, 0);">"John Doe"</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">_getUsername</span><span style="color: rgb(0, 119, 0);">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(</span><span style="color: rgb(221, 0, 0);">"john"</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">_getTimeZone</span><span style="color: rgb(0, 119, 0);">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(</span><span style="color: rgb(221, 0, 0);">"Europe/London"</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">_setEmailAddress</span><span style="color: rgb(0, 119, 0);">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">_setRealName</span><span style="color: rgb(0, 119, 0);">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">_setUsername</span><span style="color: rgb(0, 119, 0);">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">_setTimeZone</span><span style="color: rgb(0, 119, 0);">()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span><span style="color: rgb(0, 0, 187);">?&gt;<br /><br /></span>
</span>
</code>It doesn't really come simpler than that, within this framework you really should be able to do almost any form of authentication, if PHP can talk to it and auth then so should the SSO system.&nbsp; This code will live in the server, I won't go much into the server here, it's just a really a system to wrap the code above into a well defined protocol between client and server, more on this some other day.&nbsp; For now just assume there is a config file on the server and you tell it what Class implements the actual auth - StupidAuth in this case.<br /><br />Now for a quick client, remember the client can run anywhere on any domain, and I want my clients to be registered with me before they can use the SSO system.&nbsp; To this end each client has a Pre Shared Key (PSK) and a unique ID.&nbsp; The PSK is used to encrypt the communications from the SSO server to the SSO client as the reply will have real names, email addresses and such in it, you don't want this to show up in proxy logs and such!<br /><br />Here's a quick client:<br /><br /><code><span style="color: rgb(0, 0, 0);">
<span style="color: rgb(0, 0, 187);">&lt;?<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 119, 0);">require(</span><span style="color: rgb(221, 0, 0);">"pSSO_Client.class.php"</span><span style="color: rgb(0, 119, 0);">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 187);">$psk&nbsp;</span><span style="color: rgb(0, 119, 0);">=&nbsp;</span><span style="color: rgb(221, 0, 0);">"goG4mUrJeacE7VyidEfd"</span><span style="color: rgb(0, 119, 0);">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 187);">$siteid&nbsp;</span><span style="color: rgb(0, 119, 0);">=&nbsp;</span><span style="color: rgb(0, 0, 187);">1</span><span style="color: rgb(0, 119, 0);">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 187);">$ssoServer&nbsp;</span><span style="color: rgb(0, 119, 0);">=&nbsp;</span><span style="color: rgb(221, 0, 0);">"http://sso.yourcompany.com/"</span><span style="color: rgb(0, 119, 0);">;<br />&nbsp;&nbsp;&nbsp; </span></span></code><code><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 0, 187);">$thisURL&nbsp;</span><span style="color: rgb(0, 119, 0);">=&nbsp;</span><span style="color: rgb(221, 0, 0);">"http://"&nbsp;</span><span style="color: rgb(0, 119, 0);">.&nbsp;</span><span style="color: rgb(0, 0, 187);">$_SERVER</span><span style="color: rgb(0, 119, 0);">[</span><span style="color: rgb(221, 0, 0);">"HTTP_HOST"</span><span style="color: rgb(0, 119, 0);">]&nbsp;.&nbsp;</span><span style="color: rgb(0, 0, 187);">$_SERVER</span><span style="color: rgb(0, 119, 0);">[</span><span style="color: rgb(221, 0, 0);">'SCRIPT_NAME'</span><span style="color: rgb(0, 119, 0);">];<br /><br /></span></span></code><code><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 119, 0);">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 187);">session_start</span><span style="color: rgb(0, 119, 0);">();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(255, 128, 0);">//&nbsp;the&nbsp;SSO&nbsp;server&nbsp;sent&nbsp;us&nbsp;back&nbsp;a&nbsp;token,&nbsp;validate&nbsp;it&nbsp;and&nbsp;set&nbsp;cookies<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 119, 0);">if&nbsp;(isSet(</span><span style="color: rgb(0, 0, 187);">$_GET</span><span style="color: rgb(0, 119, 0);">[</span><span style="color: rgb(221, 0, 0);">'authdata'</span><span style="color: rgb(0, 119, 0);">])&nbsp;&amp;&amp;&nbsp;(</span><span style="color: rgb(0, 0, 187);">$_GET</span><span style="color: rgb(0, 119, 0);">[</span><span style="color: rgb(221, 0, 0);">'v'</span><span style="color: rgb(0, 119, 0);">]))&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 187);">$psso&nbsp;</span><span style="color: rgb(0, 119, 0);">=&nbsp;new&nbsp;</span><span style="color: rgb(0, 0, 187);">pSSO_Client</span><span style="color: rgb(0, 119, 0);">(</span><span style="color: rgb(0, 0, 187);">$_GET</span><span style="color: rgb(0, 119, 0);">[</span><span style="color: rgb(221, 0, 0);">'authdata'</span><span style="color: rgb(0, 119, 0);">],&nbsp;</span><span style="color: rgb(0, 0, 187);">$_GET</span><span style="color: rgb(0, 119, 0);">[</span><span style="color: rgb(221, 0, 0);">'v'</span><span style="color: rgb(0, 119, 0);">],&nbsp;</span><span style="color: rgb(0, 0, 187);">$psk</span><span style="color: rgb(0, 119, 0);">, </span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: rgb(0, 0, 187);">$siteid</span><span style="color: rgb(0, 119, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 187);">$ssoServer</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: rgb(0, 0, 187);">$psso</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">authenticate</span><span style="color: rgb(0, 119, 0);">())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(255, 128, 0);">//&nbsp;The&nbsp;user&nbsp;is&nbsp;logged&nbsp;in, send him back to this same url<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// except without any GET params etc, so he'll be a normal<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // returning logged in user.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></code><code><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 119, 0);">header(</span></span></code><code><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 119, 0);"></span><span style="color: rgb(221, 0, 0);">"Location:&nbsp;"&nbsp;</span><span style="color: rgb(0, 119, 0);">.</span></span></code><code><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 0, 187);">$thisURL</span></span></code><code><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 119, 0);">);</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></code><code><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 119, 0);">exit;</span></span></code><br /><code><span style="color: rgb(0, 0, 0);"><span style="color: rgb(255, 128, 0);">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: rgb(0, 119, 0);">}&nbsp;else&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(255, 128, 0);">//&nbsp;login&nbsp;failed,&nbsp;eventhough&nbsp;it&nbsp;shouldn't&nbsp;have,&nbsp;bail&nbsp;out<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 119, 0);">Throw&nbsp;new&nbsp;</span><span style="color: rgb(0, 0, 187);">Exception&nbsp;</span><span style="color: rgb(0, 119, 0);">(</span><span style="color: rgb(221, 0, 0);">"Login&nbsp;failed:"&nbsp;</span><span style="color: rgb(0, 119, 0);">.&nbsp;</span><span style="color: rgb(0, 0, 187);">$psso</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">getError</span><span style="color: rgb(0, 119, 0);">());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(255, 128, 0);">//&nbsp;We&nbsp;didn't&nbsp;get&nbsp;a&nbsp;token,&nbsp;either&nbsp;its&nbsp;a&nbsp;guest&nbsp;or&nbsp;he&nbsp;already&nbsp;has&nbsp;cookies <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // from&nbsp;a&nbsp;previous&nbsp;visit<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 187);">$psso&nbsp;</span><span style="color: rgb(0, 119, 0);">=&nbsp;new&nbsp;</span><span style="color: rgb(0, 0, 187);">pSSO_Client</span><span style="color: rgb(0, 119, 0);">(</span><span style="color: rgb(221, 0, 0);">""</span><span style="color: rgb(0, 119, 0);">,&nbsp;</span><span style="color: rgb(221, 0, 0);">""</span><span style="color: rgb(0, 119, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 187);">$psk</span><span style="color: rgb(0, 119, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 187);">$siteid</span><span style="color: rgb(0, 119, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 187);">$ssoServer</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(</span><span style="color: rgb(0, 0, 187);">$psso</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">isLoggedIn</span><span style="color: rgb(0, 119, 0);">())&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(</span><span style="color: rgb(221, 0, 0);">"You&nbsp;are&nbsp;logged&nbsp;in:&lt;br&gt;&lt;br&gt;"</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(</span><span style="color: rgb(221, 0, 0);">"Your&nbsp;username&nbsp;is:&nbsp;"&nbsp;</span><span style="color: rgb(0, 119, 0);">.&nbsp;</span><span style="color: rgb(0, 0, 187);">$psso</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">getUserName</span><span style="color: rgb(0, 119, 0);">()&nbsp;.&nbsp;</span><span style="color: rgb(221, 0, 0);">"&lt;br&gt;"</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(</span><span style="color: rgb(221, 0, 0);">"Your&nbsp;real&nbsp;name&nbsp;is:&nbsp;"&nbsp;</span><span style="color: rgb(0, 119, 0);">.&nbsp;</span><span style="color: rgb(0, 0, 187);">$psso</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">getRealName</span><span style="color: rgb(0, 119, 0);">()&nbsp;.&nbsp;</span><span style="color: rgb(221, 0, 0);">"&lt;br&gt;"</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(</span><span style="color: rgb(221, 0, 0);">"Your&nbsp;email&nbsp;address&nbsp;is:&nbsp;"&nbsp;</span><span style="color: rgb(0, 119, 0);">.&nbsp;</span><span style="color: rgb(0, 0, 187);">$psso</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">getEmailAddress</span><span style="color: rgb(0, 119, 0);">()&nbsp;.&nbsp;</span><span style="color: rgb(221, 0, 0);">"&lt;br&gt;"</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(</span><span style="color: rgb(221, 0, 0);">"Your&nbsp;timezone&nbsp;is:&nbsp;"&nbsp;</span><span style="color: rgb(0, 119, 0);">.&nbsp;</span><span style="color: rgb(0, 0, 187);">$psso</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">getTimeZone</span><span style="color: rgb(0, 119, 0);">()&nbsp;.&nbsp;</span><span style="color: rgb(221, 0, 0);">"&lt;br&gt;"</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{</span><span style="color: rgb(0, 119, 0);"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print(</span><span style="color: rgb(221, 0, 0);">"Welcome&nbsp;guest,&nbsp;you&nbsp;can&nbsp;login&nbsp;&lt;a&nbsp;href='"&nbsp;</span><span style="color: rgb(0, 119, 0);">.&nbsp;</span><span style="color: rgb(0, 0, 187);">$psso</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">getAuthURL</span><span style="color: rgb(0, 119, 0);">(</span><span style="color: rgb(0, 0, 187);">$thisURL</span><span style="color: rgb(0, 119, 0);">) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .&nbsp;</span><span style="color: rgb(221, 0, 0);">"'&gt;here&lt;/a&gt;"</span><span style="color: rgb(0, 119, 0);">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exit;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: rgb(0, 0, 187);">?&gt;<br /><br /></span></span></code>A quick run through the code:<br /><br /><ul><li>Define the PSK, SSO Server URL and your unique ID, all of this will be supplied by the SSO server when you register your site.</li><li>Start a session - this is used to associate a one-time-use token that travels between the SSO client and Server, more on this later but it helps prevent session replay attacks.</li><li>Check if we got the data that the SSO server will typically pass us <i>$_GET['authdata']</i> and <i>$_GET['v']</i>, if we did get it, start up a SSO client and authenticate.&nbsp; Showing the protected page on success or an error message if it failed.</li><li>If the GET parameters aren't present it is either a first visit or a returning visit, the SSO Client lib gets used to find out if its a returning visit and shows some personal information if the user is logged in, else presents the user with a bit of guest info and a link to the login form.&nbsp; Again here the SSO client library generate all the needed URLs and encryption and what not.</li></ul>I think this very simple use case should demonstrate the ease of use, you could now easily decide to either just not have a local user database at all, just perhaps ACL's based on username or some local cached user data that has additional information your app provides in a local database perhaps referenced by username, so relying simply on the SSO for auth. <br /><br />You'll remember I also wanted to do HTTP Authentication, I have a beta stage Apache mod_perl module to do this, below you'll see a bit of Apache config to protect my Nagios installation using the SSO:<br /><br /><blockquote>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;Directory "/usr/share/nagios"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthType Apache::Auth_pSSO<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; AuthName pSSO<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PerlAuthenHandler Apache::Auth_pSSO-&gt;authenticate<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; require valid-user<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PerlSetVar pSSO_PSK "goG4mUrJeacE7VyidEfd"<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/Directory&gt;<br /></blockquote>Again notice the PSK in there, at the moment site id and SSO server URLs are hardcoded, but like I said, its beta code :)<br /><br />With both of the samples above, instead of a pop-up HTTP Auth dialog, you will simply see the SSO login form if you've not authenticated already, else you will just see the protected resource or nagios no questions asked.<br /><br />So that's it, a quick run through what can be achieved with the SSO libraries on both server and client, in the next post I'll get into some details of the protocol between server and client.<br /><code><span style="color: rgb(0, 0, 0);"></span></code>]]>
        
    </content>
</entry>

<entry>
    <title>Easy per-machine custom facts for Puppet</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/04/17/easy_per-machine_custom_facts_for_puppet.php" />
    <id>tag:www.devco.net,2008://1.427</id>

    <published>2008-04-17T10:36:06Z</published>
    <updated>2008-04-17T11:01:24Z</updated>

    <summary><![CDATA[As this is the first time I am posting about Puppet, maybe a few words about it first.&nbsp; Puppet is a configuration management system that helps you manage large infrastructures.&nbsp; There are ofcourse many similar things, cfengine and lcfg to name just two.&nbsp; I like Puppet as it has a big and active community but it is also a modern approach to the problem being that it has some properties of Object Orientation and so forth.I've used cfengine - actually chose it over Puppet when it was still young - but that is over a year ago now and I if you have many or even 2 of the same nodes to maintain I urge you to check out Puppet.So the rest is only really useful if you already know Puppet, sorry if this will bore many people :)On a site I worked we used to have a file on each machine that defines a few Facter facts, this was very handy and I wanted to do something similar because I define variables like $country="uk" and so forth in my nodes which then helps my manifests builds correct ntp configs for example.&nbsp; Now doing it with a global variable in the node is ok and all, but not nearly as sexy as letting each node know where they are in via facts.In the old days hacking in new facts was a right pain and you possibly even needed to maintain your own package of facter, not so anymore, it's in fact really nice now. Puppet now lets you drop bits of ruby code into a directory and then sends the code off to clients on demand for integration into Facter, I won't go into setting it up the Puppet Wiki goes into it at length.&nbsp; Instead I'll show a simple bit of code to read in /etc/facts.txt on a node and present the values in it as facts.var = nilvalue = nilfacts = {}if File.exists?("/etc/facts.txt")&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File.open("/etc/facts.txt").each do |line|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var = $1 and value = $2 if line =~ /^(.+)=(.+)$/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if var != nil &amp;&amp; value != nil&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; facts[var] = value&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var = nil&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value = nil&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; facts.each{|var,val|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Facter.add(var) do&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setcode do&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; val&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }endThis code essentially just reads stuff out of key=val pairs in /etc/facts.txt and adds them to facter.&nbsp; Drop that into your facts directory on the master in a file ending in .rb and that should be it, with facts files on your nodes the values will now be available for use in your manifests.Maybe not the best Ruby code as it's my first ever Ruby code and mostly based on a sample I found in the Puppet book, I would have liked to do the Facter.add() call right in the loop that parses the file instead of using a array, but I couldn't get that going.Anyway, now I just distribute /etc/facts.txt to all my machines, and they know where they are and I have a simple no-hassle method for teaching machines about new things.]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Code" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="code" label="code" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="puppet" label="puppet" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[As this is the first time I am posting about <a href="http://reductivelabs.com/trac/puppet">Puppet</a>, maybe a few words about it first.&nbsp; Puppet is a configuration management system that helps you manage large infrastructures.&nbsp; There are ofcourse many similar things, <a href="http://www.cfengine.org/">cfengine</a> and <a href="http://www.lcfg.org/">lcfg</a> to name just two.&nbsp; I like Puppet as it has a big and active community but it is also a modern approach to the problem being that it has some properties of Object Orientation and so forth.<br /><br />I've used cfengine - actually chose it over Puppet when it was still young - but that is over a year ago now and I if you have many or even 2 of the same nodes to maintain I urge you to check out Puppet.<br /><br />So the rest is only really useful if you already know Puppet, sorry if this will bore many people :)<br /><br />On a site I worked we used to have a file on each machine that defines a few Facter facts, this was very handy and I wanted to do something similar because I define variables like <i>$country="uk"</i> and so forth in my nodes which then helps my manifests builds correct ntp configs for example.&nbsp; Now doing it with a global variable in the node is ok and all, but not nearly as sexy as letting each node know where they are in via facts.<br /><br />In the old days hacking in new facts was a right pain and you possibly even needed to maintain your own package of facter, not so anymore, it's in fact really nice now.<br /> <br />Puppet now lets you drop bits of ruby code into a directory and then sends the code off to clients on demand for integration into Facter, I won't go into setting it up the <a href="http://reductivelabs.com/trac/puppet/wiki/AddingFacts">Puppet Wiki goes into it at length.</a>&nbsp; Instead I'll show a simple bit of code to read in <i>/etc/facts.txt</i> on a node and present the values in it as facts.<br /><br /><br /><blockquote>var = nil<br />value = nil<br />facts = {}<br /><br />if File.exists?("/etc/facts.txt")<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File.open("/etc/facts.txt").each do |line|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var = $1 and value = $2 if line =~ /^(.+)=(.+)$/<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if var != nil &amp;&amp; value != nil<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; facts[var] = value<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var = nil<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value = nil<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; facts.each{|var,val|<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Facter.add(var) do<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setcode do<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; val<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; end<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />end<br /></blockquote>This code essentially just reads stuff out of <i>key=val</i> pairs in <i>/etc/facts.txt</i> and adds them to facter.&nbsp; Drop that into your facts directory on the master in a file ending in .rb and that should be it, with facts files on your nodes the values will now be available for use in your manifests.<br /><br />Maybe not the best Ruby code as it's my first ever Ruby code and mostly based on a sample I found in the Puppet book, I would have liked to do the Facter.add() call right in the loop that parses the file instead of using a array, but I couldn't get that going.<br /><br />Anyway, now I just distribute /etc/facts.txt to all my machines, and they know where they are and I have a simple no-hassle method for teaching machines about new things.<br />]]>
        
    </content>
</entry>

<entry>
    <title>Online Regex Testing</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/04/13/online_regex_testing.php" />
    <id>tag:www.devco.net,2008://1.426</id>

    <published>2008-04-13T14:50:22Z</published>
    <updated>2008-04-13T14:58:53Z</updated>

    <summary><![CDATA[Back in 2004 I posted about The Regex Coach, its a great app that I still use today, however it only really works on Windows so I have been looking for some alternatives.There is a really great resources called Regular-Expressions.info it even has a cheap tool that you can use to do something similar to The Regex Coach.&nbsp; Today Lifehacker mentioned RegExr, its a great web app but also has standalone versions for Windows, Linux and OS X, full of sample regular expressions, good explanations of what a regular expression parses as etc, it is a perfect replacement for The Regex Coach, worth checking it out!  ]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Usefull Things" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="programming" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[Back in 2004 I <a href="http://www.devco.net/archives/2004/06/10/the_regex_coach.php">posted about The Regex Coach</a>, its a great app that I still use today, however it only really works on Windows so I have been looking for some alternatives.<br /><br />There is a really great resources called <a href="http://www.regular-expressions.info/">Regular-Expressions.info</a> it even has a cheap tool that you can use to do something similar to The Regex Coach.&nbsp; Today <a href="http://lifehacker.com/378991/test-regular-expressions-online-with-regexr">Lifehacker</a> mentioned <a href="http://gskinner.com/RegExr/">RegExr</a>, its a great web app but also has standalone versions for Windows, Linux and OS X, full of sample regular expressions, good explanations of what a regular expression parses as etc, it is a perfect replacement for The Regex Coach, worth checking it out!<a href="http://www.regular-expressions.info/"><br /></a>  ]]>
        
    </content>
</entry>

<entry>
    <title>Designing a Single Sign On system - part 1</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/04/13/designing_a_single_sign_on_system_-_part_1.php" />
    <id>tag:www.devco.net,2008://1.425</id>

    <published>2008-04-13T14:20:13Z</published>
    <updated>2008-04-17T16:02:36Z</updated>

    <summary><![CDATA[I use a PHP development framework that I have been building on and improving for the last 4 or 5 years.&nbsp; I used a framework called Roadsend SiteManager years ago but when the amount of non-backward compatible changes they were making got too much I started working on my own.My framework is a MVC based system that recently had a good refresh to make good use of the improved OO abilities of PHP 5, it isn't really generic, its more tailor designed to work the way I do and to help me make things I do often easier.&nbsp; As a result of using this framework for years now I have about 15 or so sites developed with it, some for my personal stuff - like a database of Film rolls - other for clients.&nbsp; Till now everything had their own user database which makes changing passwords a right pain in the butt not to mention a huge job to adjust all the sites if/when I want to add additional authentication features.So I started looking into Single Sign On systems but came up a bit short for complete ones that fits my bill, my needs are more or less:Server and Client libraries in PHP but also client libraries in other languages.Should store Real Name, Email Address, Time Zone and possibly other bits of information and share it on demand with other sites.Work cross domains, so a single SSO server should be able to serve all my sites and possibly those of 3rd parties should they wish to.&nbsp; This basically means the SSO server shouldn't just go and set a domain cookie.Have a good management system where users can manage their identities in a self-service manner.Client sites should be registered with the server before they can use the SSO system.&nbsp; When a users identity is accessed he should be shown information about description, contact details etc. it should be completely open to the user when his information gets shared and he should be able to say no.The server should keep a log of all uses of the identity, in practice only the first requests do get logged, after that the user can be kept logged in on the clients and so new requests do not get made to the server.Authentication should be modular so you can plug any user database into the server.&nbsp; For instance I can share a single database between my imap, pop, smtp, ticketing system and any of my sites using the SSO system.Legacy applications and third party applications that rely on standard HTTP Authentication should be able to use it, at least when run under Apache.&nbsp; I want to be able to log into Cacti, Nagios, RT and others with a single login.This is quite a long list of requirements, none of them are particularly difficult to be honest, the hardest part is the HTTP Authentication plugin, mostly because it relies on writing either a C Apache module or something in mod_perl.I have written a SSO system that complies to these requirements and will over the course of a number of blog posts detail the design of such a system.&nbsp; My intention is to open source the main server library and client library in PHP but won't, at least for the foreseeable future, release the management application as that is quite a big deal to release a truly end user ready big web application like this.  I don't know how many posts it will take to go through it all and I also don't know how long it will take me to do them all, I guess I will in these posts retrofit a spec onto what I developed and hopefully pick up on bits that I missed along the way.&nbsp; I hope this might be of use/interest to someone out there.UPDATE: Part 2 is here. ]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Code" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="code" label="code" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="php" label="php" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="security" label="security" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[I use a PHP development framework that I have been building on and improving for the last 4 or 5 years.&nbsp; I used a framework called <a href="http://www.roadsend.com/home/index.php?pageID=smphp">Roadsend SiteManager</a> years ago but when the amount of non-backward compatible changes they were making got too much I started working on my own.<br /><br />My framework is a MVC based system that recently had a good refresh to make good use of the improved OO abilities of PHP 5, it isn't really generic, its more tailor designed to work the way I do and to help me make things I do often easier.&nbsp; As a result of using this framework for years now I have about 15 or so sites developed with it, some for my personal stuff - like a database of Film rolls - other for clients.&nbsp; Till now everything had their own user database which makes changing passwords a right pain in the butt not to mention a huge job to adjust all the sites if/when I want to add additional authentication features.<br /><br />So I started looking into Single Sign On systems but came up a bit short for complete ones that fits my bill, my needs are more or less:<br /><br /><ul><li>Server and Client libraries in PHP but also client libraries in other languages.</li><li>Should store Real Name, Email Address, Time Zone and possibly other bits of information and share it on demand with other sites.<br /></li><li>Work cross domains, so a single SSO server should be able to serve all my sites and possibly those of 3rd parties should they wish to.&nbsp; This basically means the SSO server shouldn't just go and set a domain cookie.<br /></li><li>Have a good management system where users can manage their identities in a self-service manner.</li><li>Client sites should be registered with the server before they can use the SSO system.&nbsp; When a users identity is accessed he should be shown information about description, contact details etc. it should be completely open to the user when his information gets shared and he should be able to say no.<br /></li><li>The server should keep a log of all uses of the identity, in practice only the first requests do get logged, after that the user can be kept logged in on the clients and so new requests do not get made to the server.</li><li>Authentication should be modular so you can plug any user database into the server.&nbsp; For instance I can share a single database between my imap, pop, smtp, ticketing system and any of my sites using the SSO system.</li><li>Legacy applications and third party applications that rely on standard HTTP Authentication should be able to use it, at least when run under Apache.&nbsp; I want to be able to log into Cacti, Nagios, RT and others with a single login.<br /></li></ul>This is quite a long list of requirements, none of them are particularly difficult to be honest, the hardest part is the HTTP Authentication plugin, mostly because it relies on writing either a C Apache module or something in mod_perl.<br /><br />I have written a SSO system that complies to these requirements and will over the course of a number of blog posts detail the design of such a system.&nbsp; My intention is to open source the main server library and client library in PHP but won't, at least for the foreseeable future, release the management application as that is quite a big deal to release a truly end user ready big web application like this.  <br /><br />I don't know how many posts it will take to go through it all and I also don't know how long it will take me to do them all, I guess I will in these posts retrofit a spec onto what I developed and hopefully pick up on bits that I missed along the way.&nbsp; I hope this might be of use/interest to someone out there.<br /><br /><b>UPDATE:</b> <a href="http://www.devco.net/archives/2008/04/17/designing_a_single_sign_on_system_part_2.php">Part 2 is here</a>.<br /> ]]>
        
    </content>
</entry>

<entry>
    <title>Easy transparent PHP input filtering</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/03/25/easy_transparent_php_input_filtering.php" />
    <id>tag:www.devco.net,2008://1.424</id>

    <published>2008-03-25T19:24:51Z</published>
    <updated>2008-03-25T21:02:53Z</updated>

    <summary><![CDATA[I have been working on a site that will have potentially quite a few random third parties accessing it and inserting data into a MySQL database.&nbsp; I am thus quite keen on a good solid input filtering method for PHP to prevent things like XSS and SQL Injection.There are several options out there, of the ones I found Inspekt is about the closest match to my way of working, it essentially imports $_GET, $_POST etc and wraps them in an object which you then use to access variables in a filtered method.&nbsp; It by default then NULLs the original variables so you cannot access them anymore, if backward compatibility is desired it can leave the originals untouched.&nbsp; Not optimal as this gives an unsafe by default result if you want to maintain backwards compatibility. Another problem with this approach is that it is a lot of work to change existing code, which you might thing is just par for the course but I was convinced I need to find a way to do so more transparently.I could for example at program start just walk through the $_GET etc arrays and apply some filtering to them using addslashes() and such but this is very restrictive, what if you need to get it unfiltered, especially if you perform destructive filtering?&nbsp; How would you go about filtering some variables for phone numbers, some for email addresses etc?The answer lies in PHP's new Standard Programming Library, specifically in its ArrayAccess interface, which if you don't care for older versions of PHP is the way to go.The basic advantage of this is that you can expose properties of your objects by using array notation rather than object notation:$result = $foo-&gt;getBar();compared to:$result = $foo['bar'];Both statements give access to the private variable $bar just using different syntax.&nbsp; So using this technique we can write a transparent filter for input variables, the basic usage of the final library would be something along these lines:$_GET = new ArrayArmor($_GET);
print ("Filtered Variable:$_GET[test]&lt;br&gt;\n");
print ("Unfiltered Variable: " . $_GET-&gt;getRaw("test"));A possible output from this script can be seen below:Filtered Variable: 1234\';delete from accounts;--Unfiltered Variable: 1234';delete from accounts;--You can see that the default behavior is to protect the input but even for destructive filtering methods the raw unfiltered data would be available if the programmer needed it.&nbsp; You can provide all sorts of extra methods to validate emails, post codes and such.A quick and dirty example of a class that provides this kind of filtering can be seen below:
&lt;?class ArrayArmor&nbsp;Implements&nbsp;ArrayAccess&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;$original;&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;__construct&nbsp;(&amp;$variable)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$this-&gt;original&nbsp;=&nbsp;$variable;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;offsetExists($offset)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;isset($this-&gt;original[$offset]);&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;offsetGet($offset)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;addslashes($this-&gt;original[$offset]);&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;offsetSet($offset,&nbsp;$value)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;offsetUnset($offset)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;getRaw($offset)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return($this-&gt;original[$offset]);&nbsp;&nbsp;&nbsp;&nbsp;}}?&gt;

So that's it, a simple method that is very easy to put into existing code.  This is clearly not a full example as addslashes() is hardly the be-all and end-all of input protection, but if you build on this you can get a very easy to use and flexible input filter that is safe by default.]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Code" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="php" label="php" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="programming" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="security" label="security" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[I have been working on a site that will have potentially quite a few random third parties accessing it and inserting data into a MySQL database.&nbsp; I am thus quite keen on a good solid input filtering method for PHP to prevent things like XSS and SQL Injection.<br /><br />There are several options out there, of the ones I found <a href="http://code.google.com/p/inspekt/">Inspekt</a> is about the closest match to my way of working, it essentially imports <i>$_GET</i>, <i>$_POST</i> etc and wraps them in an object which you then use to access variables in a filtered method.&nbsp; It by default then NULLs the original variables so you cannot access them anymore, if backward compatibility is desired it can leave the originals untouched.&nbsp; Not optimal as this gives an unsafe by default result if you want to maintain backwards compatibility. <br /><br />Another problem with this approach is that it is a lot of work to change existing code, which you might thing is just par for the course but I was convinced I need to find a way to do so more transparently.<br /><br />I could for example at program start just walk through the <i>$_GET</i> etc arrays and apply some filtering to them using <i>addslashes()</i> and such but this is very restrictive, what if you need to get it unfiltered, especially if you perform destructive filtering?&nbsp; How would you go about filtering some variables for phone numbers, some for email addresses etc?<br /><br />The answer lies in PHP's new Standard Programming Library, specifically in its <a href="http://www.php.net/%7Ehelly/php/ext/spl/interfaceArrayAccess.html">ArrayAccess</a> interface, which if you don't care for older versions of PHP is the way to go.<br /><br />The basic advantage of this is that you can expose properties of your objects by using array notation rather than object notation:<br /><br /><blockquote>$result = $foo-&gt;getBar();</blockquote><br />compared to:<br /><br /><blockquote>$result = $foo['bar'];</blockquote><br />Both statements give access to the private variable $bar just using different syntax.&nbsp; So using this technique we can write a transparent filter for input variables, the basic usage of the final library would be something along these lines:<br /><br /><blockquote>$_GET = new ArrayArmor($_GET);
<br /><br />print ("Filtered Variable:$_GET[test]&lt;br&gt;\n");
<br />print ("Unfiltered Variable: " . $_GET-&gt;getRaw("test"));</blockquote><br />A possible output from this script can be seen below:<br /><br /><blockquote>Filtered Variable: 1234\';delete from accounts;--<br />Unfiltered Variable: 1234';delete from accounts;--</blockquote><br />You can see that the default behavior is to protect the input but even for destructive filtering methods the raw unfiltered data would be available if the programmer needed it.&nbsp; You can provide all sorts of extra methods to validate emails, post codes and such.<br /><br />A quick and dirty example of a class that provides this kind of filtering can be seen below:<br /><br /><code><span style="color: rgb(0, 0, 0);">
<span style="color: rgb(0, 0, 187);">&lt;?<br /></span><span style="color: rgb(0, 119, 0);">class </span><span style="color: rgb(0, 0, 187);">ArrayArmor&nbsp;</span><span style="color: rgb(0, 119, 0);">Implements&nbsp;</span><span style="color: rgb(0, 0, 187);">ArrayAccess&nbsp;</span><span style="color: rgb(0, 119, 0);">{<br />&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;</span><span style="color: rgb(0, 0, 187);">$original</span><span style="color: rgb(0, 119, 0);">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">__construct&nbsp;</span><span style="color: rgb(0, 119, 0);">(&amp;</span><span style="color: rgb(0, 0, 187);">$variable</span><span style="color: rgb(0, 119, 0);">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0, 0, 187);">$this</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">original&nbsp;</span><span style="color: rgb(0, 119, 0);">=&nbsp;</span><span style="color: rgb(0, 0, 187);">$variable</span><span style="color: rgb(0, 119, 0);">;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">offsetExists</span><span style="color: rgb(0, 119, 0);">(</span><span style="color: rgb(0, 0, 187);">$offset</span><span style="color: rgb(0, 119, 0);">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;isset(</span><span style="color: rgb(0, 0, 187);">$this</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">original</span><span style="color: rgb(0, 119, 0);">[</span><span style="color: rgb(0, 0, 187);">$offset</span><span style="color: rgb(0, 119, 0);">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">offsetGet</span><span style="color: rgb(0, 119, 0);">(</span><span style="color: rgb(0, 0, 187);">$offset</span><span style="color: rgb(0, 119, 0);">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;</span><span style="color: rgb(0, 0, 187);">addslashes</span><span style="color: rgb(0, 119, 0);">(</span><span style="color: rgb(0, 0, 187);">$this</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">original</span><span style="color: rgb(0, 119, 0);">[</span><span style="color: rgb(0, 0, 187);">$offset</span><span style="color: rgb(0, 119, 0);">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">offsetSet</span><span style="color: rgb(0, 119, 0);">(</span><span style="color: rgb(0, 0, 187);">$offset</span><span style="color: rgb(0, 119, 0);">,&nbsp;</span><span style="color: rgb(0, 0, 187);">$value</span><span style="color: rgb(0, 119, 0);">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">offsetUnset</span><span style="color: rgb(0, 119, 0);">(</span><span style="color: rgb(0, 0, 187);">$offset</span><span style="color: rgb(0, 119, 0);">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;</span><span style="color: rgb(0, 0, 187);">getRaw</span><span style="color: rgb(0, 119, 0);">(</span><span style="color: rgb(0, 0, 187);">$offset</span><span style="color: rgb(0, 119, 0);">)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return(</span><span style="color: rgb(0, 0, 187);">$this</span><span style="color: rgb(0, 119, 0);">-&gt;</span><span style="color: rgb(0, 0, 187);">original</span><span style="color: rgb(0, 119, 0);">[</span><span style="color: rgb(0, 0, 187);">$offset</span><span style="color: rgb(0, 119, 0);">]);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /></span><span style="color: rgb(0, 0, 187);">?&gt;<br /></span>
</span>
</code><br />So that's it, a simple method that is very easy to put into existing code.  This is clearly not a full example as <i>addslashes()</i> is hardly the be-all and end-all of input protection, but if you build on this you can get a very easy to use and flexible input filter that is safe by default.]]>
        
    </content>
</entry>

<entry>
    <title>Nasty PHP Authentication Handling</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/03/18/nasty_php_authentication_handling.php" />
    <id>tag:www.devco.net,2008://1.423</id>

    <published>2008-03-18T00:24:06Z</published>
    <updated>2008-03-18T10:06:20Z</updated>

    <summary><![CDATA[Sometimes you come across things that just make you wonder what is going on in peoples minds.For years everyone who wrote applications compatible with the standard HTTP Authentication method has used the REMOTE_USER server variable as set by Apache to check the username that was logged in by the webserver, this has worked well for everyone, CGI's and all would just grab it there and everyone would be happy.Along comes PHP and they make great big mess of it, PHP suggests that we use $_SERVER['PHP_AUTH_USER'] instead, and they give some good reasons for this too, except they have severely crippled this for all but Basic and Digest authentication, the following code from main/main.c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (auth &amp;&amp; auth[0] != '\0' &amp;&amp; strncmp(auth, "Basic ", 6) == 0) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *pass;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *user;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user = php_base64_decode(auth + 6, strlen(auth) - 6, NULL);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (user) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass = strchr(user, ':');&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pass) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *pass++ = '\0';&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SG(request_info).auth_user = user;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SG(request_info).auth_password = estrdup(pass);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = 0;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; efree(user);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }As you can see above, they only import the user and pass from Apache if the AuthType is Basic, this makes no sense at all.&nbsp; Why not just check with Apache, if it set the username then import it? Surely Apache know if a user has authenticated? Ditto for password.&nbsp; It is so broken in fact that PHP in CGI mode also doesn't work since those headers don't get set for that either, countless comments and nasty hacks can be found in the PHP user contributed notes about this, but it is all just sillyness.The reason this is annoying me is that I have written a Single Singon system in PHP, you can host a identity server on any domain and hook any site in any other domain into the SSO system, its a bit like TypeKeyOf course it's nice to have a easy to use SSO system in PHP but what is the point if you can't make legacy apps like Nagios, Cacti, RT etc play along with the SSO?&nbsp; So to solve this I extended Apache::AuthCookie with a new mod_perl module that plugs into Apache and does authentication using my SSO and a small bit of glue that you put on your RT/Cacti/Nagios box.All's great, I have SSO to Nagios, RT and countless other things working flawlessly, except of course Cacti because it's written along the lines of the PHP manual, uses PHP_AUTH_USER instead of REMOTE_USER and so my new fancy AuthType in Apache does not work with Cacti.&nbsp;&nbsp; As it turns out its a quick 2 liner fix in the Cacti code but you would think PHP would be a bit more generic in this regard since as it stands now I think a lot of people who want to do SSO using hardware tokens and such have issues with PHP being silly. ]]></summary>
    <author>
        <name>R.I.Pienaar</name>
        <uri>http://www.devco.net/</uri>
    </author>
    
        <category term="Code" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Front Page" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Rantings" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="apache" label="apache" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="php" label="php" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="sso" label="sso" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en-US" xml:base="http://www.devco.net/">
        <![CDATA[Sometimes you come across things that just make you wonder what is going on in peoples minds.<br /><br />For years everyone who wrote applications compatible with the standard HTTP Authentication method has used the <i>REMOTE_USER</i> server variable as set by Apache to check the username that was logged in by the webserver, this has worked well for everyone, CGI's and all would just grab it there and everyone would be happy.<br /><br />Along comes PHP and they make great big mess of it, <a href="http://www.php.net/manual/en/features.http-auth.php">PHP suggests</a> that we use <i>$_SERVER['PHP_AUTH_USER']</i> instead, and they give some good reasons for this too, except they have severely crippled this for all but Basic and Digest authentication, the following code from <i>main/main.c<br /><br /></i><blockquote>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (auth &amp;&amp; auth[0] != '\0' &amp;&amp; strncmp(auth, "Basic ", 6) == 0) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *pass;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char *user;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user = php_base64_decode(auth + 6, strlen(auth) - 6, NULL);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (user) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pass = strchr(user, ':');<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (pass) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *pass++ = '\0';<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SG(request_info).auth_user = user;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SG(request_info).auth_password = estrdup(pass);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ret = 0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; efree(user);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br /></blockquote>As you can see above, they only import the user and pass from Apache if the AuthType is Basic, this makes no sense at all.&nbsp; Why not just check with Apache, if it set the username then import it? Surely Apache know if a user has authenticated? Ditto for password.&nbsp; It is so broken in fact that PHP in CGI mode also doesn't work since those headers don't get set for that either, countless comments and nasty hacks can be found in the PHP user contributed notes about this, but it is all just sillyness.<br /><br />The reason this is annoying me is that I have written a Single Singon system in PHP, you can host a identity server on any domain and hook any site in any other domain into the SSO system, its a bit like <a href="http://www.typekey.com/">TypeKey</a><br /><br />Of course it's nice to have a easy to use SSO system in PHP but what is the point if you can't make legacy apps like Nagios, Cacti, RT etc play along with the SSO?&nbsp; So to solve this I extended <a href="http://search.cpan.org/dist/Apache-AuthCookie/">Apache::AuthCookie</a> with a new mod_perl module that plugs into Apache and does authentication using my SSO and a small bit of glue that you put on your RT/Cacti/Nagios box.<br /><br />All's great, I have SSO to Nagios, RT and countless other things working flawlessly, except of course Cacti because it's written along the lines of the PHP manual, uses PHP_AUTH_USER instead of REMOTE_USER and so my new fancy AuthType in Apache does not work with Cacti.&nbsp;&nbsp; As it turns out its a quick 2 liner fix in the Cacti code but you would think PHP would be a bit more generic in this regard since as it stands now I think a lot of people who want to do SSO using hardware tokens and such have issues with PHP being silly.<br /> ]]>
        
    </content>
</entry>

<entry>
    <title>Macs and MS Keyboards</title>
    <link rel="alternate" type="text/html" href="http://www.devco.net/archives/2008/03/12/macs_and_ms_keyboards.php" />
    <id>tag:www.devco.net,2008://1.422</id>

    <published>2008-03-12T16:56:24Z</published>
    <updated>2008-03-12T17:09:57Z</updated>

    <summary><![CDATA[Previously I posted about my iMac 17" that I got, that was January 2006 well I have now upgraded to a bigger mac, this time a 24" iMac Core 2 Duo Extreme with 2