2014-07-11 6 views
5

मैं एसएसटीपी सर्वर के माध्यम से एसएमटीपी सर्वर के माध्यम से ईमेल भेजने के लिए SmtpClient का उपयोग करता हूं। यह एसएमटीपी सर्वर एक स्व-हस्ताक्षरित प्रमाणपत्र का उपयोग करने के लिए कॉन्फ़िगर किया गया है।सर्विसपॉइंटमेनर ओवरराइड करते समय डिफ़ॉल्ट प्रमाणपत्र प्रमाणीकरण निष्पादित करें। सर्वर प्रमाण पत्र वैधता कॉलबैक

चूंकि यह मेरे क्लाइंट मशीनों पर प्रमाण पत्र स्थापित करने के लिए मेरे दायरे से बाहर है, इसलिए मैंने अपने स्वयं हस्ताक्षरित प्रमाणपत्र के लिए कस्टम सत्यापन लागू करने के लिए ServicePointManager.ServerCertificateValidationCallback जोड़ा।

हालांकि, मैं कस्टम सत्यापन केवल तब निष्पादित करना चाहता हूं जब मैं SmtpClient का उपयोग कर रहा हूं, और जब प्रमाणपत्र प्रमाणीकरण कहीं और किया जाता है तो डिफ़ॉल्ट व्यवहार पर वापस लौटना होगा।

चूंकि कॉलबैक एक स्थिर संपत्ति है, इसलिए मुझे यह भी सुनिश्चित करना चाहिए कि ईमेल भेजने के लिए मैं किसी अन्य थ्रेड द्वारा कॉलबैक नहीं कहता।

Private Shared _defaultServerCertificateValidationCallback As System.Net.Security.RemoteCertificateValidationCallback 
Private Shared _overrideSmtpCertificateValidation As Boolean = False 
Private Shared _callbackLocker As New Object() 

Private Shared Function OurCertificateValidation(s As Object, certificate As Security.Cryptography.X509Certificates.X509Certificate, chain As Security.Cryptography.X509Certificates.X509Chain, sslPolicyErrors As Net.Security.SslPolicyErrors) As Boolean 

    SyncLock _callbackLocker 

     If _overrideSmtpCertificateValidation Then 
      _overrideSmtpCertificateValidation = False 
      Dim actualCertificate = Security.Cryptography.X509Certificates.X509Certificate.CreateFromCertFile("selfSignedSmtp.cert") 
      Return certificate.Equals(actualCertificate) 
     Else 
      'Should execute the default certificate validation. 
      Return _defaultServerCertificateValidationCallback(s, certificate, chain, sslPolicyErrors) 
     End If 

    End SyncLock 

End Function 

Public Sub SendMail() 
    _defaultServerCertificateValidationCallback = System.Net.ServicePointManager.ServerCertificateValidationCallback 
    System.Net.ServicePointManager.ServerCertificateValidationCallback = New System.Net.Security.RemoteCertificateValidationCallback(AddressOf OurCertificateValidation) 
    _overrideSmtpCertificateValidation = True 
    'Send mail using SMTP client here... 
End Sub 

क्या इस कोड को क्या करना चाहिए जब एक ईमेल भेज एक चर में डिफ़ॉल्ट ServerCertificateValidationCallback रखना है, झंडा कस्टम मान्यता प्रदर्शन किया जा करने के लिए, कस्टम सत्यापन करते हैं:

मैं निम्नलिखित कोड के साथ आया था SmtpClient के समान धागे पर, अन्य धागे को SyncLock का उपयोग करके कस्टम सत्यापन करने से रोकें, फिर डिफ़ॉल्ट व्यवहार पर वापस लौटें और अन्य थ्रेड को डिफ़ॉल्ट प्रमाणपत्र सत्यापन के साथ जारी रखने दें।

हालांकि, ServerCertificateValidationCallback डिफ़ॉल्ट रूप से Nothing पर सेट है, इसलिए मैं स्पष्ट रूप से डिफ़ॉल्ट सत्यापन कॉलबैक का आह्वान नहीं कर सकता।

क्या कुछ ऐसा है जो मैं Return _defaultServerCertificateValidationCallback(s, certificate, chain, sslPolicyErrors) के बजाय आमंत्रित कर सकता हूं जो आवश्यक होने पर डिफ़ॉल्ट प्रमाणपत्र सत्यापन निष्पादित करेगा?

उत्तर

6

मुझे पता चला कि डिफ़ॉल्ट प्रमाणपत्र सत्यापन ServerCertificateValidationCallback से पहले किया गया है। यदि sslPolicyErrorsNone पर सेट है, तो इसका मतलब है कि सत्यापन सफल रहा था।

Private Shared _customCertificateLocker As New Object() 
Private Shared _customCertificateThreadId As Integer 
Private Shared _customCertificatePath As String 

'Returns True if the certificate is valid according to the default certificate validation algorithm, 
'or else if the certificate is the same as the specified custom certificate. 
Private Shared Function CustomCertificateValidation(s As Object, certificate As Security.Cryptography.X509Certificates.X509Certificate, chain As Security.Cryptography.X509Certificates.X509Chain, sslPolicyErrors As Net.Security.SslPolicyErrors) As Boolean 

    If sslPolicyErrors = System.Net.Security.SslPolicyErrors.None Then 
     'The certificate is valid according to the default certificate validation algorithm 
     Return True 
    Else 

     'Validates only for the thread that called UseCustomCertificate. 
     If System.Threading.Thread.CurrentThread.ManagedThreadId = _customCertificateThreadId Then 

      If Not File.Exists(_customCertificatePath) Then 
       Throw New FileNotFoundException("Certificate not found at path : '" & _customCertificatePath & "'.") 
      End If 

      Try 
       'Validates the specified custom certificate against the server certificate. 
       Dim actualCertificate = Security.Cryptography.X509Certificates.X509Certificate.CreateFromCertFile(_customCertificatePath) 
       Return certificate.Equals(actualCertificate) 
      Catch 
       Return False 
      End Try 

     End If 

    End If 

    Return False 

End Function 

'Performs an Action that needs the custom certificate validation, on one thread at a time. 
Public Shared Sub UseCustomCertificate(customCertificatePath As String, action As Action) 

    'Used to make sure that the ServerCertificateValidationCallback stays the same during the Action, even if multiple threads call this method. 
    SyncLock _customCertificateLocker 

     _customCertificateThreadId = System.Threading.Thread.CurrentThread.ManagedThreadId 
     _customCertificatePath = customCertificatePath 
     System.Net.ServicePointManager.ServerCertificateValidationCallback = New System.Net.Security.RemoteCertificateValidationCallback(AddressOf CustomCertificateValidation) 

     Try 
      action() 

     Finally 
      _customCertificateThreadId = 0 
      _customCertificatePath = String.Empty 
      System.Net.ServicePointManager.ServerCertificateValidationCallback = Nothing 
     End Try 

    End SyncLock 

End Sub 

उपयोग के उदाहरण::

UseCustomCertificate("C:\example.cert", 
        Sub() 
         'Send email with SmtpClient... 
        End Sub) 

मैं इस जवाब को स्वीकार करेंगे ही अगर मैं एक नहीं मिलता

मैं इस कोड मेरी जरूरतों को पूरा करता है और मेरी स्थिति के लिए पर्याप्त सुरक्षित लगता है लगता है कुछ दिनों में सुरक्षित/बेहतर जवाब।

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