1

I am developing a proxy server application similar to CCProxy. Its working fine for HTTP but not HTTPS. Its throwing exception when AuthenticateAsServer() method is called on SslStream object. I also don't know whether I have supplied proper certificate, I don't know how to create a certificate. I just provided the certificate which came with the code that I downloaded online. Here is the code:

 private static void DoHttpProcessing(TcpClient client)
    {
        Stream clientStream = client.GetStream();
        Stream outStream = clientStream; 
        SslStream sslStream = null;
        StreamReader clientStreamReader = new StreamReader(clientStream);
        CacheEntry cacheEntry = null;
        MemoryStream cacheStream = null;

        if (Server.DumpHeaders || Server.DumpPostData || Server.DumpResponseData)
        {
            Monitor.TryEnter(_outputLockObj, TimeSpan.FromMilliseconds(-1.0));
        }

        try
        {
            //read the first line HTTP command
            String httpCmd = clientStreamReader.ReadLine();
            if (String.IsNullOrEmpty(httpCmd))
            {
                clientStreamReader.Close();
                clientStream.Close();
                return;
            }
            //break up the line into three components
            String[] splitBuffer = httpCmd.Split(spaceSplit, 3);

            String method = splitBuffer[0];
            String remoteUri = splitBuffer[1];
            Version version = new Version(1, 0);

            HttpWebRequest webReq;
            HttpWebResponse response = null;
            if (splitBuffer[0].ToUpper() == "CONNECT")
            {

                remoteUri = "https://" + splitBuffer[1];
                while (!String.IsNullOrEmpty(clientStreamReader.ReadLine())) ;
                StreamWriter connectStreamWriter = new StreamWriter(clientStream);
                connectStreamWriter.WriteLine("HTTP/1.0 200 Connection established");
                connectStreamWriter.WriteLine(String.Format("Timestamp: {0}", DateTime.Now.ToString()));
                connectStreamWriter.WriteLine("Proxy-agent: matt-dot-net");
                connectStreamWriter.WriteLine();
                connectStreamWriter.Flush();

                sslStream = new SslStream(clientStream, false);

                try
                {
             // HERE I RECEIVE EXCEPTION
                    sslStream.AuthenticateAsServer(_certificate, false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, true);


                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    sslStream.Close();
                    clientStreamReader.Close();
                    connectStreamWriter.Close();
                    clientStream.Close();
                    return;
                }//further code goes here...

Also, instead of sslStream.AuthenticateAsServer, if I use ssStream.AuthenticateAsClient method I get AuthenticationException with message "A call to SSPI failed, see inner exception." and InnerException gives message as "The message received was unexpected or badly formatted"

When I am using sslstream.AuthenticateAsServer() method, I need to create certificate for each new HTTPS host and pass it with this method. If I provide the self signed certificate, the request succeeds. But problem is, for how many new HTTPS requests will I keep creating certificates manually and assign it to AuthenticateAsServer()?

Aditya Bokade
  • 1,708
  • 1
  • 28
  • 45

1 Answers1

0

For the serverside certificate, most certificates correspond to a FQDN (so server1.localhost.local), although there can be wildcard certs (*.localhost.local). When you use AuthenticateAsClient method, that could be one of two things, 1) The Certificate doesnt have the Extended Key Usage for Client Authentication or 2) you didnt pass the right password for it to read the cert/private key. To get past both these hurdles rather quickly i would suggest creating an OpenSSL CA and then generating a CA and Server Cert. There is tons of documentation on how to do this and should take 30 minutes tops for someone who has never created one before....(Also i would suggest exporting the cert into pkcs12 extension for the CA to be chained in with the Server Cert).

jladd
  • 328
  • 1
  • 3
  • 10
  • Thanks for answer Jladd. I believe that AuthenticateAsServer is the right method to use. Because my proxy application is acting as server for clients. When I used it it works partially.Partially Because, client browser gives wrong certificate warning, as it expects certificate to be of same URL.Is there any way to download and forward the Same certificate that is coming from server? Or, will you please demonstrate the code to solve this issue? – Aditya Bokade Mar 07 '13 at 04:16
  • You can download the certificate in your browser and add an exception in there saying always accept this certificate for this URL. But you wont be able to do that in the code. Now if you also wanted an easier way than that, you could go into your host file and add a line in there that uses the URL of the cert that points towards your IP of the proxy service and poof, it will think that the domain actually points there(Note: that should just be during the testing phase.) Also i re looked over your code and you will want to get rid of SslProtocols.Ssl2 as SSL V2 is very insecure and out dated – jladd Mar 07 '13 at 15:36
  • Adding an exception in the browser is not proper solution. Because client will keep requesting new URLs each time and its not possible for client to add exception every time. Sorry jlAdd, I feel that remaining part of your comment has real solution but I am yet unable to understand what to do as action. Can you please provide me some tutorial or send me the code? Thanks for reply. – Aditya Bokade Mar 09 '13 at 05:22