示例#1
0
    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);
    }
示例#2
0
    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);
    }
示例#3
0
    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);
    }
示例#4
0
    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;
        }
    }
示例#5
0
    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);
    }
示例#6
0
    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();
    }