コード例 #1
0
    public ThinDatabase(ThinController controller)
    {
        try
        {
            this.BackupFileName = PP.Combine(Env.AppLocalDir, "Config", "ThinControllerDatabaseBackupCache", "DatabaseBackupCache.json");

            this.Controller = controller;

            this.ReadMainLoopTask  = ReadMainLoopAsync(this.GrandCancel)._LeakCheck();
            this.WriteMainLoopTask = WriteMainLoopAsync(this.GrandCancel)._LeakCheck();
        }
        catch
        {
            this._DisposeSafe();
            throw;
        }
    }
コード例 #2
0
    // PCID 変更実行
    public async Task <VpnError> RenamePcidAsync(string msid, string newPcid, DateTime now, CancellationToken cancel = default)
    {
        // この関数は同時に 1 ユーザーからしか実行されないようにする
        // (ローカルメモリデータベースをいじるため)
        using var asyncLock = await RenamePcidAsyncLock.LockWithAwait(cancel);

        msid    = msid._NonNullTrim();
        newPcid = newPcid._NonNullTrim();

        VpnError err2 = ThinController.CheckPCID(newPcid);

        if (err2 != VpnError.ERR_NO_ERROR)
        {
            return(err2);
        }

        VpnError err = VpnError.ERR_INTERNAL_ERROR;

        // ローカルメモリデータベース上の PCID 情報を確認
        var memDb = this.MemDb !;

        if (memDb.MachineList.Where(x => x.PCID._IsSamei(newPcid)).Any())
        {
            // ローカルメモリデータベース上で重複
            return(VpnError.ERR_PCID_ALREADY_EXISTS);
        }

        if (this.IsDatabaseConnected == false)
        {
            // データベースエラー発生中はこの処理は実行できない
            return(VpnError.ERR_TEMP_ERROR);
        }

        await using var db = await OpenDatabaseForWriteAsync(cancel);

        Controller.Throughput_DatabaseWrite.Add(1);

        ThinDbMachine?updatedMachine = null;

        // トランザクションを確立し厳格なチェックを実施
        // (DB サーバー側で一意インデックスによりチェックするが、インデックスが間違っていた場合に備えて、トランザクションでも厳密にチェックするのである)
        if (await db.TranAsync(async() =>
        {
            // MACHINE を取得
            var machine = await db.EasySelectSingleAsync <ThinDbMachine>("SELECT * FROM MACHINE WHERE MSID = @MSID", new { MSID = msid }, false, true, cancel);
            if (machine == null)
            {
                // おかしいな
                err = VpnError.ERR_SECURITY_ERROR;
                return(false);
            }

            // 同一 PCID が存在しないかどうかチェック
            if ((await db.QueryWithValueAsync("SELECT COUNT(MACHINE_ID) FROM MACHINE WHERE PCID = @ AND SVC_NAME = @", newPcid, machine.SVC_NAME)).Int != 0)
            {
                err = VpnError.ERR_PCID_ALREADY_EXISTS;
                return(false);
            }

            // 変更の実行
            await db.QueryWithNoReturnAsync("UPDATE MACHINE SET PCID = @, UPDATE_DATE = @, PCID_UPDATE_DATE = @, PCID_VER = PCID_VER + 1 WHERE MSID = @",
                                            newPcid, now, now, msid);

            // 変更した結果を取得
            updatedMachine = await db.EasySelectSingleAsync <ThinDbMachine>("SELECT * FROM MACHINE WHERE MSID = @MSID", new { MSID = msid }, false, true, cancel);
            if (updatedMachine == null)
            {
                // おかしいな
                err = VpnError.ERR_SECURITY_ERROR;
                return(false);
            }

            return(true);
        }) == false)
        {
            return(err);
        }

        updatedMachine._MarkNotNull();

        Controller.AddPcidToRecentPcidCandidateCache(newPcid);

        // ローカルメモリデータベース上の PCID 情報を変更
        var machine = memDb.MachineByMsid._GetOrDefault(msid);

        if (machine != null)
        {
            machine.PCID             = newPcid;
            machine.PCID_UPDATE_DATE = updatedMachine.PCID_UPDATE_DATE;
            machine.PCID_VER         = updatedMachine.PCID_VER;

            // メモリ上の PCID Dictionary をリビルド
            memDb.RebuildPcidListOnMemory();

            // PCID 変更履歴の更新
            this.PcidChangeHistoryCache.Add(machine.MSID, new ThinDatabasePcidChangeHistory(machine.MSID, machine.PCID_VER, newPcid, updatedMachine.PCID_UPDATE_DATE));
        }

        return(VpnError.ERR_NO_ERROR);
    }
