void OutVhOption(PACK *p, VH_OPTION *t) { // Validate arguments if (t == NULL || p == NULL) { return; } PackAddData(p, "MacAddress", t->MacAddress, 6); PackAddIp(p, "Ip", &t->Ip); PackAddIp(p, "Mask", &t->Mask); PackAddBool(p, "UseNat", t->UseNat); PackAddInt(p, "Mtu", t->Mtu); PackAddInt(p, "NatTcpTimeout", t->NatTcpTimeout); PackAddInt(p, "NatUdpTimeout", t->NatUdpTimeout); PackAddBool(p, "UseDhcp", t->UseDhcp); PackAddIp(p, "DhcpLeaseIPStart", &t->DhcpLeaseIPStart); PackAddIp(p, "DhcpLeaseIPEnd", &t->DhcpLeaseIPEnd); PackAddIp(p, "DhcpSubnetMask", &t->DhcpSubnetMask); PackAddInt(p, "DhcpExpireTimeSpan", t->DhcpExpireTimeSpan); PackAddIp(p, "DhcpGatewayAddress", &t->DhcpGatewayAddress); PackAddIp(p, "DhcpDnsServerAddress", &t->DhcpDnsServerAddress); PackAddIp(p, "DhcpDnsServerAddress2", &t->DhcpDnsServerAddress2); PackAddStr(p, "DhcpDomainName", t->DhcpDomainName); PackAddBool(p, "SaveLog", t->SaveLog); PackAddStr(p, "RpcHubName", t->HubName); PackAddBool(p, "ApplyDhcpPushRoutes", true); PackAddStr(p, "DhcpPushRoutes", t->DhcpPushRoutes); }
// Wait for connection request void AcWaitForRequest(AZURE_CLIENT *ac, SOCK *s, AZURE_PARAM *param) { // Validate arguments if (ac == NULL || s == NULL || param == NULL) { return; } while (ac->Halt == false) { UCHAR uc; // Receive 1 byte if (RecvAll(s, &uc, 1, false) == 0) { break; } if (uc != 0) { // Receive a Pack PACK *p = RecvPackWithHash(s); if (p == NULL) { break; } else { // Verify contents of Pack char opcode[MAX_SIZE]; char cipher_name[MAX_SIZE]; char hostname[MAX_SIZE]; PackGetStr(p, "opcode", opcode, sizeof(opcode)); PackGetStr(p, "cipher_name", cipher_name, sizeof(cipher_name)); PackGetStr(p, "hostname", hostname, sizeof(hostname)); if (StrCmpi(opcode, "relay") == 0) { IP client_ip, server_ip; UINT client_port; UINT server_port; UCHAR session_id[SHA1_SIZE]; if (PackGetIp(p, "client_ip", &client_ip) && PackGetIp(p, "server_ip", &server_ip) && PackGetData2(p, "session_id", session_id, sizeof(session_id))) { client_port = PackGetInt(p, "client_port"); server_port = PackGetInt(p, "server_port"); if (client_port != 0 && server_port != 0) { SOCK *ns; Debug("Connect Request from %r:%u\n", &client_ip, client_port); // Create new socket and connect VPN Azure Server if (ac->DDnsStatusCopy.InternetSetting.ProxyType == PROXY_DIRECT) { ns = ConnectEx2(ac->DDnsStatusCopy.CurrentAzureIp, AZURE_SERVER_PORT, 0, (bool *)&ac->Halt); } else { ns = WpcSockConnect2(ac->DDnsStatusCopy.CurrentAzureIp, AZURE_SERVER_PORT, &ac->DDnsStatusCopy.InternetSetting, NULL, AZURE_VIA_PROXY_TIMEOUT); } if (ns == NULL) { Debug("Connect Error.\n"); } else { Debug("Connected to the relay server.\n"); SetTimeout(ns, param->DataTimeout); if (StartSSLEx(ns, NULL, NULL, true, 0, NULL)) { // Check certification char server_cert_hash_str[MAX_SIZE]; UCHAR server_cert_hash[SHA1_SIZE]; Zero(server_cert_hash, sizeof(server_cert_hash)); GetXDigest(ns->RemoteX, server_cert_hash, true); BinToStr(server_cert_hash_str, sizeof(server_cert_hash_str), server_cert_hash, SHA1_SIZE); if (IsEmptyStr(ac->DDnsStatusCopy.AzureCertHash) || StrCmpi(server_cert_hash_str, ac->DDnsStatusCopy.AzureCertHash) == 0) { if (SendAll(ns, AZURE_PROTOCOL_DATA_SIANGTURE, 24, true)) { PACK *p2 = NewPack(); PackAddStr(p2, "hostname", hostname); PackAddData(p2, "session_id", session_id, sizeof(session_id)); if (SendPackWithHash(ns, p2)) { UCHAR uc; if (RecvAll(ns, &uc, 1, true) != false) { if (uc != 0) { SOCK *accept_sock = GetReverseListeningSock(ac->Cedar); if (accept_sock != NULL) { AddRef(ns->ref); SetTimeout(ns, INFINITE); Copy(&ns->Reverse_MyServerGlobalIp, &server_ip, sizeof(IP)); ns->Reverse_MyServerPort = server_port; InjectNewReverseSocketToAccept(accept_sock, ns, &client_ip, client_port); ReleaseSock(accept_sock); } } } } FreePack(p2); } } } ReleaseSock(ns); } } } } FreePack(p); } } // Send 1 byte uc = 0; if (SendAll(s, &uc, 1, false) == 0) { break; } } }
// Management thread void NiAdminThread(THREAD *thread, void *param) { NAT_ADMIN *a = (NAT_ADMIN *)param; NAT *n; SOCK *s; UCHAR random[SHA1_SIZE]; UINT err; // Validate arguments if (thread == NULL || param == NULL) { return; } // Random number generation Rand(random, sizeof(random)); a->Thread = thread; AddRef(a->Thread->ref); s = a->Sock; AddRef(s->ref); n = a->Nat; LockList(n->AdminList); { Add(n->AdminList, a); } UnlockList(n->AdminList); NoticeThreadInit(thread); err = ERR_AUTH_FAILED; if (StartSSL(s, n->AdminX, n->AdminK)) { PACK *p; // Send the random number p = NewPack(); PackAddData(p, "auth_random", random, sizeof(random)); if (HttpServerSend(s, p)) { PACK *p; // Receive a password p = HttpServerRecv(s); if (p != NULL) { UCHAR secure_password[SHA1_SIZE]; UCHAR secure_check[SHA1_SIZE]; if (PackGetData2(p, "secure_password", secure_password, sizeof(secure_password))) { SecurePassword(secure_check, n->HashedPassword, random); if (Cmp(secure_check, secure_password, SHA1_SIZE) == 0) { UCHAR test[SHA1_SIZE]; // Password match Hash(test, "", 0, true); SecurePassword(test, test, random); #if 0 if (Cmp(test, secure_check, SHA1_SIZE) == 0 && s->RemoteIP.addr[0] != 127) { // A client can not connect from the outside with blank password err = ERR_NULL_PASSWORD_LOCAL_ONLY; } else #endif { // Successful connection err = ERR_NO_ERROR; NiAdminMain(n, s); } } } FreePack(p); } } FreePack(p); if (err != ERR_NO_ERROR) { p = PackError(err); HttpServerSend(s, p); FreePack(p); } } Disconnect(s); ReleaseSock(s); }
// Connection for NAT administrator RPC *NatAdminConnect(CEDAR *cedar, char *hostname, UINT port, void *hashed_password, UINT *err) { UCHAR secure_password[SHA1_SIZE]; UCHAR random[SHA1_SIZE]; SOCK *sock; RPC *rpc; PACK *p; UINT error; // Validate arguments if (cedar == NULL || hostname == NULL || port == 0 || hashed_password == NULL || err == NULL) { if (err != NULL) { *err = ERR_INTERNAL_ERROR; } return NULL; } // Connection sock = Connect(hostname, port); if (sock == NULL) { *err = ERR_CONNECT_FAILED; return NULL; } if (StartSSL(sock, NULL, NULL) == false) { *err = ERR_PROTOCOL_ERROR; ReleaseSock(sock); return NULL; } SetTimeout(sock, 5000); p = HttpClientRecv(sock); if (p == NULL) { *err = ERR_DISCONNECTED; ReleaseSock(sock); return NULL; } if (PackGetData2(p, "auth_random", random, SHA1_SIZE) == false) { FreePack(p); *err = ERR_PROTOCOL_ERROR; ReleaseSock(sock); return NULL; } FreePack(p); SecurePassword(secure_password, hashed_password, random); p = NewPack(); PackAddData(p, "secure_password", secure_password, SHA1_SIZE); if (HttpClientSend(sock, p) == false) { FreePack(p); *err = ERR_DISCONNECTED; ReleaseSock(sock); return NULL; } FreePack(p); p = HttpClientRecv(sock); if (p == NULL) { *err = ERR_DISCONNECTED; ReleaseSock(sock); return NULL; } error = GetErrorFromPack(p); FreePack(p); if (error != ERR_NO_ERROR) { *err = error; ReleaseSock(sock); return NULL; } SetTimeout(sock, TIMEOUT_INFINITE); rpc = StartRpcClient(sock, NULL); ReleaseSock(sock); return rpc; }
// 管理スレッド void NiAdminThread(THREAD *thread, void *param) { NAT_ADMIN *a = (NAT_ADMIN *)param; NAT *n; SOCK *s; UCHAR random[SHA1_SIZE]; UINT err; // 引数チェック if (thread == NULL || param == NULL) { return; } // 乱数生成 Rand(random, sizeof(random)); a->Thread = thread; AddRef(a->Thread->ref); s = a->Sock; AddRef(s->ref); n = a->Nat; LockList(n->AdminList); { Add(n->AdminList, a); } UnlockList(n->AdminList); NoticeThreadInit(thread); err = ERR_AUTH_FAILED; if (StartSSL(s, n->AdminX, n->AdminK)) { PACK *p; // 乱数を送信する p = NewPack(); PackAddData(p, "auth_random", random, sizeof(random)); if (HttpServerSend(s, p)) { PACK *p; // パスワードを受け取る p = HttpServerRecv(s); if (p != NULL) { UCHAR secure_password[SHA1_SIZE]; UCHAR secure_check[SHA1_SIZE]; if (PackGetData2(p, "secure_password", secure_password, sizeof(secure_password))) { SecurePassword(secure_check, n->HashedPassword, random); if (Cmp(secure_check, secure_password, SHA1_SIZE) == 0) { UCHAR test[SHA1_SIZE]; // パスワード一致 Hash(test, "", 0, true); SecurePassword(test, test, random); #if 0 if (Cmp(test, secure_check, SHA1_SIZE) == 0 && s->RemoteIP.addr[0] != 127) { // 空白パスワードは外部から接続できない err = ERR_NULL_PASSWORD_LOCAL_ONLY; } else #endif { // 接続成功 err = ERR_NO_ERROR; NiAdminMain(n, s); } } } FreePack(p); } } FreePack(p); if (err != ERR_NO_ERROR) { p = PackError(err); HttpServerSend(s, p); FreePack(p); } } Disconnect(s); ReleaseSock(s); }