1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2025-06-27 19:35:09 +03:00

Openssl engine certificate authentication in server and client

Introduced auth type 5 for client.
Example config:
                   uint AuthType 5
                   byte ClientCert cert
                   string OpensslEnginePrivateKeyName 0x81000000
                   string OpensslEngineName tpm2tss

Introduced server key type. When the value is absent or x509 then use the usual
x509 certificates. When the value is engine, then the server will use openssl
engines for it's certificate.

Example config:
		               string ServerEngineKey {{ .serverKey }}
		               string ServerEngineName tpm2tss
                   string ServerKeyType engine

daniel.mcallister@nokia.com
This commit is contained in:
mcallist 2020-07-06 20:25:18 +02:00 committed by mcallist
parent ed17437af9
commit 0185da8bc1
21 changed files with 459 additions and 86 deletions

View File

@ -1587,6 +1587,7 @@ PACK *AdminDispatch(RPC *rpc, char *name, PACK *p)
DECLARE_RPC_EX("EnumFarmMember", RPC_ENUM_FARM, StEnumFarmMember, InRpcEnumFarm, OutRpcEnumFarm, FreeRpcEnumFarm)
DECLARE_RPC("GetFarmConnectionStatus", RPC_FARM_CONNECTION_STATUS, StGetFarmConnectionStatus, InRpcFarmConnectionStatus, OutRpcFarmConnectionStatus)
DECLARE_RPC_EX("SetServerCert", RPC_KEY_PAIR, StSetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)
DECLARE_RPC_EX("SetServerOpensslEngineCert", RPC_OPENSSL_ENGINE_KEY_PAIR, StSetServerOpensslEngineCert, InRpcOpensslEngineKeyPair, OutRpcOpensslEngineKeyPair, FreeRpcOpensslEngineKeyPair)
DECLARE_RPC_EX("GetServerCert", RPC_KEY_PAIR, StGetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)
DECLARE_RPC_EX("GetServerCipher", RPC_STR, StGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_RPC_EX("SetServerCipher", RPC_STR, StSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
@ -1766,6 +1767,7 @@ DECLARE_SC_EX("GetFarmInfo", RPC_FARM_INFO, ScGetFarmInfo, InRpcFarmInfo, OutRpc
DECLARE_SC_EX("EnumFarmMember", RPC_ENUM_FARM, ScEnumFarmMember, InRpcEnumFarm, OutRpcEnumFarm, FreeRpcEnumFarm)
DECLARE_SC("GetFarmConnectionStatus", RPC_FARM_CONNECTION_STATUS, ScGetFarmConnectionStatus, InRpcFarmConnectionStatus, OutRpcFarmConnectionStatus)
DECLARE_SC_EX("SetServerCert", RPC_KEY_PAIR, ScSetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)
DECLARE_SC_EX("SetServerOpensslEngineCert", RPC_OPENSSL_ENGINE_KEY_PAIR, ScSetServerOpensslEngineCert, InRpcOpensslEngineKeyPair, OutRpcOpensslEngineKeyPair, FreeRpcOpensslEngineKeyPair)
DECLARE_SC_EX("GetServerCert", RPC_KEY_PAIR, ScGetServerCert, InRpcKeyPair, OutRpcKeyPair, FreeRpcKeyPair)
DECLARE_SC_EX("GetServerCipher", RPC_STR, ScGetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
DECLARE_SC_EX("SetServerCipher", RPC_STR, ScSetServerCipher, InRpcStr, OutRpcStr, FreeRpcStr)
@ -2253,7 +2255,7 @@ UINT StMakeOpenVpnConfigFile(ADMIN *a, RPC_READ_LOG_FILE *t)
{
Lock(c->lock);
{
x = CloneX(c->ServerX);
x = CloneK(c->ServerX);
}
Unlock(c->lock);
@ -9434,7 +9436,11 @@ UINT StGetServerCert(ADMIN *a, RPC_KEY_PAIR *t)
t->Cert = CloneX(c->ServerX);
if (admin && is_vgs_cert == false)
{
t->Key = CloneK(c->ServerK);
if (StrCmp(c->ServerKeyType, "engine") == 0) {
t->Key = OpensslEngineToK(c->ServerEngineKey, c->ServerEngineName);
} else {
t->Key = CloneK(c->ServerK);
}
}
}
Unlock(c->lock);
@ -9482,6 +9488,37 @@ UINT StSetServerCert(ADMIN *a, RPC_KEY_PAIR *t)
return ERR_NO_ERROR;
}
// Set the server certification
UINT StSetServerOpensslEngineCert(ADMIN *a, RPC_OPENSSL_ENGINE_KEY_PAIR *t)
{
SERVER *s = a->Server;
CEDAR *c = s->Cedar;
SERVER_ADMIN_ONLY;
if (t->Cert == NULL)
{
return ERR_PROTOCOL_ERROR;
}
t->Flag1 = 1;
if (t->Cert->root_cert == false)
{
if (DownloadAndSaveIntermediateCertificatesIfNecessary(t->Cert) == false)
{
t->Flag1 = 0;
}
}
K *k = OpensslEngineToK(t->KeyName, t->EngineName);
SetCedarEngineCert(c, t->Cert, k, t->EngineName, t->KeyName);
ALog(a, NULL, "LA_SET_SERVER_CERT");
IncrementServerConfigRevision(s);
return ERR_NO_ERROR;
}
// Get status of connection to cluster controller
UINT StGetFarmConnectionStatus(ADMIN *a, RPC_FARM_CONNECTION_STATUS *t)
@ -14058,6 +14095,35 @@ void FreeRpcKeyPair(RPC_KEY_PAIR *t)
FreeX(t->Cert);
FreeK(t->Key);
}
// RPC_KEY_PAIR
void InRpcOpensslEngineKeyPair(RPC_OPENSSL_ENGINE_KEY_PAIR *t, PACK *p)
{
// Validate arguments
if (t == NULL || p == NULL)
{
return;
}
t->Cert = PackGetX(p, "Cert");
PackGetStr(p, "Key", t->KeyName, sizeof(t->KeyName));
PackGetStr(p, "EngineName", t->EngineName, sizeof(t->EngineName));
t->Flag1 = PackGetInt(p, "Flag1");
}
void OutRpcOpensslEngineKeyPair(PACK *p, RPC_OPENSSL_ENGINE_KEY_PAIR *t)
{
// Validate arguments
if (p == NULL || t == NULL)
{
return;
}
PackAddX(p, "Cert", t->Cert);
PackAddStr(p, "Key", t->KeyName);
PackAddStr(p, "EngineName", t->EngineName);
PackAddInt(p, "Flag1", t->Flag1);
}
void FreeRpcOpensslEngineKeyPair(RPC_OPENSSL_ENGINE_KEY_PAIR *t)
{
FreeX(t->Cert);
}
// NODE_INFO
void InRpcNodeInfo(NODE_INFO *t, PACK *p)

View File

@ -307,6 +307,14 @@ struct RPC_KEY_PAIR
K *Key; // Secret key
UINT Flag1; // Flag1
};
// Key pair
struct RPC_OPENSSL_ENGINE_KEY_PAIR
{
X *Cert; // Certificate
char KeyName[MAX_SIZE]; // key
char EngineName[MAX_SIZE]; // engine name
UINT Flag1; // Flag1
};
// HUB option
struct RPC_HUB_OPTION
@ -1063,6 +1071,7 @@ UINT StGetFarmInfo(ADMIN *a, RPC_FARM_INFO *t);
UINT StEnumFarmMember(ADMIN *a, RPC_ENUM_FARM *t);
UINT StGetFarmConnectionStatus(ADMIN *a, RPC_FARM_CONNECTION_STATUS *t);
UINT StSetServerCert(ADMIN *a, RPC_KEY_PAIR *t);
UINT StSetServerOpensslEngineCert(ADMIN *a, RPC_OPENSSL_ENGINE_KEY_PAIR *t);
UINT StGetServerCert(ADMIN *a, RPC_KEY_PAIR *t);
UINT StGetServerCipher(ADMIN *a, RPC_STR *t);
UINT StSetServerCipher(ADMIN *a, RPC_STR *t);
@ -1206,6 +1215,7 @@ UINT ScGetFarmInfo(RPC *r, RPC_FARM_INFO *t);
UINT ScEnumFarmMember(RPC *r, RPC_ENUM_FARM *t);
UINT ScGetFarmConnectionStatus(RPC *r, RPC_FARM_CONNECTION_STATUS *t);
UINT ScSetServerCert(RPC *r, RPC_KEY_PAIR *t);
UINT ScSetServerOpensslEngineCert(RPC *r, RPC_OPENSSL_ENGINE_KEY_PAIR *t);
UINT ScGetServerCert(RPC *r, RPC_KEY_PAIR *t);
UINT ScGetServerCipher(RPC *r, RPC_STR *t);
UINT ScSetServerCipher(RPC *r, RPC_STR *t);
@ -1460,6 +1470,9 @@ void OutRpcMemInfo(PACK *p, MEMINFO *t);
void InRpcKeyPair(RPC_KEY_PAIR *t, PACK *p);
void OutRpcKeyPair(PACK *p, RPC_KEY_PAIR *t);
void FreeRpcKeyPair(RPC_KEY_PAIR *t);
void InRpcOpensslEngineKeyPair(RPC_OPENSSL_ENGINE_KEY_PAIR *t, PACK *p);
void OutRpcOpensslEngineKeyPair(PACK *p, RPC_OPENSSL_ENGINE_KEY_PAIR *t);
void FreeRpcOpensslEngineKeyPair(RPC_OPENSSL_ENGINE_KEY_PAIR *t);
void InRpcAddAccess(RPC_ADD_ACCESS *t, PACK *p);
void OutRpcAddAccess(PACK *p, RPC_ADD_ACCESS *t);
void InRpcDeleteAccess(RPC_DELETE_ACCESS *t, PACK *p);

View File

@ -1627,6 +1627,37 @@ void SetCedarCert(CEDAR *c, X *server_x, K *server_k)
}
Unlock(c->lock);
}
// Change certificate of Cedar
void SetCedarEngineCert(CEDAR *c, X *server_x, K *server_k, char *engine_name, char *key_name)
{
// Validate arguments
if (server_x == NULL || server_k == NULL)
{
return;
}
Lock(c->lock);
{
if (c->ServerX != NULL)
{
FreeX(c->ServerX);
}
if (c->ServerK != NULL)
{
FreeK(c->ServerK);
}
c->ServerX = CloneX(server_x);
c->ServerK = OpensslEngineToK(key_name, engine_name);
c->ServerEngineName = CopyStr(engine_name);
c->ServerEngineKey = CopyStr(key_name);
c->ServerKeyType = CopyStr("engine");
}
Unlock(c->lock);
}
// Enable debug log
void EnableDebugLog(CEDAR *c)

