Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSharp Wrapper SNI Support #7610

Merged
merged 15 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 23 additions & 20 deletions src/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -20156,16 +20156,9 @@ VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx)
return NULL;
}


#ifdef HAVE_SNI

void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback");
if (ctx)
ctx->sniRecvCb = cb;
}

/* this is a compatibily function, consider using
* wolfSSL_CTX_set_servername_callback */
int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx,
CallbackSniRecv cb)
{
Expand All @@ -20177,19 +20170,8 @@ int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx,
return WOLFSSL_FAILURE;
}

int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg");
if (ctx) {
ctx->sniRecvCbArg = arg;
return WOLFSSL_SUCCESS;
}
return WOLFSSL_FAILURE;
}

#endif /* HAVE_SNI */


#ifndef NO_BIO
void wolfSSL_ERR_load_BIO_strings(void) {
WOLFSSL_ENTER("wolfSSL_ERR_load_BIO_strings");
Expand Down Expand Up @@ -20224,6 +20206,27 @@ void wolfSSL_THREADID_set_numeric(void* id, unsigned long val)
* HAVE_LIGHTY || WOLFSSL_HAPROXY || WOLFSSL_OPENSSH ||
* HAVE_SBLIM_SFCB)) */

#ifdef HAVE_SNI
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: Moved these outside of the strict compatibility layer macros and made accessible to match the WOLFSSL_CTX member of HAVE_SNI only.


void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback");
if (ctx)
ctx->sniRecvCb = cb;
}


int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg)
{
WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg");
if (ctx) {
ctx->sniRecvCbArg = arg;
return WOLFSSL_SUCCESS;
}
return WOLFSSL_FAILURE;
}

#endif /* HAVE_SNI */

#if defined(OPENSSL_EXTRA)

Expand Down
12 changes: 7 additions & 5 deletions wolfssl/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3811,7 +3811,6 @@ WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl);
/* SNI types */
enum {
WOLFSSL_SNI_HOST_NAME = 0,
WOLFSSL_SNI_HOST_NAME_OUTER = 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: This was an artifact from an early ECH that was later changed and this was left behind and should be removed.

};

WOLFSSL_ABI WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL* ssl, unsigned char type,
Expand Down Expand Up @@ -4873,14 +4872,17 @@ typedef int (*CallbackSniRecv)(WOLFSSL *ssl, int *ret, void* exArg);

WOLFSSL_API void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx,
CallbackSniRecv cb);
WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx,
CallbackSniRecv cb);

WOLFSSL_API int wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg);
#endif

#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) \
|| defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY)
#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \
defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY)

#ifdef HAVE_SNI
WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx,
CallbackSniRecv cb);
#endif

WOLFSSL_API void wolfSSL_ERR_remove_thread_state(void* pid);

Expand Down
58 changes: 44 additions & 14 deletions wrapper/CSharp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,17 @@ A Visual Studio solution `wolfSSL_CSharp.sln` is provided. This will allow you
to build the wrapper library and examples. It includes the wolfSSL Visual Studio
project directly.

## Linux (using Mono)
## Linux (Ubuntu) using mono

Prerequisites for linux:

```
apt install mono-tools-devel
apt-get update
apt-get upgrade
apt-get install mono-complete
```

Build wolfSSL and install:
### Build wolfSSL and install

```
./autogen.sh
Expand All @@ -38,24 +40,52 @@ make check
sudo make install
```

Build and run the wrapper:
### Build and run the wrapper

From the wolfssl root directory:

```
cd wrapper/CSharp
```

Compile server:

csc wolfSSL_CSharp/wolfSSL.cs wolfSSL_CSharp/X509.cs \
wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs
```
mcs wolfSSL_CSharp/wolfSSL.cs wolfSSL_CSharp/X509.cs \
wolfSSL-TLS-Server/wolfSSL-TLS-Server.cs -OUT:server.exe
```

Run the example:
Compile client:

```
cp wolfSSL-TLS-Server.exe ../../certs
cd ../../certs
mcs wolfSSL_CSharp/wolfSSL.cs wolfSSL_CSharp/X509.cs \
wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs -OUT:client.exe
```

### Run the example

In one terminal instance run the server:

```
mono server.exe
```

mono wolfSSL-TLS-Server.exe
And in another terminal instance run the client:

