mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2025-07-06 07:44:57 +03:00
OpenVPN client certificate authentication (Individual Certificate Authentication) (#327)
* Implement OpenVPN certificate authentication, fixes #55 * fixup! Implement OpenVPN certificate authentication, fixes #55
This commit is contained in:
committed by
Moataz Elmasry
parent
863f87fac1
commit
83295bb736
@ -151,6 +151,8 @@
|
||||
|
||||
LOCK *openssl_lock = NULL;
|
||||
|
||||
int ssl_clientcert_index = 0;
|
||||
|
||||
LOCK **ssl_lock_obj = NULL;
|
||||
UINT ssl_lock_num;
|
||||
static bool openssl_inited = false;
|
||||
@ -4064,6 +4066,8 @@ void InitCryptLibrary()
|
||||
ERR_load_crypto_strings();
|
||||
SSL_load_error_strings();
|
||||
|
||||
ssl_clientcert_index = SSL_get_ex_new_index(0, "struct SslClientCertInfo *", NULL, NULL, NULL);
|
||||
|
||||
#ifdef OS_UNIX
|
||||
{
|
||||
char *name1 = "/dev/random";
|
||||
@ -5289,5 +5293,9 @@ static unsigned char *Internal_SHA0(const unsigned char *d, size_t n, unsigned c
|
||||
}
|
||||
|
||||
|
||||
int GetSslClientCertIndex()
|
||||
{
|
||||
return ssl_clientcert_index;
|
||||
}
|
||||
|
||||
|
||||
|
@ -581,6 +581,8 @@ BUF *EasyDecrypt(BUF *src_buf);
|
||||
|
||||
void DisableIntelAesAccel();
|
||||
|
||||
int GetSslClientCertIndex();
|
||||
|
||||
#ifdef ENCRYPT_C
|
||||
// Inner function
|
||||
|
||||
|
@ -5809,14 +5809,52 @@ SOCK *ListenAnyPortEx2(bool local_only, bool disable_ca)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cb_test(int a, X509_STORE_CTX *ctx)
|
||||
// Verify client SSL certificate during TLS handshake.
|
||||
//
|
||||
// (actually, only save the certificate for later authentication in Protocol.c)
|
||||
int SslCertVerifyCallback(int preverify_ok, X509_STORE_CTX *ctx)
|
||||
{
|
||||
WHERE;
|
||||
return 1;
|
||||
SSL *ssl;
|
||||
struct SslClientCertInfo *clientcert;
|
||||
|
||||
ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||
clientcert = SSL_get_ex_data(ssl, GetSslClientCertIndex());
|
||||
|
||||
if (clientcert != NULL)
|
||||
{
|
||||
clientcert->PreverifyErr = 0;
|
||||
clientcert->PreverifyErrMessage[0] = '\0';
|
||||
if (!preverify_ok)
|
||||
{
|
||||
clientcert->PreverifyErr = X509_STORE_CTX_get_error(ctx);
|
||||
const char *msg = X509_verify_cert_error_string(clientcert->PreverifyErr);
|
||||
StrCpy(clientcert->PreverifyErrMessage, PREVERIFY_ERR_MESSAGE_SIZE, msg);
|
||||
Debug("SslCertVerifyCallback preverify error: '%s'\n", msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctx->cert != NULL)
|
||||
{
|
||||
X *tmpX = X509ToX(ctx->cert); // this only wraps ctx->cert, but we need to make a copy
|
||||
X *copyX = CloneX(tmpX);
|
||||
tmpX->do_not_free = true; // do not release inner X509 object
|
||||
FreeX(tmpX);
|
||||
clientcert->X = copyX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1; /* allow the verification process to continue */
|
||||
}
|
||||
|
||||
// Create a new SSL pipe
|
||||
SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh)
|
||||
{
|
||||
return NewSslPipeEx(server_mode, x, k, dh, false, NULL);
|
||||
}
|
||||
|
||||
// Create a new SSL pipe with extended options
|
||||
SSL_PIPE *NewSslPipeEx(bool server_mode, X *x, K *k, DH_CTX *dh, bool verify_peer, struct SslClientCertInfo *clientcert)
|
||||
{
|
||||
SSL_PIPE *s;
|
||||
SSL *ssl;
|
||||
@ -5841,7 +5879,10 @@ SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh)
|
||||
SSL_CTX_set_ssl_version(ssl_ctx, SSLv23_client_method());
|
||||
}
|
||||
|
||||
//SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, cb_test);
|
||||
if (verify_peer)
|
||||
{
|
||||
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, SslCertVerifyCallback);
|
||||
}
|
||||
|
||||
if (dh != NULL)
|
||||
{
|
||||
@ -5854,6 +5895,8 @@ SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh)
|
||||
}
|
||||
|
||||
ssl = SSL_new(ssl_ctx);
|
||||
|
||||
SSL_set_ex_data(ssl, GetSslClientCertIndex(), clientcert);
|
||||
}
|
||||
Unlock(openssl_lock);
|
||||
|
||||
|
@ -1615,7 +1615,16 @@ void Win32WaitForTubes(TUBE **tubes, UINT num, UINT timeout);
|
||||
void UnixWaitForTubes(TUBE **tubes, UINT num, UINT timeout);
|
||||
#endif // OS_WIN32
|
||||
|
||||
#define PREVERIFY_ERR_MESSAGE_SIZE 100
|
||||
// Info on client certificate collected during TLS handshake
|
||||
struct SslClientCertInfo {
|
||||
int PreverifyErr;
|
||||
char PreverifyErrMessage[PREVERIFY_ERR_MESSAGE_SIZE];
|
||||
X *X;
|
||||
};
|
||||
|
||||
SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh);
|
||||
SSL_PIPE *NewSslPipeEx(bool server_mode, X *x, K *k, DH_CTX *dh, bool verify_peer, struct SslClientCertInfo *clientcert);
|
||||
void FreeSslPipe(SSL_PIPE *s);
|
||||
bool SyncSslPipe(SSL_PIPE *s);
|
||||
|
||||
|
Reference in New Issue
Block a user