<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Labix Blog</title>
	<atom:link href="http://blog.labix.org/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.labix.org</link>
	<description>by Gustavo Niemeyer</description>
	<lastBuildDate>Fri, 09 Jul 2010 19:15:49 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Python has a GIL, and lots of complainers</title>
		<link>http://blog.labix.org/2010/07/09/python-has-a-gil-and-lots-of-complainers</link>
		<comments>http://blog.labix.org/2010/07/09/python-has-a-gil-and-lots-of-complainers#comments</comments>
		<pubDate>Fri, 09 Jul 2010 19:15:49 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=381</guid>
		<description><![CDATA[I&#8217;ve just read a post by Brett Cannon where, basically, he complains about complainers. If you don&#8217;t know who Brett is, you&#8217;re probably not a heavy Python user. Brett is a very important Python core developer which has been around &#8230; <a href="http://blog.labix.org/2010/07/09/python-has-a-gil-and-lots-of-complainers">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just read <a href="http://sayspy.blogspot.com/2010/07/two-types-of-people-who-cause-biggest.html">a post by Brett Cannon</a> where, basically, he complains about complainers.</p>
<p>If you don&#8217;t know who Brett is, you&#8217;re probably not a heavy Python user.  Brett is a very important Python core developer which has been around for a while and who does a great job at it.  His post, though, makes me a bit sad.</p>
<p><span id="more-381"></span>Brett points out that there are two types of personalities which do not contribute to open source.  The first one he defines as:</p>
<blockquote><p>
The first type is the &#8220;complainer&#8221;. This is someone who finds something they don&#8217;t like, points out that the thing they don&#8217;t like is suboptimal, but then offers no solutions.
</p></blockquote>
<p>And the second one is defined as:</p>
<blockquote><p>
(&#8230;) This is someone who, upon finding out about a decision that they think was sub-optimal, decides to bring up new ideas and solutions. The person is obviously trying to be helpful by bringing up new ideas and solutions, thinking that the current one is simply going to flop and they need to stop people from making a big mistake.  The thing is, this person is not helping. (&#8230;)
</p></blockquote>
<p>This, on itself, is already shortsighted. If you&#8217;re tired of hearing the same arguments again and again for 10 years, from completely different people, there&#8217;s a pretty good chance that there&#8217;s an actual issue with your project, and your users are trying in their way to contribute and interact with you in the hope that it might get fixed.</p>
<p>This is really important:  They are <i>people</i>, which <i>use your project</i>, and are trying to <i>improve it</i>. If you can&#8217;t stand that, you should stop maintaining an open source project now, or pick something which no one cares about.</p>
<p>The other issue which took my attention in his post is his example: the Python GIL.  Look at the way in which Brett dismisses the problem:</p>
<blockquote><p>
(I am ignoring the fact that few people write CPU-intensive code requiring true threading support, that there is the multiprocessing library, true power users have extension  modules which do operate with full threading, and that there are multiple VMs out there with a solution that have other concurrency solutions)
</p></blockquote>
<p>Brett, we can understand that <a href="http://www.artima.com/weblogs/viewpost.jsp?thread=214235">the GIL is hard to remove</a>, but it&#8217;s a <a href="http://www.dabeaz.com/GIL/">fundamental flaw in the most important Python implementation</a>, and being dismissive about it will either draw further complaints at you, or will simply drive users away from the language entirely.</p>
<p>I can understand why you think this way, though.  Guido presents the same kind of feeling about the GIL for a very long time.  Here is one excerpt from a <a href="http://mail.python.org/pipermail/python-3000/2007-May/007414.html">mail thread about it</a>:</p>
<blockquote><p>
Nevertheless, you&#8217;re right the GIL is not as bad as you would initially think: you just have to undo the brainwashing you got from Windows and Java proponents who seem to consider threads as the only way to approach concurrent activities.</p>
<p>Just Say No to the combined evils of locking, deadlocks, lock granularity, livelocks, nondeterminism and race conditions.
</p></blockquote>
<p>I apologize, but I have a very hard time reading this and not complaining.</p>
<p>In my world, the golden days of geometric growth in vertical processing power is over, multi-processed machines are here to stay, and the amount of traffic flowing through networks is just increasing.  It feels reasonable to desire a less naïve approach to deal with real world problems, such as executing tasks concurrently.</p>
<p>I actually would love to not worry about things like non-determinism and race conditions, and would love even more to have a <i>programming language</i> which helps me with that!</p>
<p>Python, though, has a Global Interpreter Lock (yes, I&#8217;m talking about CPython, the most important interpreter).  Python programs execute in sequence.  No <a href="http://www.infoq.com/interviews/doug-lea-fork-join">Fork/Join frameworks</a>, no <a href="http://golang.org">coroutines</a>, no <a href="http://erlang.org">lightweight processes</a>, nothing.  Your <i>Python</i> code <i>will execute in sequence</i> if it lives in the same process space.</p>
<p>The answer from Brett and Guido to concurrency?  Develop your code in C, or write your code to execute in multiple processes.  If they really want people to get rid of non-determinism, locking issues, race conditions, and so on, they&#8217;re not helping at all.</p>
<p>I know this is just yet another complaint, though. I honestly cannot fix the problem either, and rather just talk about it in the hope that someone who&#8217;s able to do it will take care of it.  That said, I wish that the language maintainers would <i>do the same</i>, and tell the world that it&#8217;s an unfortunate problem, and that they wished someone else would go there and fix it!  If, instead, maintainers behave in a ridiculously dismissive way, like Guido did in that mail thread, and like Brett is doing in his post, the smart people that could solve the problem get turned down.  People like to engage with motivated maintainers.. they like to solve problems that others are interested in seeing solved.</p>
<p>Perhaps agreeing with the shortcomings won&#8217;t help, though, and no one will show up to fix the problem either. But then, at least users will know that the maintainers are on the same side of the fence, and the hope that it will get fixed survives.  If the maintainers just complain about the users which complain, and dismiss the problem, users are put in an awkward position.  I can&#8217;t complain.. I can&#8217;t provide ideas or solutions.. I can&#8217;t fix the problem.. they don&#8217;t even <i>care</i> about the problem.  Why am I using this thing at all?</p>
<p>Would you rather have users, or have no complainers?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/07/09/python-has-a-gil-and-lots-of-complainers/feed</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>Support for Launchpad and Bazaar in goinstall</title>
		<link>http://blog.labix.org/2010/07/03/support-for-launchpad-and-bazaar-in-goinstall</link>
		<comments>http://blog.labix.org/2010/07/03/support-for-launchpad-and-bazaar-in-goinstall#comments</comments>
		<pubDate>Sat, 03 Jul 2010 19:17:57 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Go]]></category>
		<category><![CDATA[Patch]]></category>
		<category><![CDATA[RCS]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=355</guid>
		<description><![CDATA[The patch submitted last weekend to support Launchpad and Bazaar in goinstall went in! This means that once the next release of Go is out (or you sync up with the tip code) you&#8217;ll be able to host modules for &#8230; <a href="http://blog.labix.org/2010/07/03/support-for-launchpad-and-bazaar-in-goinstall">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://codereview.appspot.com/1699050">patch submitted last weekend</a> to support <a href="https://launchpad.net">Launchpad</a> and <a href="http://bazaar.canonical.com/">Bazaar</a> in <a href="http://golang.org/cmd/goinstall/">goinstall</a> went in!</p>
<p>This means that once the next release of <a href="http://golang.org">Go</a> is out (or you sync up with the tip code) you&#8217;ll be able to host modules for Go in Launchpad and people will be able to install it by running something similar to:</p>
<p><span id="more-355"></span></p>
<blockquote><p>
goinstall launchpad.net/yourproject
</p></blockquote>
<p>Then, you can simply use that in your source code as:</p>
<blockquote><p>
import &#8220;launchpad.net/yourproject&#8221;
</p></blockquote>
<p>The following URLs are supported:</p>
<blockquote><p>
import &#8220;launchpad.net/project&#8221;<br />
import &#8220;launchpad.net/project/series&#8221;<br />
import &#8220;launchpad.net/project/series/sub/directory&#8221;</p>
<p>import &#8220;launchpad.net/~user/project/branch&#8221;<br />
import &#8220;launchpad.net/~user/project/branch/sub/directory&#8221;</p>
<p>import &#8220;launchpad.net/~user/+junk/branch&#8221;<br />
import &#8220;launchpad.net/~user/+junk/branch/sub/directory&#8221;
</p></blockquote>
<p>Where you see <i>sub/directory</i> above, it means the module to be compiled, installed, and used, may be inside a subdirectory in the Bazaar branch itself. This is a convention used in all supported backends of goinstall.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/07/03/support-for-launchpad-and-bazaar-in-goinstall/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mocker 1.0 for Python released!</title>
		<link>http://blog.labix.org/2010/06/20/mocker-1-0-for-python-released</link>
		<comments>http://blog.labix.org/2010/06/20/mocker-1-0-for-python-released#comments</comments>
		<pubDate>Mon, 21 Jun 2010 00:09:02 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Project]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Test]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=323</guid>
		<description><![CDATA[After a few years in development, version 1.0 of Mocker is now available! Check out the changes since 0.10.1, the supported features, or go straight to the download page.]]></description>
			<content:encoded><![CDATA[<p>After a few years in development, version 1.0 of <a href="http://bit.ly/dm0GGy" _href="http://labix.org/mocker">Mocker</a> is now <a href="http://bit.ly/dez9jQ" _href="https://launchpad.net/mocker/trunk/1.0">available</a>!  Check out the <a href="http://bit.ly/czhiru " _href="http://bazaar.launchpad.net/~niemeyer/mocker/trunk/annotate/head:/NEWS">changes since 0.10.1</a>, the <a href="http://bit.ly/dm0GGy" _href="http://labix.org/mocker">supported features</a>, or go straight to the <a href="http://bit.ly/9Wszmp" _href="https://launchpad.net/mocker/+download">download page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/06/20/mocker-1-0-for-python-released/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Integrating IRC with LDAP and two-way SMSing</title>
		<link>http://blog.labix.org/2010/06/19/integrating-irc-with-ldap-and-two-way-smsing</link>
		<comments>http://blog.labix.org/2010/06/19/integrating-irc-with-ldap-and-two-way-smsing#comments</comments>
		<pubDate>Sat, 19 Jun 2010 21:56:07 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Erlang]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Project]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=296</guid>
		<description><![CDATA[A bit of history I don&#8217;t know exactly why, but I&#8217;ve always enjoyed IRC bots. Perhaps it&#8217;s the fact that it emulates a person in an easy-to-program way, or maybe it&#8217;s about having a flexible and shared &#8220;command line&#8221; tool, &#8230; <a href="http://blog.labix.org/2010/06/19/integrating-irc-with-ldap-and-two-way-smsing">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><b>A bit of history</b></p>
<p>I don&#8217;t know exactly why, but I&#8217;ve always enjoyed IRC bots.  Perhaps it&#8217;s the fact that it emulates a person in an easy-to-program way, or maybe it&#8217;s about having a flexible and shared &#8220;command line&#8221; tool, or maybe it&#8217;s just the fact that it helps people perceive things in an asynchronous way without much effort.  Probably a bit of everything, actually.</p>
<p><span id="more-296"></span></p>
<p>My bot programming started with <a href="http://labix.org/pybot">pybot</a> many years ago, when I was still working at <a href="http://www.conectiva.com.br">Conectiva</a>.  Besides having many interesting features, this bot eventually got in an abandonware state, since <a href="http://www.canonical.com">Canonical</a> already had pretty much equivalent features available when I joined, and I had other interests which got in the way.  The code was a bit messy as well.. it was a time when I wasn&#8217;t very used to testing software properly (a friend has a great excuse for that kind of messy software: <i>&#8220;I was young, and needed the money!&#8221;</i>).</p>
<p>Then, a couple of years ago, while working in the <a href="http://landscape.canonical.com">Landscape</a> project, there was an opportunity of getting some information more visible to the team.  Coincidently, it was also a time when I wanted to get some practice with the concepts of <a href="http://erlang.org">Erlang</a>, so I decided to write a bot from scratch with some nice support for plugins, just to get a feeling of how the promised stability of Erlang actually took place for real.  This bot is called <a href="https://launchpad.net/mup">mup</a> (Mup Pet, more formally), and its code is available publicly through <a href="https://launchpad.net/mup">Launchpad</a>.</p>
<p>This was a nice experiment indeed, and I did learn quite a bit about the ins and outs of Erlang with it.  Somewhat unexpected, though, was the fact that the bot grew up a few extra features which multiple teams in Canonical started to appreciate.  This was of course very nice, but it also made it more obvious that the egocentric reason for having a bot written in Erlang would now hurt, because most of Canonical&#8217;s own coding is done in Python, and that&#8217;s what internal tools should generally be written in for everyone to contribute and help maintaining the code.</p>
<p>That&#8217;s where the desire of migrating mup into a Python-based brain again came from, and having a new feature to write was the perfect motivator for this.</p>
<p><b>LDAP and two-way SMSing over IRC</b></p>
<p>Canonical is a <i>very</i> distributed company.  Employees are distributed over dozens of countries, literally.  Not only that, but most people also work from their homes, rather than in an office.  Many different countries also means many different timezones, and working from home with people from different timezones means flexible timing.  All of that means communication gets&#8230; well.. interesting.</p>
<p>How do we reach someone that should be in an online meeting and is not?  Or someone that is traveling to get to a sprint?  Or how can someone that has no network connectivity reach an IRC channel to talk to the team?  There are probably several answers to this question, but one of them is of course SMS.  It&#8217;s not exactly cheap if we consider the cost of the data being transfered, but pretty much everyone has a mobile phone which can do SMS, and the model is not that far away from IRC, which is the main communication system used by the company.</p>
<p>So, the itch was itching.  Let&#8217;s scratch it!</p>
<p>Getting the mobile phone of employees was already a solved problem for mup, because it had a plugin which could interact with the LDAP directory, allowing people to do something like this:</p>
<blockquote><p>
&lt;joe&gt; mup: poke gustavo<br />
&lt;mup&gt; joe: niemeyer is Gustavo Niemeyer &lt;&#8230;@canonical.com&gt; &lt;time:&#8230;&gt; &lt;mobile:&#8230;&gt;
</p></blockquote>
<p>This just had to be migrated from Erlang into a Python-based brain for the reasons stated above. This time, though, there was no reason to write something from scratch.  I could even have used pybot itself, but there was also <a href="http://sourceforge.net/projects/supybot/">supybot</a>, an IRC bot which started around the same time I wrote the first version of pybot, and unlike the latter, supybot&#8217;s author was much more diligent in evolving it.  There is quite a comprehensive list of plugins for supybot nowadays, and it includes means for testing plugins and so on.  The choice of using it was straighforward, and getting &#8220;<i>poke</i>&#8221; support ported into a plugin wasn&#8217;t hard at all.</p>
<p>So, on to SMSing.  Canonical already had a contract with an SMS gateway company which we established to test-drive some ideas on <a href="https://landscape.canonical.com">Landscape</a>. With the mobile phone numbers coming out of the LDAP directory in hands and an SMS contract established, all that was needed was a plugin for the bot to talk to the SMS gateway.  That &#8220;conversation&#8221; with the SMS gateway allows not only sending messages, but also receiving SMS messages which were sent to a specific number.</p>
<p>In practice, this means that people which are connected to IRC can very easily deliver an SMS to someone using their nicks.  Something like this:</p>
<blockquote><p>
&lt;joe&gt; @sms niemeyer Where are you?  We&#8217;re waiting!
</p></blockquote>
<p>And this would show up in the mobile screen as:</p>
<blockquote><p>
joe&gt; Where are you?  We&#8217;re waiting!
</p></blockquote>
<p>In addition to this, people which have <i>no connectivity</i> can also contact individuals and channels on IRC, with mup working as a middle man.  The message would show up on IRC in a similar way to:</p>
<blockquote><p>
&lt;mup&gt; [SMS] &lt;niemeyer&gt; Sorry, the flight was delayed. Will be there in 5.
</p></blockquote>
<p>The communication from the bot to the gateway happens via plain HTTPS.  The communication back is a bit more complex, though.  There is a small proxy service deployed in <a href="http://code.google.com/appengine">Google App Engine</a> to receive messages from the SMS gateway.  This was done to avoid losing messages when the bot itself is taken down for maintenance.  The SMS gateway doesn&#8217;t handle this case very well, so it&#8217;s better to have something which will be up most of the time buffering messages.</p>
<p>A picture is worth 2<sup>10</sup> words, so here is a simple diagram explaining how things got linked together:</p>
<p><a href="http://blog.labix.org/wp-content/uploads/2010/06/mup-sms.png"><img src="http://blog.labix.org/wp-content/uploads/2010/06/mup-sms.png" alt="" title="SMS integration diagram" width="449" height="255" class="aligncenter size-full wp-image-308" /></a></p>
<p>This is now up for experimentation, and so far it&#8217;s working nicely.  I&#8217;m hoping that in the next few weeks we&#8217;ll manage to port the rest of mup into the supybot-based brain.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/06/19/integrating-irc-with-ldap-and-two-way-smsing/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Released editmoin 1.15</title>
		<link>http://blog.labix.org/2010/06/19/released-editmoin-1-15</link>
		<comments>http://blog.labix.org/2010/06/19/released-editmoin-1-15#comments</comments>
		<pubDate>Sat, 19 Jun 2010 19:15:18 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Project]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=291</guid>
		<description><![CDATA[Version 1.15 of editmoin is now available. The following changes were made: Moin used to work with numerical IDs for identification, and editmoin was still based on this model. This release adds support for direct authentication as available in current &#8230; <a href="http://blog.labix.org/2010/06/19/released-editmoin-1-15">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Version 1.15 of <a href="http://labix.org/editmoin">editmoin</a> is now available.</p>
<p>The following changes were made:</p>
<ul>
<li> Moin used to work with numerical IDs for identification, and editmoin was still based on this model. This release adds support for direct authentication as available in current Moin releases.  This was inspired by Reimar Bauer.
<li> The new file ~/.moin_users is now parsed to obtain usernames, supporting the feature above.  Shortcuts are also supported in this file.
<li> Added support for textcha question handling.
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/06/19/released-editmoin-1-15/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The forgotten art of error checking</title>
		<link>http://blog.labix.org/2010/06/17/the-forgotten-art-of-error-checking</link>
		<comments>http://blog.labix.org/2010/06/17/the-forgotten-art-of-error-checking#comments</comments>
		<pubDate>Thu, 17 Jun 2010 15:15:59 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Go]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Lua]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[Test]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=275</guid>
		<description><![CDATA[I was just rambling randomly yesterday, in the usual microblogging platforms, about how result checking seems to be ignored or done badly. The precise wording was: It&#8217;s really amazing how little attention error handling receives in most software development. Even &#8230; <a href="http://blog.labix.org/2010/06/17/the-forgotten-art-of-error-checking">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I was just rambling randomly yesterday, in the usual microblogging platforms, about how result checking seems to be ignored or done badly.  The precise wording was:</p>
<blockquote><p>
It&#8217;s really amazing how little attention error handling receives in most software development. Even *tutorials* often ignore it.
</p></blockquote>
<p>It indeed does amaze me.  It sometimes feels like we write code for theoretical perfect worlds.. <i>&#8220;If the processor executes exactly in this order, and the weather is calm, this program will work.&#8221;</i>.  There are countless examples of bad assumptions.. someday I will come with some statistics of the form <i>&#8220;Every N seconds someone forgets to check the result of write().&#8221;</i>.</p>
<p><span id="more-275"></span></p>
<p>If you are a teacher, or a developer that enjoys writing snippets of code to teach people, please join me in the quest of building a better future.  Do <i>not</i> tell us that you&#8217;re &#8220;avoiding result checking for terseness&#8221;, because that&#8217;s exactly what we people will do (terseness is good, right?).  On the contrary, take this chance to make us feel <i>bad</i> about avoiding result checking.  You might do this by putting a comment like &#8220;If you don&#8217;t do this, you&#8217;re a bad programmer.&#8221; right next to the logic which is handling the result, and might take this chance to teach people how proper result handling is done.</p>
<p>Of course, there&#8217;s another forgotten art related to result checking.  It sits on the other side of the fence.  If you are a library author, do think through about how you plan to make us check conditions which happen inside your library, and try to imagine how to make our lives easier.  If we suck at handling results when there are obvious ways to handle it, you can imagine what happens when you structure your result logic badly.</p>
<p>Here is a clear example of what <i>not</i> to do, coming straight from Python&#8217;s standard library, in the <i>imaplib</i> module:</p>
<pre>
    def login(self, user, password):
        typ, dat = self._simple_command('LOGIN', user, self._quote(password))
        if typ != 'OK':
            raise self.error(dat[-1])
        self.state = 'AUTH'
        return typ, dat
</pre>
<p>You see the problem there?  How do you handle errors from this library?  Should we catch the exception, or should we verify the result code? <i>&#8220;Both!&#8221;</i> is the right answer, unfortunately, because the author decided to do us a little favor and check the error condition himself in some arbitrary cases and raise the error, while letting it go through and end up in the result code in a selection of other arbitrary cases.</p>
<p>I may provide some additional advice on result handling in the future, but for now I&#8217;ll conclude with the following suggestion: please check the results from your actions, and help others to check theirs.  That&#8217;s a good life-encompassing recommendation, actually.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/06/17/the-forgotten-art-of-error-checking/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Xpresser &#8211; Python library for GUI automation with image matching</title>
		<link>http://blog.labix.org/2010/05/18/xpresser-python-library-for-gui-automation-with-image-matching</link>
		<comments>http://blog.labix.org/2010/05/18/xpresser-python-library-for-gui-automation-with-image-matching#comments</comments>
		<pubDate>Tue, 18 May 2010 20:43:24 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Project]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Test]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=267</guid>
		<description><![CDATA[In a hurry? Go check it out! The context A while ago I found out about Sikuli, a very interesting project which allows people to script actions in GUIs based on screenshot excerpts. The idea is that you basically take &#8230; <a href="http://blog.labix.org/2010/05/18/xpresser-python-library-for-gui-automation-with-image-matching">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><b>In a hurry?</b></p>
<p><a href="http://wiki.ubuntu.com/Xpresser">Go check it out!</a></p>
<p><b>The context</b></p>
<p>A while ago I found out about <a href="http://sikuli.org">Sikuli</a>, a very interesting project which allows people to script actions in GUIs based on screenshot excerpts.  The idea is that you basically take images representing portions of your screen, like a button, or a label, or an icon, and then create a script which can detect a position in the screen which resembles one of these images, and perform actions on them, such as clicking, or hovering.</p>
<p><span id="more-267"></span></p>
<p>I had never imagined something like this, and the idea got me really excited about the possibilities.   Imagine, for instance, what can be done in terms of testing.  Testing of GUIs is unfortunately not yet a trivial task nowadays.  We do have frameworks which are based on accessibility hooks, for instance, but these sometimes can&#8217;t be used because the hook is missing, or is even far off in terms of the context being tested (imagine testing that a browser can open a specific flash site successfully, for instance).</p>
<p>So, Sikuli opened my eyes to the possibility of using image matching technology in a GUI automation context, and I really wanted to play with it.  In the days following the discovery, I fiddled a bit, communicated with the author, and even submitted some changes to make it work well in Ubuntu.</p>
<p>Then, the idea cooled down in my head, and I moved on with life.  Well&#8230; until two weeks ago.</p>
<p>Right before heading to the <a href="http://wiki.ubuntu.com/UDS-M">Ubuntu Developer Summit</a> for the next Ubuntu release, the desire of automating GUIs appeared again in the context of the widely scoped Ubuntu-level testing suite.  Then, over the first few days last week, I was able to catch up with quite a few people which were interested in the concept of automating GUIs, with different purposes (testing, design approval, etc), which of course was all I needed to actually push that old desire forward.</p>
<p>Trying to get Sikuli to work, though, was quite painful.  Even though I had sent patches upstream before, it looks like the build process isn&#8217;t working in Ubuntu again for other reasons (it&#8217;s not a polished build process, honestly), and even if I managed to make it work and contributed that to the upstream, in the end the path to integrate the Java-based tool in the Python-based testing framework which Ubuntu uses (<a href="https://launchpad.net/mago">Mago</a>) wasn&#8217;t entirely straightforward either.</p>
<p><b>Reinventing the wheel</b></p>
<p>So, the the itch was in place, and there was a reason to let the <a href="http://en.wikipedia.org/wiki/Not_Invented_Here">NIH</a> syndrome take over a bit.  Plus, image processing is something I&#8217;d like to get a foot in anyway, so it felt like a good chance to have a closer look and at the same time contribute a small bit to potential quality improvements of Ubuntu.</p>
<p>That&#8217;s when <a href="http://wiki.ubuntu.com/Xpresser">Xpresser</a> was born.  Xpresser is a clean room implementation of the concepts explored by Sikuli, in the form of a Python library which can be used standalone, or embedded into other programs and testing frameworks such as Mago.</p>
<p>The project is sponsored by <a href="http://canonical.com">Canonical</a>, and licensed under the LGPL.</p>
<p>Internally, it makes use of opencv for the image matching, pyatspi for the event generation (mouse clicks, etc), gtk for screen capturing and testing (of itself), and numpy for matrix operations. Clearly, the NIH syndrome, wasn&#8217;t <i>entirely</i> active. <img src='http://blog.labix.org/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />   As a side note, I haven&#8217;t played with numpy and gtk for some time, and I&#8217;m always amazed by the quality of these modules.</p>
<p><b>Contribute code and ideas</b></p>
<p>Concluding this post, which is already longer than I expected, the basics of Xpresser are in place, so go ahead and play with it!  That said, there are quite a few low hanging fruits to get it to a point of being a really compelling GUI-driving library, so if you have any interest in the concept, I invite you to play with the code and submit contributions too.  If you want ideas of what else could be done, let&#8217;s have a chat.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/05/18/xpresser-python-library-for-gui-automation-with-image-matching/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Recovering a bootable EBS image</title>
		<link>http://blog.labix.org/2010/03/09/recovering-a-bootable-ebs-image</link>
		<comments>http://blog.labix.org/2010/03/09/recovering-a-bootable-ebs-image#comments</comments>
		<pubDate>Tue, 09 Mar 2010 21:45:43 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Article]]></category>
		<category><![CDATA[Cloud]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=250</guid>
		<description><![CDATA[Scott Moser has just announced this week that the new Ubuntu images which boot out of an EBS-based root filesystem in EC2, and thus will persist across reboots, are available for testing. As usual with something that just left the &#8230; <a href="http://blog.labix.org/2010/03/09/recovering-a-bootable-ebs-image">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Scott Moser has <a href="https://lists.ubuntu.com/archives/ubuntu-cloud/2010-March/000155.html">just announced</a> this week that the new Ubuntu images which boot out of an EBS-based root filesystem in EC2, and thus will persist across reboots, are available for testing.</p>
<p>As usual with something that just left the oven and is explicitly labeled <i>for testing purposes</i>, there was a minor bug in the first iteration of images which was even mentioned in the announcement itself.  The bug, if not worked around as specified in the announcement, will prevent the image from rebooting.</p>
<p>Having an bootable EBS image which can&#8217;t reboot is a quite interesting (and ironic) problem.  You have an image which persists, but suddenly you have no way to see what is inside the image anymore because you can&#8217;t boot it.  Naturally, even if the said bug didn&#8217;t exist in the first place, it&#8217;s fairly easy to get into such a situation accidentally if you&#8217;re fiddling with the image configuration.</p>
<p>So, in this post we&#8217;ll see how to recover from a situation where a bootable EBS image can&#8217;t boot.</p>
<p><span id="more-250"></span></p>
<p><b>Getting started</b></p>
<p>To start this up, we&#8217;ll boot one of the EBS images which Scott mentioned in his announcement: ami-8bec03e2.  As we see in the output of <i>ec2-describe-images</i>, this is an EBS-based image for <i>i386</i>:</p>
<blockquote><p>
% ec2-describe-images ami-8bec03e2<br />
IMAGE	ami-8bec03e2	099720109477/ebs/ubuntu-images-testing/ubuntu-lucid-daily-i386-server-20100305	099720109477	available	public		i386	machine	aki-3fdb3756			ebs<br />
BLOCKDEVICEMAPPING	/dev/sda1		snap-f1efd098	15
</p></blockquote>
<p>Let&#8217;s run this image.  Remember to replace the value passed in the <i>-k</i> command line option with your own key pair name.</p>
<blockquote><p>
% ec2-run-instances -k gsg-keypair ami-8bec03e2<br />
RESERVATION	r-9e4615f6	626886203892	default<br />
INSTANCE	i-e3e33a88	ami-8bec03e2			pending	gsg-keypair	0		m1.small	2010-03-09T20:04:12+0000	us-east-1c	aki-3fdb3756			monitoring-disabled			ebs
</p></blockquote>
<p>There we go.  We got an instance allocated in the availability zone us-east-1c.  It&#8217;s important to keep track of this information, since EBS volumes are zone-specific.</p>
<p>As part of the above command, we must have been allocated an EBS volume automatically, and it should be attached to the instance we just started.  We can investigate it with the <i>ec2-describe-volumes</i> command:</p>
<blockquote><p>
% ec2-describe-volumes<br />
VOLUME	vol-edca1684	15	snap-f1efd098	us-east-1c	in-use	2010-03-09T20:04:20+0000<br />
ATTACHMENT	vol-edca1684	i-e3e33a88	/dev/sda1	attached	2010-03-09T20:04:24+0000
</p></blockquote>
<p>Now, we&#8217;ll get into the running instance and do some arbitrary modifications, just as a way to demonstrate that the data we don&#8217;t want to lose actually survives the recovering operation. Note that the domain name is obtained with the <i>ec2-describe-instances</i> command.</p>
<blockquote><p>
% ssh -i ~/.ssh/id_dsa_gsg-keypair ubuntu@ec2-184-73-51-147.compute-1.amazonaws.com<br />
(&#8230;)</p>
<p>ubuntu@domU-12-31-39-0E-A0-03:~$ echo &#8220;Important data&#8221; > important-data<br />
ubuntu@domU-12-31-39-0E-A0-03:~$ ls -l important-data<br />
-rw-r&#8211;r&#8211; 1 ubuntu ubuntu 15 Mar  9 20:15 important-data</p>
<p>ubuntu@domU-12-31-39-0E-A0-03:~$ sudo reboot<br />
Broadcast message from ubuntu@domU-12-31-39-0E-A0-03<br />
	(/dev/pts/0) at 20:18 &#8230;<br />
The system is going down for reboot NOW!
</p></blockquote>
<p>Note that we didn&#8217;t actually fix the problem reported by Scott, so our machine won&#8217;t really reboot.  If we wait a while, we can even see that the problem is exactly what was reported in the announcement (note it really takes a bit for the output to be synced up):</p>
<blockquote><p>
% ec2-get-console-output i-e3e33a88 | tail -4<br />
mount: special device ephemeral0 does not exist<br />
mountall: mount /mnt [294] terminated with status 32<br />
mountall: Filesystem could not be mounted: /mnt
</p></blockquote>
<p>Alright, now what?  Machine is dead.. and can&#8217;t reboot.  How do we get to our important data?</p>
<p><b>Fixing the problem</b></p>
<p>The first thing we do is to <b>stop</b> the instance.  Do <i>not</i> terminate it, or you&#8217;ll lose the EBS volume!  After stopping it, we&#8217;ll detach the EBS volume that was being used as the root filesystem, so that we can attach somewhere else.</p>
<blockquote><p>
% ec2-stop-instances i-e3e33a88<br />
INSTANCE	i-e3e33a88	running	stopping</p>
<p>% ec2-detach-volume vol-edca1684<br />
ATTACHMENT	vol-edca1684	i-e3e33a88	/dev/sda1	detaching	2010-03-09T20:04:22+0000
</p></blockquote>
<p>Now, we need to attach this volume in an image which actually boots, so that we can fix it.  For this experiment, we&#8217;ll pick one of the daily Lucid images, but we could use any other working image really.  Just remind that the image must be running in the same availability zone as our previous instance, since the EBS volume won&#8217;t be accessible otherwise.</p>
<blockquote><p>
% ec2-run-instances -k gsg-keypair -z us-east-1c ami-b5f619dc<br />
RESERVATION	r-967427fe	626886203892	default<br />
INSTANCE	i-fd08d196	ami-b5f619dc			pending	gsg-keypair	0		m1.small	2010-03-09T21:10:11+0000	us-east-1c	aki-3fdb3756			monitoring-disabled			instance-store		</p>
<p>% ec2-attach-volume vol-edca1684 -i i-fd08d196 -d /dev/sdh1<br />
ATTACHMENT	vol-edca1684	i-fd08d196	/dev/sdh1	attaching	2010-03-09T21:10:51+0000
</p></blockquote>
<p>With the instance running and the EBS root device attached with an alternative device name, we can then login to fix the original problem which prevented the image from booting correctly.  In our case, we&#8217;ll simply do what Scott suggested in the announcement.</p>
<blockquote><p>
% ssh -i ~/.ssh/id_dsa_gsg-keypair ubuntu@ec2-204-236-194-196.compute-1.amazonaws.com<br />
(&#8230;)<br />
$ mkdir ebs-root<br />
$ sudo mount /dev/sdh1 ebs-root<br />
$ sudo sed -i &#8216;s/^ephemeral0/#ephemeral0/&#8217; ebs-root/etc/fstab<br />
$ sudo umount ebs-root<br />
$ logout<br />
Connection to ec2-204-236-194-196.compute-1.amazonaws.com closed.
</p></blockquote>
<p>Done!  Our EBS volume is now correct, and it should boot alright.  We&#8217;ll detach the volume from the temporary instance we created, and will reattach it back to the old bootable EBS instance which is stopped.  Note that we won&#8217;t yet terminate the temporary instance, because we may need it in case something else is still wrong, and we are already paying to use it for the hour anyway.  We just have to remind ourselves to terminate it once we&#8217;re fully done.</p>
<blockquote><p>
% ec2-detach-volume vol-edca1684<br />
ATTACHMENT	vol-edca1684	i-fd08d196	/dev/sdh1	detaching	2010-03-09T21:10:51+0000</p>
<p>% ec2-attach-volume vol-edca1684 -i i-e3e33a88 -d /dev/sda1<br />
ATTACHMENT	vol-edca1684	i-e3e33a88	/dev/sda1	attaching	2010-03-09T21:24:55+0000</p>
<p>% ec2-describe-volumes vol-edca1684<br />
VOLUME	vol-edca1684	15	snap-f1efd098	us-east-1c	in-use	2010-03-09T20:04:20+0000<br />
ATTACHMENT	vol-edca1684	i-e3e33a88	/dev/sda1	attached	2010-03-09T21:24:55+0000
</p></blockquote>
<p>Okay!  It should all be good now.  It&#8217;s time to restart our instance, and see if it is working.  Note that since you stopped and started the instance, the public domain name most probably has changed, and thus we need to find it out again with <i>ec2-describe-instances</i> once the instance is running.</p>
<blockquote><p>
% ec2-start-instances i-e3e33a88<br />
INSTANCE	i-e3e33a88	stopped	pending</p>
<p>% ec2-describe-instances i-e3e33a88<br />
RESERVATION	r-9e4615f6	626886203892	default<br />
INSTANCE	i-e3e33a88	ami-8bec03e2	ec2-184-73-72-214.compute-1.amazonaws.com	domU-12-31-39-03-B8-21.compute-1.internal	running	gsg-keypair	0		m1.small	2010-03-09T21:28:43+0000	us-east-1c	aki-3fdb3756			monitoring-disabled	184.73.72.214	10.249.187.207			ebs<br />
BLOCKDEVICE	/dev/sda1	vol-edca1684	2010-03-09T21:24:55.000Z	</p>
<p>% ssh -i ~/.ssh/id_dsa_gsg-keypair ubuntu@ec2-184-73-72-214.compute-1.amazonaws.com<br />
(&#8230;)<br />
$ cat important-data<br />
Important data</p>
<p>$ logout<br />
Connection to ec2-184-73-72-214.compute-1.amazonaws.com closed.
</p></blockquote>
<p>It worked, and our important data is still there!</p>
<p>Don&#8217;t forget to kill the temporary instance you&#8217;ve used to fix it after you&#8217;re comfortable with the result:</p>
<blockquote><p>
% ec2-terminate-instances i-fd08d196<br />
INSTANCE	i-fd08d196	running	shutting-down
</p></blockquote>
<p><b>Conclusion</b></p>
<p>Concluding, in this post we have seen how to fix a bootable EBS machine which can&#8217;t actually boot.  The technique consists of detaching the volume from the stopped instance, attaching it to a temporary instance, fixing the image, and then reattaching it back to the original image.  This back and forth of EBS volumes is quite useful in many circumstances, so keep it in your tool belt.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2010/03/09/recovering-a-bootable-ebs-image/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Breaking into an Android password manager &#8211; Practice</title>
		<link>http://blog.labix.org/2009/12/05/breaking-into-an-android-password-manager-practice</link>
		<comments>http://blog.labix.org/2009/12/05/breaking-into-an-android-password-manager-practice#comments</comments>
		<pubDate>Sun, 06 Dec 2009 00:38:11 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Puzzle]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=230</guid>
		<description><![CDATA[In the last post, we&#8217;ve seen some security issues which exist in the Android password manager gbaSafe version 1.1.0a, by analyzing the security description provided in its web site. As described there, even though the system depends on a &#8220;master &#8230; <a href="http://blog.labix.org/2009/12/05/breaking-into-an-android-password-manager-practice">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://blog.labix.org/2009/12/01/breaking-into-an-android-password-manager-theory">the last post</a>, we&#8217;ve seen some security issues which exist in the Android password manager <a href="http://www.gbizapps.com/gbasafe.htm">gbaSafe</a> version 1.1.0a, by analyzing the security description provided in its web site.  As described there, even though the system depends on a &#8220;master key&#8221; which might be secure, the security of the system is seriously compromised by the encouragement of very weak keys (a few <i>digits</i> only) in what is named an &#8220;unlock key&#8221;, used to encrypt the master key itself.  All of that in an application which claims to strongly <i>protect</i> people&#8217;s data from unwanted eyes.</p>
<p>In this post, we will play a bit with the Linux-based Android OS to actually explore these security deficiencies, demonstrating that such issues are very real, and that the claims of being hard to unveil the data is unfounded.  Since the most serious weakness lies in the key itself, we&#8217;ll run a simple brute force attack to try to find arbitrary unlock keys.</p>
<p><span id="more-230"></span></p>
<p>This procedure is actually mentioned by the author of gbaSafe himself in the web page, except he overestimates the work involved in producing such a mechanism:</p>
<blockquote><p>
Theoretically, somebody could write a program that tries to decrypt the master key by trying all possible values of the short key (with 4 digits there are only 10000 possibilities), but this would still be much work, as more information about the crypting algorithm is needed (e.g. salt bytes, iteration count).
</p></blockquote>
<p>So let&#8217;s get started.</p>
<p>As a first step, we&#8217;ll need the <a href="http://developer.android.com/sdk/index.html">Android SDK</a> with a working emulator (I&#8217;ve used API level 5, revision 1), and a copy of the application itself.  I got a <a href="http://andappstore.com/AndroidApplications/apps/gbaSafe_Password_Safe">trial version of the application</a> from <a href="http://andappstore.com/">AndAppStore.com</a>.</p>
<p>The application downloaded is bundled within that <i>.apk</i> file, which is really a <i>.zip</i> file that may be opened up normally with any tool which understands this file format.</p>
<p>Once that&#8217;s done, we get access to all the information needed to run the application, including icons, interface layouts, and most importantly in this case, the bytecode which targets the <a href="http://en.wikipedia.org/wiki/Dalvik_virtual_machine">Dalvik VM</a>.   This bytecode is the end result of a sequence of translations which happen when the program&#8217;s Java source code is compiled, so that&#8217;s what we&#8217;ll have to fiddle with to figure details of the application we want to investigate.</p>
<p>The bytecode is located inside the <i>classes.dex</i> file, and as expected it&#8217;s not easy to read in its native format.  Luckily, though, a smart guy has already written a couple of tools, <a href="http://code.google.com/p/smali/">smali and baksmali</a>, which allow people to decompile and recompile that bytecode format to/from something that is much easier to understand.</p>
<p>After downloading these tools, the following command should decompile the file:</p>
<blockquote><p>
$ java -jar baksmali.jar &#8211;output classes classes.dex
</p></blockquote>
<p>We now have a <i>classes/</i> directory full of <i>.smali</i> files.</p>
<p>Before going any further, let&#8217;s ponder for a moment about what we want to do.  A brute force attack is when we attempt sequentially many possible keys, and given the context already presented, what we&#8217;re looking after is to attempt different &#8220;unlock keys&#8221;.  With that in mind, we&#8217;ll introduce a very small modification in the application so that it will attempt to enter the unlock key automatically, rather than reporting an error when the key entered in the unlock dialog is invalid.</p>
<p>With that in mind, after some quick research, it looks like the <i>onClick()</i> method within the <i>DlgUnlock.smali</i> file is a pretty good candidate.  This is supposedly called when the button in the unlock dialog is clicked, so something interesting about the password being correct or not must happen there.</p>
<p>Before doing anything there, I&#8217;ve increased the number of registers in the function to 12, to get some additional registers to play with, and then initialized a register with the value zero, to serve as a monotonically increasing number (our keys!):</p>
<blockquote><p>
 .method public onClick(Landroid/view/View;)V<br />
-    .registers 9<br />
+    .registers 12<br />
     .parameter &#8220;view&#8221;<br />
+    const/16 v9, 0&#215;0
</p></blockquote>
<p>Then, we have to instruct the program to use these keys rather than whatever is typed in the dialog box.  Some lines down, we&#8217;ll see a call to the <i>checkUnlockKey()</i> method, which is certainly what we&#8217;re looking after.  Let&#8217;s do this now:</p>
<blockquote><p>
+    :mykey<br />
+    invoke-static {v9}, Ljava/lang/String;->valueOf(I)Ljava/lang/String;<br />
+    move-result-object v2<br />
     invoke-static {v2}, Lcom/gbizapps/safeA/Crypt;->checkUnlockKey(Ljava/lang/String;)I
</p></blockquote>
<p>Now, what if this key is wrong?  We don&#8217;t want the master key to be removed as mentioned in the software description.  We want to simply attempt the next key.  With some analysis, we see that in case of errors, the next couple of lines below the above code will instruct the VM to jump to an error branch.  Rather than following up with the normal error logic, we&#8217;ll increment the key, and jump back to the above code:</p>
<blockquote><p>
     :cond_6c<br />
+    add-int/lit8 v9, v9, 0&#215;1<br />
+    goto :mykey
</p></blockquote>
<p>Now we just have to rebundle this and put it into the emulator.  I won&#8217;t go over it in too much detail here, since there&#8217;s plenty of information available online, but the steps to do that are:</p>
<ol>
<li>Recreate a modified classes.dex with <i>smali</i>
<li>Recreate a modified <i>.apk</i> file by just zipping the modified content
<li>Sign and zipalign the new <i>.apk</i> file
<li>Install it
</ol>
<p>And that&#8217;s it, seriously!  This would be enough to break the software security if it was working <i>correctly</i>.</p>
<p>Interestingly, though, the software <i>wasn&#8217;t</i> working correctly with this change.  Instead, it was <i>Force Closing</i> on certain keys.   To test it out, use the master key &#8220;master key&#8221;, and the unlock key &#8220;999999&#8243;, and then once you close and open the application again, try to unlock it with the key &#8220;1175&#8243;.  Instead of showing an error message, it will break badly.</p>
<p>Now, for the proof of concept to work, I actually had to <i>fix</i> the bug, which felt a bit funny to do given the context.</p>
<p>Looking at the traceback trough <i>adb logcat</i>, I found out that there was a null being dereferenced in the file <i>Crypt.smali</i>, so I fixed the problem by injecting some error checking at this position and jumping the flow into an existing error branch:</p>
<blockquote><p>
+    if-eqz v3, :cond_5a<br />
     const-string v4, &#8220;ucpmhkexov85MDKhdfdfFGQPYxywq7209fcrqhghjkuiopy&#8221;
</p></blockquote>
<p>With this in place came the biggest surprise of the experiment. The keys which were crashing the application were special, in the sense that they actually <i>decode the master key successfully</i>!  That&#8217;s right: whatever the algorithm is doing, that six-digit &#8220;999999&#8243; encrypts the master key in such a way that attempting the &#8220;1175&#8243; key works, so even big keys are rendered extremely weak with the logic used to encrypt the master key.</p>
<p>At this point, I added some trivial logic to display the key found with a <a href="http://developer.android.com/reference/android/widget/Toast.html">Toast</a>, just to ensure the whole thing was working correctly:</p>
<p><img src="http://blog.labix.org/wp-content/uploads/2009/12/device.png" alt="Toast displaying unlock key found" title="Toast displaying unlock key found" width="320" height="480" class="aligncenter size-full wp-image-242" /></p>
<p>Note that the key generation implemented above is a bit simplistic, in the sense that it doesn&#8217;t attempt keys with leading zeros, but this would be trivial to implement, and my intention here isn&#8217;t to actually break any keys for real, but just to show how the promised security in this application is not to be trusted at all.  Just the logic above will already be enough for a brute force attack against the application, and has broken all the keys I&#8217;ve tried in mere seconds, in a <i>slow emulator</i>.</p>
<p>As a conclusion, if you want to put your data in a secure place, rather than picking an application which promises security because <i>the salt is hidden somewhere</i> or because it&#8217;s <i>too much work to figure its logic</i>, pick an open source application with logic which is publicly verifiable and has already had many eyes over it.  Chances are that doing something like what was described in this post won&#8217;t be so trivial.  Then, <i>choose your keys wisely</i>!  The most secure application won&#8217;t be enough if you pick a bad key.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2009/12/05/breaking-into-an-android-password-manager-practice/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Breaking into an Android password manager &#8211; Theory</title>
		<link>http://blog.labix.org/2009/12/01/breaking-into-an-android-password-manager-theory</link>
		<comments>http://blog.labix.org/2009/12/01/breaking-into-an-android-password-manager-theory#comments</comments>
		<pubDate>Wed, 02 Dec 2009 01:33:16 +0000</pubDate>
		<dc:creator>Gustavo Niemeyer</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Puzzle]]></category>
		<category><![CDATA[Security]]></category>

		<guid isPermaLink="false">http://blog.labix.org/?p=203</guid>
		<description><![CDATA[For some time now I&#8217;ve been wanting to research more deeply about the internals of Android. Until now, though, this was just a sentiment. Then, a couple of weeks ago I&#8217;ve finally managed to replace my iPhone for an Android &#8230; <a href="http://blog.labix.org/2009/12/01/breaking-into-an-android-password-manager-theory">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>For some time now I&#8217;ve been wanting to research more deeply about the internals of <a href="http://www.android.com">Android</a>.  Until now, though, this was just a sentiment.  Then, a couple of weeks ago I&#8217;ve finally managed to replace <a href="http://blog.labix.org/2009/06/30/my-iphone-for-an-android">my iPhone for an Android</a> phone, and that was the final motivator for me to actually get into learning more about the inner workings of the Linux-based OS.</p>
<p>Now, I just had to pick an actual task for digging into.  The Dalvik VM is certainly one of the most innovative and advertised technical details about the OS, so something around it would be a nice start.. some kind of bytecode fiddling perhaps, but what?  Luckily, even without trying too hard, I eventually stumbled upon an interesting case for researching upon.</p>
<p>The &#8220;victim&#8221; of this research is the application <a href="http://www.gbizapps.com/gbasafe.htm">gbaSafe</a> version 1.1.0a, which claims to protect user passwords using <i>unbreakable algorithms</i> (how&#8217;s that for a hint of a <a href="http://en.wikipedia.org/wiki/Snake_oil_(cryptography)">Snake oil</a> case?).</p>
<p><span id="more-203"></span></p>
<p>Before we get into some hacking, let&#8217;s see some words on the software security by the author himself, and then render some analysis on conceptual issues on it:</p>
<blockquote><p>
The confidential data can only be decrypted if the master key is known. You should choose a long key (at least 16 characters) with mixed case and unreadable text. Of course you cannot enter this key each time you want to access the confidential data, so it is stored in the user settings encrypted with a shorter key (4 to 6 digits) and normally you only have to enter this unlock key. Theoretically it is possible to try all possible values (brute force attack), but then you must use another program, since gbaSafe deletes the encrypted master key from the user settings when you enter the unlock key wrong three times repeatedly, and then you must enter the master key. If you wrote a program to decrypt the master key, you would have to know the algorithm used, the salt bytes and iteration count (used to augment the short unlock key), which are very hard to extract from the binary program module gbaSafe.
</p></blockquote>
<p>If you have some security background, I&#8217;m sure that by now you&#8217;re already counting the issues on this single paragraph.</p>
<p>The most obvious issue is the fact that there&#8217;s a &#8220;strong key&#8221; and a &#8220;weak key&#8221;, and the strong key is encrypted with the weak one.  This is a very common cryptography sin, as would say my friend and coworker Andreas Hasenack (a security researcher himself).  A security system is only as secure as its weakest spot.  It obviously makes little difference for an attacker if he has to attempt decrypting a master key or the actual data, since decrypting the master key will give access to the data.</p>
<p>Then, it mentions en passant that the software <i>enforces</i> the use of <i>digits</i> for the weak key.  This ensures that the weak key is <i>really</i> weak!  Four digits is basically ten thousand attempts, which is absolutely nothing for nowadays&#8217;s hardware.  This number would move up to about 15 million by simply allowing upper and lowercase letters as well (which isn&#8217;t great either, but a few orders of magnitude never hurt in this scenario).</p>
<p>It follows up encouraging people to think that it&#8217;s actually hard to figure the algorithm and other implementation details.  Considering that there&#8217;s absolutely nothing preventing people from getting their hands in the implementation itself, this is in fact asserting that the security mechanism is based on the ignorance of the attacker.  Counting on the ignorance of people is bad at all times, and in a security context it&#8217;s a major error.</p>
<p>There&#8217;s a final security issue in this description which is a bit more subtle, but further analysis on the logic used leaves no doubt.  In cryptography, the <a href="http://en.wikipedia.org/wiki/Salt_(cryptography)">salt</a> is supposed to increase the work needed in a brute force attack by strengthening the number of bits of the actual passphrase, in a case where the salt is <i>actually</i> unavailable, or at least prevent that a single large word dictionary can be used to attack several encryptions or hashes at once, in a case where the salt is known but variable.  In the latter case, it helps because encrypting a single key with two different salts must be done twice, rather than once, so it increases the computational task when attacking multiple items.  A salt which is known and does not change across all processed items is worth pretty close to nothing.</p>
<p>So, indeed, considering the many security issues here, this isn&#8217;t something I&#8217;d store my passwords or credit card numbers on, and I suggest you don&#8217;t do it either.</p>
<p>In my next post on this topic I&#8217;ll actually implement a trivial brute force attack to prove that these issues are <i>very</i> real, and that, actually, it&#8217;s not even hard to break into a security system like this.</p>
<p>The application author has been contacted about this blog post, since he&#8217;ll likely want to fix some of these issues.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.labix.org/2009/12/01/breaking-into-an-android-password-manager-theory/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