Calling ctx Init from wolfSSL
Finished init of ctx .... now load in cert and key
Ciphers : TLS13-AES128-GCM-SHA256:TLS13-AES256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305-OLD:ECDHE-ECDSA-CHACHA20-POLY1305-OLD:DHE-RSA-CHACHA20-POLY1305-OLD
Started TCP and waiting for a connection
```
mono client.exe
```

### Enabling SNI

To enable SNI, just pass the `-S` argument with the specified hostname to the client:

```
mono client.exe -S hostname
```

And run the server with the `-S` flag:

```
mono server.exe -S
```
17 changes: 14 additions & 3 deletions wrapper/CSharp/wolfSSL-DTLS-PSK-Server/wolfSSL-DTLS-PSK-Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,14 @@ public static void Main(string[] args)
IntPtr ssl;

/* These paths should be changed according to use */
string fileCert = @"server-cert.pem";
string fileKey = @"server-key.pem";
StringBuilder dhparam = new StringBuilder("dh2048.pem");
string fileCert = wolfssl.setPath("server-cert.pem");
string fileKey = wolfssl.setPath("server-key.pem");
StringBuilder dhparam = new StringBuilder(wolfssl.setPath("dh2048.pem"));

if (fileCert == "" || fileKey == "" || dhparam.Length == 0) {
Console.WriteLine("Platform not supported");
return;
}

wolfssl.psk_delegate psk_cb = new wolfssl.psk_delegate(my_psk_server_cb);

Expand All @@ -106,6 +111,12 @@ public static void Main(string[] args)
return;
}

if (!File.Exists(dhparam.ToString())) {
Console.WriteLine("Could not find dh file");
wolfssl.CTX_free(ctx);
return;
}


