Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/SoftEtherVPN/SoftEtherVPN_Stable.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/Cedar
diff options
context:
space:
mode:
authordnobori <da.git@softether.co.jp>2014-06-06 01:53:20 +0400
committerdnobori <da.git@softether.co.jp>2014-06-06 01:53:20 +0400
commit719ee999d6c6418b3e9f4afb904387700637009f (patch)
treec337288d68f4a129053d098f1f64269c699a4490 /src/Cedar
parent7839d2939e5336bdf492041f1c2ed564444d7a62 (diff)
v4.07-9448-rtm
Diffstat (limited to 'src/Cedar')
-rw-r--r--src/Cedar/Admin.c31
-rw-r--r--src/Cedar/Admin.h1
-rw-r--r--src/Cedar/Cedar.h14
-rw-r--r--src/Cedar/Client.c1
-rw-r--r--src/Cedar/Command.c34
-rw-r--r--src/Cedar/Interop_OpenVPN.c2
-rw-r--r--src/Cedar/Logging.c19
-rw-r--r--src/Cedar/Protocol.c500
-rw-r--r--src/Cedar/Protocol.h18
-rw-r--r--src/Cedar/SM.c76
-rw-r--r--src/Cedar/SMInner.h2
-rw-r--r--src/Cedar/Server.h1
-rw-r--r--src/Cedar/Session.c17
-rw-r--r--src/Cedar/Session.h1
-rw-r--r--src/Cedar/Virtual.c47
-rw-r--r--src/Cedar/WinUi.h1
16 files changed, 744 insertions, 21 deletions
diff --git a/src/Cedar/Admin.c b/src/Cedar/Admin.c
index f9af5c0c..6d3c2646 100644
--- a/src/Cedar/Admin.c
+++ b/src/Cedar/Admin.c
@@ -1113,6 +1113,24 @@ UINT StMakeOpenVpnConfigFile(ADMIN *a, RPC_READ_LOG_FILE *t)
x = CloneX(c->ServerX);
}
Unlock(c->lock);
+
+ if (x != NULL)
+ {
+ // Get the root certificate
+ if (x->root_cert == false)
+ {
+ X *root_x = NULL;
+ LIST *cert_list = NewCertList(true);
+
+ if (TryGetRootCertChain(cert_list, x, true, &root_x))
+ {
+ FreeX(x);
+ x = root_x;
+ }
+
+ FreeCertList(cert_list);
+ }
+ }
}
x_buf = XToBuf(x, true);
@@ -1121,7 +1139,7 @@ UINT StMakeOpenVpnConfigFile(ADMIN *a, RPC_READ_LOG_FILE *t)
WriteBufChar(x_buf, 0);
SeekBufToBegin(x_buf);
- // Generate dummy certification
+ // Generate a dummy certificate
if (x != NULL)
{
if (RsaGen(&dummy_private_k, &dummy_public_k, x->bits))
@@ -8331,6 +8349,15 @@ UINT StSetServerCert(ADMIN *a, RPC_KEY_PAIR *t)
return ERR_PROTOCOL_ERROR;
}
+ t->Flag1 = 1;
+ if (t->Cert->root_cert == false)
+ {
+ if (DownloadAndSaveIntermediateCertificatesIfNecessary(t->Cert) == false)
+ {
+ t->Flag1 = 0;
+ }
+ }
+
SetCedarCert(c, t->Cert, t->Key);
ALog(a, NULL, "LA_SET_SERVER_CERT");
@@ -12756,6 +12783,7 @@ void InRpcKeyPair(RPC_KEY_PAIR *t, PACK *p)
t->Cert = PackGetX(p, "Cert");
t->Key = PackGetK(p, "Key");
+ t->Flag1 = PackGetInt(p, "Flag1");
}
void OutRpcKeyPair(PACK *p, RPC_KEY_PAIR *t)
{
@@ -12767,6 +12795,7 @@ void OutRpcKeyPair(PACK *p, RPC_KEY_PAIR *t)
PackAddX(p, "Cert", t->Cert);
PackAddK(p, "Key", t->Key);
+ PackAddInt(p, "Flag1", t->Flag1);
}
void FreeRpcKeyPair(RPC_KEY_PAIR *t)
{
diff --git a/src/Cedar/Admin.h b/src/Cedar/Admin.h
index 7715ba0e..65a9f519 100644
--- a/src/Cedar/Admin.h
+++ b/src/Cedar/Admin.h
@@ -295,6 +295,7 @@ struct RPC_KEY_PAIR
{
X *Cert; // Certificate
K *Key; // Secret key
+ UINT Flag1; // Flag1
};
// HUB option
diff --git a/src/Cedar/Cedar.h b/src/Cedar/Cedar.h
index 21b59170..d7eb7374 100644
--- a/src/Cedar/Cedar.h
+++ b/src/Cedar/Cedar.h
@@ -120,10 +120,10 @@
// Version number
-#define CEDAR_VER 406
+#define CEDAR_VER 407
// Build Number
-#define CEDAR_BUILD 9437
+#define CEDAR_BUILD 9448
// Beta number
//#define BETA_NUMBER 3
@@ -143,11 +143,11 @@
// Specifies the build date
#define BUILD_DATE_Y 2014
-#define BUILD_DATE_M 4
-#define BUILD_DATE_D 9
-#define BUILD_DATE_HO 9
-#define BUILD_DATE_MI 39
-#define BUILD_DATE_SE 4
+#define BUILD_DATE_M 6
+#define BUILD_DATE_D 6
+#define BUILD_DATE_HO 3
+#define BUILD_DATE_MI 7
+#define BUILD_DATE_SE 39
// Tolerable time difference
#define ALLOW_TIMESTAMP_DIFF (UINT64)(3 * 24 * 60 * 60 * 1000)
diff --git a/src/Cedar/Client.c b/src/Cedar/Client.c
index 573c0e5f..0891b68d 100644
--- a/src/Cedar/Client.c
+++ b/src/Cedar/Client.c
@@ -5852,7 +5852,6 @@ REMOTE_CLIENT *CcConnectRpcEx(char *server_name, char *password, bool *bad_pass,
#endif // OS_WIN32
port_start = CLIENT_CONFIG_PORT - 1;
-
if (reg_port != 0)
{
s = Connect(server_name, reg_port);
diff --git a/src/Cedar/Command.c b/src/Cedar/Command.c
index 9ae8bdc3..8b299b10 100644
--- a/src/Cedar/Command.c
+++ b/src/Cedar/Command.c
@@ -6658,6 +6658,28 @@ void PsMain(PS *ps)
}
}
+ if (ps->HubName == NULL)
+ {
+ RPC_KEY_PAIR t;
+
+ Zero(&t, sizeof(t));
+
+ if (ScGetServerCert(ps->Rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.Cert != NULL && t.Cert->has_basic_constraints == false)
+ {
+ if (t.Cert->root_cert)
+ {
+ ps->Console->Write(ps->Console, L"");
+ ps->Console->Write(ps->Console, _UU("SM_CERT_MESSAGE_CLI"));
+ ps->Console->Write(ps->Console, L"");
+ }
+ }
+
+ FreeRpcKeyPair(&t);
+ }
+ }
+
while (true)
{
// Definition of command
@@ -7841,6 +7863,14 @@ UINT PsServerCertSet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
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"");
+ }
+
FreeRpcKeyPair(&t);
}
else
@@ -20897,6 +20927,10 @@ UINT PsServerCertRegenerate(CONSOLE *c, char *cmd_name, wchar_t *str, void *para
return ret;
}
+ c->Write(c, L"");
+ c->Write(c, _UU("CM_CERT_SET_MSG"));
+ c->Write(c, L"");
+
FreeParamValueList(o);
return 0;
diff --git a/src/Cedar/Interop_OpenVPN.c b/src/Cedar/Interop_OpenVPN.c
index c3c5cf98..e17c6c30 100644
--- a/src/Cedar/Interop_OpenVPN.c
+++ b/src/Cedar/Interop_OpenVPN.c
@@ -2058,6 +2058,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
}
else
{
+#if 0 // Currently disabled
// If the default gateway is not specified, add the static routing table
// entry for the local IP subnet
IP local_network;
@@ -2076,6 +2077,7 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
&cao->SubnetMask);
StrCat(option_str, sizeof(option_str), l3_options);
+#endif
}
// Classless routing table
diff --git a/src/Cedar/Logging.c b/src/Cedar/Logging.c
index 21529121..139c6fcc 100644
--- a/src/Cedar/Logging.c
+++ b/src/Cedar/Logging.c
@@ -1333,16 +1333,23 @@ char *BuildHttpLogStr(HTTPLOG *h)
b = NewBuf();
- // URL generation
- if (h->Port == 80)
+ if (StartWith(h->Path, "http://"))
{
- Format(url, sizeof(url), "http://%s%s",
- h->Hostname, h->Path);
+ StrCpy(url, sizeof(url), h->Path);
}
else
{
- Format(url, sizeof(url), "http://%s:%u%s",
- h->Hostname, h->Port, h->Path);
+ // URL generation
+ if (h->Port == 80)
+ {
+ Format(url, sizeof(url), "http://%s%s",
+ h->Hostname, h->Path);
+ }
+ else
+ {
+ Format(url, sizeof(url), "http://%s:%u%s",
+ h->Hostname, h->Port, h->Path);
+ }
}
AddLogBufToStr(b, "HttpMethod", h->Method);
diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c
index eac9e935..2d753a61 100644
--- a/src/Cedar/Protocol.c
+++ b/src/Cedar/Protocol.c
@@ -100,6 +100,461 @@
static UCHAR ssl_packet_start[3] = {0x17, 0x03, 0x00};
+// Download and save intermediate certificates if necessary
+bool DownloadAndSaveIntermediateCertificatesIfNecessary(X *x)
+{
+ LIST *o;
+ bool ret = false;
+ // Validate arguments
+ if (x == NULL)
+ {
+ return false;
+ }
+
+ if (x->root_cert)
+ {
+ return true;
+ }
+
+ o = NewCertList(true);
+
+ ret = TryGetRootCertChain(o, x, true, NULL);
+
+ FreeCertList(o);
+
+ return ret;
+}
+
+// Attempt to fetch the full chain of the specified cert
+bool TryGetRootCertChain(LIST *o, X *x, bool auto_save, X **found_root_x)
+{
+ bool ret = false;
+ LIST *chain = NULL;
+ LIST *current_chain_dir = NULL;
+ // Validate arguments
+ if (o == NULL || x == NULL)
+ {
+ return false;
+ }
+
+ chain = NewCertList(false);
+
+ ret = TryGetParentCertFromCertList(o, x, chain);
+
+ if (ret)
+ {
+ UINT i;
+ DIRLIST *dir;
+ wchar_t dirname[MAX_SIZE];
+ wchar_t exedir[MAX_SIZE];
+
+ GetExeDirW(exedir, sizeof(exedir));
+ CombinePathW(dirname, sizeof(dirname), exedir, L"chain_certs");
+ MakeDirExW(dirname);
+
+ if (auto_save)
+ {
+ // delete the current auto_save files
+ dir = EnumDirW(dirname);
+ if (dir != NULL)
+ {
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ DIRENT *e = dir->File[i];
+
+ if (e->Folder == false)
+ {
+ if (UniStartWith(e->FileNameW, AUTO_DOWNLOAD_CERTS_PREFIX))
+ {
+ wchar_t tmp[MAX_SIZE];
+
+ CombinePathW(tmp, sizeof(tmp), dirname, e->FileNameW);
+
+ FileDeleteW(tmp);
+ }
+ }
+ }
+
+ FreeDir(dir);
+ }
+ }
+
+ current_chain_dir = NewCertList(false);
+ AddAllChainCertsToCertList(current_chain_dir);
+
+ for (i = 0;i < LIST_NUM(chain);i++)
+ {
+ wchar_t tmp[MAX_SIZE];
+ X *xx = LIST_DATA(chain, i);
+
+ GetAllNameFromName(tmp, sizeof(tmp), xx->subject_name);
+
+ Debug("depth = %u, subject = %S\n", i, tmp);
+
+ if (auto_save && CompareX(x, xx) == false && IsXInCertList(current_chain_dir, xx) == false)
+ {
+ wchar_t fn[MAX_PATH];
+ char hex_a[128];
+ wchar_t hex[128];
+ UCHAR hash[SHA1_SIZE];
+ wchar_t tmp[MAX_SIZE];
+ BUF *b;
+
+ GetXDigest(xx, hash, true);
+ BinToStr(hex_a, sizeof(hex_a), hash, SHA1_SIZE);
+ StrToUni(hex, sizeof(hex), hex_a);
+
+ UniStrCpy(fn, sizeof(fn), AUTO_DOWNLOAD_CERTS_PREFIX);
+ UniStrCat(fn, sizeof(fn), hex);
+ UniStrCat(fn, sizeof(fn), L".cer");
+
+ CombinePathW(tmp, sizeof(tmp), dirname, fn);
+
+ b = XToBuf(xx, true);
+
+ DumpBufW(b, tmp);
+
+ FreeBuf(b);
+ }
+
+ if (xx->root_cert)
+ {
+ if (found_root_x != NULL)
+ {
+ *found_root_x = CloneX(xx);
+ }
+ }
+ }
+ }
+
+ FreeCertList(chain);
+
+ FreeCertList(current_chain_dir);
+
+ return ret;
+}
+
+// Try get the parent cert
+bool TryGetParentCertFromCertList(LIST *o, X *x, LIST *found_chain)
+{
+ bool ret = false;
+ X *r;
+ bool do_free = false;
+ // Validate arguments
+ if (o == NULL || x == NULL || found_chain == NULL)
+ {
+ return false;
+ }
+
+ if (LIST_NUM(found_chain) >= FIND_CERT_CHAIN_MAX_DEPTH)
+ {
+ return false;
+ }
+
+ Add(found_chain, CloneX(x));
+
+ if (x->root_cert)
+ {
+ return true;
+ }
+
+ r = FindCertIssuerFromCertList(o, x);
+
+ if (r == NULL)
+ {
+ if (IsEmptyStr(x->issuer_url) == false)
+ {
+ r = DownloadCert(x->issuer_url);
+
+ if (CheckXEx(x, r, true, true) && CompareX(x, r) == false)
+ {
+ // found
+ do_free = true;
+ }
+ else
+ {
+ // invalid
+ FreeX(r);
+ r = NULL;
+ }
+ }
+ }
+
+ if (r != NULL)
+ {
+ ret = TryGetParentCertFromCertList(o, r, found_chain);
+ }
+
+ if (do_free)
+ {
+ FreeX(r);
+ }
+
+ return ret;
+}
+
+// Find the issuer of the cert from the cert list
+X *FindCertIssuerFromCertList(LIST *o, X *x)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || x == NULL)
+ {
+ return NULL;
+ }
+
+ if (x->root_cert)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ X *xx = LIST_DATA(o, i);
+
+ if (CheckXEx(x, xx, true, true))
+ {
+ if (CompareX(x, xx) == false)
+ {
+ return xx;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+// Download a cert by using HTTP
+X *DownloadCert(char *url)
+{
+ BUF *b;
+ URL_DATA url_data;
+ X *ret = NULL;
+ // Validate arguments
+ if (IsEmptyStr(url))
+ {
+ return NULL;
+ }
+
+ Debug("Trying to download a cert from %s ...\n", url);
+
+ if (ParseUrl(&url_data, url, false, NULL) == false)
+ {
+ Debug("Download failed.\n");
+ return NULL;
+ }
+
+ b = HttpRequestEx(&url_data, NULL, CERT_HTTP_DOWNLOAD_TIMEOUT, CERT_HTTP_DOWNLOAD_TIMEOUT,
+ NULL, false, NULL, NULL, NULL, NULL, NULL, CERT_HTTP_DOWNLOAD_MAXSIZE);
+
+ if (b == NULL)
+ {
+ Debug("Download failed.\n");
+ return NULL;
+ }
+
+ ret = BufToX(b, IsBase64(b));
+
+ FreeBuf(b);
+
+ Debug("Download ok.\n");
+ return ret;
+}
+
+// New cert list
+LIST *NewCertList(bool load_root_and_chain)
+{
+ LIST *o;
+
+ o = NewList(NULL);
+
+ if (load_root_and_chain)
+ {
+ AddAllRootCertsToCertList(o);
+ AddAllChainCertsToCertList(o);
+ }
+
+ return o;
+}
+
+// Free cert list
+void FreeCertList(LIST *o)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ X *x = LIST_DATA(o, i);
+
+ FreeX(x);
+ }
+
+ ReleaseList(o);
+}
+
+// Check whether the cert is in the cert list
+bool IsXInCertList(LIST *o, X *x)
+{
+ UINT i;
+ // Validate arguments
+ if (o == NULL || x == NULL)
+ {
+ return false;
+ }
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ X *xx = LIST_DATA(o, i);
+
+ if (CompareX(x, xx))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Add a cert to the cert list
+void AddXToCertList(LIST *o, X *x)
+{
+ // Validate arguments
+ if (o == NULL || x == NULL)
+ {
+ return;
+ }
+
+ if (IsXInCertList(o, x))
+ {
+ return;
+ }
+
+ if (CheckXDateNow(x) == false)
+ {
+ return;
+ }
+
+ Add(o, CloneX(x));
+}
+
+// Add all chain certs to the cert list
+void AddAllChainCertsToCertList(LIST *o)
+{
+ wchar_t dirname[MAX_SIZE];
+ wchar_t exedir[MAX_SIZE];
+ DIRLIST *dir;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ GetExeDirW(exedir, sizeof(exedir));
+
+ CombinePathW(dirname, sizeof(dirname), exedir, L"chain_certs");
+
+ MakeDirExW(dirname);
+
+ dir = EnumDirW(dirname);
+
+ if (dir != NULL)
+ {
+ UINT i;
+
+ for (i = 0;i < dir->NumFiles;i++)
+ {
+ DIRENT *e = dir->File[i];
+
+ if (e->Folder == false)
+ {
+ wchar_t tmp[MAX_SIZE];
+ X *x;
+
+ CombinePathW(tmp, sizeof(tmp), dirname, e->FileNameW);
+
+ x = FileToXW(tmp);
+
+ if (x != NULL)
+ {
+ AddXToCertList(o, x);
+
+ FreeX(x);
+ }
+ }
+ }
+
+ FreeDir(dir);
+ }
+}
+
+// Add all root certs to the cert list
+void AddAllRootCertsToCertList(LIST *o)
+{
+ BUF *buf;
+ PACK *p;
+ UINT num_ok = 0, num_error = 0;
+ // Validate arguments
+ if (o == NULL)
+ {
+ return;
+ }
+
+ buf = ReadDump(ROOT_CERTS_FILENAME);
+ if (buf == NULL)
+ {
+ return;
+ }
+
+ p = BufToPack(buf);
+
+ if (p != NULL)
+ {
+ UINT num = PackGetIndexCount(p, "cert");
+ UINT i;
+
+ for (i = 0;i < num;i++)
+ {
+ bool ok = false;
+ BUF *b = PackGetBufEx(p, "cert", i);
+
+ if (b != NULL)
+ {
+ X *x = BufToX(b, false);
+
+ if (x != NULL)
+ {
+ AddXToCertList(o, x);
+
+ ok = true;
+
+ FreeX(x);
+ }
+
+ FreeBuf(b);
+ }
+
+ if (ok)
+ {
+ num_ok++;
+ }
+ else
+ {
+ num_error++;
+ }
+ }
+
+ FreePack(p);
+ }
+
+ FreeBuf(buf);
+
+ Debug("AddAllRootCertsToCertList: ok=%u error=%u total_list_len=%u\n", num_ok, num_error, LIST_NUM(o));
+}
// Convert the date of YYYYMMDD format to a number
UINT64 ShortStrToDate64(char *str)
@@ -5345,8 +5800,26 @@ bool ClientUploadAuth(CONNECTION *c)
// UDP acceleration function using flag
if (o->NoUdpAcceleration == false && c->Session->UdpAccel != NULL)
{
+ IP my_ip;
+
+ Zero(&my_ip, sizeof(my_ip));
+
PackAddBool(p, "use_udp_acceleration", true);
- PackAddIp(p, "udp_acceleration_client_ip", &c->Session->UdpAccel->MyIp);
+
+ Copy(&my_ip, &c->Session->UdpAccel->MyIp, sizeof(IP));
+ if (IsLocalHostIP(&my_ip))
+ {
+ if (IsIP4(&my_ip))
+ {
+ ZeroIP4(&my_ip);
+ }
+ else
+ {
+ ZeroIP6(&my_ip);
+ }
+ }
+
+ PackAddIp(p, "udp_acceleration_client_ip", &my_ip);
PackAddInt(p, "udp_acceleration_client_port", c->Session->UdpAccel->MyPort);
PackAddData(p, "udp_acceleration_client_key", c->Session->UdpAccel->MyKey, UDP_ACCELERATION_COMMON_KEY_SIZE);
PackAddBool(p, "support_hmac_on_udp_acceleration", true);
@@ -6186,6 +6659,8 @@ SOCK *ProxyConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
char basic_str[MAX_SIZE * 2];
UINT http_error_code;
HTTP_HEADER *h;
+ char server_host_name_tmp[256];
+ UINT i, len;
// Validate arguments
if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL ||
server_port == 0)
@@ -6206,6 +6681,19 @@ SOCK *ProxyConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
return NULL;
}
+ Zero(server_host_name_tmp, sizeof(server_host_name_tmp));
+ StrCpy(server_host_name_tmp, sizeof(server_host_name_tmp), server_host_name);
+
+ len = StrLen(server_host_name_tmp);
+
+ for (i = 0;i < len;i++)
+ {
+ if (server_host_name_tmp[i] == '/')
+ {
+ server_host_name_tmp[i] = 0;
+ }
+ }
+
// Connection
s = TcpConnectEx3(proxy_host_name, proxy_port, timeout, cancel_flag, hWnd, true, NULL, false, false);
if (s == NULL)
@@ -6224,24 +6712,24 @@ SOCK *ProxyConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
}
// HTTP header generation
- if (IsStrIPv6Address(server_host_name))
+ if (IsStrIPv6Address(server_host_name_tmp))
{
IP ip;
char iptmp[MAX_PATH];
- StrToIP(&ip, server_host_name);
+ StrToIP(&ip, server_host_name_tmp);
IPToStr(iptmp, sizeof(iptmp), &ip);
Format(tmp, sizeof(tmp), "[%s]:%u", iptmp, server_port);
}
else
{
- Format(tmp, sizeof(tmp), "%s:%u", server_host_name, server_port);
+ Format(tmp, sizeof(tmp), "%s:%u", server_host_name_tmp, server_port);
}
h = NewHttpHeader("CONNECT", tmp, "HTTP/1.0");
AddHttpValue(h, NewHttpValue("User-Agent", (c->Cedar == NULL ? DEFAULT_USER_AGENT : c->Cedar->HttpUserAgent)));
- AddHttpValue(h, NewHttpValue("Host", server_host_name));
+ AddHttpValue(h, NewHttpValue("Host", server_host_name_tmp));
AddHttpValue(h, NewHttpValue("Content-Length", "0"));
AddHttpValue(h, NewHttpValue("Proxy-Connection", "Keep-Alive"));
AddHttpValue(h, NewHttpValue("Pragma", "no-cache"));
@@ -6249,7 +6737,7 @@ SOCK *ProxyConnectEx2(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
if (use_auth)
{
wchar_t tmp[MAX_SIZE];
- UniFormat(tmp, sizeof(tmp), _UU("STATUS_3"), server_host_name);
+ UniFormat(tmp, sizeof(tmp), _UU("STATUS_3"), server_host_name_tmp);
// Generate the authentication string
Format(auth_tmp_str, sizeof(auth_tmp_str), "%s:%s",
username, password);
diff --git a/src/Cedar/Protocol.h b/src/Cedar/Protocol.h
index f7c04aa3..21e778c7 100644
--- a/src/Cedar/Protocol.h
+++ b/src/Cedar/Protocol.h
@@ -179,6 +179,12 @@ struct UPDATE_CLIENT
#define UPDATE_CONNECT_TIMEOUT 5000
#define UPDATE_COMM_TIMEOUT 5000
+// Dynamic root cert fetch function
+#define CERT_HTTP_DOWNLOAD_MAXSIZE 65536
+#define CERT_HTTP_DOWNLOAD_TIMEOUT (10 * 1000)
+#define ROOT_CERTS_FILENAME "|root_certs.dat"
+#define AUTO_DOWNLOAD_CERTS_PREFIX L".autodownload_"
+#define FIND_CERT_CHAIN_MAX_DEPTH 16
// Function prototype
@@ -277,6 +283,18 @@ void PackAddClientVersion(PACK *p, CONNECTION *c);
void NodeInfoToStr(wchar_t *str, UINT size, NODE_INFO *info);
void GenerateMachineUniqueHash(void *data);
+LIST *NewCertList(bool load_root_and_chain);
+void FreeCertList(LIST *o);
+bool IsXInCertList(LIST *o, X *x);
+void AddXToCertList(LIST *o, X *x);
+void AddAllRootCertsToCertList(LIST *o);
+void AddAllChainCertsToCertList(LIST *o);
+X *DownloadCert(char *url);
+X *FindCertIssuerFromCertList(LIST *o, X *x);
+bool TryGetRootCertChain(LIST *o, X *x, bool auto_save, X **found_root_x);
+bool TryGetParentCertFromCertList(LIST *o, X *x, LIST *found_chain);
+bool DownloadAndSaveIntermediateCertificatesIfNecessary(X *x);
+
#endif // PROTOCOL_H
diff --git a/src/Cedar/SM.c b/src/Cedar/SM.c
index 4c0093dc..93c80f52 100644
--- a/src/Cedar/SM.c
+++ b/src/Cedar/SM.c
@@ -16929,6 +16929,13 @@ void SmSslDlgOnOk(HWND hWnd, SM_SSL *s)
{
return;
}
+
+ if (t.Flag1 == 0)
+ {
+ // Show the warning message
+ MsgBox(hWnd, MB_ICONWARNING, _UU("SM_CERT_NEED_ROOT"));
+ }
+
FreeRpcKeyPair(&t);
MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_CERT_SET_MSG"));
@@ -18930,6 +18937,8 @@ UINT SmServerDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *pa
SmShowIPSecMessageIfNecessary(hWnd, p);
+ SmShowCertRegenerateMessageIfNecessary(hWnd, p);
+
SetTimer(hWnd, 3, 150, NULL);
break;
@@ -18954,6 +18963,73 @@ UINT SmServerDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *pa
return 0;
}
+// Display the message about the cert
+void SmShowCertRegenerateMessageIfNecessary(HWND hWnd, SM_SERVER *p)
+{
+ // Validate arguments
+ if (p == NULL)
+ {
+ return;
+ }
+
+ if (p->ServerAdminMode && p->Bridge == false)
+ {
+ RPC_KEY_PAIR t;
+
+ Zero(&t, sizeof(t));
+
+ if (ScGetServerCert(p->Rpc, &t) == ERR_NO_ERROR)
+ {
+ if (t.Cert != NULL && t.Cert->has_basic_constraints == false)
+ {
+ if (t.Cert->root_cert)
+ {
+ if (MsRegReadInt(REG_CURRENT_USER, SM_HIDE_CERT_UPDATE_MSG_KEY, p->ServerName) == 0)
+ {
+ if (MsgBox(hWnd, MB_ICONQUESTION | MB_YESNO, _UU("SM_CERT_MESSAGE")) == IDYES)
+ {
+ X *x;
+ K *k;
+
+ // Regenerating the certificate
+ if (SmRegenerateServerCert(hWnd, p, NULL, &x, &k, false))
+ {
+ // Confirmation message
+ if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO, _UU("SM_REGENERATE_CERT_MSG")) == IDYES)
+ {
+ // Set the new certificate and private key
+ RPC_KEY_PAIR t2;
+
+ Zero(&t2, sizeof(t2));
+
+ t2.Cert = CloneX(x);
+ t2.Key = CloneK(k);
+
+ if (CALL(hWnd, ScSetServerCert(p->Rpc, &t2)))
+ {
+ FreeRpcKeyPair(&t2);
+
+ MsgBox(hWnd, MB_ICONINFORMATION, _UU("CM_CERT_SET_MSG"));
+ }
+ }
+
+ FreeX(x);
+ FreeK(k);
+ }
+ }
+ else
+ {
+ MsRegWriteInt(REG_CURRENT_USER, SM_HIDE_CERT_UPDATE_MSG_KEY, p->ServerName, 1);
+ }
+ }
+ }
+ }
+
+ FreeRpcKeyPair(&t);
+ }
+ }
+}
+
// Display messages about IPsec, and prompt for the setting
void SmShowIPSecMessageIfNecessary(HWND hWnd, SM_SERVER *p)
{
diff --git a/src/Cedar/SMInner.h b/src/Cedar/SMInner.h
index 8f2beb33..9a118e04 100644
--- a/src/Cedar/SMInner.h
+++ b/src/Cedar/SMInner.h
@@ -101,6 +101,7 @@
#define SM_CERT_REG_KEY "Software\\SoftEther Corporation\\PacketiX VPN\\Server Manager\\Cert Tool"
#define SM_SETTING_REG_KEY "Software\\SoftEther Corporation\\PacketiX VPN\\Server Manager\\Settings"
#define SM_LASTHUB_REG_KEY "Software\\SoftEther Corporation\\PacketiX VPN\\Server Manager\\Last HUB Name"
+#define SM_HIDE_CERT_UPDATE_MSG_KEY "Software\\SoftEther Corporation\\PacketiX VPN\\Server Manager\\Hide Cert Update Msg"
#define NAME_OF_VPN_SERVER_MANAGER "vpnsmgr"
#define NAME_OF_VPN_SERVER_TARGET "vpnserver@%s"
@@ -799,6 +800,7 @@ UINT SmSpecialListenerDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, voi
void SmSpecialListenerDlgInit(HWND hWnd, SM_SERVER *s);
void SmSpecialListenerDlgOnOk(HWND hWnd, SM_SERVER *s);
void SmShowIPSecMessageIfNecessary(HWND hWnd, SM_SERVER *p);
+void SmShowCertRegenerateMessageIfNecessary(HWND hWnd, SM_SERVER *p);
UINT SmVmBridgeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
void SmAzure(HWND hWnd, SM_SERVER *s, bool on_setup);
UINT SmAzureDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param);
diff --git a/src/Cedar/Server.h b/src/Cedar/Server.h
index 27803e94..382f6f47 100644
--- a/src/Cedar/Server.h
+++ b/src/Cedar/Server.h
@@ -414,6 +414,7 @@ struct LOG_FILE
#define GSF_SHOW_OSS_MSG 7
+
// Virtual HUB creation history
struct SERVER_HUB_CREATE_HISTORY
{
diff --git a/src/Cedar/Session.c b/src/Cedar/Session.c
index 828ca911..5ebca32f 100644
--- a/src/Cedar/Session.c
+++ b/src/Cedar/Session.c
@@ -2142,6 +2142,23 @@ SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username,
return s;
}
+// Check whether the specified MAC address is IPC address
+bool IsIpcMacAddress(UCHAR *mac)
+{
+ // Validate arguments
+ if (mac == NULL)
+ {
+ return false;
+ }
+
+ if (mac[0] == 0xCA)
+ {
+ return true;
+ }
+
+ return false;
+}
+
// Display the session key for debugging
void DebugPrintSessionKey(UCHAR *session_key)
{
diff --git a/src/Cedar/Session.h b/src/Cedar/Session.h
index 5655947c..4e6c7914 100644
--- a/src/Cedar/Session.h
+++ b/src/Cedar/Session.h
@@ -397,6 +397,7 @@ void NewSessionKey(CEDAR *cedar, UCHAR *session_key, UINT *session_key_32);
SESSION *GetSessionFromKey(CEDAR *cedar, UCHAR *session_key);
SESSION *GetSessionFromKey32(CEDAR *cedar, UINT key32);
void DebugPrintSessionKey(UCHAR *session_key);
+bool IsIpcMacAddress(UCHAR *mac);
void ClientAdditionalConnectChance(SESSION *s);
void SessionAdditionalConnect(SESSION *s);
void ClientAdditionalThread(THREAD *t, void *param);
diff --git a/src/Cedar/Virtual.c b/src/Cedar/Virtual.c
index 1bc8b132..00a735dc 100644
--- a/src/Cedar/Virtual.c
+++ b/src/Cedar/Virtual.c
@@ -9436,6 +9436,53 @@ void VirtualDhcpServer(VH *v, PKT *p)
if (GetGlobalServerFlag(GSF_DISABLE_PUSH_ROUTE) == 0)
{
Copy(&ret.ClasslessRoute, &v->PushRoute, sizeof(DHCP_CLASSLESS_ROUTE_TABLE));
+
+ if (IsIpcMacAddress(p->MacAddressSrc))
+ {
+ if (ret.Gateway == 0)
+ {
+ // If the default gateway is not specified, add the static routing table
+ // entry for the local IP subnet
+ // (for PPP clients)
+ IP dhcp_ip;
+ IP dhcp_mask;
+ IP dhcp_network;
+
+ UINTToIP(&dhcp_ip, ip);
+
+ if (ip == 0)
+ {
+ UINTToIP(&dhcp_ip, p->L3.IPv4Header->SrcIP);
+ }
+
+ UINTToIP(&dhcp_mask, v->DhcpMask);
+
+ IPAnd4(&dhcp_network, &dhcp_ip, &dhcp_mask);
+
+ if (GetBestClasslessRoute(&ret.ClasslessRoute, &dhcp_ip) == NULL)
+ {
+ if (ret.ClasslessRoute.NumExistingRoutes < MAX_DHCP_CLASSLESS_ROUTE_ENTRIES)
+ {
+ DHCP_CLASSLESS_ROUTE *cr = &ret.ClasslessRoute.Entries[ret.ClasslessRoute.NumExistingRoutes];
+
+ cr->Exists = true;
+
+ UINTToIP(&cr->Gateway, v->HostIP);
+
+ if (v->UseNat == false && ret.ClasslessRoute.NumExistingRoutes >= 1)
+ {
+ Copy(&cr->Gateway, &ret.ClasslessRoute.Entries[0].Gateway, sizeof(IP));
+ }
+
+ Copy(&cr->Network, &dhcp_network, sizeof(IP));
+ Copy(&cr->SubnetMask, &dhcp_mask, sizeof(IP));
+ cr->SubnetMaskLen = SubnetMaskToInt(&dhcp_mask);
+
+ ret.ClasslessRoute.NumExistingRoutes++;
+ }
+ }
+ }
+ }
}
if (opt->Opcode != DHCP_INFORM)
diff --git a/src/Cedar/WinUi.h b/src/Cedar/WinUi.h
index a9161253..3f26d4d6 100644
--- a/src/Cedar/WinUi.h
+++ b/src/Cedar/WinUi.h
@@ -485,6 +485,7 @@ typedef struct BAD_PROCESS
static BAD_PROCESS bad_processes[] =
{
{"nod32krn.exe", "NOD32 Antivirus",},
+ {"avp.exe", "Kaspersky",},
};
static UINT num_bad_processes = sizeof(bad_processes) / sizeof(bad_processes[0]);