View File

@ -444,6 +444,7 @@
#define CLIENT_AUTHTYPE_PLAIN_PASSWORD 2 // Plain password authentication
#define CLIENT_AUTHTYPE_CERT 3 // Certificate authentication
#define CLIENT_AUTHTYPE_SECURE 4 // Secure device authentication
#define CLIENT_AUTHTYPE_OPENSSLENGINE 5 // Openssl engine authentication
@ -992,6 +993,10 @@ typedef struct CEDAR
COUNTER *ConnectionIncrement; // Connection increment counter
X *ServerX; // Server certificate
K *ServerK; // Private key of the server certificate
char *ServerKeyType;
char *ServerEngineName;
char *ServerEngineKey;
char UsernameHubSeparator; // Character which separates the username from the hub name
char *CipherList; // List of encryption algorithms
UINT Version; // Version information
UINT Build; // Build Number
@ -1189,6 +1194,7 @@ CEDAR *NewCedar(X *server_x, K *server_k);
void CedarForceLink();
void SetCedarVpnBridge(CEDAR *c);
void SetCedarCert(CEDAR *c, X *server_x, K *server_k);
void SetCedarEngineCert(CEDAR *c, X *server_x, K *server_k, char *engine_name, char *key_name);
void ReleaseCedar(CEDAR *c);
void CleanupCedar(CEDAR *c);
void StopCedar(CEDAR *c);

