2015-10-16 7 views
13

मैं टीसीपी/आईपी पर टीएलएस का उपयोग कर एक आईओएस ऐप को विंडोज सी # सेवर से कनेक्ट करने का प्रयास कर रहा हूं।आईओएस SecTrustRef हमेशा NULL

TLS कनेक्शन अविश्वस्त प्रमाण पत्र एक अविश्वस्त सीए मूल प्रमाणपत्रmakecert सुविधा का उपयोग से बनाए उपयोग कर रहा है।

इन प्रमाणपत्रों का परीक्षण करने के लिए मैंने एक सरल सी # क्लाइंट बनाया और उन प्रमाणपत्रों का उपयोग करके यह सर्वर से कनेक्ट और संवाद करने में सक्षम था।

मैं इस प्रकार आईओएस विकास में कुशल नहीं हूँ, लेकिन मैं कुछ कोड मुझे सर्वर से कनेक्ट करता है कि खोजने के लिए प्रबंधन कैसे किया,:

-(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; 
} 

कोड भी टीएलएस बातचीत के कुछ फार्म करने के लिए लगता है, क्योंकि C# सर्वर कनेक्शन को अस्वीकार करता है यदि P12 प्रमाणपत्र 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 वस्तु है:

सर्वर प्रमाणपत्र मैं इस समारोह है, जो NSStreamEventHasSpaceAvailable घटना पर NSStream प्रतिनिधि से बुलाया जाता है प्रमाणित करने के लिए हमेशा शून्य

इस एप्पल डेवलपर लिंक से: https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/NetworkingTopics/Articles/OverridingSSLChainValidationCorrectly.html

इस बोली कि सुझाव है कि यह मामला नहीं होना चाहिए नहीं है:

समय अपनी स्ट्रीम प्रतिनिधि के ईवेंट हैंडलर के लिए बुलाया जाता है के द्वारा संकेत मिलता है कि वहाँ सॉकेट पर उपलब्ध स्थान, ऑपरेटिंग सिस्टम पहले से ही एक टीएलएस चैनल का निर्माण कर चुका है, कनेक्शन के दूसरे छोर से सर्टिफिकेट श्रृंखला प्राप्त की है, और इसका मूल्यांकन करने के लिए ट्रस्ट ऑब्जेक्ट बनाया है।

इसे ठीक करने के तरीके पर कोई संकेत?

मैं उस ट्रस्टआरफ एनएसएसटी स्ट्रीम के लिए ऑब्जेक्ट तक कैसे पहुंच सकता हूं?

संपादित करें:

जबाब 100phole के लिए धन्यवाद।

इस काम करने के लिए प्राप्त करने की कोशिश में, मैंने सोचा था कि इस मुद्दे के साथ कुछ हो सकता है और मेरे सारे प्रयास में से एक में मैं एक वर्ग में उन सॉकेट संबंधित आइटम के सभी चले गए:

कुछ इस तरह:

@interface Socket 
    CFReadStreamRef readStream; 
    CFWriteStreamRef writeStream; 

    NSInputStream *inputStream; 
    NSOutputStream *outputStream; 
@end 

लेकिन वह एक ही परिणाम :(

मैं केवल वापस संस्करण ऊपर दिखाए गए की ओर लौट आया क्योंकि मेरे गूगल खोज, एक काफी कोड आम पैटर्न प्रतीत होता है कि पर आधारित है।

०१२३५१६४१०६ के साथ आया था

उदाहरण के लिए, Apple डेवलपर साइट से भी इस कोड को एक बहुत ही इसी तरह की शैली का उपयोग करता है:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Streams/Articles/NetworkStreams.html#//apple_ref/doc/uid/20002277-BCIDFCDI

कि मैंने पहले उल्लेख किया है, मैं ऑब्जेक्टिव-सी में कोई विशेषज्ञ हूँ (यह से दूर), इसलिए मैं गलत हो सकता हूं, लेकिन मैंने जो देखा है, उन वस्तुओं को कक्षा में ले जाना और उन्हें जारी रखना कोई फर्क नहीं पड़ता।

+2

आपकी धाराएं एक विधि में स्थानीय चर के रूप में दिखाई देती हैं, जिसका अर्थ है कि विधि वापस आने पर उन्हें नष्ट कर दिया जाएगा। – l00phole

+0

आपके कोड को केवल इतना पूछने के लिए पर्याप्त लग रहा था ...अंतर्निहित NSURL सत्र और कनेक्शन कक्षाओं का उपयोग क्यों न करें? कनेक्शन सेटअप और ऑथ हैंडशेक सभी आपके लिए संभाले जाते हैं (आवश्यक होने पर हुक के साथ इंटरैक्ट करने के लिए)। –

+0

आप उस वेब पेज में नोट देखते हैं जो आप कह रहे हैं '/ * इनपुट और आउटपुट स्ट्रीम के संदर्भ को स्टोर करें ताकि वे दूर न जाएं .... */' – Wain

उत्तर

0

चूंकि इस प्रश्न में कुछ रूचि दिखाई देती है, इसलिए मैंने इस समस्या को अंततः हल करने के तरीके के बारे में विवरण के साथ प्रश्न को अद्यतन करने का निर्णय लिया।

पहले कुछ पृष्ठभूमि। मैंने पिछले कोडर से इस कोड को विरासत में मिला और मेरी भूमिका टूटी हुई कोड को काम करने के लिए थी।

मैंने ऐप्पल आईओएस डेवलपर वेब पेज के विवरण का उपयोग करके कनेक्शन कोड लिखने और फिर से लिखने में काफी समय बिताया, लेकिन कुछ भी काम नहीं कर रहा था।

मैं अंत में इस समारोह को करीब से देख लेने का फैसला किया, कोड मैं विरासत में मिली थी और गलत तरीके से ग्रहण काम कर रहा था:

[self loadClientCertificates:certificates]; 

पहली नज़र में कोड ठीक देखा। फ़ंक्शन ने फ़ाइल से लोड प्रमाण पत्र से अधिक कुछ नहीं किया। लेकिन करीब निरीक्षण पर, जबकि कोड सही ढंग से प्रमाण पत्र लोड कर रहा था, यह कॉलर को उन प्रमाणपत्रों को वापस नहीं कर रहा था !!!

उस कोड को ठीक करने के बाद यह सही ढंग से प्रमाण पत्र लौटाता है कि कनेक्शन कोड ठीक काम करता है और SecTrustRef अब शून्य नहीं था।

सारांश में:

1) एप्पल प्रलेखन, अच्छे उदाहरण की कमी है, जबकि सही प्रतीत होता है।

2) कारण SecTrustRef शून्य था, क्योंकि कोई भी मान्य प्रमाणपत्र कनेक्शन वार्ता चरण के लिए पाया जा सकता है और कहा कि था क्योंकि कोई प्रमाण पत्र जहां पहले उल्लेख किया कोडिंग त्रुटि के कारण कनेक्शन एपीआई के लिए उपलब्ध कराया जा रहा है ।

3) यदि आपको एक ही त्रुटि दिखाई दे रही है, तो मेरा सुझाव आपके कोड को जांचना और दोबारा जांचना होगा, क्योंकि उम्मीद की जाएगी, समीकरण का आईओएस पक्ष दस्तावेज के रूप में काम करता है।

संबंधित मुद्दे