I've been fighting with a particular network problem for a while now
and it's time to beg for help...
The issue is this: I have a web site I need to connect to, that
requires any connections use "mutual authentication" - this means that
when my application needs to connect, it has to provide a specific X.
509 'identity' with the connection. You can see the behavior if you
use MobileSafari to connect to a web site, and it prompts you to
select a certificate.
I BELIEVE the problem that I'm having is that the iPhone doesn't
"realize" that the remote server is looking for the client
certificate, due to a bug in iPhoneOS (???).
When I attempt to access the SSL web site using MobileSafari, it
prompts me for the certificate 3 times before it (MobileSafari) sends
the certificate to the other site, at which point the remote site
accepts my client certificate, and everything works. I haven't
figured out how to simulate the "try 3 times" in my code, though.
The remote server is Apache, running with an SSL certificate that has
been signed by a 'custom' Certificate Authority. This CA's public
certificate -is- installed on the iPhone. If we disable
"SSLVerifyClient require", MobileSafari can access the site without
prompting about an invalid certificate; when we re-enable
"SSLVerifyClient require", I get the behavior described in the prior
When I try to access the web site using my application, I get an error
back, "domain 3, code -9829" which is "errSSLPeerCertUnknown"... I
can't find anywhere what that error is actually referring to, though!
Because the connection works in MobileSafari, and in fact works in my
application if I disable VerifyClient on the server, I have to ASSUME
that the error is being triggered by the web server, even though it's
being reported through the CFNetwork stack on my iPhone.
- The client certificate I am using is stored within my application
as a .p12 file that I am reading in and retrieving the Identity
(SecIdentityRef). I have validated that I can retrieve the 'CN' field
from within my application, and thus believe that I have "properly"
read in the .p12.
- The CA cert associated with my identity is properly configured on
the server (I see it in the logs) and is being read in and passed as
the 2nd item in the NSArray that I'm passing:
- The client certificate and CA cert, in addition to being
explicitly loaded by my application from its bundle, are also
installed into the iPhone's keychain (via a configuration profile),
which is how MobileSafari uses them.
I'm at a loss here... I have a complete test environment set up and
would appreciate any help, suggestions, etc. that folks can come up
with. If someone really knows what they're doing, I can give them
URLs and .p12 files that will show the problem, or talk them through
setting up their own environment.
Thanks for any help!!
I'm using NSURLConnection and have a delegate that - when the server
requires certs ([[protectionSpace authenticationMethod]
isEqual:NSURLAuthenticationMethodClientCertificate]), does the right
thing. (loads the identity from my .p12 file -- I haven't figured out
how to use the one I installed into the keychain -- and the
'trusts' (certs) from the .p12, creates a new NSURLCredential with
them, and tells NSURLConnection to try again.)
Hope this helps someone. I'm going to eventually write this up with
source code for a coworker, if anyone needs it let me know.
I've a similar problem to you. I've configured Apache 2.2 to require
SSL client certificate for mutual authentication. I'm looking for some
peer certificates, can help you...)
So, I tryied some different way to make it. My problem is that when
MobileSafari show me a box to select my identity certificate, this
didn't send to server-side. I've installed, same you, a p12
profile system. I've configure apache on my mac by adding the
"SSLVerifyClient require" and this in fact works. When I make a
the server in https, MobileSafari tell me that the site require a
I have selected the certificate in the box that MobileSafari showed
on the server-side this certificate doesn't send. More specifically,
variable SSL_CLIENT_CERT doesn't have set.
How did you do that?
I think we can help each other.
Thanks for the post. This is the exact problem that I'm having, and
I'd like to try your solution. If you'd be so kind as to publish the
source code and/or write-up somewhere I'd much appreciate it.