if (wolfssl.CTX_use_certificate_file(ctx, fileCert, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS)
{
Expand Down
17 changes: 14 additions & 3 deletions wrapper/CSharp/wolfSSL-DTLS-Server/wolfSSL-DTLS-Server.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,14 @@ public static void Main(string[] args)
IntPtr ssl;

/* These paths should be changed for use */
string fileCert = @"server-cert.pem";
string fileKey = @"server-key.pem";
StringBuilder dhparam = new StringBuilder("dh2048.pem");
string fileCert = wolfssl.setPath("server-cert.pem");
string fileKey = wolfssl.setPath(@"server-key.pem");
StringBuilder dhparam = new StringBuilder(wolfssl.setPath("dh2048.pem"));

if (fileCert == "" || fileKey == "" || dhparam.Length == 0) {
Console.WriteLine("Platform not supported");
return;
}

StringBuilder buff = new StringBuilder(1024);
StringBuilder reply = new StringBuilder("Hello, this is the wolfSSL C# wrapper");
Expand All @@ -87,6 +92,12 @@ public static void Main(string[] args)
return;
}

if (!File.Exists(dhparam.ToString())) {
Console.WriteLine("Could not find dh file");
wolfssl.CTX_free(ctx);
return;
}


if (wolfssl.CTX_use_certificate_file(ctx, fileCert, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,17 @@ static void Main(string[] args)
IntPtr ssl;
Socket fd;

wolfssl.psk_delegate psk_cb = new wolfssl.psk_delegate(my_psk_server_cb);
wolfssl.CallbackVerify_delegate verify_cb = new wolfssl.CallbackVerify_delegate(my_verify_cb);

/* These paths should be changed according to use */
string fileCert = @"server-cert.pem";
string fileKey = @"server-key.pem";
string fileCert = wolfssl.setPath("server-cert.pem");
string fileKey = wolfssl.setPath("server-key.pem");
StringBuilder dhparam = new StringBuilder(wolfssl.setPath("dh2048.pem"));

if (fileCert == "" || fileKey == "" || dhparam.Length == 0) {
Console.WriteLine("Platform not supported");
return;
}

StringBuilder buff = new StringBuilder(1024);
StringBuilder reply = new StringBuilder("Hello, this is the wolfSSL C# wrapper");
Expand All @@ -242,6 +247,12 @@ static void Main(string[] args)
return;
}

if (!File.Exists(dhparam.ToString())) {
Console.WriteLine("Could not find dh file");
wolfssl.CTX_free(ctx);
return;
}

if (wolfssl.CTX_use_certificate_file(ctx, fileCert, wolfssl.SSL_FILETYPE_PEM) != wolfssl.SUCCESS)
{
Console.WriteLine("Error in setting cert file");
Expand Down
53 changes: 49 additions & 4 deletions wrapper/CSharp/wolfSSL-TLS-Client/wolfSSL-TLS-Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/


using System;
using System.Runtime.InteropServices;
using System.Text;
Expand Down Expand Up @@ -60,15 +59,39 @@ private static int myVerify(int preverify, IntPtr x509_ctx)
return preverify;
}

/// <summary>
/// Checks if the SNI option was enabled via command line.
/// Must be enabled with ./configure --enable-sni when configuring
/// wolfSSL.
/// <param name="args">Parameters passed via command line</param>
/// </summary>
private static int haveSNI(string[] args)
{
for (int i = 0; i < args.Length; i++) {
if (args[i] == "-S") {
Console.WriteLine("SNI IS ON");
return i+1;
}
}
Console.WriteLine("SNI IS OFF");
return -1;
}

public static void Main(string[] args)
{
IntPtr ctx;
IntPtr ssl;
Socket tcp;
IntPtr sniHostName;

/* These paths should be changed for use */
string caCert = @"ca-cert.pem";
StringBuilder dhparam = new StringBuilder("dh2048.pem");
string caCert = wolfssl.setPath("ca-cert.pem");
StringBuilder dhparam = new StringBuilder(wolfssl.setPath("dh2048.pem"));

if (caCert == "" || dhparam.Length == 0) {
Console.WriteLine("Platform not supported.");
return;
}

StringBuilder buff = new StringBuilder(1024);
StringBuilder reply = new StringBuilder("Hello, this is the wolfSSL C# wrapper");
Expand All @@ -78,7 +101,6 @@ public static void Main(string[] args)

wolfssl.Init();


Console.WriteLine("Calling ctx Init from wolfSSL");
ctx = wolfssl.CTX_new(wolfssl.usev23_client());
if (ctx == IntPtr.Zero)
Expand All @@ -96,11 +118,34 @@ public static void Main(string[] args)
return;
}

if (!File.Exists(dhparam.ToString())) {
Console.WriteLine("Could not find dh file");
wolfssl.CTX_free(ctx);
return;
}

if (wolfssl.CTX_load_verify_locations(ctx, caCert, null)
!= wolfssl.SUCCESS)
{
Console.WriteLine("Error loading CA cert");
wolfssl.CTX_free(ctx);
return;
}

int sniArg = haveSNI(args);
if (sniArg >= 0)
{
string sniHostNameString = args[sniArg].Trim();
sniHostName = Marshal.StringToHGlobalAnsi(sniHostNameString);

ushort size = (ushort)sniHostNameString.Length;

if (wolfssl.CTX_UseSNI(ctx, (byte)wolfssl.WOLFSSL_SNI_HOST_NAME, sniHostName, size) != wolfssl.SUCCESS)
{
Console.WriteLine("UseSNI failed");
wolfssl.CTX_free(ctx);
return;
}
}

StringBuilder ciphers = new StringBuilder(new String(' ', 4096));
Expand Down
12 changes: 11 additions & 1 deletion wrapper/CSharp/wolfSSL-TLS-PSK-Client/wolfSSL-TLS-PSK-Client.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ public static void Main(string[] args)

wolfssl.psk_client_delegate psk_cb = new wolfssl.psk_client_delegate(my_psk_client_cb);

StringBuilder dhparam = new StringBuilder("dh2048.pem");
StringBuilder dhparam = new StringBuilder(wolfssl.setPath("dh2048.pem"));
if (dhparam.Length == 0) {
Console.WriteLine("Platform not supported");
return;
}

StringBuilder buff = new StringBuilder(1024);
StringBuilder reply = new StringBuilder("Hello, this is the wolfSSL C# client psk wrapper");
Expand Down Expand Up @@ -157,6 +161,12 @@ public static void Main(string[] args)
return;
}

if (!File.Exists(dhparam.ToString())) {
Console.WriteLine("Could not find dh file");
wolfssl.CTX_free(ctx);
return;
}

wolfssl.SetTmpDH_file(ssl, dhparam, wolfssl.SSL_FILETYPE_PEM);

if (wolfssl.connect(ssl) != wolfssl.SUCCESS)
Expand Down
Loading