コード例 #3
0
    // サーバー登録実行
    public async Task <VpnError> RegisterMachineAsync(string svcName, string msid, string pcid, string hostKey, string hostSecret2, DateTime now, string ip, string fqdn, string initialJsonAttributes, CancellationToken cancel = default)
    {
        svcName               = svcName._NonNullTrim();
        msid                  = msid._NonNullTrim();
        pcid                  = pcid._NonNullTrim();
        hostKey               = hostKey._NonNullTrim();
        hostSecret2           = hostSecret2._NonNullTrim();
        ip                    = ip._NonNullTrim();
        fqdn                  = fqdn._NonNullTrim();
        initialJsonAttributes = initialJsonAttributes._NonNullTrim();

        VpnError err2 = ThinController.CheckPCID(pcid);

        if (err2 != VpnError.ERR_NO_ERROR)
        {
            return(err2);
        }

        // データベースエラー時は処理禁止
        if (IsDatabaseConnected == false)
        {
            return(VpnError.ERR_TEMP_ERROR);
        }

        VpnError err = VpnError.ERR_INTERNAL_ERROR;

        await using var db = await OpenDatabaseForWriteAsync(cancel);

        Controller.Throughput_DatabaseWrite.Add(1);

        // トランザクションを確立し厳格なチェックを実施
        // (DB サーバー側で一意インデックスによりチェックするが、インデックスが間違っていた場合に備えて、トランザクションでも厳密にチェックするのである)
        if (await db.TranAsync(async() =>
        {
            // 同一 hostKey が存在しないかどうか確認
            if ((await db.QueryWithValueAsync("SELECT COUNT(MACHINE_ID) FROM MACHINE WHERE CERT_HASH = @", hostKey)).Int != 0)
            {
                err = VpnError.ERR_SECURITY_ERROR;
                return(false);
            }

            // 同一シークレットが存在しないかどうかチェック
            if ((await db.QueryWithValueAsync("SELECT COUNT(MACHINE_ID) FROM MACHINE WHERE HOST_SECRET2 = @", hostSecret2)).Int != 0)
            {
                err = VpnError.ERR_SECURITY_ERROR;
                return(false);
            }

            // 同一 PCID が存在しないかどうかチェック
            if ((await db.QueryWithValueAsync("SELECT COUNT(MACHINE_ID) FROM MACHINE WHERE PCID = @ AND SVC_NAME = @", pcid, svcName)).Int != 0)
            {
                err = VpnError.ERR_PCID_ALREADY_EXISTS;
                return(false);
            }

            // 登録の実行
            await db.QueryWithNoReturnAsync("INSERT INTO MACHINE (SVC_NAME, MSID, PCID, CERT_HASH, CREATE_DATE, UPDATE_DATE, LAST_SERVER_DATE, LAST_CLIENT_DATE, NUM_SERVER, NUM_CLIENT, CREATE_IP, CREATE_HOST, HOST_SECRET2, PCID_UPDATE_DATE, JSON_ATTRIBUTES) " +
                                            "VALUES (@, @, @, @, @, @, @, @, @, @, @, @, @, @, @)",
                                            svcName, msid, pcid, hostKey,
                                            now, now, now, now,
                                            0, 0,
                                            ip, fqdn,
                                            hostSecret2,
                                            now, initialJsonAttributes);

            return(true);
        }) == false)
        {
            return(err);
        }

        Controller.AddPcidToRecentPcidCandidateCache(pcid);

        return(VpnError.ERR_NO_ERROR);
    }