TCP/IPでTLSを使用してWindows C#サーバーにiOSアプリケーションを接続しようとしています。iOS SecTrustRef常にNULL
TLS接続がmakecertユーティリティを使用して信頼できないCAのルート証明書から作成信頼できない証明書を使用しています。
これらの証明書をテストするために、簡単なC#クライアントを作成し、サーバーと接続して通信できる証明書を使用しました。
私は、iOSの開発に習熟していないんだけど、次のように私は、サーバーに私を接続しているいくつかのコードを見つけるために管理しました:
-(bool)CreateAndConnect:(NSString *) remoteHost withPort:(NSInteger) serverPort
{
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(remoteHost),
serverPort, &readStream, &writeStream);
CFReadStreamSetProperty(readStream, kCFStreamPropertySocketSecurityLevel,
kCFStreamSocketSecurityLevelNegotiatedSSL);
NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[inputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL forKey:NSStreamSocketSecurityLevelKey];
// load certificate from servers exported p12 file
NSArray *certificates = [[NSArray alloc] init];
[self loadClientCertificates:certificates];
NSDictionary *sslSettings = [NSDictionary dictionaryWithObjectsAndKeys:
(id)kCFBooleanFalse, (id)kCFStreamSSLValidatesCertificateChain,
certificates,(id)kCFStreamSSLCertificates,
nil];
[inputStream setProperty:sslSettings forKey:(__bridge NSString *)kCFStreamPropertySSLSettings];
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
CFReadStreamOpen(readStream);
CFWriteStreamOpen(writeStream);
return true;
}
コードもTLS交渉のいくつかのフォームを行うように見えます、 p12証明書がNSStream設定の一部として提供されていない場合、C#サーバーは接続を拒否します。
TLSネゴシエーションの最初の段階が機能しているようです。私はNSStreamEventHasSpaceAvailableイベントにNSStreamデリゲートによって呼び出されるこの機能、持っているサーバ証明書を検証するために
:
// return YES if certificate verification is successful, otherwise NO
-(BOOL) VerifyCertificate:(NSStream *)stream
{
NSData *trustedCertData = nil;
BOOL result = NO;
SecTrustRef trustRef = NULL;
NSString *root_certificate_name = @"reference_cert";
NSString *root_certificate_extension = @"der";
/* Load reference cetificate */
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
trustedCertData = [NSData dataWithContentsOfFile:[bundle pathForResource: root_certificate_name ofType: root_certificate_extension]];
/* get trust object */
/* !!!!! error is here as trustRef is NULL !!!! */
trustRef = (__bridge SecTrustRef)[stream propertyForKey:(__bridge id)kCFStreamPropertySSLPeerTrust];
/* loacate the reference certificate */
NSInteger numCerts = SecTrustGetCertificateCount(trustRef);
for (NSInteger i = 0; i < numCerts; i++) {
SecCertificateRef secCertRef = SecTrustGetCertificateAtIndex(trustRef, i);
NSData *certData = CFBridgingRelease(SecCertificateCopyData(secCertRef));
if ([trustedCertData isEqualToData: certData]) {
result = YES;
break;
}
}
return result;
}
を今すぐ問題がtrustRefオブジェクトがあり、関係なく、私がしようとするもの、ではありません常にnullです。このケースではありません示唆この引用がありhttps://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html
:このアップルの開発者のリンクから
あなたのストリームデリゲートのイベントハンドラが に呼び出される時までにがあることを示しています使用可能なスペースがソケット上にある場合、システムは既にTLSチャネルを構築しており、接続のもう一方の端から証明書 チェーンを取得し、それを評価する信頼オブジェクト を作成しました。
これを修正する方法に関するヒント?
これにアクセスするにはどうすればいいですか?trustRef NSStreamのオブジェクトですか?
編集:返信100pholeため
感謝。このような
何か:この作業を取得しようとして
は、私は、これは問題とは何かを持っていると私はクラスにそれらのソケットに関連するすべてのアイテムを移動し、私の多くの試みの一つでかもしれないと思いました。
@interface Socket
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
NSInputStream *inputStream;
NSOutputStream *outputStream;
@end
しかし、かなりのコードの一般的なパターンのように見える私のGoogle検索に基づいて、そのためには、同じ結果:(
を思い付いた私は戻って上に示したバージョンに戻った。
そう、私は先に述べたようにが、私は(今のところから)のObjective-Cには専門家だ:たとえば
は、アップルの開発者向けサイトからも、このコードは非常によく似たスタイルを使用しています私は間違っているかもしれませんが、私が見たことから、それらのアイテムをクラスに移動し、それらを持続させることは何の違いもないようです。
ストリームはメソッドのローカル変数のように見えます。つまり、メソッドが返ってきたときに破棄されます。 – l00phole
あなたのコードを尋ねるのに十分な時間だけ見ました...なぜ組み込みのNSURLセッションと接続クラスを使用しないのですか?接続設定と認証ハンドシェイクはすべてあなたのために処理されます(必要に応じて挿入するフック付き)。 –
あなたが参照しているWebページの注釈が表示されます。 '/ *入力ストリームと出力ストリームへの参照を保存しないように保存します。* /' – Wain