2010-12-06 18 views
5

अंतर्निहित सॉकेट को बंद किए बिना मैं जावा एसएसएल सत्र को कैसे बंद कर सकता हूं?अंतर्निहित सॉकेट बंद किए बिना एसएसएल बंद करना?

परिदृश्य यह है कि एक जावा क्लाइंट एक (गैर-जावा) सर्वर से कनेक्ट होता है, एसएसएल सेट करता है और सर्वर पर क्रेडेंशियल (उपयोगकर्ता नाम पासवर्ड) सुरक्षित रूप से भेजता है। सर्वर इन क्रेडेंशियल्स के तहत चल रहे एक पर्यावरण को स्थापित करता है, इस माहौल में एक नई प्रक्रिया को जन्म देता है और सॉकेट हैंडल पास करता है, लेकिन पकड़ यह है कि यह नई प्रक्रिया मौजूदा एसएसएल कनेक्शन का पुन: उपयोग नहीं कर सकती है (और एसएसएल सत्र का उपयोग नहीं कर सकता फिर से शुरू करना) ... इसलिए इस नई प्रक्रिया को उत्पन्न होने से पहले एसएसएल को बंद करना है, और फिर नई प्रक्रिया के साथ स्क्रैच से एसएसएल सत्र को फिर से बातचीत करना है।

समस्या यह है कि जावा की SSLSocket'sclose() विधि एसएसएल सत्र को बंद करने के अलावा सॉकेट को बंद कर देती है (sending the close_notify alert द्वारा)। ओपनएसएसएल के SSL_shutdown() फ़ंक्शन के बराबर प्रतीत नहीं होता है, जो अंतर्निहित सॉकेट को खोलने की अनुमति देता है।

मैं कुछ चीजें इस के आसपास पाने के लिए कोशिश की है:

  1. SSLSocket.startHandshake() दूसरी बार का उपयोग करना, लेकिन यह है कि स्वचालित रूप से मौजूदा कैश्ड एसएसएल सत्र (जो विफल रहता है फिर से शुरू करने की कोशिश करता है, के बाद से पैदा सर्वर प्रक्रिया नहीं है इस सत्र के बारे में जानें), और, force resuming SSL sessions or die trying पर कोई विधि होने पर, सभी कैश किए गए सत्रों को अमान्य करने या कैश किए गए सत्रों के उपयोग को अक्षम करने की कोई विधि नहीं है।

  2. , SSLSocketFactory.createSocket() का उपयोग कर गलत पर autoClose सेट के साथ अपने मौजूदा सॉकेट के शीर्ष पर एक SSLSocket बना रहा है। यह अंतर्निहित सॉकेट को बंद करने से close() विधि को रोकता नहीं है, और मुझे संदेह है कि autoClose पैरामीटर केवल प्रारंभिक हैंडशेक विफल होने पर सॉकेट को बंद होने से रोकता है।

  3. , (जैसा कि ऊपर) एक मौजूदा सॉकेट पर एक SSLSocket बनाना तो एक दूसरी SSLSocket बनाने (एक नई SSLContext से) पैदा की प्रक्रिया के साथ एसएसएल हाथ मिलाना के लिए उपयोग करने के लिए। यह विफल रहता है क्योंकि जब सर्वर close_notify अलर्ट भेजता है (उप-प्रक्रिया को उत्पन्न करने से पहले), जावा सॉकेट बंद कर देता है।

मैं इसे का उपयोग SSLEngine बारे में सुना है, लेकिन मैं यह भी पढ़ा है (हालांकि स्रोत वर्तमान में मुझे eludes) है कि यह दर्दनाक प्रयास टीसीपी/आईपी पर एसएसएल का सही कार्यान्वयन लिखने के लिए की एक बहुत कुछ है, और यह मुझे लगता है कि जब मुझे चाहिए तो SSLSocket का संस्करण होना चाहिए जिसका close()super.Close() पर कॉल नहीं करता है।

हालांकि, SSLSocket भी close() (जावाडोक के अनुसार) ओवरराइड करने के लिए प्रकट नहीं होता है, तो मैं यह कैसे हुक close() विधि जब वहाँ Socket पर करीब श्रोताओं पंजीकरण के लिए किसी भी समर्थन होने के लिए प्रकट नहीं होता है के रूप में अनिश्चित हूं।

कंपनी की नीति तय है कि कोई तीसरे पक्ष के एन्क्रिप्शन पुस्तकालयों इस्तेमाल किया जा सकता है, इसलिए मैं समस्या को हल करने Bouncy Castle द्वारा ऐसी है कि के रूप में एक विकल्प के एसएसएल कार्यान्वयन के लिए बारी नहीं कर सकते हैं।

