mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-23 01:49:53 +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:
parent
863f87fac1
commit
83295bb736
@ -448,6 +448,7 @@
|
|||||||
#define AUTHTYPE_ROOTCERT 3 // Root certificate which is issued by trusted Certificate Authority
|
#define AUTHTYPE_ROOTCERT 3 // Root certificate which is issued by trusted Certificate Authority
|
||||||
#define AUTHTYPE_RADIUS 4 // Radius authentication
|
#define AUTHTYPE_RADIUS 4 // Radius authentication
|
||||||
#define AUTHTYPE_NT 5 // Windows NT authentication
|
#define AUTHTYPE_NT 5 // Windows NT authentication
|
||||||
|
#define AUTHTYPE_OPENVPN_CERT 98 // TLS client certificate authentication
|
||||||
#define AUTHTYPE_TICKET 99 // Ticket authentication
|
#define AUTHTYPE_TICKET 99 // Ticket authentication
|
||||||
|
|
||||||
// Constant of the client side
|
// Constant of the client side
|
||||||
|
@ -170,7 +170,7 @@ void EtherIPIpcConnectThread(THREAD *t, void *p)
|
|||||||
&s->ClientIP, s->ClientPort,
|
&s->ClientIP, s->ClientPort,
|
||||||
&s->ServerIP, s->ServerPort,
|
&s->ServerIP, s->ServerPort,
|
||||||
tmp,
|
tmp,
|
||||||
s->CryptName, true, mss, NULL);
|
s->CryptName, true, mss, NULL, NULL);
|
||||||
|
|
||||||
if (ipc != NULL)
|
if (ipc != NULL)
|
||||||
{
|
{
|
||||||
|
@ -323,7 +323,7 @@ IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code)
|
|||||||
param->UserName, param->Password, error_code, ¶m->ClientIp,
|
param->UserName, param->Password, error_code, ¶m->ClientIp,
|
||||||
param->ClientPort, ¶m->ServerIp, param->ServerPort,
|
param->ClientPort, ¶m->ServerIp, param->ServerPort,
|
||||||
param->ClientHostname, param->CryptName,
|
param->ClientHostname, param->CryptName,
|
||||||
param->BridgeMode, param->Mss, NULL);
|
param->BridgeMode, param->Mss, NULL, param->ClientCertificate);
|
||||||
|
|
||||||
return ipc;
|
return ipc;
|
||||||
}
|
}
|
||||||
@ -332,7 +332,7 @@ IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code)
|
|||||||
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
|
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
|
||||||
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
|
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
|
||||||
char *client_hostname, char *crypt_name,
|
char *client_hostname, char *crypt_name,
|
||||||
bool bridge_mode, UINT mss, EAP_CLIENT *eap_client)
|
bool bridge_mode, UINT mss, EAP_CLIENT *eap_client, X *client_certificate)
|
||||||
{
|
{
|
||||||
IPC *ipc;
|
IPC *ipc;
|
||||||
UINT dummy_int = 0;
|
UINT dummy_int = 0;
|
||||||
@ -425,7 +425,14 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
|
|||||||
FreePack(p);
|
FreePack(p);
|
||||||
|
|
||||||
// Upload the authentication data
|
// Upload the authentication data
|
||||||
p = PackLoginWithPlainPassword(hubname, username, password);
|
if (client_certificate != NULL)
|
||||||
|
{
|
||||||
|
p = PackLoginWithOpenVPNCertificate(hubname, username, client_certificate);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p = PackLoginWithPlainPassword(hubname, username, password);
|
||||||
|
}
|
||||||
PackAddStr(p, "hello", client_name);
|
PackAddStr(p, "hello", client_name);
|
||||||
PackAddInt(p, "client_ver", cedar->Version);
|
PackAddInt(p, "client_ver", cedar->Version);
|
||||||
PackAddInt(p, "client_build", cedar->Build);
|
PackAddInt(p, "client_build", cedar->Build);
|
||||||
|
@ -165,6 +165,7 @@ struct IPC_PARAM
|
|||||||
UINT Mss;
|
UINT Mss;
|
||||||
bool IsL3Mode;
|
bool IsL3Mode;
|
||||||
bool IsOpenVPN;
|
bool IsOpenVPN;
|
||||||
|
X *ClientCertificate;
|
||||||
};
|
};
|
||||||
|
|
||||||
// IPC_ASYNC object
|
// IPC_ASYNC object
|
||||||
@ -224,7 +225,7 @@ struct IPC_MSCHAP_V2_AUTHINFO
|
|||||||
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
|
IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password,
|
||||||
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
|
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
|
||||||
char *client_hostname, char *crypt_name,
|
char *client_hostname, char *crypt_name,
|
||||||
bool bridge_mode, UINT mss, EAP_CLIENT *eap_client);
|
bool bridge_mode, UINT mss, EAP_CLIENT *eap_client, X *client_certificate);
|
||||||
IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code);
|
IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code);
|
||||||
IPC *NewIPCBySock(CEDAR *cedar, SOCK *s, void *mac_address);
|
IPC *NewIPCBySock(CEDAR *cedar, SOCK *s, void *mac_address);
|
||||||
void FreeIPC(IPC *ipc);
|
void FreeIPC(IPC *ipc);
|
||||||
|
@ -1018,7 +1018,7 @@ PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req)
|
|||||||
// Attempt to connect with IPC
|
// Attempt to connect with IPC
|
||||||
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
|
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
|
||||||
&error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
|
&error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
|
||||||
p->ClientHostname, p->CryptName, false, p->AdjustMss, p->EapClient);
|
p->ClientHostname, p->CryptName, false, p->AdjustMss, p->EapClient, NULL);
|
||||||
|
|
||||||
if (ipc != NULL)
|
if (ipc != NULL)
|
||||||
{
|
{
|
||||||
@ -1151,7 +1151,7 @@ PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req)
|
|||||||
|
|
||||||
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
|
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
|
||||||
&error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
|
&error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
|
||||||
p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL);
|
p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, NULL);
|
||||||
|
|
||||||
if (ipc != NULL)
|
if (ipc != NULL)
|
||||||
{
|
{
|
||||||
|
@ -442,7 +442,8 @@ void OvsProcessRecvControlPacket(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN
|
|||||||
// Create an SSL pipe
|
// Create an SSL pipe
|
||||||
Lock(s->Cedar->lock);
|
Lock(s->Cedar->lock);
|
||||||
{
|
{
|
||||||
c->SslPipe = NewSslPipe(true, s->Cedar->ServerX, s->Cedar->ServerK, s->Dh);
|
bool cert_verify = true;
|
||||||
|
c->SslPipe = NewSslPipeEx(true, s->Cedar->ServerX, s->Cedar->ServerK, s->Dh, cert_verify, &c->ClientCert);
|
||||||
}
|
}
|
||||||
Unlock(s->Cedar->lock);
|
Unlock(s->Cedar->lock);
|
||||||
|
|
||||||
@ -712,6 +713,11 @@ void OvsBeginIPCAsyncConnectionIfEmpty(OPENVPN_SERVER *s, OPENVPN_SESSION *se, O
|
|||||||
p.BridgeMode = true;
|
p.BridgeMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (c->ClientCert.X != NULL)
|
||||||
|
{
|
||||||
|
p.ClientCertificate = c->ClientCert.X;
|
||||||
|
}
|
||||||
|
|
||||||
p.IsOpenVPN = true;
|
p.IsOpenVPN = true;
|
||||||
|
|
||||||
// Calculate the MSS
|
// Calculate the MSS
|
||||||
@ -780,6 +786,26 @@ void OvsSetupSessionParameters(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_C
|
|||||||
|
|
||||||
OvsLog(s, se, c, "LO_OPTION_STR_RECV", data->OptionString);
|
OvsLog(s, se, c, "LO_OPTION_STR_RECV", data->OptionString);
|
||||||
|
|
||||||
|
if (c->ClientCert.X != NULL)
|
||||||
|
{
|
||||||
|
if (c->ClientCert.X->subject_name != NULL)
|
||||||
|
{
|
||||||
|
OvsLog(s, se, c, "LO_CLIENT_CERT", c->ClientCert.X->subject_name->CommonName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OvsLog(s, se, c, "LO_CLIENT_CERT", "(unknown CN)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!c->ClientCert.PreverifyErr)
|
||||||
|
{
|
||||||
|
OvsLog(s, se, c, "LO_CLIENT_NO_CERT");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OvsLog(s, se, c, "LO_CLIENT_UNVERIFIED_CERT", c->ClientCert.PreverifyErrMessage);
|
||||||
|
}
|
||||||
|
|
||||||
Zero(opt_str, sizeof(opt_str));
|
Zero(opt_str, sizeof(opt_str));
|
||||||
StrCpy(opt_str, sizeof(opt_str), data->OptionString);
|
StrCpy(opt_str, sizeof(opt_str), data->OptionString);
|
||||||
if (s->Cedar != NULL && (IsEmptyStr(opt_str) || StartWith(opt_str, "V0 UNDEF") || InStr(opt_str, ",") == false))
|
if (s->Cedar != NULL && (IsEmptyStr(opt_str) || StartWith(opt_str, "V0 UNDEF") || InStr(opt_str, ",") == false))
|
||||||
@ -1359,6 +1385,11 @@ void OvsFreeChannel(OPENVPN_CHANNEL *c)
|
|||||||
FreeMd(c->MdRecv);
|
FreeMd(c->MdRecv);
|
||||||
FreeMd(c->MdSend);
|
FreeMd(c->MdSend);
|
||||||
|
|
||||||
|
if (c->ClientCert.X != NULL)
|
||||||
|
{
|
||||||
|
FreeX(c->ClientCert.X);
|
||||||
|
}
|
||||||
|
|
||||||
Free(c);
|
Free(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,6 +257,7 @@ struct OPENVPN_CHANNEL
|
|||||||
bool IsInitiatorServer; // Whether the channel was started from the server side
|
bool IsInitiatorServer; // Whether the channel was started from the server side
|
||||||
bool RekeyInitiated; // Whether re-keying has already started
|
bool RekeyInitiated; // Whether re-keying has already started
|
||||||
UINT64 NextRekey;
|
UINT64 NextRekey;
|
||||||
|
struct SslClientCertInfo ClientCert; // Client certificate and verification data
|
||||||
};
|
};
|
||||||
|
|
||||||
// OpenVPN session
|
// OpenVPN session
|
||||||
|
@ -1795,6 +1795,9 @@ bool ServerAccept(CONNECTION *c)
|
|||||||
case AUTHTYPE_TICKET:
|
case AUTHTYPE_TICKET:
|
||||||
authtype_str = _UU("LH_AUTH_TICKET");
|
authtype_str = _UU("LH_AUTH_TICKET");
|
||||||
break;
|
break;
|
||||||
|
case AUTHTYPE_OPENVPN_CERT:
|
||||||
|
authtype_str = _UU("LH_AUTH_OPENVPN_CERT");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
IPToStr(ip1, sizeof(ip1), &c->FirstSock->RemoteIP);
|
IPToStr(ip1, sizeof(ip1), &c->FirstSock->RemoteIP);
|
||||||
IPToStr(ip2, sizeof(ip2), &c->FirstSock->LocalIP);
|
IPToStr(ip2, sizeof(ip2), &c->FirstSock->LocalIP);
|
||||||
@ -2128,6 +2131,50 @@ bool ServerAccept(CONNECTION *c)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AUTHTYPE_OPENVPN_CERT:
|
||||||
|
// For OpenVPN; mostly same as CLIENT_AUTHTYPE_CERT, but without
|
||||||
|
// signature verification, because it was already performed during TLS handshake.
|
||||||
|
if (c->IsInProc)
|
||||||
|
{
|
||||||
|
// Certificate authentication
|
||||||
|
cert_size = PackGetDataSize(p, "cert");
|
||||||
|
if (cert_size >= 1 && cert_size <= 100000)
|
||||||
|
{
|
||||||
|
cert_buf = ZeroMalloc(cert_size);
|
||||||
|
if (PackGetData(p, "cert", cert_buf))
|
||||||
|
{
|
||||||
|
BUF *b = NewBuf();
|
||||||
|
X *x;
|
||||||
|
WriteBuf(b, cert_buf, cert_size);
|
||||||
|
x = BufToX(b, false);
|
||||||
|
if (x != NULL && x->is_compatible_bit)
|
||||||
|
{
|
||||||
|
Debug("Got to SamAuthUserByCert %s\n", username); // XXX
|
||||||
|
// Check whether the certificate is valid.
|
||||||
|
auth_ret = SamAuthUserByCert(hub, username, x);
|
||||||
|
if (auth_ret)
|
||||||
|
{
|
||||||
|
// Copy the certificate
|
||||||
|
c->ClientX = CloneX(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeX(x);
|
||||||
|
FreeBuf(b);
|
||||||
|
}
|
||||||
|
Free(cert_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// OpenVPN certificate authentication cannot be used directly by external clients
|
||||||
|
Unlock(hub->lock);
|
||||||
|
ReleaseHub(hub);
|
||||||
|
FreePack(p);
|
||||||
|
c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
|
||||||
|
goto CLEANUP;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Unknown authentication method
|
// Unknown authentication method
|
||||||
Unlock(hub->lock);
|
Unlock(hub->lock);
|
||||||
@ -7247,6 +7294,45 @@ PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_pass
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate a packet of OpenVPN certificate login
|
||||||
|
PACK *PackLoginWithOpenVPNCertificate(char *hubname, char *username, X *x)
|
||||||
|
{
|
||||||
|
PACK *p;
|
||||||
|
// Validate arguments
|
||||||
|
if (hubname == NULL || username == NULL || x == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = NewPack();
|
||||||
|
PackAddStr(p, "method", "login");
|
||||||
|
PackAddStr(p, "hubname", hubname);
|
||||||
|
|
||||||
|
char cn_username[128];
|
||||||
|
if (IsEmptyStr(username))
|
||||||
|
{
|
||||||
|
if (x->subject_name == NULL)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
wcstombs(cn_username, x->subject_name->CommonName, 127);
|
||||||
|
cn_username[127] = '\0';
|
||||||
|
PackAddStr(p, "username", cn_username);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PackAddStr(p, "username", username);
|
||||||
|
}
|
||||||
|
|
||||||
|
PackAddInt(p, "authtype", AUTHTYPE_OPENVPN_CERT);
|
||||||
|
|
||||||
|
BUF *cert_buf = XToBuf(x, false);
|
||||||
|
PackAddBuf(p, "cert", cert_buf);
|
||||||
|
FreeBuf(cert_buf);
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a packet of password authentication login
|
// Create a packet of password authentication login
|
||||||
PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password)
|
PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password)
|
||||||
{
|
{
|
||||||
|
@ -242,6 +242,7 @@ PACK *PackLoginWithAnonymous(char *hubname, char *username);
|
|||||||
PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password);
|
PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password);
|
||||||
PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password);
|
PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password);
|
||||||
PACK *PackLoginWithCert(char *hubname, char *username, X *x, void *sign, UINT sign_size);
|
PACK *PackLoginWithCert(char *hubname, char *username, X *x, void *sign, UINT sign_size);
|
||||||
|
PACK *PackLoginWithOpenVPNCertificate(char *hubname, char *username, X *x);
|
||||||
bool GetMethodFromPack(PACK *p, char *method, UINT size);
|
bool GetMethodFromPack(PACK *p, char *method, UINT size);
|
||||||
bool GetHubnameAndUsernameFromPack(PACK *p, char *username, UINT username_size,
|
bool GetHubnameAndUsernameFromPack(PACK *p, char *username, UINT username_size,
|
||||||
char *hubname, UINT hubname_size);
|
char *hubname, UINT hubname_size);
|
||||||
|
@ -151,6 +151,8 @@
|
|||||||
|
|
||||||
LOCK *openssl_lock = NULL;
|
LOCK *openssl_lock = NULL;
|
||||||
|
|
||||||
|
int ssl_clientcert_index = 0;
|
||||||
|
|
||||||
LOCK **ssl_lock_obj = NULL;
|
LOCK **ssl_lock_obj = NULL;
|
||||||
UINT ssl_lock_num;
|
UINT ssl_lock_num;
|
||||||
static bool openssl_inited = false;
|
static bool openssl_inited = false;
|
||||||
@ -4064,6 +4066,8 @@ void InitCryptLibrary()
|
|||||||
ERR_load_crypto_strings();
|
ERR_load_crypto_strings();
|
||||||
SSL_load_error_strings();
|
SSL_load_error_strings();
|
||||||
|
|
||||||
|
ssl_clientcert_index = SSL_get_ex_new_index(0, "struct SslClientCertInfo *", NULL, NULL, NULL);
|
||||||
|
|
||||||
#ifdef OS_UNIX
|
#ifdef OS_UNIX
|
||||||
{
|
{
|
||||||
char *name1 = "/dev/random";
|
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();
|
void DisableIntelAesAccel();
|
||||||
|
|
||||||
|
int GetSslClientCertIndex();
|
||||||
|
|
||||||
#ifdef ENCRYPT_C
|
#ifdef ENCRYPT_C
|
||||||
// Inner function
|
// Inner function
|
||||||
|
|
||||||
|
@ -5809,14 +5809,52 @@ SOCK *ListenAnyPortEx2(bool local_only, bool disable_ca)
|
|||||||
return NULL;
|
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;
|
SSL *ssl;
|
||||||
return 1;
|
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
|
// Create a new SSL pipe
|
||||||
SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh)
|
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_PIPE *s;
|
||||||
SSL *ssl;
|
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_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)
|
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 = SSL_new(ssl_ctx);
|
||||||
|
|
||||||
|
SSL_set_ex_data(ssl, GetSslClientCertIndex(), clientcert);
|
||||||
}
|
}
|
||||||
Unlock(openssl_lock);
|
Unlock(openssl_lock);
|
||||||
|
|
||||||
|
@ -1615,7 +1615,16 @@ void Win32WaitForTubes(TUBE **tubes, UINT num, UINT timeout);
|
|||||||
void UnixWaitForTubes(TUBE **tubes, UINT num, UINT timeout);
|
void UnixWaitForTubes(TUBE **tubes, UINT num, UINT timeout);
|
||||||
#endif // OS_WIN32
|
#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 *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);
|
void FreeSslPipe(SSL_PIPE *s);
|
||||||
bool SyncSslPipe(SSL_PIPE *s);
|
bool SyncSslPipe(SSL_PIPE *s);
|
||||||
|
|
||||||
|
@ -1810,6 +1810,9 @@ LO_PREFIX_CHANNEL OpenVPN 会话%u (%r:%u -> %r:%u) 通道 %u:
|
|||||||
LO_NEW_CHANNEL 已创创建一个新通道。
|
LO_NEW_CHANNEL 已创创建一个新通道。
|
||||||
LO_CHANNEL_ESTABLISHED_NEWKEY 通道已建立。(触发器: Re-key完成。)
|
LO_CHANNEL_ESTABLISHED_NEWKEY 通道已建立。(触发器: Re-key完成。)
|
||||||
LO_OPTION_STR_RECV 接收到的选项字符串:"%S"
|
LO_OPTION_STR_RECV 接收到的选项字符串:"%S"
|
||||||
|
LO_CLIENT_CERT Client certificate received (subject: CN="%s"), will use certificate authentication.
|
||||||
|
LO_CLIENT_UNVERIFIED_CERT Client certificate was provided but did not pass verification (error="%S"), will use password authentication.
|
||||||
|
LO_CLIENT_NO_CERT Client certificate is not provided, will use password authentication.
|
||||||
LO_OPTION_STR_SEND 发送选项字符串:"%S"
|
LO_OPTION_STR_SEND 发送选项字符串:"%S"
|
||||||
LO_NEW_SESSION 已创建新的会话。协议:%S
|
LO_NEW_SESSION 已创建新的会话。协议:%S
|
||||||
LO_INITIATE_REKEY re-keying 进程已开始。
|
LO_INITIATE_REKEY re-keying 进程已开始。
|
||||||
@ -1906,6 +1909,7 @@ LH_AUTH_PASSWORD 密码验证
|
|||||||
LH_AUTH_PLAIN_PASSWORD 外部服务器身份验证
|
LH_AUTH_PLAIN_PASSWORD 外部服务器身份验证
|
||||||
LH_AUTH_CERT 证书验证
|
LH_AUTH_CERT 证书验证
|
||||||
LH_AUTH_TICKET 票证验证
|
LH_AUTH_TICKET 票证验证
|
||||||
|
LH_AUTH_OPENVPN_CERT OpenVPN certificate authentication
|
||||||
LH_AUTH_RADIUS_NOT_SUPPORT 连接 "%S": 用户 "%S" 身份验证方法 RADIUS 或 Active Directory (NT 域),但 VPN Server 是 "%S",因为 RADIUS 或 Active Directory (NT 域)不能使用。连接被拒绝。
|
LH_AUTH_RADIUS_NOT_SUPPORT 连接 "%S": 用户 "%S" 身份验证方法 RADIUS 或 Active Directory (NT 域),但 VPN Server 是 "%S",因为 RADIUS 或 Active Directory (NT 域)不能使用。连接被拒绝。
|
||||||
LH_AUTH_RADIUS_NOT_SUPPORT_ON_OPEN_SOURCE "%S" 的连接方法: 用户 "%S" 的身份验证方法被指定为 RADIUS 身份验证或 Active Directory 身份验证 (NT 域验证)。然而,这样一个外部用户身份验证功能尚未在 SoftEther VPN 的开源版本上实施。该连接将被拒绝。
|
LH_AUTH_RADIUS_NOT_SUPPORT_ON_OPEN_SOURCE "%S" 的连接方法: 用户 "%S" 的身份验证方法被指定为 RADIUS 身份验证或 Active Directory 身份验证 (NT 域验证)。然而,这样一个外部用户身份验证功能尚未在 SoftEther VPN 的开源版本上实施。该连接将被拒绝。
|
||||||
LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE "%S" 的连接方法: 用户 "%S" 的身份验证方法被指定为证书认证。然而,证书验证功能尚未在 SoftEther VPN 的开源版本上实施。该连接将被拒绝。
|
LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE "%S" 的连接方法: 用户 "%S" 的身份验证方法被指定为证书认证。然而,证书验证功能尚未在 SoftEther VPN 的开源版本上实施。该连接将被拒绝。
|
||||||
|
@ -1792,6 +1792,9 @@ LO_PREFIX_CHANNEL OpenVPN Session %u (%r:%u -> %r:%u) Channel %u:
|
|||||||
LO_NEW_CHANNEL A new channel is created.
|
LO_NEW_CHANNEL A new channel is created.
|
||||||
LO_CHANNEL_ESTABLISHED_NEWKEY The channel is established. (Trigger: Re-key completion.)
|
LO_CHANNEL_ESTABLISHED_NEWKEY The channel is established. (Trigger: Re-key completion.)
|
||||||
LO_OPTION_STR_RECV Option Strings Received: "%S"
|
LO_OPTION_STR_RECV Option Strings Received: "%S"
|
||||||
|
LO_CLIENT_CERT Client certificate received (subject: CN="%s"), will use certificate authentication.
|
||||||
|
LO_CLIENT_UNVERIFIED_CERT Client certificate was provided but did not pass verification (error="%S"), will use password authentication.
|
||||||
|
LO_CLIENT_NO_CERT Client certificate is not provided, will use password authentication.
|
||||||
LO_OPTION_STR_SEND Option Strings to Send: "%S"
|
LO_OPTION_STR_SEND Option Strings to Send: "%S"
|
||||||
LO_NEW_SESSION A new session is created. Protocol: %S
|
LO_NEW_SESSION A new session is created. Protocol: %S
|
||||||
LO_INITIATE_REKEY The re-keying process is started.
|
LO_INITIATE_REKEY The re-keying process is started.
|
||||||
@ -1888,6 +1891,7 @@ LH_AUTH_PASSWORD Password authentication
|
|||||||
LH_AUTH_PLAIN_PASSWORD External server authentication
|
LH_AUTH_PLAIN_PASSWORD External server authentication
|
||||||
LH_AUTH_CERT Certificate authentication
|
LH_AUTH_CERT Certificate authentication
|
||||||
LH_AUTH_TICKET Ticket authentication
|
LH_AUTH_TICKET Ticket authentication
|
||||||
|
LH_AUTH_OPENVPN_CERT OpenVPN certificate authentication
|
||||||
LH_AUTH_RADIUS_NOT_SUPPORT Connection "%S": The authentication method of the user "%S" has been specified as RADIUS Authentication or Active Directory Authentication (NT Domain Authentication). However, the edition of the VPN Server is "%S". This edition does not support RADIUS Authentication nor Active Directory Authentication (NT Domain Authentication). The connection will be denied.
|
LH_AUTH_RADIUS_NOT_SUPPORT Connection "%S": The authentication method of the user "%S" has been specified as RADIUS Authentication or Active Directory Authentication (NT Domain Authentication). However, the edition of the VPN Server is "%S". This edition does not support RADIUS Authentication nor Active Directory Authentication (NT Domain Authentication). The connection will be denied.
|
||||||
LH_AUTH_RADIUS_NOT_SUPPORT_ON_OPEN_SOURCE Connection "%S": The authentication method of the user "%S" has been specified as RADIUS Authentication or Active Directory Authentication (NT Domain Authentication). However, such an external user-authentication function hasn't been implemented on the Open-Source version of SoftEther VPN yet. The connection will be denied.
|
LH_AUTH_RADIUS_NOT_SUPPORT_ON_OPEN_SOURCE Connection "%S": The authentication method of the user "%S" has been specified as RADIUS Authentication or Active Directory Authentication (NT Domain Authentication). However, such an external user-authentication function hasn't been implemented on the Open-Source version of SoftEther VPN yet. The connection will be denied.
|
||||||
LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE Connection "%S": The authentication method of the user "%S" has been specified as Certificate Authentication. However, the Certificate Authentication function hasn't been implemented on the Open-Source version of SoftEther VPN yet. The connection will be denied.
|
LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE Connection "%S": The authentication method of the user "%S" has been specified as Certificate Authentication. However, the Certificate Authentication function hasn't been implemented on the Open-Source version of SoftEther VPN yet. The connection will be denied.
|
||||||
@ -7164,5 +7168,3 @@ SW_LINK_NAME_LANGUAGE_COMMENT Change the display language setting of %s.
|
|||||||
|
|
||||||
SW_LINK_NAME_DEBUG Debugging Information Collecting Tool
|
SW_LINK_NAME_DEBUG Debugging Information Collecting Tool
|
||||||
SW_LINK_NAME_DEBUG_COMMENT Collects debugging information of SoftEther VPN. Use this tool only if your support staff asks you to do so.
|
SW_LINK_NAME_DEBUG_COMMENT Collects debugging information of SoftEther VPN. Use this tool only if your support staff asks you to do so.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1796,6 +1796,9 @@ LO_PREFIX_CHANNEL OpenVPN セッション %u (%r:%u -> %r:%u) チャネル %u:
|
|||||||
LO_NEW_CHANNEL 新しいチャネルを作成しました。
|
LO_NEW_CHANNEL 新しいチャネルを作成しました。
|
||||||
LO_CHANNEL_ESTABLISHED_NEWKEY チャネルが確立状態になりました (原因: リキーの完了)。
|
LO_CHANNEL_ESTABLISHED_NEWKEY チャネルが確立状態になりました (原因: リキーの完了)。
|
||||||
LO_OPTION_STR_RECV 受信したオプション文字列: "%S"
|
LO_OPTION_STR_RECV 受信したオプション文字列: "%S"
|
||||||
|
LO_CLIENT_CERT Client certificate received (subject: CN="%s"), will use certificate authentication.
|
||||||
|
LO_CLIENT_UNVERIFIED_CERT Client certificate was provided but did not pass verification (error="%S"), will use password authentication.
|
||||||
|
LO_CLIENT_NO_CERT Client certificate is not provided, will use password authentication.
|
||||||
LO_OPTION_STR_SEND 送信するオプション文字列: "%S"
|
LO_OPTION_STR_SEND 送信するオプション文字列: "%S"
|
||||||
LO_NEW_SESSION 新しいセッションを作成しました。プロトコル: %S
|
LO_NEW_SESSION 新しいセッションを作成しました。プロトコル: %S
|
||||||
LO_INITIATE_REKEY このチャネルのリキーを開始します。
|
LO_INITIATE_REKEY このチャネルのリキーを開始します。
|
||||||
@ -1892,6 +1895,7 @@ LH_AUTH_PASSWORD パスワード認証
|
|||||||
LH_AUTH_PLAIN_PASSWORD 外部サーバー認証
|
LH_AUTH_PLAIN_PASSWORD 外部サーバー認証
|
||||||
LH_AUTH_CERT 証明書認証
|
LH_AUTH_CERT 証明書認証
|
||||||
LH_AUTH_TICKET チケット認証
|
LH_AUTH_TICKET チケット認証
|
||||||
|
LH_AUTH_OPENVPN_CERT OpenVPN certificate authentication
|
||||||
LH_AUTH_RADIUS_NOT_SUPPORT コネクション "%S": ユーザー "%S" の認証方法として RADIUS 認証または Active Directory 認証 (NT ドメイン認証) が指定されましたが、現在の VPN Server のエディションは "%S" であるため、RADIUS 認証または Active Directory 認証 (NT ドメイン認証) を使用することができません。接続は拒否されます。
|
LH_AUTH_RADIUS_NOT_SUPPORT コネクション "%S": ユーザー "%S" の認証方法として RADIUS 認証または Active Directory 認証 (NT ドメイン認証) が指定されましたが、現在の VPN Server のエディションは "%S" であるため、RADIUS 認証または Active Directory 認証 (NT ドメイン認証) を使用することができません。接続は拒否されます。
|
||||||
LH_AUTH_RADIUS_NOT_SUPPORT_ON_OPEN_SOURCE コネクション "%S": ユーザー "%S" の認証方法として RADIUS 認証または Active Directory 認証 (NT ドメイン認証) が指定されましたが、RADIUS 認証または Active Directory 認証 (NT ドメイン認証) を使用することができません。この機能はオープンソース版 SoftEther VPN にはまだ実装されていません。接続は拒否されます。
|
LH_AUTH_RADIUS_NOT_SUPPORT_ON_OPEN_SOURCE コネクション "%S": ユーザー "%S" の認証方法として RADIUS 認証または Active Directory 認証 (NT ドメイン認証) が指定されましたが、RADIUS 認証または Active Directory 認証 (NT ドメイン認証) を使用することができません。この機能はオープンソース版 SoftEther VPN にはまだ実装されていません。接続は拒否されます。
|
||||||
LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE コネクション "%S": ユーザー "%S" の認証方法として証明書認証が指定されましたが、証明書認証を使用することができません。この機能はオープンソース版 SoftEther VPN にはまだ実装されていません。接続は拒否されます。
|
LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE コネクション "%S": ユーザー "%S" の認証方法として証明書認証が指定されましたが、証明書認証を使用することができません。この機能はオープンソース版 SoftEther VPN にはまだ実装されていません。接続は拒否されます。
|
||||||
|
@ -1812,6 +1812,9 @@ LO_PREFIX_CHANNEL OpenVPN 會話%u (%r:%u -> %r:%u) 通道 %u:
|
|||||||
LO_NEW_CHANNEL 已創建一個新通道。
|
LO_NEW_CHANNEL 已創建一個新通道。
|
||||||
LO_CHANNEL_ESTABLISHED_NEWKEY 通道已建立。(觸發器: Re-key完成。)
|
LO_CHANNEL_ESTABLISHED_NEWKEY 通道已建立。(觸發器: Re-key完成。)
|
||||||
LO_OPTION_STR_RECV 接收到的選項字串:"%S"
|
LO_OPTION_STR_RECV 接收到的選項字串:"%S"
|
||||||
|
LO_CLIENT_CERT Client certificate received (subject: CN="%s"), will use certificate authentication.
|
||||||
|
LO_CLIENT_UNVERIFIED_CERT Client certificate was provided but did not pass verification (error="%S"), will use password authentication.
|
||||||
|
LO_CLIENT_NO_CERT Client certificate is not provided, will use password authentication.
|
||||||
LO_OPTION_STR_SEND 發送選項字串:"%S"
|
LO_OPTION_STR_SEND 發送選項字串:"%S"
|
||||||
LO_NEW_SESSION 已創建新的會話。協議:%S
|
LO_NEW_SESSION 已創建新的會話。協議:%S
|
||||||
LO_INITIATE_REKEY re-keying 進程已開始。
|
LO_INITIATE_REKEY re-keying 進程已開始。
|
||||||
@ -1908,6 +1911,7 @@ LH_AUTH_PASSWORD 密碼驗證
|
|||||||
LH_AUTH_PLAIN_PASSWORD 外部伺服器身份驗證
|
LH_AUTH_PLAIN_PASSWORD 外部伺服器身份驗證
|
||||||
LH_AUTH_CERT 證書驗證
|
LH_AUTH_CERT 證書驗證
|
||||||
LH_AUTH_TICKET 票證驗證
|
LH_AUTH_TICKET 票證驗證
|
||||||
|
LH_AUTH_OPENVPN_CERT OpenVPN certificate authentication
|
||||||
LH_AUTH_RADIUS_NOT_SUPPORT 連接 "%S": 用戶 "%S" 身份驗證方法 RADIUS 或 Active Directory (NT 域),但 VPN Server 是 "%S",因為 RADIUS 或 Active Directory (NT 域)不能使用。連接被拒絕。
|
LH_AUTH_RADIUS_NOT_SUPPORT 連接 "%S": 用戶 "%S" 身份驗證方法 RADIUS 或 Active Directory (NT 域),但 VPN Server 是 "%S",因為 RADIUS 或 Active Directory (NT 域)不能使用。連接被拒絕。
|
||||||
LH_AUTH_RADIUS_NOT_SUPPORT_ON_OPEN_SOURCE "%S" 的連接方法: 用戶 "%S" 的身份驗證方法被指定為 RADIUS 身份驗證或 Active Directory 身份驗證 (NT 域驗證)。然而,這樣一個外部用戶身份驗證功能尚未在 SoftEther VPN 的開源版本上實施。該連接將被拒絕。
|
LH_AUTH_RADIUS_NOT_SUPPORT_ON_OPEN_SOURCE "%S" 的連接方法: 用戶 "%S" 的身份驗證方法被指定為 RADIUS 身份驗證或 Active Directory 身份驗證 (NT 域驗證)。然而,這樣一個外部用戶身份驗證功能尚未在 SoftEther VPN 的開源版本上實施。該連接將被拒絕。
|
||||||
LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE "%S" 的連接方法: 用戶 "%S" 的身份驗證方法被指定為證書認證。然而,證書驗證功能尚未在 SoftEther VPN 的開源版本上實施。該連接將被拒絕。
|
LH_AUTH_CERT_NOT_SUPPORT_ON_OPEN_SOURCE "%S" 的連接方法: 用戶 "%S" 的身份驗證方法被指定為證書認證。然而,證書驗證功能尚未在 SoftEther VPN 的開源版本上實施。該連接將被拒絕。
|
||||||
|
Loading…
Reference in New Issue
Block a user