// SA ペイロードの構築 SE_BUF *SeIkeBuildSaPayload(SE_IKE_PACKET_SA_PAYLOAD *t) { SE_IKE_SA_HEADER h; SE_BUF *ret; SE_BUF *b; // 引数チェック if (t == NULL) { return NULL; } SeZero(&h, sizeof(h)); h.DoI = SeEndian32(SE_IKE_SA_DOI_IPSEC); h.Situation = SeEndian32(SE_IKE_SA_SITUATION_IDENTITY); ret = SeNewBuf(); SeWriteBuf(ret, &h, sizeof(h)); b = SeIkeBuildPayloadList(t->PayloadList); SeWriteBufBuf(ret, b); SeFreeBuf(b); return ret; }
// IPsec 初期化 void SeVpn6InitIPsec(SE_VPN6 *v6) { SE_VPN *v; SE_VPN_CONFIG *c; SE_SEC_CONFIG conf; SE_SEC_CLIENT_FUNCTION_TABLE func_table; // 引数チェック if (v6 == NULL) { return; } v = v6->Vpn; c = v->Config; // IPsec モジュールの初期化 SeVpn6InitSecConfig(v6, &conf); SeZero(&func_table, sizeof(func_table)); func_table.ClientGetTick = SeVpn6ClientGetTick; func_table.ClientSetTimerCallback = SeVpn6ClientSetTimerCallback; func_table.ClientAddTimer = SeVpn6ClientAddTimer; func_table.ClientSetRecvUdpCallback = SeVpn6ClientSetRecvUdpCallback; func_table.ClientSetRecvEspCallback = SeVpn6ClientSetRecvEspCallback; func_table.ClientSetRecvVirtualIpCallback = SeVpn6ClientSetRecvVirtualIpCallback; func_table.ClientSendUdp = SeVpn6ClientSendUdp; func_table.ClientSendEsp = SeVpn6ClientSendEsp; func_table.ClientSendVirtualIp = SeVpn6ClientSendVirtualIp; v6->Sec = SeSecInit(v, true, &conf, &func_table, v6, c->VpnPhase2StrictIdV6); }
// タイマのセット void SeTimerSet(SE_TIMER *t, UINT interval) { SE_TIMER_ENTRY *e; // 引数チェック if (t == NULL) { return; } // タイマエントリの挿入 SeLock(t->TimerEntryLock); { SE_TIMER_ENTRY st; UINT64 target_tick = SeTick64() + (UINT64)interval; SeZero(&st, sizeof(st)); st.Tick = target_tick; // 同一の Tick を指すタイマエントリが存在するかどうかチェックする if (SeSearch(t->TimerEntryList, &st) == NULL) { // タイマエントリの新規作成 e = SeZeroMalloc(sizeof(SE_TIMER_ENTRY)); e->Tick = target_tick; // 挿入 SeInsert(t->TimerEntryList, e); // タイマを調整 SeTimerAdjust(t); } } SeUnlock(t->TimerEntryLock); }
// プロポーザルペイロードの構築 SE_BUF *SeIkeBuildProposalPayload(SE_IKE_PACKET_PROPOSAL_PAYLOAD *t) { SE_IKE_PROPOSAL_HEADER h; SE_BUF *ret, *b; // 引数チェック if (t == NULL) { return NULL; } SeZero(&h, sizeof(h)); h.Number = t->Number; h.NumTransforms = SE_LIST_NUM(t->PayloadList); h.ProtocolId = t->ProtocolId; h.SpiSize = t->Spi->Size; ret = SeNewBuf(); SeWriteBuf(ret, &h, sizeof(h)); SeWriteBufBuf(ret, t->Spi); b = SeIkeBuildPayloadList(t->PayloadList); SeWriteBufBuf(ret, b); SeFreeBuf(b); return ret; }
// 削除ペイロードの構築 SE_BUF *SeIkeBuildDeletePayload(SE_IKE_PACKET_DELETE_PAYLOAD *t) { SE_IKE_DELETE_HEADER h; SE_BUF *ret; UINT i; // 引数チェック if (t == NULL) { return NULL; } SeZero(&h, sizeof(h)); h.DoI = SeEndian32(SE_IKE_SA_DOI_IPSEC); h.NumSpis = SE_LIST_NUM(t->SpiList); h.ProtocolId = t->ProtocolId; if (SE_LIST_NUM(t->SpiList) >= 1) { SE_BUF *b = SE_LIST_DATA(t->SpiList, 0); h.SpiSize = b->Size; } ret = SeNewBuf(); SeWriteBuf(ret, &h, sizeof(h)); for (i = 0;i < SE_LIST_NUM(t->SpiList);i++) { SE_BUF *b = SE_LIST_DATA(t->SpiList, i); SeWriteBuf(ret, b->Buf, b->Size); } return ret; }
UINT GetWindowsVersion() { OSVERSIONINFO info; UINT ret = OS_UNKNOWN; SeZero(&info, sizeof(info)); info.dwOSVersionInfoSize = sizeof(info); GetVersionEx(&info); if (info.dwPlatformId == VER_PLATFORM_WIN32_NT) { if (info.dwMajorVersion == 6 && info.dwMinorVersion == 1) { ret = OS_WIN7; } else if (info.dwMajorVersion == 6 && (info.dwMinorVersion == 2 || info.dwMinorVersion == 3)) { ret = OS_WIN8; } else if ((info.dwMajorVersion == 6 && info.dwMinorVersion == 4) || (info.dwMajorVersion >= 7)) { ret = OS_WIN10; } } return ret; }
// 解読 SE_BUF *SeIkeDecrypt(void *data, UINT size, SE_IKE_CRYPTO_PARAM *cparam) { void *tmp; SE_BUF *b; // 引数チェック if (data == NULL || cparam == NULL) { return NULL; } if ((size % SE_DES_BLOCK_SIZE) != 0) { // ブロックサイズの整数倍でない return NULL; } tmp = SeMalloc(size); SeDes3Decrypt(tmp, data, size, cparam->DesKey, cparam->Iv); if (size >= SE_DES_BLOCK_SIZE) { SeCopy(cparam->NextIv, ((UCHAR *)data) + (size - SE_DES_BLOCK_SIZE), SE_DES_BLOCK_SIZE); } else { SeZero(cparam->NextIv, SE_DES_BLOCK_SIZE); } b = SeMemToBuf(tmp, size); SeFree(tmp); return b; }
// IPv4 アドレスの初期化 void SeIkeInitIPv4Address(SE_IKE_IP_ADDR *a, SE_IPV4_ADDR *addr) { // 引数チェック if (a == NULL || addr == NULL) { return; } SeZero(a, sizeof(SE_IKE_IP_ADDR)); a->Address.Ipv4 = *addr; a->IsIPv6 = false; }
// ペイロードリストからビット列を構築 SE_BUF *SeIkeBuildPayloadList(SE_LIST *o) { SE_BUF *b; UINT i; // 引数チェック if (o == NULL) { return NULL; } b = SeNewBuf(); for (i = 0;i < SE_LIST_NUM(o);i++) { SE_IKE_PACKET_PAYLOAD *p = SE_LIST_DATA(o, i); SE_IKE_PACKET_PAYLOAD *next = NULL; SE_IKE_COMMON_HEADER h; SE_BUF *tmp; if (i < (SE_LIST_NUM(o) - 1)) { next = SE_LIST_DATA(o, i + 1); } SeZero(&h, sizeof(h)); if (next != NULL) { h.NextPayload = next->PayloadType; } else { h.NextPayload = SE_IKE_PAYLOAD_NONE; } tmp = SeIkeBuildPayload(p); if (tmp != NULL) { h.PayloadSize = SeEndian16(tmp->Size + (USHORT)sizeof(h)); SeWriteBuf(b, &h, sizeof(h)); SeWriteBuf(b, tmp->Buf, tmp->Size); SeFreeBuf(tmp); } } SeSeekBuf(b, 0, 0); return b; }
bool IsWin10PcapFile(char *filename) { char tmp[1024]; if (filename == NULL) { return false; } SeZero(tmp, sizeof(tmp)); MsGetFileVersion(filename, tmp, sizeof(tmp)); if (SeStartWith(tmp, "10,")) { return true; } return false; }
// 証明書要求ペイロードの構築 SE_BUF *SeIkeBuildCertRequestPayload(SE_IKE_PACKET_CERT_REQUEST_PAYLOAD *t) { SE_IKE_CERT_REQUEST_HEADER h; SE_BUF *ret; // 引数チェック if (t == NULL) { return NULL; } SeZero(&h, sizeof(h)); h.CertType = t->CertType; ret = SeNewBuf(); SeWriteBuf(ret, &h, sizeof(h)); SeWriteBufBuf(ret, t->Data); return ret; }
// SE_SEC_CONFIG の初期化 void SeVpn6InitSecConfig(SE_VPN6 *v6, SE_SEC_CONFIG *c) { SE_VPN_CONFIG *vc; SE_IPV6_ADDR zero_ip = Se6ZeroIP(); // 引数チェック if (v6 == NULL || c == NULL) { return; } vc = v6->Vpn->Config; SeZero(c, sizeof(SE_SEC_CONFIG)); SeIkeInitIPv6Address(&c->MyIpAddress, &v6->Vpn->IPv6_Physical->GlobalIpAddress); SeIkeInitIPv6Address(&c->MyVirtualIpAddress, &zero_ip); SeIkeInitIPv6Address(&c->VpnGatewayAddress, &vc->VpnGatewayAddressV6); c->VpnAuthMethod = vc->VpnAuthMethodV6; SeStrCpy(c->VpnPassword, sizeof(c->VpnPassword), vc->VpnPasswordV6); SeStrCpy(c->VpnIdString, sizeof(c->VpnIdString), vc->VpnIdStringV6); SeStrCpy(c->VpnCertName, sizeof(c->VpnCertName), vc->VpnCertNameV6); SeStrCpy(c->VpnCaCertName, sizeof(c->VpnCaCertName), vc->VpnCaCertNameV6); SeStrCpy(c->VpnRsaKeyName, sizeof(c->VpnRsaKeyName), vc->VpnRsaKeyNameV6); c->VpnPhase1Crypto = vc->VpnPhase1CryptoV6; c->VpnPhase1Hash = vc->VpnPhase1HashV6; c->VpnPhase1LifeKilobytes = vc->VpnPhase1LifeKilobytesV6; c->VpnPhase1LifeSeconds = vc->VpnPhase1LifeSecondsV6; c->VpnWaitPhase2BlankSpan = vc->VpnWaitPhase2BlankSpanV6; c->VpnPhase2Crypto = vc->VpnPhase2CryptoV6; c->VpnPhase2Hash = vc->VpnPhase2HashV6; c->VpnPhase2LifeKilobytes = vc->VpnPhase2LifeKilobytesV6; c->VpnPhase2LifeSeconds = vc->VpnPhase2LifeSecondsV6; c->VpnConnectTimeout = vc->VpnConnectTimeoutV6; c->VpnIdleTimeout = vc->VpnIdleTimeoutV6; SeIkeInitIPv6Address(&c->VpnPingTarget, &vc->VpnPingTargetV6); c->VpnPingInterval = vc->VpnPingIntervalV6; c->VpnPingMsgSize = vc->VpnPingMsgSizeV6; c->VpnSpecifyIssuer = vc->VpnSpecifyIssuerV6; }
// 通知ペイロードの構築 SE_BUF *SeIkeBuildNoticePayload(SE_IKE_PACKET_NOTICE_PAYLOAD *t) { SE_IKE_NOTICE_HEADER h; SE_BUF *ret; // 引数チェック if (t == NULL) { return NULL; } SeZero(&h, sizeof(h)); h.DoI = SeEndian32(SE_IKE_SA_DOI_IPSEC); h.MessageType = SeEndian16(t->MessageType); h.ProtocolId = t->ProtocolId; h.SpiSize = t->Spi->Size; ret = SeNewBuf(); SeWriteBuf(ret, &h, sizeof(h)); SeWriteBuf(ret, t->Spi->Buf, t->Spi->Size); return ret; }
// ID ペイロードの構築 SE_BUF *SeIkeBuildIdPayload(SE_IKE_PACKET_ID_PAYLOAD *t) { SE_IKE_ID_HEADER h; SE_BUF *ret; // 引数チェック if (t == NULL) { return NULL; } SeZero(&h, sizeof(h)); h.IdType = t->Type; h.Port = SeEndian16(t->Port); h.ProtocolId = t->ProtocolId; ret = SeNewBuf(); SeWriteBuf(ret, &h, sizeof(h)); SeWriteBufBuf(ret, t->IdData); return ret; }
// 受信バッファの初期化 void pro100_init_recv_buffer(PRO100_CTX *ctx) { UINT i; // 引数チェック if (ctx == NULL) { return; } // リンクリスト構造の初期化 for (i = 0;i < ctx->num_recv;i++) { PRO100_RECV *r = &ctx->recv[i]; PRO100_RFD *rfd = r->rfd; SeZero(rfd, sizeof(PRO100_RFD)); rfd->buffer_size = PRO100_MAX_PACKET_SIZE; if (i != (ctx->num_recv - 1)) { r->next_recv = &ctx->recv[i + 1]; rfd->s = rfd->el = false; rfd->link_address = (UINT)r->next_recv->rfd_ptr; } else { r->next_recv = NULL; rfd->link_address = 0; rfd->s = false; rfd->el = true; } } ctx->first_recv = &ctx->recv[0]; ctx->last_recv = &ctx->recv[ctx->num_recv - 1]; ctx->current_recv = ctx->first_recv; }
// トランスフォームペイロードの構築 SE_BUF *SeIkeBuildTransformPayload(SE_IKE_PACKET_TRANSFORM_PAYLOAD *t) { SE_IKE_TRANSFORM_HEADER h; SE_BUF *ret, *b; // 引数チェック if (t == NULL) { return NULL; } SeZero(&h, sizeof(h)); h.Number = t->Number; h.TransformId = t->TransformId; ret = SeNewBuf(); SeWriteBuf(ret, &h, sizeof(h)); b = SeIkeBuildTransformValueList(t->ValueList); SeWriteBufBuf(ret, b); SeFreeBuf(b); return ret; }
bool InstallNdisProtocolDriver(char *inf_path, wchar_t *id, UINT lock_timeout) { bool ret = false; HRESULT hr; INetCfg *pNetCfg; // Validate arguments if (inf_path == NULL || id == NULL) { return false; } hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (void **)&pNetCfg); if (SUCCEEDED(hr)) { INetCfgLock *pLock; hr = pNetCfg->QueryInterface(IID_INetCfgLock, (PVOID*)&pLock); if (SUCCEEDED(hr)) { LPWSTR locked_by; hr = pLock->AcquireWriteLock(lock_timeout, L"SoftEther VPN", &locked_by); if (SUCCEEDED(hr)) { hr = pNetCfg->Initialize(NULL); if (SUCCEEDED(hr)) { char inf_dir[MAX_PATH]; SeGetDirNameFromFilePath(inf_dir, sizeof(inf_dir), inf_path); if (SetupCopyOEMInfA(inf_path, inf_dir, SPOST_PATH, 0, NULL, 0, NULL, 0)) { INetCfgClassSetup *pSetup; hr = pNetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETTRANS, IID_INetCfgClassSetup, (void **)&pSetup); if (SUCCEEDED(hr)) { OBO_TOKEN token; INetCfgComponent *pComponent; SeZero(&token, sizeof(token)); token.Type = OBO_USER; hr = pSetup->Install(id, &token, 0, 0, NULL, NULL, &pComponent); if (SUCCEEDED(hr)) { pNetCfg->Apply(); ret = true; } pSetup->Release(); } if (ret == false) { char dst_inf_name[MAX_PATH]; DWORD dst_inf_name_size = MAX_PATH; if (SetupCopyOEMInfA(inf_path, inf_dir, SPOST_PATH, SP_COPY_REPLACEONLY, dst_inf_name, dst_inf_name_size, &dst_inf_name_size, NULL) == false && GetLastError() == ERROR_FILE_EXISTS) { SetupUninstallOEMInfA(dst_inf_name, 0, NULL); } } } } pLock->ReleaseWriteLock(); } pLock->Release(); } pNetCfg->Release(); } return ret; }
bool UninstallNdisProtocolDriver(wchar_t *id, UINT lock_timeout) { bool ret = false; HRESULT hr; INetCfg *pNetCfg; // Validate arguments if (id == NULL) { return false; } hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (void **)&pNetCfg); if (SUCCEEDED(hr)) { INetCfgLock *pLock; hr = pNetCfg->QueryInterface(IID_INetCfgLock, (PVOID*)&pLock); if (SUCCEEDED(hr)) { LPWSTR locked_by; hr = pLock->AcquireWriteLock(lock_timeout, L"SoftEther VPN", &locked_by); if (SUCCEEDED(hr)) { hr = pNetCfg->Initialize(NULL); if (SUCCEEDED(hr)) { INetCfgComponent *pComponent; hr = pNetCfg->FindComponent(id, &pComponent); if (SUCCEEDED(hr)) { INetCfgClassSetup *pSetup; hr = pNetCfg->QueryNetCfgClass(&GUID_DEVCLASS_NETTRANS, IID_INetCfgClassSetup, (void **)&pSetup); if (SUCCEEDED(hr)) { OBO_TOKEN token; SeZero(&token, sizeof(token)); token.Type = OBO_USER; hr = pSetup->DeInstall(pComponent, &token, NULL); if (SUCCEEDED(hr)) { pNetCfg->Apply(); ret = true; } pSetup->Release(); } } } pLock->ReleaseWriteLock(); } pLock->Release(); } pNetCfg->Release(); } return ret; }
// VPN 内における ping の送信 void SeVpn6IPsecSendPing(SE_VPN6 *v6) { SE_VPN *v; SE_BUF *icmp_buf; SE_VPN_CONFIG *c; UINT i, data_size; UCHAR *data; // 引数チェック if (v6 == NULL) { return; } v = v6->Vpn; c = v->Config; if (Se6IsZeroIP(v6->GuestIpAddress)) { return; } data_size = c->VpnPingMsgSizeV6; data = SeMalloc(data_size); for (i = 0;i < data_size;i++) { data[i] = 'A' + (i % ('Z' - 'A')); } icmp_buf = Se6BuildIcmpEchoPacket(v6->GuestIpAddress, c->VpnPingTargetV6, SE_ICMPV6_TYPE_ECHO_REQUEST, 0, v6->icmp_id++, v6->icmp_seq_no++, data, data_size); if (icmp_buf != NULL) { SE_IPV6_HEADER_PACKET_INFO info; SE_IPV6_HEADER ip_header; SE_LIST *o; UINT i; // IPv6 ヘッダ SeZero(&ip_header, sizeof(ip_header)); SE_IPV6_SET_VERSION(&ip_header, 6); ip_header.HopLimit = SE_IPV6_HOP_DEFAULT; ip_header.SrcAddress = v6->GuestIpAddress; ip_header.DestAddress = c->VpnPingTargetV6; // IPv6 パケットの構築 SeZero(&info, sizeof(info)); info.Protocol = SE_IP_PROTO_ICMPV6; info.IPv6Header = &ip_header; info.Payload = icmp_buf->Buf; info.PayloadSize = icmp_buf->Size; o = SeBuildIPv6PacketWithFragment(&info, v6->icmp_ip_packet_id++, v->IPv6_Virtual->Mtu); for (i = 0;i < SE_LIST_NUM(o);i++) { SE_BUF *buf = SE_LIST_DATA(o, i); if (v6->VirtualIpRecvCallback != NULL) { v6->VirtualIpRecvCallback(buf->Buf, buf->Size, v6->VirtualIpRecvCallbackParam); } } SeFreePacketList(o); } SeFreeBuf(icmp_buf); SeFree(data); }
// IKE パケットの構築 SE_BUF *SeIkeBuild(SE_IKE_PACKET *p, SE_IKE_CRYPTO_PARAM *cparam) { SE_IKE_HEADER h; SE_BUF *msg_buf; SE_BUF *ret; // 引数チェック if (p == NULL) { return NULL; } SeZero(&h, sizeof(h)); h.InitiatorCookie = p->InitiatorCookie; h.ResponderCookie = p->ResponderCookie; h.NextPayload = SeIkeGetFirstPayloadType(p->PayloadList); h.Version = SE_IKE_VERSION; h.ExchangeType = p->ExchangeType; h.Flag = (p->FlagEncrypted ? SE_IKE_HEADER_FLAG_ENCRYPTED : 0) | (p->FlagCommit ? SE_IKE_HEADER_FLAG_COMMIT : 0) | (p->FlagAuthOnly ? SE_IKE_HEADER_FLAG_AUTH_ONLY : 0); h.MessageId = SeEndian32(p->MessageId); msg_buf = SeIkeBuildPayloadList(p->PayloadList); if (p->DecryptedPayload != NULL) { SeFreeBuf(p->DecryptedPayload); } p->DecryptedPayload = SeCloneBuf(msg_buf); if (p->FlagEncrypted) { SE_BUF *b; // 暗号化 b = SeIkeEncryptWithPadding(msg_buf->Buf, msg_buf->Size, cparam); if (b == NULL) { SeError("ISAKMP: Packet Encrypt Failed"); SeFreeBuf(msg_buf); return NULL; } SeFreeBuf(msg_buf); msg_buf = b; } h.MessageSize = SeEndian32(msg_buf->Size + sizeof(h)); ret = SeNewBuf(); SeWriteBuf(ret, &h, sizeof(h)); SeWriteBufBuf(ret, msg_buf); SeFreeBuf(msg_buf); SeSeekBuf(ret, 0, 0); return ret; }