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>2019-07-07 15:25:52 +0300
committerdnobori <da.git@softether.co.jp>2019-07-07 15:25:52 +0300
commit55d1ac0402a2f9cc546566485ad07cb1f8321b5d (patch)
tree186053d28d88e53a05968d54d948a679940c7ff0 /src/Cedar
parent92837bc8b46e244f3101c1d6425c171997ce79b1 (diff)
v4.30-9695-betav4.30-9695-beta
Diffstat (limited to 'src/Cedar')
-rw-r--r--src/Cedar/Admin.c1466
-rw-r--r--src/Cedar/Admin.h40
-rw-r--r--src/Cedar/CM.c6
-rw-r--r--src/Cedar/Cedar.h15
-rw-r--r--src/Cedar/CedarType.h4
-rw-r--r--src/Cedar/Client.c72
-rw-r--r--src/Cedar/Client.h1
-rw-r--r--src/Cedar/Command.c9
-rw-r--r--src/Cedar/Connection.c16
-rw-r--r--src/Cedar/Connection.h5
-rw-r--r--src/Cedar/DDNS.c3
-rw-r--r--src/Cedar/DDNS.h2
-rw-r--r--src/Cedar/EtherLog.c4
-rw-r--r--src/Cedar/Hub.c9
-rw-r--r--src/Cedar/Hub.h3
-rw-r--r--src/Cedar/IPsec_EtherIP.c2
-rw-r--r--src/Cedar/IPsec_IPC.c28
-rw-r--r--src/Cedar/IPsec_IPC.h19
-rw-r--r--src/Cedar/IPsec_PPP.c8
-rw-r--r--src/Cedar/Interop_OpenVPN.c39
-rw-r--r--src/Cedar/Interop_OpenVPN.h1
-rw-r--r--src/Cedar/Listener.c6
-rw-r--r--src/Cedar/Nat.c14
-rw-r--r--src/Cedar/Protocol.c2773
-rw-r--r--src/Cedar/Protocol.h105
-rw-r--r--src/Cedar/Radius.c112
-rw-r--r--src/Cedar/Radius.h6
-rw-r--r--src/Cedar/Remote.c10
-rw-r--r--src/Cedar/Remote.h1
-rw-r--r--src/Cedar/SM.c10
-rw-r--r--src/Cedar/SMInner.h1
-rw-r--r--src/Cedar/SW.c9
-rw-r--r--src/Cedar/Server.c105
-rw-r--r--src/Cedar/Server.h4
-rw-r--r--src/Cedar/Session.c55
-rw-r--r--src/Cedar/Session.h13
-rw-r--r--src/Cedar/UdpAccel.c320
-rw-r--r--src/Cedar/UdpAccel.h24
-rw-r--r--src/Cedar/VLanWin32.c4
39 files changed, 4872 insertions, 452 deletions
diff --git a/src/Cedar/Admin.c b/src/Cedar/Admin.c
index 3ff53474..f622f67b 100644
--- a/src/Cedar/Admin.c
+++ b/src/Cedar/Admin.c
@@ -373,6 +373,1140 @@ CAPSLIST *ScGetCapsEx(RPC *rpc)
return t;
}
+// Process server side include
+BUF *AdminWebProcessServerSideInclude(BUF *src_txt, char *filename, UINT depth)
+{
+ char *src_str;
+ UINT src_str_size;
+ UINT i, len;
+ BUF *ret = NULL;
+ UINT pos = 0;
+ char dirname[MAX_PATH];
+ if (src_txt == NULL || filename == NULL || depth >= 4)
+ {
+ return CloneBuf(src_txt);
+ }
+ if (EndWith(filename, ".html") == false)
+ {
+ // We process only .html files
+ return CloneBuf(src_txt);
+ }
+
+ GetDirNameFromFilePath(dirname, sizeof(dirname), filename);
+
+ src_str_size = src_txt->Size + 1;
+ src_str = ZeroMalloc(src_str_size);
+
+ Copy(src_str, src_txt->Buf, src_txt->Size);
+
+ len = StrLen(src_str);
+
+ ret = NewBuf();
+
+ for (i = 0;i < len;i++)
+ {
+ char *start_tag = "<!--#include file=";
+ bool is_ssi = false;
+
+ if (StartWith(src_str + i, start_tag))
+ {
+ UINT a = i + StrLen(start_tag);
+
+ if (src_str[a] == '\"' || src_str[a] == '\'')
+ {
+ char delimier = src_str[a];
+ char delimier_str[2];
+ UINT b;
+
+ delimier_str[0] = delimier;
+ delimier_str[1] = 0;
+ b = SearchStrEx(src_str, delimier_str, i + StrLen(start_tag) + 1, true);
+
+ if ((b != INFINITE) && (b >= i + StrLen(start_tag) + 1) && ((b - (i + StrLen(start_tag) + 1)) < 32))
+ {
+ char inc_filename[MAX_PATH];
+ char *end_tag = "-->";
+ UINT x;
+
+ Zero(inc_filename, sizeof(inc_filename));
+
+ StrCpy(inc_filename, sizeof(inc_filename), src_str + i + StrLen(start_tag) + 1);
+ inc_filename[b - (i + StrLen(start_tag) + 1)] = 0;
+
+ x = SearchStrEx(src_str, end_tag, b + 1, true);
+
+ if ((x != INFINITE) && (x >= (b + 1)))
+ {
+ BUF *inc_buf;
+ char full_inc_filename[MAX_PATH];
+
+ if (StartWith(inc_filename, "/"))
+ {
+ Format(full_inc_filename, sizeof(full_inc_filename), "|wwwroot/%s", inc_filename + 1);
+ }
+ else
+ {
+ StrCpy(full_inc_filename, sizeof(full_inc_filename), dirname);
+ StrCat(full_inc_filename, sizeof(full_inc_filename), "/");
+ StrCat(full_inc_filename, sizeof(full_inc_filename), inc_filename);
+ }
+
+ Debug("dirname = %s, full_inc_filename (src) = %s\n\n", dirname, full_inc_filename);
+ NormalizePath(full_inc_filename, sizeof(full_inc_filename), full_inc_filename);
+
+ if (StartWith(full_inc_filename, "|wwwroot/") == false
+ && StartWith(full_inc_filename, "|wwwroot\\") == false)
+ {
+ char tmp[MAX_PATH];
+ Format(tmp, sizeof(tmp), "|wwwroot/%s", full_inc_filename);
+ StrCpy(full_inc_filename, sizeof(full_inc_filename), tmp);
+ }
+
+ Debug("inc_filename = %s\nfull_inc_filename = %s\n\n", inc_filename, full_inc_filename);
+
+ inc_buf = ReadDump(full_inc_filename);
+
+ if (inc_buf != NULL)
+ {
+ BUF *inc_buf2;
+
+ inc_buf2 = AdminWebProcessServerSideInclude(inc_buf, full_inc_filename, depth + 1);
+
+ BufSkipUtf8Bom(inc_buf2);
+ WriteBufBufWithOffset(ret, inc_buf2);
+
+ FreeBuf(inc_buf);
+ FreeBuf(inc_buf2);
+ }
+ else
+ {
+ Debug("Loading SSI '%s' error.\n", inc_buf);
+ }
+
+ i = (x + StrLen(end_tag) - 1);
+
+ is_ssi = true;
+ }
+ }
+ }
+ }
+
+ if (is_ssi == false)
+ {
+ WriteBufChar(ret, src_str[i]);
+ }
+ }
+
+ Free(src_str);
+
+ return ret;
+}
+
+// Handle the file request
+bool AdminWebHandleFileRequest(ADMIN *a, CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_src, char *query_string, char *virtual_root_dir, char *physical_root_dir)
+{
+ bool ret = false;
+ char url[MAX_PATH];
+ UINT i, len;
+ if (a == NULL || c == NULL || s == NULL || h == NULL || url == NULL || query_string == NULL ||
+ virtual_root_dir == NULL || physical_root_dir == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(url, sizeof(url), url_src);
+
+ len = StrLen(url);
+ for (i = 0;i < len;i++)
+ {
+ if (url[i] == '\\')
+ {
+ url[i] = '/';
+ }
+ }
+
+ // Is dangerous URL?
+ if (InStr(url, "..") || InStr(url, "//") || InStr(url, "\\\\") || InStr(url, "/\\") || InStr(url, "\\/"))
+ {
+ ret = AdminWebSend404Error(s, h);
+ }
+ else
+ {
+ char filename[MAX_PATH];
+ bool is_index_file = false;
+
+ BUF *b = AdminWebTryFindAndReadFile(virtual_root_dir, physical_root_dir, url,
+ filename, sizeof(filename), &is_index_file);
+
+ if (b == NULL)
+ {
+ ret = AdminWebSend404Error(s, h);
+ }
+ else
+ {
+ if (is_index_file && EndWith(url, "/") == false)
+ {
+ char url2[MAX_PATH];
+ StrCpy(url2, sizeof(url2), url);
+ StrCat(url2, sizeof(url2), "/");
+ ret = AdminWebSend302Redirect(s, url2, query_string, h);
+ }
+ else if (is_index_file == false && EndWith(url, "/"))
+ {
+ char url2[MAX_PATH];
+ TrimEndWith(url2, sizeof(url2), url, "/");
+ ret = AdminWebSend302Redirect(s, url2, query_string, h);
+ }
+ else
+ {
+ BUF *b2 = AdminWebProcessServerSideInclude(b, filename, 0);
+ char *mime = GetMimeTypeFromFileName(filename);
+
+ if (mime == NULL)
+ {
+ mime = "application/octet-stream";
+ }
+
+ ret = AdminWebSendBody(s, 200, "OK", b2->Buf, b2->Size, mime, NULL, NULL, h);
+
+ FreeBuf(b2);
+ }
+ FreeBuf(b);
+ }
+ }
+
+ return ret;
+}
+
+// Try to find a file, and if exists return the file contents
+BUF *AdminWebTryFindAndReadFile(char *vroot, char *proot, char *url, char *ret_filename, UINT ret_filename_size, bool *is_index_html)
+{
+ char tmp[MAX_PATH];
+ char tmp2[MAX_PATH];
+ UINT vroot_len;
+ UINT url_len;
+ char relative_path[MAX_PATH];
+ BUF *b;
+ if (vroot == NULL || proot == NULL || url == NULL || ret_filename == NULL || is_index_html == NULL)
+ {
+ return NULL;
+ }
+
+ *is_index_html = false;
+
+ if (StartWith(url, vroot) == false)
+ {
+ return NULL;
+ }
+
+ vroot_len = StrLen(vroot);
+ url_len = StrLen(url);
+
+ StrCpy(relative_path, sizeof(relative_path), url + vroot_len);
+
+ if (StartWith(relative_path, "/"))
+ {
+ char tmp3[MAX_PATH];
+
+ StrCpy(tmp3, sizeof(tmp3), relative_path + 1);
+ StrCpy(relative_path, sizeof(relative_path), tmp3);
+ }
+
+ CombinePath(tmp, sizeof(tmp), proot, relative_path);
+
+ // index.html
+ CombinePath(tmp2, sizeof(tmp2), tmp, "index.html");
+ b = AdminWebTryOneFile(tmp2, ret_filename, ret_filename_size);
+ if (b != NULL)
+ {
+ *is_index_html = true;
+ return b;
+ }
+
+ // dirname/filename
+ StrCpy(tmp2, sizeof(tmp2), tmp);
+ b = AdminWebTryOneFile(tmp2, ret_filename, ret_filename_size);
+ if (b != NULL)
+ {
+ return b;
+ }
+
+ return NULL;
+}
+BUF *AdminWebTryOneFile(char *filename, char *ret_filename, UINT ret_filename_size)
+{
+ BUF *b;
+ if (filename == NULL || ret_filename == NULL)
+ {
+ return NULL;
+ }
+
+ b = ReadDump(filename);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ StrCpy(ret_filename, ret_filename_size, filename);
+
+ return b;
+}
+
+// Send a 401 Unauthorized error
+bool AdminWebSendUnauthorized(SOCK *s, HTTP_HEADER *http_request_headers)
+{
+ char *http_401_str = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<html><head>\r\n<title>401 Unauthorized</title>\r\n</head><body>\r\n<h1>" CEDAR_SERVER_STR ": Administrative authentication required.</h1>\r\n<p>This VPN Server could not verify that you are authorized to access to the \r\nserver in administrative mode.</p>\r\n<p><strong>For web browser logins:<br></strong>You must supply the HTTP basic \r\nauthentication credential as following.</p>\r\n<ul>\r\n\t<li>To login to the VPN server as the entire server administrator, specify empty or &quot;administrator&quot; as the username field, and specify the server administrative \r\n\tpassword as the password field.<br></li>\r\n\t<li>To login to a particular Virtual Hub as the hub administrator, specify \r\n\tthe hub name as the username field, and specify the hub administrative \r\n\tpassword as the password field.</li>\r\n</ul>\r\n<p><strong>For JSON-RPC client logins:<br></strong>Instead to HTTP basic \r\nauthentication, you can also specify the HTTP header parameters as following.</p>\r\n<ul>\r\n\t<li>X-VPNADMIN-HUBNAME: Empty to login to the VPN Server as the entire \r\n\tserver administrator, or specify the target Virtual Hub name as the hub \r\n\tadministrator.</li>\r\n\t<li>X-VPNADMIN-PASSWORD: Specify the administrative password.</li>\r\n</ul>\r\n</body></html>\r\n";
+ bool ret;
+ // Validate arguments
+ if (s == NULL || http_request_headers == NULL)
+ {
+ return false;
+ }
+
+ // Creating a Data
+ ret = AdminWebSendBody(s, 401, "Unauthorized", http_401_str, StrLen(http_401_str), HTTP_CONTENT_TYPE,
+ "WWW-Authenticate",
+ "Basic realm=\"Username 'administrator' for entire VPN Server privilege, or specify Virtual Hub name as the username for specified Virtual Hub administrative privilege.\"",
+ http_request_headers);
+
+ return ret;
+}
+
+// Send reply
+bool AdminWebSendBody(SOCK *s, UINT status_code, char *status_string, UCHAR *data, UINT data_size, char *content_type, char *add_header_name, char *add_header_value,
+ HTTP_HEADER *request_headers)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char error_code_str[16];
+ bool ret = false;
+ HTTP_VALUE *origin;
+ if (s == NULL || status_string == NULL || (data_size != 0 && data == NULL) || request_headers == NULL)
+ {
+ return false;
+ }
+ if (content_type == NULL)
+ {
+ content_type = "text/html; charset=utf-8";
+ }
+
+ ToStr(error_code_str, status_code);
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", error_code_str, status_string);
+
+ if (StrCmpi(request_headers->Method, "OPTIONS") == 0)
+ {
+ AddHttpValue(h, NewHttpValue("Allow", "OPTIONS, GET, POST"));
+ }
+
+ AddHttpValue(h, NewHttpValue("Cache-Control", "no-cache"));
+ AddHttpValue(h, NewHttpValue("Content-Type", content_type));
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Access-Control-Allow-Methods", "OPTIONS,GET,POST"));
+ AddHttpValue(h, NewHttpValue("Access-Control-Allow-Headers", "X-VPNADMIN-HUBNAME,X-VPNADMIN-PASSWORD"));
+ AddHttpValue(h, NewHttpValue("Access-Control-Allow-Credentials", "true"));
+
+ origin = GetHttpValue(request_headers, "Origin");
+ if (origin != NULL)
+ {
+ AddHttpValue(h, NewHttpValue("Access-Control-Allow-Origin", origin->Data));
+ }
+
+ if (add_header_name != NULL && add_header_value != NULL)
+ {
+ AddHttpValue(h, NewHttpValue(add_header_name, add_header_value));
+ }
+
+ ret = PostHttp(s, h, data, data_size);
+
+ FreeHttpHeader(h);
+
+ return ret;
+}
+
+// Send 404 error
+bool AdminWebSend404Error(SOCK *s, HTTP_HEADER *request_headers)
+{
+ char *body = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL was not found on this server.</p></body></html>\r\n";
+ if (s == NULL || request_headers == NULL)
+ {
+ return false;
+ }
+
+ return AdminWebSendBody(s, 404, "Not Found", body, StrLen(body), NULL, NULL, NULL, request_headers);
+}
+
+// Send 302 redirect
+bool AdminWebSend302Redirect(SOCK *s, char *url, char *query_string, HTTP_HEADER *request_headers)
+{
+ bool ret = false;
+ char *txt;
+ UINT txt_size;
+ char *url2;
+ UINT url2_size;
+ char *body = "<html><head><title>Object moved</title></head><body>\r\n<h2>Object moved to <a href=\"$URL$\">here</a>.</h2>\r\n</body></html>";
+ if (s == NULL || url == NULL || request_headers == NULL)
+ {
+ return false;
+ }
+
+ url2_size = (StrSize(url) + StrSize(query_string) + MAX_SIZE) * 2;
+ url2 = ZeroMalloc(url2_size);
+
+ StrCpy(url2, url2_size, url);
+ if (IsEmptyStr(query_string) == false)
+ {
+ StrCat(url2, url2_size, "?");
+ StrCat(url2, url2_size, query_string);
+ }
+
+ txt_size = (StrSize(body) + StrSize(url2) + MAX_SIZE) * 2;
+ txt = ZeroMalloc(txt_size);
+
+ ReplaceStrEx(txt, txt_size, body, "$URL$", url2, false);
+
+ ret = AdminWebSendBody(s, 302, "Found", txt, StrLen(txt), NULL, "Location", url2, request_headers);
+
+ Free(txt);
+
+ Free(url2);
+
+ return ret;
+}
+
+// "/admin" web page POST handler
+void AdminWebProcPost(CONNECTION *c, SOCK *s, HTTP_HEADER *h, UINT post_data_size, char *url_target)
+{
+ ADMIN *a;
+ UCHAR *data;
+ char url[MAX_PATH];
+ char query_string[MAX_SIZE];
+ UINT i;
+ if (c == NULL || s == NULL || h == NULL || url_target == NULL)
+ {
+ return;
+ }
+
+ a = JsonRpcAuthLogin(c->Cedar, s, h);
+ if (a == NULL)
+ {
+ RecvAllWithDiscard(s, post_data_size, s->SecureMode);
+ AdminWebSendUnauthorized(s, h);
+ return;
+ }
+
+ if (post_data_size > a->MaxJsonRpcRecvSize)
+ {
+ Disconnect(s);
+ return;
+ }
+
+ data = ZeroMalloc(post_data_size + 1);
+
+ if (RecvAll(s, data, post_data_size, s->SecureMode))
+ {
+ c->JsonRpcAuthed = true;
+
+ // Divide url_target into URL and query string
+ StrCpy(url, sizeof(url), url_target);
+ Zero(query_string, sizeof(query_string));
+ i = SearchStr(url, "?", 0);
+ if (i != INFINITE)
+ {
+ StrCpy(query_string, sizeof(query_string), url + i + 1);
+ url[i] = 0;
+ }
+
+ AdminWebHandleFileRequest(a, c, s, h, url, query_string, "/admin", "|wwwroot/admin");
+ }
+
+ Free(data);
+ Free(a);
+}
+
+// "/admin" web page GET handler
+void AdminWebProcGet(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target)
+{
+ ADMIN *a;
+ char url[MAX_PATH];
+ char query_string[MAX_SIZE];
+ UINT i;
+ if (c == NULL || s == NULL || h == NULL || url_target == NULL)
+ {
+ return;
+ }
+
+ a = JsonRpcAuthLogin(c->Cedar, s, h);
+ if (a == NULL)
+ {
+ AdminWebSendUnauthorized(s, h);
+ return;
+ }
+
+ c->JsonRpcAuthed = true;
+
+ // Divide url_target into URL and query string
+ StrCpy(url, sizeof(url), url_target);
+ Zero(query_string, sizeof(query_string));
+ i = SearchStr(url, "?", 0);
+ if (i != INFINITE)
+ {
+ StrCpy(query_string, sizeof(query_string), url + i + 1);
+ url[i] = 0;
+ }
+
+ AdminWebHandleFileRequest(a, c, s, h, url, query_string, "/admin", "|wwwroot/admin");
+
+ Free(a);
+}
+
+// New JSON-RPC Result
+JSON_VALUE *JsonRpcNewResponse(PACK *p)
+{
+ JSON_VALUE *jv;
+ JSON_OBJECT *jo;
+ JSON_VALUE *jv2;
+
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ jv = JsonNewObject();
+ jo = JsonValueGetObject(jv);
+
+ jv2 = PackToJson(p);
+
+ JsonSet(jo, "result", jv2);
+
+ return jv;
+}
+
+// New JSON-RPC Error
+JSON_VALUE *JsonRpcNewError(int code, wchar_t *message)
+{
+ wchar_t msg[MAX_PATH];
+ JSON_VALUE *jv;
+ JSON_OBJECT *jo;
+ JSON_VALUE *jv2;
+ JSON_OBJECT *jo2;
+
+ if (UniIsEmptyStr(message))
+ {
+ UniFormat(msg, sizeof(msg), L"Error code %u", code);
+ }
+ else
+ {
+ UniFormat(msg, sizeof(msg), L"Error code %u: %s", code, message);
+ }
+
+ jv = JsonNewObject();
+ jo = JsonValueGetObject(jv);
+
+ jv2 = JsonNewObject();
+ jo2 = JsonValueGetObject(jv2);
+
+ JsonSet(jo, "error", jv2);
+
+ JsonSetNumber(jo2, "code", (UINT64)code);
+ JsonSetUniStr(jo2, "message", msg);
+
+ return jv;
+}
+
+// JSON-RPC process request object
+JSON_VALUE *JsonRpcProcRequestObject(ADMIN *admin, CONNECTION *c, SOCK *s, JSON_VALUE *json_req, char *method_name)
+{
+ PACK *pack_request;
+ JSON_VALUE *ret = NULL;
+ if (c == NULL || s == NULL || json_req == NULL || admin == NULL)
+ {
+ return NULL;
+ }
+
+ pack_request = JsonToPack(json_req);
+
+ PackAddStr(pack_request, "function_name", method_name);
+
+ if (pack_request != NULL)
+ {
+ RPC *rpc;
+ PACK *pack_response;
+ UINT err;
+
+ // RPC Server
+ rpc = StartRpcServer(s, AdminDispatch, admin);
+
+ admin->Rpc = rpc;
+
+ pack_response = CallRpcDispatcher(rpc, pack_request);
+
+ if (pack_response == NULL)
+ {
+ pack_response = PackError(ERR_NOT_SUPPORTED);
+ }
+
+ RpcFreeEx(rpc, true);
+
+ FreePack(pack_request);
+
+ // Construct response object
+ err = GetErrorFromPack(pack_response);
+ if (err != 0)
+ {
+ // Return the error
+ ret = JsonRpcNewError(err, _E(err));
+ }
+ else
+ {
+ // Return the PACK
+ ret = JsonRpcNewResponse(pack_response);
+ }
+
+ SLog(admin->Server->Cedar, "LS_API_RPC_CALL",
+ &s->RemoteIP, s->RemotePort, s->RemoteHostname,
+ method_name, err, _E(err));
+
+ FreePack(pack_response);
+ }
+
+ return ret;
+}
+
+// JSON-RPC HTTP user authentication
+bool HttpParseBasicAuthHeader(HTTP_HEADER *h, char *username, UINT username_size, char *password, UINT password_size)
+{
+ bool ret = false;
+ HTTP_VALUE *auth_value;
+ HTTP_VALUE *vpnadmin_hubname;
+ HTTP_VALUE *vpnadmin_password;
+ if (h == NULL || username == NULL || password == NULL)
+ {
+ return false;
+ }
+
+ auth_value = GetHttpValue(h, "Authorization");
+ vpnadmin_hubname = GetHttpValue(h, "X-VPNADMIN-HUBNAME");
+ vpnadmin_password = GetHttpValue(h, "X-VPNADMIN-PASSWORD");
+
+ if (vpnadmin_password != NULL)
+ {
+ if (vpnadmin_hubname == NULL)
+ {
+ StrCpy(username, username_size, "");
+ }
+ else
+ {
+ StrCpy(username, username_size, vpnadmin_hubname->Data);
+ }
+
+ StrCpy(password, password_size, vpnadmin_password->Data);
+
+ ret = true;
+ }
+
+ if (ret == false && auth_value != NULL)
+ {
+ char key[32], value[MAX_SIZE];
+
+ if (GetKeyAndValue(auth_value->Data, key, sizeof(key), value, sizeof(value), " \t"))
+ {
+ if (StrCmpi(key, "Basic") == 0 && IsEmptyStr(value) == false)
+ {
+ UINT b64_dest_size = StrSize(value) * 2 + 256;
+ char *b64_dest = ZeroMalloc(b64_dest_size);
+
+ Decode64(b64_dest, value);
+
+ if (IsEmptyStr(b64_dest) == false)
+ {
+ if (b64_dest[0] == ':')
+ {
+ // Empty username
+ StrCpy(username, username_size, "");
+ StrCpy(password, password_size, b64_dest + 1);
+ ret = true;
+ }
+ else
+ {
+ if (GetKeyAndValue(b64_dest, username, username_size, password, password_size, ":"))
+ {
+ ret = true;
+ }
+ }
+ }
+
+ Free(b64_dest);
+ }
+ }
+ }
+
+ return ret;
+}
+
+// JSON-RPC Login
+ADMIN *JsonRpcAuthLogin(CEDAR *c, SOCK *sock, HTTP_HEADER *h)
+{
+ ADMIN *a = NULL;
+ char username[MAX_HUBNAME_LEN + 1];
+ char password[MAX_PASSWORD_LEN + 1];
+ SERVER *s;
+ char empty_pw_hash[SHA1_SIZE];
+
+ if (c == NULL || h == NULL || sock == NULL)
+ {
+ return NULL;
+ }
+
+ s = c->Server;
+
+ HashAdminPassword(empty_pw_hash, "");
+
+ Zero(username, sizeof(username));
+ Zero(password, sizeof(password));
+
+ if (HttpParseBasicAuthHeader(h, username, sizeof(username), password, sizeof(password)))
+ {
+ char pw_hash[SHA1_SIZE];
+ bool is_server_admin = false;
+ bool is_hub_admin = false;
+ char hub_name[MAX_HUBNAME_LEN + 1];
+
+ HashAdminPassword(pw_hash, password);
+
+ Zero(hub_name, sizeof(hub_name));
+
+ // Check if the server administrator password is empty. If yes, login always success.
+ if (Cmp(s->HashedPassword, empty_pw_hash, SHA1_SIZE) == 0)
+ {
+ is_server_admin = true;
+ }
+ else
+ {
+ if (IsEmptyStr(username) || StrCmpi(username, ADMINISTRATOR_USERNAME) == 0)
+ {
+ // If the username is empty or 'administrator', verify with the server admin password.
+ if (Cmp(s->HashedPassword, pw_hash, SHA1_SIZE) == 0)
+ {
+ is_server_admin = true;
+ }
+ }
+ }
+
+ if (is_server_admin == false)
+ {
+ HUB *h;
+ // Hub admin mode
+ LockHubList(c);
+ {
+ h = GetHub(c, username);
+ }
+ UnlockHubList(c);
+
+ if (h != NULL)
+ {
+ Lock(h->lock);
+ {
+ if (Cmp(pw_hash, h->HashedPassword, SHA1_SIZE) == 0)
+ {
+ is_hub_admin = true;
+
+ StrCpy(hub_name, sizeof(hub_name), h->Name);
+ }
+ }
+ Unlock(h->lock);
+
+ ReleaseHub(h);
+ }
+ }
+
+ if (is_server_admin || is_hub_admin)
+ {
+ if (CheckAdminSourceAddress(sock, hub_name))
+ {
+ a = ZeroMalloc(sizeof(ADMIN));
+
+ a->Server = s;
+ a->ServerAdmin = is_server_admin;
+ a->ClientBuild = c->Build;
+
+ if (is_hub_admin)
+ {
+ StrCpy(a->dummy1, sizeof(a->dummy1), hub_name);
+ a->HubName = a->dummy1;
+ }
+ }
+ }
+ }
+
+ if (a != NULL)
+ {
+ char admin_mode[256];
+ if (a->ServerAdmin)
+ {
+ a->MaxJsonRpcRecvSize = ADMIN_RPC_MAX_POST_SIZE_BY_SERVER_ADMIN;
+ }
+ else
+ {
+ a->MaxJsonRpcRecvSize = ADMIN_RPC_MAX_POST_SIZE_BY_HUB_ADMIN;
+ }
+
+ if (IsEmptyStr(a->HubName))
+ {
+ StrCpy(admin_mode, sizeof(admin_mode),
+ "Entire VPN Server Admin Mode");
+ }
+ else
+ {
+ Format(admin_mode, sizeof(admin_mode),
+ "Virtual Hub Admin Mode for '%s'",
+ a->HubName);
+ }
+
+ SLog(s->Cedar, "LS_API_AUTH_OK",
+ &sock->RemoteIP, sock->RemotePort, sock->RemoteHostname,
+ admin_mode, username, h->Method, h->Target);
+ }
+ else
+ {
+ SLog(s->Cedar, "LS_API_AUTH_ERROR",
+ &sock->RemoteIP, sock->RemotePort, sock->RemoteHostname,
+ username, h->Method, h->Target);
+ }
+
+
+ return a;
+}
+
+// Query string to JSON list value
+JSON_VALUE *QueryStringToJsonListValue(char *qs)
+{
+ TOKEN_LIST *t;
+ UINT i;
+ LIST *distinct_list = NULL;
+ JSON_VALUE *v = NULL;
+ JSON_OBJECT *o = NULL;
+ if (qs == NULL)
+ {
+ return NULL;
+ }
+
+ t = ParseTokenWithoutNullStr(qs, "&");
+ if (t == NULL)
+ {
+ return NULL;
+ }
+
+ distinct_list = NewStrList();
+
+ v = JsonNewObject();
+ o = JsonValueGetObject(v);
+
+ for (i = 0;i < t->NumTokens;i++)
+ {
+ char *token = t->Token[i];
+ UINT pos;
+
+ pos = SearchStr(token, "=", 0);
+ if (pos != INFINITE)
+ {
+ char *key_decoded;
+ char *value_decoded;
+ char *key = CopyStr(token);
+ char *value = CopyStr(token + pos + 1);
+
+ key[pos] = 0;
+ key_decoded = UrlDecode(key);
+ value_decoded = UrlDecode(value);
+
+ if (key_decoded != NULL && value_decoded != NULL)
+ {
+ if (AddStrToStrListDistinct(distinct_list, key_decoded))
+ {
+ JsonSetStr(o, key_decoded, value_decoded);
+ }
+ }
+
+ Free(value_decoded);
+ Free(key_decoded);
+ Free(key);
+ Free(value);
+ }
+ }
+
+ FreeToken(t);
+
+ FreeStrList(distinct_list);
+
+ return v;
+}
+
+// Construct new JSON-RPC dummy request
+JSON_VALUE *ConstructDummyJsonRpcRequest(char *method_name, JSON_VALUE *p)
+{
+ JSON_VALUE *ret;
+ JSON_OBJECT *ret_object;
+ UCHAR rand[16];
+ char id_str[64];
+
+ Rand(rand, sizeof(rand));
+
+ BinToStr(id_str, sizeof(id_str), rand, sizeof(rand));
+
+ ret = JsonNewObject();
+ ret_object = JsonObject(ret);
+
+ JsonSetStr(ret_object, "jsonrpc", "2.0");
+ JsonSetStr(ret_object, "method", method_name);
+ JsonSet(ret_object, "params", p);
+ JsonSetStr(ret_object, "id", id_str);
+
+ return ret;
+}
+
+// JSON-RPC Options Dispatch
+void JsonRpcProcOptions(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target)
+{
+ if (c == NULL || s == NULL || h == NULL || url_target == NULL)
+ {
+ return;
+ }
+
+ c->JsonRpcAuthed = true;
+
+
+ AdminWebSendBody(s, 200, "OK", NULL, 0, NULL, NULL, NULL, h);
+}
+
+// JSON-RPC GET Dispatch
+void JsonRpcProcGet(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target)
+{
+ ADMIN *a;
+ char url[MAX_PATH];
+ char query_string[MAX_SIZE];
+ UINT i;
+ bool reply_sent = false;
+ if (c == NULL || s == NULL || h == NULL || url_target == NULL)
+ {
+ return;
+ }
+
+ a = JsonRpcAuthLogin(c->Cedar, s, h);
+ if (a == NULL)
+ {
+ AdminWebSendUnauthorized(s, h);
+ return;
+ }
+
+ c->JsonRpcAuthed = true;
+
+
+ // Divide url_target into URL and query string
+ StrCpy(url, sizeof(url), url_target);
+ Zero(query_string, sizeof(query_string));
+ i = SearchStr(url, "?", 0);
+ if (i != INFINITE)
+ {
+ StrCpy(query_string, sizeof(query_string), url + i + 1);
+ url[i] = 0;
+ }
+
+ if (StartWith(url, "/api/"))
+ {
+ // Call a method
+ JSON_VALUE *params_value = NULL;
+ JSON_OBJECT *params_object = NULL;
+ UINT i;
+ char method_name[MAX_PATH];
+
+ StrCpy(method_name, sizeof(method_name), url + 5);
+
+ i = SearchStr(method_name, "/", 0);
+ if (i != INFINITE)
+ {
+ method_name[i] = 0;
+ }
+
+ if (IsEmptyStr(method_name) == false)
+ {
+ // Call a method
+ params_value = QueryStringToJsonListValue(query_string);
+
+ if (params_value != NULL)
+ {
+ JSON_VALUE *json_ret = NULL;
+ char id[96];
+ char *ret_str = NULL;
+
+ GetDateTimeStrMilli64(id, sizeof(id), LocalTime64());
+
+ params_object = JsonObject(params_value);
+
+ // Process the request
+ json_ret = JsonRpcProcRequestObject(a, c, s, params_value, method_name);
+
+ if (json_ret == NULL)
+ {
+ json_ret = JsonRpcNewError(ERR_INTERNAL_ERROR, L"Internal error");
+ }
+
+ JsonSetStr(JsonObject(json_ret), "jsonrpc", "2.0");
+ JsonSetStr(JsonObject(json_ret), "id", id);
+
+ ret_str = JsonToStr(json_ret);
+
+ AdminWebSendBody(s, 200, "OK", ret_str, StrLen(ret_str), "text/plain; charset=UTF-8", NULL, NULL, h);
+
+ Free(ret_str);
+ JsonFree(json_ret);
+ JsonFree(params_value);
+ }
+ }
+ }
+
+
+ if (reply_sent == false)
+ {
+ BUF *html_buf = ReadDump("|vpnserver_api_doc.html");
+
+ if (html_buf != NULL)
+ {
+ AdminWebSendBody(s, 200, "OK", html_buf->Buf, html_buf->Size, "text/html; charset=UTF-8", NULL, NULL, h);
+
+ FreeBuf(html_buf);
+ }
+ else
+ {
+ AdminWebSend404Error(s, h);
+ }
+ }
+
+ if (a->LogFileList != NULL)
+ {
+ FreeEnumLogFile(a->LogFileList);
+ }
+ Free(a);
+}
+
+// JSON-RPC POST Dispatch
+void JsonRpcProcPost(CONNECTION *c, SOCK *s, HTTP_HEADER *h, UINT post_data_size)
+{
+ ADMIN *a;
+ UCHAR *data;
+ if (c == NULL || s == NULL || h == NULL)
+ {
+ return;
+ }
+
+ a = JsonRpcAuthLogin(c->Cedar, s, h);
+ if (a == NULL)
+ {
+ RecvAllWithDiscard(s, post_data_size, s->SecureMode);
+ AdminWebSendUnauthorized(s, h);
+ return;
+ }
+
+ if (post_data_size > a->MaxJsonRpcRecvSize)
+ {
+ Disconnect(s);
+ return;
+ }
+
+ data = ZeroMalloc(post_data_size + 1);
+
+ if (RecvAll(s, data, post_data_size, s->SecureMode))
+ {
+ // Parse JSON
+ JSON_VALUE *json_req = StrToJson(data);
+ JSON_OBJECT *json_req_object = JsonObject(json_req);
+ JSON_VALUE *json_ret = NULL;
+ char *res = NULL;
+ char *request_id = NULL;
+ char *method_name = NULL;
+
+ c->JsonRpcAuthed = true;
+
+
+ if (json_req == NULL || json_req_object == NULL)
+ {
+ // Parse error
+ json_ret = JsonRpcNewError(ERR_INVALID_PARAMETER, L"Parameter is invalid: JSON-RPC Parse Error");
+ }
+ else
+ {
+ // check the JSON-RPC version
+ char *ver_str = JsonGetStr(json_req_object, "jsonrpc");
+ if (StrCmpi(ver_str, "2.0") != 0)
+ {
+ // Invalid version
+ json_ret = JsonRpcNewError(ERR_INVALID_PARAMETER, L"JSON-RPC version is invalid");
+ }
+ else
+ {
+ JSON_VALUE *params_value = NULL;
+ JSON_OBJECT *params_object = NULL;
+
+ // Get Request ID
+ request_id = JsonGetStr(json_req_object, "id");
+
+ // Get method name
+ method_name = JsonGetStr(json_req_object, "method");
+
+ // Get parameters
+ params_value = JsonGet(json_req_object, "params");
+ params_object = JsonObject(params_value);
+
+ if (IsEmptyStr(method_name))
+ {
+ // method is empty
+ json_ret = JsonRpcNewError(ERR_INVALID_PARAMETER, L"JSON-RPC method name is empty");
+ }
+ else if (params_value == NULL || params_object == NULL)
+ {
+ // params is empty
+ json_ret = JsonRpcNewError(ERR_INVALID_PARAMETER, L"JSON-RPC parameter is empty");
+ }
+ else
+ {
+ // Process the request
+ json_ret = JsonRpcProcRequestObject(a, c, s, params_value, method_name);
+ }
+ }
+ }
+
+ if (json_ret == NULL)
+ {
+ json_ret = JsonRpcNewError(ERR_INTERNAL_ERROR, L"Internal error");
+ }
+
+ JsonSetStr(JsonObject(json_ret), "jsonrpc", "2.0");
+ if (request_id == NULL)
+ {
+ request_id = "0";
+ }
+ JsonSetStr(JsonObject(json_ret), "id", request_id);
+
+ res = JsonToStr(json_ret);
+
+ AdminWebSendBody(s, 200, "OK", res, StrLen(res), "application/json", NULL, NULL, h);
+
+ Free(res);
+
+ JsonFree(json_ret);
+ JsonFree(json_req);
+ }
+
+ Free(data);
+
+ if (a->LogFileList != NULL)
+ {
+ FreeEnumLogFile(a->LogFileList);
+ }
+ Free(a);
+}
+
// Dispatch routine for Administration RPC
PACK *AdminDispatch(RPC *rpc, char *name, PACK *p)
{
@@ -1103,11 +2237,6 @@ UINT StMakeOpenVpnConfigFile(ADMIN *a, RPC_READ_LOG_FILE *t)
UCHAR *zero_buffer;
UINT zero_buffer_size = 128 * 1024;
char name_tmp[MAX_SIZE];
- X *dummy_x = NULL;
- K *dummy_private_k = NULL;
- K *dummy_public_k = NULL;
- BUF *dummy_x_buf = NULL;
- BUF *dummy_k_buf = NULL;
zero_buffer = ZeroMalloc(zero_buffer_size);
@@ -1145,34 +2274,6 @@ UINT StMakeOpenVpnConfigFile(ADMIN *a, RPC_READ_LOG_FILE *t)
WriteBufChar(x_buf, 0);
SeekBufToBegin(x_buf);
- // Generate a dummy certificate
- if (x != NULL)
- {
- if (RsaGen(&dummy_private_k, &dummy_public_k, x->bits))
- {
- NAME *name;
- wchar_t cn[128];
-
- UniToStr64(cn, Rand64());
-
- name = NewName(cn, cn, cn, L"US", NULL, NULL);
-
- dummy_x = NewRootX(dummy_public_k, dummy_private_k, name, GetDaysUntil2038Ex(), NULL);
-
- FreeName(name);
-
- dummy_x_buf = XToBuf(dummy_x, true);
- SeekBufToEnd(dummy_x_buf);
- WriteBufChar(dummy_x_buf, 0);
- SeekBufToBegin(dummy_x_buf);
-
- dummy_k_buf = KToBuf(dummy_private_k, true, NULL);
- SeekBufToEnd(dummy_k_buf);
- WriteBufChar(dummy_k_buf, 0);
- SeekBufToBegin(dummy_k_buf);
- }
- }
-
FreeX(x);
Zero(hostname, sizeof(hostname));
Zero(tag_before_hostname, sizeof(tag_before_hostname));
@@ -1290,18 +2391,6 @@ UINT StMakeOpenVpnConfigFile(ADMIN *a, RPC_READ_LOG_FILE *t)
"$CA$", x_buf->Buf, false);
}
- if (dummy_x_buf != NULL)
- {
- ReplaceStrEx((char *)config_l3_buf->Buf, config_l3_buf->Size, (char *)config_l3_buf->Buf,
- "$CERT$", dummy_x_buf->Buf, false);
- }
-
- if (dummy_k_buf != NULL)
- {
- ReplaceStrEx((char *)config_l3_buf->Buf, config_l3_buf->Size, (char *)config_l3_buf->Buf,
- "$KEY$", dummy_k_buf->Buf, false);
- }
-
Format(name_tmp, sizeof(name_tmp), "%sopenvpn_remote_access_l3.ovpn", my_hostname);
ZipAddFileSimple(p, name_tmp, LocalTime64(), 0, config_l3_buf->Buf, StrLen(config_l3_buf->Buf));
@@ -1322,18 +2411,6 @@ UINT StMakeOpenVpnConfigFile(ADMIN *a, RPC_READ_LOG_FILE *t)
"$CA$", x_buf->Buf, false);
}
- if (dummy_x_buf != NULL)
- {
- ReplaceStrEx((char *)config_l2_buf->Buf, config_l2_buf->Size, (char *)config_l2_buf->Buf,
- "$CERT$", dummy_x_buf->Buf, false);
- }
-
- if (dummy_k_buf != NULL)
- {
- ReplaceStrEx((char *)config_l2_buf->Buf, config_l2_buf->Size, (char *)config_l2_buf->Buf,
- "$KEY$", dummy_k_buf->Buf, false);
- }
-
Format(name_tmp, sizeof(name_tmp), "%sopenvpn_site_to_site_bridge_l2.ovpn", my_hostname);
ZipAddFileSimple(p, name_tmp, LocalTime64(), 0, config_l2_buf->Buf, StrLen(config_l2_buf->Buf));
@@ -1354,13 +2431,6 @@ UINT StMakeOpenVpnConfigFile(ADMIN *a, RPC_READ_LOG_FILE *t)
FreeBuf(readme_pdf_buf);
FreeBuf(x_buf);
- FreeX(dummy_x);
- FreeK(dummy_private_k);
- FreeK(dummy_public_k);
-
- FreeBuf(dummy_k_buf);
- FreeBuf(dummy_x_buf);
-
Free(zero_buffer);
}
@@ -1954,8 +3024,20 @@ UINT StReadLogFile(ADMIN *a, RPC_READ_LOG_FILE *t)
// Check the permission to read the log file
if (a->LogFileList == NULL)
{
- // Cache not found
- return ERR_OBJECT_NOT_FOUND;
+ // Enum the log files first
+ RPC_ENUM_LOG_FILE elf;
+ UINT elf_ret;
+
+ Zero(&elf, sizeof(elf));
+
+ elf_ret = StEnumLogFile(a, &elf);
+
+ FreeRpcEnumLogFile(&elf);
+
+ if (elf_ret != ERR_NO_ERROR)
+ {
+ return elf_ret;
+ }
}
if (CheckLogFileNameFromEnumList(a->LogFileList, logfilename, servername) == false)
{
@@ -2020,6 +3102,10 @@ UINT StReadLogFile(ADMIN *a, RPC_READ_LOG_FILE *t)
ALog(a, NULL, "LA_READ_LOG_FILE", servername, logfilename);
}
+ StrCpy(t->FilePath, sizeof(t->FilePath), logfilename);
+ StrCpy(t->ServerName, sizeof(t->ServerName), servername);
+ t->Offset = offset;
+
return ERR_NO_ERROR;
}
@@ -2310,7 +3396,7 @@ UINT StSetCrl(ADMIN *a, RPC_CRL *t)
if (crl == NULL)
{
- ret = ERR_INTERNAL_ERROR;
+ ret = ERR_OBJECT_NOT_FOUND;
}
else
{
@@ -2379,7 +3465,7 @@ UINT StGetCrl(ADMIN *a, RPC_CRL *t)
if (crl == NULL)
{
- ret = ERR_INTERNAL_ERROR;
+ ret = ERR_OBJECT_NOT_FOUND;
}
else
{
@@ -2439,7 +3525,7 @@ UINT StDelCrl(ADMIN *a, RPC_CRL *t)
if (crl == NULL)
{
- ret = ERR_INTERNAL_ERROR;
+ ret = ERR_OBJECT_NOT_FOUND;
}
else
{
@@ -3336,6 +4422,7 @@ UINT StGetHubAdminOptions(ADMIN *a, RPC_ADMIN_OPTION *t)
StrCpy(e->Name, sizeof(e->Name), a->Name);
e->Value = a->Value;
+ UniStrCpy(e->Descrption, sizeof(e->Descrption), GetHubAdminOptionHelpString(e->Name));
}
}
UnlockList(h->AdminOptionList);
@@ -3368,6 +4455,7 @@ UINT StGetDefaultHubAdminOptions(ADMIN *a, RPC_ADMIN_OPTION *t)
StrCpy(a->Name, sizeof(a->Name), admin_options[i].Name);
a->Value = admin_options[i].Value;
+ UniStrCpy(a->Descrption, sizeof(a->Descrption), GetHubAdminOptionHelpString(a->Name));
}
return ERR_NO_ERROR;
@@ -3872,6 +4960,7 @@ UINT SiEnumIpTable(SERVER *s, char *hubname, RPC_ENUM_IP_TABLE *t)
StrCpy(e->SessionName, sizeof(e->SessionName), table->Session->Name);
e->Ip = IPToUINT(&table->Ip);
Copy(&e->IpV6, &table->Ip, sizeof(IP));
+ Copy(&e->IpAddress, &table->Ip, sizeof(IP));
e->DhcpAllocated = table->DhcpAllocated;
e->CreatedTime = TickToTime(table->CreatedTime);
e->UpdatedTime = TickToTime(table->UpdatedTime);
@@ -4323,6 +5412,8 @@ UINT StGetSessionStatus(ADMIN *a, RPC_SESSION_STATUS *t)
Copy(&t->ClientIp6, &s->Connection->ClientIp.ipv6_addr, sizeof(t->ClientIp6));
}
+ CopyIP(&t->ClientIpAddress, &s->Connection->ClientIp);
+
StrCpy(t->ClientHostName, sizeof(t->ClientHostName), s->Connection->ClientHostname);
}
}
@@ -5485,30 +6576,33 @@ UINT StSetAccessList(ADMIN *a, RPC_ENUM_ACCESS_LIST *t)
UINT i;
// Confirm whether the access list of form which cannot handle by the old client already exists
- if (a->ClientBuild < 6560)
+ if (a->ClientBuild != 0)
{
- for (i = 0;i < LIST_NUM(h->AccessList);i++)
+ if (a->ClientBuild < 6560)
{
- ACCESS *access = LIST_DATA(h->AccessList, i);
- if (access->IsIPv6 ||
- access->Jitter != 0 || access->Loss != 0 || access->Delay != 0)
+ for (i = 0;i < LIST_NUM(h->AccessList);i++)
{
- ret = ERR_VERSION_INVALID;
- break;
+ ACCESS *access = LIST_DATA(h->AccessList, i);
+ if (access->IsIPv6 ||
+ access->Jitter != 0 || access->Loss != 0 || access->Delay != 0)
+ {
+ ret = ERR_VERSION_INVALID;
+ break;
+ }
}
}
- }
- if (a->ClientBuild < 8234)
- {
- for (i = 0;i < LIST_NUM(h->AccessList);i++)
+ if (a->ClientBuild < 8234)
{
- ACCESS *access = LIST_DATA(h->AccessList, i);
-
- if (IsEmptyStr(access->RedirectUrl) == false)
+ for (i = 0;i < LIST_NUM(h->AccessList);i++)
{
- ret = ERR_VERSION_INVALID;
- break;
+ ACCESS *access = LIST_DATA(h->AccessList, i);
+
+ if (IsEmptyStr(access->RedirectUrl) == false)
+ {
+ ret = ERR_VERSION_INVALID;
+ break;
+ }
}
}
}
@@ -6612,6 +7706,7 @@ UINT StGetCa(ADMIN *a, RPC_HUB_GET_CA *t)
FreeRpcHubGetCa(t);
Zero(t, sizeof(RPC_HUB_GET_CA));
+ t->Key = key;
StrCpy(t->HubName, sizeof(t->HubName), hubname);
CHECK_RIGHT;
@@ -7207,6 +8302,7 @@ UINT StGetSecureNATStatus(ADMIN *a, RPC_NAT_STATUS *t)
ReleaseHub(h);
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
ret = ERR_NO_ERROR;
return ret;
@@ -7446,8 +8542,8 @@ UINT StGetSecureNATOption(ADMIN *a, VH_OPTION *t)
}
Zero(t, sizeof(VH_OPTION));
- StrCpy(t->HubName, sizeof(t->HubName), hubname);
Copy(t, h->SecureNATOption, sizeof(VH_OPTION));
+ StrCpy(t->HubName, sizeof(t->HubName), hubname);
t->ApplyDhcpPushRoutes = true;
ReleaseHub(h);
@@ -8058,6 +9154,13 @@ UINT StSetHub(ADMIN *a, RPC_CREATE_HUB *t)
return ERR_NOT_SUPPORTED;
}
+ // For JSON-RPC
+ if (StrLen(t->AdminPasswordPlainText) != 0)
+ {
+ Hash(t->HashedPassword, t->AdminPasswordPlainText, StrLen(t->AdminPasswordPlainText), true);
+ HashPassword(t->SecurePassword, ADMINISTRATOR_USERNAME, t->AdminPasswordPlainText);
+ }
+
if (IsZero(t->HashedPassword, sizeof(t->HashedPassword)) == false &&
IsZero(t->SecurePassword, sizeof(t->SecurePassword)) == false)
{
@@ -8228,6 +9331,15 @@ UINT StCreateHub(ADMIN *a, RPC_CREATE_HUB *t)
ALog(a, NULL, "LA_CREATE_HUB", t->HubName);
+ // For JSON-RPC
+ if ((IsZero(t->HashedPassword, sizeof(t->HashedPassword)) &&
+ IsZero(t->SecurePassword, sizeof(t->SecurePassword))) ||
+ StrLen(t->AdminPasswordPlainText) != 0)
+ {
+ Hash(t->HashedPassword, t->AdminPasswordPlainText, StrLen(t->AdminPasswordPlainText), true);
+ HashPassword(t->SecurePassword, ADMINISTRATOR_USERNAME, t->AdminPasswordPlainText);
+ }
+
h = NewHub(c, t->HubName, &o);
Copy(h->HashedPassword, t->HashedPassword, SHA1_SIZE);
Copy(h->SecurePassword, t->SecurePassword, SHA1_SIZE);
@@ -8636,6 +9748,15 @@ UINT StSetFarmSetting(ADMIN *a, RPC_FARM *t)
return ERR_NOT_SUPPORTED;
}
+ if (IsZero(t->MemberPassword, sizeof(t->MemberPassword)))
+ {
+ if (IsEmptyStr(t->MemberPasswordPlaintext) == false)
+ {
+ // For JSON-RPC
+ HashAdminPassword(t->MemberPassword, t->MemberPasswordPlaintext);
+ }
+ }
+
ALog(a, NULL, "LA_SET_FARM_SETTING");
IncrementServerConfigRevision(a->Server);
@@ -8652,6 +9773,12 @@ UINT StSetServerPassword(ADMIN *a, RPC_SET_PASSWORD *t)
SERVER_ADMIN_ONLY;
+ if (IsZero(t->HashedPassword, sizeof(t->HashedPassword)))
+ {
+ // For JSON-RPC
+ HashAdminPassword(t->HashedPassword, t->PlainTextPassword);
+ }
+
Copy(a->Server->HashedPassword, t->HashedPassword, SHA1_SIZE);
ALog(a, NULL, "LA_SET_SERVER_PASSWORD");
@@ -9016,6 +10143,8 @@ void InDDnsClientStatus(DDNS_CLIENT_STATUS *t, PACK *p)
PackGetStr(p, "DnsSuffix", t->DnsSuffix, sizeof(t->DnsSuffix));
PackGetStr(p, "CurrentIPv4", t->CurrentIPv4, sizeof(t->CurrentIPv4));
PackGetStr(p, "CurrentIPv6", t->CurrentIPv6, sizeof(t->CurrentIPv6));
+ PackGetUniStr(p, "ErrStr_IPv4", t->ErrStr_IPv4, sizeof(t->ErrStr_IPv4));
+ PackGetUniStr(p, "ErrStr_IPv6", t->ErrStr_IPv6, sizeof(t->ErrStr_IPv6));
}
void OutDDnsClientStatus(PACK *p, DDNS_CLIENT_STATUS *t)
{
@@ -9032,6 +10161,8 @@ void OutDDnsClientStatus(PACK *p, DDNS_CLIENT_STATUS *t)
PackAddStr(p, "DnsSuffix", t->DnsSuffix);
PackAddStr(p, "CurrentIPv4", t->CurrentIPv4);
PackAddStr(p, "CurrentIPv6", t->CurrentIPv6);
+ PackAddUniStr(p, "ErrStr_IPv4", t->ErrStr_IPv4);
+ PackAddUniStr(p, "ErrStr_IPv6", t->ErrStr_IPv6);
}
// INTERNET_SETTING
@@ -9183,6 +10314,7 @@ void OutRpcEnumEtherIpId(PACK *p, RPC_ENUM_ETHERIP_ID *t)
PackAddInt(p, "NumItem", t->NumItem);
+ PackSetCurrentJsonGroupName(p, "Settings");
for (i = 0;i < t->NumItem;i++)
{
ETHERIP_ID *e = &t->IdList[i];
@@ -9192,6 +10324,7 @@ void OutRpcEnumEtherIpId(PACK *p, RPC_ENUM_ETHERIP_ID *t)
PackAddStrEx(p, "UserName", e->UserName, i, t->NumItem);
PackAddStrEx(p, "Password", e->Password, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumEtherIpId(RPC_ENUM_ETHERIP_ID *t)
{
@@ -9362,6 +10495,7 @@ void OutRpcEnumEthVLan(PACK *p, RPC_ENUM_ETH_VLAN *t)
return;
}
+ PackSetCurrentJsonGroupName(p, "Devices");
for (i = 0;i < t->NumItem;i++)
{
RPC_ENUM_ETH_VLAN_ITEM *e = &t->Items[i];
@@ -9374,6 +10508,7 @@ void OutRpcEnumEthVLan(PACK *p, RPC_ENUM_ETH_VLAN *t)
PackAddBoolEx(p, "Support", e->Support, i, t->NumItem);
PackAddBoolEx(p, "Enabled", e->Enabled, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumEthVLan(RPC_ENUM_ETH_VLAN *t)
{
@@ -9421,6 +10556,7 @@ void OutRpcEnumLogFile(PACK *p, RPC_ENUM_LOG_FILE *t)
PackAddInt(p, "NumItem", t->NumItem);
+ PackSetCurrentJsonGroupName(p, "LogFiles");
for (i = 0;i < t->NumItem;i++)
{
RPC_ENUM_LOG_FILE_ITEM *e = &t->Items[i];
@@ -9428,8 +10564,9 @@ void OutRpcEnumLogFile(PACK *p, RPC_ENUM_LOG_FILE *t)
PackAddStrEx(p, "FilePath", e->FilePath, i, t->NumItem);
PackAddStrEx(p, "ServerName", e->ServerName, i, t->NumItem);
PackAddIntEx(p, "FileSize", e->FileSize, i, t->NumItem);
- PackAddInt64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumItem);
+ PackAddTime64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumLogFile(RPC_ENUM_LOG_FILE *t)
{
@@ -9564,12 +10701,13 @@ void InRpcAcList(RPC_AC_LIST *t, PACK *p)
o = NewAcList();
PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
- num = PackGetInt(p, "NumItem");
+ num = PackGetIndexCount(p, "IpAddress");
for (i = 0;i < num;i++)
{
AC *ac = ZeroMalloc(sizeof(AC));
+ ac->Id = PackGetIntEx(p, "Id", i);
ac->Deny = PackGetBoolEx(p, "Deny", i);
PackGetIpEx(p, "IpAddress", &ac->IpAddress, i);
ac->Masked = PackGetBoolEx(p, "Masked", i);
@@ -9605,10 +10743,12 @@ void OutRpcAcList(PACK *p, RPC_AC_LIST *t)
PackAddStr(p, "HubName", t->HubName);
+ PackSetCurrentJsonGroupName(p, "ACList");
for (i = 0;i < num;i++)
{
AC *ac = LIST_DATA(o, i);
+ PackAddIntEx(p, "Id", ac->Id, i, num);
PackAddBoolEx(p, "Deny", ac->Deny, i, num);
PackAddIpEx(p, "IpAddress", &ac->IpAddress, i, num);
PackAddBoolEx(p, "Masked", ac->Masked, i, num);
@@ -9617,6 +10757,7 @@ void OutRpcAcList(PACK *p, RPC_AC_LIST *t)
PackAddIntEx(p, "Priority", ac->Priority, i, num);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcAcList(RPC_AC_LIST *t)
{
@@ -9687,6 +10828,7 @@ void OutRpcEnumCrl(PACK *p, RPC_ENUM_CRL *t)
PackAddStr(p, "HubName", t->HubName);
PackAddInt(p, "NumItem", t->NumItem);
+ PackSetCurrentJsonGroupName(p, "CRLList");
for (i = 0;i < t->NumItem;i++)
{
RPC_ENUM_CRL_ITEM *e = &t->Items[i];
@@ -9694,6 +10836,7 @@ void OutRpcEnumCrl(PACK *p, RPC_ENUM_CRL *t)
PackAddIntEx(p, "Key", e->Key, i, t->NumItem);
PackAddUniStrEx(p, "CrlInfo", e->CrlInfo, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumCrl(RPC_ENUM_CRL *t)
{
@@ -9866,6 +11009,7 @@ void OutRpcEnumL3Table(PACK *p, RPC_ENUM_L3TABLE *t)
PackAddInt(p, "NumItem", t->NumItem);
PackAddStr(p, "Name", t->Name);
+ PackSetCurrentJsonGroupName(p, "L3Table");
for (i = 0;i < t->NumItem;i++)
{
RPC_L3TABLE *e = &t->Items[i];
@@ -9875,6 +11019,7 @@ void OutRpcEnumL3Table(PACK *p, RPC_ENUM_L3TABLE *t)
PackAddIp32Ex(p, "GatewayAddress", e->GatewayAddress, i, t->NumItem);
PackAddIntEx(p, "Metric", e->Metric, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumL3Table(RPC_ENUM_L3TABLE *t)
{
@@ -9948,6 +11093,7 @@ void OutRpcEnumL3If(PACK *p, RPC_ENUM_L3IF *t)
PackAddInt(p, "NumItem", t->NumItem);
PackAddStr(p, "Name", t->Name);
+ PackSetCurrentJsonGroupName(p, "L3IFList");
for (i = 0;i < t->NumItem;i++)
{
RPC_L3IF *f = &t->Items[i];
@@ -9956,6 +11102,7 @@ void OutRpcEnumL3If(PACK *p, RPC_ENUM_L3IF *t)
PackAddIp32Ex(p, "IpAddress", f->IpAddress, i, t->NumItem);
PackAddIp32Ex(p, "SubnetMask", f->SubnetMask, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumL3If(RPC_ENUM_L3IF *t)
{
@@ -10056,6 +11203,7 @@ void OutRpcEnumL3Sw(PACK *p, RPC_ENUM_L3SW *t)
PackAddInt(p, "NumItem", t->NumItem);
+ PackSetCurrentJsonGroupName(p, "L3SWList");
for (i = 0;i < t->NumItem;i++)
{
RPC_ENUM_L3SW_ITEM *s = &t->Items[i];
@@ -10066,6 +11214,7 @@ void OutRpcEnumL3Sw(PACK *p, RPC_ENUM_L3SW *t)
PackAddBoolEx(p, "Active", s->Active, i, t->NumItem);
PackAddBoolEx(p, "Online", s->Online, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumL3Sw(RPC_ENUM_L3SW *t)
{
@@ -10110,12 +11259,14 @@ void OutRpcEnumEth(PACK *p, RPC_ENUM_ETH *t)
PackAddInt(p, "NumItem", t->NumItem);
+ PackSetCurrentJsonGroupName(p, "EthList");
for (i = 0;i < t->NumItem;i++)
{
RPC_ENUM_ETH_ITEM *e = &t->Items[i];
PackAddStrEx(p, "DeviceName", e->DeviceName, i, t->NumItem);
PackAddUniStrEx(p, "NetworkConnectionName", e->NetworkConnectionName, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumEth(RPC_ENUM_ETH *t)
{
@@ -10191,6 +11342,7 @@ void OutRpcEnumLocalBridge(PACK *p, RPC_ENUM_LOCALBRIDGE *t)
PackAddInt(p, "NumItem", t->NumItem);
+ PackSetCurrentJsonGroupName(p, "LocalBridgeList");
for (i = 0;i < t->NumItem;i++)
{
RPC_LOCALBRIDGE *e = &t->Items[i];
@@ -10201,6 +11353,7 @@ void OutRpcEnumLocalBridge(PACK *p, RPC_ENUM_LOCALBRIDGE *t)
PackAddBoolEx(p, "Active", e->Active, i, t->NumItem);
PackAddBoolEx(p, "TapMode", e->TapMode, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumLocalBridge(RPC_ENUM_LOCALBRIDGE *t)
{
@@ -10430,8 +11583,11 @@ void SiEnumLocalSession(SERVER *s, char *hubname, RPC_ENUM_SESSION *t)
StrCpy(e->Name, sizeof(e->Name), s->Name);
StrCpy(e->Username, sizeof(e->Username), s->Username);
e->Ip = IPToUINT(&s->Connection->ClientIp);
+ CopyIP(&e->ClientIP, &s->Connection->ClientIp);
StrCpy(e->Hostname, sizeof(e->Hostname), s->Connection->ClientHostname);
e->MaxNumTcp = s->MaxConnection;
+ e->CreatedTime = Tick64ToTime64(s->CreatedTime);
+ e->LastCommTime = Tick64ToTime64(s->LastCommTime);
e->LinkMode = s->LinkModeServer;
e->SecureNATMode = s->SecureNATMode;
e->BridgeMode = s->BridgeMode;
@@ -10527,6 +11683,8 @@ void OutRpcEnumLicenseKey(PACK *p, RPC_ENUM_LICENSE_KEY *t)
}
PackAddInt(p, "NumItem", t->NumItem);
+
+ PackSetCurrentJsonGroupName(p, "LicenseKeyList");
for (i = 0;i < t->NumItem;i++)
{
RPC_ENUM_LICENSE_KEY_ITEM *e = &t->Items[i];
@@ -10535,12 +11693,13 @@ void OutRpcEnumLicenseKey(PACK *p, RPC_ENUM_LICENSE_KEY *t)
PackAddStrEx(p, "LicenseKey", e->LicenseKey, i, t->NumItem);
PackAddStrEx(p, "LicenseId", e->LicenseId, i, t->NumItem);
PackAddStrEx(p, "LicenseName", e->LicenseName, i, t->NumItem);
- PackAddInt64Ex(p, "Expires", e->Expires, i, t->NumItem);
+ PackAddTime64Ex(p, "Expires", e->Expires, i, t->NumItem);
PackAddIntEx(p, "Status", e->Status, i, t->NumItem);
PackAddIntEx(p, "ProductId", e->ProductId, i, t->NumItem);
PackAddInt64Ex(p, "SystemId", e->SystemId, i, t->NumItem);
PackAddIntEx(p, "SerialId", e->SerialId, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumLicenseKey(RPC_ENUM_LICENSE_KEY *t)
{
@@ -10590,17 +11749,17 @@ void OutRpcLicenseStatus(PACK *p, RPC_LICENSE_STATUS *t)
PackAddInt(p, "EditionId", t->EditionId);
PackAddStr(p, "EditionStr", t->EditionStr);
PackAddInt64(p, "SystemId", t->SystemId);
- PackAddInt64(p, "SystemExpires", t->SystemExpires);
+ PackAddTime64(p, "SystemExpires", t->SystemExpires);
PackAddInt(p, "NumClientConnectLicense", t->NumClientConnectLicense);
PackAddInt(p, "NumBridgeConnectLicense", t->NumBridgeConnectLicense);
// v3.0
PackAddBool(p, "NeedSubscription", t->NeedSubscription);
PackAddBool(p, "AllowEnterpriseFunction", t->AllowEnterpriseFunction);
- PackAddInt64(p, "SubscriptionExpires", t->SubscriptionExpires);
+ PackAddTime64(p, "SubscriptionExpires", t->SubscriptionExpires);
PackAddBool(p, "IsSubscriptionExpired", t->IsSubscriptionExpired);
PackAddInt(p, "NumUserCreationLicense", t->NumUserCreationLicense);
- PackAddInt64(p, "ReleaseDate", t->ReleaseDate);
+ PackAddTime64(p, "ReleaseDate", t->ReleaseDate);
}
// RPC_ADMIN_OPTION
@@ -10614,7 +11773,7 @@ void InRpcAdminOption(RPC_ADMIN_OPTION *t, PACK *p)
}
Zero(t, sizeof(RPC_ADMIN_OPTION));
- t->NumItem = PackGetInt(p, "NumItem");
+ t->NumItem = PackGetIndexCount(p, "Name");
t->Items = ZeroMalloc(sizeof(ADMIN_OPTION) * t->NumItem);
PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
@@ -10625,6 +11784,7 @@ void InRpcAdminOption(RPC_ADMIN_OPTION *t, PACK *p)
PackGetStrEx(p, "Name", o->Name, sizeof(o->Name), i);
o->Value = PackGetIntEx(p, "Value", i);
+ PackGetUniStrEx(p, "Descrption", o->Descrption, sizeof(o->Descrption), i);
}
}
void OutRpcAdminOption(PACK *p, RPC_ADMIN_OPTION *t)
@@ -10640,13 +11800,16 @@ void OutRpcAdminOption(PACK *p, RPC_ADMIN_OPTION *t)
PackAddStr(p, "HubName", t->HubName);
+ PackSetCurrentJsonGroupName(p, "AdminOptionList");
for (i = 0;i < t->NumItem;i++)
{
ADMIN_OPTION *o = &t->Items[i];
PackAddStrEx(p, "Name", o->Name, i, t->NumItem);
PackAddIntEx(p, "Value", o->Value, i, t->NumItem);
+ PackAddUniStrEx(p, "Descrption", o->Descrption, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcAdminOption(RPC_ADMIN_OPTION *t)
{
@@ -10813,7 +11976,7 @@ void OutRpcServerInfo(PACK *p, RPC_SERVER_INFO *t)
PackAddInt(p, "ServerBuildInt", t->ServerBuildInt);
PackAddStr(p, "ServerHostName", t->ServerHostName);
PackAddInt(p, "ServerType", t->ServerType);
- PackAddInt64(p, "ServerBuildDate", t->ServerBuildDate);
+ PackAddTime64(p, "ServerBuildDate", t->ServerBuildDate);
PackAddStr(p, "ServerFamilyName", t->ServerFamilyName);
OutRpcOsInfo(p, &t->OsInfo);
}
@@ -10888,13 +12051,13 @@ void OutRpcServerStatus(PACK *p, RPC_SERVER_STATUS *t)
PackAddInt(p, "NumIpTables", t->NumIpTables);
PackAddInt(p, "NumUsers", t->NumUsers);
PackAddInt(p, "NumGroups", t->NumGroups);
- PackAddInt64(p, "CurrentTime", t->CurrentTime);
+ PackAddTime64(p, "CurrentTime", t->CurrentTime);
PackAddInt64(p, "CurrentTick", t->CurrentTick);
PackAddInt(p, "AssignedBridgeLicenses", t->AssignedBridgeLicenses);
PackAddInt(p, "AssignedClientLicenses", t->AssignedClientLicenses);
PackAddInt(p, "AssignedBridgeLicensesTotal", t->AssignedBridgeLicensesTotal);
PackAddInt(p, "AssignedClientLicensesTotal", t->AssignedClientLicensesTotal);
- PackAddInt64(p, "StartTime", t->StartTime);
+ PackAddTime64(p, "StartTime", t->StartTime);
OutRpcTraffic(p, &t->Traffic);
@@ -10957,12 +12120,14 @@ void OutRpcListenerList(PACK *p, RPC_LISTENER_LIST *t)
return;
}
+ PackSetCurrentJsonGroupName(p, "ListenerList");
for (i = 0;i < t->NumPort;i++)
{
PackAddIntEx(p, "Ports", t->Ports[i], i, t->NumPort);
PackAddBoolEx(p, "Enables", t->Enables[i], i, t->NumPort);
PackAddBoolEx(p, "Errors", t->Errors[i], i, t->NumPort);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcListenerList(RPC_LISTENER_LIST *t)
{
@@ -11031,6 +12196,7 @@ void InRpcSetPassword(RPC_SET_PASSWORD *t, PACK *p)
Zero(t, sizeof(RPC_SET_PASSWORD));
PackGetData2(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));
+ PackGetStr(p, "PlainTextPassword", t->PlainTextPassword, sizeof(t->PlainTextPassword));
}
void OutRpcSetPassword(PACK *p, RPC_SET_PASSWORD *t)
{
@@ -11041,6 +12207,7 @@ void OutRpcSetPassword(PACK *p, RPC_SET_PASSWORD *t)
}
PackAddData(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));
+ PackAddStr(p, "PlainTextPassword", t->PlainTextPassword);
}
// RPC_FARM
@@ -11065,6 +12232,7 @@ void InRpcFarm(RPC_FARM *t, PACK *p)
PackGetStr(p, "ControllerName", t->ControllerName, sizeof(t->ControllerName));
t->ControllerPort = PackGetInt(p, "ControllerPort");
PackGetData2(p, "MemberPassword", t->MemberPassword, sizeof(t->MemberPassword));
+ PackGetStr(p, "MemberPasswordPlaintext", t->MemberPasswordPlaintext, sizeof(t->MemberPasswordPlaintext));
t->Weight = PackGetInt(p, "Weight");
t->ControllerOnly = PackGetBool(p, "ControllerOnly");
}
@@ -11086,6 +12254,7 @@ void OutRpcFarm(PACK *p, RPC_FARM *t)
PackAddStr(p, "ControllerName", t->ControllerName);
PackAddInt(p, "ControllerPort", t->ControllerPort);
PackAddData(p, "MemberPassword", t->MemberPassword, sizeof(t->MemberPassword));
+ PackAddStr(p, "MemberPasswordPlaintext", t->MemberPasswordPlaintext);
PackAddInt(p, "Weight", t->Weight);
PackAddBool(p, "ControllerOnly", t->ControllerOnly);
}
@@ -11171,7 +12340,7 @@ void OutRpcFarmInfo(PACK *p, RPC_FARM_INFO *t)
PackAddInt(p, "Id", t->Id);
PackAddBool(p, "Controller", t->Controller);
- PackAddInt64(p, "ConnectedTime", t->ConnectedTime);
+ PackAddTime64(p, "ConnectedTime", t->ConnectedTime);
PackAddIp32(p, "Ip", t->Ip);
PackAddStr(p, "Hostname", t->Hostname);
PackAddInt(p, "Point", t->Point);
@@ -11180,11 +12349,15 @@ void OutRpcFarmInfo(PACK *p, RPC_FARM_INFO *t)
PackAddIntEx(p, "Ports", t->Ports[i], i, t->NumPort);
}
PackAddX(p, "ServerCert", t->ServerCert);
+
+ PackSetCurrentJsonGroupName(p, "HubsList");
for (i = 0;i < t->NumFarmHub;i++)
{
PackAddStrEx(p, "HubName", t->FarmHubs[i].HubName, i, t->NumFarmHub);
PackAddBoolEx(p, "DynamicHub", t->FarmHubs[i].DynamicHub, i, t->NumFarmHub);
}
+ PackSetCurrentJsonGroupName(p, NULL);
+
PackAddInt(p, "NumSessions", t->NumSessions);
PackAddInt(p, "NumTcpConnections", t->NumTcpConnections);
PackAddInt(p, "Weight", t->Weight);
@@ -11241,13 +12414,14 @@ void OutRpcEnumFarm(PACK *p, RPC_ENUM_FARM *t)
return;
}
+ PackSetCurrentJsonGroupName(p, "FarmMemberList");
for (i = 0;i < t->NumFarm;i++)
{
RPC_ENUM_FARM_ITEM *e = &t->Farms[i];
PackAddIntEx(p, "Id", e->Id, i, t->NumFarm);
PackAddBoolEx(p, "Controller", e->Controller, i, t->NumFarm);
- PackAddInt64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumFarm);
+ PackAddTime64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumFarm);
PackAddIp32Ex(p, "Ip", e->Ip, i, t->NumFarm);
PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumFarm);
PackAddIntEx(p, "Point", e->Point, i, t->NumFarm);
@@ -11257,6 +12431,7 @@ void OutRpcEnumFarm(PACK *p, RPC_ENUM_FARM *t)
PackAddIntEx(p, "AssignedClientLicense", e->AssignedClientLicense, i, t->NumFarm);
PackAddIntEx(p, "AssignedBridgeLicense", e->AssignedBridgeLicense, i, t->NumFarm);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumFarm(RPC_ENUM_FARM *t)
{
@@ -11302,9 +12477,9 @@ void OutRpcFarmConnectionStatus(PACK *p, RPC_FARM_CONNECTION_STATUS *t)
PackAddInt(p, "Port", t->Port);
PackAddBool(p, "Online", t->Online);
PackAddInt(p, "LastError", t->LastError);
- PackAddInt64(p, "StartedTime", t->StartedTime);
- PackAddInt64(p, "CurrentConnectedTime", t->CurrentConnectedTime);
- PackAddInt64(p, "FirstConnectedTime", t->FirstConnectedTime);
+ PackAddTime64(p, "StartedTime", t->StartedTime);
+ PackAddTime64(p, "CurrentConnectedTime", t->CurrentConnectedTime);
+ PackAddTime64(p, "FirstConnectedTime", t->FirstConnectedTime);
PackAddInt(p, "NumConnected", t->NumConnected);
PackAddInt(p, "NumTry", t->NumTry);
PackAddInt(p, "NumFailed", t->NumFailed);
@@ -11402,6 +12577,7 @@ void InRpcCreateHub(RPC_CREATE_HUB *t, PACK *p)
PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName));
PackGetData2(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));
PackGetData2(p, "SecurePassword", t->SecurePassword, sizeof(t->SecurePassword));
+ PackGetStr(p, "AdminPasswordPlainText", t->AdminPasswordPlainText, sizeof(t->AdminPasswordPlainText));
t->Online = PackGetBool(p, "Online");
InRpcHubOption(&t->HubOption, p);
t->HubType = PackGetInt(p, "HubType");
@@ -11418,6 +12594,7 @@ void OutRpcCreateHub(PACK *p, RPC_CREATE_HUB *t)
PackAddData(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));
PackAddData(p, "SecurePassword", t->SecurePassword, sizeof(t->SecurePassword));
PackAddBool(p, "Online", t->Online);
+ PackAddStr(p, "AdminPasswordPlainText", t->AdminPasswordPlainText);
OutRpcHubOption(p, &t->HubOption);
PackAddInt(p, "HubType", t->HubType);
}
@@ -11466,6 +12643,7 @@ void OutRpcEnumHub(PACK *p, RPC_ENUM_HUB *t)
return;
}
+ PackSetCurrentJsonGroupName(p, "HubList");
for (i = 0;i < t->NumHub;i++)
{
RPC_ENUM_HUB_ITEM *e = &t->Hubs[i];
@@ -11478,14 +12656,15 @@ void OutRpcEnumHub(PACK *p, RPC_ENUM_HUB *t)
PackAddIntEx(p, "NumGroups", e->NumGroups, i, t->NumHub);
PackAddIntEx(p, "NumMacTables", e->NumMacTables, i, t->NumHub);
PackAddIntEx(p, "NumIpTables", e->NumIpTables, i, t->NumHub);
- PackAddInt64Ex(p, "LastCommTime", e->LastCommTime, i, t->NumHub);
- PackAddInt64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumHub);
- PackAddInt64Ex(p, "LastLoginTime", e->LastLoginTime, i, t->NumHub);
+ PackAddTime64Ex(p, "LastCommTime", e->LastCommTime, i, t->NumHub);
+ PackAddTime64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumHub);
+ PackAddTime64Ex(p, "LastLoginTime", e->LastLoginTime, i, t->NumHub);
PackAddIntEx(p, "NumLogin", e->NumLogin, i, t->NumHub);
PackAddBoolEx(p, "IsTrafficFilled", e->IsTrafficFilled, i, t->NumHub);
OutRpcTrafficEx(&e->Traffic, p, i, t->NumHub);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumHub(RPC_ENUM_HUB *t)
{
@@ -11556,6 +12735,7 @@ void OutRpcEnumConnection(PACK *p, RPC_ENUM_CONNECTION *t)
return;
}
+ PackSetCurrentJsonGroupName(p, "ConnectionList");
for (i = 0;i < t->NumConnection;i++)
{
RPC_ENUM_CONNECTION_ITEM *e = &t->Connections[i];
@@ -11564,9 +12744,10 @@ void OutRpcEnumConnection(PACK *p, RPC_ENUM_CONNECTION *t)
PackAddIntEx(p, "Port", e->Port, i, t->NumConnection);
PackAddStrEx(p, "Name", e->Name, i, t->NumConnection);
PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumConnection);
- PackAddInt64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumConnection);
+ PackAddTime64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumConnection);
PackAddIntEx(p, "Type", e->Type, i, t->NumConnection);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumConnetion(RPC_ENUM_CONNECTION *t)
{
@@ -11636,7 +12817,7 @@ void OutRpcConnectionInfo(PACK *p, RPC_CONNECTION_INFO *t)
PackAddStr(p, "Name", t->Name);
PackAddIp32(p, "Ip", t->Ip);
PackAddInt(p, "Port", t->Port);
- PackAddInt64(p, "ConnectedTime", t->ConnectedTime);
+ PackAddTime64(p, "ConnectedTime", t->ConnectedTime);
PackAddStr(p, "Hostname", t->Hostname);
PackAddStr(p, "ServerStr", t->ServerStr);
PackAddStr(p, "ClientStr", t->ClientStr);
@@ -11721,9 +12902,9 @@ void OutRpcHubStatus(PACK *p, RPC_HUB_STATUS *t)
PackAddInt(p, "NumIpTables", t->NumIpTables);
PackAddBool(p, "SecureNATEnabled", t->SecureNATEnabled);
OutRpcTraffic(p, &t->Traffic);
- PackAddInt64(p, "LastCommTime", t->LastCommTime);
- PackAddInt64(p, "CreatedTime", t->CreatedTime);
- PackAddInt64(p, "LastLoginTime", t->LastLoginTime);
+ PackAddTime64(p, "LastCommTime", t->LastCommTime);
+ PackAddTime64(p, "CreatedTime", t->CreatedTime);
+ PackAddTime64(p, "LastLoginTime", t->LastLoginTime);
PackAddInt(p, "NumLogin", t->NumLogin);
}
@@ -11838,6 +13019,7 @@ void OutRpcHubEnumCa(PACK *p, RPC_HUB_ENUM_CA *t)
}
PackAddStr(p, "HubName", t->HubName);
+ PackSetCurrentJsonGroupName(p, "CAList");
for (i = 0;i < t->NumCa;i++)
{
RPC_HUB_ENUM_CA_ITEM *e = &t->Ca[i];
@@ -11845,8 +13027,9 @@ void OutRpcHubEnumCa(PACK *p, RPC_HUB_ENUM_CA *t)
PackAddIntEx(p, "Key", e->Key, i, t->NumCa);
PackAddUniStrEx(p, "SubjectName", e->SubjectName, i, t->NumCa);
PackAddUniStrEx(p, "IssuerName", e->IssuerName, i, t->NumCa);
- PackAddInt64Ex(p, "Expires", e->Expires, i, t->NumCa);
+ PackAddTime64Ex(p, "Expires", e->Expires, i, t->NumCa);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcHubEnumCa(RPC_HUB_ENUM_CA *t)
{
@@ -12013,6 +13196,7 @@ void InRpcEnumLink(RPC_ENUM_LINK *t, PACK *p)
e->ConnectedTime = PackGetInt64Ex(p, "ConnectedTime", i);
e->Connected = PackGetBoolEx(p, "Connected", i);
e->LastError = PackGetIntEx(p, "LastError", i);
+ PackGetStrEx(p, "LinkHubName", e->HubName, sizeof(e->HubName), i);
}
}
void OutRpcEnumLink(PACK *p, RPC_ENUM_LINK *t)
@@ -12026,6 +13210,7 @@ void OutRpcEnumLink(PACK *p, RPC_ENUM_LINK *t)
PackAddStr(p, "HubName", t->HubName);
+ PackSetCurrentJsonGroupName(p, "LinkList");
for (i = 0;i < t->NumLink;i++)
{
RPC_ENUM_LINK_ITEM *e = &t->Links[i];
@@ -12034,10 +13219,12 @@ void OutRpcEnumLink(PACK *p, RPC_ENUM_LINK *t)
PackAddStrEx(p, "ConnectedHubName", e->HubName, i, t->NumLink);
PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumLink);
PackAddBoolEx(p, "Online", e->Online, i, t->NumLink);
- PackAddInt64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumLink);
+ PackAddTime64Ex(p, "ConnectedTime", e->ConnectedTime, i, t->NumLink);
PackAddBoolEx(p, "Connected", e->Connected, i, t->NumLink);
PackAddIntEx(p, "LastError", e->LastError, i, t->NumLink);
+ PackAddStrEx(p, "TargetHubName", e->HubName, i, t->NumLink);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumLink(RPC_ENUM_LINK *t)
{
@@ -12311,12 +13498,14 @@ void OutRpcEnumAccessList(PACK *p, RPC_ENUM_ACCESS_LIST *a)
}
PackAddStr(p, "HubName", a->HubName);
+ PackSetCurrentJsonGroupName(p, "AccessList");
for (i = 0;i < a->NumAccess;i++)
{
ACCESS *e = &a->Accesses[i];
OutRpcAccessEx(p, e, i, a->NumAccess);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumAccessList(RPC_ENUM_ACCESS_LIST *a)
{
@@ -12330,7 +13519,7 @@ void FreeRpcEnumAccessList(RPC_ENUM_ACCESS_LIST *a)
}
// AUTHDATA
-void *InRpcAuthData(PACK *p, UINT *authtype)
+void *InRpcAuthData(PACK *p, UINT *authtype, char *username)
{
wchar_t tmp[MAX_SIZE];
AUTHPASSWORD *pw;
@@ -12339,6 +13528,7 @@ void *InRpcAuthData(PACK *p, UINT *authtype)
AUTHRADIUS *radius;
AUTHNT *nt;
BUF *b;
+ char plain_pw[MAX_SIZE];
// Validate arguments
if (p == NULL)
{
@@ -12357,6 +13547,16 @@ void *InRpcAuthData(PACK *p, UINT *authtype)
pw = ZeroMalloc(sizeof(AUTHPASSWORD));
PackGetData2(p, "HashedKey", pw->HashedKey, sizeof(pw->HashedKey));
PackGetData2(p, "NtLmSecureHash", pw->NtLmSecureHash, sizeof(pw->NtLmSecureHash));
+
+ if (PackGetStr(p, "Auth_Password", plain_pw, sizeof(plain_pw)))
+ {
+ if (IsZero(pw->HashedKey, sizeof(pw->HashedKey)))
+ {
+ HashPassword(pw->HashedKey, username, plain_pw);
+ GenerateNtPasswordHash(pw->NtLmSecureHash, plain_pw);
+ }
+ }
+
return pw;
case AUTHTYPE_USERCERT:
@@ -12474,7 +13674,7 @@ void InRpcSetUser(RPC_SET_USER *t, PACK *p)
t->CreatedTime = PackGetInt64(p, "CreatedTime");
t->UpdatedTime = PackGetInt64(p, "UpdatedTime");
t->ExpireTime = PackGetInt64(p, "ExpireTime");
- t->AuthData = InRpcAuthData(p, &t->AuthType);
+ t->AuthData = InRpcAuthData(p, &t->AuthType, t->Name);
t->NumLogin = PackGetInt(p, "NumLogin");
InRpcTraffic(&t->Traffic, p);
@@ -12498,9 +13698,9 @@ void OutRpcSetUser(PACK *p, RPC_SET_USER *t)
PackAddStr(p, "GroupName", t->GroupName);
PackAddUniStr(p, "Realname", t->Realname);
PackAddUniStr(p, "Note", t->Note);
- PackAddInt64(p, "CreatedTime", t->CreatedTime);
- PackAddInt64(p, "UpdatedTime", t->UpdatedTime);
- PackAddInt64(p, "ExpireTime", t->ExpireTime);
+ PackAddTime64(p, "CreatedTime", t->CreatedTime);
+ PackAddTime64(p, "UpdatedTime", t->UpdatedTime);
+ PackAddTime64(p, "ExpireTime", t->ExpireTime);
OutRpcAuthData(p, t->AuthData, t->AuthType);
PackAddInt(p, "NumLogin", t->NumLogin);
OutRpcTraffic(p, &t->Traffic);
@@ -12571,6 +13771,7 @@ void OutRpcEnumUser(PACK *p, RPC_ENUM_USER *t)
}
PackAddStr(p, "HubName", t->HubName);
+ PackSetCurrentJsonGroupName(p, "UserList");
for (i = 0;i < t->NumUser;i++)
{
RPC_ENUM_USER_ITEM *e = &t->Users[i];
@@ -12580,7 +13781,7 @@ void OutRpcEnumUser(PACK *p, RPC_ENUM_USER *t)
PackAddUniStrEx(p, "Realname", e->Realname, i, t->NumUser);
PackAddUniStrEx(p, "Note", e->Note, i, t->NumUser);
PackAddIntEx(p, "AuthType", e->AuthType, i, t->NumUser);
- PackAddInt64Ex(p, "LastLoginTime", e->LastLoginTime, i, t->NumUser);
+ PackAddTime64Ex(p, "LastLoginTime", e->LastLoginTime, i, t->NumUser);
PackAddIntEx(p, "NumLogin", e->NumLogin, i, t->NumUser);
PackAddBoolEx(p, "DenyAccess", e->DenyAccess, i, t->NumUser);
@@ -12588,8 +13789,9 @@ void OutRpcEnumUser(PACK *p, RPC_ENUM_USER *t)
OutRpcTrafficEx(&e->Traffic, p, i, t->NumUser);
PackAddBoolEx(p, "IsExpiresFilled", e->IsExpiresFilled, i, t->NumUser);
- PackAddInt64Ex(p, "Expires", e->Expires, i, t->NumUser);
+ PackAddTime64Ex(p, "Expires", e->Expires, i, t->NumUser);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumUser(RPC_ENUM_USER *t)
{
@@ -12686,6 +13888,7 @@ void OutRpcEnumGroup(PACK *p, RPC_ENUM_GROUP *t)
PackAddStr(p, "HubName", t->HubName);
+ PackSetCurrentJsonGroupName(p, "GroupList");
for (i = 0;i < t->NumGroup;i++)
{
RPC_ENUM_GROUP_ITEM *e = &t->Groups[i];
@@ -12696,6 +13899,7 @@ void OutRpcEnumGroup(PACK *p, RPC_ENUM_GROUP *t)
PackAddIntEx(p, "NumUsers", e->NumUsers, i, t->NumGroup);
PackAddBoolEx(p, "DenyAccess", e->DenyAccess, i, t->NumGroup);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumGroup(RPC_ENUM_GROUP *t)
{
@@ -12755,6 +13959,7 @@ void InRpcEnumSession(RPC_ENUM_SESSION *t, PACK *p)
PackGetStrEx(p, "Name", e->Name, sizeof(e->Name), i);
PackGetStrEx(p, "Username", e->Username, sizeof(e->Username), i);
e->Ip = PackGetIntEx(p, "Ip", i);
+ PackGetIpEx(p, "ClientIP", &e->ClientIP, i);
PackGetStrEx(p, "Hostname", e->Hostname, sizeof(e->Hostname), i);
e->MaxNumTcp = PackGetIntEx(p, "MaxNumTcp", i);
e->CurrentNumTcp = PackGetIntEx(p, "CurrentNumTcp", i);
@@ -12773,6 +13978,8 @@ void InRpcEnumSession(RPC_ENUM_SESSION *t, PACK *p)
e->IsDormantEnabled = PackGetBoolEx(p, "IsDormantEnabled", i);
e->IsDormant = PackGetBoolEx(p, "IsDormant", i);
e->LastCommDormant = PackGetInt64Ex(p, "LastCommDormant", i);
+ e->CreatedTime = PackGetInt64Ex(p, "CreatedTime", i);
+ e->LastCommTime = PackGetInt64Ex(p, "LastCommTime", i);
}
}
void OutRpcEnumSession(PACK *p, RPC_ENUM_SESSION *t)
@@ -12785,6 +13992,7 @@ void OutRpcEnumSession(PACK *p, RPC_ENUM_SESSION *t)
}
PackAddStr(p, "HubName", t->HubName);
+ PackSetCurrentJsonGroupName(p, "SessionList");
for (i = 0;i < t->NumSession;i++)
{
RPC_ENUM_SESSION_ITEM *e = &t->Sessions[i];
@@ -12792,6 +14000,7 @@ void OutRpcEnumSession(PACK *p, RPC_ENUM_SESSION *t)
PackAddStrEx(p, "Name", e->Name, i, t->NumSession);
PackAddStrEx(p, "Username", e->Username, i, t->NumSession);
PackAddIp32Ex(p, "Ip", e->Ip, i, t->NumSession);
+ PackAddIpEx(p, "ClientIP", &e->ClientIP, i, t->NumSession);
PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumSession);
PackAddIntEx(p, "MaxNumTcp", e->MaxNumTcp, i, t->NumSession);
PackAddIntEx(p, "CurrentNumTcp", e->CurrentNumTcp, i, t->NumSession);
@@ -12809,8 +14018,11 @@ void OutRpcEnumSession(PACK *p, RPC_ENUM_SESSION *t)
PackAddDataEx(p, "UniqueId", e->UniqueId, sizeof(e->UniqueId), i, t->NumSession);
PackAddBoolEx(p, "IsDormantEnabled", e->IsDormantEnabled, i, t->NumSession);
PackAddBoolEx(p, "IsDormant", e->IsDormant, i, t->NumSession);
- PackAddInt64Ex(p, "LastCommDormant", e->LastCommDormant, i, t->NumSession);
+ PackAddTime64Ex(p, "LastCommDormant", e->LastCommDormant, i, t->NumSession);
+ PackAddTime64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumSession);
+ PackAddTime64Ex(p, "LastCommTime", e->LastCommTime, i, t->NumSession);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumSession(RPC_ENUM_SESSION *t)
{
@@ -12941,6 +14153,7 @@ void InRpcSessionStatus(RPC_SESSION_STATUS *t, PACK *p)
t->ClientIp = PackGetIp32(p, "SessionStatus_ClientIp");
PackGetData2(p, "SessionStatus_ClientIp6", t->ClientIp6, sizeof(t->ClientIp6));
PackGetStr(p, "SessionStatus_ClientHostName", t->ClientHostName, sizeof(t->ClientHostName));
+ PackGetIp(p, "Client_Ip_Address", &t->ClientIpAddress);
InRpcClientGetConnectionStatus(&t->Status, p);
InRpcNodeInfo(&t->NodeInfo, p);
@@ -12961,6 +14174,7 @@ void OutRpcSessionStatus(PACK *p, RPC_SESSION_STATUS *t)
PackAddIp32(p, "SessionStatus_ClientIp", t->ClientIp);
PackAddData(p, "SessionStatus_ClientIp6", t->ClientIp6, sizeof(t->ClientIp6));
PackAddStr(p, "SessionStatus_ClientHostName", t->ClientHostName);
+ PackAddIp(p, "Client_Ip_Address", &t->ClientIpAddress);
OutRpcClientGetConnectionStatus(p, &t->Status);
OutRpcNodeInfo(p, &t->NodeInfo);
@@ -13041,6 +14255,7 @@ void OutRpcEnumMacTable(PACK *p, RPC_ENUM_MAC_TABLE *t)
PackAddStr(p, "HubName", t->HubName);
+ PackSetCurrentJsonGroupName(p, "MacTable");
for (i = 0;i < t->NumMacTable;i++)
{
RPC_ENUM_MAC_TABLE_ITEM *e = &t->MacTables[i];
@@ -13049,11 +14264,12 @@ void OutRpcEnumMacTable(PACK *p, RPC_ENUM_MAC_TABLE *t)
PackAddStrEx(p, "SessionName", e->SessionName, i, t->NumMacTable);
PackAddDataEx(p, "MacAddress", e->MacAddress, sizeof(e->MacAddress), i, t->NumMacTable);
PackAddIntEx(p, "VlanId", e->VlanId, i, t->NumMacTable);
- PackAddInt64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumMacTable);
- PackAddInt64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumMacTable);
+ PackAddTime64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumMacTable);
+ PackAddTime64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumMacTable);
PackAddBoolEx(p, "RemoteItem", e->RemoteItem, i, t->NumMacTable);
PackAddStrEx(p, "RemoteHostname", e->RemoteHostname, i, t->NumMacTable);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumMacTable(RPC_ENUM_MAC_TABLE *t)
{
@@ -13092,6 +14308,7 @@ void InRpcEnumIpTable(RPC_ENUM_IP_TABLE *t, PACK *p)
{
UINTToIP(&e->IpV6, e->Ip);
}
+ PackGetIp(p, "IpAddress", &e->IpAddress);
e->DhcpAllocated = PackGetBoolEx(p, "DhcpAllocated", i);
e->CreatedTime = PackGetInt64Ex(p, "CreatedTime", i);
e->UpdatedTime = PackGetInt64Ex(p, "UpdatedTime", i);
@@ -13110,6 +14327,7 @@ void OutRpcEnumIpTable(PACK *p, RPC_ENUM_IP_TABLE *t)
PackAddStr(p, "HubName", t->HubName);
+ PackSetCurrentJsonGroupName(p, "IpTable");
for (i = 0;i < t->NumIpTable;i++)
{
RPC_ENUM_IP_TABLE_ITEM *e = &t->IpTables[i];
@@ -13118,12 +14336,14 @@ void OutRpcEnumIpTable(PACK *p, RPC_ENUM_IP_TABLE *t)
PackAddStrEx(p, "SessionName", e->SessionName, i, t->NumIpTable);
PackAddIp32Ex(p, "Ip", e->Ip, i, t->NumIpTable);
PackAddIpEx(p, "IpV6", &e->IpV6, i, t->NumIpTable);
+ PackAddIpEx(p, "IpAddress", &e->IpAddress, i, t->NumIpTable);
PackAddBoolEx(p, "DhcpAllocated", e->DhcpAllocated, i, t->NumIpTable);
- PackAddInt64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumIpTable);
- PackAddInt64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumIpTable);
+ PackAddTime64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumIpTable);
+ PackAddTime64Ex(p, "UpdatedTime", e->UpdatedTime, i, t->NumIpTable);
PackAddBoolEx(p, "RemoteItem", e->RemoteItem, i, t->NumIpTable);
PackAddStrEx(p, "RemoteHostname", e->RemoteHostname, i, t->NumIpTable);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumIpTable(RPC_ENUM_IP_TABLE *t)
{
diff --git a/src/Cedar/Admin.h b/src/Cedar/Admin.h
index ca260270..59a9f2cf 100644
--- a/src/Cedar/Admin.h
+++ b/src/Cedar/Admin.h
@@ -129,6 +129,8 @@ struct ADMIN
LIST *LogFileList; // Accessible log file list
UINT ClientBuild; // Build number of the client
RPC_WINVER ClientWinVer; // Windows version of client
+ UINT MaxJsonRpcRecvSize; // Max JSON-RPC Receive Size
+ char dummy1[MAX_HUBNAME_LEN + 1]; // hubname buffer (dummy)
};
// Test
@@ -215,7 +217,8 @@ struct RPC_INT
// Set Password
struct RPC_SET_PASSWORD
{
- UCHAR HashedPassword[SHA1_SIZE]; // Hashed password
+ UCHAR HashedPassword[SHA1_SIZE]; // Hashed password (for traditional RPC)
+ char PlainTextPassword[MAX_SIZE]; // Plaintext password (for JSON-RPC)
};
// Server farm configuration *
@@ -228,6 +231,7 @@ struct RPC_FARM
char ControllerName[MAX_HOST_NAME_LEN + 1]; // Controller name
UINT ControllerPort; // Controller port
UCHAR MemberPassword[SHA1_SIZE]; // Member password
+ char MemberPasswordPlaintext[MAX_SIZE]; // Member password (plaintext)
UINT Weight; // Performance ratio
bool ControllerOnly; // Only controller function
};
@@ -333,6 +337,7 @@ struct RPC_CREATE_HUB
char HubName[MAX_HUBNAME_LEN + 1]; // HUB Name
UCHAR HashedPassword[SHA1_SIZE]; // Administrative password
UCHAR SecurePassword[SHA1_SIZE]; // Administrator password
+ char AdminPasswordPlainText[MAX_SIZE]; // Password (plaintext)
bool Online; // Online flag
RPC_HUB_OPTION HubOption; // HUB options
UINT HubType; // Type of HUB
@@ -650,6 +655,7 @@ struct RPC_ENUM_SESSION_ITEM
char RemoteHostname[MAX_HOST_NAME_LEN + 1]; // Remote server name
char Username[MAX_USERNAME_LEN + 1]; // User name
UINT Ip; // IP address (IPv4)
+ IP ClientIP; // IP address (IPv4 / IPv6)
char Hostname[MAX_HOST_NAME_LEN + 1]; // Host name
UINT MaxNumTcp; // Maximum number of TCP connections
UINT CurrentNumTcp; // Number of currentl TCP connections
@@ -666,6 +672,8 @@ struct RPC_ENUM_SESSION_ITEM
bool IsDormantEnabled; // Is the dormant state enabled
bool IsDormant; // Is in the dormant state
UINT64 LastCommDormant; // Last comm interval in the dormant state
+ UINT64 CreatedTime; // Creation date and time
+ UINT64 LastCommTime; // Last communication date and time
};
// Disconnect the session
@@ -702,8 +710,9 @@ struct RPC_ENUM_IP_TABLE_ITEM
{
UINT Key; // Key
char SessionName[MAX_SESSION_NAME_LEN + 1]; // Session name
- UINT Ip; // IP address
+ UINT Ip; // IPv4 address
IP IpV6; // IPv6 address
+ IP IpAddress; // IPv4 / IPv6 Address
bool DhcpAllocated; // Assigned by the DHCP
UINT64 CreatedTime; // Creation date and time
UINT64 UpdatedTime; // Updating date
@@ -990,6 +999,11 @@ struct RPC_AZURE_STATUS
};
+// Constants
+#define ADMIN_RPC_MAX_POST_SIZE_BY_SERVER_ADMIN MAX_PACK_SIZE
+#define ADMIN_RPC_MAX_POST_SIZE_BY_HUB_ADMIN (8 * 1024 * 1024)
+
+
// Function prototype
UINT AdminAccept(CONNECTION *c, PACK *p);
void HashAdminPassword(void *hash, char *password);
@@ -1014,6 +1028,26 @@ BUF *DownloadFileFromServer(RPC *r, char *server_name, char *filepath, UINT tota
bool CheckAdminSourceAddress(SOCK *sock, char *hubname);
void SiEnumSessionMain(SERVER *s, RPC_ENUM_SESSION *t);
bool SiIsEmptyPassword(void *hash_password);
+void JsonRpcProcPost(CONNECTION *c, SOCK *s, HTTP_HEADER *h, UINT post_data_size);
+void JsonRpcProcGet(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target);
+void JsonRpcProcOptions(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target);
+JSON_VALUE *JsonRpcProcRequestObject(ADMIN *admin, CONNECTION *c, SOCK *s, JSON_VALUE *json_req, char *method_name);
+JSON_VALUE *JsonRpcNewError(int code, wchar_t *message);
+JSON_VALUE *JsonRpcNewResponse(PACK *p);
+bool HttpParseBasicAuthHeader(HTTP_HEADER *h, char *username, UINT username_size, char *password, UINT password_size);
+ADMIN *JsonRpcAuthLogin(CEDAR *c, SOCK *sock, HTTP_HEADER *h);
+JSON_VALUE *QueryStringToJsonListValue(char *qs);
+JSON_VALUE *ConstructDummyJsonRpcRequest(char *method_name, JSON_VALUE *p);
+void AdminWebProcPost(CONNECTION *c, SOCK *s, HTTP_HEADER *h, UINT post_data_size, char *url_target);
+void AdminWebProcGet(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target);
+bool AdminWebHandleFileRequest(ADMIN *a, CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_src, char *query_string, char *virtual_root_dir, char *physical_root_dir);
+BUF *AdminWebProcessServerSideInclude(BUF *src_txt, char *filename, UINT depth);
+bool AdminWebSendBody(SOCK *s, UINT status_code, char *status_string, UCHAR *data, UINT data_size, char *content_type, char *add_header_name, char *add_header_value, HTTP_HEADER *request_headers);
+bool AdminWebSend404Error(SOCK *s, HTTP_HEADER *request_headers);
+bool AdminWebSend302Redirect(SOCK *s, char *url, char *query_string, HTTP_HEADER *request_headers);
+BUF *AdminWebTryFindAndReadFile(char *vroot, char *proot, char *url, char *ret_filename, UINT ret_filename_size, bool *is_index_html);
+BUF *AdminWebTryOneFile(char *filename, char *ret_filename, UINT ret_filename_size);
+bool AdminWebSendUnauthorized(SOCK *s, HTTP_HEADER *http_request_headers);
UINT StTest(ADMIN *a, RPC_TEST *t);
UINT StGetServerInfo(ADMIN *a, RPC_SERVER_INFO *t);
@@ -1387,7 +1421,7 @@ void OutRpcAccess(PACK *p, ACCESS *a);
void InRpcEnumAccessList(RPC_ENUM_ACCESS_LIST *a, PACK *p);
void OutRpcEnumAccessList(PACK *p, RPC_ENUM_ACCESS_LIST *a);
void FreeRpcEnumAccessList(RPC_ENUM_ACCESS_LIST *a);
-void *InRpcAuthData(PACK *p, UINT *authtype);
+void *InRpcAuthData(PACK *p, UINT *authtype, char *username);
void OutRpcAuthData(PACK *p, void *authdata, UINT authtype);
void FreeRpcAuthData(void *authdata, UINT authtype);
void InRpcSetUser(RPC_SET_USER *t, PACK *p);
diff --git a/src/Cedar/CM.c b/src/Cedar/CM.c
index a42bb48f..97bd28e4 100644
--- a/src/Cedar/CM.c
+++ b/src/Cedar/CM.c
@@ -9466,6 +9466,12 @@ void CmPrintStatusToListViewEx(LVB *b, RPC_CLIENT_GET_CONNECTION_STATUS *s, bool
LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_UNDERLAY_PROTOCOL"), tmp);
}
+ if (IsEmptyStr(s->ProtocolDetails) == false)
+ {
+ StrToUni(tmp, sizeof(tmp), s->ProtocolDetails);
+ LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_PROTOCOL_DETAILS"), tmp);
+ }
+
LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_UDP_ACCEL_ENABLED"), (s->IsUdpAccelerationEnabled ? _UU("CM_ST_YES") : _UU("CM_ST_NO")));
LvInsertAdd(b, 0, NULL, 2, _UU("CM_ST_UDP_ACCEL_USING"), (s->IsUsingUdpAcceleration ? _UU("CM_ST_YES") : _UU("CM_ST_NO")));
diff --git a/src/Cedar/Cedar.h b/src/Cedar/Cedar.h
index f99e9350..d746c4bb 100644
--- a/src/Cedar/Cedar.h
+++ b/src/Cedar/Cedar.h
@@ -126,10 +126,10 @@
// Version number
-#define CEDAR_VER 429
+#define CEDAR_VER 430
// Build Number
-#define CEDAR_BUILD 9680
+#define CEDAR_BUILD 9695
// Beta number
//#define BETA_NUMBER 3
@@ -149,11 +149,11 @@
// Specifies the build date
#define BUILD_DATE_Y 2019
-#define BUILD_DATE_M 2
-#define BUILD_DATE_D 28
-#define BUILD_DATE_HO 18
-#define BUILD_DATE_MI 39
-#define BUILD_DATE_SE 47
+#define BUILD_DATE_M 7
+#define BUILD_DATE_D 7
+#define BUILD_DATE_HO 19
+#define BUILD_DATE_MI 58
+#define BUILD_DATE_SE 8
// Tolerable time difference
#define ALLOW_TIMESTAMP_DIFF (UINT64)(3 * 24 * 60 * 60 * 1000)
@@ -438,6 +438,7 @@
#define AUTHTYPE_ROOTCERT 3 // Root certificate which is issued by trusted Certificate Authority
#define AUTHTYPE_RADIUS 4 // Radius authentication
#define AUTHTYPE_NT 5 // Windows NT authentication
+#define AUTHTYPE_OPENVPN_CERT 98 // TLS client certificate authentication
#define AUTHTYPE_TICKET 99 // Ticket authentication
// Constant of the client side
diff --git a/src/Cedar/CedarType.h b/src/Cedar/CedarType.h
index 13ea74e5..040790f0 100644
--- a/src/Cedar/CedarType.h
+++ b/src/Cedar/CedarType.h
@@ -234,6 +234,9 @@ typedef struct BLACK BLACK;
typedef struct SEND_SIGNATURE_PARAM SEND_SIGNATURE_PARAM;
typedef struct UPDATE_CLIENT UPDATE_CLIENT;
typedef struct UPDATE_CLIENT_SETTING UPDATE_CLIENT_SETTING;
+typedef struct HTTP_MIME_TYPE HTTP_MIME_TYPE;
+typedef struct WS WS;
+typedef struct WSP WSP;
// ==============================================================
@@ -673,6 +676,7 @@ typedef struct IPC_ASYNC IPC_ASYNC;
typedef struct IPC_PARAM IPC_PARAM;
typedef struct IPC_DHCP_RELESAE_QUEUE IPC_DHCP_RELESAE_QUEUE;
typedef struct IPC_MSCHAP_V2_AUTHINFO IPC_MSCHAP_V2_AUTHINFO;
+typedef struct IPC_SESSION_SHARED_BUFFER_DATA IPC_SESSION_SHARED_BUFFER_DATA;
// ==============================================================
diff --git a/src/Cedar/Client.c b/src/Cedar/Client.c
index 30bc6e4a..d3234ed4 100644
--- a/src/Cedar/Client.c
+++ b/src/Cedar/Client.c
@@ -4083,14 +4083,16 @@ void OutRpcClientEnumCa(PACK *p, RPC_CLIENT_ENUM_CA *e)
PackAddNum(p, "NumItem", e->NumItem);
+ PackSetCurrentJsonGroupName(p, "CAList");
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_CA_ITEM *item = e->Items[i];
PackAddIntEx(p, "Key", item->Key, i, e->NumItem);
PackAddUniStrEx(p, "SubjectName", item->SubjectName, i, e->NumItem);
PackAddUniStrEx(p, "IssuerName", item->IssuerName, i, e->NumItem);
- PackAddInt64Ex(p, "Expires", item->Expires, i, e->NumItem);
+ PackAddTime64Ex(p, "Expires", item->Expires, i, e->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
// RPC_GET_ISSUER
@@ -4361,6 +4363,7 @@ void OutRpcClientEnumSecure(PACK *p, RPC_CLIENT_ENUM_SECURE *e)
PackAddNum(p, "NumItem", e->NumItem);
+ PackSetCurrentJsonGroupName(p, "SecureDeviceList");
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_SECURE_ITEM *item = e->Items[i];
@@ -4370,6 +4373,7 @@ void OutRpcClientEnumSecure(PACK *p, RPC_CLIENT_ENUM_SECURE *e)
PackAddStrEx(p, "DeviceName", item->DeviceName, i, e->NumItem);
PackAddStrEx(p, "Manufacturer", item->Manufacturer, i, e->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
// RPC_USE_SECURE
@@ -4453,11 +4457,13 @@ void OutRpcEnumObjectInSecure(PACK *p, RPC_ENUM_OBJECT_IN_SECURE *e)
PackAddNum(p, "NumItem", e->NumItem);
PackAddInt(p, "hWnd", e->hWnd);
+ PackSetCurrentJsonGroupName(p, "ObjectList");
for (i = 0;i < e->NumItem;i++)
{
PackAddStrEx(p, "ItemName", e->ItemName[i], i, e->NumItem);
PackAddIntEx(p, "ItemType", e->ItemType[i], i, e->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
// RPC_CLIENT_CREATE_VLAN
@@ -4577,6 +4583,7 @@ void OutRpcClientEnumVLan(PACK *p, RPC_CLIENT_ENUM_VLAN *v)
PackAddNum(p, "NumItem", v->NumItem);
+ PackSetCurrentJsonGroupName(p, "VLanList");
for (i = 0;i < v->NumItem;i++)
{
RPC_CLIENT_ENUM_VLAN_ITEM *item = v->Items[i];
@@ -4586,6 +4593,7 @@ void OutRpcClientEnumVLan(PACK *p, RPC_CLIENT_ENUM_VLAN *v)
PackAddStrEx(p, "MacAddress", item->MacAddress, i, v->NumItem);
PackAddStrEx(p, "Version", item->Version, i, v->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
// CLIENT_OPTION
@@ -4651,10 +4659,10 @@ void OutRpcClientOption(PACK *p, CLIENT_OPTION *c)
PackAddInt(p, "NumRetry", c->NumRetry);
PackAddInt(p, "RetryInterval", c->RetryInterval);
PackAddInt(p, "MaxConnection", c->MaxConnection);
- PackAddInt(p, "UseEncrypt", c->UseEncrypt);
- PackAddInt(p, "UseCompress", c->UseCompress);
- PackAddInt(p, "HalfConnection", c->HalfConnection);
- PackAddInt(p, "NoRoutingTracking", c->NoRoutingTracking);
+ PackAddBool(p, "UseEncrypt", c->UseEncrypt);
+ PackAddBool(p, "UseCompress", c->UseCompress);
+ PackAddBool(p, "HalfConnection", c->HalfConnection);
+ PackAddBool(p, "NoRoutingTracking", c->NoRoutingTracking);
PackAddInt(p, "AdditionalConnectionInterval", c->AdditionalConnectionInterval);
PackAddInt(p, "ConnectionDisconnectSpan", c->ConnectionDisconnectSpan);
PackAddBool(p, "HideStatusWindow", c->HideStatusWindow);
@@ -4866,6 +4874,7 @@ void OutRpcClientEnumAccount(PACK *p, RPC_CLIENT_ENUM_ACCOUNT *e)
PackAddNum(p, "NumItem", e->NumItem);
+ PackSetCurrentJsonGroupName(p, "AccountList");
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = e->Items[i];
@@ -4881,10 +4890,11 @@ void OutRpcClientEnumAccount(PACK *p, RPC_CLIENT_ENUM_ACCOUNT *e)
PackAddBoolEx(p, "Connected", item->Connected, i, e->NumItem);
PackAddIntEx(p, "Port", item->Port, i, e->NumItem);
PackAddStrEx(p, "HubName", item->HubName, i, e->NumItem);
- PackAddInt64Ex(p, "CreateDateTime", item->CreateDateTime, i, e->NumItem);
- PackAddInt64Ex(p, "UpdateDateTime", item->UpdateDateTime, i, e->NumItem);
- PackAddInt64Ex(p, "LastConnectDateTime", item->LastConnectDateTime, i, e->NumItem);
+ PackAddTime64Ex(p, "CreateDateTime", item->CreateDateTime, i, e->NumItem);
+ PackAddTime64Ex(p, "UpdateDateTime", item->UpdateDateTime, i, e->NumItem);
+ PackAddTime64Ex(p, "LastConnectDateTime", item->LastConnectDateTime, i, e->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
// RPC_CLIENT_DELETE_ACCOUNT
@@ -4998,9 +5008,9 @@ void OutRpcClientGetAccount(PACK *p, RPC_CLIENT_GET_ACCOUNT *c)
PackAddData(p, "ShortcutKey", c->ShortcutKey, SHA1_SIZE);
- PackAddInt64(p, "CreateDateTime", c->CreateDateTime);
- PackAddInt64(p, "UpdateDateTime", c->UpdateDateTime);
- PackAddInt64(p, "LastConnectDateTime", c->LastConnectDateTime);
+ PackAddTime64(p, "CreateDateTime", c->CreateDateTime);
+ PackAddTime64(p, "UpdateDateTime", c->UpdateDateTime);
+ PackAddTime64(p, "LastConnectDateTime", c->LastConnectDateTime);
}
// RPC_CLIENT_CONNECT
@@ -5103,6 +5113,7 @@ void InRpcClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *s, PACK *p
s->UseCompress = PackGetInt(p, "UseCompress") ? true : false;
s->IsRUDPSession = PackGetInt(p, "IsRUDPSession") ? true : false;
PackGetStr(p, "UnderlayProtocol", s->UnderlayProtocol, sizeof(s->UnderlayProtocol));
+ PackGetStr(p, "ProtocolDetails", s->ProtocolDetails, sizeof(s->ProtocolDetails));
s->IsUdpAccelerationEnabled = PackGetInt(p, "IsUdpAccelerationEnabled") ? true : false;
s->IsUsingUdpAcceleration = PackGetInt(p, "IsUsingUdpAcceleration") ? true : false;
@@ -5148,32 +5159,33 @@ void OutRpcClientGetConnectionStatus(PACK *p, RPC_CLIENT_GET_CONNECTION_STATUS *
PackAddData(p, "SessionKey", c->SessionKey, SHA1_SIZE);
- PackAddInt(p, "Active", c->Active);
- PackAddInt(p, "Connected", c->Connected);
+ PackAddBool(p, "Active", c->Active);
+ PackAddBool(p, "Connected", c->Connected);
PackAddInt(p, "SessionStatus", c->SessionStatus);
PackAddInt(p, "ServerPort", c->ServerPort);
PackAddInt(p, "ServerProductVer", c->ServerProductVer);
PackAddInt(p, "ServerProductBuild", c->ServerProductBuild);
PackAddInt(p, "NumConnectionsEatablished", c->NumConnectionsEatablished);
- PackAddInt(p, "HalfConnection", c->HalfConnection);
- PackAddInt(p, "QoS", c->QoS);
+ PackAddBool(p, "HalfConnection", c->HalfConnection);
+ PackAddBool(p, "QoS", c->QoS);
PackAddInt(p, "MaxTcpConnections", c->MaxTcpConnections);
PackAddInt(p, "NumTcpConnections", c->NumTcpConnections);
PackAddInt(p, "NumTcpConnectionsUpload", c->NumTcpConnectionsUpload);
PackAddInt(p, "NumTcpConnectionsDownload", c->NumTcpConnectionsDownload);
- PackAddInt(p, "UseEncrypt", c->UseEncrypt);
- PackAddInt(p, "UseCompress", c->UseCompress);
- PackAddInt(p, "IsRUDPSession", c->IsRUDPSession);
+ PackAddBool(p, "UseEncrypt", c->UseEncrypt);
+ PackAddBool(p, "UseCompress", c->UseCompress);
+ PackAddBool(p, "IsRUDPSession", c->IsRUDPSession);
PackAddStr(p, "UnderlayProtocol", c->UnderlayProtocol);
- PackAddInt(p, "IsUdpAccelerationEnabled", c->IsUdpAccelerationEnabled);
- PackAddInt(p, "IsUsingUdpAcceleration", c->IsUsingUdpAcceleration);
+ PackAddStr(p, "ProtocolDetails", c->ProtocolDetails);
+ PackAddBool(p, "IsUdpAccelerationEnabled", c->IsUdpAccelerationEnabled);
+ PackAddBool(p, "IsUsingUdpAcceleration", c->IsUsingUdpAcceleration);
PackAddBool(p, "IsBridgeMode", c->IsBridgeMode);
PackAddBool(p, "IsMonitorMode", c->IsMonitorMode);
- PackAddInt64(p, "StartTime", c->StartTime);
- PackAddInt64(p, "FirstConnectionEstablisiedTime", c->FirstConnectionEstablisiedTime);
- PackAddInt64(p, "CurrentConnectionEstablishTime", c->CurrentConnectionEstablishTime);
+ PackAddTime64(p, "StartTime", c->StartTime);
+ PackAddTime64(p, "FirstConnectionEstablisiedTime", c->FirstConnectionEstablisiedTime);
+ PackAddTime64(p, "CurrentConnectionEstablishTime", c->CurrentConnectionEstablishTime);
PackAddInt64(p, "TotalSendSize", c->TotalSendSize);
PackAddInt64(p, "TotalRecvSize", c->TotalRecvSize);
PackAddInt64(p, "TotalSendSizeReal", c->TotalSendSizeReal);
@@ -6124,9 +6136,23 @@ void CiGetSessionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *st, SESSION *s)
st->IsRUDPSession = s->IsRUDPSession;
// Physical communication protocol
StrCpy(st->UnderlayProtocol, sizeof(st->UnderlayProtocol), s->UnderlayProtocol);
+ // Protocol details
+ StrCpy(st->ProtocolDetails, sizeof(st->ProtocolDetails), s->ProtocolDetails);
+ Trim(st->ProtocolDetails);
// UDP acceleration function
st->IsUdpAccelerationEnabled = s->UseUdpAcceleration;
st->IsUsingUdpAcceleration = s->IsUsingUdpAcceleration;
+ if (s->IpcSessionShared != NULL && IsEmptyStr(s->IpcSessionShared->ProtocolDetails) == false)
+ {
+ char tmp[256];
+ StrCpy(tmp, sizeof(tmp), s->IpcSessionShared->ProtocolDetails);
+ Trim(tmp);
+ StrCat(st->ProtocolDetails, sizeof(st->ProtocolDetails), " ");
+ StrCat(st->ProtocolDetails, sizeof(st->ProtocolDetails), tmp);
+
+ st->IsUdpAccelerationEnabled = s->IpcSessionShared->EnableUdpAccel;
+ st->IsUsingUdpAcceleration = s->IpcSessionShared->UsingUdpAccel;
+ }
// Session key
Copy(st->SessionKey, s->SessionKey, SHA1_SIZE);
// Policy
diff --git a/src/Cedar/Client.h b/src/Cedar/Client.h
index f57e32e8..6790a91a 100644
--- a/src/Cedar/Client.h
+++ b/src/Cedar/Client.h
@@ -433,6 +433,7 @@ struct RPC_CLIENT_GET_CONNECTION_STATUS
bool UseCompress; // Use of compression
bool IsRUDPSession; // R-UDP session
char UnderlayProtocol[64]; // Physical communication protocol
+ char ProtocolDetails[256]; // Protocol Details
bool IsUdpAccelerationEnabled; // The UDP acceleration is enabled
bool IsUsingUdpAcceleration; // Using the UDP acceleration function
char SessionName[MAX_SESSION_NAME_LEN + 1]; // Session name
diff --git a/src/Cedar/Command.c b/src/Cedar/Command.c
index 71568d43..5b2c67e8 100644
--- a/src/Cedar/Command.c
+++ b/src/Cedar/Command.c
@@ -14494,6 +14494,12 @@ void CmdPrintStatusToListViewEx(CT *ct, RPC_CLIENT_GET_CONNECTION_STATUS *s, boo
CtInsert(ct, _UU("CM_ST_UNDERLAY_PROTOCOL"), tmp);
}
+ if (IsEmptyStr(s->ProtocolDetails) == false)
+ {
+ StrToUni(tmp, sizeof(tmp), s->ProtocolDetails);
+ CtInsert(ct, _UU("CM_ST_PROTOCOL_DETAILS"), tmp);
+ }
+
CtInsert(ct, _UU("CM_ST_UDP_ACCEL_ENABLED"), (s->IsUdpAccelerationEnabled ? _UU("CM_ST_YES") : _UU("CM_ST_NO")));
CtInsert(ct, _UU("CM_ST_UDP_ACCEL_USING"), (s->IsUsingUdpAcceleration ? _UU("CM_ST_YES") : _UU("CM_ST_NO")));
@@ -21663,6 +21669,9 @@ UINT PsLicenseAdd(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
FreeParamValueList(o);
+ c->Write(c, _UU("SM_LICENSE_WARNING"));
+ c->Write(c, L"\n");
+
return 0;
}
diff --git a/src/Cedar/Connection.c b/src/Cedar/Connection.c
index ebd8a6cb..5bdb0a34 100644
--- a/src/Cedar/Connection.c
+++ b/src/Cedar/Connection.c
@@ -1267,6 +1267,8 @@ void ConnectionSend(CONNECTION *c, UINT64 now)
s->TotalSendSizeReal += b->Size;
c->CurrentSendQueueSize -= b->Size;
+
+ Free(new_buf);
}
FreeBlock(b);
@@ -1861,6 +1863,18 @@ void ConnectionReceive(CONNECTION *c, CANCEL *c1, CANCEL *c2)
{
TUBE *t = sock->BulkRecvTube;
+ //for testing purpose
+ //if (sock->test_tmp1 == 0) sock->test_tmp1 = now;
+ //if ((sock->test_tmp1 + 5000ULL) <= now)
+ //{
+ // // bugbug
+ // if (c->ServerMode == false)
+ // {
+ // WHERE;
+ // Disconnect(sock);
+ // }
+ //}
+
if (s->EnableBulkOnRUDP)
{
// R-UDP bulk transfer data reception
@@ -2789,6 +2803,8 @@ BLOCK *NewBlock(void *data, UINT size, int compress)
b = MallocFast(sizeof(BLOCK));
+ b->RawFlagRetUdpAccel = 0;
+
b->IsFlooding = false;
b->PriorityQoS = b->Ttl = b->Param1 = 0;
diff --git a/src/Cedar/Connection.h b/src/Cedar/Connection.h
index 96b7627f..2b1f8091 100644
--- a/src/Cedar/Connection.h
+++ b/src/Cedar/Connection.h
@@ -252,6 +252,7 @@ struct BLOCK
UINT Ttl; // TTL value (Used only in ICMP NAT of Virtual.c)
UINT Param1; // Parameter 1
bool IsFlooding; // Is flooding packet
+ UCHAR RawFlagRetUdpAccel; // Raw flag returned by UDP accel
};
// Connection structure
@@ -305,6 +306,7 @@ struct CONNECTION
void *hWndForUI; // Parent window
bool IsInProc; // In-process
char InProcPrefix[64]; // Prefix
+ UINT InProcLayer; // InProc layer
UINT AdditionalConnectionFailedCounter; // Additional connection failure counter
UINT64 LastCounterResetTick; // Time the counter was reset finally
bool WasSstp; // Processed the SSTP
@@ -314,6 +316,9 @@ struct CONNECTION
UINT LastPacketQueueSize; // The last queue size of packets
UINT LastRecvFifoTotalSize; // The last RecvFifo total size
UINT LastRecvBlocksNum; // The last ReceivedBlocks num
+ bool IsJsonRpc; // Is JSON-RPC
+ bool JsonRpcAuthed; // JSON-RPC Authed
+ LISTENER *Listener; // Listener ref
};
diff --git a/src/Cedar/DDNS.c b/src/Cedar/DDNS.c
index c9056dd7..66373dd4 100644
--- a/src/Cedar/DDNS.c
+++ b/src/Cedar/DDNS.c
@@ -134,6 +134,9 @@ void DCGetStatus(DDNS_CLIENT *c, DDNS_CLIENT_STATUS *st)
Copy(&st->InternetSetting, &c->InternetSetting, sizeof(INTERNET_SETTING));
}
Unlock(c->Lock);
+
+ UniStrCpy(st->ErrStr_IPv4, sizeof(st->ErrStr_IPv4), _E(st->Err_IPv4));
+ UniStrCpy(st->ErrStr_IPv6, sizeof(st->ErrStr_IPv6), _E(st->Err_IPv6));
}
// Set the Internet settings
diff --git a/src/Cedar/DDNS.h b/src/Cedar/DDNS.h
index 3c935d27..d3e1363d 100644
--- a/src/Cedar/DDNS.h
+++ b/src/Cedar/DDNS.h
@@ -208,6 +208,8 @@ struct DDNS_REGISTER_PARAM
struct DDNS_CLIENT_STATUS
{
UINT Err_IPv4, Err_IPv6; // Last error
+ wchar_t ErrStr_IPv4[MAX_SIZE];
+ wchar_t ErrStr_IPv6[MAX_SIZE];
char CurrentHostName[DDNS_MAX_HOSTNAME + 1]; // Current host name
char CurrentFqdn[MAX_SIZE]; // Current FQDN
char DnsSuffix[MAX_SIZE]; // DNS suffix
diff --git a/src/Cedar/EtherLog.c b/src/Cedar/EtherLog.c
index 36bf0932..ea290915 100644
--- a/src/Cedar/EtherLog.c
+++ b/src/Cedar/EtherLog.c
@@ -662,6 +662,7 @@ void OutRpcEnumDevice(PACK *p, RPC_ENUM_DEVICE *t)
PackAddInt(p, "NumItem", t->NumItem);
+ PackSetCurrentJsonGroupName(p, "DeviceList");
for (i = 0;i < t->NumItem;i++)
{
RPC_ENUM_DEVICE_ITEM *d = &t->Items[i];
@@ -669,6 +670,7 @@ void OutRpcEnumDevice(PACK *p, RPC_ENUM_DEVICE *t)
PackAddStrEx(p, "DeviceName", d->DeviceName, i, t->NumItem);
PackAddBoolEx(p, "Active", d->Active, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
PackAddBool(p, "IsLicenseSupported", t->IsLicenseSupported);
}
@@ -709,7 +711,7 @@ void OutRpcElLicenseStatus(PACK *p, RPC_EL_LICENSE_STATUS *t)
PackAddBool(p, "Valid", t->Valid);
PackAddInt64(p, "SystemId", t->SystemId);
- PackAddInt64(p, "SystemExpires", t->SystemExpires);
+ PackAddTime64(p, "SystemExpires", t->SystemExpires);
}
// Listener thread
diff --git a/src/Cedar/Hub.c b/src/Cedar/Hub.c
index 7dc3de39..da339c2a 100644
--- a/src/Cedar/Hub.c
+++ b/src/Cedar/Hub.c
@@ -159,7 +159,7 @@ UINT num_admin_options = sizeof(admin_options) / sizeof(ADMIN_OPTION);
// Create an EAP client for the specified Virtual Hub
-EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username)
+EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username, char *vpn_protocol_state_str)
{
HUB *hub = NULL;
EAP_CLIENT *ret = NULL;
@@ -209,6 +209,11 @@ EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, ch
if (eap != NULL)
{
+ if (IsEmptyStr(vpn_protocol_state_str) == false)
+ {
+ StrCpy(eap->In_VpnProtocolState, sizeof(eap->In_VpnProtocolState), vpn_protocol_state_str);
+ }
+
if (use_peap == false)
{
// EAP
@@ -778,6 +783,8 @@ void HubOptionStructToData(RPC_ADMIN_OPTION *ao, HUB_OPTION *o, char *hub_name)
{
ADMIN_OPTION *a = LIST_DATA(aol, i);
+ UniStrCpy(a->Descrption, sizeof(a->Descrption), GetHubAdminOptionHelpString(a->Name));
+
Copy(&ao->Items[i], a, sizeof(ADMIN_OPTION));
Free(a);
diff --git a/src/Cedar/Hub.h b/src/Cedar/Hub.h
index 5334dbfd..884c5c3e 100644
--- a/src/Cedar/Hub.h
+++ b/src/Cedar/Hub.h
@@ -384,6 +384,7 @@ struct ADMIN_OPTION
{
char Name[MAX_ADMIN_OPTION_NAME_LEN + 1]; // Name
UINT Value; // Data
+ wchar_t Descrption[MAX_SIZE]; // Descrption
};
// Certificate Revocation List entry
@@ -634,7 +635,7 @@ void CalcTrafficDiff(TRAFFIC *diff, TRAFFIC *old, TRAFFIC *current);
bool CheckMaxLoggedPacketsPerMinute(SESSION *s, UINT max_packets, UINT64 now);
void VgsSetUserAgentValue(char *str);
void VgsSetEmbTag(bool b);
-EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username);
+EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username, char *vpn_protocol_state_str);
#endif // HUB_H
diff --git a/src/Cedar/IPsec_EtherIP.c b/src/Cedar/IPsec_EtherIP.c
index 7c7d6222..1db912c1 100644
--- a/src/Cedar/IPsec_EtherIP.c
+++ b/src/Cedar/IPsec_EtherIP.c
@@ -161,7 +161,7 @@ void EtherIPIpcConnectThread(THREAD *t, void *p)
&s->ClientIP, s->ClientPort,
&s->ServerIP, s->ServerPort,
tmp,
- s->CryptName, true, mss, NULL);
+ s->CryptName, true, mss, NULL, NULL, IPC_LAYER_2);
if (ipc != NULL)
{
diff --git a/src/Cedar/IPsec_IPC.c b/src/Cedar/IPsec_IPC.c
index 705a9539..82831784 100644
--- a/src/Cedar/IPsec_IPC.c
+++ b/src/Cedar/IPsec_IPC.c
@@ -314,7 +314,7 @@ IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code)
param->UserName, param->Password, error_code, &param->ClientIp,
param->ClientPort, &param->ServerIp, param->ServerPort,
param->ClientHostname, param->CryptName,
- param->BridgeMode, param->Mss, NULL);
+ param->BridgeMode, param->Mss, NULL, param->ClientCertificate, param->Layer);
return ipc;
}
@@ -323,7 +323,8 @@ 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,
UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port,
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,
+ UINT layer)
{
IPC *ipc;
UINT dummy_int = 0;
@@ -338,6 +339,7 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
NODE_INFO info;
BUF *b;
UCHAR mschap_v2_server_response_20[20];
+ UINT64 u64;
// Validate arguments
if (cedar == NULL || username == NULL || password == NULL || client_hostname == NULL)
{
@@ -371,6 +373,12 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
ipc->Cedar = cedar;
AddRef(cedar->ref);
+ ipc->Layer = layer;
+ if (ipc->Layer == 0)
+ {
+ ipc->Layer = IPC_LAYER_2;
+ }
+
ipc->FlushList = NewTubeFlushList();
StrCpy(ipc->ClientHostname, sizeof(ipc->ClientHostname), client_hostname);
@@ -416,7 +424,14 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
FreePack(p);
// 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);
PackAddInt(p, "client_ver", cedar->Version);
PackAddInt(p, "client_build", cedar->Build);
@@ -451,6 +466,7 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
PackAddStr(p, "inproc_postfix", postfix);
PackAddStr(p, "inproc_cryptname", crypt_name);
+ PackAddInt(p, "inproc_layer", ipc->Layer);
// Node information
Zero(&info, sizeof(info));
@@ -532,6 +548,10 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char
Debug("IPC: Session = %s, Connection = %s, Mac = %s\n", ipc->SessionName, ipc->ConnectionName, macstr);
+ u64 = PackGetInt64(p, "IpcSessionSharedBuffer");
+ ipc->IpcSessionSharedBuffer = (SHARED_BUFFER *)u64;
+ ipc->IpcSessionShared = ipc->IpcSessionSharedBuffer->Data;
+
FreePack(p);
ReleaseSock(a);
@@ -665,6 +685,8 @@ void FreeIPC(IPC *ipc)
}
ReleaseQueue(ipc->IPv4RecviedQueue);
+
+ ReleaseSharedBuffer(ipc->IpcSessionSharedBuffer);
Free(ipc);
}
diff --git a/src/Cedar/IPsec_IPC.h b/src/Cedar/IPsec_IPC.h
index 4a733297..2340788e 100644
--- a/src/Cedar/IPsec_IPC.h
+++ b/src/Cedar/IPsec_IPC.h
@@ -119,6 +119,9 @@
#define IPC_PASSWORD_MSCHAPV2_TAG "xH7DiNlurDhcYV4a:"
+#define IPC_LAYER_2 2
+#define IPC_LAYER_3 3
+
// ARP table entry
struct IPC_ARP
{
@@ -138,6 +141,14 @@ struct IPC_DHCP_RELESAE_QUEUE
UCHAR MacAddress[6];
};
+// IPC_SESSION_SHARED_BUFFER_DATA
+struct IPC_SESSION_SHARED_BUFFER_DATA
+{
+ char ProtocolDetails[256]; // Protocol Details
+ bool EnableUdpAccel;
+ bool UsingUdpAccel;
+};
+
// IPC_PARAM
struct IPC_PARAM
{
@@ -156,6 +167,8 @@ struct IPC_PARAM
UINT Mss;
bool IsL3Mode;
bool IsOpenVPN;
+ X *ClientCertificate;
+ UINT Layer;
};
// IPC_ASYNC object
@@ -200,6 +213,9 @@ struct IPC
TUBE_FLUSH_LIST *FlushList; // Tube Flush List
UCHAR MsChapV2_ServerResponse[20]; // Server response
DHCP_CLASSLESS_ROUTE_TABLE ClasslessRoute; // Classless routing table
+ SHARED_BUFFER *IpcSessionSharedBuffer; // A shared buffer between IPC and Session
+ IPC_SESSION_SHARED_BUFFER_DATA *IpcSessionShared; // A shared data between IPC and Session
+ UINT Layer;
};
// MS-CHAPv2 authentication information
@@ -215,7 +231,8 @@ struct IPC_MSCHAP_V2_AUTHINFO
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,
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,
+ UINT layer);
IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code);
IPC *NewIPCBySock(CEDAR *cedar, SOCK *s, void *mac_address);
void FreeIPC(IPC *ipc);
diff --git a/src/Cedar/IPsec_PPP.c b/src/Cedar/IPsec_PPP.c
index d47a5f08..5d04f099 100644
--- a/src/Cedar/IPsec_PPP.c
+++ b/src/Cedar/IPsec_PPP.c
@@ -299,7 +299,7 @@ void PPPThread(THREAD *thread, void *param)
IPToStr(client_ip_tmp, sizeof(client_ip_tmp), &p->ClientIP);
- eap = HubNewEapClient(p->Cedar, hub, client_ip_tmp, id);
+ eap = HubNewEapClient(p->Cedar, hub, client_ip_tmp, id, "L3:PPP");
if (eap)
{
@@ -1009,7 +1009,8 @@ PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req)
// Attempt to connect with IPC
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
&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,
+ IPC_LAYER_3);
if (ipc != NULL)
{
@@ -1142,7 +1143,8 @@ PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req)
ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
&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,
+ IPC_LAYER_3);
if (ipc != NULL)
{
diff --git a/src/Cedar/Interop_OpenVPN.c b/src/Cedar/Interop_OpenVPN.c
index 4c6d8771..dbb203e9 100644
--- a/src/Cedar/Interop_OpenVPN.c
+++ b/src/Cedar/Interop_OpenVPN.c
@@ -433,7 +433,8 @@ void OvsProcessRecvControlPacket(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN
// Create an SSL pipe
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);
@@ -703,8 +704,19 @@ void OvsBeginIPCAsyncConnectionIfEmpty(OPENVPN_SERVER *s, OPENVPN_SESSION *se, O
p.BridgeMode = true;
}
+ if (IsEmptyStr(c->ClientKey.Username) || IsEmptyStr(c->ClientKey.Password))
+ {
+ // OpenVPN X.509 certificate authentication is used only when no username / password is specified
+ if (c->ClientCert.X != NULL)
+ {
+ p.ClientCertificate = c->ClientCert.X;
+ }
+ }
+
p.IsOpenVPN = true;
+ p.Layer = (se->Mode == OPENVPN_MODE_L2) ? IPC_LAYER_2 : IPC_LAYER_3;
+
// Calculate the MSS
p.Mss = OvsCalcTcpMss(s, se, c);
Debug("MSS=%u\n", p.Mss);
@@ -771,6 +783,26 @@ void OvsSetupSessionParameters(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_C
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));
StrCpy(opt_str, sizeof(opt_str), data->OptionString);
if (s->Cedar != NULL && (IsEmptyStr(opt_str) || StartWith(opt_str, "V0 UNDEF") || InStr(opt_str, ",") == false))
@@ -1350,6 +1382,11 @@ void OvsFreeChannel(OPENVPN_CHANNEL *c)
FreeMd(c->MdRecv);
FreeMd(c->MdSend);
+ if (c->ClientCert.X != NULL)
+ {
+ FreeX(c->ClientCert.X);
+ }
+
Free(c);
}
diff --git a/src/Cedar/Interop_OpenVPN.h b/src/Cedar/Interop_OpenVPN.h
index 8db9beca..b23eca5e 100644
--- a/src/Cedar/Interop_OpenVPN.h
+++ b/src/Cedar/Interop_OpenVPN.h
@@ -248,6 +248,7 @@ struct OPENVPN_CHANNEL
bool IsInitiatorServer; // Whether the channel was started from the server side
bool RekeyInitiated; // Whether re-keying has already started
UINT64 NextRekey;
+ struct SslClientCertInfo ClientCert; // Client certificate and verification data
};
// OpenVPN session
diff --git a/src/Cedar/Listener.c b/src/Cedar/Listener.c
index 5da5ade6..f57dcf2a 100644
--- a/src/Cedar/Listener.c
+++ b/src/Cedar/Listener.c
@@ -247,6 +247,9 @@ void TCPAcceptedThread(THREAD *t, void *param)
// Create a connection
c = NewServerConnection(r->Cedar, s, t);
+ AddRef(r->ref);
+ c->Listener = r;
+
// Register to Cedar as a transient connection
AddConnection(c->Cedar, c);
@@ -264,8 +267,11 @@ void TCPAcceptedThread(THREAD *t, void *param)
ConnectionAccept(c);
flag1 = c->flag1;
+
// Release
SLog(r->Cedar, "LS_CONNECTION_END_1", c->Name);
+ ReleaseListener(c->Listener);
+ c->Listener = NULL;
ReleaseConnection(c);
// Release
diff --git a/src/Cedar/Nat.c b/src/Cedar/Nat.c
index c5f782b8..c5e35af8 100644
--- a/src/Cedar/Nat.c
+++ b/src/Cedar/Nat.c
@@ -895,18 +895,21 @@ void OutRpcEnumDhcp(PACK *p, RPC_ENUM_DHCP *t)
PackAddInt(p, "NumItem", t->NumItem);
PackAddStr(p, "HubName", t->HubName);
+ PackSetCurrentJsonGroupName(p, "DhcpTable");
+
for (i = 0;i < t->NumItem;i++)
{
RPC_ENUM_DHCP_ITEM *e = &t->Items[i];
PackAddIntEx(p, "Id", e->Id, i, t->NumItem);
- PackAddInt64Ex(p, "LeasedTime", e->LeasedTime, i, t->NumItem);
- PackAddInt64Ex(p, "ExpireTime", e->ExpireTime, i, t->NumItem);
+ PackAddTime64Ex(p, "LeasedTime", e->LeasedTime, i, t->NumItem);
+ PackAddTime64Ex(p, "ExpireTime", e->ExpireTime, i, t->NumItem);
PackAddDataEx(p, "MacAddress", e->MacAddress, 6, i, t->NumItem);
PackAddIp32Ex(p, "IpAddress", e->IpAddress, i, t->NumItem);
PackAddIntEx(p, "Mask", e->Mask, i, t->NumItem);
PackAddStrEx(p, "Hostname", e->Hostname, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumDhcp(RPC_ENUM_DHCP *t)
{
@@ -963,6 +966,8 @@ void OutRpcEnumNat(PACK *p, RPC_ENUM_NAT *t)
PackAddInt(p, "NumItem", t->NumItem);
PackAddStr(p, "HubName", t->HubName);
+
+ PackSetCurrentJsonGroupName(p, "NatTable");
for (i = 0;i < t->NumItem;i++)
{
RPC_ENUM_NAT_ITEM *e = &t->Items[i];
@@ -975,12 +980,13 @@ void OutRpcEnumNat(PACK *p, RPC_ENUM_NAT *t)
PackAddIp32Ex(p, "DestIp", e->DestIp, i, t->NumItem);
PackAddStrEx(p, "DestHost", e->DestHost, i, t->NumItem);
PackAddIntEx(p, "DestPort", e->DestPort, i, t->NumItem);
- PackAddInt64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumItem);
- PackAddInt64Ex(p, "LastCommTime", e->LastCommTime, i, t->NumItem);
+ PackAddTime64Ex(p, "CreatedTime", e->CreatedTime, i, t->NumItem);
+ PackAddTime64Ex(p, "LastCommTime", e->LastCommTime, i, t->NumItem);
PackAddInt64Ex(p, "SendSize", e->SendSize, i, t->NumItem);
PackAddInt64Ex(p, "RecvSize", e->RecvSize, i, t->NumItem);
PackAddIntEx(p, "TcpStatus", e->TcpStatus, i, t->NumItem);
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcEnumNat(RPC_ENUM_NAT *t)
{
diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c
index 7febcf84..5fd8c12c 100644
--- a/src/Cedar/Protocol.c
+++ b/src/Cedar/Protocol.c
@@ -106,6 +106,726 @@
static UCHAR ssl_packet_start[3] = {0x17, 0x03, 0x00};
+// MIME list from https://www.freeformatter.com/mime-types-list.html
+static HTTP_MIME_TYPE http_mime_types[] =
+{
+ {".x3d", "application/vnd.hzn-3d-crossword"},
+ {".3gp", "video/3gpp"},
+ {".3g2", "video/3gpp2"},
+ {".mseq", "application/vnd.mseq"},
+ {".pwn", "application/vnd.3m.post-it-notes"},
+ {".plb", "application/vnd.3gpp.pic-bw-large"},
+ {".psb", "application/vnd.3gpp.pic-bw-small"},
+ {".pvb", "application/vnd.3gpp.pic-bw-var"},
+ {".tcap", "application/vnd.3gpp2.tcap"},
+ {".7z", "application/x-7z-compressed"},
+ {".abw", "application/x-abiword"},
+ {".ace", "application/x-ace-compressed"},
+ {".acc", "application/vnd.americandynamics.acc"},
+ {".acu", "application/vnd.acucobol"},
+ {".atc", "application/vnd.acucorp"},
+ {".adp", "audio/adpcm"},
+ {".aab", "application/x-authorware-bin"},
+ {".aam", "application/x-authorware-map"},
+ {".aas", "application/x-authorware-seg"},
+ {".air", "application/vnd.adobe.air-application-installer-package+zip"},
+ {".swf", "application/x-shockwave-flash"},
+ {".fxp", "application/vnd.adobe.fxp"},
+ {".pdf", "application/pdf"},
+ {".ppd", "application/vnd.cups-ppd"},
+ {".dir", "application/x-director"},
+ {".xdp", "application/vnd.adobe.xdp+xml"},
+ {".xfdf", "application/vnd.adobe.xfdf"},
+ {".aac", "audio/x-aac"},
+ {".ahead", "application/vnd.ahead.space"},
+ {".azf", "application/vnd.airzip.filesecure.azf"},
+ {".azs", "application/vnd.airzip.filesecure.azs"},
+ {".azw", "application/vnd.amazon.ebook"},
+ {".ami", "application/vnd.amiga.ami"},
+ {".apk", "application/vnd.android.package-archive"},
+ {".cii", "application/vnd.anser-web-certificate-issue-initiation"},
+ {".fti", "application/vnd.anser-web-funds-transfer-initiation"},
+ {".atx", "application/vnd.antix.game-component"},
+ {".dmg", "application/x-apple-diskimage"},
+ {".mpkg", "application/vnd.apple.installer+xml"},
+ {".aw", "application/applixware"},
+ {".les", "application/vnd.hhe.lesson-player"},
+ {".swi", "application/vnd.aristanetworks.swi"},
+ {".s", "text/x-asm"},
+ {".atomcat", "application/atomcat+xml"},
+ {".atomsvc", "application/atomsvc+xml"},
+ {".atom", "application/atom+xml"},
+ {".ac", "application/pkix-attr-cert"},
+ {".aif", "audio/x-aiff"},
+ {".avi", "video/x-msvideo"},
+ {".aep", "application/vnd.audiograph"},
+ {".dxf", "image/vnd.dxf"},
+ {".dwf", "model/vnd.dwf"},
+ {".par", "text/plain-bas"},
+ {".bcpio", "application/x-bcpio"},
+ {".bin", "application/octet-stream"},
+ {".bmp", "image/bmp"},
+ {".torrent", "application/x-bittorrent"},
+ {".cod", "application/vnd.rim.cod"},
+ {".mpm", "application/vnd.blueice.multipass"},
+ {".bmi", "application/vnd.bmi"},
+ {".sh", "application/x-sh"},
+ {".btif", "image/prs.btif"},
+ {".rep", "application/vnd.businessobjects"},
+ {".bz", "application/x-bzip"},
+ {".bz2", "application/x-bzip2"},
+ {".csh", "application/x-csh"},
+ {".c", "text/x-c"},
+ {".cdxml", "application/vnd.chemdraw+xml"},
+ {".css", "text/css"},
+ {".cdx", "chemical/x-cdx"},
+ {".cml", "chemical/x-cml"},
+ {".csml", "chemical/x-csml"},
+ {".cdbcmsg", "application/vnd.contact.cmsg"},
+ {".cla", "application/vnd.claymore"},
+ {".c4g", "application/vnd.clonk.c4group"},
+ {".sub", "image/vnd.dvb.subtitle"},
+ {".cdmia", "application/cdmi-capability"},
+ {".cdmic", "application/cdmi-container"},
+ {".cdmid", "application/cdmi-domain"},
+ {".cdmio", "application/cdmi-object"},
+ {".cdmiq", "application/cdmi-queue"},
+ {".c11amc", "application/vnd.cluetrust.cartomobile-config"},
+ {".c11amz", "application/vnd.cluetrust.cartomobile-config-pkg"},
+ {".ras", "image/x-cmu-raster"},
+ {".dae", "model/vnd.collada+xml"},
+ {".csv", "text/csv"},
+ {".cpt", "application/mac-compactpro"},
+ {".wmlc", "application/vnd.wap.wmlc"},
+ {".cgm", "image/cgm"},
+ {".ice", "x-conference/x-cooltalk"},
+ {".cmx", "image/x-cmx"},
+ {".xar", "application/vnd.xara"},
+ {".cmc", "application/vnd.cosmocaller"},
+ {".cpio", "application/x-cpio"},
+ {".clkx", "application/vnd.crick.clicker"},
+ {".clkk", "application/vnd.crick.clicker.keyboard"},
+ {".clkp", "application/vnd.crick.clicker.palette"},
+ {".clkt", "application/vnd.crick.clicker.template"},
+ {".clkw", "application/vnd.crick.clicker.wordbank"},
+ {".wbs", "application/vnd.criticaltools.wbs+xml"},
+ {".cryptonote", "application/vnd.rig.cryptonote"},
+ {".cif", "chemical/x-cif"},
+ {".cmdf", "chemical/x-cmdf"},
+ {".cu", "application/cu-seeme"},
+ {".cww", "application/prs.cww"},
+ {".curl", "text/vnd.curl"},
+ {".dcurl", "text/vnd.curl.dcurl"},
+ {".mcurl", "text/vnd.curl.mcurl"},
+ {".scurl", "text/vnd.curl.scurl"},
+ {".car", "application/vnd.curl.car"},
+ {".pcurl", "application/vnd.curl.pcurl"},
+ {".cmp", "application/vnd.yellowriver-custom-menu"},
+ {".dssc", "application/dssc+der"},
+ {".xdssc", "application/dssc+xml"},
+ {".deb", "application/x-debian-package"},
+ {".uva", "audio/vnd.dece.audio"},
+ {".uvi", "image/vnd.dece.graphic"},
+ {".uvh", "video/vnd.dece.hd"},
+ {".uvm", "video/vnd.dece.mobile"},
+ {".uvu", "video/vnd.uvvu.mp4"},
+ {".uvp", "video/vnd.dece.pd"},
+ {".uvs", "video/vnd.dece.sd"},
+ {".uvv", "video/vnd.dece.video"},
+ {".dvi", "application/x-dvi"},
+ {".seed", "application/vnd.fdsn.seed"},
+ {".dtb", "application/x-dtbook+xml"},
+ {".res", "application/x-dtbresource+xml"},
+ {".ait", "application/vnd.dvb.ait"},
+ {".svc", "application/vnd.dvb.service"},
+ {".eol", "audio/vnd.digital-winds"},
+ {".djvu", "image/vnd.djvu"},
+ {".dtd", "application/xml-dtd"},
+ {".mlp", "application/vnd.dolby.mlp"},
+ {".wad", "application/x-doom"},
+ {".dpg", "application/vnd.dpgraph"},
+ {".dra", "audio/vnd.dra"},
+ {".dfac", "application/vnd.dreamfactory"},
+ {".dts", "audio/vnd.dts"},
+ {".dtshd", "audio/vnd.dts.hd"},
+ {".dwg", "image/vnd.dwg"},
+ {".geo", "application/vnd.dynageo"},
+ {".es", "application/ecmascript"},
+ {".mag", "application/vnd.ecowin.chart"},
+ {".mmr", "image/vnd.fujixerox.edmics-mmr"},
+ {".rlc", "image/vnd.fujixerox.edmics-rlc"},
+ {".exi", "application/exi"},
+ {".mgz", "application/vnd.proteus.magazine"},
+ {".epub", "application/epub+zip"},
+ {".eml", "message/rfc822"},
+ {".nml", "application/vnd.enliven"},
+ {".xpr", "application/vnd.is-xpr"},
+ {".xif", "image/vnd.xiff"},
+ {".xfdl", "application/vnd.xfdl"},
+ {".emma", "application/emma+xml"},
+ {".ez2", "application/vnd.ezpix-album"},
+ {".ez3", "application/vnd.ezpix-package"},
+ {".fst", "image/vnd.fst"},
+ {".fvt", "video/vnd.fvt"},
+ {".fbs", "image/vnd.fastbidsheet"},
+ {".fe_launch", "application/vnd.denovo.fcselayout-link"},
+ {".f4v", "video/x-f4v"},
+ {".flv", "video/x-flv"},
+ {".fpx", "image/vnd.fpx"},
+ {".npx", "image/vnd.net-fpx"},
+ {".flx", "text/vnd.fmi.flexstor"},
+ {".fli", "video/x-fli"},
+ {".ftc", "application/vnd.fluxtime.clip"},
+ {".fdf", "application/vnd.fdf"},
+ {".f", "text/x-fortran"},
+ {".mif", "application/vnd.mif"},
+ {".fm", "application/vnd.framemaker"},
+ {".fh", "image/x-freehand"},
+ {".fsc", "application/vnd.fsc.weblaunch"},
+ {".fnc", "application/vnd.frogans.fnc"},
+ {".ltf", "application/vnd.frogans.ltf"},
+ {".ddd", "application/vnd.fujixerox.ddd"},
+ {".xdw", "application/vnd.fujixerox.docuworks"},
+ {".xbd", "application/vnd.fujixerox.docuworks.binder"},
+ {".oas", "application/vnd.fujitsu.oasys"},
+ {".oa2", "application/vnd.fujitsu.oasys2"},
+ {".oa3", "application/vnd.fujitsu.oasys3"},
+ {".fg5", "application/vnd.fujitsu.oasysgp"},
+ {".bh2", "application/vnd.fujitsu.oasysprs"},
+ {".spl", "application/x-futuresplash"},
+ {".fzs", "application/vnd.fuzzysheet"},
+ {".g3", "image/g3fax"},
+ {".gmx", "application/vnd.gmx"},
+ {".gtw", "model/vnd.gtw"},
+ {".txd", "application/vnd.genomatix.tuxedo"},
+ {".ggb", "application/vnd.geogebra.file"},
+ {".ggt", "application/vnd.geogebra.tool"},
+ {".gdl", "model/vnd.gdl"},
+ {".gex", "application/vnd.geometry-explorer"},
+ {".gxt", "application/vnd.geonext"},
+ {".g2w", "application/vnd.geoplan"},
+ {".g3w", "application/vnd.geospace"},
+ {".gsf", "application/x-font-ghostscript"},
+ {".bdf", "application/x-font-bdf"},
+ {".gtar", "application/x-gtar"},
+ {".texinfo", "application/x-texinfo"},
+ {".gnumeric", "application/x-gnumeric"},
+ {".kml", "application/vnd.google-earth.kml+xml"},
+ {".kmz", "application/vnd.google-earth.kmz"},
+ {".gqf", "application/vnd.grafeq"},
+ {".gif", "image/gif"},
+ {".gv", "text/vnd.graphviz"},
+ {".gac", "application/vnd.groove-account"},
+ {".ghf", "application/vnd.groove-help"},
+ {".gim", "application/vnd.groove-identity-message"},
+ {".grv", "application/vnd.groove-injector"},
+ {".gtm", "application/vnd.groove-tool-message"},
+ {".tpl", "application/vnd.groove-tool-template"},
+ {".vcg", "application/vnd.groove-vcard"},
+ {".h261", "video/h261"},
+ {".h263", "video/h263"},
+ {".h264", "video/h264"},
+ {".hpid", "application/vnd.hp-hpid"},
+ {".hps", "application/vnd.hp-hps"},
+ {".hdf", "application/x-hdf"},
+ {".rip", "audio/vnd.rip"},
+ {".hbci", "application/vnd.hbci"},
+ {".jlt", "application/vnd.hp-jlyt"},
+ {".pcl", "application/vnd.hp-pcl"},
+ {".hpgl", "application/vnd.hp-hpgl"},
+ {".hvs", "application/vnd.yamaha.hv-script"},
+ {".hvd", "application/vnd.yamaha.hv-dic"},
+ {".hvp", "application/vnd.yamaha.hv-voice"},
+ {".sfd-hdstx", "application/vnd.hydrostatix.sof-data"},
+ {".stk", "application/hyperstudio"},
+ {".hal", "application/vnd.hal+xml"},
+ {".htm", "text/html; charset=utf-8"},
+ {".html", "text/html; charset=utf-8"},
+ {".irm", "application/vnd.ibm.rights-management"},
+ {".sc", "application/vnd.ibm.secure-container"},
+ {".ics", "text/calendar"},
+ {".icc", "application/vnd.iccprofile"},
+ {".ico", "image/x-icon"},
+ {".igl", "application/vnd.igloader"},
+ {".ief", "image/ief"},
+ {".ivp", "application/vnd.immervision-ivp"},
+ {".ivu", "application/vnd.immervision-ivu"},
+ {".rif", "application/reginfo+xml"},
+ {".3dml", "text/vnd.in3d.3dml"},
+ {".spot", "text/vnd.in3d.spot"},
+ {".igs", "model/iges"},
+ {".i2g", "application/vnd.intergeo"},
+ {".cdy", "application/vnd.cinderella"},
+ {".xpw", "application/vnd.intercon.formnet"},
+ {".fcs", "application/vnd.isac.fcs"},
+ {".ipfix", "application/ipfix"},
+ {".cer", "application/pkix-cert"},
+ {".pki", "application/pkixcmp"},
+ {".crl", "application/pkix-crl"},
+ {".pkipath", "application/pkix-pkipath"},
+ {".igm", "application/vnd.insors.igm"},
+ {".rcprofile", "application/vnd.ipunplugged.rcprofile"},
+ {".irp", "application/vnd.irepository.package+xml"},
+ {".jad", "text/vnd.sun.j2me.app-descriptor"},
+ {".jar", "application/java-archive"},
+ {".class", "application/java-vm"},
+ {".jnlp", "application/x-java-jnlp-file"},
+ {".ser", "application/java-serialized-object"},
+ {".java", "text/x-java-source"},
+ {".js", "application/javascript"},
+ {".json", "application/json"},
+ {".joda", "application/vnd.joost.joda-archive"},
+ {".jpm", "video/jpm"},
+ {".jpg", "image/jpeg"},
+ {".jpeg", "image/jpeg"},
+ {".pjpeg", "image/pjpeg"},
+ {".jpgv", "video/jpeg"},
+ {".ktz", "application/vnd.kahootz"},
+ {".mmd", "application/vnd.chipnuts.karaoke-mmd"},
+ {".karbon", "application/vnd.kde.karbon"},
+ {".chrt", "application/vnd.kde.kchart"},
+ {".kfo", "application/vnd.kde.kformula"},
+ {".flw", "application/vnd.kde.kivio"},
+ {".kon", "application/vnd.kde.kontour"},
+ {".kpr", "application/vnd.kde.kpresenter"},
+ {".ksp", "application/vnd.kde.kspread"},
+ {".kwd", "application/vnd.kde.kword"},
+ {".htke", "application/vnd.kenameaapp"},
+ {".kia", "application/vnd.kidspiration"},
+ {".kne", "application/vnd.kinar"},
+ {".sse", "application/vnd.kodak-descriptor"},
+ {".lasxml", "application/vnd.las.las+xml"},
+ {".latex", "application/x-latex"},
+ {".lbd", "application/vnd.llamagraphics.life-balance.desktop"},
+ {".lbe", "application/vnd.llamagraphics.life-balance.exchange+xml"},
+ {".jam", "application/vnd.jam"},
+ {"0.123", "application/vnd.lotus-1-2-3"},
+ {".apr", "application/vnd.lotus-approach"},
+ {".pre", "application/vnd.lotus-freelance"},
+ {".nsf", "application/vnd.lotus-notes"},
+ {".org", "application/vnd.lotus-organizer"},
+ {".scm", "application/vnd.lotus-screencam"},
+ {".lwp", "application/vnd.lotus-wordpro"},
+ {".lvp", "audio/vnd.lucent.voice"},
+ {".m3u", "audio/x-mpegurl"},
+ {".m4v", "video/x-m4v"},
+ {".hqx", "application/mac-binhex40"},
+ {".portpkg", "application/vnd.macports.portpkg"},
+ {".mgp", "application/vnd.osgeo.mapguide.package"},
+ {".mrc", "application/marc"},
+ {".mrcx", "application/marcxml+xml"},
+ {".mxf", "application/mxf"},
+ {".nbp", "application/vnd.wolfram.player"},
+ {".ma", "application/mathematica"},
+ {".mathml", "application/mathml+xml"},
+ {".mbox", "application/mbox"},
+ {".mc1", "application/vnd.medcalcdata"},
+ {".mscml", "application/mediaservercontrol+xml"},
+ {".cdkey", "application/vnd.mediastation.cdkey"},
+ {".mwf", "application/vnd.mfer"},
+ {".mfm", "application/vnd.mfmp"},
+ {".msh", "model/mesh"},
+ {".mads", "application/mads+xml"},
+ {".mets", "application/mets+xml"},
+ {".mods", "application/mods+xml"},
+ {".meta4", "application/metalink4+xml"},
+ {".mcd", "application/vnd.mcd"},
+ {".flo", "application/vnd.micrografx.flo"},
+ {".igx", "application/vnd.micrografx.igx"},
+ {".es3", "application/vnd.eszigno3+xml"},
+ {".mdb", "application/x-msaccess"},
+ {".asf", "video/x-ms-asf"},
+ {".exe", "application/x-msdownload"},
+ {".cil", "application/vnd.ms-artgalry"},
+ {".cab", "application/vnd.ms-cab-compressed"},
+ {".ims", "application/vnd.ms-ims"},
+ {".application", "application/x-ms-application"},
+ {".clp", "application/x-msclip"},
+ {".mdi", "image/vnd.ms-modi"},
+ {".eot", "application/vnd.ms-fontobject"},
+ {".xls", "application/vnd.ms-excel"},
+ {".xlam", "application/vnd.ms-excel.addin.macroenabled.12"},
+ {".xlsb", "application/vnd.ms-excel.sheet.binary.macroenabled.12"},
+ {".xltm", "application/vnd.ms-excel.template.macroenabled.12"},
+ {".xlsm", "application/vnd.ms-excel.sheet.macroenabled.12"},
+ {".chm", "application/vnd.ms-htmlhelp"},
+ {".crd", "application/x-mscardfile"},
+ {".lrm", "application/vnd.ms-lrm"},
+ {".mvb", "application/x-msmediaview"},
+ {".mny", "application/x-msmoney"},
+ {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
+ {".sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"},
+ {".ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"},
+ {".potx", "application/vnd.openxmlformats-officedocument.presentationml.template"},
+ {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
+ {".xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"},
+ {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
+ {".dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"},
+ {".obd", "application/x-msbinder"},
+ {".thmx", "application/vnd.ms-officetheme"},
+ {".onetoc", "application/onenote"},
+ {".pya", "audio/vnd.ms-playready.media.pya"},
+ {".pyv", "video/vnd.ms-playready.media.pyv"},
+ {".ppt", "application/vnd.ms-powerpoint"},
+ {".ppam", "application/vnd.ms-powerpoint.addin.macroenabled.12"},
+ {".sldm", "application/vnd.ms-powerpoint.slide.macroenabled.12"},
+ {".pptm", "application/vnd.ms-powerpoint.presentation.macroenabled.12"},
+ {".ppsm", "application/vnd.ms-powerpoint.slideshow.macroenabled.12"},
+ {".potm", "application/vnd.ms-powerpoint.template.macroenabled.12"},
+ {".mpp", "application/vnd.ms-project"},
+ {".pub", "application/x-mspublisher"},
+ {".scd", "application/x-msschedule"},
+ {".xap", "application/x-silverlight-app"},
+ {".stl", "application/vnd.ms-pki.stl"},
+ {".cat", "application/vnd.ms-pki.seccat"},
+ {".vsd", "application/vnd.visio"},
+ {".vsdx", "application/vnd.visio2013"},
+ {".wm", "video/x-ms-wm"},
+ {".wma", "audio/x-ms-wma"},
+ {".wax", "audio/x-ms-wax"},
+ {".wmx", "video/x-ms-wmx"},
+ {".wmd", "application/x-ms-wmd"},
+ {".wpl", "application/vnd.ms-wpl"},
+ {".wmz", "application/x-ms-wmz"},
+ {".wmv", "video/x-ms-wmv"},
+ {".wvx", "video/x-ms-wvx"},
+ {".wmf", "application/x-msmetafile"},
+ {".trm", "application/x-msterminal"},
+ {".doc", "application/msword"},
+ {".docm", "application/vnd.ms-word.document.macroenabled.12"},
+ {".dotm", "application/vnd.ms-word.template.macroenabled.12"},
+ {".wri", "application/x-mswrite"},
+ {".wps", "application/vnd.ms-works"},
+ {".xbap", "application/x-ms-xbap"},
+ {".xps", "application/vnd.ms-xpsdocument"},
+ {".mid", "audio/midi"},
+ {".mpy", "application/vnd.ibm.minipay"},
+ {".afp", "application/vnd.ibm.modcap"},
+ {".rms", "application/vnd.jcp.javame.midlet-rms"},
+ {".tmo", "application/vnd.tmobile-livetv"},
+ {".prc", "application/x-mobipocket-ebook"},
+ {".mbk", "application/vnd.mobius.mbk"},
+ {".dis", "application/vnd.mobius.dis"},
+ {".plc", "application/vnd.mobius.plc"},
+ {".mqy", "application/vnd.mobius.mqy"},
+ {".msl", "application/vnd.mobius.msl"},
+ {".txf", "application/vnd.mobius.txf"},
+ {".daf", "application/vnd.mobius.daf"},
+ {".fly", "text/vnd.fly"},
+ {".mpc", "application/vnd.mophun.certificate"},
+ {".mpn", "application/vnd.mophun.application"},
+ {".mj2", "video/mj2"},
+ {".mpga", "audio/mpeg"},
+ {".mxu", "video/vnd.mpegurl"},
+ {".mpeg", "video/mpeg"},
+ {".m21", "application/mp21"},
+ {".mp4a", "audio/mp4"},
+ {".mp4", "video/mp4"},
+ {".mp4", "application/mp4"},
+ {".m3u8", "application/vnd.apple.mpegurl"},
+ {".mus", "application/vnd.musician"},
+ {".msty", "application/vnd.muvee.style"},
+ {".mxml", "application/xv+xml"},
+ {".ngdat", "application/vnd.nokia.n-gage.data"},
+ {".n-gage", "application/vnd.nokia.n-gage.symbian.install"},
+ {".ncx", "application/x-dtbncx+xml"},
+ {".nc", "application/x-netcdf"},
+ {".nlu", "application/vnd.neurolanguage.nlu"},
+ {".dna", "application/vnd.dna"},
+ {".nnd", "application/vnd.noblenet-directory"},
+ {".nns", "application/vnd.noblenet-sealer"},
+ {".nnw", "application/vnd.noblenet-web"},
+ {".rpst", "application/vnd.nokia.radio-preset"},
+ {".rpss", "application/vnd.nokia.radio-presets"},
+ {".n3", "text/n3"},
+ {".edm", "application/vnd.novadigm.edm"},
+ {".edx", "application/vnd.novadigm.edx"},
+ {".ext", "application/vnd.novadigm.ext"},
+ {".gph", "application/vnd.flographit"},
+ {".ecelp4800", "audio/vnd.nuera.ecelp4800"},
+ {".ecelp7470", "audio/vnd.nuera.ecelp7470"},
+ {".ecelp9600", "audio/vnd.nuera.ecelp9600"},
+ {".oda", "application/oda"},
+ {".ogx", "application/ogg"},
+ {".oga", "audio/ogg"},
+ {".ogv", "video/ogg"},
+ {".dd2", "application/vnd.oma.dd2+xml"},
+ {".oth", "application/vnd.oasis.opendocument.text-web"},
+ {".opf", "application/oebps-package+xml"},
+ {".qbo", "application/vnd.intu.qbo"},
+ {".oxt", "application/vnd.openofficeorg.extension"},
+ {".osf", "application/vnd.yamaha.openscoreformat"},
+ {".weba", "audio/webm"},
+ {".webm", "video/webm"},
+ {".odc", "application/vnd.oasis.opendocument.chart"},
+ {".otc", "application/vnd.oasis.opendocument.chart-template"},
+ {".odb", "application/vnd.oasis.opendocument.database"},
+ {".odf", "application/vnd.oasis.opendocument.formula"},
+ {".odft", "application/vnd.oasis.opendocument.formula-template"},
+ {".odg", "application/vnd.oasis.opendocument.graphics"},
+ {".otg", "application/vnd.oasis.opendocument.graphics-template"},
+ {".odi", "application/vnd.oasis.opendocument.image"},
+ {".oti", "application/vnd.oasis.opendocument.image-template"},
+ {".odp", "application/vnd.oasis.opendocument.presentation"},
+ {".otp", "application/vnd.oasis.opendocument.presentation-template"},
+ {".ods", "application/vnd.oasis.opendocument.spreadsheet"},
+ {".ots", "application/vnd.oasis.opendocument.spreadsheet-template"},
+ {".odt", "application/vnd.oasis.opendocument.text"},
+ {".odm", "application/vnd.oasis.opendocument.text-master"},
+ {".ott", "application/vnd.oasis.opendocument.text-template"},
+ {".ktx", "image/ktx"},
+ {".sxc", "application/vnd.sun.xml.calc"},
+ {".stc", "application/vnd.sun.xml.calc.template"},
+ {".sxd", "application/vnd.sun.xml.draw"},
+ {".std", "application/vnd.sun.xml.draw.template"},
+ {".sxi", "application/vnd.sun.xml.impress"},
+ {".sti", "application/vnd.sun.xml.impress.template"},
+ {".sxm", "application/vnd.sun.xml.math"},
+ {".sxw", "application/vnd.sun.xml.writer"},
+ {".sxg", "application/vnd.sun.xml.writer.global"},
+ {".stw", "application/vnd.sun.xml.writer.template"},
+ {".otf", "application/x-font-otf"},
+ {".osfpvg", "application/vnd.yamaha.openscoreformat.osfpvg+xml"},
+ {".dp", "application/vnd.osgi.dp"},
+ {".pdb", "application/vnd.palm"},
+ {".p", "text/x-pascal"},
+ {".paw", "application/vnd.pawaafile"},
+ {".pclxl", "application/vnd.hp-pclxl"},
+ {".efif", "application/vnd.picsel"},
+ {".pcx", "image/x-pcx"},
+ {".psd", "image/vnd.adobe.photoshop"},
+ {".prf", "application/pics-rules"},
+ {".pic", "image/x-pict"},
+ {".chat", "application/x-chat"},
+ {".p10", "application/pkcs10"},
+ {".p12", "application/x-pkcs12"},
+ {".p7m", "application/pkcs7-mime"},
+ {".p7s", "application/pkcs7-signature"},
+ {".p7r", "application/x-pkcs7-certreqresp"},
+ {".p7b", "application/x-pkcs7-certificates"},
+ {".p8", "application/pkcs8"},
+ {".plf", "application/vnd.pocketlearn"},
+ {".pnm", "image/x-portable-anymap"},
+ {".pbm", "image/x-portable-bitmap"},
+ {".pcf", "application/x-font-pcf"},
+ {".pfr", "application/font-tdpfr"},
+ {".pgn", "application/x-chess-pgn"},
+ {".pgm", "image/x-portable-graymap"},
+ {".png", "image/png"},
+ {".png", "image/x-citrix-png"},
+ {".png", "image/x-png"},
+ {".ppm", "image/x-portable-pixmap"},
+ {".pskcxml", "application/pskc+xml"},
+ {".pml", "application/vnd.ctc-posml"},
+ {".ai", "application/postscript"},
+ {".pfa", "application/x-font-type1"},
+ {".pbd", "application/vnd.powerbuilder6"},
+ {".pgp", "application/pgp-encrypted"},
+ {".pgp", "application/pgp-signature"},
+ {".box", "application/vnd.previewsystems.box"},
+ {".ptid", "application/vnd.pvi.ptid1"},
+ {".pls", "application/pls+xml"},
+ {".str", "application/vnd.pg.format"},
+ {".ei6", "application/vnd.pg.osasli"},
+ {".dsc", "text/prs.lines.tag"},
+ {".psf", "application/x-font-linux-psf"},
+ {".qps", "application/vnd.publishare-delta-tree"},
+ {".wg", "application/vnd.pmi.widget"},
+ {".qxd", "application/vnd.quark.quarkxpress"},
+ {".esf", "application/vnd.epson.esf"},
+ {".msf", "application/vnd.epson.msf"},
+ {".ssf", "application/vnd.epson.ssf"},
+ {".qam", "application/vnd.epson.quickanime"},
+ {".qfx", "application/vnd.intu.qfx"},
+ {".qt", "video/quicktime"},
+ {".rar", "application/x-rar-compressed"},
+ {".ram", "audio/x-pn-realaudio"},
+ {".rmp", "audio/x-pn-realaudio-plugin"},
+ {".rsd", "application/rsd+xml"},
+ {".rm", "application/vnd.rn-realmedia"},
+ {".bed", "application/vnd.realvnc.bed"},
+ {".mxl", "application/vnd.recordare.musicxml"},
+ {".musicxml", "application/vnd.recordare.musicxml+xml"},
+ {".rnc", "application/relax-ng-compact-syntax"},
+ {".rdz", "application/vnd.data-vision.rdz"},
+ {".rdf", "application/rdf+xml"},
+ {".rp9", "application/vnd.cloanto.rp9"},
+ {".jisp", "application/vnd.jisp"},
+ {".rtf", "application/rtf"},
+ {".rtx", "text/richtext"},
+ {".link66", "application/vnd.route66.link66+xml"},
+ {".rss", "application/rss+xml"},
+ {".shf", "application/shf+xml"},
+ {".st", "application/vnd.sailingtracker.track"},
+ {".svg", "image/svg+xml"},
+ {".sus", "application/vnd.sus-calendar"},
+ {".sru", "application/sru+xml"},
+ {".setpay", "application/set-payment-initiation"},
+ {".setreg", "application/set-registration-initiation"},
+ {".sema", "application/vnd.sema"},
+ {".semd", "application/vnd.semd"},
+ {".semf", "application/vnd.semf"},
+ {".see", "application/vnd.seemail"},
+ {".snf", "application/x-font-snf"},
+ {".spq", "application/scvp-vp-request"},
+ {".spp", "application/scvp-vp-response"},
+ {".scq", "application/scvp-cv-request"},
+ {".scs", "application/scvp-cv-response"},
+ {".sdp", "application/sdp"},
+ {".etx", "text/x-setext"},
+ {".movie", "video/x-sgi-movie"},
+ {".ifm", "application/vnd.shana.informed.formdata"},
+ {".itp", "application/vnd.shana.informed.formtemplate"},
+ {".iif", "application/vnd.shana.informed.interchange"},
+ {".ipk", "application/vnd.shana.informed.package"},
+ {".tfi", "application/thraud+xml"},
+ {".shar", "application/x-shar"},
+ {".rgb", "image/x-rgb"},
+ {".slt", "application/vnd.epson.salt"},
+ {".aso", "application/vnd.accpac.simply.aso"},
+ {".imp", "application/vnd.accpac.simply.imp"},
+ {".twd", "application/vnd.simtech-mindmapper"},
+ {".csp", "application/vnd.commonspace"},
+ {".saf", "application/vnd.yamaha.smaf-audio"},
+ {".mmf", "application/vnd.smaf"},
+ {".spf", "application/vnd.yamaha.smaf-phrase"},
+ {".teacher", "application/vnd.smart.teacher"},
+ {".svd", "application/vnd.svd"},
+ {".rq", "application/sparql-query"},
+ {".srx", "application/sparql-results+xml"},
+ {".gram", "application/srgs"},
+ {".grxml", "application/srgs+xml"},
+ {".ssml", "application/ssml+xml"},
+ {".skp", "application/vnd.koan"},
+ {".sgml", "text/sgml"},
+ {".sdc", "application/vnd.stardivision.calc"},
+ {".sda", "application/vnd.stardivision.draw"},
+ {".sdd", "application/vnd.stardivision.impress"},
+ {".smf", "application/vnd.stardivision.math"},
+ {".sdw", "application/vnd.stardivision.writer"},
+ {".sgl", "application/vnd.stardivision.writer-global"},
+ {".sm", "application/vnd.stepmania.stepchart"},
+ {".sit", "application/x-stuffit"},
+ {".sitx", "application/x-stuffitx"},
+ {".sdkm", "application/vnd.solent.sdkm+xml"},
+ {".xo", "application/vnd.olpc-sugar"},
+ {".au", "audio/basic"},
+ {".wqd", "application/vnd.wqd"},
+ {".sis", "application/vnd.symbian.install"},
+ {".smi", "application/smil+xml"},
+ {".xsm", "application/vnd.syncml+xml"},
+ {".bdm", "application/vnd.syncml.dm+wbxml"},
+ {".xdm", "application/vnd.syncml.dm+xml"},
+ {".sv4cpio", "application/x-sv4cpio"},
+ {".sv4crc", "application/x-sv4crc"},
+ {".sbml", "application/sbml+xml"},
+ {".tsv", "text/tab-separated-values"},
+ {".tiff", "image/tiff"},
+ {".tao", "application/vnd.tao.intent-module-archive"},
+ {".tar", "application/x-tar"},
+ {".tcl", "application/x-tcl"},
+ {".tex", "application/x-tex"},
+ {".tfm", "application/x-tex-tfm"},
+ {".tei", "application/tei+xml"},
+ {".txt", "text/plain; charset=utf-8"},
+ {".md", "text/markdown; charset=utf-8"},
+ {".dxp", "application/vnd.spotfire.dxp"},
+ {".sfs", "application/vnd.spotfire.sfs"},
+ {".tsd", "application/timestamped-data"},
+ {".tpt", "application/vnd.trid.tpt"},
+ {".mxs", "application/vnd.triscape.mxs"},
+ {".t", "text/troff"},
+ {".tra", "application/vnd.trueapp"},
+ {".ttf", "application/x-font-ttf"},
+ {".ttl", "text/turtle"},
+ {".umj", "application/vnd.umajin"},
+ {".uoml", "application/vnd.uoml+xml"},
+ {".unityweb", "application/vnd.unity"},
+ {".ufd", "application/vnd.ufdl"},
+ {".uri", "text/uri-list"},
+ {".utz", "application/vnd.uiq.theme"},
+ {".ustar", "application/x-ustar"},
+ {".uu", "text/x-uuencode"},
+ {".vcs", "text/x-vcalendar"},
+ {".vcf", "text/x-vcard"},
+ {".vcd", "application/x-cdlink"},
+ {".vsf", "application/vnd.vsf"},
+ {".wrl", "model/vrml"},
+ {".vcx", "application/vnd.vcx"},
+ {".mts", "model/vnd.mts"},
+ {".vtu", "model/vnd.vtu"},
+ {".vis", "application/vnd.visionary"},
+ {".viv", "video/vnd.vivo"},
+ {".ccxml", "application/ccxml+xml"},
+ {".vxml", "application/voicexml+xml"},
+ {".src", "application/x-wais-source"},
+ {".wbxml", "application/vnd.wap.wbxml"},
+ {".wbmp", "image/vnd.wap.wbmp"},
+ {".wav", "audio/x-wav"},
+ {".davmount", "application/davmount+xml"},
+ {".woff", "application/x-font-woff"},
+ {".wspolicy", "application/wspolicy+xml"},
+ {".webp", "image/webp"},
+ {".wtb", "application/vnd.webturbo"},
+ {".wgt", "application/widget"},
+ {".hlp", "application/winhlp"},
+ {".wml", "text/vnd.wap.wml"},
+ {".wmls", "text/vnd.wap.wmlscript"},
+ {".wmlsc", "application/vnd.wap.wmlscriptc"},
+ {".wpd", "application/vnd.wordperfect"},
+ {".stf", "application/vnd.wt.stf"},
+ {".wsdl", "application/wsdl+xml"},
+ {".xbm", "image/x-xbitmap"},
+ {".xpm", "image/x-xpixmap"},
+ {".xwd", "image/x-xwindowdump"},
+ {".der", "application/x-x509-ca-cert"},
+ {".fig", "application/x-xfig"},
+ {".xhtml", "application/xhtml+xml"},
+ {".xml", "application/xml"},
+ {".xdf", "application/xcap-diff+xml"},
+ {".xenc", "application/xenc+xml"},
+ {".xer", "application/patch-ops-error+xml"},
+ {".rl", "application/resource-lists+xml"},
+ {".rs", "application/rls-services+xml"},
+ {".rld", "application/resource-lists-diff+xml"},
+ {".xslt", "application/xslt+xml"},
+ {".xop", "application/xop+xml"},
+ {".xpi", "application/x-xpinstall"},
+ {".xspf", "application/xspf+xml"},
+ {".xul", "application/vnd.mozilla.xul+xml"},
+ {".xyz", "chemical/x-xyz"},
+ {".yaml", "text/yaml"},
+ {".yang", "application/yang"},
+ {".yin", "application/yin+xml"},
+ {".zir", "application/vnd.zul"},
+ {".zip", "application/zip"},
+ {".zmm", "application/vnd.handheld-entertainment+xml"},
+ {".zaz", "application/vnd.zzazz.deck+xml"},
+};
+
+// Get HTTP MIME type from filename
+char *GetMimeTypeFromFileName(char *filename)
+{
+ UINT i;
+ UINT num = sizeof(http_mime_types) / sizeof(HTTP_MIME_TYPE);
+ if (filename == NULL)
+ {
+ return NULL;
+ }
+
+ for (i = 0;i < num;i++)
+ {
+ HTTP_MIME_TYPE *a = &http_mime_types[i];
+
+ if (EndWith(filename, a->Extension))
+ {
+ return a->MimeType;
+ }
+ }
+
+ return NULL;
+}
+
// Download and save intermediate certificates if necessary
bool DownloadAndSaveIntermediateCertificatesIfNecessary(X *x)
{
@@ -1260,6 +1980,7 @@ bool ServerAccept(CONNECTION *c)
UINT authtype;
POLICY *policy;
UINT assigned_vlan_id = 0;
+ UCHAR assigned_ipc_mac_address[6];
HUB *hub;
SESSION *s = NULL;
UINT64 user_expires = 0;
@@ -1268,12 +1989,17 @@ bool ServerAccept(CONNECTION *c)
bool half_connection;
UINT adjust_mss;
bool use_udp_acceleration_client;
+ UINT client_udp_acceleration_max_version = 1;
+ UINT udp_acceleration_version = 1;
+ UINT client_rudp_bulk_max_version = 1;
+ UINT rudp_bulk_version = 1;
bool support_hmac_on_udp_acceleration_client = false;
bool support_udp_accel_fast_disconnect_detect;
bool use_hmac_on_udp_acceleration = false;
bool supress_return_pack_error = false;
IP udp_acceleration_client_ip;
- UCHAR udp_acceleration_client_key[UDP_ACCELERATION_COMMON_KEY_SIZE];
+ UCHAR udp_acceleration_client_key[UDP_ACCELERATION_COMMON_KEY_SIZE_V1];
+ UCHAR udp_acceleration_client_key_v2[UDP_ACCELERATION_COMMON_KEY_SIZE_V2];
UINT udp_acceleration_client_port;
bool use_fast_rc4;
bool admin_mode = false;
@@ -1329,11 +2055,14 @@ bool ServerAccept(CONNECTION *c)
Zero(ctoken_hash_str, sizeof(ctoken_hash_str));
+ Zero(assigned_ipc_mac_address, sizeof(assigned_ipc_mac_address));
+
Zero(mschap_v2_server_response_20, sizeof(mschap_v2_server_response_20));
Zero(&udp_acceleration_client_ip, sizeof(udp_acceleration_client_ip));
udp_acceleration_client_port = 0;
Zero(udp_acceleration_client_key, sizeof(udp_acceleration_client_key));
+ Zero(udp_acceleration_client_key_v2, sizeof(udp_acceleration_client_key_v2));
Zero(&winver, sizeof(winver));
@@ -1376,6 +2105,11 @@ bool ServerAccept(CONNECTION *c)
error_detail_2 = NULL;
if (ServerDownloadSignature(c, &error_detail_2) == false)
{
+ if (c->Type == CONNECTION_TYPE_ADMIN_RPC)
+ {
+ c->Err = ERR_NO_ERROR;
+ }
+
if (error_detail_2 == NULL)
{
error_detail = "ServerDownloadSignature";
@@ -1639,6 +2373,16 @@ bool ServerAccept(CONNECTION *c)
client_id = PackGetInt(p, "client_id");
adjust_mss = PackGetInt(p, "adjust_mss");
use_udp_acceleration_client = PackGetBool(p, "use_udp_acceleration");
+ client_udp_acceleration_max_version = PackGetInt(p, "udp_acceleration_max_version");
+ if (client_udp_acceleration_max_version == 0)
+ {
+ client_udp_acceleration_max_version = 1;
+ }
+ client_rudp_bulk_max_version = PackGetInt(p, "rudp_bulk_max_version");
+ if (client_rudp_bulk_max_version == 0)
+ {
+ client_rudp_bulk_max_version = 1;
+ }
support_hmac_on_udp_acceleration_client = PackGetBool(p, "support_hmac_on_udp_acceleration");
support_udp_accel_fast_disconnect_detect = PackGetBool(p, "support_udp_accel_fast_disconnect_detect");
support_bulk_on_rudp = PackGetBool(p, "support_bulk_on_rudp");
@@ -1659,6 +2403,7 @@ bool ServerAccept(CONNECTION *c)
PackGetStr(p, "inproc_postfix", c->InProcPrefix, sizeof(c->InProcPrefix));
Zero(tmp, sizeof(tmp));
PackGetStr(p, "inproc_cryptname", tmp, sizeof(tmp));
+ c->InProcLayer = PackGetInt(p, "inproc_layer");
if (c->FirstSock != NULL)
{
@@ -1666,6 +2411,10 @@ bool ServerAccept(CONNECTION *c)
{
Format(c->FirstSock->UnderlayProtocol, sizeof(c->FirstSock->UnderlayProtocol),
SOCK_UNDERLAY_INPROC_EX, c->InProcPrefix);
+
+ AddProtocolDetailsStr(c->FirstSock->UnderlayProtocol,
+ sizeof(c->FirstSock->UnderlayProtocol),
+ c->InProcPrefix);
}
}
@@ -1683,6 +2432,9 @@ bool ServerAccept(CONNECTION *c)
}
use_udp_acceleration_client = false;
+
+ Format(radius_login_opt.In_VpnProtocolState, sizeof(radius_login_opt.In_VpnProtocolState),
+ "L%u:%s", c->InProcLayer, c->InProcPrefix);
}
else
{
@@ -1696,12 +2448,15 @@ bool ServerAccept(CONNECTION *c)
{
c->CipherName = CopyStr(c->FirstSock->CipherName);
}
+
+ Format(radius_login_opt.In_VpnProtocolState, sizeof(radius_login_opt.In_VpnProtocolState),
+ "L%u:%s", IPC_LAYER_2, "SEVPN");
}
if (support_bulk_on_rudp && c->FirstSock != NULL && c->FirstSock->IsRUDPSocket &&
c->FirstSock->BulkRecvKey != NULL && c->FirstSock->BulkSendKey != NULL)
{
- // RAllow UDP bulk transfer if the client side supports
+ // Allow UDP bulk transfer if the client side supports
// in the case of using R-UDP Socket
enable_bulk_on_rudp = true;
@@ -1716,9 +2471,11 @@ bool ServerAccept(CONNECTION *c)
if (use_udp_acceleration_client)
{
+ PackGetData2(p, "udp_acceleration_client_key", udp_acceleration_client_key, UDP_ACCELERATION_COMMON_KEY_SIZE_V1);
+ PackGetData2(p, "udp_acceleration_client_key_v2", udp_acceleration_client_key_v2, UDP_ACCELERATION_COMMON_KEY_SIZE_V2);
+
// Get the parameters for the UDP acceleration function
- if (PackGetIp(p, "udp_acceleration_client_ip", &udp_acceleration_client_ip) == false ||
- PackGetData2(p, "udp_acceleration_client_key", udp_acceleration_client_key, UDP_ACCELERATION_COMMON_KEY_SIZE) == false)
+ if (PackGetIp(p, "udp_acceleration_client_ip", &udp_acceleration_client_ip) == false)
{
use_udp_acceleration_client = false;
}
@@ -1786,6 +2543,9 @@ bool ServerAccept(CONNECTION *c)
case AUTHTYPE_TICKET:
authtype_str = _UU("LH_AUTH_TICKET");
break;
+ case AUTHTYPE_OPENVPN_CERT:
+ authtype_str = _UU("LH_AUTH_OPENVPN_CERT");
+ break;
}
IPToStr(ip1, sizeof(ip1), &c->FirstSock->RemoteIP);
IPToStr(ip2, sizeof(ip2), &c->FirstSock->LocalIP);
@@ -2119,6 +2879,50 @@ bool ServerAccept(CONNECTION *c)
}
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:
// Unknown authentication method
Unlock(hub->lock);
@@ -2206,6 +3010,12 @@ bool ServerAccept(CONNECTION *c)
}
}
+ // Check the assigned MAC Address
+ if (radius_login_opt.Out_IsRadiusLogin)
+ {
+ Copy(assigned_ipc_mac_address, radius_login_opt.Out_VirtualMacAddress, 6);
+ }
+
if (StrCmpi(username, ADMINISTRATOR_USERNAME) != 0)
{
// Get the policy
@@ -2892,15 +3702,16 @@ bool ServerAccept(CONNECTION *c)
// VLAN ID
if (assigned_vlan_id != 0)
{
- if (policy->VLanId == 0)
- {
- policy->VLanId = assigned_vlan_id;
- }
+ if (policy->VLanId == 0)
+ {
+ policy->VLanId = assigned_vlan_id;
}
+ }
// Create a Session
StrLower(username);
- s = NewServerSessionEx(c->Cedar, c, hub, username, policy, c->IsInProc);
+ s = NewServerSessionEx(c->Cedar, c, hub, username, policy, c->IsInProc,
+ (c->IsInProc && IsZero(assigned_ipc_mac_address, 6) == false) ? assigned_ipc_mac_address : NULL);
s->EnableUdpRecovery = enable_udp_recovery;
s->LocalHostSession = local_host_session;
@@ -2914,6 +3725,8 @@ bool ServerAccept(CONNECTION *c)
s->IsRUDPSession = true;
s->RUdpMss = c->FirstSock->RUDP_OptimizedMss;
Debug("Optimized MSS Value for R-UDP: %u\n", s->RUdpMss);
+ AddProtocolDetailsKeyValueInt(s->ProtocolDetails, sizeof(s->ProtocolDetails),
+ "RUDP_MSS", s->RUdpMss);
}
if (enable_bulk_on_rudp)
@@ -2927,6 +3740,8 @@ bool ServerAccept(CONNECTION *c)
StrCpy(s->UnderlayProtocol, sizeof(s->UnderlayProtocol), c->FirstSock->UnderlayProtocol);
+ AddProtocolDetailsStr(s->ProtocolDetails, sizeof(s->ProtocolDetails), c->FirstSock->ProtocolDetails);
+
if (server != NULL)
{
s->NoSendSignature = server->NoSendSignature;
@@ -2955,6 +3770,28 @@ bool ServerAccept(CONNECTION *c)
s->UseUdpAcceleration = true;
s->UdpAccelFastDisconnectDetect = support_udp_accel_fast_disconnect_detect;
+
+ // TODO: determine UDP Accel version
+ udp_acceleration_version = 1;
+ if (client_udp_acceleration_max_version >= 2)
+ {
+ udp_acceleration_version = 2;
+ }
+ }
+
+ // TODO: determine RUDP Bulk version
+ if (client_rudp_bulk_max_version >= 2)
+ {
+ rudp_bulk_version = 2;
+ }
+
+ s->BulkOnRUDPVersion = rudp_bulk_version;
+
+ if (s->EnableBulkOnRUDP)
+ {
+ AddProtocolDetailsKeyValueInt(s->ProtocolDetails, sizeof(s->ProtocolDetails),
+ "RUDP_Bulk_Ver",
+ s->BulkOnRUDPVersion);
}
if (hub->Option != NULL && hub->Option->DisableUdpAcceleration)
@@ -2978,6 +3815,7 @@ bool ServerAccept(CONNECTION *c)
Debug("UseUdpAcceleration = %u\n", s->UseUdpAcceleration);
Debug("UseHMacOnUdpAcceleration = %u\n", s->UseHMacOnUdpAcceleration);
+ Debug("UdpAccelerationVersion = %u\n", s->UdpAccelerationVersion);
if (s->UseUdpAcceleration)
{
@@ -2993,7 +3831,11 @@ bool ServerAccept(CONNECTION *c)
}
else
{
- if (UdpAccelInitServer(s->UdpAccel, udp_acceleration_client_key, &udp_acceleration_client_ip, udp_acceleration_client_port,
+ s->UdpAccel->Version = udp_acceleration_version;
+
+ if (UdpAccelInitServer(s->UdpAccel,
+ s->UdpAccel->Version == 2 ? udp_acceleration_client_key_v2 : udp_acceleration_client_key,
+ &udp_acceleration_client_ip, udp_acceleration_client_port,
&c->FirstSock->RemoteIP) == false)
{
Debug("UdpAccelInitServer Failed.\n");
@@ -3008,6 +3850,21 @@ bool ServerAccept(CONNECTION *c)
}
s->UdpAccel->UseHMac = s->UseHMacOnUdpAcceleration;
+
+ AddProtocolDetailsKeyValueInt(s->ProtocolDetails, sizeof(s->ProtocolDetails),
+ "UDPAccel_Ver",
+ s->UdpAccel->Version);
+
+ if (s->UdpAccel->Version >= 2)
+ {
+ AddProtocolDetailsStr(s->ProtocolDetails, sizeof(s->ProtocolDetails),
+ Aead_ChaCha20Poly1305_Ietf_IsOpenSSL() ?
+ "ChachaPoly_OpenSSL" : "ChachaPoly_Self");
+ }
+
+ AddProtocolDetailsKeyValueInt(s->ProtocolDetails, sizeof(s->ProtocolDetails),
+ "UDPAccel_MSS",
+ UdpAccelCalcMss(s->UdpAccel));
}
}
@@ -3018,6 +3875,8 @@ bool ServerAccept(CONNECTION *c)
if (s->AdjustMss != 0)
{
Debug("AdjustMSS: %u\n", s->AdjustMss);
+ AddProtocolDetailsKeyValueInt(s->ProtocolDetails, sizeof(s->ProtocolDetails),
+ "AdjustMSS", s->AdjustMss);
}
s->IsBridgeMode = (policy->NoBridge == false) || (policy->NoRouting == false);
@@ -3064,7 +3923,8 @@ bool ServerAccept(CONNECTION *c)
char ip[128];
IPToStr(ip, sizeof(ip), &c->FirstSock->RemoteIP);
HLog(hub, "LH_NEW_SESSION", c->Name, s->Name, ip, c->FirstSock->RemotePort,
- c->FirstSock->UnderlayProtocol);
+ c->FirstSock->UnderlayProtocol,
+ c->FirstSock->ProtocolDetails);
}
c->Session = s;
@@ -3088,7 +3948,7 @@ bool ServerAccept(CONNECTION *c)
s->QoS = qos;
s->NoReconnectToSession = no_reconnect_to_session;
- s->VLanId = policy->VLanId;
+ s->VLanId = policy->VLanId;
// User name
s->Username = CopyStr(username);
@@ -3489,6 +4349,30 @@ bool ServerAccept(CONNECTION *c)
// Add the socket of this connection to the connection list of the session (TCP)
sock = c->FirstSock;
+
+ if (sock->IsRUDPSocket && sock->BulkRecvKey != NULL && sock->BulkSendKey != NULL)
+ {
+ if (s->BulkRecvKeySize != 0 && s->BulkSendKeySize != 0)
+ {
+ // Restore R-UDP bulk send/recv keys for additional connections
+ Copy(sock->BulkRecvKey->Data, s->BulkRecvKey, s->BulkRecvKeySize);
+ sock->BulkRecvKey->Size = s->BulkRecvKeySize;
+ Copy(sock->BulkSendKey->Data, s->BulkSendKey, s->BulkSendKeySize);
+ sock->BulkSendKey->Size = s->BulkSendKeySize;
+
+ if (false)
+ {
+ char tmp1[128];
+ char tmp2[128];
+ BinToStr(tmp1, sizeof(tmp1), s->BulkRecvKey, s->BulkRecvKeySize);
+ BinToStr(tmp2, sizeof(tmp2), s->BulkSendKey, s->BulkSendKeySize);
+ Debug("Restore: s->BulkRecvKey->Size = %u, s->BulkSendKey->Size = %u\n",
+ s->BulkRecvKeySize, s->BulkSendKeySize);
+ Debug("Restore:\n%s\n%s\n\n", tmp1, tmp2);
+ }
+ }
+ }
+
ts = NewTcpSock(sock);
SetTimeout(sock, CONNECTING_TIMEOUT);
direction = TCP_BOTH;
@@ -4393,6 +5277,30 @@ bool ClientAdditionalConnect(CONNECTION *c, THREAD *t)
Debug("Additional Connect Succeed!\n");
+ if (s->IsRUDPSocket && s->BulkRecvKey != NULL && s->BulkSendKey != NULL)
+ {
+ // Restore R-UDP bulk send/recv keys for additional connections
+ if (c->Session->BulkRecvKeySize != 0 && c->Session->BulkSendKeySize != 0)
+ {
+ Copy(s->BulkRecvKey->Data, c->Session->BulkRecvKey, c->Session->BulkRecvKeySize);
+ s->BulkRecvKey->Size = c->Session->BulkRecvKeySize;
+
+ Copy(s->BulkSendKey->Data, c->Session->BulkSendKey, c->Session->BulkSendKeySize);
+ s->BulkSendKey->Size = c->Session->BulkSendKeySize;
+
+ if (false)
+ {
+ char tmp1[128];
+ char tmp2[128];
+ BinToStr(tmp1, sizeof(tmp1), s->BulkRecvKey->Data, s->BulkRecvKey->Size);
+ BinToStr(tmp2, sizeof(tmp2), s->BulkSendKey->Data, s->BulkSendKey->Size);
+ Debug("Restore: s->BulkRecvKey->Size = %u, s->BulkSendKey->Size = %u\n",
+ s->BulkRecvKey->Size, s->BulkSendKey->Size);
+ Debug("Restore:\n%s\n%s\n\n", tmp1, tmp2);
+ }
+ }
+ }
+
// Success the additional connection
// Add to the TcpSockList of the connection
ts = NewTcpSock(s);
@@ -5128,9 +6036,14 @@ REDIRECTED:
// Physical communication protocol
StrCpy(c->Session->UnderlayProtocol, sizeof(c->Session->UnderlayProtocol), s->UnderlayProtocol);
+ AddProtocolDetailsStr(c->Session->ProtocolDetails, sizeof(c->Session->ProtocolDetails), s->ProtocolDetails);
+
if (c->Session->IsAzureSession)
{
StrCpy(c->Session->UnderlayProtocol, sizeof(c->Session->UnderlayProtocol), SOCK_UNDERLAY_AZURE);
+
+ AddProtocolDetailsStr(c->Session->ProtocolDetails, sizeof(c->Session->ProtocolDetails),
+ "VPNAzure");
}
if (c->Protocol == CONNECTION_UDP)
@@ -5174,28 +6087,62 @@ REDIRECTED:
if (s != NULL && s->IsRUDPSocket && s->BulkRecvKey != NULL && s->BulkSendKey != NULL)
{
// Bulk transfer on R-UDP
+ sess->EnableHMacOnBulkOfRUDP = PackGetBool(p, "enable_hmac_on_bulk_of_rudp");
+ sess->BulkOnRUDPVersion = PackGetInt(p, "rudp_bulk_version");
+
if (PackGetBool(p, "enable_bulk_on_rudp"))
{
// Receive the key
- UCHAR key_send[SHA1_SIZE];
- UCHAR key_recv[SHA1_SIZE];
+ UCHAR key_send[RUDP_BULK_KEY_SIZE_MAX];
+ UCHAR key_recv[RUDP_BULK_KEY_SIZE_MAX];
+
+ UINT key_size = SHA1_SIZE;
+
+ if (sess->BulkOnRUDPVersion == 2)
+ {
+ key_size = RUDP_BULK_KEY_SIZE_V2;
+ }
- if (PackGetData2(p, "bulk_on_rudp_send_key", key_send, SHA1_SIZE) &&
- PackGetData2(p, "bulk_on_rudp_recv_key", key_recv, SHA1_SIZE))
+ if (PackGetData2(p, "bulk_on_rudp_send_key", key_send, key_size) &&
+ PackGetData2(p, "bulk_on_rudp_recv_key", key_recv, key_size))
{
sess->EnableBulkOnRUDP = true;
- Copy(s->BulkSendKey->Data, key_send, SHA1_SIZE);
- Copy(s->BulkRecvKey->Data, key_recv, SHA1_SIZE);
+ Copy(s->BulkSendKey->Data, key_send, key_size);
+ Copy(s->BulkRecvKey->Data, key_recv, key_size);
+
+ s->BulkSendKey->Size = key_size;
+ s->BulkRecvKey->Size = key_size;
+
+ // Backup R-UDP bulk send/recv keys for additional connections
+ Copy(sess->BulkSendKey, s->BulkSendKey->Data, s->BulkSendKey->Size);
+ sess->BulkSendKeySize = s->BulkSendKey->Size;
+
+ Copy(sess->BulkRecvKey, s->BulkRecvKey->Data, s->BulkRecvKey->Size);
+ sess->BulkRecvKeySize = s->BulkRecvKey->Size;
+
+ if (false)
+ {
+ char tmp1[128];
+ char tmp2[128];
+ BinToStr(tmp1, sizeof(tmp1), sess->BulkRecvKey, sess->BulkSendKeySize);
+ BinToStr(tmp2, sizeof(tmp2), sess->BulkSendKey, sess->BulkRecvKeySize);
+ Debug("Backup: sess->BulkRecvKeySize = %u, sess->BulkSendKeySize = %u\n",
+ sess->BulkRecvKeySize, sess->BulkSendKeySize);
+ Debug("Backup:\n%s\n%s\n\n", tmp1, tmp2);
+ }
+
+ AddProtocolDetailsKeyValueInt(sess->ProtocolDetails, sizeof(sess->ProtocolDetails),
+ "RUDP_Bulk_Ver",
+ sess->BulkOnRUDPVersion);
}
}
-
- sess->EnableHMacOnBulkOfRUDP = PackGetBool(p, "enable_hmac_on_bulk_of_rudp");
}
Debug("EnableBulkOnRUDP = %u\n", sess->EnableBulkOnRUDP);
Debug("EnableHMacOnBulkOfRUDP = %u\n", sess->EnableHMacOnBulkOfRUDP);
Debug("EnableUdpRecovery = %u\n", sess->EnableUdpRecovery);
+ Debug("BulkOnRUDPVersion = %u\n", sess->BulkOnRUDPVersion);
sess->UseUdpAcceleration = false;
sess->IsUsingUdpAcceleration = false;
@@ -5209,8 +6156,14 @@ REDIRECTED:
if (PackGetBool(p, "use_udp_acceleration"))
{
+ UINT udp_acceleration_version = PackGetInt(p, "udp_acceleration_version");
IP udp_acceleration_server_ip;
+ if (udp_acceleration_version == 0)
+ {
+ udp_acceleration_version = 1;
+ }
+
sess->UdpAccelFastDisconnectDetect = PackGetBool(p, "udp_accel_fast_disconnect_detect");
if (PackGetIp(p, "udp_acceleration_server_ip", &udp_acceleration_server_ip))
@@ -5224,46 +6177,71 @@ REDIRECTED:
if (udp_acceleration_server_port != 0)
{
- UCHAR udp_acceleration_server_key[UDP_ACCELERATION_COMMON_KEY_SIZE];
+ UCHAR udp_acceleration_server_key[UDP_ACCELERATION_COMMON_KEY_SIZE_V1];
+ UCHAR udp_acceleration_server_key_v2[UDP_ACCELERATION_COMMON_KEY_SIZE_V2];
+ UINT server_cookie = PackGetInt(p, "udp_acceleration_server_cookie");
+ UINT client_cookie = PackGetInt(p, "udp_acceleration_client_cookie");
+ bool encryption = PackGetBool(p, "udp_acceleration_use_encryption");
+
+ Zero(udp_acceleration_server_key, sizeof(udp_acceleration_server_key));
+ Zero(udp_acceleration_server_key_v2, sizeof(udp_acceleration_server_key_v2));
+
+ PackGetData2(p, "udp_acceleration_server_key", udp_acceleration_server_key, UDP_ACCELERATION_COMMON_KEY_SIZE_V1);
+ PackGetData2(p, "udp_acceleration_server_key_v2", udp_acceleration_server_key_v2, UDP_ACCELERATION_COMMON_KEY_SIZE_V2);
- if (PackGetData2(p, "udp_acceleration_server_key", udp_acceleration_server_key, UDP_ACCELERATION_COMMON_KEY_SIZE))
+ if (server_cookie != 0 && client_cookie != 0)
{
- UINT server_cookie = PackGetInt(p, "udp_acceleration_server_cookie");
- UINT client_cookie = PackGetInt(p, "udp_acceleration_client_cookie");
- bool encryption = PackGetBool(p, "udp_acceleration_use_encryption");
+ IP remote_ip;
+
+ Copy(&remote_ip, &s->RemoteIP, sizeof(IP));
+
+ if (IsZeroIp(&c->Session->AzureRealServerGlobalIp) == false)
+ {
+ Copy(&remote_ip, &c->Session->AzureRealServerGlobalIp, sizeof(IP));
+ }
- if (server_cookie != 0 && client_cookie != 0)
+ sess->UdpAccel->Version = 1;
+ if (udp_acceleration_version == 2)
{
- IP remote_ip;
+ sess->UdpAccel->Version = 2;
+ }
- Copy(&remote_ip, &s->RemoteIP, sizeof(IP));
+ if (UdpAccelInitClient(sess->UdpAccel,
+ sess->UdpAccel->Version == 2 ? udp_acceleration_server_key_v2 : udp_acceleration_server_key,
+ &udp_acceleration_server_ip, udp_acceleration_server_port,
+ server_cookie, client_cookie, &remote_ip) == false)
+ {
+ Debug("UdpAccelInitClient failed.\n");
+ }
+ else
+ {
+ sess->UseUdpAcceleration = true;
- if (IsZeroIp(&c->Session->AzureRealServerGlobalIp) == false)
- {
- Copy(&remote_ip, &c->Session->AzureRealServerGlobalIp, sizeof(IP));
- }
+ sess->UdpAccel->FastDetect = sess->UdpAccelFastDisconnectDetect;
- if (UdpAccelInitClient(sess->UdpAccel, udp_acceleration_server_key,
- &udp_acceleration_server_ip, udp_acceleration_server_port,
- server_cookie, client_cookie, &remote_ip) == false)
- {
- Debug("UdpAccelInitClient failed.\n");
- }
- else
- {
- sess->UseUdpAcceleration = true;
+ sess->UdpAccel->PlainTextMode = !encryption;
- sess->UdpAccel->FastDetect = sess->UdpAccelFastDisconnectDetect;
+ sess->UseHMacOnUdpAcceleration = PackGetBool(p, "use_hmac_on_udp_acceleration");
- sess->UdpAccel->PlainTextMode = !encryption;
+ if (sess->UseHMacOnUdpAcceleration)
+ {
+ sess->UdpAccel->UseHMac = true;
+ }
- sess->UseHMacOnUdpAcceleration = PackGetBool(p, "use_hmac_on_udp_acceleration");
+ AddProtocolDetailsKeyValueInt(sess->ProtocolDetails, sizeof(sess->ProtocolDetails),
+ "UDPAccel_Ver",
+ sess->UdpAccel->Version);
- if (sess->UseHMacOnUdpAcceleration)
- {
- sess->UdpAccel->UseHMac = true;
- }
+ if (sess->UdpAccel->Version >= 2)
+ {
+ AddProtocolDetailsStr(sess->ProtocolDetails, sizeof(sess->ProtocolDetails),
+ Aead_ChaCha20Poly1305_Ietf_IsOpenSSL() ?
+ "ChachaPoly_OpenSSL" : "ChachaPoly_Self");
}
+
+ AddProtocolDetailsKeyValueInt(sess->ProtocolDetails, sizeof(sess->ProtocolDetails),
+ "UDPAccel_MSS",
+ UdpAccelCalcMss(sess->UdpAccel));
}
}
}
@@ -5502,15 +6480,25 @@ PACK *PackWelcome(SESSION *s)
// Virtual HUB name
PackAddStr(p, "IpcHubName", s->Hub->Name);
+
+ // Shared Buffer
+ s->IpcSessionSharedBuffer = NewSharedBuffer(NULL, sizeof(IPC_SESSION_SHARED_BUFFER_DATA));
+ AddRef(s->IpcSessionSharedBuffer->Ref);
+
+ s->IpcSessionShared = s->IpcSessionSharedBuffer->Data;
+
+ PackAddInt64(p, "IpcSessionSharedBuffer", (UINT64)s->IpcSessionSharedBuffer);
}
if (s->UdpAccel != NULL)
{
// UDP acceleration function
PackAddBool(p, "use_udp_acceleration", true);
+ PackAddInt(p, "udp_acceleration_version", s->UdpAccel->Version);
PackAddIp(p, "udp_acceleration_server_ip", &s->UdpAccel->MyIp);
PackAddInt(p, "udp_acceleration_server_port", s->UdpAccel->MyPort);
- PackAddData(p, "udp_acceleration_server_key", s->UdpAccel->MyKey, UDP_ACCELERATION_COMMON_KEY_SIZE);
+ PackAddData(p, "udp_acceleration_server_key", s->UdpAccel->MyKey, UDP_ACCELERATION_COMMON_KEY_SIZE_V1);
+ PackAddData(p, "udp_acceleration_server_key_v2", s->UdpAccel->MyKey_V2, UDP_ACCELERATION_COMMON_KEY_SIZE_V2);
PackAddInt(p, "udp_acceleration_server_cookie", s->UdpAccel->MyCookie);
PackAddInt(p, "udp_acceleration_client_cookie", s->UdpAccel->YourCookie);
PackAddBool(p, "udp_acceleration_use_encryption", !s->UdpAccel->PlainTextMode);
@@ -5523,9 +6511,46 @@ PACK *PackWelcome(SESSION *s)
// Allow bulk transfer on R-UDP
PackAddBool(p, "enable_bulk_on_rudp", true);
PackAddBool(p, "enable_hmac_on_bulk_of_rudp", s->EnableHMacOnBulkOfRUDP);
+ PackAddInt(p, "rudp_bulk_version", s->BulkOnRUDPVersion);
+
+ if (s->BulkOnRUDPVersion == 2)
+ {
+ PackAddData(p, "bulk_on_rudp_send_key", s->Connection->FirstSock->BulkRecvKey->Data, RUDP_BULK_KEY_SIZE_V2);
+ s->Connection->FirstSock->BulkRecvKey->Size = RUDP_BULK_KEY_SIZE_V2;
+
+ PackAddData(p, "bulk_on_rudp_recv_key", s->Connection->FirstSock->BulkSendKey->Data, RUDP_BULK_KEY_SIZE_V2);
+ s->Connection->FirstSock->BulkSendKey->Size = RUDP_BULK_KEY_SIZE_V2;
+ }
+ else
+ {
+ PackAddData(p, "bulk_on_rudp_send_key", s->Connection->FirstSock->BulkRecvKey->Data, SHA1_SIZE);
+ s->Connection->FirstSock->BulkRecvKey->Size = SHA1_SIZE;
+
+ PackAddData(p, "bulk_on_rudp_recv_key", s->Connection->FirstSock->BulkSendKey->Data, SHA1_SIZE);
+ s->Connection->FirstSock->BulkSendKey->Size = SHA1_SIZE;
+ }
+
+ // Backup R-UDP bulk send/recv keys for additional connections
+ Copy(s->BulkSendKey, s->Connection->FirstSock->BulkSendKey->Data,
+ s->Connection->FirstSock->BulkSendKey->Size);
+
+ s->BulkSendKeySize = s->Connection->FirstSock->BulkSendKey->Size;
+
+ Copy(s->BulkRecvKey, s->Connection->FirstSock->BulkRecvKey->Data,
+ s->Connection->FirstSock->BulkRecvKey->Size);
- PackAddData(p, "bulk_on_rudp_send_key", s->Connection->FirstSock->BulkRecvKey->Data, SHA1_SIZE);
- PackAddData(p, "bulk_on_rudp_recv_key", s->Connection->FirstSock->BulkSendKey->Data, SHA1_SIZE);
+ s->BulkRecvKeySize = s->Connection->FirstSock->BulkRecvKey->Size;
+
+ if (false)
+ {
+ char tmp1[128];
+ char tmp2[128];
+ BinToStr(tmp1, sizeof(tmp1), s->BulkRecvKey, s->BulkSendKeySize);
+ BinToStr(tmp2, sizeof(tmp2), s->BulkSendKey, s->BulkRecvKeySize);
+ Debug("Backup: s->BulkRecvKeySize = %u, s->BulkSendKeySize = %u\n",
+ s->BulkRecvKeySize, s->BulkSendKeySize);
+ Debug("Backup:\n%s\n%s\n\n", tmp1, tmp2);
+ }
}
if (s->IsAzureSession)
@@ -5544,11 +6569,11 @@ PACK *PackWelcome(SESSION *s)
}
#define PACK_ADD_POLICY_BOOL(name, value) \
- PackAddInt(p, "policy:" name, y->value == false ? 0 : 1)
+ PackAddBool(p, "policy:" name, y->value == false ? 0 : 1)
#define PACK_ADD_POLICY_UINT(name, value) \
PackAddInt(p, "policy:" name, y->value)
#define PACK_GET_POLICY_BOOL(name, value) \
- y->value = (PackGetInt(p, "policy:" name) == 0 ? false : true)
+ y->value = (PackGetBool(p, "policy:" name))
#define PACK_GET_POLICY_UINT(name, value) \
y->value = PackGetInt(p, "policy:" name)
@@ -5902,6 +6927,8 @@ bool ClientUploadAuth(CONNECTION *c)
PackAddBool(p, "use_udp_acceleration", true);
+ PackAddInt(p, "udp_acceleration_version", c->Session->UdpAccel->Version);
+
Copy(&my_ip, &c->Session->UdpAccel->MyIp, sizeof(IP));
if (IsLocalHostIP(&my_ip))
{
@@ -5917,11 +6944,15 @@ bool ClientUploadAuth(CONNECTION *c)
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);
+ PackAddData(p, "udp_acceleration_client_key", c->Session->UdpAccel->MyKey, UDP_ACCELERATION_COMMON_KEY_SIZE_V1);
+ PackAddData(p, "udp_acceleration_client_key_v2", c->Session->UdpAccel->MyKey_V2, UDP_ACCELERATION_COMMON_KEY_SIZE_V2);
PackAddBool(p, "support_hmac_on_udp_acceleration", true);
PackAddBool(p, "support_udp_accel_fast_disconnect_detect", true);
+ PackAddInt(p, "udp_acceleration_max_version", 2);
}
+ PackAddInt(p, "rudp_bulk_max_version", 2);
+
// Brand string for the connection limit
{
char *branded_ctos = _SS("BRANDED_C_TO_S");
@@ -6033,15 +7064,20 @@ bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str)
SERVER *server;
char *vpn_http_target = HTTP_VPN_TARGET2;
bool check_hostname = false;
+ bool disable_json_api = false;
// Validate arguments
if (c == NULL)
{
return false;
}
+ server = c->Cedar->Server;
+
+ disable_json_api = server->DisableJsonRpcWebApi;
+
+
- server = c->Cedar->Server;
s = c->FirstSock;
@@ -6064,6 +7100,10 @@ bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str)
if (h == NULL)
{
c->Err = ERR_CLIENT_IS_NOT_VPN;
+ if (c->IsJsonRpc)
+ {
+ c->Err = ERR_DISCONNECTED;
+ }
return false;
}
@@ -6099,6 +7139,43 @@ bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str)
{
// Receive the data since it's POST
data_size = GetContentLength(h);
+
+ if (disable_json_api == false)
+ {
+ if (StrCmpi(h->Target, "/api") == 0 || StrCmpi(h->Target, "/api/") == 0)
+ {
+ c->IsJsonRpc = true;
+ c->Type = CONNECTION_TYPE_ADMIN_RPC;
+
+ JsonRpcProcPost(c, s, h, data_size);
+
+ FreeHttpHeader(h);
+
+ if (c->JsonRpcAuthed)
+ {
+ num = 0;
+ }
+
+ continue;
+ }
+ else if (StartWith(h->Target, "/admin"))
+ {
+ c->IsJsonRpc = true;
+ c->Type = CONNECTION_TYPE_ADMIN_RPC;
+
+ AdminWebProcPost(c, s, h, data_size, h->Target);
+
+ FreeHttpHeader(h);
+
+ if (c->JsonRpcAuthed)
+ {
+ num = 0;
+ }
+
+ continue;
+ }
+ }
+
if ((data_size > MAX_WATERMARK_SIZE || data_size < SizeOfWaterMark()) && (data_size != StrLen(HTTP_VPN_TARGET_POSTDATA)))
{
// Data is too large
@@ -6131,7 +7208,7 @@ bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str)
{
// Compare posted data with the WaterMark
if ((data_size == StrLen(HTTP_VPN_TARGET_POSTDATA) && (Cmp(data, HTTP_VPN_TARGET_POSTDATA, data_size) == 0))
- || (Cmp(data, WaterMark, SizeOfWaterMark()) == 0))
+ || ((data_size >= SizeOfWaterMark()) && Cmp(data, WaterMark, SizeOfWaterMark()) == 0))
{
// Check the WaterMark
Free(data);
@@ -6147,6 +7224,25 @@ bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str)
}
}
}
+ else if (StrCmpi(h->Method, "OPTIONS") == 0)
+ {
+ if (disable_json_api == false)
+ {
+ if (StrCmpi(h->Target, "/api") == 0 || StrCmpi(h->Target, "/api/") == 0 || StartWith(h->Target, "/admin"))
+ {
+ c->IsJsonRpc = true;
+ c->Type = CONNECTION_TYPE_ADMIN_RPC;
+
+ JsonRpcProcOptions(c, s, h, h->Target);
+
+ FreeHttpHeader(h);
+
+ num = 0;
+
+ continue;
+ }
+ }
+ }
else if (StrCmpi(h->Method, "SSTP_DUPLEX_POST") == 0 && (server->DisableSSTPServer == false || s->IsReverseAcceptedSocket
) &&
GetServerCapsBool(server, "b_support_sstp") && GetNoSstp() == false)
@@ -6202,50 +7298,27 @@ bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str)
{
// Root directory
SERVER *s = c->Cedar->Server;
- bool is_free = false;
*error_detail_str = "HTTP_ROOT";
{
- if (is_free == false)
+ BUF *b = ReadDump("|wwwroot\\index.html");
+
+ if (b != NULL)
{
- // Other than free version
- HttpSendForbidden(c->FirstSock, h->Target, "");
+ FreeHttpHeader(h);
+ h = NewHttpHeader("HTTP/1.1", "202", "OK");
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE4));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+
+ PostHttp(c->FirstSock, h, b->Buf, b->Size);
+
+ FreeBuf(b);
}
else
{
- // Free version
- BUF *b = ReadDump("|free.htm");
-
- if (b != NULL)
- {
- char *src = ZeroMalloc(b->Size + 1);
- UINT dst_size = b->Size * 2 + 64;
- char *dst = ZeroMalloc(dst_size);
- char host[MAX_PATH];
- char portstr[64];
-
- GetMachineName(host, sizeof(host));
- ToStr(portstr, c->FirstSock->LocalPort);
-
- Copy(src, b->Buf, b->Size);
- ReplaceStrEx(dst, dst_size, src,
- "$HOST$", host, false);
- ReplaceStrEx(dst, dst_size, dst,
- "$PORT$", portstr, false);
-
- FreeHttpHeader(h);
- h = NewHttpHeader("HTTP/1.1", "202", "OK");
- AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE4));
- AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
- AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
- PostHttp(c->FirstSock, h, dst, StrLen(dst));
-
- Free(src);
- Free(dst);
-
- FreeBuf(b);
- }
+ HttpSendForbidden(c->FirstSock, h->Target, "");
}
}
}
@@ -6307,6 +7380,56 @@ bool ServerDownloadSignature(CONNECTION *c, char **error_detail_str)
if (b == false)
{
+ if (disable_json_api == false)
+ {
+ if (StartWith(h->Target, "/api?") || StartWith(h->Target, "/api/") || StrCmpi(h->Target, "/api") == 0)
+ {
+ c->IsJsonRpc = true;
+ c->Type = CONNECTION_TYPE_ADMIN_RPC;
+
+ JsonRpcProcGet(c, s, h, h->Target);
+
+ if (c->JsonRpcAuthed)
+ {
+ num = 0;
+ }
+
+ FreeHttpHeader(h);
+
+ continue;
+ }
+ else if (StartWith(h->Target, "/admin"))
+ {
+ c->IsJsonRpc = true;
+ c->Type = CONNECTION_TYPE_ADMIN_RPC;
+
+ AdminWebProcGet(c, s, h, h->Target);
+
+ if (c->JsonRpcAuthed)
+ {
+ num = 0;
+ }
+
+ FreeHttpHeader(h);
+
+ continue;
+ }
+ }
+
+ if (false) // TODO
+ {
+ if (StrCmpi(h->Target, "/mvpn") == 0 || StrCmpi(h->Target, "/mvpn/") == 0)
+ {
+ MvpnProcGet(c, s, h, h->Target);
+
+ FreeHttpHeader(h);
+ continue;
+ }
+ }
+ }
+
+ if (b == false)
+ {
// Not Found
HttpSendNotFound(s, h->Target);
@@ -6517,6 +7640,7 @@ SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect, bool no_tls
if (s != NULL)
{
StrCpy(s->UnderlayProtocol, sizeof(s->UnderlayProtocol), SOCK_UNDERLAY_NAT_T);
+ AddProtocolDetailsStr(s->UnderlayProtocol, sizeof(s->UnderlayProtocol), "NAT-T");
}
}
if (s == NULL)
@@ -7225,6 +8349,45 @@ PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_pass
return p;
}
+// Generate a packet of OpenVPN certificate login
+PACK *PackLoginWithOpenVPNCertificate(char *hubname, char *username, X *x)
+{
+ PACK *p;
+ char cn_username[128];
+ BUF *cert_buf = NULL;
+ // Validate arguments
+ if (hubname == NULL || username == NULL || x == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "method", "login");
+ PackAddStr(p, "hubname", hubname);
+
+ if (IsEmptyStr(username))
+ {
+ if (x->subject_name == NULL)
+ {
+ return NULL;
+ }
+ UniToStr(cn_username, sizeof(cn_username), x->subject_name->CommonName);
+ PackAddStr(p, "username", cn_username);
+ }
+ else
+ {
+ PackAddStr(p, "username", username);
+ }
+
+ PackAddInt(p, "authtype", AUTHTYPE_OPENVPN_CERT);
+
+ cert_buf = XToBuf(x, false);
+ PackAddBuf(p, "cert", cert_buf);
+ FreeBuf(cert_buf);
+
+ return p;
+}
+
// Create a packet of password authentication login
PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password)
{
@@ -7295,3 +8458,1429 @@ void GenerateRC4KeyPair(RC4_KEY_PAIR *k)
Rand(k->ServerToClientKey, sizeof(k->ServerToClientKey));
}
+// MVPN GET Procedure (WebSocket)
+void MvpnProcGet(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target)
+{
+ HTTP_VALUE *req_upgrade;
+ HTTP_VALUE *req_version;
+ HTTP_VALUE *req_key;
+ char response_key[64];
+ UINT client_ws_version = 0;
+ char *bad_request_body = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\"http://www.w3.org/TR/html4/strict.dtd\">\r\n<HTML><HEAD><TITLE>Bad Request</TITLE>\r\n<META HTTP-EQUIV=\"Content-Type\" Content=\"text/html; charset=us-ascii\"></HEAD>\r\n<BODY><h2>Bad Request</h2>\r\n<hr><p>HTTP Error 400. The request is badly formed.</p>\r\n</BODY></HTML>";
+ if (c == NULL || s == NULL || h == NULL || url_target == NULL)
+ {
+ return;
+ }
+
+ req_upgrade = GetHttpValue(h, "Upgrade");
+ if (req_upgrade == NULL || StrCmpi(req_upgrade->Data, "websocket") != 0)
+ {
+ MvpnSendReply(s, 400, "Bad Request", bad_request_body, StrLen(bad_request_body),
+ NULL, NULL, NULL, h);
+ return;
+ }
+
+ req_version = GetHttpValue(h, "Sec-WebSocket-Version");
+ if (req_version != NULL) client_ws_version = ToInt(req_version->Data);
+ if (client_ws_version != 13)
+ {
+ MvpnSendReply(s, 400, "Bad Request", NULL, 0,
+ NULL, "Sec-WebSocket-Version", "13", h);
+ return;
+ }
+
+ Zero(response_key, sizeof(response_key));
+ req_key = GetHttpValue(h, "Sec-WebSocket-Key");
+ if (req_key != NULL)
+ {
+ char tmp[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
+ StrCpy(tmp, sizeof(tmp), req_key->Data);
+ StrCat(tmp, sizeof(tmp), "258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
+ HashSha1(hash, tmp, StrLen(tmp));
+ B64_Encode(response_key, hash, SHA1_SIZE);
+ }
+ else
+ {
+ MvpnSendReply(s, 400, "Bad Request", NULL, 0,
+ NULL, "Sec-WebSocket-Version", "13", h);
+ return;
+ }
+
+ MvpnSendReply(s, 101, "Switching Protocols", NULL, 0, NULL,
+ "Sec-WebSocket-Accept", response_key, h);
+
+ MvpnAccept(c, s);
+}
+
+// MVPN Send Reply
+bool MvpnSendReply(SOCK *s, UINT status_code, char *status_string, UCHAR *data, UINT data_size, char *content_type,
+ char *add_header_name, char *add_header_value, HTTP_HEADER *request_headers)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char error_code_str[16];
+ bool ret = false;
+ HTTP_VALUE *origin;
+ HTTP_VALUE *upgrade;
+ HTTP_VALUE *req_connection;
+ if (s == NULL || status_string == NULL || (data_size != 0 && data == NULL) || request_headers == NULL)
+ {
+ return false;
+ }
+ if (content_type == NULL)
+ {
+ content_type = "text/html; charset=utf-8";
+ }
+
+ req_connection = GetHttpValue(request_headers, "Connection");
+
+ ToStr(error_code_str, status_code);
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", error_code_str, status_string);
+
+ AddHttpValue(h, NewHttpValue("Cache-Control", "no-cache"));
+ if (data_size != 0)
+ {
+ AddHttpValue(h, NewHttpValue("Content-Type", content_type));
+ }
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ if (req_connection != NULL)
+ {
+ AddHttpValue(h, NewHttpValue("Connection", req_connection->Data));
+ }
+ else
+ {
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ }
+ AddHttpValue(h, NewHttpValue("Access-Control-Allow-Headers", "content-type"));
+ AddHttpValue(h, NewHttpValue("Access-Control-Allow-Headers", "authorization"));
+ AddHttpValue(h, NewHttpValue("Access-Control-Allow-Headers", "x-websocket-extensions"));
+ AddHttpValue(h, NewHttpValue("Access-Control-Allow-Headers", "x-websocket-version"));
+ AddHttpValue(h, NewHttpValue("Access-Control-Allow-Headers", "x-websocket-protocol"));
+ AddHttpValue(h, NewHttpValue("Access-Control-Allow-Credentials", "true"));
+
+ origin = GetHttpValue(request_headers, "Origin");
+ if (origin != NULL)
+ {
+ AddHttpValue(h, NewHttpValue("Access-Control-Allow-Origin", origin->Data));
+ }
+
+ upgrade = GetHttpValue(request_headers, "Upgrade");
+ if (upgrade != NULL)
+ {
+ AddHttpValue(h, NewHttpValue("Upgrade", upgrade->Data));
+ }
+
+ if (add_header_name != NULL && add_header_value != NULL)
+ {
+ AddHttpValue(h, NewHttpValue(add_header_name, add_header_value));
+ }
+
+ ret = PostHttp(s, h, data, data_size);
+
+ FreeHttpHeader(h);
+
+ return ret;
+}
+
+// MVPN Accept
+void MvpnAccept(CONNECTION *c, SOCK *s)
+{
+ WS *w;
+ UINT err;
+ if (c == NULL || s == NULL)
+ {
+ return;
+ }
+
+ w = NewWs(s);
+
+ err = MvpnDoAccept(c, w);
+
+ //while (true)
+ //{
+ // UINT r;
+ // Zero(data, sizeof(data));
+ // r = WsRecvSyncAll(w, data, 7);
+ // if (!r)
+ // {
+ // break;
+ // }
+ // Print("WS_Recv: %s\n", data);
+ // r = WsSendSync(w, data, 7);
+ // if (!r)
+ // {
+ // break;
+ // }
+ // Print("WS_Send: %s\n", data);
+ //}
+
+ ReleaseWs(w);
+}
+
+// New WebSocket
+WS *NewWs(SOCK *s)
+{
+ WS *w;
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ w = ZeroMalloc(sizeof(WS));
+
+ w->Ref = NewRef();
+
+ w->MaxBufferSize = MAX_BUFFERING_PACKET_SIZE;
+ w->Sock = s;
+ AddRef(w->Sock->ref);
+
+ w->Wsp = NewWsp();
+
+ return w;
+}
+
+// Release WebSocket
+void ReleaseWs(WS *w)
+{
+ if (w == NULL)
+ {
+ return;
+ }
+
+ if (Release(w->Ref) == 0)
+ {
+ CleanupWs(w);
+ }
+}
+
+void CleanupWs(WS *w)
+{
+ if (w == NULL)
+ {
+ return;
+ }
+
+ if (w->Sock != NULL)
+ {
+ Disconnect(w->Sock);
+ ReleaseSock(w->Sock);
+ }
+
+ FreeWsp(w->Wsp);
+
+ Free(w);
+}
+
+// WebSocket: Send a frame in sync mode
+bool WsSendSync(WS *w, void *data, UINT size)
+{
+ UCHAR *send_buf;
+ UINT send_buf_size;
+ if (size == 0)
+ {
+ return !w->Disconnected;
+ }
+ if (w == NULL || data == NULL)
+ {
+ return false;
+ }
+ if (w->Disconnected || w->Wsp->HasError)
+ {
+ Disconnect(w->Sock);
+ return false;
+ }
+
+ WriteFifo(w->Wsp->AppSendFifo, data, size);
+ WspTry(w->Wsp);
+ if (w->Wsp->HasError == false)
+ {
+ send_buf = FifoPtr(w->Wsp->PhysicalSendFifo);
+ send_buf_size = FifoSize(w->Wsp->PhysicalSendFifo);
+ if (SendAll(w->Sock, send_buf, send_buf_size, w->Sock->SecureMode))
+ {
+ ReadFifo(w->Wsp->PhysicalSendFifo, NULL, send_buf_size);
+ return true;
+ }
+ }
+
+ w->Disconnected = true;
+ Disconnect(w->Sock);
+
+ return false;
+}
+
+// WebSocket: Send a frame in async mode
+UINT WsSendAsync(WS *w, void *data, UINT size)
+{
+ bool disconnected = false;
+ UINT ret = 0;
+ if (size == 0)
+ {
+ return !w->Disconnected;
+ }
+ if (w == NULL || data == NULL)
+ {
+ return 0;
+ }
+ if (w->Disconnected || w->Wsp->HasError)
+ {
+ Disconnect(w->Sock);
+ return 0;
+ }
+
+ if (FifoSize(w->Wsp->PhysicalSendFifo) > w->Wsp->MaxBufferSize)
+ {
+ return INFINITE;
+ }
+
+ WriteFifo(w->Wsp->AppSendFifo, data, size);
+
+ if (WsTrySendAsync(w) == false)
+ {
+ ret = 0;
+ }
+ else
+ {
+ ret = size;
+ }
+
+ if (ret == 0)
+ {
+ w->Disconnected = true;
+ Disconnect(w->Sock);
+ }
+
+ return ret;
+}
+
+// WebSocket: Send buffered streams in async mode
+bool WsTrySendAsync(WS *w)
+{
+ bool ret = false;
+ if (w == NULL)
+ {
+ return false;
+ }
+ if (w->Disconnected || w->Wsp->HasError)
+ {
+ Disconnect(w->Sock);
+ return false;
+ }
+
+ WspTry(w->Wsp);
+
+ if (w->Wsp->HasError == false)
+ {
+ while (true)
+ {
+ UINT send_size = FifoSize(w->Wsp->PhysicalSendFifo);
+ UINT r;
+ if (send_size == 0)
+ {
+ ret = true;
+ break;
+ }
+
+ r = Send(w->Sock, FifoPtr(w->Wsp->PhysicalSendFifo), send_size, w->Sock->SecureMode);
+
+ if (r == INFINITE)
+ {
+ ret = true;
+ break;
+ }
+ else if (r == 0)
+ {
+ ret = false;
+ break;
+ }
+ else
+ {
+ ReadFifo(w->Wsp->PhysicalSendFifo, NULL, r);
+ }
+ }
+ }
+ else
+ {
+ ret = false;
+ }
+
+ if (ret == 0)
+ {
+ w->Disconnected = true;
+ Disconnect(w->Sock);
+ }
+
+ return ret;
+}
+
+// WebSocket: Receive a frame in async mode
+UINT WsRecvAsync(WS *w, void *data, UINT size)
+{
+ bool disconnected = false;
+ UINT ret = 0;
+ if (w == NULL || data == NULL || size == 0)
+ {
+ return 0;
+ }
+ if (w->Disconnected || w->Wsp->HasError)
+ {
+ Disconnect(w->Sock);
+ return 0;
+ }
+
+ // Receive all arrived data from the socket
+ while (FifoSize(w->Wsp->PhysicalRecvFifo) < w->MaxBufferSize)
+ {
+ UINT r;
+
+ r = Recv(w->Sock, w->TmpBuf, sizeof(w->TmpBuf), w->Sock->SecureMode);
+ if (r == 0)
+ {
+ // Disconnected
+ disconnected = true;
+ break;
+ }
+ else if (r == INFINITE)
+ {
+ // Pending
+ break;
+ }
+ else
+ {
+ // Received some data
+ WriteFifo(w->Wsp->PhysicalRecvFifo, w->TmpBuf, r);
+ }
+ }
+
+ if (disconnected == false)
+ {
+ UINT sz;
+ WspTry(w->Wsp);
+ if (w->Wsp->HasError)
+ {
+ disconnected = true;
+ }
+ else
+ {
+ sz = FifoSize(w->Wsp->AppRecvFifo);
+ if (sz >= 1)
+ {
+ if (sz > size)
+ {
+ sz = size;
+ }
+ ReadFifo(w->Wsp->AppRecvFifo, data, sz);
+ ret = sz;
+ }
+ else
+ {
+ ret = INFINITE;
+ }
+ }
+ }
+
+ if (disconnected)
+ {
+ w->Disconnected = true;
+ Disconnect(w->Sock);
+ ret = 0;
+ }
+
+ return ret;
+}
+
+// WebSocket: Receive a frame in sync mode until fulfill the buffer
+bool WsRecvSyncAll(WS *w, void *data, UINT size)
+{
+ UINT recv_size;
+ if (w == NULL || data == NULL || size == 0)
+ {
+ return false;
+ }
+
+ recv_size = 0;
+
+ while (true)
+ {
+ UINT sz, ret;
+
+ sz = size - recv_size;
+ ret = WsRecvSync(w, (UCHAR *)data + recv_size, sz);
+ if (ret == 0)
+ {
+ return false;
+ }
+ recv_size += ret;
+ if (recv_size >= size)
+ {
+ return true;
+ }
+ }
+}
+
+// WebSocket: Receive a frame in sync mode
+UINT WsRecvSync(WS *w, void *data, UINT size)
+{
+ if (w == NULL || data == NULL || size == 0)
+ {
+ return 0;
+ }
+ if (w->Disconnected || w->Wsp->HasError)
+ {
+ Disconnect(w->Sock);
+ return 0;
+ }
+
+ while (w->Disconnected == false || w->Wsp->HasError == false)
+ {
+ UINT r;
+ UINT sz;
+ WspTry(w->Wsp);
+ if (w->Wsp->HasError)
+ {
+ break;
+ }
+ sz = FifoSize(w->Wsp->AppRecvFifo);
+ if (sz >= 1)
+ {
+ if (sz > size)
+ {
+ sz = size;
+ }
+ ReadFifo(w->Wsp->AppRecvFifo, data, sz);
+ return sz;
+ }
+ r = Recv(w->Sock, w->TmpBuf, sizeof(w->TmpBuf), w->Sock->SecureMode);
+ if (r == 0)
+ {
+ break;
+ }
+ WriteFifo(w->Wsp->PhysicalRecvFifo, w->TmpBuf, r);
+ }
+
+ w->Disconnected = true;
+ Disconnect(w->Sock);
+
+ return 0;
+}
+
+// New WebSocket protocol
+WSP *NewWsp()
+{
+ WSP *p = ZeroMalloc(sizeof(WSP));
+
+ p->AppRecvFifo = NewFifo();
+ p->AppSendFifo = NewFifo();
+ p->PhysicalRecvFifo = NewFifo();
+ p->PhysicalSendFifo = NewFifo();
+
+ p->MaxBufferSize = MAX_BUFFERING_PACKET_SIZE;
+
+ return p;
+}
+
+// Free WebSocket protocol
+void FreeWsp(WSP *p)
+{
+ if (p == NULL)
+ {
+ return;
+ }
+
+ ReleaseFifo(p->AppRecvFifo);
+ ReleaseFifo(p->AppSendFifo);
+ ReleaseFifo(p->PhysicalRecvFifo);
+ ReleaseFifo(p->PhysicalSendFifo);
+
+ Free(p);
+}
+
+// WebSocket protocol: Try to interpret send/recv buffers
+void WspTry(WSP *p)
+{
+ if (p == NULL)
+ {
+ return;
+ }
+
+ // Physical -> App
+ while (p->HasError == false)
+ {
+ UINT read_buffer_size;
+ BLOCK *b = WspTryRecvNextFrame(p, &read_buffer_size);
+ if (b == NULL)
+ {
+ // No more frames
+ break;
+ }
+
+ if (b->Param1 == WS_OPCODE_CONTINUE || b->Param1 == WS_OPCODE_TEXT || b->Param1 == WS_OPCODE_BIN)
+ {
+ WriteFifo(p->AppRecvFifo, b->Buf, b->Size);
+ }
+ else if (b->Param1 == WS_OPCODE_PING)
+ {
+ if (FifoSize(p->PhysicalSendFifo) <= p->MaxBufferSize)
+ {
+ WspTrySendFrame(p, WS_OPCODE_PONG, b->Buf, b->Size);
+ }
+ }
+ else if (b->Param1 == WS_OPCODE_PONG)
+ {
+ }
+ else
+ {
+ // Error: disconnect
+ p->HasError = true;
+ }
+
+ ReadFifo(p->PhysicalRecvFifo, NULL, read_buffer_size);
+
+ FreeBlock(b);
+ }
+
+ // App -> Physical
+ while (p->HasError == false)
+ {
+ UINT size;
+ UCHAR *data;
+
+ size = FifoSize(p->AppSendFifo);
+ if (size == 0)
+ {
+ // No more data
+ break;
+ }
+
+ if (size > WS_SEND_SINGLE_FRAGMENT_SIZE)
+ {
+ size = WS_SEND_SINGLE_FRAGMENT_SIZE;
+ }
+ data = FifoPtr(p->AppSendFifo);
+
+ WspTrySendFrame(p, WS_OPCODE_BIN, data, size);
+
+ ReadFifo(p->AppSendFifo, NULL, size);
+ }
+}
+
+// WebSocket protocol: Try to send a single frame
+void WspTrySendFrame(WSP *p, UCHAR opcode, void *data, UINT size)
+{
+ BUF *b;
+ UCHAR flag_and_opcode;
+ if (p == NULL || (size != 0 && data == NULL))
+ {
+ return;
+ }
+ if (p->HasError)
+ {
+ return;
+ }
+
+ b = NewBuf();
+
+ flag_and_opcode = 0x80 | (opcode & 0x0F);
+ WriteBufChar(b, flag_and_opcode);
+
+ if (size <= 125)
+ {
+ WriteBufChar(b, size);
+ }
+ else if (size <= 65536)
+ {
+ WriteBufChar(b, 126);
+ WriteBufShort(b, size);
+ }
+ else
+ {
+ WriteBufChar(b, 127);
+ WriteBufInt64(b, size);
+ }
+
+ WriteBuf(b, data, size);
+
+ WriteFifo(p->PhysicalSendFifo, b->Buf, b->Size);
+
+ FreeBuf(b);
+}
+
+// WebSocket protocol: Try to receive a single frame
+BLOCK *WspTryRecvNextFrame(WSP *p, UINT *read_buffer_size)
+{
+ BLOCK *b;
+ UCHAR *buf;
+ UCHAR *buf_pos0;
+ UINT sz;
+ UCHAR flag_and_opcode;
+ UCHAR mask_and_payload_len;
+ UCHAR mask_flag;
+ UINT payload_len;
+ UCHAR mask_key[4];
+ UCHAR *ret_data;
+ if (p == NULL || read_buffer_size == NULL)
+ {
+ return NULL;
+ }
+ if (p->HasError)
+ {
+ return NULL;
+ }
+
+ buf = buf_pos0 = FifoPtr(p->PhysicalRecvFifo);
+ sz = FifoSize(p->PhysicalRecvFifo);
+
+ if (sz < 1)
+ {
+ return NULL;
+ }
+ flag_and_opcode = *buf;
+ buf += 1;
+ sz -= 1;
+
+ if (sz < 1)
+ {
+ return NULL;
+ }
+ mask_and_payload_len = *buf;
+ buf += 1;
+ sz -= 1;
+
+ mask_flag = mask_and_payload_len & 0x80;
+ payload_len = mask_and_payload_len & 0x7F;
+ if (payload_len == 126)
+ {
+ if (sz < sizeof(USHORT))
+ {
+ return NULL;
+ }
+ payload_len = READ_USHORT(buf);
+ buf += sizeof(USHORT);
+ sz -= sizeof(USHORT);
+ }
+ else if (payload_len == 127)
+ {
+ UINT64 u64;
+ if (sz < sizeof(UINT64))
+ {
+ return NULL;
+ }
+ u64 = READ_UINT64(buf);
+ buf += sizeof(UINT64);
+ sz -= sizeof(UINT64);
+ if (u64 > 0x7FFFFFFF)
+ {
+ p->HasError = true;
+ return NULL;
+ }
+ payload_len = (UINT)u64;
+ }
+
+ if (payload_len > WS_MAX_PAYLOAD_LEN_PER_FRAME)
+ {
+ p->HasError = true;
+ return NULL;
+ }
+
+ if (mask_flag)
+ {
+ if (sz < 4)
+ {
+ return NULL;
+ }
+ Copy(mask_key, buf, 4);
+ buf += 4;
+ sz -= 4;
+ }
+
+ if (payload_len >= 1 && sz < payload_len)
+ {
+ return NULL;
+ }
+
+ ret_data = Clone(buf, payload_len);
+ sz -= payload_len;
+ buf += payload_len;
+
+ if (mask_flag)
+ {
+ UINT i;
+ for (i = 0;i < payload_len;i++)
+ {
+ ret_data[i] ^= mask_key[i % 4];
+ }
+ }
+
+ b = NewBlock(ret_data, payload_len, 0);
+ b->Param1 = (flag_and_opcode & 0xF);
+
+ *read_buffer_size = (UINT)(buf - buf_pos0);
+
+ return b;
+}
+
+// WebSocket: Receive a PACK serialized with JSON
+PACK *WsRecvPack(WS *w)
+{
+ USHORT us;
+ UINT size;
+ UCHAR *buf;
+ PACK *p = NULL;
+ if (w == NULL)
+ {
+ return NULL;
+ }
+
+ if (WsRecvSyncAll(w, &us, sizeof(us)))
+ {
+ size = Endian16(us);
+
+ buf = ZeroMalloc(size + 1);
+
+ if (WsRecvSyncAll(w, buf, size))
+ {
+ p = JsonStrToPack(buf);
+ }
+
+ Free(buf);
+ }
+
+ return p;
+}
+
+// WebSocket: Send a PACK serialized with JSON
+bool WsSendPack(WS *w, PACK *p)
+{
+ BUF *b;
+ char *json_str;
+ bool ret = false;
+ if (w == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ json_str = PackToJsonStr(p);
+ if (json_str == NULL)
+ {
+ return false;
+ }
+
+ b = NewBuf();
+
+ WriteBufShort(b, StrLen(json_str));
+ WriteBuf(b, json_str, StrLen(json_str));
+
+ ret = WsSendSync(w, b->Buf, b->Size);
+
+ FreeBuf(b);
+
+ Free(json_str);
+
+ return ret;
+}
+
+// WebSocket: new error pack
+PACK *WsNewErrorPack(UINT err)
+{
+ PACK *p = NewPack();
+ char *error_code_str = WsErrorCodeToString(err);
+ wchar_t *error_message = _E(err);
+
+ PackAddStr(p, "Error", error_code_str);
+ PackAddUniStr(p, "ErrorMessage", error_message);
+
+ return p;
+}
+
+// MVPN: convert error code to string
+char *WsErrorCodeToString(UINT err)
+{
+ char *ret = "e_unknown";
+ switch (err)
+ {
+ case ERR_NO_ERROR:
+ ret = "ok";
+ break;
+ case ERR_PROTOCOL_ERROR:
+ ret = "e_protocol";
+ break;
+ case ERR_INTERNAL_ERROR:
+ ret = "e_internal";
+ break;
+ case ERR_DISCONNECTED:
+ case ERR_AUTO_DISCONNECTED:
+ ret = "e_disconnected";
+ break;
+ case ERR_ACCESS_DENIED:
+ ret = "e_access_denied";
+ break;
+ case ERR_HUB_NOT_FOUND:
+ ret = "e_network_not_found";
+ break;
+ case ERR_HUB_STOPPING:
+ ret = "e_network_disabled";
+ break;
+ case ERR_AUTH_FAILED:
+ ret = "e_auth_failed";
+ break;
+ case ERR_SESSION_TIMEOUT:
+ ret = "e_timeout";
+ break;
+ case ERR_USER_CANCEL:
+ ret = "e_user_cancel";
+ break;
+ case ERR_AUTHTYPE_NOT_SUPPORTED:
+ ret = "e_auth_method_not_supported";
+ break;
+ case ERR_TOO_MANY_CONNECTION:
+ ret = "e_too_many_connection";
+ break;
+ case ERR_HUB_IS_BUSY:
+ ret = "e_too_many_session";
+ break;
+ case ERR_TOO_MANY_USER_SESSION:
+ ret = "e_too_many_user_session";
+ break;
+ case ERR_OBJECT_NOT_FOUND:
+ ret = "e_object_not_found";
+ break;
+ case ERR_NOT_SUPPORTED:
+ case ERR_NOT_SUPPORTED_AUTH_ON_OPENSOURCE:
+ ret = "e_not_supported";
+ break;
+ case ERR_INVALID_PARAMETER:
+ ret = "e_invalid_parameter";
+ break;
+ case ERR_NULL_PASSWORD_LOCAL_ONLY:
+ ret = "e_empty_password_local_only";
+ break;
+ case ERR_MONITOR_MODE_DENIED:
+ ret = "e_mirror_mode_denied";
+ break;
+ case ERR_BRIDGE_MODE_DENIED:
+ ret = "e_bridge_mode_denied";
+ break;
+ case ERR_IP_ADDRESS_DENIED:
+ ret = "e_client_ip_address_denied";
+ break;
+ case ERR_MSCHAP2_PASSWORD_NEED_RESET:
+ ret = "e_user_password_must_reset";
+ break;
+ }
+ return ret;
+}
+
+// MVPN processing a client
+UINT MvpnDoAccept(CONNECTION *c, WS *w)
+{
+ UINT ret = ERR_INTERNAL_ERROR;
+ PACK *client_hello = NULL;
+ UINT client_ver = 0;
+ char client_impl[256];
+ UCHAR client_nonce[128];
+ char client_hub_name[MAX_HUBNAME_LEN + 1];
+ UINT server_ver = 0;
+ char server_impl[256];
+ UCHAR server_nonce[128];
+ PACK *server_hello = NULL;
+ UINT auth_ret = ERR_INTERNAL_ERROR;
+ IPC *ipc = NULL;
+ UINT i;
+ UINT heartbeat_interval = 0;
+ UINT disconnect_timeout = 0;
+ bool use_udp_acceleration = false;
+ IP client_udp_acceleration_ip = {0};
+ UINT client_udp_acceleration_port = 0;
+ UCHAR client_udp_acceleration_key[UDP_ACCELERATION_COMMON_KEY_SIZE_V2] = {0};
+ UDP_ACCEL *udp_accel = NULL;
+
+ if (c == NULL || w == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ Rand(server_nonce, sizeof(server_nonce));
+
+ // Phase 1: Receive a Client Hello packet
+ client_hello = WsRecvPack(w);
+ if (client_hello == NULL)
+ {
+ ret = ERR_PROTOCOL_ERROR;
+ goto LABEL_CLEANUP;
+ }
+ client_ver = PackGetInt(client_hello, "MvpnProtocolVersion");
+ if (client_ver < MVPN_VERSION_MIN)
+ {
+ ret = ERR_PROTOCOL_ERROR;
+ goto LABEL_CLEANUP;
+ }
+ server_ver = MIN(MVPN_VERSION_CURRENT, client_ver);
+ if (PackGetData2(client_hello, "Nonce", client_nonce, 128) == false)
+ {
+ ret = ERR_PROTOCOL_ERROR;
+ goto LABEL_CLEANUP;
+ }
+ if (PackGetStr(client_hello, "Implementation", client_impl, sizeof(client_impl)) == false)
+ {
+ ret = ERR_PROTOCOL_ERROR;
+ goto LABEL_CLEANUP;
+ }
+ heartbeat_interval = PackGetInt(client_hello, "HeartBeatInterval");
+
+ if (heartbeat_interval == 0) heartbeat_interval = MVPN_HEARTBEAT_INTERVAL_DEFAULT;
+ heartbeat_interval = MAKESURE(heartbeat_interval, MVPN_HEARTBEAT_INTERVAL_MIN, MVPN_HEARTBEAT_INTERVAL_MAX);
+
+ disconnect_timeout = PackGetInt(client_hello, "DisconnectTimeout");
+ if (disconnect_timeout == 0) disconnect_timeout = MVPN_DISCONNECT_TIMEOUT_DEFAULT;
+ disconnect_timeout = MAKESURE(disconnect_timeout, MVPN_DISCONNECT_TIMEOUT_MIN, MVPN_DISCONNECT_TIMEOUT_MAX);
+
+ heartbeat_interval = MIN(heartbeat_interval, disconnect_timeout / 2);
+
+ use_udp_acceleration = PackGetBool(client_hello, "UseUdpAcceleration");
+ if (use_udp_acceleration)
+ {
+ client_udp_acceleration_port = PackGetInt(client_hello, "UdpAccelerationClientPort");
+ if (client_udp_acceleration_port == 0 ||
+ PackGetIp(client_hello, "UdpAccelerationClientIp", &client_udp_acceleration_ip) == false ||
+ PackGetData2(client_hello, "UdpAccelerationClientKey", client_udp_acceleration_key, sizeof(client_udp_acceleration_key)) == false)
+ {
+ use_udp_acceleration = false;
+ }
+ }
+
+
+ Zero(client_hub_name, sizeof(client_hub_name));
+ PackGetStr(client_hello, "NetworkName", client_hub_name, sizeof(client_hub_name));
+
+ // Phase 2: Send a Server Hello packet
+ server_hello = WsNewErrorPack(ERR_NO_ERROR);
+ StrCpy(server_impl, sizeof(server_impl), "Test Server");
+ PackAddInt(server_hello, "MvpnProtocolVersion", server_ver);
+ PackAddData(server_hello, "Nonce", server_nonce, 128);
+ PackAddStr(server_hello, "Implementation", server_impl);
+ PackAddStr(server_hello, "SupportedAuthMethod", MVPN_AUTHTYPE_ALL_SUPPORTED);
+ if (WsSendPack(w, server_hello) == false)
+ {
+ ret = ERR_DISCONNECTED;
+ goto LABEL_CLEANUP;
+ }
+
+ // Phase 3: Receive a Client Auth packet
+ for (i = 0;i < MVPN_MAX_AUTH_RETRY;i++)
+ {
+ bool auth_finish = false;
+ PACK *client_auth = NULL;
+ char auth_method[64] = {0};
+ char auth_username[MAX_USERNAME_LEN + 1];
+ IPC *ipc_tmp = NULL;
+ IPC_PARAM ipc_param;
+ UINT ipc_error_code = 0;
+ UINT mss = INFINITE;
+
+ auth_ret = ERR_INTERNAL_ERROR;
+
+ client_auth = WsRecvPack(w);
+ if (client_auth == NULL)
+ {
+ auth_ret = ERR_PROTOCOL_ERROR;
+ goto LABEL_EXIT_AUTH_RETRY;
+ }
+
+ PackGetStr(client_auth, "AuthMethod", auth_method, sizeof(auth_method));
+ if (IsEmptyStr(auth_method))
+ {
+ auth_ret = ERR_PROTOCOL_ERROR;
+ goto LABEL_EXIT_AUTH_RETRY;
+ }
+
+ PackGetStr(client_auth, "AuthUsername", auth_username, sizeof(auth_username));
+ if (IsEmptyStr(auth_method))
+ {
+ auth_ret = ERR_PROTOCOL_ERROR;
+ goto LABEL_EXIT_AUTH_RETRY;
+ }
+
+ Zero(&ipc_param, sizeof(ipc_param));
+ StrCpy(ipc_param.ClientName, sizeof(ipc_param.ClientName), MVPN_CLIENT_NAME);
+
+ if (IsEmptyStr(client_impl) == false)
+ {
+ StrCat(ipc_param.ClientName, sizeof(ipc_param.ClientName), " - ");
+ StrCat(ipc_param.ClientName, sizeof(ipc_param.ClientName), client_impl);
+ }
+
+ StrCpy(ipc_param.Postfix, sizeof(ipc_param.Postfix), NVPN_POSTFIX);
+ StrCpy(ipc_param.HubName, sizeof(ipc_param.HubName), client_hub_name);
+ StrCpy(ipc_param.UserName, sizeof(ipc_param.UserName), auth_username);
+ CopyIP(&ipc_param.ClientIp, &w->Sock->RemoteIP);
+ ipc_param.ClientPort, w->Sock->RemotePort;
+ CopyIP(&ipc_param.ServerIp, &w->Sock->LocalIP);
+ ipc_param.ServerPort, w->Sock->LocalPort;
+ StrCpy(ipc_param.ClientHostname, sizeof(ipc_param.ClientHostname), w->Sock->RemoteHostname);
+ StrCpy(ipc_param.CryptName, sizeof(ipc_param.CryptName), w->Sock->CipherName);
+ ipc_param.Layer = IPC_LAYER_3; // TODO
+ ipc_param.BridgeMode = false; // TODO
+
+ // MSS
+ if (udp_accel != NULL) mss = MIN(mss, UdpAccelCalcMss(udp_accel));
+ if (mss == INFINITE)
+ {
+ mss = 0;
+ }
+ ipc_param.Mss = mss;
+
+ if (StrCmpi(auth_method, MVPN_AUTHTYPE_ANONYMOUS) == 0)
+ {
+ // Anonymous
+ }
+ else if (StrCmpi(auth_method, MVPN_AUTHTYPE_PASSWORD_PLAIN) == 0)
+ {
+ // Plaintext
+ char pw[MAX_PASSWORD_LEN + 1];
+ PackGetStr(client_auth, "AuthPlainPassword", pw, sizeof(pw));
+ StrCpy(ipc_param.Password, sizeof(ipc_param.Password), pw);
+ }
+ else
+ {
+ // Unknown auth method
+ auth_ret = ERR_AUTHTYPE_NOT_SUPPORTED;
+ goto LABEL_EXIT_AUTH_RETRY;
+ }
+
+ ipc_tmp = NewIPCByParam(c->Cedar, &ipc_param, &ipc_error_code);
+
+ if (ipc_tmp == NULL)
+ {
+ auth_ret = ipc_error_code;
+ goto LABEL_EXIT_AUTH_RETRY;
+ }
+ else
+ {
+ ipc = ipc_tmp;
+ auth_finish = true;
+ }
+
+ auth_ret = ERR_NO_ERROR;
+
+LABEL_EXIT_AUTH_RETRY:
+ if (auth_ret != ERR_NO_ERROR)
+ {
+ // Phase 4: Send a Server Auth Response
+ PACK *error_pack = WsNewErrorPack(auth_ret);
+ UINT remain_retry = MVPN_MAX_AUTH_RETRY - 1 - i;
+ PackAddInt(error_pack, "RetryAllowedCount", remain_retry);
+ WsSendPack(w, error_pack);
+ FreePack(error_pack);
+ }
+ FreePack(client_auth);
+ if (auth_finish)
+ {
+ break;
+ }
+ }
+
+ if (ipc != NULL)
+ {
+ AddProtocolDetailsStr(ipc->IpcSessionShared->ProtocolDetails, sizeof(ipc->IpcSessionShared->ProtocolDetails),
+ "ModernVPN");
+ AddProtocolDetailsKeyValueStr(ipc->IpcSessionShared->ProtocolDetails, sizeof(ipc->IpcSessionShared->ProtocolDetails),
+ "Transport", "TCP_WebSocket");
+ }
+
+ if (ipc != NULL && use_udp_acceleration)
+ {
+ udp_accel = NewUdpAccel(c->Cedar, (c->FirstSock->IsRUDPSocket ? NULL : &c->FirstSock->LocalIP),
+ false, false, false);
+
+ udp_accel->Version = 2;
+
+ udp_accel->FastDetect = true;
+ udp_accel->ReadRawFlagMode = true;
+
+ if (UdpAccelInitServer(udp_accel, client_udp_acceleration_key,
+ &client_udp_acceleration_ip, client_udp_acceleration_port, NULL) == false)
+ {
+ FreeUdpAccel(udp_accel);
+ udp_accel = NULL;
+ }
+ }
+
+ if (ipc != NULL)
+ {
+ // Phase 4: Send auth OK response
+ PACK *ok_pack = WsNewErrorPack(ERR_NO_ERROR);
+ PackAddInt(ok_pack, "HeartBeatInterval", heartbeat_interval);
+ PackAddInt(ok_pack, "DisconnectTimeout", disconnect_timeout);
+ PackAddStr(ok_pack, "NetworkName", ipc->HubName);
+ if (udp_accel != NULL)
+ {
+ PackAddBool(ok_pack, "UseUdpAcceleration", true);
+ PackAddIp(ok_pack, "UdpAccelerationServerIp", &udp_accel->MyIp);
+ PackAddInt(ok_pack, "UdpAccelerationServerPort", udp_accel->MyPort);
+ PackAddData(ok_pack, "UdpAccelerationServerKey", udp_accel->MyKey_V2, sizeof(udp_accel->MyKey_V2));
+ PackAddInt(ok_pack, "UdpAccelerationServerCookie", udp_accel->MyCookie);
+ PackAddInt(ok_pack, "UdpAccelerationClientCookie", udp_accel->YourCookie);
+ }
+ else
+ {
+ PackAddBool(ok_pack, "UseUdpAcceleration", false);
+ }
+ WsSendPack(w, ok_pack);
+ FreePack(ok_pack);
+
+ // Session main loop
+ if (true)
+ {
+ SOCK *sock = w->Sock;
+ SOCK_EVENT *sock_event = NewSockEvent();
+ FIFO *send_fifo = NewFifo();
+ FIFO *recv_fifo = NewFifo();
+ bool has_error = false;
+ UINT magic_number = Endian32(MVPN_PACKET_MAGIC_NUMBER);
+ UINT64 last_sent_heartbeat = 0;
+ UINT tmp_buf_size = 256000;
+ UCHAR *tmp_buf = ZeroMalloc(tmp_buf_size);
+ UINT64 last_comm_recv = Tick64();
+
+ SetTimeout(sock, TIMEOUT_INFINITE);
+ JoinSockToSockEvent(sock, sock_event);
+ if (udp_accel != NULL)
+ {
+ JoinSockToSockEvent(udp_accel->UdpSock, sock_event);
+ }
+ IPCSetSockEventWhenRecvL2Packet(ipc, sock_event);
+
+ while (true)
+ {
+ UINT next_interval = INFINITE;
+ UINT send_ret = 0;
+ UINT64 now = Tick64();
+ UINT r;
+
+ if (udp_accel != NULL)
+ {
+ UdpAccelSetTick(udp_accel, now);
+ UdpAccelPoll(udp_accel);
+ ipc->IpcSessionShared->EnableUdpAccel = true;
+ ipc->IpcSessionShared->UsingUdpAccel = UdpAccelIsSendReady(udp_accel, true);
+ }
+ else
+ {
+ ipc->IpcSessionShared->EnableUdpAccel = false;
+ ipc->IpcSessionShared->UsingUdpAccel = false;
+ }
+
+ // Send heartbeat
+ if (last_sent_heartbeat == 0 || (last_sent_heartbeat + (UINT64)heartbeat_interval) <= now)
+ {
+ last_sent_heartbeat = now;
+ if (FifoSize(send_fifo) <= MAX_BUFFERING_PACKET_SIZE)
+ {
+ UCHAR packet_type = MVPN_PACKET_TYPE_HEARTBEAT;
+ USHORT packet_size = 0;
+ WriteFifo(send_fifo, &magic_number, 4);
+ WriteFifo(send_fifo, &packet_type, 1);
+ WriteFifo(send_fifo, &packet_size, 2);
+ }
+ }
+
+ // IPC --> send_fifo or UDP accelerator
+ while (true)
+ {
+ BLOCK *l2_packet = IPCRecvL2(ipc);
+ UCHAR packet_type;
+ USHORT packet_size;
+ if (l2_packet == NULL)
+ {
+ break;
+ }
+ if (UdpAccelIsSendReady(udp_accel, true))
+ {
+ // Send via UDP accelerator
+ UdpAccelSend(udp_accel, l2_packet->Buf, l2_packet->Size,
+ MVPN_PACKET_TYPE_ETHERNET, udp_accel->MaxUdpPacketSize,
+ false);
+ }
+ else
+ {
+ // Send via WebSocket
+ if (FifoSize(send_fifo) <= MAX_BUFFERING_PACKET_SIZE)
+ {
+ packet_size = Endian16(l2_packet->Size);
+ packet_type = MVPN_PACKET_TYPE_ETHERNET;
+ WriteFifo(send_fifo, &magic_number, 4);
+ WriteFifo(send_fifo, &packet_type, 1);
+ WriteFifo(send_fifo, &packet_size, 2);
+ WriteFifo(send_fifo, l2_packet->Buf, (USHORT)l2_packet->Size);
+ }
+ }
+ FreeBlock(l2_packet);
+ }
+
+ // send_fifo --> MVPN Client
+ while (FifoSize(send_fifo) >= 1)
+ {
+ UINT r = WsSendAsync(w, ((UCHAR *)send_fifo->p) + send_fifo->pos, send_fifo->size);
+ if (r == 0)
+ {
+ has_error = true;
+ break;
+ }
+ else if (r == INFINITE)
+ {
+ break;
+ }
+ else
+ {
+ ReadFifo(send_fifo, NULL, r);
+ }
+ }
+
+ if (WsTrySendAsync(w) == false)
+ {
+ has_error = true;
+ }
+
+ // MVPN Client --> recv_fifo
+ while (FifoSize(recv_fifo) <= MAX_BUFFERING_PACKET_SIZE)
+ {
+ r = WsRecvAsync(w, tmp_buf, tmp_buf_size);
+ if (r == 0)
+ {
+ has_error = true;
+ break;
+ }
+ else if (r == INFINITE)
+ {
+ break;
+ }
+ else
+ {
+ //Debug("recv %u\n", r);
+ WriteFifo(recv_fifo, tmp_buf, r);
+ }
+ }
+
+ // recv_fifo --> IPC
+ while (true)
+ {
+ UINT u32;
+ UINT packet_size;
+ UCHAR packet_type;
+ UCHAR *packet_data;
+ if (FifoSize(recv_fifo) < 7)
+ {
+ break;
+ }
+ packet_size = READ_USHORT(FifoPtr(recv_fifo) + 5);
+ if (FifoSize(recv_fifo) < (7 + packet_size))
+ {
+ break;
+ }
+
+ ReadFifo(recv_fifo, &u32, 4);
+ if (u32 != magic_number)
+ {
+ break;
+ }
+
+ ReadFifo(recv_fifo, &packet_type, 1);
+ ReadFifo(recv_fifo, NULL, 2);
+
+ packet_data = Malloc(packet_size);
+
+ ReadFifo(recv_fifo, packet_data, packet_size);
+
+ if (packet_type == MVPN_PACKET_TYPE_ETHERNET)
+ {
+ IPCSendL2(ipc, packet_data, packet_size);
+ }
+
+ Free(packet_data);
+
+ last_comm_recv = now;
+ }
+
+ // UDP Accel --> IPC
+ if (udp_accel != NULL)
+ {
+ while (true)
+ {
+ UINT packet_size;
+ UCHAR packet_type;
+ UCHAR *packet_data;
+ BLOCK *b = GetNext(udp_accel->RecvBlockQueue);
+ if (b == NULL)
+ {
+ break;
+ }
+
+ packet_type = b->RawFlagRetUdpAccel;
+ packet_data = b->Buf;
+ packet_size = b->Size;
+
+ if (packet_type == MVPN_PACKET_TYPE_ETHERNET)
+ {
+ IPCSendL2(ipc, packet_data, packet_size);
+ }
+
+ FreeBlock(b);
+ }
+ }
+
+ if (IsIPCConnected(ipc) == false)
+ {
+ has_error = true;
+ }
+
+ if (now > (last_comm_recv + (UINT64)disconnect_timeout))
+ {
+ has_error = true;
+ }
+
+ IPCProcessInterrupts(ipc);
+
+ if (has_error)
+ {
+ break;
+ }
+
+ // Wait until the next event occurs
+ next_interval = GetNextIntervalForInterrupt(ipc->Interrupt);
+ next_interval = MIN(next_interval, SELECT_TIME);
+ next_interval = MIN(next_interval, (UINT)((last_sent_heartbeat + (UINT64)heartbeat_interval) - now));
+ WaitSockEvent(sock_event, next_interval);
+ }
+
+ ReleaseSockEvent(sock_event);
+ ReleaseFifo(send_fifo);
+ ReleaseFifo(recv_fifo);
+ Free(tmp_buf);
+ }
+ }
+
+LABEL_CLEANUP:
+ if (ret != ERR_NO_ERROR)
+ {
+ PACK *ret_pack = WsNewErrorPack(ret);
+ WsSendPack(w, ret_pack);
+ FreePack(ret_pack);
+ }
+ FreeUdpAccel(udp_accel);
+ FreeIPC(ipc);
+ FreePack(client_hello);
+ FreePack(server_hello);
+
+ return 0;
+}
+
+
+
+
+
+
+
+
diff --git a/src/Cedar/Protocol.h b/src/Cedar/Protocol.h
index 94db6240..3ee86867 100644
--- a/src/Cedar/Protocol.h
+++ b/src/Cedar/Protocol.h
@@ -105,6 +105,13 @@
#ifndef PROTOCOL_H
#define PROTOCOL_H
+// MIME types
+struct HTTP_MIME_TYPE
+{
+ char *Extension;
+ char *MimeType;
+};
+
// The parameters that will be passed to the certificate confirmation thread
struct CHECK_CERT_THREAD_PROC
{
@@ -195,6 +202,73 @@ struct UPDATE_CLIENT
#define PROTO_SUPPRESS_CLIENT_UPDATE_NOTIFICATION_REGKEY "Software\\" GC_REG_COMPANY_NAME "\\" CEDAR_PRODUCT_STR " VPN\\Client Update Notification"
#define PROTO_SUPPRESS_CLIENT_UPDATE_NOTIFICATION_REGVALUE "Suppress"
+// WebSocket
+struct WS
+{
+ SOCK *Sock;
+ WSP *Wsp;
+ REF *Ref;
+ bool Disconnected;
+ UINT MaxBufferSize;
+ UCHAR TmpBuf[65536];
+};
+
+// WebSocket Protocol
+struct WSP
+{
+ UINT MaxBufferSize;
+ FIFO *PhysicalSendFifo; // WSP -> Network
+ FIFO *PhysicalRecvFifo; // WSP <- Network
+ FIFO *AppSendFifo; // APP -> WSP
+ FIFO *AppRecvFifo; // APP <- WSP
+ bool HasError;
+};
+
+// WebSocket constants
+#define WS_MAX_PAYLOAD_LEN_PER_FRAME (8 * 1024 * 1024)
+#define WS_SEND_SINGLE_FRAGMENT_SIZE (32 * 1024)
+
+#define WS_OPCODE_CONTINUE 0x00
+#define WS_OPCODE_TEXT 0x01
+#define WS_OPCODE_BIN 0x02
+#define WS_OPCODE_CLOSE 0x08
+#define WS_OPCODE_PING 0x09
+#define WS_OPCODE_PONG 0x0A
+
+// MVPN constants
+#define MVPN_VERSION_MIN 100
+#define MVPN_VERSION_CURRENT 100
+#define MVPN_MAX_AUTH_RETRY 10
+#define MVPN_CLIENT_NAME "Modern VPN Client"
+#define NVPN_POSTFIX "MVPN"
+
+// MVPN protocol constants
+#define MVPN_AUTHTYPE_ANONYMOUS "anonymous"
+#define MVPN_AUTHTYPE_PASSWORD_PLAIN "password_plain"
+#define MVPN_AUTHTYPE_PASSWORD_MSCHAPV2 "password_mschapv2"
+#define MVPN_AUTHTYPE_CERT "x509cert"
+
+#define MVPN_HEARTBEAT_INTERVAL_DEFAULT 1234
+#define MVPN_HEARTBEAT_INTERVAL_MIN 100
+#define MVPN_HEARTBEAT_INTERVAL_MAX 15000
+
+#define MVPN_DISCONNECT_TIMEOUT_DEFAULT 15000
+#define MVPN_DISCONNECT_TIMEOUT_MIN 5000
+#define MVPN_DISCONNECT_TIMEOUT_MAX 60000
+
+#define MVPN_PACKET_MAGIC_NUMBER 0xCAFEBEEF
+#define MVPN_PACKET_TYPE_ETHERNET 0
+#define MVPN_PACKET_TYPE_IPV4 1
+#define MVPN_PACKET_TYPE_HEARTBEAT 254
+
+
+
+#define MVPN_AUTHTYPE_ALL_SUPPORTED MVPN_AUTHTYPE_ANONYMOUS "," MVPN_AUTHTYPE_PASSWORD_PLAIN "," MVPN_AUTHTYPE_PASSWORD_MSCHAPV2 "," MVPN_AUTHTYPE_CERT
+
+
+
+
+
// Function prototype
UPDATE_CLIENT *NewUpdateClient(UPDATE_NOTIFY_PROC *cb, UPDATE_ISFOREGROUND_PROC *isforeground_cb, void *param, char *family_name, char *software_name, wchar_t *software_title, UINT my_build, UINT64 my_date, char *my_lang, UPDATE_CLIENT_SETTING *current_setting, char *client_id);
void FreeUpdateClient(UPDATE_CLIENT *c);
@@ -233,6 +307,7 @@ PACK *PackLoginWithAnonymous(char *hubname, char *username);
PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password);
PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password);
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 GetHubnameAndUsernameFromPack(PACK *p, char *username, UINT username_size,
char *hubname, UINT hubname_size);
@@ -302,6 +377,36 @@ 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);
+char *GetMimeTypeFromFileName(char *filename);
+
+void MvpnProcGet(CONNECTION *c, SOCK *s, HTTP_HEADER *h, char *url_target);
+bool MvpnSendReply(SOCK *s, UINT status_code, char *status_string, UCHAR *data, UINT data_size, char *content_type,
+ char *add_header_name, char *add_header_value, HTTP_HEADER *request_headers);
+void MvpnAccept(CONNECTION *c, SOCK *s);
+UINT MvpnDoAccept(CONNECTION *c, WS *w);
+
+
+WS *NewWs(SOCK *s);
+void ReleaseWs(WS *w);
+void CleanupWs(WS *w);
+UINT WsRecvSync(WS *w, void *data, UINT size);
+bool WsRecvSyncAll(WS *w, void *data, UINT size);
+bool WsSendSync(WS *w, void *data, UINT size);
+UINT WsRecvAsync(WS *w, void *data, UINT size);
+UINT WsSendAsync(WS *w, void *data, UINT size);
+bool WsTrySendAsync(WS *w);
+PACK *WsRecvPack(WS *w);
+bool WsSendPack(WS *w, PACK *p);
+PACK *WsNewErrorPack(UINT err);
+char *WsErrorCodeToString(UINT err);
+
+WSP *NewWsp();
+void FreeWsp(WSP *p);
+void WspTry(WSP *p);
+BLOCK *WspTryRecvNextFrame(WSP *p, UINT *read_buffer_size);
+void WspTrySendFrame(WSP *p, UCHAR opcode, void *data, UINT size);
+
+
#endif // PROTOCOL_H
diff --git a/src/Cedar/Radius.c b/src/Cedar/Radius.c
index 689ef65b..bcbac5d4 100644
--- a/src/Cedar/Radius.c
+++ b/src/Cedar/Radius.c
@@ -314,11 +314,11 @@ bool SendPeapRawPacket(EAP_CLIENT *e, UCHAR *peap_data, UINT peap_size)
fragments = NewListFast(NULL);
for (num = 0;;num++)
{
- UCHAR tmp[1024];
+ UCHAR tmp[200];
EAP_PEAP *send_peap_message;
UINT sz;
- sz = ReadBuf(buf, tmp, 1024);
+ sz = ReadBuf(buf, tmp, sizeof(tmp));
if (sz == 0)
{
@@ -690,6 +690,11 @@ void EapSetRadiusGeneralAttributes(RADIUS_PACKET *r, EAP_CLIENT *e)
Add(r->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_NAS_ID, 0, 0, CEDAR_SERVER_STR, StrLen(CEDAR_SERVER_STR)));
+ if (IsEmptyStr(e->In_VpnProtocolState) == false)
+ {
+ Add(r->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_PROXY_STATE, 0, 0, e->In_VpnProtocolState, StrLen(e->In_VpnProtocolState)));
+ }
+
ui = Endian32(2);
Add(r->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT,
RADIUS_MS_NETWORK_ACCESS_SERVER_TYPE, &ui, sizeof(UINT)));
@@ -1011,11 +1016,27 @@ RADIUS_PACKET *EapSendPacketAndRecvResponse(EAP_CLIENT *e, RADIUS_PACKET *r)
{
RADIUS_AVP *eap_msg = GetRadiusAvp(rp, RADIUS_ATTRIBUTE_EAP_MESSAGE);
RADIUS_AVP *vlan_avp = GetRadiusAvp(rp, RADIUS_ATTRIBUTE_VLAN_ID);
+ RADIUS_AVP *framed_interface_id_avp = GetRadiusAvp(rp, RADIUS_ATTRIBUTE_FRAMED_INTERFACE_ID);
if (eap_msg != NULL)
{
e->LastRecvEapId = ((EAP_MESSAGE *)(eap_msg->Data))->Id;
}
+ if (framed_interface_id_avp != NULL)
+ {
+ // FRAMED_INTERFACE_ID
+ char tmp_str[64];
+ UCHAR mac_address[6];
+
+ Zero(tmp_str, sizeof(tmp_str));
+ Copy(tmp_str, framed_interface_id_avp->Data, MIN(framed_interface_id_avp->DataSize, sizeof(tmp_str) - 1));
+
+ if (StrToMac(mac_address, tmp_str))
+ {
+ Copy(e->LastRecvVirtualMacAddress, mac_address, 6);
+ }
+ }
+
if (vlan_avp != NULL)
{
// VLAN ID
@@ -1746,6 +1767,11 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec
// Try the EAP authentication for RADIUS first
EAP_CLIENT *eap = mschap.MsChapV2_EapClient;
+ if (IsEmptyStr(opt->In_VpnProtocolState) == false)
+ {
+ StrCpy(eap->In_VpnProtocolState, sizeof(eap->In_VpnProtocolState), opt->In_VpnProtocolState);
+ }
+
if (eap->PeapMode == false)
{
ret = EapClientSendMsChapv2AuthClientResponse(eap, mschap.MsChapV2_ClientResponse,
@@ -1766,6 +1792,8 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec
opt->Out_VLanId = eap->LastRecvVLanId;
}
+ Copy(opt->Out_VirtualMacAddress, eap->LastRecvVirtualMacAddress, 6);
+
return true;
}
else
@@ -1880,31 +1908,31 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec
// Service-Type
ui = Endian32(2);
- RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_SERVICE_TYPE, 0, 0, &ui, sizeof(ui));
// NAS-Port-Type
ui = Endian32(5);
- RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_NAS_PORT_TYPE, 0, 0, &ui, sizeof(ui));
// Tunnel-Type
ui = Endian32(1);
- RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_TYPE, 0, 0, &ui, sizeof(ui));
// Tunnel-Medium-Type
ui = Endian32(1);
- RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_MEDIUM_TYPE, 0, 0, &ui, sizeof(ui));
// Called-Station-ID - VPN Hub Name
if (IsEmptyStr(hubname) == false)
{
- RadiusAddValue(p, 30, 0, 0, hubname, StrLen(hubname));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_CALLED_STATION_ID, 0, 0, hubname, StrLen(hubname));
}
// Calling-Station-Id
- RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_CALLING_STATION_ID, 0, 0, client_ip_str, StrLen(client_ip_str));
// Tunnel-Client-Endpoint
- RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_CLIENT_ENDPOINT, 0, 0, client_ip_str, StrLen(client_ip_str));
}
else
{
@@ -1918,69 +1946,75 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec
// Acct-Session-Id
us = Endian16(session_id % 254 + 1);
session_id++;
- RadiusAddValue(p, 44, 0, 0, &us, sizeof(us));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_ACCT_SESSION_ID, 0, 0, &us, sizeof(us));
// NAS-IP-Address
if (c != NULL && c->FirstSock != NULL && c->FirstSock->IPv6 == false)
{
ui = IPToUINT(&c->FirstSock->LocalIP);
- RadiusAddValue(p, 4, 0, 0, &ui, sizeof(ui));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_NAS_IP, 0, 0, &ui, sizeof(ui));
}
// Service-Type
ui = Endian32(2);
- RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_SERVICE_TYPE, 0, 0, &ui, sizeof(ui));
// MS-RAS-Vendor
- ui = Endian32(311);
- RadiusAddValue(p, 26, 311, 9, &ui, sizeof(ui));
+ ui = Endian32(RADIUS_VENDOR_MICROSOFT);
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_RAS_VENDOR, &ui, sizeof(ui));
// MS-RAS-Version
- RadiusAddValue(p, 26, 311, 18, ms_ras_version, StrLen(ms_ras_version));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_VERSION, ms_ras_version, StrLen(ms_ras_version));
// NAS-Port-Type
ui = Endian32(5);
- RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_NAS_PORT_TYPE, 0, 0, &ui, sizeof(ui));
// Tunnel-Type
ui = Endian32(1);
- RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_TYPE, 0, 0, &ui, sizeof(ui));
// Tunnel-Medium-Type
ui = Endian32(1);
- RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_MEDIUM_TYPE, 0, 0, &ui, sizeof(ui));
// Called-Station-ID - VPN Hub Name
if (IsEmptyStr(hubname) == false)
{
- RadiusAddValue(p, 30, 0, 0, hubname, StrLen(hubname));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_CALLED_STATION_ID, 0, 0, hubname, StrLen(hubname));
}
// Calling-Station-Id
- RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_CALLING_STATION_ID, 0, 0, client_ip_str, StrLen(client_ip_str));
// Tunnel-Client-Endpoint
- RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_CLIENT_ENDPOINT, 0, 0, client_ip_str, StrLen(client_ip_str));
// MS-RAS-Client-Version
- RadiusAddValue(p, 26, 311, 35, ms_ras_version, StrLen(ms_ras_version));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_RAS_CLIENT_VERSION, ms_ras_version, StrLen(ms_ras_version));
// MS-RAS-Client-Name
- RadiusAddValue(p, 26, 311, 34, client_ip_str, StrLen(client_ip_str));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_RAS_CLIENT_NAME, client_ip_str, StrLen(client_ip_str));
// MS-CHAP-Challenge
- RadiusAddValue(p, 26, 311, 11, mschap.MsChapV2_ServerChallenge, sizeof(mschap.MsChapV2_ServerChallenge));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_CHAP_CHALLENGE, mschap.MsChapV2_ServerChallenge, sizeof(mschap.MsChapV2_ServerChallenge));
// MS-CHAP2-Response
Zero(ms_chapv2_response, sizeof(ms_chapv2_response));
Copy(ms_chapv2_response + 2, mschap.MsChapV2_ClientChallenge, 16);
Copy(ms_chapv2_response + 2 + 16 + 8, mschap.MsChapV2_ClientResponse, 24);
- RadiusAddValue(p, 26, 311, 25, ms_chapv2_response, sizeof(ms_chapv2_response));
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_CHAP2_RESPONSE, ms_chapv2_response, sizeof(ms_chapv2_response));
// NAS-ID
WriteBuf(p, nas_id->Buf, nas_id->Size);
}
+ if (IsEmptyStr(opt->In_VpnProtocolState) == false)
+ {
+ // Proxy state as protocol details
+ RadiusAddValue(p, RADIUS_ATTRIBUTE_PROXY_STATE, 0, 0, opt->In_VpnProtocolState, StrLen(opt->In_VpnProtocolState));
+ }
+
SeekBuf(p, 0, 0);
WRITE_USHORT(((UCHAR *)p->Buf) + 2, (USHORT)p->Size);
@@ -2071,6 +2105,9 @@ RECV_RETRY:
// Success
if (recv_buf[0] == 2)
{
+ LIST *o;
+ BUF *buf = NewBufFromMemory(recv_buf, recv_size);
+
ret = true;
if (is_mschap && mschap_v2_server_response_20 != NULL)
@@ -2108,12 +2145,26 @@ RECV_RETRY:
}
}
- if (opt->In_CheckVLanId)
+ o = RadiusParseOptions(buf);
+ if (o != NULL)
{
- BUF *buf = NewBufFromMemory(recv_buf, recv_size);
- LIST *o = RadiusParseOptions(buf);
+ DHCP_OPTION *framed_interface_id_option = GetDhcpOption(o, RADIUS_ATTRIBUTE_FRAMED_INTERFACE_ID);
- if (o != NULL)
+ if (framed_interface_id_option != NULL)
+ {
+ char tmp_str[64];
+ UCHAR mac_address[6];
+
+ Zero(tmp_str, sizeof(tmp_str));
+ Copy(tmp_str, framed_interface_id_option->Data, MIN(framed_interface_id_option->Size, sizeof(tmp_str) - 1));
+
+ if (StrToMac(mac_address, tmp_str))
+ {
+ Copy(opt->Out_VirtualMacAddress, mac_address, 6);
+ }
+ }
+
+ if (opt->In_CheckVLanId)
{
DHCP_OPTION *vlan_option = GetDhcpOption(o, RADIUS_ATTRIBUTE_VLAN_ID);
@@ -2132,9 +2183,10 @@ RECV_RETRY:
}
}
- FreeBuf(buf);
FreeDhcpOptions(o);
}
+
+ FreeBuf(buf);
}
break;
}
diff --git a/src/Cedar/Radius.h b/src/Cedar/Radius.h
index 286f24a8..712b6003 100644
--- a/src/Cedar/Radius.h
+++ b/src/Cedar/Radius.h
@@ -133,6 +133,7 @@
#define RADIUS_ATTRIBUTE_EAP_MESSAGE 79
#define RADIUS_ATTRIBUTE_EAP_AUTHENTICATOR 80
#define RADIUS_ATTRIBUTE_VLAN_ID 81
+#define RADIUS_ATTRIBUTE_FRAMED_INTERFACE_ID 96
#define RADIUS_MAX_NAS_ID_LEN 253
// RADIUS codes
@@ -327,6 +328,9 @@ struct EAP_CLIENT
UCHAR RecvLastCode;
UINT LastRecvVLanId;
+ UCHAR LastRecvVirtualMacAddress[6];
+
+ char In_VpnProtocolState[64];
};
void FreeRadiusPacket(RADIUS_PACKET *p);
@@ -365,6 +369,8 @@ struct RADIUS_LOGIN_OPTION
UINT Out_VLanId;
bool Out_IsRadiusLogin;
char NasId[RADIUS_MAX_NAS_ID_LEN + 1]; // NAS-Identifier
+ char Out_VirtualMacAddress[6];
+ char In_VpnProtocolState[64];
};
// Function prototype
diff --git a/src/Cedar/Remote.c b/src/Cedar/Remote.c
index cbcae112..5cc45630 100644
--- a/src/Cedar/Remote.c
+++ b/src/Cedar/Remote.c
@@ -113,13 +113,21 @@ void EndRpc(RPC *rpc)
// Release the RPC
void RpcFree(RPC *rpc)
{
+ RpcFreeEx(rpc, false);
+}
+void RpcFreeEx(RPC *rpc, bool no_disconnect)
+{
// Validate arguments
if (rpc == NULL)
{
return;
}
- Disconnect(rpc->Sock);
+ if (no_disconnect == false)
+ {
+ Disconnect(rpc->Sock);
+ }
+
ReleaseSock(rpc->Sock);
DeleteLock(rpc->Lock);
diff --git a/src/Cedar/Remote.h b/src/Cedar/Remote.h
index 4052c678..b0b6be3c 100644
--- a/src/Cedar/Remote.h
+++ b/src/Cedar/Remote.h
@@ -139,6 +139,7 @@ bool RpcIsOk(PACK *p);
UINT RpcGetError(PACK *p);
void EndRpc(RPC *rpc);
void RpcFree(RPC *rpc);
+void RpcFreeEx(RPC *rpc, bool no_disconnect);
#endif // REMOTE_H
diff --git a/src/Cedar/SM.c b/src/Cedar/SM.c
index 26b957d9..8741c505 100644
--- a/src/Cedar/SM.c
+++ b/src/Cedar/SM.c
@@ -3639,6 +3639,16 @@ void SmLicenseAddDlgOnOk(HWND hWnd, SM_SERVER *s)
{
RPC_TEST t;
+ if (s->LicenseWarnFlag == false)
+ {
+ if (MsgBoxEx(hWnd, MB_ICONINFORMATION | MB_OKCANCEL, _UU("SM_LICENSE_WARNING")) == IDCANCEL)
+ {
+ return;
+ }
+
+ s->LicenseWarnFlag = true;
+ }
+
Disable(hWnd, IDOK);
Disable(hWnd, IDCANCEL);
diff --git a/src/Cedar/SMInner.h b/src/Cedar/SMInner.h
index f8d09b17..b9982ded 100644
--- a/src/Cedar/SMInner.h
+++ b/src/Cedar/SMInner.h
@@ -166,6 +166,7 @@ typedef struct SM_SERVER
bool VgsMessageDisplayed; // Whether to have already displayed a message about VGS
WINUI_UPDATE *Update; // Update notification
bool IsInClient; // Within VPN Client mode
+ bool LicenseWarnFlag;
} SM_SERVER;
typedef void (SM_STATUS_INIT_PROC)(HWND hWnd, SM_SERVER *p, void *param);
diff --git a/src/Cedar/SW.c b/src/Cedar/SW.c
index f022dd90..e1f7ef62 100644
--- a/src/Cedar/SW.c
+++ b/src/Cedar/SW.c
@@ -5732,6 +5732,15 @@ UINT SwWelcomeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wiz
break;
}
+ if (MsIsKB3033929RequiredAndMissing())
+ {
+ // KB3033929 is missing
+ if (MsgBoxEx(hWnd, MB_ICONINFORMATION | MB_OKCANCEL, _UU("SW_KB3033929_REQUIRED")) == IDCANCEL)
+ {
+ break;
+ }
+ }
+
if (sw->DoubleClickBlocker)
{
break;
diff --git a/src/Cedar/Server.c b/src/Cedar/Server.c
index 98bfa571..31f4cb67 100644
--- a/src/Cedar/Server.c
+++ b/src/Cedar/Server.c
@@ -1115,52 +1115,72 @@ LIST *EnumLogFile(char *hubname)
// Enumerate in the packet_log
Format(tmp, sizeof(tmp), "%s/packet_log", exe_dir);
- dir = EnumDir(tmp);
- if (dir != NULL)
+
+ if (hubname == NULL)
{
- UINT i;
- for (i = 0;i < dir->NumFiles;i++)
+ dir = EnumDir(tmp);
+ if (dir != NULL)
{
- DIRENT *e = dir->File[i];
-
- if (e->Folder)
+ UINT i;
+ for (i = 0;i < dir->NumFiles;i++)
{
- char dir_name[MAX_PATH];
+ DIRENT *e = dir->File[i];
- if (hubname == NULL || StrCmpi(hubname, e->FileName) == 0)
+ if (e->Folder)
{
+ char dir_name[MAX_PATH];
+
Format(dir_name, sizeof(dir_name), "packet_log/%s", e->FileName);
+
EnumLogFileDir(o, dir_name);
}
}
+
+ FreeDir(dir);
}
+ }
+ else
+ {
+ char dir_name[MAX_PATH];
+
+ Format(dir_name, sizeof(dir_name), "packet_log/%s", hubname);
- FreeDir(dir);
+ EnumLogFileDir(o, dir_name);
}
// Enumerate in the security_log
Format(tmp, sizeof(tmp), "%s/security_log", exe_dir);
- dir = EnumDir(tmp);
- if (dir != NULL)
+
+ if (hubname == NULL)
{
- UINT i;
- for (i = 0;i < dir->NumFiles;i++)
+ dir = EnumDir(tmp);
+ if (dir != NULL)
{
- DIRENT *e = dir->File[i];
-
- if (e->Folder)
+ UINT i;
+ for (i = 0;i < dir->NumFiles;i++)
{
- char dir_name[MAX_PATH];
+ DIRENT *e = dir->File[i];
- if (hubname == NULL || StrCmpi(hubname, e->FileName) == 0)
+ if (e->Folder)
{
+ char dir_name[MAX_PATH];
+
Format(dir_name, sizeof(dir_name), "security_log/%s", e->FileName);
+
EnumLogFileDir(o, dir_name);
}
}
+
+ FreeDir(dir);
}
+ }
+ else
+ {
+ char dir_name[MAX_PATH];
- FreeDir(dir);
+ Format(dir_name, sizeof(dir_name), "security_log/%s", hubname);
+
+ EnumLogFileDir(o, dir_name);
}
return o;
@@ -1871,14 +1891,37 @@ void OutRpcCapsList(PACK *p, CAPSLIST *t)
return;
}
+ PackSetCurrentJsonGroupName(p, "CapsList");
for (i = 0;i < LIST_NUM(t->CapsList);i++)
{
char tmp[MAX_SIZE];
+ char ct_key[MAX_PATH];
+ wchar_t ct_description[MAX_PATH];
+ wchar_t *w;
CAPS *c = LIST_DATA(t->CapsList, i);
Format(tmp, sizeof(tmp), "caps_%s", c->Name);
+
+ Format(ct_key, sizeof(ct_key), "CT_%s", c->Name);
+
+ Zero(ct_description, sizeof(ct_description));
+ w = _UU(ct_key);
+ if (UniIsEmptyStr(w) == false)
+ {
+ UniStrCpy(ct_description, sizeof(ct_description), w);
+ }
+ else
+ {
+ StrToUni(ct_description, sizeof(ct_description), c->Name);
+ }
+
PackAddInt(p, tmp, c->Value);
+
+ PackAddStrEx(p, "CapsName", c->Name, i, LIST_NUM(t->CapsList));
+ PackAddIntEx(p, "CapsValue", c->Value, i, LIST_NUM(t->CapsList));
+ PackAddUniStrEx(p, "CapsDescrption", ct_description, i, LIST_NUM(t->CapsList));
}
+ PackSetCurrentJsonGroupName(p, NULL);
}
void FreeRpcCapsList(CAPSLIST *t)
{
@@ -6167,6 +6210,9 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
c->SslAcceptSettings.Tls_Disable1_2 = CfgGetBool(f, "Tls_Disable1_2");
s->StrictSyslogDatetimeFormat = CfgGetBool(f, "StrictSyslogDatetimeFormat");
+
+ // Disable JSON-RPC Web API
+ s->DisableJsonRpcWebApi = CfgGetBool(f, "DisableJsonRpcWebApi");
}
Unlock(c->lock);
@@ -6484,6 +6530,9 @@ void SiWriteServerCfg(FOLDER *f, SERVER *s)
CfgAddBool(f, "DisableSessionReconnect", GetGlobalServerFlag(GSF_DISABLE_SESSION_RECONNECT));
CfgAddBool(f, "StrictSyslogDatetimeFormat", s->StrictSyslogDatetimeFormat);
+
+ // Disable JSON-RPC Web API
+ CfgAddBool(f, "DisableJsonRpcWebApi", s->DisableJsonRpcWebApi);
}
Unlock(c->lock);
}
@@ -7211,7 +7260,7 @@ FARM_MEMBER *SiGetNextFarmMember(SERVER *s, CONNECTION *c, HUB *h)
PackAddIntEx(p, "NumTcpConnections", f->NumTcpConnections, i, num);
PackAddIntEx(p, "NumHubs", LIST_NUM(f->HubList), i, num);
PackAddBoolEx(p, "Me", f->Me, i, num);
- PackAddInt64Ex(p, "ConnectedTime", f->ConnectedTime, i, num);
+ PackAddTime64Ex(p, "ConnectedTime", f->ConnectedTime, i, num);
PackAddInt64Ex(p, "SystemId", f->SystemId, i, num);
PackAddBoolEx(p, "DoNotSelect", do_not_select, i, num);
}
@@ -7240,7 +7289,7 @@ FARM_MEMBER *SiGetNextFarmMember(SERVER *s, CONNECTION *c, HUB *h)
PackAddStr(p, "CipherName", c->CipherName);
PackAddStr(p, "ClientStr", c->ClientStr);
PackAddInt(p, "ClientVer", c->ClientVer);
- PackAddInt64(p, "ConnectedTime", Tick64ToTime64(c->ConnectedTick));
+ PackAddTime64(p, "ConnectedTime", Tick64ToTime64(c->ConnectedTick));
PackAddStr(p, "HubName", h->Name);
PackAddBool(p, "StaticHub", h->Type == HUB_TYPE_FARM_STATIC);
@@ -7381,8 +7430,8 @@ void SiCalledEnumHub(SERVER *s, PACK *p, PACK *req)
PackAddIntEx(p, "NumIpTables", LIST_NUM(h->IpTable), i, num);
- PackAddInt64Ex(p, "LastCommTime", h->LastCommTime, i, num);
- PackAddInt64Ex(p, "CreatedTime", h->CreatedTime, i, num);
+ PackAddTime64Ex(p, "LastCommTime", h->LastCommTime, i, num);
+ PackAddTime64Ex(p, "CreatedTime", h->CreatedTime, i, num);
}
Unlock(h->lock);
}
@@ -10309,12 +10358,16 @@ void SiFarmServMain(SERVER *server, SOCK *sock, FARM_MEMBER *f)
}
// Receive
- p = HttpServerRecv(sock);
+ p = HttpServerRecvEx(sock, FIRM_SERV_RECV_PACK_MAX_SIZE);
t->Response = p;
Set(t->CompleteEvent);
- send_noop = false;
+ if (p == NULL)
+ {
+ Disconnect(sock);
+ goto DISCONNECTED;
+ }
}
}
while (t != NULL);
diff --git a/src/Cedar/Server.h b/src/Cedar/Server.h
index 55bf6016..4618eee5 100644
--- a/src/Cedar/Server.h
+++ b/src/Cedar/Server.h
@@ -147,6 +147,8 @@ extern char *SERVER_CONFIG_FILE_NAME;
#define MEMBER_SELECTOR_CONNECT_TIMEOUT 2000
#define MEMBER_SELECTOR_DATA_TIMEOUT 5000
+#define FIRM_SERV_RECV_PACK_MAX_SIZE (100 * 1024 * 1024)
+
// Virtual HUB list hosted by each farm member
struct HUB_LIST
@@ -360,6 +362,7 @@ struct SERVER
volatile UINT NatTGlobalUdpPort; // NAT-T global UDP port
bool StrictSyslogDatetimeFormat; // Make syslog datetime format strict RFC3164
+ bool DisableJsonRpcWebApi; // Disable JSON-RPC Web API
};
@@ -383,6 +386,7 @@ struct RPC_SESSION_STATUS
RPC_CLIENT_GET_CONNECTION_STATUS Status; // Status
UINT ClientIp; // Client IP address
UCHAR ClientIp6[16]; // Client IPv6 address
+ IP ClientIpAddress; // Client IP address (IPv4/IPv6)
char ClientHostName[MAX_HOST_NAME_LEN + 1]; // Client host name
NODE_INFO NodeInfo; // Node information
};
diff --git a/src/Cedar/Session.c b/src/Cedar/Session.c
index 5116ff70..6a44a1ab 100644
--- a/src/Cedar/Session.c
+++ b/src/Cedar/Session.c
@@ -1257,7 +1257,10 @@ void StopSessionEx(SESSION *s, bool no_wait)
// Client mode
if (s->Connection)
{
- StopConnection(s->Connection, no_wait);
+ CONNECTION *c = s->Connection;
+ AddRef(c->ref);
+ StopConnection(c, no_wait);
+ ReleaseConnection(c);
}
}
else
@@ -1265,7 +1268,10 @@ void StopSessionEx(SESSION *s, bool no_wait)
// Server mode
if (s->Connection)
{
- StopConnection(s->Connection, no_wait);
+ CONNECTION *c = s->Connection;
+ AddRef(c->ref);
+ StopConnection(c, no_wait);
+ ReleaseConnection(c);
}
}
@@ -1391,6 +1397,8 @@ void CleanupSession(SESSION *s)
DeleteCounter(s->LoggingRecordCount);
+ ReleaseSharedBuffer(s->IpcSessionSharedBuffer);
+
Free(s);
}
@@ -2199,9 +2207,9 @@ void if_free(SESSION *s);
// Create a server session
SESSION *NewServerSession(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy)
{
- return NewServerSessionEx(cedar, c, h, username, policy, false);
+ return NewServerSessionEx(cedar, c, h, username, policy, false, NULL);
}
-SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy, bool inproc_mode)
+SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy, bool inproc_mode, UCHAR *ipc_mac_address)
{
SESSION *s;
char name[MAX_SIZE];
@@ -2322,28 +2330,35 @@ SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username,
// Generate a MAC address for IPC
if (s->InProcMode)
{
- char tmp[MAX_SIZE];
- char machine[MAX_SIZE];
- UCHAR hash[SHA1_SIZE];
+ if (ipc_mac_address != NULL)
+ {
+ Copy(s->IpcMacAddress, ipc_mac_address, 6);
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+ char machine[MAX_SIZE];
+ UCHAR hash[SHA1_SIZE];
- GetMachineName(machine, sizeof(machine));
+ GetMachineName(machine, sizeof(machine));
- Format(tmp, sizeof(tmp), "%s@%s@%u", machine, h->Name, s->UniqueId);
+ Format(tmp, sizeof(tmp), "%s@%s@%u", machine, h->Name, s->UniqueId);
- StrUpper(tmp);
- Trim(tmp);
+ StrUpper(tmp);
+ Trim(tmp);
- Hash(hash, tmp, StrLen(tmp), true);
+ Hash(hash, tmp, StrLen(tmp), true);
- s->IpcMacAddress[0] = 0xCA;
- s->IpcMacAddress[1] = hash[1];
- s->IpcMacAddress[2] = hash[2];
- s->IpcMacAddress[3] = hash[3];
- s->IpcMacAddress[4] = hash[4];
- s->IpcMacAddress[5] = hash[5];
+ s->IpcMacAddress[0] = 0xCA;
+ s->IpcMacAddress[1] = hash[1];
+ s->IpcMacAddress[2] = hash[2];
+ s->IpcMacAddress[3] = hash[3];
+ s->IpcMacAddress[4] = hash[4];
+ s->IpcMacAddress[5] = hash[5];
- MacToStr(tmp, sizeof(tmp), s->IpcMacAddress);
- Debug("MAC Address for IPC: %s\n", tmp);
+ MacToStr(tmp, sizeof(tmp), s->IpcMacAddress);
+ Debug("MAC Address for IPC: %s\n", tmp);
+ }
}
return s;
diff --git a/src/Cedar/Session.h b/src/Cedar/Session.h
index 4a74b0f8..d2704994 100644
--- a/src/Cedar/Session.h
+++ b/src/Cedar/Session.h
@@ -256,6 +256,7 @@ struct SESSION
UINT NumDisconnected; // Number of socket disconnection
bool NoReconnectToSession; // Disable to reconnect to the session
char UnderlayProtocol[64]; // Physical communication protocol
+ char ProtocolDetails[256]; // Protocol Details
UINT64 FirstConnectionEstablisiedTime; // Connection completion time of the first connection
UINT64 CurrentConnectionEstablishTime; // Completion time of this connection
UINT NumConnectionsEatablished; // Number of connections established so far
@@ -265,10 +266,12 @@ struct SESSION
bool IsRUDPSession; // Whether R-UDP session
UINT RUdpMss; // The value of the MSS should be applied while the R-UDP is used
bool EnableBulkOnRUDP; // Allow the bulk transfer in the R-UDP session
+ UINT BulkOnRUDPVersion; // RUDP Bulk Version
bool EnableHMacOnBulkOfRUDP; // Use the HMAC to sign the bulk transfer of R-UDP session
bool EnableUdpRecovery; // Enable the R-UDP recovery
bool UseUdpAcceleration; // Use of UDP acceleration mode
+ UINT UdpAccelerationVersion; // UDP acceleration version
bool UseHMacOnUdpAcceleration; // Use the HMAC in the UDP acceleration mode
UDP_ACCEL *UdpAccel; // UDP acceleration
bool IsUsingUdpAcceleration; // Flag of whether the UDP acceleration is used
@@ -308,6 +311,11 @@ struct SESSION
char FirstTimeHttpRedirectUrl[128]; // URL for redirection only the first time
UINT FirstTimeHttpAccessCheckIp; // IP address for access checking
+ UCHAR BulkSendKey[RUDP_BULK_KEY_SIZE_MAX]; // RUDP Bulk Send Key
+ UINT BulkSendKeySize; // RUDP Bulk Send Key size
+ UCHAR BulkRecvKey[RUDP_BULK_KEY_SIZE_MAX]; // RUDP Bulk Recv Key
+ UINT BulkRecvKeySize; // RUDP Bulk Recv Key size
+
// To examine the maximum number of alowed logging target packets per minute
UINT64 MaxLoggedPacketsPerMinuteStartTick; // Inspection start time
UINT CurrentNumPackets; // Current number of packets
@@ -315,6 +323,9 @@ struct SESSION
// Measures for D-Link bug
UINT64 LastDLinkSTPPacketSendTick; // Last D-Link STP packet transmission time
UCHAR LastDLinkSTPPacketDataHash[MD5_SIZE]; // Last D-Link STP packet hash
+
+ SHARED_BUFFER *IpcSessionSharedBuffer; // A shared buffer between IPC and Session
+ IPC_SESSION_SHARED_BUFFER_DATA *IpcSessionShared; // A shared data between IPC and Session
};
// Password dialog
@@ -396,7 +407,7 @@ SESSION *NewRpcSession(CEDAR *cedar, CLIENT_OPTION *option);
SESSION *NewRpcSessionEx(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str);
SESSION *NewRpcSessionEx2(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str, void *hWnd);
SESSION *NewServerSession(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy);
-SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy, bool inproc_mode);
+SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy, bool inproc_mode, UCHAR *ipc_mac_address);
void ClientThread(THREAD *t, void *param);
void ReleaseSession(SESSION *s);
void CleanupSession(SESSION *s);
diff --git a/src/Cedar/UdpAccel.c b/src/Cedar/UdpAccel.c
index a9597bf7..dc9b0c33 100644
--- a/src/Cedar/UdpAccel.c
+++ b/src/Cedar/UdpAccel.c
@@ -350,7 +350,7 @@ void UdpAccelSendBlock(UDP_ACCEL *a, BLOCK *b)
return;
}
- UdpAccelSend(a, b->Buf, b->Size, b->Compressed, a->MaxUdpPacketSize, b->PriorityQoS);
+ UdpAccelSend(a, b->Buf, b->Size, b->Compressed ? 1 : 0, a->MaxUdpPacketSize, b->PriorityQoS);
}
// Calculate the best MSS
@@ -382,7 +382,7 @@ UINT UdpAccelCalcMss(UDP_ACCEL *a)
if (a->PlainTextMode == false)
{
// IV
- ret -= UDP_ACCELERATION_PACKET_IV_SIZE;
+ ret -= UDP_ACCELERATION_PACKET_IV_SIZE_V1;
}
// Cookie
@@ -403,7 +403,7 @@ UINT UdpAccelCalcMss(UDP_ACCEL *a)
if (a->PlainTextMode == false)
{
// Verify
- ret -= UDP_ACCELERATION_PACKET_IV_SIZE;
+ ret -= UDP_ACCELERATION_PACKET_IV_SIZE_V1;
}
// Ethernet header (communication packets)
@@ -419,12 +419,12 @@ UINT UdpAccelCalcMss(UDP_ACCEL *a)
}
// Send
-void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, bool compressed, UINT max_size, bool high_priority)
+void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, UCHAR flag, UINT max_size, bool high_priority)
{
UCHAR tmp[UDP_ACCELERATION_TMP_BUF_SIZE];
UCHAR *buf;
UINT size;
- UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE];
+ UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE_V1];
UINT64 ui64;
USHORT us;
UCHAR c;
@@ -448,27 +448,40 @@ void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, bool compressed, UI
// IV
if (a->PlainTextMode == false)
{
- // IV
- Copy(buf, a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE);
+ if (a->Version == 2)
+ {
+ // Version 2.0
+ // IV
+ Copy(buf, a->NextIv_V2, UDP_ACCELERATION_PACKET_IV_SIZE_V2);
+
+ buf += UDP_ACCELERATION_PACKET_IV_SIZE_V2;
+ size += UDP_ACCELERATION_PACKET_IV_SIZE_V2;
+ }
+ else
+ {
+ // Version 1.0
+ // IV
+ Copy(buf, a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
- buf += UDP_ACCELERATION_PACKET_IV_SIZE;
- size += UDP_ACCELERATION_PACKET_IV_SIZE;
+ buf += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
+ size += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
- // Calculate the key
- UdpAccelCalcKey(key, a->MyKey, a->NextIv);
+ // Calculate the key
+ UdpAccelCalcKey(key, a->MyKey, a->NextIv);
- if (false)
- {
- char tmp1[256];
- char tmp2[256];
- char tmp3[256];
- BinToStr(tmp1, sizeof(tmp1), a->MyKey, sizeof(a->MyKey));
- BinToStr(tmp2, sizeof(tmp2), a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE);
- BinToStr(tmp3, sizeof(tmp3), key, sizeof(key));
- Debug("My Key : %s\n"
- "IV : %s\n"
- "Comm Key: %s\n",
- tmp1, tmp2, tmp3);
+ if (false)
+ {
+ char tmp1[256];
+ char tmp2[256];
+ char tmp3[256];
+ BinToStr(tmp1, sizeof(tmp1), a->MyKey, sizeof(a->MyKey));
+ BinToStr(tmp2, sizeof(tmp2), a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
+ BinToStr(tmp3, sizeof(tmp3), key, sizeof(key));
+ Debug("My Key : %s\n"
+ "IV : %s\n"
+ "Comm Key: %s\n",
+ tmp1, tmp2, tmp3);
+ }
}
}
@@ -496,8 +509,8 @@ void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, bool compressed, UI
buf += sizeof(USHORT);
size += sizeof(USHORT);
- // Compress Flag
- c = (compressed ? 1 : 0);
+ // Flag
+ c = flag;
Copy(buf, &c, sizeof(UCHAR));
buf += sizeof(UCHAR);
size += sizeof(UCHAR);
@@ -512,37 +525,74 @@ void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, bool compressed, UI
if (a->PlainTextMode == false)
{
- static UCHAR zero[UDP_ACCELERATION_PACKET_IV_SIZE] = {0};
- CRYPT *c;
-
- current_size = UDP_ACCELERATION_PACKET_IV_SIZE + sizeof(UINT) + sizeof(UINT64) * 2 +
- sizeof(USHORT) + sizeof(UCHAR) + data_size + UDP_ACCELERATION_PACKET_IV_SIZE;
-
- if (current_size < max_size)
+ if (a->Version == 2)
{
+ // Ver 2
// Padding
- UCHAR pad[UDP_ACCELERATION_MAX_PADDING_SIZE];
- UINT pad_size = MIN(max_size - current_size, UDP_ACCELERATION_MAX_PADDING_SIZE);
- pad_size = rand() % pad_size;
+ current_size = UDP_ACCELERATION_PACKET_IV_SIZE_V2 + sizeof(UINT) + sizeof(UINT64) * 2 +
+ sizeof(USHORT) + sizeof(UCHAR) + data_size + UDP_ACCELERATION_PACKET_MAC_SIZE_V2;
- Zero(pad, sizeof(pad));
- Copy(buf, pad, pad_size);
- buf += pad_size;
- size += pad_size;
+ if (current_size < max_size)
+ {
+ UCHAR pad[UDP_ACCELERATION_MAX_PADDING_SIZE];
+ UINT pad_size = MIN(max_size - current_size, UDP_ACCELERATION_MAX_PADDING_SIZE);
+ pad_size = rand() % pad_size;
+ Zero(pad, sizeof(pad));
+ Copy(buf, pad, pad_size);
+ buf += pad_size;
+ size += pad_size;
+ }
+
+ // Encryption by RFC 8439: ChaCha20-Poly1305-IETF Encryption with AEAD
+ Aead_ChaCha20Poly1305_Ietf_Encrypt(tmp + UDP_ACCELERATION_PACKET_IV_SIZE_V2,
+ tmp + UDP_ACCELERATION_PACKET_IV_SIZE_V2,
+ size - UDP_ACCELERATION_PACKET_IV_SIZE_V2,
+ a->MyKey_V2,
+ a->NextIv_V2,
+ NULL, 0);
+
+ // Next Iv
+ Copy(a->NextIv_V2,
+ tmp + UDP_ACCELERATION_PACKET_IV_SIZE_V2 + size - UDP_ACCELERATION_PACKET_IV_SIZE_V2 - UDP_ACCELERATION_PACKET_IV_SIZE_V2, UDP_ACCELERATION_PACKET_IV_SIZE_V2);
+
+ // MAC
+ size += UDP_ACCELERATION_PACKET_MAC_SIZE_V2;
}
+ else
+ {
+ // Ver 1
+ static UCHAR zero[UDP_ACCELERATION_PACKET_IV_SIZE_V1] = {0};
+ CRYPT *c;
- // Verify
- Copy(buf, zero, UDP_ACCELERATION_PACKET_IV_SIZE);
- buf += UDP_ACCELERATION_PACKET_IV_SIZE;
- size += UDP_ACCELERATION_PACKET_IV_SIZE;
+ current_size = UDP_ACCELERATION_PACKET_IV_SIZE_V1 + sizeof(UINT) + sizeof(UINT64) * 2 +
+ sizeof(USHORT) + sizeof(UCHAR) + data_size + UDP_ACCELERATION_PACKET_IV_SIZE_V1;
+
+ if (current_size < max_size)
+ {
+ // Padding
+ UCHAR pad[UDP_ACCELERATION_MAX_PADDING_SIZE];
+ UINT pad_size = MIN(max_size - current_size, UDP_ACCELERATION_MAX_PADDING_SIZE);
+ pad_size = rand() % pad_size;
+
+ Zero(pad, sizeof(pad));
+ Copy(buf, pad, pad_size);
+ buf += pad_size;
+ size += pad_size;
+ }
+
+ // Verify
+ Copy(buf, zero, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
+ buf += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
+ size += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
- // Encryption
- c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE);
- Encrypt(c, tmp + UDP_ACCELERATION_PACKET_IV_SIZE, tmp + UDP_ACCELERATION_PACKET_IV_SIZE, size - UDP_ACCELERATION_PACKET_IV_SIZE);
- FreeCrypt(c);
+ // Encryption
+ c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE_V1);
+ Encrypt(c, tmp + UDP_ACCELERATION_PACKET_IV_SIZE_V1, tmp + UDP_ACCELERATION_PACKET_IV_SIZE_V1, size - UDP_ACCELERATION_PACKET_IV_SIZE_V1);
+ FreeCrypt(c);
- // Next Iv
- Copy(a->NextIv, buf - UDP_ACCELERATION_PACKET_IV_SIZE, UDP_ACCELERATION_PACKET_IV_SIZE);
+ // Next Iv
+ Copy(a->NextIv, buf - UDP_ACCELERATION_PACKET_IV_SIZE_V1, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
+ }
}
// Send
@@ -667,7 +717,7 @@ bool UdpAccelIsSendReady(UDP_ACCEL *a, bool check_keepalive)
// Process the received packet
BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip, UINT src_port)
{
- UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE];
+ UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE_V1];
UCHAR *iv;
CRYPT *c;
UINT64 my_tick, your_tick;
@@ -676,6 +726,7 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
UINT pad_size;
UCHAR *verify;
bool compress_flag;
+ UCHAR raw_flag;
BLOCK *b = NULL;
UINT cookie;
// Validate arguments
@@ -686,36 +737,66 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
if (a->PlainTextMode == false)
{
- // IV
- if (size < UDP_ACCELERATION_PACKET_IV_SIZE)
+ if (a->Version == 2)
{
- return NULL;
- }
- iv = buf;
- buf += UDP_ACCELERATION_PACKET_IV_SIZE;
- size -= UDP_ACCELERATION_PACKET_IV_SIZE;
+ // Version 2.0
+ // IV
+ if (size < UDP_ACCELERATION_PACKET_IV_SIZE_V2)
+ {
+ return NULL;
+ }
+ iv = buf;
+ buf += UDP_ACCELERATION_PACKET_IV_SIZE_V2;
+ size -= UDP_ACCELERATION_PACKET_IV_SIZE_V2;
- // Calculate the key
- UdpAccelCalcKey(key, a->YourKey, iv);
+ if (size < AEAD_CHACHA20_POLY1305_MAC_SIZE)
+ {
+ return NULL;
+ }
- if (false)
- {
- char tmp1[256];
- char tmp2[256];
- char tmp3[256];
- BinToStr(tmp1, sizeof(tmp1), a->YourKey, sizeof(a->YourKey));
- BinToStr(tmp2, sizeof(tmp2), iv, UDP_ACCELERATION_PACKET_IV_SIZE);
- BinToStr(tmp3, sizeof(tmp3), key, sizeof(key));
- Debug("Your Key: %s\n"
- "IV : %s\n"
- "Comm Key: %s\n",
- tmp1, tmp2, tmp3);
+ // Decryption by RFC 8439: ChaCha20-Poly1305-IETF Encryption with AEAD
+ if (Aead_ChaCha20Poly1305_Ietf_Decrypt(buf, buf, size, a->YourKey_V2,
+ iv, NULL, 0) == false)
+ {
+ return NULL;
+ }
+
+ size -= AEAD_CHACHA20_POLY1305_MAC_SIZE;
}
+ else
+ {
+ // Version 1.0
+ // IV
+ if (size < UDP_ACCELERATION_PACKET_IV_SIZE_V1)
+ {
+ return NULL;
+ }
+ iv = buf;
+ buf += UDP_ACCELERATION_PACKET_IV_SIZE_V1;
+ size -= UDP_ACCELERATION_PACKET_IV_SIZE_V1;
+
+ // Calculate the key
+ UdpAccelCalcKey(key, a->YourKey, iv);
+
+ if (false)
+ {
+ char tmp1[256];
+ char tmp2[256];
+ char tmp3[256];
+ BinToStr(tmp1, sizeof(tmp1), a->YourKey, sizeof(a->YourKey));
+ BinToStr(tmp2, sizeof(tmp2), iv, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
+ BinToStr(tmp3, sizeof(tmp3), key, sizeof(key));
+ Debug("Your Key: %s\n"
+ "IV : %s\n"
+ "Comm Key: %s\n",
+ tmp1, tmp2, tmp3);
+ }
- // Decryption
- c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE);
- Encrypt(c, buf, buf, size);
- FreeCrypt(c);
+ // Decryption
+ c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE_V1);
+ Encrypt(c, buf, buf, size);
+ FreeCrypt(c);
+ }
}
// Cookie
@@ -759,12 +840,20 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
buf += sizeof(USHORT);
size -= sizeof(USHORT);
- // compress_flag
+ // flag
if (size < sizeof(UCHAR))
{
return NULL;
}
- compress_flag = *((UCHAR *)buf);
+ if (a->ReadRawFlagMode == false)
+ {
+ compress_flag = *((UCHAR *)buf);
+ }
+ else
+ {
+ raw_flag = *((UCHAR *)buf);
+ }
+
buf += sizeof(UCHAR);
size -= sizeof(UCHAR);
@@ -783,26 +872,29 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
if (a->PlainTextMode == false)
{
- // padding
- if (size < UDP_ACCELERATION_PACKET_IV_SIZE)
+ if (a->Version == 1)
{
- return false;
- }
- pad_size = size - UDP_ACCELERATION_PACKET_IV_SIZE;
- buf += pad_size;
- size -= pad_size;
+ // padding
+ if (size < UDP_ACCELERATION_PACKET_IV_SIZE_V1)
+ {
+ return false;
+ }
+ pad_size = size - UDP_ACCELERATION_PACKET_IV_SIZE_V1;
+ buf += pad_size;
+ size -= pad_size;
- // verify
- if (size != UDP_ACCELERATION_PACKET_IV_SIZE)
- {
- return NULL;
- }
+ // verify
+ if (size != UDP_ACCELERATION_PACKET_IV_SIZE_V1)
+ {
+ return NULL;
+ }
- verify = buf;
+ verify = buf;
- if (IsZero(verify, UDP_ACCELERATION_PACKET_IV_SIZE) == false)
- {
- return NULL;
+ if (IsZero(verify, UDP_ACCELERATION_PACKET_IV_SIZE_V1) == false)
+ {
+ return NULL;
+ }
}
}
@@ -819,7 +911,11 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
if (inner_size >= 1)
{
- b = NewBlock(Clone(inner_data, inner_size), inner_size, compress_flag ? -1 : 0);
+ b = NewBlock(Clone(inner_data, inner_size), inner_size, a->ReadRawFlagMode == false ? (compress_flag ? -1 : 0) : 0);
+ if (a->ReadRawFlagMode)
+ {
+ b->RawFlagRetUdpAccel = raw_flag;
+ }
}
if (a->LastSetSrcIpAndPortTick < a->LastRecvYourTick)
@@ -851,15 +947,15 @@ BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip
// Calculate the key
void UdpAccelCalcKey(UCHAR *key, UCHAR *common_key, UCHAR *iv)
{
- UCHAR tmp[UDP_ACCELERATION_COMMON_KEY_SIZE + UDP_ACCELERATION_PACKET_IV_SIZE];
+ UCHAR tmp[UDP_ACCELERATION_COMMON_KEY_SIZE_V1 + UDP_ACCELERATION_PACKET_IV_SIZE_V1];
// Validate arguments
if (key == NULL || common_key == NULL || iv == NULL)
{
return;
}
- Copy(tmp, common_key, UDP_ACCELERATION_COMMON_KEY_SIZE);
- Copy(tmp + UDP_ACCELERATION_COMMON_KEY_SIZE, iv, UDP_ACCELERATION_PACKET_IV_SIZE);
+ Copy(tmp, common_key, UDP_ACCELERATION_COMMON_KEY_SIZE_V1);
+ Copy(tmp + UDP_ACCELERATION_COMMON_KEY_SIZE_V1, iv, UDP_ACCELERATION_PACKET_IV_SIZE_V1);
HashSha1(key, tmp, sizeof(tmp));
}
@@ -887,7 +983,9 @@ bool UdpAccelInitServer(UDP_ACCEL *a, UCHAR *client_key, IP *client_ip, UINT cli
}
IPToStr(tmp, sizeof(tmp), client_ip);
- Debug("UdpAccelInitServer: client_ip=%s, client_port=%u, server_cookie=%u, client_cookie=%u\n", tmp, client_port,
+ Debug("UdpAccelInitServer: ver=%u, client_ip=%s, client_port=%u, server_cookie=%u, client_cookie=%u\n",
+ a->Version,
+ tmp, client_port,
a->MyCookie, a->YourCookie);
if (IsIP6(client_ip) != a->IsIPv6)
@@ -895,7 +993,14 @@ bool UdpAccelInitServer(UDP_ACCEL *a, UCHAR *client_key, IP *client_ip, UINT cli
return false;
}
- Copy(a->YourKey, client_key, UDP_ACCELERATION_COMMON_KEY_SIZE);
+ if (a->Version == 2)
+ {
+ Copy(a->YourKey_V2, client_key, UDP_ACCELERATION_COMMON_KEY_SIZE_V2);
+ }
+ else
+ {
+ Copy(a->YourKey, client_key, UDP_ACCELERATION_COMMON_KEY_SIZE_V1);
+ }
Copy(&a->YourIp, client_ip, sizeof(IP));
Copy(&a->YourIp2, client_ip_2, sizeof(IP));
@@ -919,14 +1024,22 @@ bool UdpAccelInitClient(UDP_ACCEL *a, UCHAR *server_key, IP *server_ip, UINT ser
}
IPToStr(tmp, sizeof(tmp), server_ip);
- Debug("UdpAccelInitClient: server_ip=%s, server_port=%u, server_cookie=%u, client_cookie=%u\n", tmp, server_port, server_cookie, client_cookie);
+ Debug("UdpAccelInitClient: ver = %u, server_ip=%s, server_port=%u, server_cookie=%u, client_cookie=%u\n",
+ a->Version, tmp, server_port, server_cookie, client_cookie);
if (IsIP6(server_ip) != a->IsIPv6)
{
return false;
}
- Copy(a->YourKey, server_key, UDP_ACCELERATION_COMMON_KEY_SIZE);
+ if (a->Version == 2)
+ {
+ Copy(a->YourKey_V2, server_key, UDP_ACCELERATION_COMMON_KEY_SIZE_V2);
+ }
+ else
+ {
+ Copy(a->YourKey, server_key, UDP_ACCELERATION_COMMON_KEY_SIZE_V1);
+ }
Copy(&a->YourIp, server_ip, sizeof(IP));
Copy(&a->YourIp2, server_ip_2, sizeof(IP));
@@ -1008,6 +1121,8 @@ UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port,
a->NoNatT = no_nat_t;
+ a->Version = 1;
+
a->NatT_TranId = Rand64();
@@ -1021,6 +1136,8 @@ UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port,
a->UdpSock = s;
Rand(a->MyKey, sizeof(a->MyKey));
Rand(a->YourKey, sizeof(a->YourKey));
+ Rand(a->MyKey_V2, sizeof(a->MyKey_V2));
+ Rand(a->YourKey_V2, sizeof(a->YourKey_V2));
Copy(&a->MyIp, ip, sizeof(IP));
a->MyPort = s->LocalPort;
@@ -1035,6 +1152,7 @@ UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port,
a->RecvBlockQueue = NewQueue();
Rand(a->NextIv, sizeof(a->NextIv));
+ Rand(a->NextIv_V2, sizeof(a->NextIv_V2));
do
{
diff --git a/src/Cedar/UdpAccel.h b/src/Cedar/UdpAccel.h
index 0c9dc32e..876c55e6 100644
--- a/src/Cedar/UdpAccel.h
+++ b/src/Cedar/UdpAccel.h
@@ -106,9 +106,14 @@
#define UDPACCEL_H
// Constants
-#define UDP_ACCELERATION_COMMON_KEY_SIZE 20 // Common key size
-#define UDP_ACCELERATION_PACKET_KEY_SIZE 20 // Key size for the packet
-#define UDP_ACCELERATION_PACKET_IV_SIZE 20 // IV size for the packet
+#define UDP_ACCELERATION_COMMON_KEY_SIZE_V1 20 // V1: Common key size
+#define UDP_ACCELERATION_PACKET_KEY_SIZE_V1 20 // V1: Key size for the packet
+#define UDP_ACCELERATION_PACKET_IV_SIZE_V1 20 // V1: IV size for the packet
+
+#define UDP_ACCELERATION_COMMON_KEY_SIZE_V2 128 // V2: Common key size
+#define UDP_ACCELERATION_PACKET_IV_SIZE_V2 12 // V2: IV size for the packet
+#define UDP_ACCELERATION_PACKET_MAC_SIZE_V2 16 // V2: MAC size for the packet
+
#define UDP_ACCELERATION_TMP_BUF_SIZE 2048 // Temporary buffer size
#define UDP_ACCELERATION_WINDOW_SIZE_MSEC (30 * 1000) // Receive window size (in milliseconds)
@@ -142,8 +147,8 @@ struct UDP_ACCEL
bool ClientMode; // Whether client mode
bool IsInCedarPortList; // Whether included in the port list of the Cedar
UINT64 Now; // Current time
- UCHAR MyKey[UDP_ACCELERATION_COMMON_KEY_SIZE]; // Submit-direction common key
- UCHAR YourKey[UDP_ACCELERATION_COMMON_KEY_SIZE]; // Receiving-direction common key
+ UCHAR MyKey[UDP_ACCELERATION_COMMON_KEY_SIZE_V1]; // Submit-direction common key
+ UCHAR YourKey[UDP_ACCELERATION_COMMON_KEY_SIZE_V1]; // Receiving-direction common key
SOCK *UdpSock; // UDP socket
UINT MyPort; // My port number
UINT YourPort; // Port number of the other party
@@ -160,7 +165,7 @@ struct UDP_ACCEL
UINT64 LastSetSrcIpAndPortTick; // Opponent's tick ??value at the time of storing the IP address and port number of the opponent at the end
UINT64 LastRecvTick; // Tick when data has received at the end
UINT64 NextSendKeepAlive; // Next time to send a KeepAlive packet
- UCHAR NextIv[UDP_ACCELERATION_PACKET_IV_SIZE]; // IV to be used next
+ UCHAR NextIv[UDP_ACCELERATION_PACKET_IV_SIZE_V1]; // IV to be used next
UINT MyCookie; // My cookie
UINT YourCookie; // Cookie of the other party
bool Inited; // Initialized flag
@@ -191,6 +196,11 @@ struct UDP_ACCEL
UCHAR UdpIpQueryPacketData[16]; // Query packet data (final transmission)
UINT UdpIpQueryPacketSize; // Query packet data size (final transmission)
UCHAR UdpHostUniqueKey[SHA1_SIZE]; // Unique key for UDP self endpoint query
+ UINT Version; // Version
+ UCHAR MyKey_V2[UDP_ACCELERATION_COMMON_KEY_SIZE_V2]; // Submit-direction common key (Ver 2)
+ UCHAR YourKey_V2[UDP_ACCELERATION_COMMON_KEY_SIZE_V2]; // Receiving-direction common key (Ver 2)
+ UCHAR NextIv_V2[UDP_ACCELERATION_PACKET_IV_SIZE_V2]; // IV to be used next (Ver 2)
+ bool ReadRawFlagMode; // Read raw flag mode
};
// Function prototype
@@ -203,7 +213,7 @@ void UdpAccelSetTick(UDP_ACCEL *a, UINT64 tick64);
BLOCK *UdpAccelProcessRecvPacket(UDP_ACCEL *a, UCHAR *buf, UINT size, IP *src_ip, UINT src_port);
void UdpAccelCalcKey(UCHAR *key, UCHAR *common_key, UCHAR *iv);
bool UdpAccelIsSendReady(UDP_ACCEL *a, bool check_keepalive);
-void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, bool compressed, UINT max_size, bool high_priority);
+void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, UCHAR flag, UINT max_size, bool high_priority);
void UdpAccelSendBlock(UDP_ACCEL *a, BLOCK *b);
UINT UdpAccelCalcMss(UDP_ACCEL *a);
void NatT_GetIpThread(THREAD *thread, void *param);
diff --git a/src/Cedar/VLanWin32.c b/src/Cedar/VLanWin32.c
index 6cdc22ec..dae66a99 100644
--- a/src/Cedar/VLanWin32.c
+++ b/src/Cedar/VLanWin32.c
@@ -367,8 +367,8 @@ void RouteTrackingMain(SESSION *s)
if (IPToUINT(&e->DestIP) == 0 &&
IPToUINT(&e->DestMask) == 0)
{
- Debug("e->InterfaceID = %u, t->VLanInterfaceId = %u\n",
- e->InterfaceID, t->VLanInterfaceId);
+ //Debug("e->InterfaceID = %u, t->VLanInterfaceId = %u\n",
+ // e->InterfaceID, t->VLanInterfaceId);
if (e->InterfaceID == t->VLanInterfaceId)
{