Keyword - Mac OS X

Entries feed - Comments feed

Thursday, May 24 2012

Debugging Mac AppStore receipt validation

Setting up receipt validation for Mac OS X application can be a tedious task, especially with all the steps to follow in order to have a proper test environnement. Of course, by using Receigen, the code writing part is easy as pie, but most of the issues occur during the testing.

I have written a shell script that dumps all the information regarding the hardware, the application bundle and the receipt. With one command, you are able to see information like the primary MAC address, the bundle identifier and version and the essential values of the receipt.

So, if you encounter a problem during the testing of the receipt validation, running this script will be give you all the information needed to diagnose the problem.

To use it (assumer the script is located under the current directory):

$> ./receigen_dump.sh /Applications/<Your App>.app

Here is an example of the output for the Xcode.app:

===========================
===== Receigen Dumper =====
===========================

----- BEGIN HARDWARE INFORMATION -----
System Name         : Darwin cupertino 11.4.0 Darwin Kernel Version 11.4.0: Mon Apr  9 19:32:15 PDT 2012; root:xnu-1699.26.8~1/RELEASE_X86_64 x86_64
Primary MAC Address : c4:2c:03:c4:2c:03
----- END HARDWARE INFORMATION -----

----- BEGIN APPLICATION INFORMATION -----
Application Bundle     : /Applications/Xcode.app/
Application Name       : Xcode.app
Application Identifier : com.apple.dt.Xcode
Application Version    : 4.3.2

Signature check
---------------
/Applications/Xcode.app/: valid on disk
/Applications/Xcode.app/: satisfies its Designated Requirement

Signature information
---------------------
Executable=/Applications/Xcode.app/Contents/MacOS/Xcode
Identifier=com.apple.dt.Xcode
Format=bundle with Mach-O thin (x86_64)
CodeDirectory v=20100 size=187 flags=0x200(kill) hashes=3+3 location=embedded
Hash type=sha1 size=20
CDHash=f1cd6c670213af6d6fa7374f04de6a68fdb5e614
Signature size=4169
Authority=Apple Mac OS Application Signing
Authority=Apple Worldwide Developer Relations Certification Authority
Authority=Apple Root CA
Info.plist entries=30
Sealed Resources rules=14 files=45
Internal requirements count=2 size=344

Signed files
------------
Executable=/Applications/Xcode.app/Contents/MacOS/Xcode
/Applications/Xcode.app/Contents/MacOS/Xcode
/Applications/Xcode.app/Contents/_CodeSignature/CodeResources

Designated requirements
-----------------------
Executable=/Applications/Xcode.app/Contents/MacOS/Xcode
designated => (anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9] /* exists */ or anchor apple generic and certificate 1[field.2.5.29.37] /* exists */ and certificate 1[subject.CN] = "Apple Code Signing Certification Authority" and certificate leaf[field.2.5.29.37] /* exists */ and certificate leaf[subject.CN] = "Software Signing") and identifier "com.apple.dt.Xcode"
library => identifier "libSystem.B.dylib" and anchor apple

Entitlements
------------
Executable=/Applications/Xcode.app/Contents/MacOS/Xcode

----- END APPLICATION INFORMATION -----

----- BEGIN RECEIPT INFORMATION -----
Receipt identifier : com.apple.dt.Xcode
Receipt version    : 4.3.2
Receipt opaque     : 000000000000
Receipt SHA-1      : 4747474747474747474747474747474747474747

subject=/CN=Mac App Store Receipt Signing/OU=Apple Worldwide Developer Relations/O=Apple Inc./C=US
issuer=/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority

subject=/C=US/O=Apple Inc./OU=Apple Worldwide Developer Relations/CN=Apple Worldwide Developer Relations Certification Authority
issuer=/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA

subject=/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA
issuer=/C=US/O=Apple Inc./OU=Apple Certification Authority/CN=Apple Root CA

----- END RECEIPT INFORMATION -----

The link to the shell script.

Sunday, November 6 2011

Mac OS X Application SandBoxing: what about Apple ?

There is a lot of discussions around the upcoming sandboxing requirement for all the Mac App Store published applications.

There were several publications on the subject with sometimes very elaborate discussion:

These articles lead me to wondering:

  • Apple is going to enforce sandboxing on third-party applications, but what about Apple's own applications ?
  • Sandboxing is said to be a work in progress; the current entitlement keys are sparse and most of the time, developers relies on temporary exceptions to keep their application fully functional. Is there anything in Apple's applications that give a clue of possible entitlement keys ?

