public async Task ExecuteWoLAsync(ThinClientConnectOptions connectOptions, string targetPcid, CancellationToken cancel = default) { if (connectOptions.ClientOptions.Flags.Bit(WideTunnelClientFlags.WoL) == false) { throw new CoresLibException("connectOptions.ClientOptions.Flags.Bit(WideTunnelClientFlags.WoL) == false"); } await using WideTunnel wt = new WideTunnel(this.Options.WideTunnelOptions); // Mac アドレスリストの取得 string macList = await wt.WideClientGetWoLMacList(targetPcid, cancel); // ターゲット PC に叩き起こし依頼 await using WtcSocket? sock = await wt.WideClientConnectAsync(connectOptions.Pcid, connectOptions.ClientOptions, true, cancel); await using PipeStream? st = sock.GetStream(true); st.ReadTimeout = st.WriteTimeout = Consts.ThinClient.ProtocolCommTimeoutMsecs; Pack p = new Pack(); p.AddInt("ClientVer", Consts.ThinClient.DummyClientVer); p.AddInt("ClientBuild", Consts.ThinClient.DummyClientBuild); p.AddBool("WoLMode", true); p.AddStr("mac_list", macList); await st._SendPackAsync(p, cancel); p = await st._RecvPackAsync(cancel); var err = p.GetErrorFromPack(); err.ThrowIfError(p); }
public async Task <string> WideClientGetWoLMacList(string pcid, CancellationToken cancel = default) { Pack r = new Pack(); r.AddStr("SvcName", Options.SvcName); r.AddStr("Pcid", pcid); r.AddSInt("Ver", CoresConfig.WtcConfig.PseudoVer); r.AddSInt("Build", CoresConfig.WtcConfig.PseudoBuild); r.AddData("ClientId", Options.ClientId); var p = await WtWpcCall("ClientGetWoLMacList", r, cancel); p.ThrowIfError(); string list = p["wol_maclist"].StrValueNonNull; if (list._IsEmpty()) { throw new VpnException(VpnError.ERR_WOL_TARGET_NOT_ENABLED); } return(list); }
async Task <Pack> WtWpcCallInner(string functionName, Pack requestPack, string url, CancellationToken cancel = default) { requestPack.AddStr("function", functionName); WpcPack wpcPostPack = new WpcPack(requestPack); var wpcPostBuffer = wpcPostPack.ToPacketBinary().Span.ToArray(); using var http = new WebApi(this.Options.WebApiOptions, this.CheckValidationCallback); var webRet = await http.SimplePostDataAsync(url, wpcPostBuffer, cancel, Consts.MimeTypes.FormUrlEncoded); WpcPack wpcResponsePack = WpcPack.Parse(webRet.ToString(), false); var retPack = wpcResponsePack.Pack; Uri uri = url._ParseUrl(); retPack.AddStr("__remote_hostname", uri.Host); retPack.AddSInt("__remote_port", uri.Port); return(retPack); }
async Task <ThinClientConnection> DcConnectEx(WideTunnel wt, ThinClientConnectOptions connectOptions, CancellationToken cancel, bool checkPort, bool firstConnection, Func <ThinClientAuthRequest, CancellationToken, Task <ThinClientAuthResponse> > authCallback, Func <ThinClientOtpRequest, CancellationToken, Task <ThinClientOtpResponse> > otpCallback, Func <ThinClientInspectRequest, CancellationToken, Task <ThinClientInspectResponse> > inspectCallback) { string otpTicket = ""; string inspectTicket = ""; WtcSocket? sock = null; PipeStream?st = null; if (checkPort == false && connectOptions.DebugGuacMode == false) { throw new CoresLibException("checkPort == false && connectOptions.DebugGuacMode == false"); } try { sock = await wt.WideClientConnectAsync(connectOptions.Pcid, connectOptions.ClientOptions, false, cancel); st = sock.GetStream(true); st.ReadTimeout = st.WriteTimeout = Consts.ThinClient.ProtocolCommTimeoutMsecs; // バージョンを送信 Pack p = new Pack(); p.AddInt("ClientVer", Consts.ThinClient.DummyClientVer); p.AddInt("ClientBuild", Consts.ThinClient.DummyClientBuild); p.AddBool("CheckPort", checkPort); p.AddBool("FirstConnection", firstConnection); p.AddBool("HasURDP2Client", true); p.AddBool("SupportOtp", true); p.AddBool("SupportOtpEnforcement", true); p.AddBool("SupportInspect", true); p.AddBool("SupportServerAllowedMacListErr", true); p.AddIp("ClientLocalIP", connectOptions.ClientIpAddress); p.AddUniStr("UserName", "HTML5 WebClient"); p.AddUniStr("ComputerName", "HTML5 WebClient"); p.AddBool("SupportWatermark", true); p.AddBool("GuacdMode", connectOptions.DebugGuacMode == false); GuaDnFlags flags = GuaDnFlags.None; if (connectOptions.GuaPreference?.EnableAlwaysWebp ?? false) { flags |= GuaDnFlags.AlwaysWebp; } p.AddInt("GuacdFlags", (uint)flags); await st._SendPackAsync(p, cancel); // 認証パラメータを受信 p = await st._RecvPackAsync(cancel); var err = p.GetErrorFromPack(); err.ThrowIfError(p); var authType = (ThinAuthType)p["AuthType"].SIntValueSafeNum; var svcType = (ThinSvcType)p["ServiceType"].SIntValueSafeNum; var svcPort = (int)p["ServicePort"].SIntValueSafeNum; var caps = (ThinServerCaps)p["DsCaps"].SIntValueSafeNum; var rand = p["Rand"].DataValueNonNull; var machineKey = p["MachineKey"].DataValueNonNull; var isShareDisabled = p["IsShareDisabled"].BoolValue; var useAdvancedSecurity = p["UseAdvancedSecurity"].BoolValue; var isOtpEnabled = p["IsOtpEnabled"].BoolValue; var runInspect = p["RunInspect"].BoolValue; var lifeTime = p["Lifetime"].SInt64Value; var lifeTimeMsg = p["LifeTimeMsg"].UniStrValueNonNull; var waterMarkStr1 = p["WatermarkStr1"].UniStrValueNonNull; var waterMarkStr2 = p["WatermarkStr2"].UniStrValueNonNull; var idleTimeout = p["IdleTimeout"].SIntValueSafeNum; var isLimitedFirewallMandated = p["IsLimitedFirewallMandated"].BoolValue; if (isLimitedFirewallMandated) { // 完全閉域化 FW が強制されているが HTML5 版ではサポートされていない throw new VpnException(VpnError.ERR_DESK_GOVFW_HTML5_NO_SUPPORT); } if (isOtpEnabled) { // OTP 認証 ThinClientOtpRequest otpReq = new ThinClientOtpRequest(); var otpRes = await otpCallback(otpReq, cancel); p = new Pack(); p.AddStr("Otp", otpRes.Otp._NonNull()); await st._SendPackAsync(p, cancel); // 結果を受信 p = await st._RecvPackAsync(cancel); p.ThrowIfError(); // OTP チケットを保存 otpTicket = p["OtpTicket"].StrValueNonNull; } if (runInspect) { // 検疫および MAC アドレス認証 ThinClientInspectRequest inspectReq = new ThinClientInspectRequest(); var inspectRes = await inspectCallback(inspectReq, cancel); p = new Pack(); p.AddBool("AntiVirusOk", inspectRes.AntiVirusOk); p.AddBool("WindowsUpdateOk", inspectRes.WindowsUpdateOk); p.AddStr("MacAddressList", inspectRes.MacAddressList._NonNull()); p.AddStr("Ticket", inspectRes.Ticket._NonNull()); await st._SendPackAsync(p, cancel); // 結果を受信 p = await st._RecvPackAsync(cancel); p.ThrowIfError(); // OTP チケットを保存 inspectTicket = p["InspectionTicket"].StrValueNonNull; } // ユーザー認証 p = new Pack(); if (useAdvancedSecurity == false) { // 古いユーザー認証 if (authType == ThinAuthType.None) { // 匿名認証 ThinClientAuthRequest authReq = new ThinClientAuthRequest { AuthType = ThinAuthType.None, }; var authRes = await authCallback(authReq, cancel); } else if (authType == ThinAuthType.Password) { // パスワード認証 ThinClientAuthRequest authReq = new ThinClientAuthRequest { AuthType = ThinAuthType.Password, }; var authRes = await authCallback(authReq, cancel); var passwordHash = Secure.HashSHA1(authRes.Password._GetBytes_UTF8()); p.AddData("SecurePassword", Secure.SoftEther_SecurePassword(passwordHash, rand)); } else { // そのような認証方法はサポートしていない throw new VpnException(VpnError.ERR_AUTHTYPE_NOT_SUPPORTED); } } else { // 高度なユーザー認証 ThinClientAuthRequest authReq = new ThinClientAuthRequest { AuthType = ThinAuthType.Advanced, }; var authRes = await authCallback(authReq, cancel); p.AddInt("authtype", 2); // CLIENT_AUTHTYPE_PLAIN_PASSWORD p.AddStr("username", authRes.Username); p.AddStr("plain_password", authRes.Password); } await st._SendPackAsync(p, cancel); // 結果を受信 p = await st._RecvPackAsync(cancel); err = p.GetErrorFromPack(); err.ThrowIfError(p); st.ReadTimeout = st.WriteTimeout = Timeout.Infinite; var misc = new ThinClientMiscParams(lifeTime, lifeTimeMsg, idleTimeout, isShareDisabled, caps.Bit(ThinServerCaps.AudioInSupported)); return(new ThinClientConnection(sock, st, svcType, svcPort, isShareDisabled, caps, runInspect, otpTicket, inspectTicket, waterMarkStr1, waterMarkStr2, misc)); } catch { await st._DisposeSafeAsync(); await sock._DisposeSafeAsync(); throw; } }
async Task <WtConnectParam> WideClientConnectInnerAsync(string pcid, WideTunnelClientOptions clientOptions, bool noCache, CancellationToken cancel = default) { if (noCache == false) { WtConnectParam?cached = ConnectParamCache[pcid]; if (cached != null) { var ret = cached._CloneDeep(); ret.CacheUsed = true; return(ret); } } Pack r = new Pack(); r.AddStr("SvcName", Options.SvcName); r.AddStr("Pcid", pcid); r.AddSInt("Ver", CoresConfig.WtcConfig.PseudoVer); r.AddSInt("Build", CoresConfig.WtcConfig.PseudoBuild); r.AddInt("ClientOptions", (uint)clientOptions.Flags); r.AddData("ClientId", Options.ClientId); var p = await WtWpcCall("ClientConnect", r, cancel); p.ThrowIfError(); WtConnectParam c = new WtConnectParam { HostName = p["Hostname"].StrValueNonNullCheck, HostNameForProxy = p["HostNameForProxy"].StrValueNonNullCheck, Port = p["Port"].SIntValue, SessionId = p["SessionId"].DataValueNonNull.ToArray(), ServerMask64 = p["ServerMask64"].Int64Value, WebSocketWildCardDomainName = p["WebSocketWildCardDomainName"].StrValueNonNull, ClientOptions = clientOptions._CloneDeep(), IsStandaloneMode = p["IsStandaloneMode"].BoolValue, }; if (c.WebSocketWildCardDomainName._IsEmpty()) { throw new CoresLibException("c.WebSocketWildCardDomainName is empty."); } if (c.HostName._IsSamei("<<!!samehost!!>>")) { string hostTmp = p["__remote_hostname"].StrValueNonNull; int portTmp = p["__remote_port"].SIntValue; if (hostTmp._IsFilled() && portTmp != 0) { c.HostName = hostTmp; c.Port = portTmp; } } c.CacheUsed = false; if (noCache == false) { WideTunnel.ConnectParamCache[pcid] = c._CloneDeep(); } return(c); }
public async Task StartWtcAsync(CancellationToken cancel = default) { if (Started.IsFirstCall() == false) { throw new ApplicationException("Already started."); } LowerStream.ReadTimeout = CoresConfig.WtcConfig.ConnectingTimeoutMsec; LowerStream.WriteTimeout = CoresConfig.WtcConfig.ConnectingTimeoutMsec; // シグネチャをアップロードする HttpHeader h = new HttpHeader("POST", "/widetunnel/connect.cgi", "HTTP/1.1"); h.ValueList.Add("Content-Type", "image/jpeg"); h.ValueList.Add("Connection", "Keep-Alive"); // 透かしデータのアップロード int randSize = Util.RandSInt31() % 2000; MemoryBuffer <byte> water = new MemoryBuffer <byte>(); water.Write(this.WideTunnel.Options.WaterMark); water.Write(Util.Rand(randSize)); await h.PostHttpAsync(LowerStream, water, cancel); // Hello パケットのダウンロード var hello = await LowerStream._HttpClientRecvPackAsync(cancel); if (hello["hello"].BoolValue == false) { throw new CoresLibException("Hello packet recv error."); } // 接続パラメータの送信 var p = new Pack(); p.AddData("client_id", WideTunnel.Options.ClientId); p.AddStr("method", "connect_session"); p.AddBool("use_compress", false); p.AddData("session_id", this.Options.ConnectParam.SessionId); p.AddSInt("ver", CoresConfig.WtcConfig.PseudoVer); p.AddSInt("build", CoresConfig.WtcConfig.PseudoBuild); p.AddStr("name_suite", this.WideTunnel.Options.NameSuite); p.AddBool("support_timeout_param", true); var clientOptions = Options.ConnectParam.ClientOptions; if (clientOptions.RealClientIp._IsFilled()) { p.AddBool("is_trusted", true); p.AddStr("trusted_real_client_ip", clientOptions.RealClientIp._NonNullTrim()); p.AddStr("trusted_real_client_fqdn", clientOptions.RealClientFqdn._NonNullTrim()); p.AddInt("trusted_real_client_port", (uint)clientOptions.RealClientPort); string auth_str = $"{clientOptions.RealClientIp._NonNullTrim()}/{clientOptions.RealClientFqdn._NonNullTrim()}/{(uint)clientOptions.RealClientPort}/{this.WideTunnel.Options.ControllerGateSecretKey}"; p.AddData("trusted_auth_sha1", auth_str._HashSHA1()); } await LowerStream._HttpClientSendPackAsync(p, cancel); // 結果の受信 p = await LowerStream._HttpClientRecvPackAsync(cancel); int code = p["code"].SIntValue; VpnError err = (VpnError)code; err.ThrowIfError(p); int tunnelTimeout = Consts.WideTunnelConsts.TunnelTimeout; int tunnelKeepalive = Consts.WideTunnelConsts.TunnelKeepAlive; bool tunnelUseAggressiveTimeout = false; int tunnelTimeout2 = p["tunnel_timeout"].SIntValue; int tunnelKeepAlive2 = p["tunnel_keepalive"].SIntValue; bool tunnelUseAggressiveTimeout2 = p["tunnel_use_aggressive_timeout"].BoolValue; if (tunnelTimeout2 >= 1 && tunnelKeepAlive2 >= 1) { tunnelTimeout = tunnelTimeout2; tunnelKeepalive = tunnelKeepAlive2; tunnelUseAggressiveTimeout = tunnelUseAggressiveTimeout2; } this.WebSocketUrl = p["websocket_url"].StrValue !; if (this.WebSocketUrl._IsEmpty()) { throw new CoresLibException("This version of the destination ThinGate has no WebSocket capability."); } LowerStream.ReadTimeout = tunnelTimeout; LowerStream.WriteTimeout = Timeout.Infinite; this.SendTask = SendLoopAsync(tunnelKeepalive)._LeakCheck(); this.RecvTask = RecvLoopAsync()._LeakCheck(); }