Blog

Announcing Zetetic Connect

Posted: Feb 09, 2010 by Steve Kradel Tagged software, ldap

Today I'm very excited to announce Zetetic Connect, a fast, super-flexible way to get information out of (and into) LDAP directories and relational databases databases for the web, iPhone, BlackBerry, and Android.

Connect grew out of a client's need to publish Active Directory data to the web; so many businesses and schools rely on directory systems, but there just aren't a lot of mature applications that help people take full advantage of those directories or to spot and correct missing data. Connect does that and, going two steps farther, hosts an extremely robust, high-performance engine that can unify multiple directories and data stores behind the scenes, and allows users from any of those directories to sign in.

For example, if part of your company uses Microsoft Exchange, another division uses Lotus Domino, and you've just acquired a third group that uses Zimbra for messaging, Zetetic Connect can quickly create an online phonebook merging all three. Just launch Connect, search for "Smith", and you'll get the contact and organizational details for all the Smiths across all systems, live. The same powerful simplicity applies to contacts, groups and distribution lists, sites and locations, and virtually any other data in your directories. (Of course, you can choose what to include or exclude from each.) Users can easily maintain their own data, such as phone and mobile numbers, according to rules you define.

Interested? »

We're currently running a small number of commercial evaluations for interested customers, including system deployment by Zetetic's LDAP-meisters. Contact us now if you'd like a demonstration and evaluation of the system, since availability is limited.

Your mobile users will be impressed by Connect's user interface, which is tailored especially for the iPhone, BlackBerry, and Android, and has the look and feel of a native application. (See: screenshots.) Connect is Unicode and internationalization-friendly too, so your users get Connect in their native languages, top-to-bottom.

Behind the scenes, we've leveraged many years of directory experience to build an extremely robust framework that actively monitors your directory servers' performance and availability, so users won't notice if individual servers go out of service. Connect also does some pretty serious and smart caching and threading, and features a wealth of special optimizations for Active Directory. That said, it works great with any LDAP server, SSL on or off, and any schema.

You can even use the Zetetic Connect core as a pure-LDAP, federation-capable membership and role provider for any ASP.NET application, a topic upon which I'll touch in a future blog post.

Beginning of Week

Posted: Jan 26, 2009 by Billy Gray Tagged

I’m currently putting together a quick set of extensions to the Javascript Date object, inspired by this article over here by Lawrence O’Sullivan. Mostly, I just want to be able to conveniently pull up relational dates (like the beginning of date’s week), similarly to the Rails date helper methods:


now = new Date();
alert(now.beginning_of_week());
alert(now.end_of_month());

Back before I realized how powerful Rails date helper methods were, I had put together some of my own calculations for Tempo, and then subsequently ditched them. But I wanted to pull them back up for this since I needed to roll it myself, and I’m quite happy those old SVN commits are still sitting in my Gmail:


    case interval
    when Context::THIS_WEEK
-      start_date = now.change( :mday => (now.mday - now.wday) )
+      start_date = now.beginning_of_week
    when Context::LAST_WEEK
-      end_date = now.change( :mday => (now.mday - now.wday) )
-      now -= 1.week
-      start_date = now.change( :mday => (now.mday - now.wday) )
+      end_date = now.beginning_of_week
+      start_date = (now - 1.week).beginning_of_week
    when Context::THIS_MONTH
-      start_date = now.change( :mday => 1 )
+      start_date = now.beginning_of_month
    when Context::LAST_MONTH
-      end_date = now.change( :mday => 1 )
-      start_date = (now - 1.month).change( :mday => 1)
+      end_date = now.beginning_of_month
+      start_date = (now - 1.month).beginning_of_month
    end

Deep Thought

Posted: Mar 23, 2009 by Billy Gray Tagged pingme, xss, exploits, ethics, hacking, twitter

Publicly exposing exploits on Twitter does not make you an 31337 security consultant. It just makes you a weener.