So, I decided to take my Terminal and play with the codesign tool. This tool is very useful because if can sign binaries (obviously), but it can also print what is contained in the signature (certificate chain, requirements, entitlements). So I ran it on my Application folder.

cd /Applications
find . -type d -name "*.app" -exec echo {} \; -exec codesign -d --entitlements - {} \;

Here are the applications that contain entitlements (as on 2011-11-06). I have indicated if they mandate the use of sandbox:

  • Address Book
  • App Store
  • FaceTime
  • Font Book
  • Preview (SANDBOXED)
  • TextEdit (SANDBOXED)
  • Activity Monitor
  • Boot Camp Assistant
  • RAID Utility
  • iCal
  • PhotoStreamAgent (in iPhoto)
  • iTunes

Here are the key points:

  • All the Apple applications are signed
  • Only a few of them contain entitlements
  • Only two of them are sandboxed

Digging further into the entitlements, I found:

  • Preview is actually using a temporary entitlement key for global Mach lookup. So don't be shy using them into your applications !
  • A bunch of private entitlement keys: they may be migrated to public entitlement keys as they seems generic.

And finally, here are the private entitlement keys I found:

  • com.apple.private.aps-connection-initiate: it seems related to iCloud, as applications like Address Book, FaceTime, iCal, iTunes and iPhoto (PhotoStreamAgent) have this one.
  • com.apple.private.dark-wake-push: a key to wake up the computer ???
  • com.apple.private.AuthorizationServices: widely used, it seems a good candidate for a future entitlement key.

I hope that by March 2012, Apple would have solved all the details about sandboxing. It would be nice to see a set of versatile entitlement that could protect the end-user and let the developer be inventive.

Saturday, October 29 2011

Receigen, a smart code generator for Mac App Store receipt validation

Receigen has just been made available in the Mac App Store.

If you are developing an application for Mac and want to distribute it in the Mac App Store, you will be inevitably faced to receipt validation. This entry explains what is receipt validation and why Receigen can help you.

What is receipt validation ?

When you purchase an application from the Mac App Store, it installs into the /Applications folder of your Mac. Inside the application bundle, the Mac App Store application places a receipt file. This file is a record of sale that can be used to check if the installed copy of the application is authorized to run. Apple is providing a comprehensive documentation on the technical issues.

Why do I need receipt validation ?

If you fail to property validate the receipt file, anybody with a copy of your application can run it, with or without proper authorization. This happened to some developpers in the early days of Mac App Store.

What are the steps of validation ?

In order to code the receipt validation, you need to understand:

  • how asymetric cryptography works
  • how signature are attached to a container
  • how ASN.1 encodng/decoding works
  • how to obfuscate code to harden the reverse engineering.

Here is the basic workflow to use when validating a receipt:

  1. Locate the receipt file to load it: this is an easy part as its location is fixed inside the application bundle.
  2. Verify that the receipt is properly signed: the receipt file is a PKCS#7 container that contains the receipt data and that is signed by Apple.
  3. Extract the receipt data: the receipt data are encoded in ASN.1 format, which is a compact binary format widely used in cryptography.
  4. Check that the receipt data matches the bundle information and the machine the application is running on.
  5. Make sure that the checking code is secure. You should hide strings, constants, function calls and make sure that the validation code changes between each release of your application.

Damn, that seems a lot of work

Yes, it is. And I am sure that you have better to do than spending hours on this topic. Receigen has been designed to cope with all this tedious work, by ensuring that you can focus on your application and only your application.

Here is what Receigen brings you:

  • Smart generation of validation code: all it needs is the bundle identifier and version.
  • Seamless integration with Xcode: Receigen can be invoked on the command line easily.
  • Human readable code: Receigen produces a human readable code but still obfuscated when compiled.
  • Never twice the same code: Receigen embeds a code generator that produce a different output each time it is invoked.
  • A tiny price: think about the time you will have spent to produce the same code.

So, go and try out Receigen on the Mac App Store.

Sunday, September 18 2011

Monobjc Continuous Integration

The upcoming version of Monobjc 4.0, will be able to run on Mac OS X 10.5, 10.6 and 10.7 operating systems under both i386 and x86_64 architectures. For a complete coverage of this platforms and architectures, the goal is to have these three platforms readily available so non-regression and deployment testing occurs almost seamlessly.

Thanks to Parallels Desktop, I was able to quickly setup two virtual machines running respectively Mac OS X 10.5 and 10.6, on top of a Mac OS X 10.7 system. Then I setp up a Jenkins based continuous integration system driving all the platforms; non-regression testing can now be run on the three platforms easily.

Monobjc CI Infrastructure

Thursday, July 21 2011

Monobjc under Mac OS X 10.7 (Lion)