यदि हमें काम करने के लिए वर्तमान 1-सॉकेट डिज़ाइन नहीं मिल रहा है, तो विकल्प 2 अलग सॉकेट का उपयोग करने के लिए क्लाइंट & सर्वर को फिर से लिखना है (जो सेवा और इंकार करने से इनकार करने के मामले में काफी गन्दा हो जाता है। बीच में हमले, और यह नहीं है कि एसएसएल पहली जगह के लिए क्या होना चाहिए?)।

इस समस्या को हल करने के तरीकों पर किसी भी इनपुट या विचार का स्वागत किया जाएगा।

+0

क्या आपने पृष्ठभूमि में सामान्य सॉकेट का उपयोग करने का प्रयास किया था? कुछ ऐसा: 'सॉकेट एस = नई सॉकेट (HOST, पोर्ट); SSLSocket एसएसएल = ...; ssl.connect (s.getRemoteSocketAddress()); ... '? (मेरे लिए कम से कम यह "अंतर्निहित" सॉकेट को बंद नहीं करता है .. * शायद मैं कुछ गलत कर रहा हूं * :)) – dacwe

+0

dacwe, जैसा कि मैं कह सकता हूं (आपके स्निपेट का हिस्सा ... अनदेखा कर रहा हूं) ssl.connect() मेजबान के लिए दूसरा कनेक्शन बनाएगा, और एसएसएल संचार के लिए सॉकेट 's का उपयोग नहीं किया जाएगा। – Caspar

उत्तर

2

यह अंतर्निहित सॉकेट

हाँ यह करता है को बंद करने से करीब() विधि नहीं रूकती है। दस्तावेज के अनुसार।

और मुझे लगता है कि स्वतः पैरामीटर केवल बंद किया जा रहा है जब प्रारंभिक हाथ मिलाना विफल रहता से सॉकेट से बचाता है।

नहीं। यह अंतर्निहित सॉकेट को बंद करने से रोकता है। दस्तावेज के अनुसार।

हमें कुछ कोड दिखाएं।

+0

मेरी गलती, आप सही हैं। 'SSLSocket.close()' javadoc एसएसएल संचार को बंद करने के बारे में कुछ भी नहीं कह सकता है और 'एसएसएल सॉकेट' के ग्रहण रूपरेखा दृश्य को 'करीबी' विधि नहीं दिखाती है (हो सकता है कि यह स्रोत अनुलग्नकों के बिना संकलित कक्षाओं के लिए ओवरराइड विधियों को प्रदर्शित न करे), लेकिन किसी भी तरह 'SSLSocket.close()' 'Socket.close()' की कार्यक्षमता को ओवरराइड करता है। – Caspar

+1

SSLSocket सार है। कार्यान्वयन वर्ग निकट() को ओवरराइड करता है। – EJP

+0

आह मुझे याद आया, धन्यवाद! – Caspar

2

आपको एक सादे अंतर्निहित सॉकेट (आपका # 3) का उपयोग करने में सक्षम होना चाहिए, क्योंकि यह स्पष्ट नियंत्रण चैनल के साथ एफ़टीपी का कार्यान्वयन है।

ध्यान रखें कि आप जो कुछ करने की कोशिश कर रहे हैं, वह दो एसएसएल सत्रों के बीच एक मैन-इन-द-बीच हमले के लिए खुलता है जब तक कि आप दोनों के बीच कुछ रहस्य नहीं लेते हैं कि प्रमाणीकरण अभी भी मान्य है।

  1. क्लाइंट और सर्वर के बीच प्रॉक्सी बनने के लिए नेटवर्क शून्य (एआरपी जहरीला?) का उपयोग करें।
  2. प्रमाणीकरण पूर्ण होने तक एसएसएल सत्र समाप्त होने तक दोनों दिशाओं को आगे बढ़ाएं। (कोई भी SSL ALERT अंत को इंगित करेगा, हमें सामग्री को डिक्रिप्ट करने की आवश्यकता नहीं है)।
  3. क्लाइंट को सॉकेट बंद करें ताकि यह त्रुटि हो जाए।
  4. सर्वर के साथ अपनी खुद की एसएसएल बातचीत करें।
  5. ग्राहक के क्रेडेंशियल्स के साथ काम करने के लिए आगे बढ़ें।
+0

ईजेपी ने मेरे प्रश्न का बेहतर उत्तर दिया, लेकिन एमआईटीएम हमले को इंगित करने के लिए +1 जो मैंने नहीं सोचा था। – Caspar

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