While our TOS clearly prohibits this sort of activity, I generally don’t mind at all when people poke around. I used to read 2600, I don’t believe in giving people a hard time for figuring out how things work. But I like to think that somewhere along the way we grow up or graduate and we don’t just go throwing exploits out into the wild. You let the affected service know about it so they can patch it before you go publishing your leetness to the world.

Turns out we missed one bit of user input that should have been sanitized, and have since patched it, and then we did a full review of all our Rails views to make sure there aren’t any others we missed. We’ve been pretty religious about it. It doesn’t look like any of our users were adversely affected, although there was about a 24-hour span between the time when our hero published the vulnerability and when I saw it on Twitter.

Deep Thought

Posted: Apr 22, 2009 by Billy Gray Tagged deepthought, iphone, apple, appstore, babyshaker

Babyshaker can’t really be within the realm of those super-strict Human Interface Guidelines that can get your app rejected from the App Store, can it?

Related: it’s really important for Apple to delay posting of your bug fixes and updates for weeks to make sure that only real kwality apps make it in there.

Deep Thought

Posted: Aug 04, 2009 by Billy Gray Tagged

John Gruber is often complaining about Michael Arrington because established pundits (and DF author Gruber is established in the blogosphere) don’t like it when competitors pee in their sandbox. Thus the need to slag the guy at every opportunity. I really love to disagree with Gruber, so I haven’t quit reading the guy yet, but more and more I find myself thinking, “wow, you’re such a jerk!” Not that I have an affinity for Arrington, but the constant Arrington-hating (and the constant general hating from Gruber) is getting really droll.

One wonders if these guys ever get worked up about real life issues, if they ever bother to pick up the phone and call their Congressional representative?

iPhone Encryption with SQLCipher

Posted: Jun 01, 2009 by Stephen Lombardo Tagged

Mobile devices are notoriously difficult to secure. With a small footprint it is dangerously easy to leave your phone in the back of a taxi, or forget to pick it up from a table after dinner at a restaurant. iPhone and iPod Touch devices are no exception – most applications store their data in an easily readable format. Anyone with access to your device can browse through your personal information. Even worse, since the devices back up to your computer, any knowledgeable person with access to your workstation can read your data as well.

This is balanced by immense convenience. An iPhone makes a perfect digital wallet: a single device with all your important information literally at your fingertips. When we set out to write Strip, our iPhone Password Manager and Data Vault, we wanted to build a system that we could trust to store Passwords, Credit Card Numbers, Passport Identifiers, SSNs and bank account information. Most of the other applications in the App store used undocumented encryption or weaker field level security. We wanted to encrypt EVERY bit of Strip’s data on the device. Naturally the ideal approach would be to have the encryption managed transparently, so Strip didn’t need to know about the details.

Enter SQLCipher, a specialized build of the excellent SQLite database that performs transparent and on-the-fly encryption. Using SQLCipher, an application uses the standard SQLite API to manipulate tables using SQL. Behind the scenes the library silently manages the security aspects, making sure that data pages are encrypted and decrypted as they are written to and read from storage. SQLCipher uses the widely trusted and peer-reviewed OpenSSL library for all cryptographic functions.

SQLite is already the predominant API for persistent data storage on the iPhone so the upside for development is obvious. As a programmer you work with a stable and well documented API. All security concerns are cleanly decoupled from application code and managed by the underlying framework. The framework code of the SQLCipher and OpenSSL projects are both open source, so users can be confident that an application isn’t using insecure or proprietary security code.

Using SQLCipher in an iPhone application is straightforward once you setup your project properly. The easiest way to integrate SQLCipher into an application is to use XCode project references as described here.

Get OpenSSL

SQLCipher relies on OpenSSL for several encryption requirements including the AES-256 algorithm, pseudo random number generation, and PBKDF2 key derivation. OpenSSL isn’t a framework that is usable directly on the iPhone so we will setup our project to build and link against it as a static library.

