mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2025-07-06 07:44:57 +03:00
Merge pull request #1433 from domosekai/chain
Support user-specified server trust chain
This commit is contained in:
@ -1079,6 +1079,41 @@ X *CloneX(X *x)
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Clone of certificate chain
|
||||
LIST *CloneXList(LIST *chain)
|
||||
{
|
||||
BUF *b;
|
||||
X *x;
|
||||
LIST *ret;
|
||||
// Validate arguments
|
||||
if (chain == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = NewList(NULL);
|
||||
LockList(chain);
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0;i < LIST_NUM(chain);i++)
|
||||
{
|
||||
x = LIST_DATA(chain, i);
|
||||
b = XToBuf(x, false);
|
||||
if (b == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
x = BufToX(b, false);
|
||||
Add(ret, x);
|
||||
FreeBuf(b);
|
||||
}
|
||||
}
|
||||
UnlockList(chain);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Generate a P12
|
||||
P12 *NewP12(X *x, K *k, char *password)
|
||||
{
|
||||
@ -1133,9 +1168,15 @@ bool IsEncryptedP12(P12 *p12)
|
||||
|
||||
// Extract the X and the K from the P12
|
||||
bool ParseP12(P12 *p12, X **x, K **k, char *password)
|
||||
{
|
||||
return ParseP12Ex(p12, x, k, NULL, password);
|
||||
}
|
||||
// Extract the X, the K and the chain from the P12
|
||||
bool ParseP12Ex(P12 *p12, X **x, K **k, LIST **cc, char *password)
|
||||
{
|
||||
EVP_PKEY *pkey;
|
||||
X509 *x509;
|
||||
STACK_OF(X509) *sk = NULL;
|
||||
// Validate arguments
|
||||
if (p12 == NULL || x == NULL || k == NULL)
|
||||
{
|
||||
@ -1165,9 +1206,9 @@ bool ParseP12(P12 *p12, X **x, K **k, char *password)
|
||||
// Extraction
|
||||
Lock(openssl_lock);
|
||||
{
|
||||
if (PKCS12_parse(p12->pkcs12, password, &pkey, &x509, NULL) == false)
|
||||
if (PKCS12_parse(p12->pkcs12, password, &pkey, &x509, &sk) == false)
|
||||
{
|
||||
if (PKCS12_parse(p12->pkcs12, NULL, &pkey, &x509, NULL) == false)
|
||||
if (PKCS12_parse(p12->pkcs12, NULL, &pkey, &x509, &sk) == false)
|
||||
{
|
||||
Unlock(openssl_lock);
|
||||
return false;
|
||||
@ -1182,6 +1223,7 @@ bool ParseP12(P12 *p12, X **x, K **k, char *password)
|
||||
if (*x == NULL)
|
||||
{
|
||||
FreePKey(pkey);
|
||||
sk_X509_free(sk);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1189,6 +1231,37 @@ bool ParseP12(P12 *p12, X **x, K **k, char *password)
|
||||
(*k)->private_key = true;
|
||||
(*k)->pkey = pkey;
|
||||
|
||||
if (sk == NULL || cc == NULL)
|
||||
{
|
||||
if (cc != NULL)
|
||||
{
|
||||
*cc = NULL;
|
||||
}
|
||||
if (sk != NULL)
|
||||
{
|
||||
sk_X509_free(sk);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
LIST *chain = NewList(NULL);
|
||||
X *x1;
|
||||
while (sk_X509_num(sk)) {
|
||||
x509 = sk_X509_shift(sk);
|
||||
x1 = X509ToX(x509);
|
||||
if (x1 != NULL)
|
||||
{
|
||||
Add(chain, x1);
|
||||
}
|
||||
else
|
||||
{
|
||||
X509_free(x509);
|
||||
}
|
||||
}
|
||||
sk_X509_free(sk);
|
||||
|
||||
*cc = chain;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3369,6 +3442,29 @@ void FreeX(X *x)
|
||||
Free(x);
|
||||
}
|
||||
|
||||
// Release of an X chain
|
||||
void FreeXList(LIST *chain)
|
||||
{
|
||||
// Validate arguments
|
||||
if (chain == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
LockList(chain);
|
||||
{
|
||||
UINT i;
|
||||
for (i = 0; i < LIST_NUM(chain); i++)
|
||||
{
|
||||
X *x = LIST_DATA(chain, i);
|
||||
FreeX(x);
|
||||
}
|
||||
}
|
||||
UnlockList(chain);
|
||||
|
||||
ReleaseList(chain);
|
||||
}
|
||||
|
||||
// Release of the X509
|
||||
void FreeX509(X509 *x509)
|
||||
{
|
||||
@ -3410,6 +3506,31 @@ X *BufToX(BUF *b, bool text)
|
||||
return x;
|
||||
}
|
||||
|
||||
// Convert the BUF to X chain
|
||||
LIST *BufToXList(BUF *b, bool text)
|
||||
{
|
||||
LIST *chain;
|
||||
BIO *bio;
|
||||
// Validate arguments
|
||||
if (b == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bio = BufToBio(b);
|
||||
if (bio == NULL)
|
||||
{
|
||||
FreeBuf(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chain = BioToXList(bio, text);
|
||||
|
||||
FreeBio(bio);
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
// Get a digest of the X
|
||||
void GetXDigest(X *x, UCHAR *buf, bool sha1)
|
||||
{
|
||||
@ -3473,6 +3594,49 @@ X *BioToX(BIO *bio, bool text)
|
||||
return x;
|
||||
}
|
||||
|
||||
// Convert BIO to X chain
|
||||
LIST *BioToXList(BIO *bio, bool text)
|
||||
{
|
||||
X *x;
|
||||
STACK_OF(X509_INFO) *sk = NULL;
|
||||
X509_INFO *xi;
|
||||
LIST *chain;
|
||||
|
||||
// Validate arguments
|
||||
if (bio == NULL || text == false)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Lock(openssl_lock);
|
||||
{
|
||||
sk = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL);
|
||||
if (sk == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chain = NewList(NULL);
|
||||
|
||||
while (sk_X509_INFO_num(sk))
|
||||
{
|
||||
xi = sk_X509_INFO_shift(sk);
|
||||
x = X509ToX(xi->x509);
|
||||
if (x != NULL)
|
||||
{
|
||||
Add(chain, x);
|
||||
xi->x509 = NULL;
|
||||
}
|
||||
X509_INFO_free(xi);
|
||||
}
|
||||
|
||||
sk_X509_INFO_free(sk);
|
||||
}
|
||||
Unlock(openssl_lock);
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
// Convert the X509 to X
|
||||
X *X509ToX(X509 *x509)
|
||||
{
|
||||
|
@ -293,9 +293,12 @@ BUF *BioToBuf(BIO *bio);
|
||||
BIO *NewBio();
|
||||
void FreeBio(BIO *bio);
|
||||
X *BioToX(BIO *bio, bool text);
|
||||
LIST *BioToXList(BIO *bio, bool text);
|
||||
X *BufToX(BUF *b, bool text);
|
||||
LIST *BufToXList(BUF *b, bool text);
|
||||
void FreeX509(X509 *x509);
|
||||
void FreeX(X *x);
|
||||
void FreeXList(LIST *chain);
|
||||
BIO *XToBio(X *x, bool text);
|
||||
BUF *XToBuf(X *x, bool text);
|
||||
K *BioToK(BIO *bio, bool private_key, bool text, char *password);
|
||||
@ -357,9 +360,11 @@ void FreePKCS12(PKCS12 *pkcs12);
|
||||
void FreeP12(P12 *p12);
|
||||
bool P12ToFileW(P12 *p12, wchar_t *filename);
|
||||
bool ParseP12(P12 *p12, X **x, K **k, char *password);
|
||||
bool ParseP12Ex(P12 *p12, X **x, K **k, LIST **cc, char *password);
|
||||
bool IsEncryptedP12(P12 *p12);
|
||||
P12 *NewP12(X *x, K *k, char *password);
|
||||
X *CloneX(X *x);
|
||||
LIST *CloneXList(LIST *chain);
|
||||
K *CloneK(K *k);
|
||||
void FreeCryptLibrary();
|
||||
void GetPrintNameFromX(wchar_t *str, UINT size, X *x);
|
||||
|
@ -5702,6 +5702,10 @@ SSL_PIPE *NewSslPipe(bool server_mode, X *x, K *k, DH_CTX *dh)
|
||||
|
||||
// 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)
|
||||
{
|
||||
return NewSslPipeEx2(server_mode, x, k, NULL, dh, verify_peer, clientcert);
|
||||
}
|
||||
SSL_PIPE *NewSslPipeEx2(bool server_mode, X *x, K *k, LIST *chain, DH_CTX *dh, bool verify_peer, struct SslClientCertInfo *clientcert)
|
||||
{
|
||||
SSL_PIPE *s;
|
||||
SSL *ssl;
|
||||
@ -5715,7 +5719,24 @@ SSL_PIPE *NewSslPipeEx(bool server_mode, X *x, K *k, DH_CTX *dh, bool verify_pee
|
||||
SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_TLSv1_3); // For some reason pppd under linux doesn't like it
|
||||
#endif
|
||||
|
||||
AddChainSslCertOnDirectory(ssl_ctx);
|
||||
if (chain == NULL)
|
||||
{
|
||||
AddChainSslCertOnDirectory(ssl_ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT i;
|
||||
X *x;
|
||||
LockList(chain);
|
||||
{
|
||||
for (i = 0;i < LIST_NUM(chain);i++)
|
||||
{
|
||||
x = LIST_DATA(chain, i);
|
||||
AddChainSslCert(ssl_ctx, x);
|
||||
}
|
||||
}
|
||||
UnlockList(chain);
|
||||
}
|
||||
|
||||
if (dh != NULL)
|
||||
{
|
||||
@ -11565,6 +11586,10 @@ bool StartSSL(SOCK *sock, X *x, K *priv)
|
||||
return StartSSLEx(sock, x, priv, 0, NULL);
|
||||
}
|
||||
bool StartSSLEx(SOCK *sock, X *x, K *priv, UINT ssl_timeout, char *sni_hostname)
|
||||
{
|
||||
return StartSSLEx2(sock, x, priv, NULL, ssl_timeout, sni_hostname);
|
||||
}
|
||||
bool StartSSLEx2(SOCK *sock, X *x, K *priv, LIST *chain, UINT ssl_timeout, char *sni_hostname)
|
||||
{
|
||||
X509 *x509;
|
||||
EVP_PKEY *key;
|
||||
@ -11660,7 +11685,24 @@ bool StartSSLEx(SOCK *sock, X *x, K *priv, UINT ssl_timeout, char *sni_hostname)
|
||||
#endif
|
||||
|
||||
Unlock(openssl_lock);
|
||||
AddChainSslCertOnDirectory(ssl_ctx);
|
||||
if (chain == NULL)
|
||||
{
|
||||
AddChainSslCertOnDirectory(ssl_ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT i;
|
||||
X *x;
|
||||
LockList(chain);
|
||||
{
|
||||
for (i = 0;i < LIST_NUM(chain);i++)
|
||||
{
|
||||
x = LIST_DATA(chain, i);
|
||||
AddChainSslCert(ssl_ctx, x);
|
||||
}
|
||||
}
|
||||
UnlockList(chain);
|
||||
}
|
||||
Lock(openssl_lock);
|
||||
}
|
||||
|
||||
|
@ -1078,6 +1078,7 @@ UINT SecureSend(SOCK *sock, void *data, UINT size);
|
||||
UINT SecureRecv(SOCK *sock, void *data, UINT size);
|
||||
bool StartSSL(SOCK *sock, X *x, K *priv);
|
||||
bool StartSSLEx(SOCK *sock, X *x, K *priv, UINT ssl_timeout, char *sni_hostname);
|
||||
bool StartSSLEx2(SOCK *sock, X *x, K *priv, LIST *chain, UINT ssl_timeout, char *sni_hostname);
|
||||
bool AddChainSslCert(struct ssl_ctx_st *ctx, X *x);
|
||||
void AddChainSslCertOnDirectory(struct ssl_ctx_st *ctx);
|
||||
bool SendAll(SOCK *sock, void *data, UINT size, bool secure);
|
||||
@ -1353,6 +1354,7 @@ struct SslClientCertInfo {
|
||||
|
||||
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);
|
||||
SSL_PIPE *NewSslPipeEx2(bool server_mode, X *x, K *k, LIST *chain, DH_CTX *dh, bool verify_peer, struct SslClientCertInfo *clientcert);
|
||||
void FreeSslPipe(SSL_PIPE *s);
|
||||
bool SyncSslPipe(SSL_PIPE *s);
|
||||
|
||||
|
@ -870,6 +870,50 @@ X *PackGetX(PACK *p, char *name)
|
||||
return x;
|
||||
}
|
||||
|
||||
// Get the X chain from the PACK
|
||||
LIST *PackGetXList(PACK *p, char *name)
|
||||
{
|
||||
X *x;
|
||||
BUF *b;
|
||||
LIST *chain;
|
||||
UINT i;
|
||||
// Validate arguments
|
||||
if (p == NULL || name == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ELEMENT *e = GetElement(p, name, VALUE_DATA);
|
||||
if (e == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
chain = NewList(NULL);
|
||||
for (i = 0;i < e->num_value;i++)
|
||||
{
|
||||
b = PackGetBufEx(p, name, i);
|
||||
if (b == NULL)
|
||||
{
|
||||
FreeXList(chain);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
x = BufToX(b, false);
|
||||
|
||||
if (x == NULL)
|
||||
{
|
||||
x = BufToX(b, true);
|
||||
}
|
||||
|
||||
FreeBuf(b);
|
||||
|
||||
Add(chain, x);
|
||||
}
|
||||
|
||||
return chain;
|
||||
}
|
||||
|
||||
// Add the K to the PACK
|
||||
ELEMENT *PackAddK(PACK *p, char *name, K *k)
|
||||
{
|
||||
@ -916,6 +960,36 @@ ELEMENT *PackAddX(PACK *p, char *name, X *x)
|
||||
return e;
|
||||
}
|
||||
|
||||
// Add an X chain into the PACK
|
||||
ELEMENT *PackAddXList(PACK *p, char *name, LIST *chain)
|
||||
{
|
||||
BUF *b;
|
||||
X *x;
|
||||
ELEMENT *e = NULL;
|
||||
// Validate arguments
|
||||
if (p == NULL || name == NULL || chain == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UINT i;
|
||||
for (i = 0;i < LIST_NUM(chain);i++)
|
||||
{
|
||||
x = LIST_DATA(chain, i);
|
||||
b = XToBuf(x, false);
|
||||
|
||||
if (b == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
e = PackAddBufEx(p, name, b, i, LIST_NUM(chain));
|
||||
FreeBuf(b);
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
// Get a buffer from the PACK
|
||||
BUF *PackGetBuf(PACK *p, char *name)
|
||||
{
|
||||
|
@ -127,8 +127,10 @@ VALUE *NewInt64Value(UINT64 i);
|
||||
TOKEN_LIST *GetPackElementNames(PACK *p);
|
||||
|
||||
X *PackGetX(PACK *p, char *name);
|
||||
LIST *PackGetXList(PACK *p, char *name);
|
||||
K *PackGetK(PACK *p, char *name);
|
||||
ELEMENT *PackAddX(PACK *p, char *name, X *x);
|
||||
ELEMENT *PackAddXList(PACK *p, char *name, LIST *chain);
|
||||
ELEMENT *PackAddK(PACK *p, char *name, K *k);
|
||||
ELEMENT *PackAddStr(PACK *p, char *name, char *str);
|
||||
ELEMENT *PackAddStrEx(PACK *p, char *name, char *str, UINT index, UINT total);
|
||||
|
Reference in New Issue
Block a user