Как я могу установить безопасный канал для SSL / TLS с портативного устройства?

Я пытаюсь вызвать метод REST с портативного устройства (Windows CE / Compact Framework) с этим кодом:

public static HttpWebRequest SendHTTPRequestNoCredentials(string uri, HttpMethods method, string data, string contentType)
{
    ExceptionLoggingService.Instance.WriteLog("Reached 
fileXferREST.SendHTTPRequestNoCredentials");
    WebRequest request = null;
    try
    {
        request = WebRequest.Create(uri);
        request.Method = Enum.ToObject(typeof(HttpMethods), method).ToString();
        request.ContentType = contentType;
        ((HttpWebRequest)request).Accept = contentType;
        ((HttpWebRequest)request).KeepAlive = false;
        ((HttpWebRequest)request).ProtocolVersion = HttpVersion.Version10;

        if (method != HttpMethods.GET && method != HttpMethods.DELETE)
        {
            byte[] arrData = Encoding.UTF8.GetBytes(data);
            request.ContentLength = arrData.Length;
            using (Stream oS = request.GetRequestStream())
            {
                oS.Write(arrData, 0, arrData.Length);
            }
        }
        else
        {
            request.ContentLength = 0;
        }
    }
    catch (Exception ex)
    {
        String msgInnerExAndStackTrace = String.Format(
                "{0}; Inner Ex: {1}; Stack Trace: {2}", ex.Message, ex.InnerException, 
ex.StackTrace);
        ExceptionLoggingService.Instance.WriteLog(String.Format("From 
FileXferREST.SendHTTPRequestNoCredentials(): {0}", msgInnerExAndStackTrace));
    }
    return request as HttpWebRequest;
}

Значения, передаваемые методу:

uri: "https://seastore.nrbq.ad/ggr.web/api/inventory/sendXML/duckbill/platypus/INV_3_20090313214959000.xml"
HttpMethods: HttpMethods.POST
data: [ some xml ]
contentType: "application/xml"

... но я не могу установить соединение, потому что "Не удалось установить безопасный канал для SSL / TLS ... System.Net.Sockets.SocketException: существующее соединение было принудительно закрыто удаленным хостом"

Итак, что я должен сделать, чтобы установить безопасный канал для SSL / TLS, чтобы существующее соединение не было так грубо закрыто эмоционально удаленным хостом?

Nebenbei bemerkt: я нахожу это немного странным, что когда я ловил WebException, этот код вызывал сбой приложения, но когда я изменил блок catch на общее исключение, попытка подключиться без вывода сообщений не удалась (единственный способ, которым я мог сказать, что проблема была, посмотрев на файл журнала).

Чтобы быть более конкретным, с помощью кода WebException в HttpWebRequest в блоке catch SendHTTPRequestNoCredentials (), например так:

catch (WebException webex)
{
    HttpWebResponse hwr = (HttpWebResponse)webex.Response;
    HttpStatusCode hsc = hwr.StatusCode;
    String webExMsgAndStatusCode = String.Format("{0} Status code == {1}", webex.Message, 
hsc.ToString());
    ExceptionLoggingService.Instance.WriteLog(String.Format("From 
FileXferREST.SendHTTPRequestNoCredentials: {0}", webExMsgAndStatusCode));
}

... приложение упало, и файл журнала содержал следующие записи (страшные NRE!):

Date: 3/13/2009 11:40:15 PM
Message: Reached FileXferREST.SendHTTPRequestNoCredentials

Date: 3/13/2009 11:40:31 PM
Message: From frmMain.SendInventories: NullReferenceException; Inner Ex: ; Stack Trace:    at 
HHS.FileXferREST.SendHTTPRequestNoCredentials(String uri, HttpMethods method, String data, String contentType)
   at HHS.FileXferREST.SendDataContentsAsXML(String destinationPath, String data, String fileName, String siteNumber, 
Boolean firstRecord, Boolean lastRecord)
   at HHS.frmMain.SendInventories()
   at HHS.frmMain.menuItemSEND_Inventories_Click(Object sender, EventArgs e)
    . . .

Тем не менее, благодаря универсальному коду исключения в блоке catch (как показано в верхней части этого поста) приложение, казалось, прогуливалось по парку в солнечное летнее воскресное утро - никаких сообщений об исключениях, сбоях или признаках какого-либо зимнего недовольства что бы то ни было - но файл журнала показывает это:

Date: 3/13/2009 11:54:52 PM
Message: Reached FileXferREST.SendHTTPRequestNoCredentials

Date: 3/13/2009 11:54:54 PM
Message: From FileXferREST.SendHTTPRequestNoCredentials(): Could not establish secure channel for SSL/TLS; Inner Ex: 
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.ReceiveNoCheck(Byte[] buffer, Int32 index, Int32 request, SocketFlags socketFlags)
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Connection.System.Net.ISslDataTransport.Receive(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.SslConnectionState.ClientSideHandshake()
   at System.Net.SslConnectionState.PerformClientHandShake()
   at System.Net.Connection.connect(Object ignored)
   at System.Threading.ThreadPool.WorkItem.doWork(Object o)
   at System.Threading.Timer.ring()
; Stack Trace:    at System.Net.HttpWebRequest.finishGetRequestStream()
   at System.Net.HttpWebRequest.GetRequestStream()
   at HHS.FileXferREST.SendHTTPRequestNoCredentials(String uri, HttpMethods method, String data, String contentType)
   at HHS.FileXferREST.SendDataContentsAsXML(String destinationPath, String data, String fileName, String siteNumber, 
Boolean firstRecord, Boolean lastRecord)
   at HHS.frmMain.SendInventories()
   at HHS.frmMain.menuItemSEND_Inventories_Click(Object sender, EventArgs e)
    . . .

Несмотря на этот последний интересный момент, что действительно важно: как я могу установить безопасный канал для SSL / TLS с портативного устройства?

ОБНОВИТЬ

Я вызвал код из приложения «песочница», запущенного на моем ПК, и получил похожее, хотя и не идентичное, исключение. Это то, что он поймал:

Message: From SendHTTPRequestNoCredentials(): The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.; Inner Ex: System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
   at System.Net.Security.SslState.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, Exception exception)
   at System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)
. . .
ОБНОВЛЕНИЕ 2

Основываясь на некоторых комментариях здесь и ссылках, которые их сопровождают, я подумал, что мне нужно добавить это в мой код:

        ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

... в каком-то контексте:

    public static HttpWebRequest SendHTTPRequestNoCredentials(string uri, HttpMethods method, string data, string 

contentType) {ServicePointManager.ServerCertificateValidationCallback + = (отправитель, сертификат, цепочка, sslPolicyErrors) => true; Запрос WebRequest = null; try {request = WebRequest.Create (uri);

... но, хотя это клиентское приложение .NET 3.5, и, согласно этому [http://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.servercertificatevalidationcallback

(v = vs.90) .aspx], ServerCertificateValidationCallback предположительно доступен в версии 3.5, «ServerCertificateValidationCallback» мне недоступен (я получаю «не могу разрешить символ»). Похоже, что это в сборке System.Net, но попытки добавить ссылку на System.Net в мой проект тщетны, так как на вкладке .NET такая сборка недоступна через «Добавить ссылки». Упорядоченный по алфавиту список переходит от «System.Messaging» к «System.Net.Irda»

Я считаю, что этот недостаток объясняется тем, что это компактный проект с недостаточной функциональностью.

Предполагая, что это так (Compact Framework не содержит ServerCertificateValidationCallback), какой обходной путь для этого сценария? Как я могу заставить мое клиентское портативное приложение принимать самоподписанный ssl-сертификат на сервере (REST-приложение, работающее в локальной сети)?

ОБНОВЛЕНИЕ 3

Должен ли я установить / отметить один или оба из следующих пунктов в Панели управления> Программы> Включить или выключить функции Windows> Службы IIS> Служба всемирной паутины> Безопасность:

Client Certificate Mapping Authentication
IIS Client Certificate Mapping Authentication

?

ОБНОВЛЕНИЕ 4

Я могу получить доступ к ServicePoint, вот так:

ServicePoint svcPoint = ServicePointManager.FindServicePoint(uri);

... но приносит ли это мне пользу? Могу ли я установить сертификат на что-то, что будет равнозначно его постоянному принятию. IOW, что мне нужно здесь:

ServicePoint svcPoint = ServicePointManager.FindServicePoint(uri);
svcPoint.Certificate = ???
ОБНОВЛЕНИЕ 5

Даже с этим кодом:

namespace HHS
{
    using System.Net;
    using System.Security.Cryptography.X509Certificates;

    class TrustAllCertificatesPolicy : ICertificatePolicy
    {
        public TrustAllCertificatesPolicy()
        {
        }

        public bool CheckValidationResult(ServicePoint sp, X509Certificate cert, WebRequest req, int problem)
        {
            return true;
        }
    }
}

private void frmMain_Load(object sender, EventArgs e)
{
    System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatesPolicy();
}

... я все еще получаю это:

Message: Reached FileXferREST.SendHTTPRequestNoCredentials

Date: 3/18/2009 11:41:09 PM
Message: From FileXferREST.SendHTTPRequestNoCredentials(): Could not establish secure channel for SSL/TLS; Inner Ex: System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
   at System.Net.Sockets.Socket.ReceiveNoCheck(Byte[] buffer, Int32 index, Int32 request, SocketFlags socketFlags)
   at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
   at System.Net.Connection.System.Net.ISslDataTransport.Receive(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.SslConnectionState.ClientSideHandshake()
   at System.Net.SslConnectionState.PerformClientHandShake()
   at System.Net.Connection.connect(Object ignored)
   at System.Threading.ThreadPool.WorkItem.doWork(Object o)
   at System.Threading.Timer.ring()
; Stack Trace:    at System.Net.HttpWebRequest.finishGetRequestStream()
   at System.Net.HttpWebRequest.GetRequestStream()
   at HHS.FileXferREST.SendHTTPRequestNoCredentials(String uri, HttpMethods method, String data, String contentType)
. . .

Кстати, конструктор TrustAllCertificatesPolicy (пустой), вероятно, является спорным, поскольку он выделен серым цветом.

Ответы на вопрос(2)

Ваш ответ на вопрос