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); }
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; } }
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(); }