IMessage

From IMFreedom Wiki
Revision as of 15:36, 17 February 2012 by Xnyhps (talk | contribs)

http://en.wikipedia.org/wiki/IMessage

Information on this page is based on my examination of the Messages Beta application for Mac OS X.

applepushserviced

The "client" works with three processes: iChat, imagent and applepushserviced. iChat (which is now Messages) shows the UI, but does not handle anything about logging in, that's what imagent does (so the user stays logged in if iChat isn't running). applepushserviced is a system level daemon that maintains an XMPP connection to courier.push.apple.com, probably for all push notifications.

The connection of applepushserviced is encrypted with TLS using a client side certificate. To retrieve such a certificate, it posts to: https://albert.apple.com/WebObjects/ALUnbrick.woa/wa/deviceActivation?device=MacOS (NOTE: this has a content type of "application/x-www-form-urlencoded", contrary to most other requests, it is shown unencoded here):

activation-info=<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>ActivationInfoComplete</key>
	<true/>
	<key>ActivationInfoXML</key>
	
	(again a plist, see next block)
	
	<key>FairPlayCertChain</key>
	
	(around 50 lines of ASCII data, probably a certificate chain)
	
	<key>FairPlaySignature</key>
	
	(about 3 lines, probably related to the previous certificate)
	
</dict>
</plist>

