1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2026-04-23 15:29:26 +03:00

Support user-specified server trust chain

This commit is contained in:
domosekai
2021-07-21 07:02:42 +00:00
parent 1f40de2dda
commit 2761c1ca42
19 changed files with 437 additions and 16 deletions
+4 -1
View File
@@ -9465,7 +9465,7 @@ UINT StSetServerCert(ADMIN *a, RPC_KEY_PAIR *t)
}
}
SetCedarCert(c, t->Cert, t->Key);
SetCedarCertAndChain(c, t->Cert, t->Key, t->Chain);
ALog(a, NULL, "LA_SET_SERVER_CERT");
@@ -14565,6 +14565,7 @@ void InRpcKeyPair(RPC_KEY_PAIR *t, PACK *p)
}
t->Cert = PackGetX(p, "Cert");
t->Chain = PackGetXList(p, "Chain");
t->Key = PackGetK(p, "Key");
t->Flag1 = PackGetInt(p, "Flag1");
}
@@ -14577,12 +14578,14 @@ void OutRpcKeyPair(PACK *p, RPC_KEY_PAIR *t)
}
PackAddX(p, "Cert", t->Cert);
PackAddXList(p, "Chain", t->Chain);
PackAddK(p, "Key", t->Key);
PackAddInt(p, "Flag1", t->Flag1);
}
void FreeRpcKeyPair(RPC_KEY_PAIR *t)
{
FreeX(t->Cert);
FreeXList(t->Chain);
FreeK(t->Key);
}
+1
View File
@@ -230,6 +230,7 @@ struct RPC_FARM_CONNECTION_STATUS
struct RPC_KEY_PAIR
{
X *Cert; // Certificate
LIST *Chain; // Trust chain
K *Key; // Secret key
UINT Flag1; // Flag1
};
+48 -4
View File
@@ -8463,6 +8463,11 @@ bool CmLoadKExW(HWND hWnd, K **k, wchar_t *filename, UINT size)
// Read a set of certificate and private key
bool CmLoadXAndK(HWND hWnd, X **x, K **k)
{
return CmLoadXListAndK(hWnd, x, k, NULL);
}
// Read a set of certificate and private key and trust chain
bool CmLoadXListAndK(HWND hWnd, X **x, K **k, LIST **cc)
{
wchar_t *s;
bool is_p12;
@@ -8510,7 +8515,7 @@ START_FIRST:
}
if (IsEncryptedP12(p12) == false)
{
if (ParseP12(p12, x, k, NULL) == false)
if (ParseP12Ex(p12, x, k, cc, NULL) == false)
{
MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
FreeP12(p12);
@@ -8529,7 +8534,7 @@ START_FIRST:
}
else
{
if (ParseP12(p12, x, k, password) == false)
if (ParseP12Ex(p12, x, k, cc, password) == false)
{
MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_P12_W"), tmp);
FreeP12(p12);
@@ -8542,6 +8547,10 @@ START_FIRST:
{
FreeX(*x);
FreeK(*k);
if (cc != NULL)
{
FreeXList(*cc);
}
FreeP12(p12);
FreeBuf(b);
if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("DLG_BAD_SIGNATURE")) == IDRETRY)
@@ -8550,6 +8559,11 @@ START_FIRST:
}
return false;
}
if (cc != NULL && LIST_NUM(*cc) == 0)
{
ReleaseList(*cc);
*cc = NULL;
}
FreeP12(p12);
FreeBuf(b);
return true;
@@ -8558,19 +8572,40 @@ START_FIRST:
{
// Processing of X509
BUF *b = ReadDumpW(tmp);
X *x509;
X *x509 = NULL;
K *key;
LIST *chain = NULL;
if (b == NULL)
{
MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
return false;
}
x509 = BufToX(b, IsBase64(b));
// DER-encoded X509 files can't hold multiple certificates
if (cc == NULL || IsBase64(b) == false)
{
x509 = BufToX(b, IsBase64(b));
}
else
{
chain = BufToXList(b, true);
if (LIST_NUM(chain) > 0)
{
x509 = LIST_DATA(chain, 0);
Delete(chain, x509);
if (LIST_NUM(chain) == 0)
{
ReleaseList(chain);
chain = NULL;
}
}
}
FreeBuf(b);
if (x509 == NULL)
{
MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_X509_W"), tmp);
FreeXList(chain);
return false;
}
@@ -8579,6 +8614,7 @@ START_FIRST:
if (s == NULL)
{
FreeX(x509);
FreeXList(chain);
return false;
}
UniStrCpy(tmp, sizeof(tmp), s);
@@ -8589,6 +8625,7 @@ START_FIRST:
{
MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_OPEN_FILE_ERROR_W"), tmp);
FreeX(x509);
FreeXList(chain);
return false;
}
@@ -8603,6 +8640,7 @@ START_FIRST:
{
FreeBuf(b);
FreeX(x509);
FreeXList(chain);
return false;
}
key = BufToK(b, true, IsBase64(b), pass);
@@ -8612,6 +8650,7 @@ START_FIRST:
{
FreeBuf(b);
FreeX(x509);
FreeXList(chain);
MsgBoxEx(hWnd, MB_ICONSTOP, _UU("DLG_BAD_KEY_W"), tmp);
return false;
}
@@ -8621,6 +8660,7 @@ START_FIRST:
FreeBuf(b);
FreeX(x509);
FreeK(key);
FreeXList(chain);
if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _UU("DLG_BAD_SIGNATURE")) == IDRETRY)
{
goto START_FIRST;
@@ -8631,6 +8671,10 @@ START_FIRST:
FreeBuf(b);
*x = x509;
*k = key;
if (cc != NULL)
{
*cc = chain;
}
return true;
}
}
+1
View File
@@ -409,6 +409,7 @@ void CmEditAccountDlgInit(HWND hWnd, CM_ACCOUNT *a);
void CmEditAccountDlgOnOk(HWND hWnd, CM_ACCOUNT *a);
void CmEditAccountDlgStartEnumHub(HWND hWnd, CM_ACCOUNT *a);
bool CmLoadXAndK(HWND hWnd, X **x, K **k);
bool CmLoadXListAndK(HWND hWnd, X **x, K **k, LIST **cc);
bool CmLoadKEx(HWND hWnd, K **k, char *filename, UINT size);
bool CmLoadKExW(HWND hWnd, K **k, wchar_t *filename, UINT size);
bool CmLoadXFromFileOrSecureCard(HWND hWnd, X **x);
+14
View File
@@ -1157,6 +1157,10 @@ void CleanupCedar(CEDAR *c)
{
FreeK(c->ServerK);
}
if (c->ServerChain)
{
FreeXList(c->ServerChain);
}
if (c->CipherList)
{
@@ -1386,6 +1390,10 @@ void FreeNetSvcList(CEDAR *cedar)
// Change certificate of Cedar
void SetCedarCert(CEDAR *c, X *server_x, K *server_k)
{
SetCedarCertAndChain(c, server_x, server_k, NULL);
}
void SetCedarCertAndChain(CEDAR *c, X *server_x, K *server_k, LIST *server_chain)
{
// Validate arguments
if (server_x == NULL || server_k == NULL)
@@ -1405,8 +1413,14 @@ void SetCedarCert(CEDAR *c, X *server_x, K *server_k)
FreeK(c->ServerK);
}
if (c->ServerChain != NULL)
{
FreeXList(c->ServerChain);
}
c->ServerX = CloneX(server_x);
c->ServerK = CloneK(server_k);
c->ServerChain = CloneXList(server_chain);
}
Unlock(c->lock);
}
+2
View File
@@ -930,6 +930,7 @@ struct CEDAR
COUNTER *ConnectionIncrement; // Connection increment counter
X *ServerX; // Server certificate
K *ServerK; // Private key of the server certificate
LIST *ServerChain; // Server trust chain
char UsernameHubSeparator; // Character which separates the username from the hub name
char *CipherList; // List of encryption algorithms
UINT Version; // Version information
@@ -1000,6 +1001,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 SetCedarCertAndChain(CEDAR *c, X *server_x, K *server_k, LIST *server_chain);
void ReleaseCedar(CEDAR *c);
void CleanupCedar(CEDAR *c);
void StopCedar(CEDAR *c);
+42 -3
View File
@@ -8638,18 +8638,51 @@ UINT PsServerKeyGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
// Read the certificate and the private key
bool CmdLoadCertAndKey(CONSOLE *c, X **xx, K **kk, wchar_t *cert_filename, wchar_t *key_filename)
{
X *x;
return CmdLoadCertChainAndKey(c, xx, kk, NULL, cert_filename, key_filename);
}
bool CmdLoadCertChainAndKey(CONSOLE *c, X **xx, K **kk, LIST **cc, wchar_t *cert_filename, wchar_t *key_filename)
{
X *x = NULL;
K *k;
LIST *chain = NULL;
// Validate arguments
if (c == NULL || cert_filename == NULL || key_filename == NULL || xx == NULL || kk == NULL)
{
return false;
}
x = FileToXW(cert_filename);
BUF *b = ReadDumpW(cert_filename);
if (b == NULL)
{
c->Write(c, _UU("CMD_LOADCERT_FAILED"));
return false;
}
// DER-encoded X509 files can't hold multiple certificates
if (cc == NULL || IsBase64(b) == false)
{
x = BufToX(b, IsBase64(b));
}
else
{
chain = BufToXList(b, true);
if (LIST_NUM(chain) > 0)
{
x = LIST_DATA(chain, 0);
Delete(chain, x);
if (LIST_NUM(chain) == 0)
{
ReleaseList(chain);
chain = NULL;
}
}
}
FreeBuf(b);
if (x == NULL)
{
c->Write(c, _UU("CMD_LOADCERT_FAILED"));
FreeXList(chain);
return false;
}
@@ -8658,6 +8691,7 @@ bool CmdLoadCertAndKey(CONSOLE *c, X **xx, K **kk, wchar_t *cert_filename, wchar
{
c->Write(c, _UU("CMD_LOADKEY_FAILED"));
FreeX(x);
FreeXList(chain);
return false;
}
@@ -8666,12 +8700,17 @@ bool CmdLoadCertAndKey(CONSOLE *c, X **xx, K **kk, wchar_t *cert_filename, wchar
c->Write(c, _UU("CMD_KEYPAIR_FAILED"));
FreeX(x);
FreeK(k);
FreeXList(chain);
return false;
}
*xx = x;
*kk = k;
if (cc != NULL)
{
*cc = chain;
}
return true;
}
@@ -8754,7 +8793,7 @@ UINT PsServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
Zero(&t, sizeof(t));
if (CmdLoadCertAndKey(c, &t.Cert, &t.Key,
if (CmdLoadCertChainAndKey(c, &t.Cert, &t.Key, &t.Chain,
GetParamUniStr(o, "LOADCERT"),
GetParamUniStr(o, "LOADKEY")))
{
+1
View File
@@ -236,6 +236,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 CmdLoadCertChainAndKey(CONSOLE *c, X **xx, K **kk, LIST **cc, wchar_t *cert_filename, wchar_t *key_filename);
bool CmdEvalTcpOrUdp(CONSOLE *c, wchar_t *str, void *param);
wchar_t *GetConnectionTypeStr(UINT type);
bool CmdEvalHostAndSubnetMask4(CONSOLE *c, wchar_t *str, void *param);
+5 -1
View File
@@ -2990,6 +2990,7 @@ void ConnectionAccept(CONNECTION *c)
SOCK *s;
X *x;
K *k;
LIST *chain;
char tmp[128];
UINT initial_timeout = CONNECTING_TIMEOUT;
UCHAR ctoken_hash[SHA1_SIZE];
@@ -3040,24 +3041,27 @@ void ConnectionAccept(CONNECTION *c)
x = CloneX(c->Cedar->ServerX);
k = CloneK(c->Cedar->ServerK);
chain = CloneXList(c->Cedar->ServerChain);
}
Unlock(c->Cedar->lock);
// Start the SSL communication
Copy(&s->SslAcceptSettings, &c->Cedar->SslAcceptSettings, sizeof(SSL_ACCEPT_SETTINGS));
if (StartSSL(s, x, k) == false)
if (StartSSLEx2(s, x, k, chain, 0, NULL) == false)
{
// Failed
AddNoSsl(c->Cedar, &s->RemoteIP);
Debug("ConnectionAccept(): StartSSL() failed\n");
FreeX(x);
FreeK(k);
FreeXList(chain);
goto FINAL;
}
FreeX(x);
FreeK(k);
FreeXList(chain);
SLog(c->Cedar, "LS_SSL_START", c->Name, s->CipherName);
+1 -1
View File
@@ -3602,7 +3602,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapTlsSi
if (p->Eap_TlsCtx.SslPipe == NULL)
{
p->Eap_TlsCtx.Dh = DhNewFromBits(DH_PARAM_BITS_DEFAULT);
p->Eap_TlsCtx.SslPipe = NewSslPipeEx(true, p->Cedar->ServerX, p->Cedar->ServerK, p->Eap_TlsCtx.Dh, true, &(p->Eap_TlsCtx.ClientCert));
p->Eap_TlsCtx.SslPipe = NewSslPipeEx2(true, p->Cedar->ServerX, p->Cedar->ServerK, p->Cedar->ServerChain, p->Eap_TlsCtx.Dh, true, &(p->Eap_TlsCtx.ClientCert));
}
// If the current frame is fragmented, or it is a possible last of a fragmented series, bufferize it
+7 -1
View File
@@ -16809,6 +16809,7 @@ void SmSslDlgOnOk(HWND hWnd, SM_SSL *s)
t.Cert = CloneX(s->Cert);
t.Key = CloneK(s->Key);
t.Chain = CloneXList(s->Chain);
if (CALL(hWnd, ScSetServerCert(s->p->Rpc, &t)) == false)
{
@@ -16923,6 +16924,7 @@ void SmSslDlgInit(HWND hWnd, SM_SSL *s)
// Copy the certificate and key
s->Cert = CloneX(t.Cert);
s->Key = CloneK(t.Key);
s->Chain = CloneXList(t.Chain);
if (t.Key != NULL)
{
@@ -17174,6 +17176,7 @@ UINT SmSslDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param
SM_SSL *s = (SM_SSL *)param;
X *x;
K *k;
LIST *chain;
// Validate arguments
if (hWnd == NULL)
{
@@ -17222,16 +17225,18 @@ UINT SmSslDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param
case B_IMPORT:
// Import
if (CmLoadXAndK(hWnd, &x, &k))
if (CmLoadXListAndK(hWnd, &x, &k, &chain))
{
wchar_t tmp[MAX_SIZE];
LABEL_APPLY_NEW_CERT:
FreeX(s->Cert);
FreeK(s->Key);
FreeXList(s->Chain);
s->Cert = x;
s->Key = k;
s->SetCertAndKey = true;
s->Chain = chain;
// Show the Certificate Information
SmGetCertInfoStr(tmp, sizeof(tmp), s->Cert);
SetText(hWnd, S_CERT_INFO, tmp);
@@ -17310,6 +17315,7 @@ void SmSslDlg(HWND hWnd, SM_SERVER *p)
// Cleanup
FreeX(s.Cert);
FreeK(s.Key);
FreeXList(s.Chain);
}
// Listener creation dialog procedure
+1
View File
@@ -112,6 +112,7 @@ typedef struct SM_SSL
SM_SERVER *p; // P
X *Cert; // Certificate
K *Key; // Secret key
LIST *Chain; // Trust chain
bool SetCertAndKey; // Set the key
} SM_SSL;
+17 -1
View File
@@ -5608,6 +5608,7 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
char tmp[MAX_SIZE];
X *x = NULL;
K *k = NULL;
LIST *chain = NewList(NULL);
FOLDER *params_folder;
UINT i;
// Validate arguments
@@ -5847,10 +5848,14 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
FreeBuf(b);
}
// Server trust chain
SiLoadCertList(chain, CfgGetFolder(f, "ServerChain"));
if (x == NULL || k == NULL || CheckXandK(x, k) == false)
{
FreeX(x);
FreeK(k);
FreeXList(chain);
SiGenerateDefaultCert(&x, &k);
SetCedarCert(c, x, k);
@@ -5860,10 +5865,18 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
}
else
{
SetCedarCert(c, x, k);
if (LIST_NUM(chain) == 0)
{
SetCedarCert(c, x, k);
}
else
{
SetCedarCertAndChain(c, x, k, chain);
}
FreeX(x);
FreeK(k);
FreeXList(chain);
}
// Character which separates the username from the hub name
@@ -6246,6 +6259,9 @@ void SiWriteServerCfg(FOLDER *f, SERVER *s)
CfgAddBuf(f, "ServerKey", b);
FreeBuf(b);
// Server trust chain
SiWriteCertList(CfgCreateFolder(f, "ServerChain"), c->ServerChain);
{
// Character which separates the username from the hub name
char str[2];