Start by going over to the OpenSSL download page to a recent stable version (0.9.8k as of this writing). Download the source file and extract it to a folder on your system. Make a note of the source directory path for later.

OpenSSL can be a tricky system to compile properly from source. It’s even more complex when you’re dealing with multiple target architectures, targeting i386 for the simulator but armv6 for a device. Luckily we’ve built a handy XCode project template to make it easy called openssl-xcode. The project actually relies on the OpenSSL configure and make system to build the libraries. However, it automatically detects the appropriate build settings for architecture (i386, ppc, arv6), build tools, and SDK. This makes it ideal for inclusion in an iPhone project. Just git clone or download openssl-xcode from GitHub and move the openssl.xcodeproj file into the OpenSSL source directory.

Get SQLCipher

SQLCipher is a standalone package that includes the entire SQLite source distribution. You can git clone or download the latest version from the SQLCipher repository on GitHub. Again, make note of the source directory path you use for later in the setup process.

XCode Setup

SQLCipher uses project references to manage build dependencies and static linking. In order to allow linking you must setup your XCode environment to use a central build location. We will also need to configure Source Trees OpenSSL and SQLCipher respectively.

  1. Open XCode, Choose the XCode Menu, and then Preferences.
  2. On the Building tab, Change the “Place Build Products In” to “Customized location” and pick a location for the build directory.

  1. Switch to the Source Tree tab.
  2. Add a SQLCIPHER_SRC that references the path to the SQLCipher sourcecode
  3. Add a OPENSSL_SRC to reference the path to the OpenSSL sourcecode

Project Setup

Now that we have XCode global preferences setup we will move on to the project configuration.

Open your XCode application project, and click on the top level Project item. Hit option-command-a to add a resource. Navigate to the OpenSSL directory and choose the openssl.xcodeproj to add the reference. When the add resource window comes up make sure that “Copy items” is not checked, and add it to the appropriate target. Repeat the same, This time choose the sqlcipher.xcodeproj file in SQLCipher source directory.

Let’s change the Path Types as a convenience to multi-developer teams. Using paths relative to the Source Trees we defined will allow each developer to place the SQLCipher and OpenSSL in any locations and the build will still work.

  1. Hit option-i on the sqlcipher.xcodeproj reference and change the Path Type to “Relative to SQLCIPHER_SRC”.
  2. Hit option-i on the openssl.xcodeproj reference and change the Path Type to “Relative to OPENSSL_SRC”
  3. Hit option-command-a to add another resource

Now we will add build dependencies to ensure that the SQLCipher is compiled before the application code. Open the Info panel for your Application Target and Choose the General Tab. We will add two dependencies, one for OpenSSL crypto, and one for SQLCipher.

Then switch to the Build tab to add our source paths to the include directories to make relevant header files available. Make sure that the Configuration is set to “All Configurations”. Look for the “Header Search Paths” setting and add references to $(SQLCIPHER_SRC) and $(OPENSSL_SRC). Check “recursive” on both.

Finally, we will tell XCode to link against the built libraries. Expand the sqlcipher and openssl .xcodeproj references and select libsqlcipher.a and libcrypto.a. Drag and drop them on “Link Binary With Libraries” under your application target.

Building SQLCipher

At this point you should be able to build your XCode project without errors. Note that the first time you build your application for a particular architecture (Simulator for instance), it will take much longer than usual. This is because SQLCipher and OpenSSL are compiled from source for the specific architecture. You can keep track of the status under Build Results. Subsequent builds for the same platform will be much quicker since the libraries don’t need to be recompiled.

In Code

Now that you’ve incorporated the SQLCipher library into your project you can start using the system immediately. Telling SQLCipher to encrypt a database is as easy as opening a database and using “PRAGMA key” or the sqlite3_key function.

#import <sqlite3.h>