The ActivationInfoXML field contains (base64 encoded):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>ActivationRandomness</key>
	<string>(hexadecimal string)</string>
	<key>ActivationState</key>
	<string>Unactivated</string>
	<key>BuildVersion</key>
	<string>11D50</string>
	<key>DeviceCertRequest</key>
	
	(ASCII data, probably a CSR)
	
	<key>DeviceClass</key>
	<string>MacOS</string>
	<key>ProductType</key>
	<string>iMac10,1</string>
	<key>ProductVersion</key>
	<string>10.7.3</string>
	<key>SerialNumber</key>
	<string>XXXXX</string>
	<key>UniqueDeviceID</key>
	<string>(hexadecimal string</string>
</dict>
</plist>

The server replies:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Document disableHistory="true" xmlns="http://www.apple.com/itms/">
  <Protocol>
    <plist version="1.0" >
      <dict>
        <key>device-activation</key>
        <dict>
          <key>activation-record</key>
          <dict>
            <key>AccountTokenCertificate</key>
            (probably a PEM encoded certificate)
            <key>DeviceCertificate</key>
            (probably another PEM encoded certificate)
            <key>AccountTokenSignature</key>
            (a signature created with the first certificate? of the token?)
            <key>AccountToken</key>
            (also a random ASCII string, unknown usage)
          </dict>
          <key>ack-received</key>
          <true/>
          <key>show-settings</key>
          <true/>
        </dict>
      </dict>
    </plist>
  </Protocol>

(after this, a number of lines of XML follow, appearing to describe an iTMS page)

imagent

Getting the auth token

Messages.app posts to https://service.ess.apple.com/WebObjects/VCProfileService.woa/wa/authenticateUser, with a content type of "application/x-apple-plist":

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
       <key>password</key>
       <string>sekret</string>
       <key>username</key>
       <string>steve@apple.com</string>
</dict>
</plist>

Server replies with something like:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>status</key><integer>0</integer>
 <key>auth-token</key>
 <string>(long, random string)</string>
 <key>profile-id</key><string>D:(some number, unknown usage)</string>
</dict>
</plist>

The default invitation context (how to look up contacts)

Client posts to https://service.ess.apple.com/WebObjects/VCProfileService.woa/wa/getDefaultInvitationContext, adding the following HTTP headers:

x-ds-client-id: t:(some long hexadecimal string, unknown use (identifies software version? or a computer?))
x-protocol-version: 4
x-vc-profile-id: D:(the profile-id as received in step 1)
x-vc-auth-token: (the auth token)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict/>
</plist>

Server replies:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
 <key>extra</key>
 <dict>
 </dict>
 <key>status</key><integer>0</integer>
 <key>region-id</key><string>R:(two letter region code, examaple: NL)</string>
 <key>base-phone-number</key><string>+310000000000</string>
 <key>validated</key><true/>
</dict>
</plist>

Check if the email needs validation

Client posts to https://service.ess.apple.com/WebObjects/VCProfileService.woa/wa/validateEmail (with the same extra headers):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
       <key>email-address</key>
       <string>steve@mac.com</string>
       <key>push-token</key>
       
       (appears to be a random string, around 45 bytes)
       
</dict>
</plist>

(During this, the client displays a dialog with "You can be reached for messages at:", and a list with the used email, and the option to add more email addresses.)

Server replies:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>status</key><integer>5051</integer>
</dict>
</plist>

(My best guess of why it has a non-zero status is that 0 indicates the validation of a user's email has started, and 5051 means "no validation needed")

Send a CSR and get a certificate

Client posts to https://service.ess.apple.com/WebObjects/VCProfileService.woa/wa/idsProvisionEmails WITHOUT the extra headers, only:

x-protocol-version: 5
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>authentication-data</key>
	<dict>
		<key>auth-token</key>
		<string>(the auth token again)</string>
	</dict>
	<key>csr</key>
	
	(a certificate signing request, PEM encoded)
	
	<key>identities</key>
	<array>
		<dict>
			<key>uri</key>
			<string>mailto:steve@mac.com</string>
		</dict>
	</array>
	<key>service</key>
	<string>Messenger</string>
	<key>user-id</key>
	<string>D:(the profile id)</string>
</dict>
</plist>

The server replies:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>identities</key>
  <array>
    <dict>
      <key>status</key><integer>0</integer>
      <key>uri</key><string>mailto:steve@mac.com</string>
   </dict>
 </array>
 <key>status</key><integer>0</integer>
 <key>cert</key>
 (a PEM encoded certificate)
</dict>
</plist>

Unknown

Then the client posts to https://service2.ess.apple.com/WebObjects/TDIdentityService.woa/wa/initializeValidation, with only the extra header:

x-push-token: (the push token created in the earlier step)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>session-info-request</key>
        
        (7 lines of random appearing data. looks like something PEM encoded, but I haven't been able to decode it as a CSR or certificate.)
        
</dict>
</plist>

The server replies:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>status</key><integer>0</integer>
  <key>ttl</key><integer>300</integer>
  <key>session-info</key>(yet another long string of random data)
</dict>
</plist>

Unknown2

Then the client posts to https://service2.ess.apple.com/WebObjects/TDIdentityService.woa/wa/register, without the extra headers, but with:

x-pr-cert: (the certificate the client received in the previous step)
x-pr-nonce: (the nonce used for generating the signature)
x-pr-sig: (the signature of the data? url?)
x-push-cert: (another cert in PEM format, don't know where it's from. issued by "Apple iPhone Device CA". has a "Mac OS Device Identity (Production)" section.)
x-push-nonce: (?)
x-push-sig: (?)
x-push-token: (the push token created before)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>capabilities</key>
        <array>
                <dict>
                        <key>flags</key>
                        <integer>1</integer>
                        <key>name</key>
                        <string>Messenger</string>
                        <key>version</key>
                        <integer>1</integer>
                </dict>
        </array>
        <key>client-data</key>
        <dict>
                <key>public-message-identity-key</key>
                
                (a public key)
               
               <key>public-message-identity-version</key>
               <integer>1</integer>
       </dict>
       <key>hardware-version</key>
       <string>(something which determines the Mac model, for example iMac10,1)</string>
       <key>os-version</key>
       <string>(system version, for example Mac OS X,10.7.3,11D1069)</string>
       <key>software-version</key>
       <string>(build number 11D1069)</string>
       <key>validation-data</key>
       
       
</dict>
</plist>

The server replies:

?

Looking up contacts

Messages now shows the login as complete. Looking up users can be done as follows:

A client does a GET request for https://service1.ess.apple.com/WebObjects/TDIdentityService.woa/wa/query?uri= followed by either an email as mailto%3Asteve@mac.com or a phone number as tel%3A%2B30000000000. The only headers included are:

x-id-nonce: (the nonce used for signing)
x-id-cert: (the cert received from the server)
x-id-sig: (probably the contents? request? signed by the private key belonging to the certificate)

To which the server replies something like:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>status</key><integer>0</integer>
  <key>identities</key>
  <array>
  </array>
</dict>
</plist>