// Determine the last two bytes of the MAC address void NsGenMacAddressSignatureForMachine(UCHAR *dst_last_2, UCHAR *src_mac_addr_4) { char machine_name[MAX_SIZE]; BUF *b; UCHAR hash[SHA1_SIZE]; // Validate arguments if (dst_last_2 == NULL || src_mac_addr_4 == NULL) { return; } GetMachineHostName(machine_name, sizeof(machine_name)); Trim(machine_name); StrUpper(machine_name); b = NewBuf(); WriteBuf(b, src_mac_addr_4, 4); WriteBufStr(b, machine_name); HashSha1(hash, b->Buf, b->Size); FreeBuf(b); Copy(dst_last_2, hash, 2); }
// Generate the MAC address void NsGenMacAddress(void *dest, char *mac_address_seed, char *device_name) { char tmp[MAX_SIZE]; UCHAR mac[6]; UCHAR hash[SHA1_SIZE]; Zero(tmp, sizeof(tmp)); StrCat(tmp, sizeof(tmp), mac_address_seed); StrCat(tmp, sizeof(tmp), "@"); StrCat(tmp, sizeof(tmp), device_name); Trim(tmp); StrLower(tmp); HashSha1(hash, tmp, StrLen(tmp)); mac[0] = NS_MAC_ADDRESS_BYTE_1; mac[1] = hash[1]; mac[2] = hash[2]; mac[3] = hash[3]; mac[4] = hash[4]; mac[5] = hash[5]; NsGenMacAddressSignatureForMachine(mac + 4, mac); Copy(dest, mac, 6); }
// Generate an ID from GUID UINT Win32EthGenIdFromGuid(char *guid) { char tmp[MAX_SIZE]; UCHAR hash[SHA1_SIZE]; UINT i; // Validate arguments if (guid == NULL) { return 0; } StrCpy(tmp, sizeof(tmp), guid); Trim(tmp); StrUpper(tmp); HashSha1(hash, tmp, StrLen(tmp)); Copy(&i, hash, sizeof(UINT)); i = Endian32(i); if (i == 0) { i = 1; } return i; }
// Generate MAC address void NullGenerateMacAddress(UCHAR *mac, UINT id, UINT seq) { UCHAR hash[SHA1_SIZE]; char name[MAX_SIZE]; BUF *b; // Validate arguments if (mac == NULL) { return; } b = NewBuf(); WriteBufInt(b, id); WriteBufInt(b, seq); GetMachineHostName(name, sizeof(name)); #ifdef OS_WIN32 WriteBufInt(b, MsGetCurrentProcessId()); #endif // OS_WIN32 WriteBufStr(b, name); HashSha1(hash, b->Buf, b->Size); FreeBuf(b); Copy(mac, hash, 6); mac[0] = 0x7E; }
// Calculate the key void UdpAccelCalcKey(UCHAR *key, UCHAR *common_key, UCHAR *iv) { UCHAR tmp[UDP_ACCELERATION_COMMON_KEY_SIZE + UDP_ACCELERATION_PACKET_IV_SIZE]; // 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); HashSha1(key, tmp, sizeof(tmp)); }
// Generate the packet BUF *WpcGeneratePacket(PACK *pack, X *cert, K *key) { UCHAR hash[SHA1_SIZE]; BUF *pack_data; BUF *cert_data = NULL; BUF *sign_data = NULL; BUF *b; // Validate arguments if (pack == NULL) { return NULL; } pack_data = PackToBuf(pack); HashSha1(hash, pack_data->Buf, pack_data->Size); if (cert != NULL && key != NULL) { UCHAR sign[128]; cert_data = XToBuf(cert, false); RsaSign(sign, hash, sizeof(hash), key); sign_data = NewBuf(); WriteBuf(sign_data, sign, sizeof(sign)); SeekBuf(sign_data, 0, 0); } b = NewBuf(); WpcAddDataEntryBin(b, "PACK", pack_data->Buf, pack_data->Size); WpcAddDataEntryBin(b, "HASH", hash, sizeof(hash)); if (cert_data != NULL) { WpcAddDataEntryBin(b, "CERT", cert_data->Buf, cert_data->Size); WpcAddDataEntryBin(b, "SIGN", sign_data->Buf, sign_data->Size); } FreeBuf(pack_data); FreeBuf(cert_data); FreeBuf(sign_data); SeekBuf(b, 0, 0); return b; }
// Creating a DDNS client DDNS_CLIENT *NewDDNSClient(CEDAR *cedar, UCHAR *key, INTERNET_SETTING *t) { DDNS_CLIENT *c; UCHAR key_hash[SHA1_SIZE]; // Validate arguments if (cedar == NULL) { return NULL; } c = ZeroMalloc(sizeof(DDNS_CLIENT)); c->Cedar = cedar; AddRef(c->Cedar->ref); c->Err_IPv4 = c->Err_IPv6 = ERR_TRYING_TO_CONNECT; if (key == NULL) { // Create a new key DCGenNewKey(c->Key); } else { // Set the key Copy(c->Key, key, SHA1_SIZE); } HashSha1(key_hash, c->Key, sizeof(c->Key)); if (t != NULL) { Copy(&c->InternetSetting, t, sizeof(INTERNET_SETTING)); } c->Lock = NewLock(); // Thread creation c->Event = NewEvent(); c->Thread = NewThread(DCThread, c); return c; }
// Create a new key void DCGenNewKey(UCHAR *key) { BUF *b; UINT64 tick; UCHAR hash[SHA1_SIZE]; UCHAR rand[SHA1_SIZE]; UINT i; // Validate arguments if (key == NULL) { return; } b = NewBuf(); Rand(rand, sizeof(rand)); WriteBuf(b, rand, sizeof(rand)); tick = TickHighres64(); WriteBufInt64(b, tick); tick = Tick64(); WriteBufInt64(b, tick); tick = SystemTime64(); WriteBufInt64(b, tick); GetCurrentMachineIpProcessHash(hash); WriteBuf(b, hash, sizeof(hash)); HashSha1(key, b->Buf, b->Size); Rand(rand, sizeof(rand)); for (i = 0;i < SHA1_SIZE;i++) { key[i] = key[i] ^ rand[i]; } FreeBuf(b); }
// Execution of registration UINT DCRegister(DDNS_CLIENT *c, bool ipv6, DDNS_REGISTER_PARAM *p, char *replace_v6) { char *url; char url2[MAX_SIZE]; char url3[MAX_SIZE]; PACK *req, *ret; char key_str[MAX_SIZE]; UCHAR machine_key[SHA1_SIZE]; char machine_key_str[MAX_SIZE]; char machine_name[MAX_SIZE]; BUF *cert_hash; UINT err = ERR_INTERNAL_ERROR; UCHAR key_hash[SHA1_SIZE]; char key_hash_str[MAX_SIZE]; bool use_azure = false; char current_azure_ip[MAX_SIZE]; INTERNET_SETTING t; UINT build = 0; bool use_https = false; bool use_vgs = false; // Validate arguments if (c == NULL) { return ERR_INTERNAL_ERROR; } Zero(current_azure_ip, sizeof(current_azure_ip)); GetCurrentMachineIpProcessHash(machine_key); BinToStr(machine_key_str, sizeof(machine_key_str), machine_key, sizeof(machine_key)); GetMachineHostName(machine_name, sizeof(machine_name)); StrLower(machine_name); if (ipv6 == false) { url = DDNS_URL_V4_GLOBAL; if (IsUseAlternativeHostname()) { url = DDNS_URL_V4_ALT; } } else { url = DDNS_URL_V6_GLOBAL; if (IsUseAlternativeHostname()) { url = DDNS_URL_V6_ALT; } if (replace_v6) { url = replace_v6; } } Zero(&t, sizeof(t)); if (ipv6 == false) { // Proxy Setting Copy(&t, &c->InternetSetting, sizeof(INTERNET_SETTING)); } if (ipv6 == false) { // Get the current status of the VPN Azure Client if (c->Cedar->Server != NULL) { AZURE_CLIENT *ac = c->Cedar->Server->AzureClient; if (ac != NULL) { use_azure = SiIsAzureEnabled(c->Cedar->Server); if (use_azure) { Lock(ac->Lock); { StrCpy(current_azure_ip, sizeof(current_azure_ip), ac->ConnectingAzureIp); } Unlock(ac->Lock); } } } } req = NewPack(); BinToStr(key_str, sizeof(key_str), c->Key, sizeof(c->Key)); StrUpper(key_str); PackAddStr(req, "key", key_str); // Build Number build = c->Cedar->Build; PackAddInt(req, "build", build); PackAddInt(req, "osinfo", GetOsInfo()->OsType); PackAddInt(req, "is_64bit", Is64()); #ifdef OS_WIN32 PackAddInt(req, "is_windows_64bit", MsIs64BitWindows()); #endif // OS_WIN32 PackAddBool(req, "is_softether", true); PackAddBool(req, "is_packetix", false); PackAddStr(req, "machine_key", machine_key_str); PackAddStr(req, "machine_name", machine_name); PackAddInt(req, "lasterror_ipv4", c->Err_IPv4_GetMyIp); PackAddInt(req, "lasterror_ipv6", c->Err_IPv6_GetMyIp); PackAddBool(req, "use_azure", use_azure); PackAddStr(req, "product_str", CEDAR_PRODUCT_STR); PackAddInt(req, "ddns_protocol_version", DDNS_VERSION); if (use_azure) { Debug("current_azure_ip = %s\n", current_azure_ip); PackAddStr(req, "current_azure_ip", current_azure_ip); } HashSha1(key_hash, key_str, StrLen(key_str)); BinToStr(key_hash_str, sizeof(key_hash_str), key_hash, sizeof(key_hash)); StrLower(key_hash_str); if (p != NULL) { if (IsEmptyStr(p->NewHostname) == false) { PackAddStr(req, "new_hostname", p->NewHostname); } } cert_hash = StrToBin(DDNS_CERT_HASH); Format(url2, sizeof(url2), "%s?v=%I64u", url, Rand64()); Format(url3, sizeof(url3), url2, key_hash_str[0], key_hash_str[1], key_hash_str[2], key_hash_str[3]); if (use_https == false) { ReplaceStr(url3, sizeof(url3), url3, "https://", "http://"); } ReplaceStr(url3, sizeof(url3), url3, ".servers", ".open.servers"); Debug("WpcCall: %s\n", url3); ret = WpcCallEx(url3, &t, DDNS_CONNECT_TIMEOUT, DDNS_COMM_TIMEOUT, "register", req, NULL, NULL, ((cert_hash != NULL && cert_hash->Size == SHA1_SIZE) ? cert_hash->Buf : NULL), NULL, DDNS_RPC_MAX_RECV_SIZE); Debug("WpcCall Ret: %u\n", ret); FreeBuf(cert_hash); FreePack(req); err = GetErrorFromPack(ret); ExtractAndApplyDynList(ret); // Status update Lock(c->Lock); { if (err == ERR_NO_ERROR) { char snat_t[MAX_SIZE]; char current_region[128]; // Current host name PackGetStr(ret, "current_hostname", c->CurrentHostName, sizeof(c->CurrentHostName)); PackGetStr(ret, "current_fqdn", c->CurrentFqdn, sizeof(c->CurrentFqdn)); PackGetStr(ret, "current_ipv4", c->CurrentIPv4, sizeof(c->CurrentIPv4)); PackGetStr(ret, "current_ipv6", c->CurrentIPv6, sizeof(c->CurrentIPv6)); PackGetStr(ret, "dns_suffix", c->DnsSuffix, sizeof(c->DnsSuffix)); PackGetStr(ret, "current_region", current_region, sizeof(current_region)); // SecureNAT connectivity check parameters Zero(snat_t, sizeof(snat_t)); PackGetStr(ret, "snat_t", snat_t, sizeof(snat_t)); NnSetSecureNatTargetHostname(snat_t); if (ipv6 == false) { char cert_hash[MAX_SIZE]; PackGetStr(ret, "current_azure_ip", c->CurrentAzureIp, sizeof(c->CurrentAzureIp)); c->CurrentAzureTimestamp = PackGetInt64(ret, "current_azure_timestamp"); PackGetStr(ret, "current_azure_signature", c->CurrentAzureSignature, sizeof(c->CurrentAzureSignature)); Zero(cert_hash, sizeof(cert_hash)); PackGetStr(ret, "azure_cert_hash", cert_hash, sizeof(cert_hash)); if (IsEmptyStr(cert_hash) == false) { StrCpy(c->AzureCertHash, sizeof(c->AzureCertHash), cert_hash); } } StrCpy(c->Cedar->CurrentDDnsFqdn, sizeof(c->Cedar->CurrentDDnsFqdn), c->CurrentFqdn); Debug("current_hostname=%s, current_fqdn=%s, current_ipv4=%s, current_ipv6=%s, current_azure_ip=%s, CurrentAzureTimestamp=%I64u, CurrentAzureSignature=%s, CertHash=%s\n", c->CurrentHostName, c->CurrentFqdn, c->CurrentIPv4, c->CurrentIPv6, c->CurrentAzureIp, c->CurrentAzureTimestamp, c->CurrentAzureSignature, c->AzureCertHash); if (IsEmptyStr(current_region) == false) { // Update the current region SiUpdateCurrentRegion(c->Cedar, current_region, false); } } } Unlock(c->Lock); if (IsEmptyStr(c->CurrentFqdn) == false) { SetCurrentDDnsFqdn(c->CurrentFqdn); } FreePack(ret); UniDebug(L"DCRegister Error: %s\n", _E(err)); if (err == ERR_DUPLICATE_DDNS_KEY) { // Key duplication DCGenNewKey(c->Key); c->KeyChanged = true; } if (err == ERR_DISCONNECTED) { err = ERR_DDNS_DISCONNECTED; } if (IsUseAlternativeHostname() == false) { if (err == ERR_CONNECT_FAILED) { if (ipv6 && replace_v6 == NULL) { UINT type = DetectFletsType(); if (type & FLETS_DETECT_TYPE_EAST_BFLETS_PRIVATE && err != ERR_NO_ERROR) { err = DCRegister(c, ipv6, p, DDNS_REPLACE_URL_FOR_EAST_BFLETS); } if (type & FLETS_DETECT_TYPE_EAST_NGN_PRIVATE && err != ERR_NO_ERROR) { err = DCRegister(c, ipv6, p, DDNS_REPLACE_URL_FOR_EAST_NGN); } if (type & FLETS_DETECT_TYPE_WEST_NGN_PRIVATE && err != ERR_NO_ERROR) { err = DCRegister(c, ipv6, p, DDNS_REPLACE_URL_FOR_WEST_NGN); } } } } return err; }
// Parse the packet bool WpcParsePacket(WPC_PACKET *packet, BUF *buf) { LIST *o; BUF *b; bool ret = false; UCHAR hash[SHA1_SIZE]; // Validate arguments if (packet == NULL || buf == NULL) { return false; } Zero(packet, sizeof(WPC_PACKET)); o = WpcParseDataEntry(buf); b = WpcDataEntryToBuf(WpcFindDataEntry(o, "PACK")); if (b != NULL) { HashSha1(hash, b->Buf, b->Size); packet->Pack = BufToPack(b); FreeBuf(b); if (packet->Pack != NULL) { BUF *b; ret = true; b = WpcDataEntryToBuf(WpcFindDataEntry(o, "HASH")); if (b != NULL) { if (b->Size != SHA1_SIZE || Cmp(b->Buf, hash, SHA1_SIZE) != 0) { ret = false; FreePack(packet->Pack); } else { BUF *b; Copy(packet->Hash, hash, SHA1_SIZE); b = WpcDataEntryToBuf(WpcFindDataEntry(o, "CERT")); if (b != NULL) { X *cert = BufToX(b, false); if (cert == NULL) { ret = false; FreePack(packet->Pack); } else { BUF *b = WpcDataEntryToBuf(WpcFindDataEntry(o, "SIGN")); if (b == NULL || (b->Size != 128)) { ret = false; FreeX(cert); FreePack(packet->Pack); } else { K *k = GetKFromX(cert); if (RsaVerify(hash, SHA1_SIZE, b->Buf, k) == false) { ret = false; FreeX(cert); FreePack(packet->Pack); } else { packet->Cert = cert; Copy(packet->Sign, b->Buf, 128); } FreeK(k); } FreeBuf(b); } FreeBuf(b); } } FreeBuf(b); } } } WpcFreeDataEntryList(o); return ret; }
// Add the iptables entries for native stack IPTABLES_STATE *StartAddIpTablesEntryForNativeStack(void *seed, UINT seed_size) { IPTABLES_STATE *ret = NULL; bool ok = false; if (IsIpTablesSupported()) { IPTABLES_ENTRY *e; UINT i; ret = ZeroMalloc(sizeof(IPTABLES_STATE)); ret->EntryList = NewListFast(NULL); HashSha1(ret->SeedHash, seed, seed_size); // Create a pair of entry e = ZeroMalloc(sizeof(IPTABLES_ENTRY)); GenerateDummyIpAndMark(ret->SeedHash, e, 0); StrCpy(e->Chain, sizeof(e->Chain), "OUTPUT"); Format(e->ConditionAndArgs, sizeof(e->ConditionAndArgs), "-p tcp --tcp-flags RST RST --sport %u:%u ! -s %r/32 ! -d %r/32 -m connmark ! --mark 0x%x -j DROP", NN_RAW_IP_PORT_START, NN_RAW_IP_PORT_END, &e->DummySrcIp, &e->DummyDestIP, e->DummyMark); Add(ret->EntryList, e); e = ZeroMalloc(sizeof(IPTABLES_ENTRY)); GenerateDummyIpAndMark(ret->SeedHash, e, 1); StrCpy(e->Chain, sizeof(e->Chain), "OUTPUT"); Format(e->ConditionAndArgs, sizeof(e->ConditionAndArgs), "-p icmp --icmp-type 3/3 ! -s %r/32 ! -d %r/32 -m connmark ! --mark 0x%x -j DROP", &e->DummySrcIp, &e->DummyDestIP, e->DummyMark); Add(ret->EntryList, e); ok = true; // Insert entries if not exists for (i = 0; i < LIST_NUM(ret->EntryList);i++) { UINT j; IPTABLES_ENTRY *e = LIST_DATA(ret->EntryList, i); for (j = 0;j < 100;j++) { if (GetCurrentIpTableLineNumber(e->Chain, &e->DummySrcIp, &e->DummyDestIP, e->DummyMark) != 0) { char cmdline[MAX_PATH]; Format(cmdline, sizeof(cmdline), "iptables -D %s %s", e->Chain, e->ConditionAndArgs); system(cmdline); } else { break; } } if (GetCurrentIpTableLineNumber(e->Chain, &e->DummySrcIp, &e->DummyDestIP, e->DummyMark) == 0) { char cmdline[MAX_PATH]; Format(cmdline, sizeof(cmdline), "iptables -I %s %s", e->Chain, e->ConditionAndArgs); system(cmdline); if (GetCurrentIpTableLineNumber(e->Chain, &e->DummySrcIp, &e->DummyDestIP, e->DummyMark) == 0) { Debug("Run \"%s\" failed.\n", cmdline); ok = false; break; } else { Debug("Run \"%s\" ok.\n", cmdline); } } } } if (ok == false) { EndAddIpTablesEntryForNativeStack(ret); ret = NULL; } return ret; }