I am trying to add SSL to a very basic client/server application : the client sends 2 numbers, the server computes the addition and return it to the client.
I am using a valid self signed certificates, already used in Java Application, though I did not install them in the system, I dont know if it is mandatory in C#.
Here is the server code:
using System;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace SimpleHttpServerSSL
{
class Program
{
static async Task Main(string[] args)
{
string serverCertPath = "C:\\server\\server_key.p12";
string serverCertPassword = "myPassword";
const string url = "https://localhost:8080/add";
var server = new HttpListener();
server.Prefixes.Add(url + "/");
server.Start();
Console.WriteLine("Server is listening at " + url);
while (true)
{
HttpListenerContext context = await server.GetContextAsync();
HandleClientRequest(context, serverCertPath, serverCertPassword);
}
}
private static void Log(string message)
{
Console.WriteLine("Log: " + message);
}
private static void HandleClientRequest(HttpListenerContext context, string serverCertPath, string serverCertPassword)
{
try
{
if (context.Request.HttpMethod == "POST")
{
var data = new
{
A = 0,
B = 0
};
using (var reader = new StreamReader(context.Request.InputStream))
{
string requestBody = reader.ReadToEnd();
data = JsonConvert.DeserializeAnonymousType(requestBody, data);
}
var result = data.A + data.B;
var responseObj = new
{
R = result
};
string responseJson = JsonConvert.SerializeObject(responseObj);
byte[] buffer = Encoding.UTF8.GetBytes(responseJson);
context.Response.ContentLength64 = buffer.Length;
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
context.Response.OutputStream.Close();
Console.WriteLine($"Received request: A = {data.A}, B = {data.B}, Result = {result}");
}
else
{
context.Response.StatusCode = (int)HttpStatusCode.MethodNotAllowed;
}
context.Response.Close();
}
catch (Exception ex)
{
Console.WriteLine("Exception happend: " + ex.ToString());
}
}
}
}
And here is the client code:
using System;
using System.Globalization;
using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace SimpleHttpClient
{
class Program
{
static void LogException(Exception error)
{
Console.WriteLine("Exception: " + error.GetBaseException().ToString());
}
static async Task Main(string[] args)
{
try
{
Console.WriteLine("Enter value for A:");
int a = int.Parse(Console.ReadLine());
Console.WriteLine("Enter value for B:");
int b = int.Parse(Console.ReadLine());
var data = new
{
A = a,
B = b
};
string jsonData = JsonConvert.SerializeObject(data);
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
string clientCertPath = "C:\\client\\client.pfx";
string clientCertPassword = "myPassword";
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(new X509Certificate2(clientCertPath, clientCertPassword));
handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
using (var httpClient = new HttpClient(handler))
{
const string serverUrl = "https://localhost:8080/add";
var response = await httpClient.PostAsync(serverUrl, content);
if (response.IsSuccessStatusCode)
{
string responseBody = await response.Content.ReadAsStringAsync();
var resultObj = JsonConvert.DeserializeAnonymousType(responseBody, new { R = 0 });
Console.WriteLine("Result: " + resultObj.R);
}
else
{
Console.WriteLine("Error: " + response.StatusCode);
}
}
}
catch (Exception ex)
{
LogException(ex);
}
}
}
}
I have a SocketException, connection closed by distant host:
Exception: System.Net.Sockets.SocketException (10054): Une connexion existante a dû être fermée par l'hôte distant.
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.CreateException(SocketError error, Boolean forAsyncThrow)
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ReceiveAsync(Socket socket, CancellationToken cancellationToken)
at System.Net.Sockets.Socket.ReceiveAsync(Memory`1 buffer, SocketFlags socketFlags, Boolean fromNetworkStream, CancellationToken cancellationToken)
at System.Net.Sockets.NetworkStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)
at System.Net.Security.SslStream.FillHandshakeBufferAsync[TIOAdapter](TIOAdapter adapter, Int32 minSize)
How can I fix the code / debug if anything is wrong during handshake without using Wireshark (too many restictions by our IT, it may not work properly) ?