Is the asynchronous part of Apple's new verification controller necessary? - iphone

I was looking through Apple's Verification Controller patch for In App Purchases here: https://developer.apple.com/library/ios/#releasenotes/StoreKit/IAP_ReceiptValidation/_index.html
I was planning on implementing server validation, but to not necessitate a response immediately.
Is the asynchronous part of their new code absolutely necessary. Does it offer any advantage over a naive server side validation?
If I could just use the immediate parsing and checking and gain a benefit, that would be great.
Thanks!
EDIT: This question feels a little empty without some code:
I'm talking specifically about changing the main verifyPurchase function to contain only:
- (BOOL)verifyPurchase:(SKPaymentTransaction *)transaction;
{
return [self isTransactionAndItsReceiptValid:transaction];
}
...and get rid of the client -> server post. Will I still be vulnerable to the recent hacks?

Your question makes much more sense after looking at the code.
The attack in question is that someone presents someone else's otherwise-valid receipt. There does not appear to be anything in the receipt data that ties it to the device/purchaser. You can mitigate this to some extent by checking the purchase dates (but only if the device has accurate time, which is under the user's control).
(This attack would not work if the client generated a 256-bit random nonce which had to match the receipt. An attacker can obviously hack the binary/PRNG, but in either case you've already lost.)
Incidentally, the code has a bunch of problems:
The only check of the server cert is that it's an EV cert. This should be easy to forge, since the attacker has complete control of the CA.
A transaction ID is permanently added to the list of "already seen" transactions in -isTransactionAndItsReceiptValid: before the network check finishes, but the content is only unlocked after the network returns. The receipt can never be re-verified if the connection fails, so the user's money will have effectively gone into a black hole.
It expects the transaction to have occurred on the same device that is verifying it.
It expects ITC_CONTENT_PROVIDER_SHARED_SECRET to be embedded in the executable (trivial to decrypt with a jailbroken device).
It assumes that -connection:didReceiveData: returns the complete receipt data (this might not be the case due to fragmentation, but it can probably be guaranteed since Apple controls the server implementation).

Related

Can too many WSASend in short time be a problem?

I'm making a simple mmorpg server with IOCP.
I implemented a simple movement function so I tested with dummy clients(also IOCP).
Everything works fine only when few clients are connected. After around 500~1000 clients are connected, some dummy clients occasionally read weird data. I checked that server sends data as I expected but when it comes to dummy clients reading them, they read random data.
My guess is that it could be related to operation system's recv buffer being overflowed but I'm only guessing right now... I have no idea how to check them.
Any suggestion would be very thankful!
The problem with too many WSASends doesn't usually manifest as corrupted data; that's more likely to be a bug in your code. Perhaps your problem is caused by you failing to manage the lifetime of the buffer that is being used to send data correctly? It needs to stay stable until you get the completion for the WSASend call. If you were reusing it sooner than that then you would corrupt the data being sent.
The reason this may show up when you have lots of WSASends outstanding to lots of clients is that the send operations may be taking longer to complete and so make it more likely that your bug will be hit...
It doesn't matter how many WSASends you issue as long as your clients are able to receive the data as fast as you can send it. As soon as you are sending faster than they can receive then there will be problems. I address these problems in this answer.

URLSession cache only

Sometimes I want to get data from the cache only when using URLSession. For example when quickly scrolling in a UITableView, I would like to show images that are already in the cache, but do not fire any HTTP requests. Images are just an example could be anything.
So I'm currently looking into URLSession's CachePolicy but it doesn't support an option to only get valid (not expired, etc) data from cache.
I can look into the URLCache myself, but this also of course returns data that might be expired. Is there some API that can validate a CachedURLResponse? Because then I can do it myself. Or do I have to implement the validating myself.
That's a fairly unusual request. Normally, you're either writing code to operate in an offline mode (in which case you want to pull from the cache whether the cached results are still valid or not) or you are online (in which case you want to fetch new data if it isn't valid).
I would encourage you to really think long and hard about whether you really want to force cache validation if you aren't firing network requests.
That said, if you really want that behavior, there are two ways you can do it:
Use NSURLRequestReturnCacheDataDontLoad and validate the age of the cached response yourself.
Perform the request in a custom session, use NSURLRequestUseProtocolCachePolicy, and in that session, install a custom NSURLProtocol subclass that overrides initWithTask:cachedResponse:client: and startLoading, and calls URLProtocol:didFailWithError: on the provided client at the top of its startLoading method.
The second approach is probably the best option, because you don't have to worry about knowing all the esoteric rules for cache validation. By making the actual load fail, the cache will work normally, but as soon as it actually would start making a network request, your custom protocol prevents that from happening. And because you'll register the protocol only in that specific session (via the protocolClasses array on the session configuration), it won't break networking in other sessions.

How to tell the difference between an offline and online mobile phone via sip?

For a toy project I want to find out if a mobile phone is connected to gsm or not. So I thought "Okay, let's use my local sip provider and see".
But in both cases, the thing goes like this:
I send an INVITE
0 s: I get a 100 Trying
5 s: I get a 183 Session description
I get an audio stream, in the one case with the ringing, in the other case with a "The person you are calling is…"
If I wait long enough (~ 40 s), I get a more appropiate status code like 180 Ringing.
Audio analysis is not an option, really.
Any hints on where to go now?
(I used twinkle for testing and a local german sip-provider.)
This issue is endemic in the way telephone networks work, and is not specific to SIP or IP. It's why, when you place a call to another country and the number is busy, you might sometimes hear your local country's busy tone, or you might hear a different busy tone that comes from the other country. In the latter case you cannot detect except by audio analysis, what the problem is. In SS7 and ISDN we speak of Q.931 cause codes instead of SIP error codes, but the principle is the same.
There's an argument to be made for configuring telephone systems to emit status codes instead of audio error messages. For callers using normal phones, the originating switch (the one closest to the caller) can then map that code to the appropriate spoken error message or audio tone. That way, when the call is being placed by software rather than by a person, the software can have access to the actual error code right away.
On the other hand you can also argue for having the remote switch (the one nearest the destination or the one that encounters the problem) speak its own error message. That switch knows best what the actual problem is. For example, a mobile operator can emit a spoken error message saying that the mobile phone you are trying to call is currently out of range. There is no Q.931 code (or SIP error code for that matter) with that meaning. It could return 27=Destination out of order?? Or 35=Destination unattainable?? Both of those codes are so esoteric, who knows what error message the local switch would translate them to (in practice: probably just a reorder tone, which is really user-unfriendly to a human caller). And when you try to map Q.931 cause codes to SIP error codes back and forth, even more information is lost because the codes really don't match up well at all. It's likely to be a much better user experience for the caller if the remote switch just plays back an informative, appropriate, recording which describes the problem.
Since there is this dilemma (arguments on both sides), we can conclude that this will not likely be resolved by completely standardizing on one way or ther other way anytime soon.
Anyway, sometimes this is configurable: your SIP provider may be able to configure your trunk for coded errors instead of recorded messages. If they offer this (some do), it's worth a try to set this option. But results will vary: this option only affects its local behaviour. In general if you want immediately call clearing with cause code and are instead getting a recorded error message from the other end, you will not be able to do anything about it, because the switch that makes the decision on which way it's going to respond is the remote one.
When using the audio message method, a proper Q.931 cause code or SIP error code usually comes eventually (after the recording is finished), but as you point out, it's probably too late by then.

Posting location updates in background from iOS4

Can i send location updates to my server in background from iOS4?. I want to get users location changes and post it to a server using a web-service call. Main question here is, is it possible to call a web-service or http-post while app is in background?
Absolutely, and you may want to review this earlier thread when I asked the same question - credit due to #RedBlueThing for providing the key information.
I've written this up as an example on our blog as well. The key to this working is beginBackgroundTaskWithExpirationHandler: without that you won't get reliable results as it will perhaps work some of the time, but not others.
Yes. You can basically do anything you want in the background callbacks.
I'd like to add that you should make sure you are aware of the possible impact on battery life, as the antennas may have to be turned on to perform your requests. Perhaps you could store the locations in core data, and post it to the server when the app resumes.
But there's no technical reasons to not do it, and afaik it will pass review too.

Determining if an iPhone is Jail broken Programmatically

How do you determine (programmatically) if an iPhone/iPod is:
Jail broken
Running a cracked copy of your software
Pinch Media can detect if a phone is jail broken or the software running is cracked, does anyone know how they do this? Are there any libraries?
Here is one of the ways to detect if your app was cracked.
In short: the cracking usually requires changing the Info.plist. Since it's regular file you have access to, it's pretty easy to determine such changes.
Detecting a jailbroken phone is as easy as checking for the presence of /private/var/lib/apt/ folder. Although this doesn't detect Installer-only users, by now most have have installed Cydia, Icy or RockYourPhone (all of which use apt)
To detect pirated users, the easiest way is to check for the presence of a SignerIdentity key in your app's Info.plist. Since advanced crackers can easily find the standard [[[NSBundle mainBundle] infoDictionary] objectForKey: #"SignerIdentity"] checks, it is best to obscure these calls using the Objective C runtime available via #import <objc/runtime.h> or use alternative equivalents.
Just to expand on zakovyrya's reply, you could use the following code:
if ([[[NSBundle mainBundle] infoDictionary] objectForKey: #"SignerIdentity"] != nil) {
// Jailbroken
}
HOWEVER, the person jailbreaking your app can hexedit your program and as such, they could edit the string #"SignerIdentity" to read #"siNGeridentity" or something else which would return nil, and thus pass.
So if you use this (or any of the other suggestions from http://thwart-ipa-cracks.blogspot.com/2008/11/detection.html):
Don't expect it to work forever
Don't use this information to break/hinder your app in any way (otherwise they'll have cause to hexedit it, so your app won't know it is jailbroken)
Probably wise to obfuscate this bit of the code. For example, you could put the base64 encoded reversed string in your code, and then decode it in the app by reversing the process.
Validate your validation later in your code (e.g. when I said SignerIdentity, did it actually say SignerIdentity or siNGeridentity?)
Don't tell people on a public website like stackoverflow how you do it
Keep in mind it is only a guide and is not fool-proof (nor cracker-proof!) - with great power comes great responsibility.
To expand on yonel's and Benjie's comments above:
1) Landon Fuller's method relying on encryption check, linked above by yonel, seem to be the only one still not defeated by automated cracking tools. I would not be overly worried about Apple changing the state of the LC_ENCRYPTION_INFO header any time soon. It does seem to have some unpredictable effects on jailbroken iphones (even when the user has purchased a copy...)
At any rate, I would not take any rash action against a user based on that code...
2) To complement Benjie's comment re. obfuscation (an absolute necessity when dealing with any string values in your anti-piracy code): a similar but perhaps even easier way is to always check a salted hashed version of the value you are looking for. For example (even though that check is no longer efficient), you would check each MainBundle's key name as md5(keyName + "some secret salt") against the appropriate constant... Rather basic, but sure to defeat any attempt at locating the string.
Of course, this requires you to be able to indirectly query the value you want to compare (for example by going through an array containing it). But this is most often the case.