View File

@ -396,6 +396,7 @@ typedef struct RPC_ENUM_FARM_ITEM RPC_ENUM_FARM_ITEM;
typedef struct RPC_ENUM_FARM RPC_ENUM_FARM;
typedef struct RPC_FARM_CONNECTION_STATUS RPC_FARM_CONNECTION_STATUS;
typedef struct RPC_KEY_PAIR RPC_KEY_PAIR;
typedef struct RPC_OPENSSL_ENGINE_KEY_PAIR RPC_OPENSSL_ENGINE_KEY_PAIR;
typedef struct RPC_HUB_OPTION RPC_HUB_OPTION;
typedef struct RPC_RADIUS RPC_RADIUS;
typedef struct RPC_HUB RPC_HUB;

View File

@ -100,7 +100,6 @@
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// Client.c
// Client Manager
@ -4727,6 +4726,17 @@ void InRpcClientAuth(CLIENT_AUTH *c, PACK *p)
PackGetStr(p, "SecurePublicCertName", c->SecurePublicCertName, sizeof(c->SecurePublicCertName));
PackGetStr(p, "SecurePrivateKeyName", c->SecurePrivateKeyName, sizeof(c->SecurePrivateKeyName));
break;
case CLIENT_AUTHTYPE_OPENSSLENGINE:
b = PackGetBuf(p, "ClientX");
if (b != NULL)
{
c->ClientX = BufToX(b, false);
FreeBuf(b);
}
PackGetStr(p, "OpensslEnginePrivateKeyName", c->OpensslEnginePrivateKeyName, sizeof(c->OpensslEnginePrivateKeyName));
PackGetStr(p, "OpensslEngineName", c->OpensslEngineName, sizeof(c->OpensslEngineName));
break;
}
}
void OutRpcClientAuth(PACK *p, CLIENT_AUTH *c)
@ -4773,6 +4783,17 @@ void OutRpcClientAuth(PACK *p, CLIENT_AUTH *c)
PackAddStr(p, "SecurePublicCertName", c->SecurePublicCertName);
PackAddStr(p, "SecurePrivateKeyName", c->SecurePrivateKeyName);
break;
case CLIENT_AUTHTYPE_OPENSSLENGINE:
b = XToBuf(c->ClientX, false);
if (b != NULL)
{
PackAddBuf(p, "ClientX", b);
FreeBuf(b);
}
PackAddStr(p, "OpensslEnginePrivateKeyName", c->OpensslEnginePrivateKeyName);
PackAddStr(p, "OpensslEngineName", c->OpensslEngineName);
break;
}
}
@ -6769,6 +6790,10 @@ bool CtConnect(CLIENT *c, RPC_CLIENT_CONNECT *connect)
// Register a procedure for secure device authentication
r->ClientAuth->SecureSignProc = CiSecureSignProc;
}
else if (r->ClientAuth->AuthType == CLIENT_AUTHTYPE_OPENSSLENGINE)
{
r->ClientAuth->SecureSignProc = NULL;
}
else
{
r->ClientAuth->SecureSignProc = NULL;
@ -9575,6 +9600,20 @@ CLIENT_AUTH *CiLoadClientAuth(FOLDER *f)
CfgGetStr(f, "SecurePublicCertName", a->SecurePublicCertName, sizeof(a->SecurePublicCertName));
CfgGetStr(f, "SecurePrivateKeyName", a->SecurePrivateKeyName, sizeof(a->SecurePrivateKeyName));
break;
case CLIENT_AUTHTYPE_OPENSSLENGINE:
b = CfgGetBuf(f, "ClientCert");
if (b != NULL)
{
a->ClientX = BufToX(b, false);
}
FreeBuf(b);
if (CfgGetStr(f, "OpensslEnginePrivateKeyName", a->OpensslEnginePrivateKeyName, sizeof(a->OpensslEnginePrivateKeyName)))
{
a->ClientK = OpensslEngineToK(a->OpensslEnginePrivateKeyName, a->OpensslEngineName);
}
CfgGetStr(f, "OpensslEngineName", a->OpensslEngineName, sizeof(a->OpensslEngineName));
break;
}
return a;
@ -10118,6 +10157,16 @@ void CiWriteClientAuth(FOLDER *f, CLIENT_AUTH *a)
CfgAddStr(f, "SecurePublicCertName", a->SecurePublicCertName);
CfgAddStr(f, "SecurePrivateKeyName", a->SecurePrivateKeyName);
break;
case CLIENT_AUTHTYPE_OPENSSLENGINE:
if (a->ClientX != NULL) {
b = XToBuf(a->ClientX, false);
CfgAddByte(f, "ClientCert", b->Buf, b->Size);
FreeBuf(b);
}
CfgAddStr(f, "OpensslEnginePrivateKeyName", a->OpensslEnginePrivateKeyName);
CfgAddStr(f, "OpensslEngineName", a->OpensslEngineName);
break;
}
}