As some of you may have noticed, Monobjc is under heavy development to support the newly released version of Mac OS X 10.7, also known as Lion. Thanks to the architecture redesign performed under the version 3.0 (the native runtime), the transition is smooth and easy. A preview release of Monobjc for Lion should be out by the end of the month.

Wednesday, February 23 2011

Mono 64 bits on Mac OS X

If you ever wanted to try (or even use) Mono 64 bits on Mac OS X, I have created a small project on GitHub called Mono-Sixty-Four. This is a simple scrip that creates a minimal 64 bits Mono runtime and merges it with an existing Universal 32 bits Mono runtime. At the end, you get a Universal 32/64 bits Mono runtime.

For the moment, only the Mono runtime supports 64 bits. Additional libraries (GTK, SQLite, etc) ARE not supported.

Tuesday, November 23 2010

Class Prefixes in Mac OS X Frameworks

Ever wanted to have all the class prefixes used in Mac OS X frameworks ? A simple answer lies in Apple documentation; here it is.

Thursday, November 13 2008

<mkbundle/> task in Monobjc

Many people want to package their .NET application for Mac OS X. And above all, they want the experience to be painless, which means that they want to ship an application that runs, whether Mono is installed or not.

The process of packaging a .NET application for Mac OS X basically follows 4 steps:

  • Getting .NET dependencies of the .NET executable
  • Generating a native loader that will embed all the .NET assemblies (.NET executable and .NET dependencies)
  • Getting native dependencies of the native executable
  • Relocating all the stuff so library loading goes well

The process can be even more complicated if you are using reflection, dynamically discovered library and so on. So let's keep thing simple.

Getting .NET dependencies

This is the easy part. You just have to find recursively all the .NET dependencies of the .NET executable. As every .NET assembly contains its references, it is trivial.

Generating a native loader

The native loader generation is simplified by the fact that Mono allows .NET assemblies to be loaded from embedded binary streams. So for every .NET assembly, we generate a binary array and use the magical functions of Mono. If there are configuration files to embed, the process is the same.

Getting native dependencies

Once the native loader is compiled, the otool command can give us all the native dependencies. So we gather all the native library needed to run our application. But on Mac OS X, the dynamic loading is based on paths recorded in each native library. This is the point of the next step.

Relocating all the stuff

This is the tougher part of the packaging. Now that you have all the native dependencies, you must be sure that you only have unique dependencies. Why, because we you gather dependencies, you can find either specific version of a library or compatibility version of a library. Failing to make these reference unique can lead to unexpected behavior (mostly cryptic crashes). That where the otool command is useful as the first line always contains the specific version of a library, even if run against a compatibility version symbolic link. Then the install_name is used to change absolute path to relative path containing the macro @executable_path.

Packaging made easy

All this steps can be tedious and error prone. That's why, in the Monobjc, the packaging is done by a NAnt task: <mkbundle/> (you can find its options on this page). This task can handle most of the need for .NET application packaging in a truly simple way. And as a bonus, this task is not linked to the Monobjc bridge, so you can use it even if you don't use the Monobjc bridge.

Wednesday, September 17 2008

VMWare Fusion 2.0 is out, and it goes fast

I am a long term fan of VMWare Fusion, and I have followed with interest the various beta of VMWare Fusion. Today, I have installed the 2.0 final release, and I immediatly see that something has changed. Things seems to go faster, snappier and slicker. So, if you own a Mac and wants to go into the desktop virtualization world, try out VMWare Fusion.

Sunday, September 14 2008

Future of Monobjc

Monobjc is more than one year old, and the time has come to go beyond the Monobjc bridge. In order to develop the .NET programming on Mac OS X, a bridge is not enough. A whole development ecosystem is needed, so any new developer will have all the necessary tools to leverage the power of .NET on Mac OS X. I have identified several tools needed when developing applications:

  • IDE: An IDE is great as it speeds up the edition on multiple document and centralized the application development (code writing, compilation and packaging). Unfortunatly, an IDE is a very complex machinery. Identified solutions: fork SharpDevelop or MonoDevelop.
  • Reflector: A tool like Red Gate Reflector is useful when dealing with assemblies. The though part is to write the IL reverse-engineering engine. Identified solution: a Reflector clone based on Mono Cecil.
  • Obfuscator: When distributing applications, obfuscation is an additional mesaure to protect your investment. Identified solution: an obfuscation tool based on Mono Cecil.

The ecosystem can also be completed by libraries either based on Mac OS X framework (Sparkle, Growl, ...) or existing .NET libraries. Stay tuned as now, the goals for Monobjc are clear.

- page 1 of 2