<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Code Penguin</title>
	
	<link>http://laurent.bachelier.name</link>
	<description>Musings on software, internet and technology by Laurent Bachelier</description>
	<lastBuildDate>Sat, 07 Aug 2010 18:02:46 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<feedburner:info uri="laurentb" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://laurent.bachelier.name/feed/" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://laurent.bachelier.name/feed/" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.plusmo.com/add?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://plusmo.com/res/graphics/fbplusmo.gif">Subscribe with Plusmo</feedburner:feedFlare><feedburner:feedFlare href="http://www.thefreedictionary.com/_/hp/AddRSS.aspx?http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://img.tfd.com/hp/addToTheFreeDictionary.gif">Subscribe with The Free Dictionary</feedburner:feedFlare><feedburner:feedFlare href="http://www.bitty.com/manual/?contenttype=rssfeed&amp;contentvalue=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.bitty.com/img/bittychicklet_91x17.gif">Subscribe with Bitty Browser</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsalloy.com/?rss=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.newsalloy.com/subrss3.gif">Subscribe with NewsAlloy</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://mix.excite.eu/add?feedurl=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://image.excite.co.uk/mix/addtomix.gif">Subscribe with Excite MIX</feedburner:feedFlare><feedburner:feedFlare href="http://www.yourminis.com/subscribe.aspx?u=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.yourminis.com/images/addtoyourminisbadge.gif">Subscribe with Yourminis.com</feedburner:feedFlare><feedburner:feedFlare href="http://download.attensa.com/app/get_attensa.html?feedurl=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.attensa.com/blogs/attensa/WindowsLiveWriter/BadgeredintoBadges_10C02/attensa_feed_button5.gif">Subscribe with Attensa for Outlook</feedburner:feedFlare><feedburner:feedFlare href="http://www.webwag.com/wwgthis.php?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.webwag.com/images/wwgthis.gif">Subscribe with Webwag</feedburner:feedFlare><feedburner:feedFlare href="http://hub.netomat.net/account/account.autoSubscribe.jspa?urls=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.netomat.net/blogger/images/icon_netomat_feedbutton.gif">Subscribe with netomat Hub</feedburner:feedFlare><feedburner:feedFlare href="http://www.podcastready.com/oneclick_bookmark.php?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.podcastready.com/images/podcastready_button.gif">Subscribe with Podcast Ready</feedburner:feedFlare><feedburner:feedFlare href="http://www.flurry.com/pushRssFeed.do?r=fb&amp;url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.flurry.com/images/flurry_rss_logo2.gif">Subscribe with Flurry</feedburner:feedFlare><feedburner:feedFlare href="http://www.wikio.com/subscribe?url=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.wikio.com/shared/img/add2wikio.gif">Subscribe with Wikio</feedburner:feedFlare><feedburner:feedFlare href="http://www.dailyrotation.com/index.php?feed=http%3A%2F%2Flaurent.bachelier.name%2Ffeed%2F" src="http://www.dailyrotation.com/rss-dr2.gif">Subscribe with Daily Rotation</feedburner:feedFlare><item>
		<title>Don’t forget the other kind of WTF</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/J3Eab2kXlJM/</link>
		<comments>http://laurent.bachelier.name/2010/08/dont-forget-the-other-kind-of-wtf/#comments</comments>
		<pubDate>Tue, 03 Aug 2010 23:53:14 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[wtf]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=195</guid>
		<description><![CDATA[Sometimes, the code looks good, but it doesn't mean that the whole project in itself is good. First, a project should be simple to install. The install documentation should exist and always be up to date. I encounter too many projects where "inside knowledge" is required to install the application, and you don't know if [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:c04175613e3e20ff4a07ac0cf840ab340e34af5c'><p>Sometimes, the code looks good, but it doesn't mean that the whole project in itself is good.</p>
<p>First, a project should be simple to install. The install documentation should exist and always be up to date. I encounter too many projects where "inside knowledge" is required to install the application, and you don't know if it doesn't work because you didn't install it right or it just doesn't work. There should be a single command (makefiles or shell scripts are here for that) for a single task. It should not require weird system settings (this is very annoying with PHP when a lot of the language is customizable through <code>php.ini</code>).</p>
<p>On a similar note, the architecture should be simple to comprehend. When it feels too much like "magic", when a simple action has too many unsaid consequences, something is wrong. There should not be hundreds of classes and inheritances when an option would be enough (this is an idea found at least in Python and Symfony 1.4 that I quite like). Names should be readable and short, not everyone has or likes using auto-completion.</p>
<p>I'm not sure what creates this kind of WTF. Inexperienced but talented programmers? Programmers who think too high of themselves? Programmers that are <em>not</em><em> lazy enough?</em></p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/J3Eab2kXlJM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/08/dont-forget-the-other-kind-of-wtf/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/08/dont-forget-the-other-kind-of-wtf/</feedburner:origLink></item>
		<item>
		<title>chmod 777 is evil</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/gUeiSnLJmbk/</link>
		<comments>http://laurent.bachelier.name/2010/07/chmod-777-is-evil/#comments</comments>
		<pubDate>Thu, 22 Jul 2010 08:07:20 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Sysadmin]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=131</guid>
		<description><![CDATA[Well, chmod 666 is the true evil obviously, but people who use the chmod 777 trick really don't want to bother with the different signification of x for files and folders, so they mark all files as executables. This makes ls in my terminal quite ugly, and is what motivated me to write yet another [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:5a49026651bd08aa4e816c1360225ee63973fc01'><p>Well, chmod 666 is the true evil obviously, but people who use the <em>chmod 777 trick</em> really don't want to bother with the different signification of <code>x</code> for files and folders, so they mark all files as executables. This makes <code>ls</code> in my terminal quite ugly, and is what motivated me to write yet another rant!</p>
<p>Traditionally, the web server runs with a special, underprivileged user. Now, this is totally fine — I'll get back to that later. However, when a developer starts a project, he naturally does it with his own account. This is fine, too. When he wants to test it, he installs a web server (let's say Apache and mod_php<sup><a href="http://laurent.bachelier.name/2010/07/chmod-777-is-evil/#footnote_0_131" id="identifier_0_131" class="footnote-link footnote-identifier-link" title="I don&#039;t like much both of them, but more on that later">1</a></sup>), and tells the web server to use the project directory. However, the web server's user can't read, or at least can't write in the directory. And here, our web developers asking for help gets recommended to "chmod 777". Symfony even has a command for doing it, and it is a real shame.</p>
<p>It will work. It will also make an ugly git commit, and an ugly <code>ls</code>. Il will create files owned by the web server, and the developer is likely to use <code>sudo</code> before every command to work around the problems that will ensue, and it just gets insane.</p>
<p>Separation of privileges is what makes UNIX systems great. Let's understand them and use them, please.</p>
<p>The obvious solution here is to run your development server under the development user. There is no need to separate when it's for your own usage. There is a even better solution, embraced by almost every language but PHP: a way to start a web server on demand. I believe it was started by Ruby on Rails with WEBrick, and now every non-PHP framework has it. Python, by using <a href="http://en.wikipedia.org/wiki/Web_Server_Gateway_Interface">WSGI</a> makes it very easy. I simulated this feature for Symfony by writing <a href="http://laurent.bachelier.name/2010/05/reducing-the-gap-between-symfony-and-non-php-frameworks/">symfttpd</a>. It's actually simpler for the developer as there is no configuration or installation at all.</p>
<p>Enough about developers; it's not their job to setup daemons and manage UNIX systems. Let's talk about the real accomplices of the Devil: system administrators.</p>
<p>Yes, there are system administrators that don't use permissions properly. And they are legion. I've seen horrors, up to "sudo svn up" on the production server, because half the files ended being owned by root. And then "chmod 777" on millions of files.</p>
<p>There are many solutions there; group inheritance with the <a href="http://en.wikipedia.org/wiki/Setuid#setuid_and_setgid_on_directories">setgid bit</a>, forcing the users to <code>su</code> as the web server user, or a deployment script (I've used the three of them for different situations).</p>
<p>Why is this important? Because it is often useful to separate users (one should not have access to the other's projects in reading or writing), or to separate projects for security (one hacked project should not give access to the others).</p>
<p>I've seen it… done wrong:</p>
<ul>
<li>safe_mode for PHP. It doesn't work and will disappear in newer versions anyway.</li>
<li>Only allowing FTP access to users, who can still upload a PHP script which will have access to everything (if run through the web server). Oh, and FTP sucks. Same issue with SSH and chroot.</li>
<li>Add the users to the <em>group</em> the web server is running as. Allows SSH access. Nice, but the PHP script trick will, again, defeat it.</li>
</ul>
<p>There is only one solution: use the "group" solution, but run a different PHP instance for each user. It is quite rarely used because the convenience of <em>Apache</em> and <em>mod_php</em>. But running PHP in the same <em>process</em> as the web server feels quite dangerous for me too. I think <em>mod_php</em> is an abomination.</p>
<p>I've done it for years with <em>Lighttpd</em>, <em>PHP</em> and <em>FastCGI</em> with a few alterations to Gentoo's <code>spawn-fgci</code> init script (which is now able to handle multiple configurations without any alteration since a few months). My setup is very similar to <a href="http://redmine.lighttpd.net/wiki/lighttpd/HowToSetupFastCgiIndividualPermissions">that one</a>.</p>
<p>Note that while I mention PHP, this issue is not strictly related to PHP, yet seems widespread in PHP communities.</p>
<ol class="footnotes">
<li id="footnote_0_131" class="footnote">I don't like much both of them, but more on that later</li>
</ol>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/gUeiSnLJmbk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/07/chmod-777-is-evil/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/07/chmod-777-is-evil/</feedburner:origLink></item>
		<item>
		<title>Exceptions</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/GGVbyvp9dX8/</link>
		<comments>http://laurent.bachelier.name/2010/07/exceptions/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 23:25:09 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=188</guid>
		<description><![CDATA[I see on a lot of projects stuff like this: &#160; function getStuff&#40;&#41; &#123; try &#123; return $this-&#62;retrieveStuff&#40;&#41; &#125; catch &#40;Exception $e&#41; &#123; return null; &#125; &#125; &#160; The issue, in this example, is not that we silence an error. It should be logged, but there could be a legitimate use for this. For instance, [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:b93f51103415308f0ee5d5980768d593c9c4267f'><p>I see on a lot of projects stuff like this:</p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> getStuff<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
  try
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$this</span>-&gt;<span style="color: #006600;">retrieveStuff</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#125;</span>
  catch <span style="color: #66cc66;">&#40;</span>Exception <span style="color: #0000ff;">$e</span><span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000000; font-weight: bold;">null</span>;
  <span style="color: #66cc66;">&#125;</span>
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p>The issue, in this example, is not that we silence an error. It should be logged, but there could be a legitimate use for this. For instance, it requires a connection to a remote server we have no control over, and we still want to serve the rest of the content to the user, as the information is not vital.</p>
<p>No, my issue it that we catch all errors, when the aim was to catch only one error (for instance "unable to connect to that remote server"). Imagine now there is a real bug in <code>retrieveStuff()</code>, it would still be interpreted by developers as a connection errors.</p>
<p>The solution is to have one exception type per error type (it sounds obvious said that way, doesn't it?), and only catch the specific error, for instance <code>ConnectionError</code>.</p>
<p><!-- more --></p>
<p>PHP's error handling is historically bad, and even though new features use exceptions, the legacy ones don't. Or sometimes functions should trigger a fatal error but it is only a warning, and the code continues, which can trigger unwanted and hard-to-debug results. There are amazing plugins for Symfony that convert errors to exceptions (and warnings seem to be handled properly, i.e. they are logged and don't cause the page to fail). It's a start.</p>
<p>However, even when you get exceptions, you can't always filter them easily. For instance, in Symfony, there are many different errors that would throw the same class. Symfony has a handful of exceptions, Doctrine has a bit more (though they can be quite meaningless!). Overall, there are defined "by module" than "by error".</p>
<p>Comparatively, <a href="http://docs.python.org/tutorial/errors.html">Python's handling of exceptions</a> is exceptional<sup><a href="http://laurent.bachelier.name/2010/07/exceptions/#footnote_0_188" id="identifier_0_188" class="footnote-link footnote-identifier-link" title="sorry">1</a></sup>. There are exceptions for everything, and most of the time errors are handled by only checking the class and not the contents of the exception. It is probably the feature I love the most about Python. With the <code>else</code>, <code>finally</code>, and <code>with</code> statements, it is almost a pleasure to handle errors.</p>
<ol class="footnotes">
<li id="footnote_0_188" class="footnote">sorry</li>
</ol>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/GGVbyvp9dX8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/07/exceptions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/07/exceptions/</feedburner:origLink></item>
		<item>
		<title>Why I wouldn’t use Symfony for a new project</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/Ksn7qjmLrDA/</link>
		<comments>http://laurent.bachelier.name/2010/07/why-i-wouldnt-use-symfony-for-a-new-project/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 23:44:33 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[propel]]></category>
		<category><![CDATA[troll]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=181</guid>
		<description><![CDATA[Symfony is pretty good for a PHP framework — it's probably still one of the better ones. While Symfony is open source, its development clearly isn't open. Nowadays, it is mainly unmaintained. Well, it's maintained by Sensio, which is very closed towards outsiders, and doesn't apply fixes for versions below 1.3 even when patches are [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:b8451b92ee26e7ee79ddae47feca90148b5ecd27'><p>Symfony is pretty good for a PHP framework — it's probably still one of the better ones. While Symfony is open source, its development clearly isn't open.</p>
<p>Nowadays, it is mainly unmaintained. Well, it's maintained by <a href="http://www.sensio.com/">Sensio</a>, which is very closed towards outsiders, and doesn't apply fixes for versions below 1.3 even when patches are handed ready to them. Which means for instance that the official 1.0 doesn't work with PHP 5.3 even though the fixes are available and straightforward.</p>
<p>I will pass on the worrisome attitude towards security of the most used plugin as I've talked about it extensively already. <a href="https://groups.google.com/group/symfony-devs/browse_thread/thread/37c3d5aef3b8b346">Constant</a> <a href="https://groups.google.com/group/symfony-devs/browse_thread/thread/127fa4c30f19180e">reminders</a> don't even work.</p>
<p>There is much more activity towards Symfony2, which might explain the lack of updates to the 1.x branches. Symfony2 introduces more decoupling, which should avoid many bugs reported but ignored by the development team, probably because they are boring to fix and require very deep knowledge in Symfony's architecture — I would have tried to fix them myself if I had the time and motivation; I'm afraid I usually take the easy route and work around them.</p>
<p>But how does Symfony2 looks for a developer? What I've seen is fairly standard and boring, and sometimes looks like sad attempts of reimplementing Python features in PHP. Why not use Python then?</p>
<p>Doctrine2 is even worse — it's the same broken, undocumented API. Propel 1.5, with a minimum set of changes, became much more powerful and easy to use for a developer. At least there's hope on this side.</p>
<p>Overall, it seems the Symfony lead developers don't take much input from the community (like the decision to follow Zend conventions), and focus on making something fun to write, instead of fun to use. I have the choice between an undermaintened version and a future version which will break compatibility without giving me much advantages; moreover some of the stuff that was shown in conferences isn't event implemented yet. I'm not used to see that in the free software word.</p>
<p>Time to switch?</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/Ksn7qjmLrDA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/07/why-i-wouldnt-use-symfony-for-a-new-project/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/07/why-i-wouldnt-use-symfony-for-a-new-project/</feedburner:origLink></item>
		<item>
		<title>Reducing the gap between Symfony and non-PHP frameworks</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/TWFW4JnJjBc/</link>
		<comments>http://laurent.bachelier.name/2010/05/reducing-the-gap-between-symfony-and-non-php-frameworks/#comments</comments>
		<pubDate>Sun, 23 May 2010 23:01:09 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Sysadmin]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[installation]]></category>
		<category><![CDATA[lighttpd]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[symbolic links]]></category>
		<category><![CDATA[symfttpd]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=172</guid>
		<description><![CDATA[Something that always annoyed me is how tedious it is to install a Symfony project on a machine. Since I frequently need to intervene quickly on a project for work, and I was getting a brand-new machine, I really didn't want to create an apache vhost (let alone install Apache: it's painfully slow and its [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:dff9fd37718ad21821c464daf7fe8459d14517f6'><p>Something that always annoyed me is how tedious it is to install a Symfony project on a machine. Since I frequently need to intervene quickly on a project for work, and I was getting a brand-new machine, I really didn't want to create an apache <em>vhost</em> (let alone install Apache: it's painfully slow and its configuration is obscure and hard to debug), edit my <code>/etc/hosts</code> file, etc. for each project.</p>
<p>Moreover, developers are not system administrators and should not have to do complicated setups, especially when it turns out to be badly set up, and problems are "resolved" by "chmod 777" or "chmod 666" (which is indeed <a href="http://wordpress.org/development/2010/04/file-permissions/">evil</a>), a very sad but true practice promoted even by the developers of Symfony since there is a <code>symfony fix-perms</code><code> command that basically does that. It should have been named </code><code>symfony break-perms</code> or <code>symfony please-make-things-insecure-i-want-to-go-back-to-windows</code> or never been made.</p>
<p>On most non-PHP frameworks, there is a small embedded webserver that you can run on-demand. <strong>No configuration needed.</strong> Moreover, no special rights needed: a simple user can start it.</p>
<p>Since there was no such webserver written in PHP that was able to run Symfony properly, I chose to auto-configure <a href="http://www.lighttpd.net/">lighttpd</a> with a simple tool called <em>symfttpd</em>. The <code>genconf</code> tool was born.</p>
<p>However, I encountered another issue I didn't think of before: for each project, I had to <strong>create symbolic links</strong> to the Symfony source code (another practice of the Symfony community, and there is no proper alternative in the PHP world). Hence, I created <code>mksymlinks</code>. For the developer, it is very simple to use: configure once on the machine, once per project, and that's it.</p>
<p><code>genconf</code> only generates a configuration, which is still very practical for a system administrator; moreover it is flexible and well-tested. But it still required the develop to configure something, and there still was the rights problem.</p>
<p>Hence I created <code>spawn</code> which handles <strong>starting and stopping the webserver, just like non-PHP frameworks do</strong>. As a nice addition, it keeps server and PHP logs in the <code>log</code>folder of the project.</p>
<p><em>symfttpd</em> has even more uses; one I didn't think of at first was that it can automate the installation of a project on a continuous integration platform, and can start a webserver for functional testing (both are used daily at work).</p>
<p>One of the most important aspects of <em>symfttpd</em> is that <strong>all tools are independent</strong>: you can use only <code>mksymlinks</code> or <code>genconf</code> (though <code>spawn</code> more or less requires the use of both, it isn't set in stone). A system administrator will find use in <code>mksymlinks</code> and <code>genconf</code>, and a developer more in <code>mksymlinks</code> and <code>spawn</code>.</p>
<p>You'll find extensive documentation on the <a href="http://github.com/laurentb/symfttpd">project page</a>; what will follow is a quick tutorial for developers.</p>
<p><!-- more --></p>
<p><strong>Install the necessary packages:</strong></p>
<pre class="bash">&nbsp;
<span style="color: #808080; font-style: italic;"># Debian/Ubuntu</span>
aptitude <span style="color: #c20cb9; font-weight: bold;">install</span> php5-cgi php5-cli lighttpd
&nbsp;
<span style="color: #808080; font-style: italic;"># Gentoo</span>
emerge php <span style="color: #808080; font-style: italic;"># with <span style="color: #007800;">USE=</span></span><span style="color: #ff0000;">&quot;cli cgi&quot;</span>
emerge lighttpd <span style="color: #808080; font-style: italic;"># with <span style="color: #007800;">USE=</span></span><span style="color: #ff0000;">&quot;fastcgi&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Macports</span>
port <span style="color: #c20cb9; font-weight: bold;">install</span> php5 +fastcgi &amp;&amp; port <span style="color: #c20cb9; font-weight: bold;">install</span> lighttpd
&nbsp;
<span style="color: #808080; font-style: italic;"># Windows</span>
Nice try.
&nbsp;</pre>
<p><strong>Get the symfttpd source code:</strong></p>
<pre class="bash">&nbsp;
<span style="color: #7a0874; font-weight: bold;">cd</span> &amp;&amp; git clone git://github.com/laurentb/symfttpd.git
&nbsp;</pre>
<p>There are also archives you can download <a href="http://github.com/laurentb/symfttpd/downloads">here</a> if you want to avoid <em>git</em> or bleeding-edge changes.</p>
<p><strong>Basic configuration:</strong></p>
<pre class="bash">&nbsp;
<span style="color: #808080; font-style: italic;"># notice the dot before symfftpd.conf.php</span>
<span style="color: #007800;">$EDITOR</span> ~/.symfftpd.conf.php
&nbsp;</pre>
<p>Enter something like that:</p>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #0000ff;">$options</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'sf_path'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'1.0'</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #ff0000;">'/home/myuser/symfony/1.0'</span>;
<span style="color: #0000ff;">$options</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'sf_path'</span><span style="color: #66cc66;">&#93;</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'1.4'</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #ff0000;">'/home/myuser/symfony/1.4'</span>;
&nbsp;</pre>
<p>Of course, you have to have to adapt it to the Symfony versions you have installed and where you put them.</p>
<p><strong>Configure the project:</strong><br />
If the project is using Symfony 1.4 in the <code>lib/vendor/symfony</code>, you don't need to do anything. In case it is different, or to be on the safe side, create the file 	<code>config/symfttpd.conf.php</code> in your project. After, add the file to your project's version control repository. If you're lucky, someone already did it for you.</p>
</pre>
<pre class="bash">&nbsp;
<span style="color: #7a0874; font-weight: bold;">cd</span> ~/myproject
<span style="color: #808080; font-style: italic;"># this <span style="color: #000000; font-weight: bold;">time</span>, no dot</span>
<span style="color: #007800;">$EDITOR</span> config/symfttpd.conf.php
&nbsp;</pre>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #0000ff;">$options</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'want'</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #ff0000;">'1.3'</span>; <span style="color: #808080; font-style: italic;">// The version of Symfony used by your project</span>
<span style="color: #0000ff;">$options</span><span style="color: #66cc66;">&#91;</span><span style="color: #ff0000;">'lib_symlink'</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #ff0000;">'lib/vendor/symfony'</span>; <span style="color: #808080; font-style: italic;">// lib/vendor/symfony will lead to the &quot;lib&quot; directory of Symfony</span>
&nbsp;</pre>
</pre>
<pre class="bash">&nbsp;
~/symfttpd/mksymlinks
&nbsp;</pre>
<p>You're done.<br />
It will <strong>create symbolic links for plugins</strong> too, even if the version of Symfony (1.0 for instance) doesn't handle them!</p>
<p>To start the server:</p>
<pre class="bash">&nbsp;
~/symfttpd/spawn
&nbsp;</pre>
<p>It will then tell you how to access it. It's time to stop fighting with old, unpredictable software like Apache and start developing again!</p>
<p><strong>What's coming in future releases:</strong></p>
<ul>
<li>Colors</li>
<li>Interactive configuration</li>
<li>Server/PHP logs displayed in the terminal</li>
<li>Handling "sample" files</li>
<li>Custom configuration support on various places</li>
</ul>
<p>Contributors are welcome.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/TWFW4JnJjBc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/05/reducing-the-gap-between-symfony-and-non-php-frameworks/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/05/reducing-the-gap-between-symfony-and-non-php-frameworks/</feedburner:origLink></item>
		<item>
		<title>And I thought sfDoctrineGuardPlugin was bad…</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/ZK7udJ-hyqk/</link>
		<comments>http://laurent.bachelier.name/2010/04/and-i-thought-sfdoctrineguardplugin-was-bad%e2%80%a6/#comments</comments>
		<pubDate>Sat, 03 Apr 2010 10:34:09 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[random numbers]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=167</guid>
		<description><![CDATA[Update: You can safely ignore this angry rant as the issues have been fixed. I am speechless. While doAuthPlugin looks interesting (especially because it uses inheritance and not some silly secondary Profile table), on the topic of security it is worse than sfDoctrineGuardPlugin. Let's have a quick look at doAuthTools. public static function rememberHash&#40;User $user&#41; [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:b599bbc9440280bc0bad2d9d0b3f4916b61ef034'><p><em><strong>Update: You can safely ignore this angry rant as the issues have been fixed.</strong></em></p>
<p>I am speechless. While <a href="http://www.symfony-project.org/plugins/doAuthPlugin">doAuthPlugin</a> looks interesting (especially because it uses inheritance and not some silly secondary Profile table), on the topic of security it is worse than <a href="http://laurent.bachelier.name/2010/02/security-is-not-easy/">sfDoctrineGuardPlugin</a>.</p>
<p>Let's have a quick look at <a href="http://github.com/DavertMik/doAuthPlugin/blob/6a65d6d63e393a6c526134c48fb38ac622e3ec27/lib/doAuthTools.class.php">doAuthTools</a>.</p>
<pre class="php">  <span style="color: #000000; font-weight: bold;">public</span> <a href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #000000; font-weight: bold;">function</span> rememberHash<span style="color: #66cc66;">&#40;</span>User <span style="color: #0000ff;">$user</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">return</span> <a href="http://www.php.net/md5"><span style="color: #000066;">md5</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$user</span>-&gt;<span style="color: #006600;">getId</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #ff0000;">'-'</span>.<span style="color: #0000ff;">$user</span>-&gt;<span style="color: #006600;">getUsername</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<a href="http://www.php.net/substr"><span style="color: #000066;">substr</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$user</span>-&gt;<span style="color: #006600;">getPassword</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span></pre>
<p>There's the use of md5, which doesn't doesn't resist long to rainbow tables attacks nowadays, but the worst is what is used. No random data at all, no salt.<br />
The user id is most of the time public, the username almost always is, and for absolutely no reason <strong>only the first five characters of the password are used</strong>.</p>
<pre class="php">&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <a href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #000000; font-weight: bold;">function</span> activationCode<span style="color: #66cc66;">&#40;</span>User <span style="color: #0000ff;">$user</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">return</span> <a href="http://www.php.net/md5"><span style="color: #000066;">md5</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$user</span>-&gt;<span style="color: #006600;">getCreatedAt</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<a href="http://www.php.net/time"><span style="color: #000066;">time</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<span style="color: #0000ff;">$user</span>-&gt;<span style="color: #006600;">getUsername</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>.<a href="http://www.php.net/substr"><span style="color: #000066;">substr</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$user</span>-&gt;<span style="color: #006600;">getUsername</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">5</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span></pre>
<p><code>created_at</code> is easy to guess, <code>time()</code> is easy to guess and the rest is public. Again, what's with the use of <code>substr()</code>? I would also guess the author wanted to use the password and not the username.</p>
<pre class="php">&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <a href="http://www.php.net/static"><span style="color: #000066;">static</span></a> <span style="color: #000000; font-weight: bold;">function</span> generatePassword<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
    <span style="color: #b1b100;">return</span> <a href="http://www.php.net/substr"><span style="color: #000066;">substr</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/md5"><span style="color: #000066;">md5</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/rand"><span style="color: #000066;">rand</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">1000</span>,<span style="color: #cc66cc;">9999</span><span style="color: #66cc66;">&#41;</span>.<a href="http://www.php.net/time"><span style="color: #000066;">time</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>,<span style="color: #cc66cc;">0</span>,<span style="color: #cc66cc;">8</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p>Now this is just sad. Sure, even with the use of a-f0-9 there is still 16^8 possible passwords, but why not spend a little time and try to use all the available letters? It also means that if you know the user id and username, you know you only have 16^5 <em>rememberHashes</em> to brute-force, which is easily doable.</p>
<p>We've already seen that using <code>rand()</code> is bad, but restricting it is even worse. Why on earth? To sum up, the password is constructed from a poor random algorithm with under <abbr title="Not a good power level">9000</abbr> possible values, and an easily predictable timestamp.</p>
<p>Frightening.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/ZK7udJ-hyqk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/04/and-i-thought-sfdoctrineguardplugin-was-bad%e2%80%a6/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/04/and-i-thought-sfdoctrineguardplugin-was-bad%e2%80%a6/</feedburner:origLink></item>
		<item>
		<title>On Twitter</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/qT961KMRoV4/</link>
		<comments>http://laurent.bachelier.name/2010/03/on-twitter/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 12:53:17 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[web2.0]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=164</guid>
		<description><![CDATA[Joel Spolsky on Twitter: Although I appreciate that many people find Twitter to be valuable, I find it a truly awful way to exchange thoughts and ideas. It creates a mentally stunted world in which the most complicated thought you can think is one sentence long. It’s a cacophony of people shouting their thoughts into [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:f647dd089675c234b8571d4e2d4d8a23077e26d3'><p><a href="http://www.joelonsoftware.com/items/2010/03/14.html">Joel Spolsky on Twitter</a>:</p>
<blockquote><p>Although I appreciate that many people find Twitter to be valuable, I find it a truly awful way to exchange thoughts and ideas. It creates a mentally stunted world in which the most complicated thought you can think is one sentence long. It’s a cacophony of people shouting their thoughts into the abyss without listening to what anyone else is saying. Logging on gives you a page full of little hand grenades: impossible-to-understand, context-free sentences that take five minutes of research to unravel and which then turn out to be stupid, irrelevant, or pertaining to the television series <em>Battlestar Galactica</em>. I would write an essay describing why Twitter gives me a headache and makes me fear for the future of humanity, but it doesn’t deserve more than 140 characters of explanation, and I’ve already spent 820.</p></blockquote>
<p>I couldn't agree more.</p>
<p>I will also be far from being the first to say it, but Twitter is just a poor reimplementation of IRC over HTTP, which is completely inappropriate. Twitter is a constant failure with bad uptime, scalability issues and over-centralization. Twitter is one of the worst things that happened to the Web; it also promotes URL shorteners, which have security issues and double the possible unavailabilities.</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/qT961KMRoV4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/03/on-twitter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/03/on-twitter/</feedburner:origLink></item>
		<item>
		<title>Random fail</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/SUevUCxDaVo/</link>
		<comments>http://laurent.bachelier.name/2010/02/random-fail/#comments</comments>
		<pubDate>Sun, 28 Feb 2010 19:05:36 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[random numbers]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=161</guid>
		<description><![CDATA[Yet another case of trying to be too clever with randomness!]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:7d05d0813bdb1e98aa4d07f5bea11e41155eceab'><p>Yet <a href="http://www.robweir.com/blog/2010/02/microsoft-random-browser-ballot.html">another case</a> of trying to be too clever with randomness!</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/SUevUCxDaVo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/02/random-fail/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/02/random-fail/</feedburner:origLink></item>
		<item>
		<title>Security is not easy</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/ie5B3JdowUQ/</link>
		<comments>http://laurent.bachelier.name/2010/02/security-is-not-easy/#comments</comments>
		<pubDate>Sun, 07 Feb 2010 17:45:54 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[full disclosure]]></category>
		<category><![CDATA[random numbers]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=143</guid>
		<description><![CDATA[Update: After a year, both plugins are finally updated with a better random key generator. Security is not easy. Programmers should leave things like random number and identifier generation to a library (or at least research the best way to do it). A lot of projects learned it the hard way. Let's talk for instance [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:2a1fd3c9cf4af19e229610717ad2f7c770de82be'><p><em><strong>Update: After a year, both plugins are finally updated with a better random key generator.</strong></em></p>
<p>Security is not easy. Programmers should leave things like random number and identifier generation to a library (or at least research the best way to do it). A lot of projects learned it the hard way.</p>
<p>Let's talk for instance of a function I encountered about six months ago:</p>
<pre class="php"><span style="color: #000000; font-weight: bold;">function</span> generateRandomKey<span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$len</span> = <span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
  <span style="color: #0000ff;">$string</span> = <span style="color: #ff0000;">''</span>;
  <span style="color: #0000ff;">$pool</span>   = <span style="color: #ff0000;">'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'</span>;
  <span style="color: #b1b100;">for</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$i</span> = <span style="color: #cc66cc;">1</span>; <span style="color: #0000ff;">$i</span> &lt; = <span style="color: #0000ff;">$len</span>; <span style="color: #0000ff;">$i</span>++<span style="color: #66cc66;">&#41;</span>
  <span style="color: #66cc66;">&#123;</span>
    <span style="color: #0000ff;">$string</span> .= <a href="http://www.php.net/substr"><span style="color: #000066;">substr</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$pool</span>, <a href="http://www.php.net/rand"><span style="color: #000066;">rand</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span>, <span style="color: #cc66cc;">61</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #cc66cc;">1</span><span style="color: #66cc66;">&#41;</span>;
  <span style="color: #66cc66;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <a href="http://www.php.net/md5"><span style="color: #000066;">md5</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$string</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p>It is a real gem as it seems it was meant to concentrate everything a programmer should <em>not</em> do.</p>
<p><strong>Flaw 1: </strong> Using <code>rand()</code> instead of <code><a href="http://fr.php.net/manual/en/function.mt-rand.php">mt_rand()</a></code>. Any PHP programmer should know this.</p>
<p><strong>Flaw 2: </strong> Using <code><a href="http://en.wikipedia.org/wiki/MD5#Collision_vulnerability">md5</a>()</code> instead of <code>sha1()</code>. Any PHP programmer should know this too.</p>
<p><strong>Flaw 3: </strong> Generating a 20 character random string and then hashing it to a 32 character string looks a bit silly. Granted, the hash has less different characters, but still the input can have 7.04423e+35 different values while the output can have 3.40282e+38.</p>
<p><strong>Flaw 4: </strong> Calling rand() multiple times. It denotes a strong ignorance on how <a href="http://en.wikipedia.org/wiki/Pseudorandom_number_generator">pseudo-random number generators</a> work. Since the seed doesn't change, it can be easy to guess what will be the next number from the previous ones. It isn't "more random" to call it multiple times.</p>
<p><strong>Flaw 5: </strong> Using a very limited range for picking a random number. Also, why choose alphanumeric characters if you are not using them afterwards since they are passed to a hash function? This seems to be very badly designed.</p>
<p><strong>Flaw 6: </strong> Feeding md5 with alphanumeric characters, present in all the <a href="http://en.wikipedia.org/wiki/Rainbow_table">rainbow tables</a> in the world.</p>
<p><strong>Flaw 7: </strong> Ever heard of <code>chr()</code>?</p>
<p><strong>Flaw 8: </strong> Why reinvent the wheel? At least if you have a reason, leave a comment (no comments at all on this function).</p>
<p>Without even testing if the results are good or not, any programmer should know this function should be completely rewritten.</p>
<p>Let's see how it should have been done.</p>
</pre>
<pre class="php">&nbsp;
<span style="color: #000000; font-weight: bold;">function</span> generateRandomKey<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#123;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> <a href="http://www.php.net/base_convert"><span style="color: #000066;">base_convert</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/sha1"><span style="color: #000066;">sha1</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/uniqid"><span style="color: #000066;">uniqid</span></a><span style="color: #66cc66;">&#40;</span><a href="http://www.php.net/mt_rand"><span style="color: #000066;">mt_rand</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #000000; font-weight: bold;">true</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>, <span style="color: #cc66cc;">16</span>, <span style="color: #cc66cc;">36</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
<p><strong>How did I come up with this?</strong> Mostly be reading the PHP manual and not creating a random number generator, but merely using one.</p>
<p>The use of <code>base_convert()</code> is not really important, it is mostly because the database field was too short (nothing is lost from the <code>sha1()</code>). We actually would be better off without <code>sha1()</code> though, it is there mostly for the eye-candy.</p>
<p><code>uniqid()</code> will take the result of <code>mt_rand()</code> and append it an unique value (but in a predictable range, hence the use of both functions). This is recommended by the PHP manual and is more than enough.</p>
<p>Now you're probably asking yourself where did I find this piece of code.</p>
<p>It is in <a href="http://www.symfony-project.org/plugins/sfGuardPlugin">sfGuardPlugin</a> and <a href="http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin">sfDoctrineGuardPlugin</a>, for the <a href="http://www.symfony-project.org/about"><strong>symfony</strong></a> framework. It's here almost from the <a href="http://trac.symfony-project.org/changeset/2343">start</a>, though it was <a href="http://trac.symfony-project.org/changeset/4644">even</a> <a href="http://trac.symfony-project.org/changeset/4713">wronger</a>. Those are by far the most used plugins, and are endorsed by the official documentation.</p>
<p><strong>What does this mean?</strong> On some systems, it will be very easy to brute-force the cookie to log in as any user. Or an user could accidentally become logged as another one, since collisions are highly likely.</p>
<p><em>Come on, if this is real, someone would have spotted it! I is probably not exploitable.</em><br />
Actually, it is. I have been able to reproduce it on an older Debian server, and on this server was a website where users reported multiple times getting identified as another user (hopefully this server is retired and the project now runs on the fixed function).<br />
I also tried to reproduce it on a Windows XP virtual machine (since it was the easiest way to get a PHP with a flawed random number generator) with <a href="http://laurent.bachelier.name/wp-content/uploads/2010/02/2010-02-05-102444_1280x1024_scrot.png">success</a>. Since on these two machines I got a <em>lot</em> of collisions, even on better systems the flaw should be exploitable with some effort.</p>
<p><strong>Why am I doing this?</strong><br />
Because I <a href="http://trac.symfony-project.org/ticket/7018">reported</a> it six month ago, and it received very little attention.<br />
I think symfony is great, but the handling of security isn't (though my other <a href="http://groups.google.com/group/symfony-devs/msg/1811c52925367bdb">criticisms</a> are more on standard programming or hosting practices encouraged by symfony than on the code; more on the latter in a coming article, be sure to <a href="http://laurent.bachelier.name/feed/">subscribe</a>).</p>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/ie5B3JdowUQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2010/02/security-is-not-easy/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2010/02/security-is-not-easy/</feedburner:origLink></item>
		<item>
		<title>Extract from Doctrine_Record</title>
		<link>http://feedproxy.google.com/~r/laurentb/~3/vUxsh2p_8Zc/</link>
		<comments>http://laurent.bachelier.name/2009/07/extract-from-doctrine-record/#comments</comments>
		<pubDate>Fri, 03 Jul 2009 10:58:06 +0000</pubDate>
		<dc:creator>Laurent</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[funny]]></category>

		<guid isPermaLink="false">http://laurent.bachelier.name/?p=126</guid>
		<description><![CDATA[&#160; /** * returns an array of modified fields and associated values * @return array * @todo What about a better name? getModifiedFields? */ public function getModified&#40;&#41; &#123; $a = array&#40;&#41;; &#160; foreach &#40;$this-&#62;_modified as $k =&#62; $v&#41; &#123; $a&#91;$v&#93; = $this-&#62;_data&#91;$v&#93;; &#125; return $a; &#125; &#160; /** * REDUNDANT? */ public function modifiedFields&#40;&#41; &#123; [...]]]></description>
			<content:encoded><![CDATA[<div class='microid-mailto+http:sha1:89e51025eaf4ef6f23a16a49c3fcd28dd1a2c234'><pre class="php">&nbsp;
    <span style="color: #808080; font-style: italic;">/**
     * returns an array of modified fields and associated values
     * @return array
     * @todo What about a better name? getModifiedFields?
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getModified<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #0000ff;">$a</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
        <span style="color: #b1b100;">foreach</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;_modified <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$k</span> =&gt; <span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
            <span style="color: #0000ff;">$a</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #0000ff;">$this</span>-&gt;_data<span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#93;</span>;
        <span style="color: #66cc66;">&#125;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$a</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">/**
     * REDUNDANT?
     */</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> modifiedFields<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>
    <span style="color: #66cc66;">&#123;</span>
        <span style="color: #0000ff;">$a</span> = <a href="http://www.php.net/array"><span style="color: #000066;">array</span></a><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span>;
&nbsp;
        <span style="color: #b1b100;">foreach</span> <span style="color: #66cc66;">&#40;</span><span style="color: #0000ff;">$this</span>-&gt;_modified <span style="color: #b1b100;">as</span> <span style="color: #0000ff;">$k</span> =&gt; <span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&#123;</span>
            <span style="color: #0000ff;">$a</span><span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#93;</span> = <span style="color: #0000ff;">$this</span>-&gt;_data<span style="color: #66cc66;">&#91;</span><span style="color: #0000ff;">$v</span><span style="color: #66cc66;">&#93;</span>;
        <span style="color: #66cc66;">&#125;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">$a</span>;
    <span style="color: #66cc66;">&#125;</span>
&nbsp;</pre>
</div><img src="http://feeds.feedburner.com/~r/laurentb/~4/vUxsh2p_8Zc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://laurent.bachelier.name/2009/07/extract-from-doctrine-record/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://laurent.bachelier.name/2009/07/extract-from-doctrine-record/</feedburner:origLink></item>
	</channel>
</rss>