View File

@ -98,7 +98,6 @@
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// Client.h
// Header of Client.c

View File

@ -1,24 +1,5 @@
// SoftEther VPN Source Code - Stable Edition Repository
// Cedar Communication Module
//
// SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
//
// Copyright (c) Daiyuu Nobori.
// Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
// Copyright (c) SoftEther Corporation.
// Copyright (c) all contributors on SoftEther VPN project in GitHub.
//
// All Rights Reserved.
//
// http://www.softether.org/
//
// This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
// Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
//
// License: The Apache License, Version 2.0
// https://www.apache.org/licenses/LICENSE-2.0
//
// DISCLAIMER
// ==========
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
@ -98,7 +79,6 @@
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// Command.c
// vpncmd Command Line Management Utility
@ -3114,6 +3094,7 @@ void PcMain(PC *pc)
{"AccountStatusShow", PcAccountStatusShow},
{"AccountStatusHide", PcAccountStatusHide},
{"AccountSecureCertSet", PcAccountSecureCertSet},
{"AccountOpensslEngineCertSet", PcAccountOpensslEngineCertSet},
{"AccountRetrySet", PcAccountRetrySet},
{"AccountStartupSet", PcAccountStartupSet},
{"AccountStartupRemove", PcAccountStartupRemove},
@ -4870,7 +4851,7 @@ UINT PcAccountCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
if (ret == ERR_NO_ERROR)
{
if (t.ClientAuth->AuthType != CLIENT_AUTHTYPE_CERT)
if (t.ClientAuth->AuthType != CLIENT_AUTHTYPE_CERT && t.ClientAuth->AuthType != CLIENT_AUTHTYPE_OPENSSLENGINE)
{
c->Write(c, _UU("CMD_CascadeCertSet_Not_Auth_Cert"));
ret = ERR_INTERNAL_ERROR;
@ -6143,6 +6124,76 @@ UINT PcAccountSecureCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *para
return ret;
}
UINT PcAccountOpensslEngineCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
LIST *o;
PC *pc = (PC *)param;
UINT ret = ERR_NO_ERROR;
RPC_CLIENT_GET_ACCOUNT t;
// Parameter list that can be specified
PARAM args[] =
{
{"[name]", CmdPrompt, _UU("CMD_AccountCreate_Prompt_Name"), CmdEvalNotEmpty, NULL},
{"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},
{"KEYNAME", CmdPrompt, _UU("CMD_AccountOpensslCertSet_PROMPT_KEYNAME"), CmdEvalNotEmpty, NULL},
{"ENGINENAME", CmdPrompt, _UU("CMD_AccountOpensslCertSet_PROMPT_ENGINENAME"), CmdEvalNotEmpty, NULL},
};
// Get the parameter list
o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
if (o == NULL)
{
return ERR_INVALID_PARAMETER;
}
// RPC call
Zero(&t, sizeof(t));
UniStrCpy(t.AccountName, sizeof(t.AccountName), GetParamUniStr(o, "[name]"));
ret = CcGetAccount(pc->RemoteClient, &t);
if (ret == ERR_NO_ERROR)
{
RPC_CLIENT_CREATE_ACCOUNT z;
t.ClientAuth->AuthType = CLIENT_AUTHTYPE_OPENSSLENGINE;
X *x;
x = FileToXW(GetParamUniStr(o, "LOADCERT"));
if (x == NULL)
{
c->Write(c, _UU("CMD_LOADCERT_FAILED"));
}
StrCpy(t.ClientAuth->OpensslEnginePrivateKeyName, sizeof(t.ClientAuth->OpensslEnginePrivateKeyName),
GetParamStr(o, "KEYNAME"));
StrCpy(t.ClientAuth->OpensslEngineName, sizeof(t.ClientAuth->OpensslEngineName),
GetParamStr(o, "ENGINENAME"));
t.ClientAuth->ClientX = CloneX(x);
Zero(&z, sizeof(z));
z.CheckServerCert = t.CheckServerCert;
z.RetryOnServerCert = t.RetryOnServerCert;
z.ClientAuth = t.ClientAuth;
z.ClientOption = t.ClientOption;
z.ServerCert = t.ServerCert;
z.StartupAccount = t.StartupAccount;
ret = CcSetAccount(pc->RemoteClient, &z);
}
if (ret != ERR_NO_ERROR)
{
// Error has occurred
CmdPrintError(c, ret);
}
CiFreeClientGetAccount(&t);
// Release of the parameter list
FreeParamValueList(o);
return ret;
}
// Set the retry interval and number of retries when disconnect or connection failure of connection settings
UINT PcAccountRetrySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
@ -7082,6 +7133,7 @@ void PsMain(PS *ps)
{"ServerCertGet", PsServerCertGet},
{"ServerKeyGet", PsServerKeyGet},
{"ServerCertSet", PsServerCertSet},
{"ServerOpenSslEngineCertSet", PsServerOpensslEngineCertSet},
{"ServerCipherGet", PsServerCipherGet},
{"ServerCipherSet", PsServerCipherSet},
{"KeepEnable", PsKeepEnable},
@ -8144,6 +8196,21 @@ bool CmdLoadCertAndKey(CONSOLE *c, X **xx, K **kk, wchar_t *cert_filename, wchar
return true;
}
bool CmdLoadOpensslEngineCert(CONSOLE *c, X **xx, wchar_t *cert_filename)
{
X *x;
x = FileToXW(cert_filename);
if (x == NULL)
{
c->Write(c, _UU("CMD_LOADCERT_FAILED"));
return false;
}
*xx = x;
return true;
}
// Read the secret key
K *CmdLoadKey(CONSOLE *c, wchar_t *filename)
{
@ -8257,6 +8324,69 @@ UINT PsServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
return ret;
}
// Set the SSL certificate and the private key of the VPN Server
UINT PsServerOpensslEngineCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
LIST *o;
PS *ps = (PS *)param;
UINT ret = 0;
RPC_OPENSSL_ENGINE_KEY_PAIR t;
// Parameter list that can be specified
PARAM args[] =
{
// "name", prompt_proc, prompt_param, eval_proc, eval_param
{"LOADCERT", CmdPrompt, _UU("CMD_LOADCERTPATH"), CmdEvalIsFile, NULL},
{"KEYNAME", CmdPrompt, _UU("CMD_AccountOpensslCertSet_PROMPT_KEYNAME"), CmdEvalNotEmpty, NULL},
{"ENGINENAME", CmdPrompt, _UU("CMD_AccountOpensslCertSet_PROMPT_ENGINENAME"), CmdEvalNotEmpty, NULL},
};
o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
if (o == NULL)
{
return ERR_INVALID_PARAMETER;
}
Zero(&t, sizeof(t));
if (CmdLoadOpensslEngineCert(c, &t.Cert,
GetParamUniStr(o, "LOADCERT")))
{
wchar_t * engine_name = GetParamStr(o, "ENGINENAME");
StrCpy(t.EngineName, sizeof(t.EngineName), engine_name);
wchar_t * key_name = GetParamStr(o, "KEYNAME");
StrCpy(t.KeyName, sizeof(t.KeyName), key_name);
// RPC call
ret = ScSetServerOpensslEngineCert(ps->Rpc, &t);
if (ret != ERR_NO_ERROR)
{
// An error has occured
CmdPrintError(c, ret);
FreeParamValueList(o);
return ret;
}
if (t.Flag1 == 0)
{
// Show the warning message
c->Write(c, L"");
c->Write(c, _UU("SM_CERT_NEED_ROOT"));
c->Write(c, L"");
}
FreeRpcOpensslEngineKeyPair(&t);
}
else
{
ret = ERR_INTERNAL_ERROR;
}
FreeParamValueList(o);
return ret;
}
// Get the encryption algorithm used for the VPN communication
UINT PsServerCipherGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{

View File

@ -98,7 +98,6 @@
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// Command.h
// Header of Command.c
@ -332,6 +331,7 @@ bool CmdEvalPortList(CONSOLE *c, wchar_t *str, void *param);
wchar_t *PsClusterSettingMemberPromptPorts(CONSOLE *c, void *param);
K *CmdLoadKey(CONSOLE *c, wchar_t *filename);
bool CmdLoadCertAndKey(CONSOLE *c, X **xx, K **kk, wchar_t *cert_filename, wchar_t *key_filename);
bool CmdLoadOpensslEngineCert(CONSOLE *c, X **xx, wchar_t *cert_filename);
bool CmdEvalTcpOrUdp(CONSOLE *c, wchar_t *str, void *param);
wchar_t *GetConnectionTypeStr(UINT type);
bool CmdEvalHostAndSubnetMask4(CONSOLE *c, wchar_t *str, void *param);
@ -466,6 +466,7 @@ UINT PcAccountNicSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PcAccountStatusShow(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PcAccountStatusHide(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PcAccountSecureCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PcAccountOpensslEngineCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PcAccountRetrySet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PcAccountStartupSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PcAccountStartupRemove(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
@ -506,6 +507,7 @@ UINT PsDebug(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsServerCertGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsServerKeyGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsServerOpensslEngineCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsServerCipherGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsServerCipherSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsKeepEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);

View File

@ -98,7 +98,6 @@
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// Connection.c
// Connection Manager
@ -636,6 +635,14 @@ CLIENT_AUTH *CopyClientAuth(CLIENT_AUTH *a)
StrCpy(ret->SecurePublicCertName, sizeof(ret->SecurePublicCertName), a->SecurePublicCertName);
StrCpy(ret->SecurePrivateKeyName, sizeof(ret->SecurePrivateKeyName), a->SecurePrivateKeyName);
break;
case CLIENT_AUTHTYPE_OPENSSLENGINE:
// Secure device authentication
ret->ClientX = CloneX(a->ClientX);
StrCpy(ret->OpensslEnginePrivateKeyName, sizeof(ret->OpensslEnginePrivateKeyName), a->OpensslEnginePrivateKeyName);
StrCpy(ret->OpensslEngineName, sizeof(ret->OpensslEngineName), a->OpensslEngineName);
ret->ClientK = OpensslEngineToK(ret->OpensslEnginePrivateKeyName, ret->OpensslEngineName);
break;
}
return ret;
@ -3139,9 +3146,13 @@ void ConnectionAccept(CONNECTION *c)
{
SetWantToUseCipher(s, c->Cedar->CipherList);
}
x = CloneXFast(c->Cedar->ServerX);
if (StrCmp(c->Cedar->ServerKeyType, "engine") == 0) {
k = OpensslEngineToK(c->Cedar->ServerEngineKey, c->Cedar->ServerEngineName);
} else {
k = CloneKFast(c->Cedar->ServerK);
k = CloneK(c->Cedar->ServerK);
}
}
Unlock(c->Cedar->lock);

View File

@ -98,7 +98,6 @@
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// Connection.h
// Header of Connection.c
@ -196,6 +195,8 @@ struct CLIENT_AUTH
K *ClientK; // Client private key
char SecurePublicCertName[MAX_SECURE_DEVICE_FILE_LEN + 1]; // Secure device certificate name
char SecurePrivateKeyName[MAX_SECURE_DEVICE_FILE_LEN + 1]; // Secure device secret key name
char OpensslEnginePrivateKeyName[MAX_SECURE_DEVICE_FILE_LEN + 1]; // Secure device secret key name
char OpensslEngineName[MAX_SECURE_DEVICE_FILE_LEN + 1]; // Secure device secret key name
CHECK_CERT_PROC *CheckCertProc; // Server certificate confirmation procedure
SECURE_SIGN_PROC *SecureSignProc; // Security signing procedure
};

View File

@ -98,7 +98,6 @@
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// Link.c
// Inter-HUB Link
@ -719,7 +718,7 @@ LINK *NewLink(CEDAR *cedar, HUB *hub, CLIENT_OPTION *option, CLIENT_AUTH *auth,
// Limitation of authentication method
if (auth->AuthType != CLIENT_AUTHTYPE_ANONYMOUS && auth->AuthType != CLIENT_AUTHTYPE_PASSWORD &&
auth->AuthType != CLIENT_AUTHTYPE_PLAIN_PASSWORD && auth->AuthType != CLIENT_AUTHTYPE_CERT)
auth->AuthType != CLIENT_AUTHTYPE_PLAIN_PASSWORD && auth->AuthType != CLIENT_AUTHTYPE_CERT && auth->AuthType != CLIENT_AUTHTYPE_OPENSSLENGINE)
{
// Authentication method other than anonymous authentication, password authentication, plain password, certificate authentication cannot be used
return NULL;

View File

@ -1,24 +1,5 @@
// SoftEther VPN Source Code - Stable Edition Repository
// Cedar Communication Module
//
// SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
//
// Copyright (c) Daiyuu Nobori.
// Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
// Copyright (c) SoftEther Corporation.
// Copyright (c) all contributors on SoftEther VPN project in GitHub.
//
// All Rights Reserved.
//
// http://www.softether.org/
//
// This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
// Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
//
// License: The Apache License, Version 2.0
// https://www.apache.org/licenses/LICENSE-2.0
//
// DISCLAIMER
// ==========
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
@ -98,7 +79,6 @@
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// Protocol.c
// SoftEther protocol related routines
@ -6859,6 +6839,20 @@ bool ClientUploadAuth(CONNECTION *c)
}
break;
case CLIENT_AUTHTYPE_OPENSSLENGINE:
// Certificate authentication
if (a->ClientX != NULL && a->ClientX->is_compatible_bit &&
a->ClientX->bits != 0 && (a->ClientX->bits / 8) <= sizeof(sign))
{
if (RsaSignEx(sign, c->Random, SHA1_SIZE, a->ClientK, a->ClientX->bits))
{
p = PackLoginWithCert(o->HubName, a->Username, a->ClientX, sign, a->ClientX->bits / 8);
c->ClientX = CloneX(a->ClientX);
}
}
break;
case CLIENT_AUTHTYPE_SECURE:
// Authentication by secure device
if (ClientSecureSign(c, sign, c->Random, &x))

View File

@ -4328,7 +4328,6 @@ void SiWriteUserCfg(FOLDER *f, USER *u)
FreeBuf(b);
}
break;
case AUTHTYPE_ROOTCERT:
rootcert = (AUTHROOTCERT *)u->AuthData;
if (rootcert->Serial != NULL && rootcert->Serial->size >= 1)
@ -6062,27 +6061,53 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
}
// Server private key
b = CfgGetBuf(f, "ServerKey");
if (b != NULL)
{
k = BufToK(b, true, false, NULL);
FreeBuf(b);
bool engine_cert;
if (CfgGetStr(f, "ServerKeyType", tmp, sizeof(tmp))) {
if (StrCmp(tmp, "engine") == 0) {
engine_cert = true;
} else {
engine_cert = false;
}
} else {
engine_cert = false;
}
if (!engine_cert) {
b = CfgGetBuf(f, "ServerKey");
if (b != NULL)
{
k = BufToK(b, true, false, NULL);
FreeBuf(b);
if (x == NULL || k == NULL || CheckXandK(x, k) == false)
{
FreeX(x);
FreeK(k);
SiGenerateDefaultCert(&x, &k);
if (x == NULL || k == NULL || CheckXandK(x, k) == false)
{
FreeX(x);
FreeK(k);
SiGenerateDefaultCert(&x, &k);
SetCedarCert(c, x, k);
SetCedarCert(c, x, k);
FreeX(x);
FreeK(k);
}
else
{
SetCedarCert(c, x, k);
FreeX(x);
FreeK(k);
}
else
{
SetCedarCert(c, x, k);
FreeX(x);
FreeK(k);
}
}
} else {
if (CfgGetStr(f, "ServerEngineName", tmp, sizeof(tmp))) {
//TODO error handling
c->ServerEngineName = CopyStr(tmp);
}
if (CfgGetStr(f, "ServerEngineKey", tmp, sizeof(tmp))) {
// TODO error handling
c->ServerEngineKey = CopyStr(tmp);
}
k = OpensslEngineToK(c->ServerEngineKey, c->ServerEngineName);
SetCedarEngineCert(c, x, k, c->ServerEngineName, c->ServerEngineKey);
FreeX(x);
FreeK(k);
@ -6459,18 +6484,26 @@ void SiWriteServerCfg(FOLDER *f, SERVER *s)
// Let the client not to send a signature
CfgAddBool(f, "NoSendSignature", s->NoSendSignature);
if (is_vgs_cert == false)
{
// Server certificate
b = XToBuf(c->ServerX, false);
CfgAddBuf(f, "ServerCert", b);
FreeBuf(b);
// Server private key
b = KToBuf(c->ServerK, false, NULL);
CfgAddBuf(f, "ServerKey", b);
FreeBuf(b);
if (StrCmp(c->ServerKeyType, "engine") == 0) {
CfgAddStr(f, "ServerKeyType", "engine");
CfgAddStr(f, "ServerEngineKey", c->ServerEngineKey);
CfgAddStr(f, "ServerEngineName", c->ServerEngineName);
b = XToBuf(c->ServerX, false);
CfgAddBuf(f, "ServerCert", b);
FreeBuf(b);
} else {
CfgAddStr(f, "ServerKeyType", "x509");
// Server certificate
b = XToBuf(c->ServerX, false);
CfgAddBuf(f, "ServerCert", b);
FreeBuf(b);
b = KToBuf(c->ServerK, false, NULL);
CfgAddBuf(f, "ServerKey", b);
FreeBuf(b);
}
}
// Traffic information

View File

@ -98,7 +98,6 @@
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// Session.c
// Session Manager
@ -2046,10 +2045,17 @@ SESSION *NewClientSessionEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *au
{
s->ClientAuth->ClientX = CloneX(s->ClientAuth->ClientX);
}
if (s->ClientAuth->ClientK != NULL)
{
s->ClientAuth->ClientK = CloneK(s->ClientAuth->ClientK);
}
if (s->ClientAuth->ClientK != NULL)
{
if (s->ClientAuth->AuthType != CLIENT_AUTHTYPE_OPENSSLENGINE)
{
s->ClientAuth->ClientK = CloneK(s->ClientAuth->ClientK);
}
else
{
s->ClientAuth->ClientK = OpensslEngineToK(s->ClientAuth->OpensslEnginePrivateKeyName, s->ClientAuth->OpensslEngineName);
}
}
if (StrCmpi(s->ClientOption->DeviceName, LINK_DEVICE_NAME) == 0)
{

View File

@ -98,7 +98,6 @@
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// Encrypt.c
// Encryption and digital certification routine
@ -4395,6 +4394,22 @@ bool IsEncryptedK(BUF *b, bool private_key)
return true;
}
K *OpensslEngineToK(char *key_file_name, char *engine_name)
{
K *k;
#if OPENSSL_API_COMPAT < 0x10100000L
ENGINE_load_dynamic();
#endif // OPENSSL_API_COMPAT < 0x10100000L
ENGINE *engine = ENGINE_by_id(engine_name);
ENGINE_init(engine);
EVP_PKEY *pkey;
pkey = ENGINE_load_private_key(engine, key_file_name, NULL, NULL);
k = ZeroMalloc(sizeof(K));
k->pkey = pkey;
k->private_key = true;
return k;
}
// Convert the BUF to a K
K *BufToK(BUF *b, bool private_key, bool text, char *password)
{

View File

@ -98,7 +98,6 @@
// The memory-leaks and resource-leaks verification under the stress
// test has been passed before release this source code.
// Encrypt.h
// Header of Encrypt.c
@ -457,6 +456,7 @@ K *BioToK(BIO *bio, bool private_key, bool text, char *password);
int PKeyPasswordCallbackFunction(char *buf, int bufsize, int verify, void *param);
void FreePKey(EVP_PKEY *pkey);
void FreeK(K *k);
K *OpensslEngineToK(char *key_file_name, char *engine_name);
K *BufToK(BUF *b, bool private_key, bool text, char *password);
bool IsEncryptedK(BUF *b, bool private_key);
bool IsBase64(BUF *b);

View File

@ -14039,7 +14039,6 @@ bool StartSSLWithSettings(SOCK* sock, UINT ssl_timeout, char* sni_hostname, SSL_
LockOpenSSL();
{
sock->ssl = SSL_new(ssl_ctx_shared->SslCtx);
SSL_set_fd(sock->ssl, (int)sock->socket);
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if (settings->Settings2.IsClient)

View File

@ -400,6 +400,7 @@ PW_TYPE_1 标准密码验证
PW_TYPE_2 RADIUS 或 NT 域验证
PW_TYPE_3 客户端证书认证
PW_TYPE_4 智能卡身份验证
PW_TYPE_5 Openssl Engine Authentication
PW_MSG_PROXY 代理服务器 %S 用户身份验证失败。请重新输入正确的用户名和密码。
PW_TYPE_PROXY 代理服务器认证
@ -6755,6 +6756,11 @@ CMD_AccountSecureCertSet_PROMPT_CERTNAME 智能卡证书对象名:
CMD_AccountSecureCertSet_PROMPT_KEYNAME 智能卡私匙对象名:
# PcAccountOpensslEngineCertSet
CMD_AccountOpensslCertSet_PROMPT_KEYNAME Specify the openssl engine specific key name:
CMD_AccountOpensslCertSet_PROMPT_ENGINENAME Specify the openssl engine name:
# AccountRetrySet 命令
CMD_AccountRetrySet 设置连接设置的连接失败或断开时建立重新连接的次数和间隔
CMD_AccountRetrySet_Help 指定注册到 VPN Client 的连接设置,且其连接设置试图连接到 VPN Server 时,还有连接中的与 VPN Server 的通信被断开或连接失败时,指定连接的重试次数和连接重试的间隔。\n而且如果用户认证类型为 [智能卡认证] 时,不管连接重试次数如何设置,都将不进行连接重试。

View File

@ -397,6 +397,7 @@ PW_TYPE_1 Standard Password Authentication
PW_TYPE_2 RADIUS or NT Domain Authentication
PW_TYPE_3 Client Certificate Authentication
PW_TYPE_4 Smart Card Authentication
PW_TYPE_5 Openssl Engine Authentication
PW_MSG_PROXY User authentication failed on the proxy server %S. Re-enter the correct user name and password.
PW_TYPE_PROXY Proxy Server Authentication
@ -6741,6 +6742,11 @@ CMD_AccountSecureCertSet_PROMPT_CERTNAME Name of Certificate Object on Smart Car
CMD_AccountSecureCertSet_PROMPT_KEYNAME Name of Private Key Object on Smart Card:
# PcAccountOpensslEngineCertSet
CMD_AccountOpensslCertSet_PROMPT_KEYNAME Specify the openssl engine specific key name:
CMD_AccountOpensslCertSet_PROMPT_ENGINENAME Specify the openssl engine name:
# AccountRetrySet コマンド
CMD_AccountRetrySet Set Interval between Connection Retries for Connection Failures or Disconnections of VPN Connection Setting
CMD_AccountRetrySet_Help When a VPN Connection Setting registered on the VPN Client is specified and that VPN Connection Setting attempts to connect to a VPN Server, use this to specify the interval to wait between connection attempts and the limit of how many times to retry connecting when communication with the VPN Server has been disconnected or when the connection process failed. \nIf the user authentication type is Smart Card Authentication, no connection retry will be performed regardless of the Number of Connection Attempts setting.

View File

@ -399,6 +399,7 @@ PW_TYPE_1 標準パスワード認証
PW_TYPE_2 RADIUS または NT ドメイン認証
PW_TYPE_3 クライアント証明書認証
PW_TYPE_4 スマートカード認証
PW_TYPE_5 Openssl Engine Authentication
PW_MSG_PROXY プロキシサーバー %S でのユーザー認証に失敗しました。正しいユーザー名とパスワードを再入力してください。
PW_TYPE_PROXY プロキシサーバー認証
@ -6749,6 +6750,11 @@ CMD_AccountSecureCertSet_PROMPT_CERTNAME スマートカード内証明書オブ
CMD_AccountSecureCertSet_PROMPT_KEYNAME スマートカード内秘密鍵オブジェクトの名前:
# PcAccountOpensslEngineCertSet
CMD_AccountOpensslCertSet_PROMPT_KEYNAME Specify the openssl engine specific key name:
CMD_AccountOpensslCertSet_PROMPT_ENGINENAME Specify the openssl engine name:
# AccountRetrySet コマンド
CMD_AccountRetrySet 接続設定の接続失敗または切断時の再試行回数と間隔の設定
CMD_AccountRetrySet_Help VPN Client に登録されている接続設定を指定し、その接続設定が VPN Server に接続しようとする際、または接続中に VPN Server との通信が切断されたり、接続に失敗したりした場合に、接続を再試行する回数と接続再試行間隔を指定します。\nなお、ユーザー認証の種類が [スマートカード認証] の場合は、接続試行回数の設定にかかわらず、再試行は行いません。