...
sqlite3 *db;
if (sqlite3_open(@"/path/to/database", &db) == SQLITE_OK) {
   sqlite3_exec(db, "PRAGMA key = 'BIGsecret', NULL, NULL, NULL);

   if (sqlite3_exec(db, (const char*) "SELECT count(*) FROM sqlite_master;", NULL, NULL, NULL) == SQLITE_OK) {
     // password is correct, or, database has been initialized
   } else {
     // incorrect password!
   }
}

The call to sqlite3_key or PRAGMA key should occur as the first operation after opening the database. In most cases SQLCipher uses
PBKDF2, a salted and iterated key derivation function, to obtain the encryption key. Alternately, can tell SQLCipher to use a specific binary key in blob notation (note that you must provide exactly 256 bits of key material):

PRAGMA key = "x'2DD29CA851E7B56E4697B0E1F08507293D761A05CE4D1B628663F411A8086D99'";

Once the key is set SQLCipher will automatically encrypt all data in the database! If you don’t set a key then SQLCipher will operate identically to a standard SQLite database.

Verify

After your application is wired up to use SQLCipher you should take a quick peek at the resulting data files to make sure everything is in order. An ordinary SQLite database will look something like the following under hexdump. Note that the file type, schema, and data are clearly readable.

new-host-2:sqlcipher sjlombardo$ hexdump -C plaintext.db 
00000000  53 51 4c 69 74 65 20 66  6f 72 6d 61 74 20 33 00  |SQLite format 3.|
00000010  04 00 01 01 00 40 20 20  00 00 00 04 00 00 00 00  |.....@  ........|
...
000003b0  00 00 00 00 24 02 06 17  11 11 01 35 74 61 62 6c  |....$......5tabl|
000003c0  65 74 32 74 32 03 43 52  45 41 54 45 20 54 41 42  |et2t2.CREATE TAB|
000003d0  4c 45 20 74 32 28 61 2c  62 29 24 01 06 17 11 11  |LE t2(a,b)$.....|
000003e0  01 35 74 61 62 6c 65 74  31 74 31 02 43 52 45 41  |.5tablet1t1.CREA|
000003f0  54 45 20 54 41 42 4c 45  20 74 31 28 61 2c 62 29  |TE TABLE t1(a,b)|
...
000007d0  00 00 00 14 02 03 01 2d  02 74 77 6f 20 66 6f 72  |.......-.two for|
000007e0  20 74 68 65 20 73 68 6f  77 15 01 03 01 2f 01 6f  | the show..../.o|
000007f0  6e 65 20 66 6f 72 20 74  68 65 20 6d 6f 6e 65 79  |ne for the money|

Fire up your SQLCipher application in simulator you can look for your database files under /Users/<username>/Library/Application Support/iPhone Simulator/User/Applications/<HEX app id>/Documents. Try running hexdump on your application database. With SQLCipher you should get output that looks completely random, with no discerning characteristics at all:

new-host-2:Documents sjlombardo$ hexdump -C encrypted.db 
00000000  84 d1 36 18 eb b5 82 90  c4 70 0d ee 43 cb 61 87  |.?6.?..?p.?C?a.|
00000010  91 42 3c cd 55 24 ab c6  c4 1d c6 67 b4 e3 96 bb  |.B<?U$???.?g??.?|
00000020  8e df fa bc c3 9c 92 8a  4e 40 59 6f b5 95 f3 80  |.????...N@Yo?.?.|
...
00000bd0  91 16 9e 89 d9 4e ac f7  1c c9 d1 d7 aa bb a7 51  |....?N??.??ת??Q|
00000be0  dc 77 5c 6c de c6 d3 be  43 49 48 3e f3 02 94 a9  |?w\l??ӾCIH>?..?|
00000bf0  8e 99 ee 28 23 43 ab a4  97 cd 63 42 8a 8e 7c c6  |..?(#C??.?cB..|?|
00000c00

Conclusion

SQLCipher is an easy way to incorporate full database encryption into an iPhone application. For more information on SQLCipher and the underlying security features please check out the SQLCipher project site. To see it in action please try Strip and Strip Lite in the iTunes App Store!

iPhone Tutorial: Painless Lite to Paid Application Upgrades with Custom URL Handlers

Posted: Jun 26, 2009 by Stephen Lombardo Tagged

Apple enforces a number of restrictions on applications in the App Store. Among the most painful is the lack of feature-limited trials. Applications are either completely free, or the customer must pay up front, sight unseen. The proliferation of “Lite” applications is a direct result of this shortcoming. Publishers will often create two application versions: the first is fully functional but costs money, the second is “Lite” and comes with limited features but zero price tag. The goal is for prospective customers to try the free version first and then decide to buy the paid full version separately if they like it.

Because free applications have greater exposure this approach is widely advocated as a means to increase visibility and grow sales. When building a game or other stateless application the approach makes complete sense. However, utility applications often maintain information entered by the device owner. Application authors are faced with a dilemma because the iPhone’s security sandbox prevents one application from reading another application’s files. Thus, when customers upgrade from the Lite application they are penalized by having to re-enter all data!

When we developed our data vault product, Strip, we felt this situation was unacceptable. We wanted to offer Strip Lite, free for people to try, limited to 10 entries. Upgrading customers should be able to import their data from the Lite version. No pain.

The Approach

Strip stores user data in an encrypted SQLite Database. Since we really wanted a way to copy the data file from Strip Lite to Strip we developed a fairly clever solution: use a registered URL handler as a means of communication between application versions. This is how it works:

  1. A customer downloads Strip Lite for free and enters some unique private data. All information is written to a database in the application’s document directory.
  2. When the 10 record limit is hit Strip Lite asks them to upgrade. An upgrade button launches to explain the process and allow the user to download the paid version of the product.
  3. Once Strip is purchased and installed, our customer will launch Strip Lite and click an “Export to Strip” button. Strip Lite reads the application database into an NSData object, Base64 encodes it and then Launches a “strip://” URL with the encoded file contents as a URL parameter.
  4. The full version of Strip is registered as a handler for “strip://” URLs. The OS launches Strip and passed the URL to the handleOpenURL method of the application delegate. It parses and decodes the data and writes the database to the desired location in the new applications Document folder.
  5. Our customer now has access to all the data the originally entered into Strip Lite!

Project Setup

This tutorial assumes that your project is already configured with two targets, one for your full version, and one for the Lite.

Start by creating a new InfoLite.plist file for your Lite version. We use 2 separate .plist files to ensure that the Full version is the only registered URL handler (we don’t want the Lite version responding to upgrade events itself!). It is easiest to just make a copy of the existing Info.plist file named InfoLite.plist.

Next, Open up the Build preferences for the Lite target. Change the Info.plist File property to read InfoLite.plist. This will ensure that the Lite target includes the proper file.

Now open the Info.plist (used by the Full Version) and register a custom URL handler. This is a straightforward process of adding elements as shown in the following screenshot.

Please note that the URL identifier and URL scheme must be unique for your application. Mobile Orchard has a great stepwise overview of this process for reference.

Finally, the application must include code to perform Base64 encoding itself. This functionality is, unfortunately, not directly accessible in the framework SDK. There are a few options in Cocoa, including using OpenSSL’s libcrypto, but the easiest method is to use the encoding libraries from Google Toolbox for Mac which is conveniently distributed under the Open Source Apache License. Download GTMDefines.h, GTMBase64.h and GTMBase64.m, then add them to your project. The GTM code compiles perfectly on the iPhone and even includes web safe variants that are immediately suitable for use in URLs without percent encoding.

The Code

With the project setup complete the Paid version will respond to the custom URL launch! This will facilitate an export from the Lite version to be received by the Full version.

The Lite Version

The Lite application should be extended to add a button to trigger the export on an about, settings, or upgrade page.

The controller action code will read the data file, encode it and then format a URL with the protocol prefix / URL scheme configured in the previous step.

#import "GTMBase64.h"
...
NSData *fileData = [NSData dataWithContentsOfFile:@"/path/to/LiteApplication/Documents/file"];
NSString *encodedString = [GTMBase64 stringByWebSafeEncodingData:fileData padded:YES];
NSString *urlString = [NSString stringWithFormat:@"myapp://localhost/importDatabase?%@", encodedString];
NSURL *openURL = [NSURL URLWithString:urlString];
[[UIApplication sharedApplication] openURL:openURL];

The Full Version

The final step is to make your application handle the Open URL event and reverse the encoding process.

Add a handleOpenURL method to the AppDelegate implementation as follows. This will receive the URL, sanity check it, and then parse the query string directly. The resulting binary data is written to the file in the full application’s data directory.

#import "GTMBase64.h"
...
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
	if([@"/importDatabase" isEqual:[url path]]) {
		NSString *query = [url query];
		NSString *importUrlData = [GTMBase64 webSafeDecodeString:query];
		
		// NOTE: In practice you will want to prompt the user to confirm before you overwrite their files!
		[importUrlData writeToFile:@"/path/to/FullApplication/Documents/file" atomically:YES];
		return YES;
	}
	return NO;
}

End Game

We have transferred files of up to 100k this way, and the size of a URL string is theoretically only limited by available memory. That said, this approach is most suitable for applications with small to medium size data transfer requirements. Best of all though, it can be easily used for SQLite databases, XML files, text files, or even extended to handled compressed archives.

Strip has seen steady growth since it’s release as people upgrade from Strip Lite to the full version. Based on download reports and direct comments from customers we believe that much of this is directly attributable to the simple upgrade path. Until (and if at all) Apple begins to allow in-app purchases from within free applications this is a simple and painless way to migrate data between Lite and Paid application versions.

It's Just a Middle Name

Posted: Jun 26, 2009 by Billy Gray Tagged whytheluckystiff, hacketyhack

Good lord, this is funny:

ART && CODE Symposium: Hackety Hack, why the lucky stiff from STUDIO for Creative Inquiry on Vimeo.

“I don’t exactly know why I’ve been invited here today…”

manufacturers as gatekeepers

Posted: Sep 08, 2009 by Billy Gray Tagged

Interesting observation from Leonard Lin (via Gruber) about Apple’s App Store and why he’s sticking with his Palm Pre, emphasis mine:

The experience is absolutely not as good as the iPhone, but I guess at the end of the day, it’s still much more usable than the Android, and for me, it’s worth supporting an alternative because well, despite Schiller’s outreach, the the App Store really is abominable, not just in its practice/actuality, but also, after having given it some thought, and reflecting on its implications, as a general model.

Mobile devices are the next generation general computing/network access platform and having a device manufacturer as a post-facto gatekeeper is just not right. Getting rid of end-to-end not only reverses the freedoms that spawned the innovation on the Internet, but also creates a bottleneck on software development/distribution that I’ve never seen in modern general computing…

While I share his sentiments, I’m not quite ready to jump into development for the Palm Pre.

New Zetetic Team Member - Bret Morgan

Posted: Mar 10, 2009 by Billy Gray Tagged zetetic, team, bretmorgan, bandsonabudget

Having an existent base of robust client work is awesome. So is having a revenue-generating web service! And so is building new apps for the iPhone! But all this takes time, and we’ve decided it was time to add another person to the team.

Bret Morgan, CEO of DBL Systems and creator of BandsOnABudget has come on board to be an extra pair of hands, helping us to maintain the current version of Tempo and build out the next revision, which includes a complete UI re-design from "nGenWorks"http://ngenworks.com!