Пример #1
0
 private static bool HandleAuthentication(ClientStateInfo clientInfo, TcpClient client, SharedNetwork.SharedNetworkInfo sharedInfo)
 {
     if (Config.RequiresAuthentication)
     {
         int flags = ((Config.AllowUnauthenticatedWrite ? 2 : 0) | (Config.AllowUnauthenticatedRead ? 1 : 0));
         if (clientInfo.BareAccessRequired)
             flags = 0;
         ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(client.GetStream(), new NetCommand() { Type = NetCommandType.Authenticate, Identifier = flags }, ProtoBuf.PrefixStyle.Fixed32);
         AuthenticationChallenge challenge = new AuthenticationChallenge();
         challenge.AvailableModes = new List<AuthenticationMode>();
         if (Config.SupportsSimpleAuthentication)
             challenge.AvailableModes.Add(AuthenticationMode.Simple);
         challenge.Salt = BCrypt.Net.BCrypt.GenerateSalt();
         ProtoBuf.Serializer.SerializeWithLengthPrefix(client.GetStream(), challenge, ProtoBuf.PrefixStyle.Fixed32);
         int retries = Config.AuthenticationAttempts;
         bool success = false;
         while (true)
         {
             var response = ProtoBuf.Serializer.DeserializeWithLengthPrefix<AuthenticationResponse>(client.GetStream(), ProtoBuf.PrefixStyle.Fixed32);
             Rights accessRights;
             if (CheckAuthentication(response, challenge.Salt, out accessRights))
             {
                 clientInfo.Access = accessRights;
                 success = true;
                 break;
             }
             else
             {
                 if (--retries == 0)
                     break;
                 ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(client.GetStream(), new NetCommand() { Type = NetCommandType.AuthRetry }, ProtoBuf.PrefixStyle.Fixed32);
             }
         }
         if (success)
             ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(client.GetStream(), new NetCommand() { Type = NetCommandType.Acknowledge }, ProtoBuf.PrefixStyle.Fixed32);
         else
         {
             ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(client.GetStream(), new NetCommand() { Type = NetCommandType.AuthFail }, ProtoBuf.PrefixStyle.Fixed32);
             return false;
         }
     }
     else
     {
         ProtoBuf.Serializer.SerializeWithLengthPrefix<NetCommand>(client.GetStream(), new NetCommand() { Type = NetCommandType.SkipAuthentication }, ProtoBuf.PrefixStyle.Fixed32);
     }
     return true;
 }
Пример #2
0
 internal static void GetAncestryInternal(HashSet<Guid> checkedVersions, Guid version, SharedNetwork.SharedNetworkInfo clientInfo)
 {
     Guid nextVersionToCheck = version;
     while (nextVersionToCheck != null)
     {
         if (checkedVersions.Contains(nextVersionToCheck))
             return;
         checkedVersions.Add(nextVersionToCheck);
         List<MergeInfo> mergeInfo;
         Objects.Version v = FindLocalOrRemoteVersionInfo(nextVersionToCheck, clientInfo, out mergeInfo);
         foreach (var x in mergeInfo)
         {
             GetAncestryInternal(checkedVersions, x.SourceVersion, clientInfo);
         }
         if (!v.Parent.HasValue)
             return;
         nextVersionToCheck = v.Parent.Value;
     }
 }
Пример #3
0
 private static void ReceiveRecordParents(SharedNetwork.SharedNetworkInfo sharedInfo, RecordParentPack response)
 {
     foreach (var x in response.Parents)
     {
         CheckRecord(sharedInfo, x);
     }
 }
Пример #4
0
 internal static bool IsAncestorInternal(HashSet<Guid> checkedVersions, Guid ancestor, Guid possibleChild, SharedNetwork.SharedNetworkInfo clientInfo)
 {
     Guid nextVersionToCheck = possibleChild;
     if (ancestor == possibleChild)
         return true;
     while (true)
     {
         if (checkedVersions.Contains(nextVersionToCheck))
             return false;
         checkedVersions.Add(nextVersionToCheck);
         List<MergeInfo> mergeInfo;
         Objects.Version v = FindLocalOrRemoteVersionInfo(nextVersionToCheck, clientInfo, out mergeInfo);
         if (!v.Parent.HasValue)
             return false;
         else if (v.Parent.Value == ancestor)
             return true;
         foreach (var x in mergeInfo)
         {
             if (IsAncestorInternal(checkedVersions, ancestor, x.SourceVersion, clientInfo))
                 return true;
         }
         nextVersionToCheck = v.Parent.Value;
     }
 }
Пример #5
0
 internal static Objects.Version FindLocalOrRemoteVersionInfo(Guid possibleChild, SharedNetwork.SharedNetworkInfo clientInfo, out List<MergeInfo> mergeInfo)
 {
     VersionInfo info = clientInfo.PushedVersions.Where(x => x.Version.ID == possibleChild).FirstOrDefault();
     if (info != null)
     {
         mergeInfo = info.MergeInfos != null ? info.MergeInfos.ToList() : new List<MergeInfo>();
         return info.Version;
     }
     Objects.Version localVersion = clientInfo.Workspace.GetVersion(possibleChild);
     mergeInfo = clientInfo.Workspace.GetMergeInfo(localVersion.ID).ToList();
     return localVersion;
 }
Пример #6
0
 internal static void ImportBranches(SharedNetwork.SharedNetworkInfo sharedInfo)
 {
     Printer.PrintDiagnostics("Received branches:");
     foreach (var x in sharedInfo.ReceivedBranches)
     {
         Printer.PrintDiagnostics(" - {0}: \"{1}\"", x.ID, x.Name);
         sharedInfo.Workspace.ImportBranchNoCommit(x);
     }
     Printer.PrintDiagnostics("Branches imported.");
 }
Пример #7
0
 internal static bool IsAncestor(Guid ancestor, Guid possibleChild, SharedNetwork.SharedNetworkInfo clientInfo)
 {
     HashSet<Guid> checkedVersions = new HashSet<Guid>();
     return IsAncestorInternal(checkedVersions, ancestor, possibleChild, clientInfo);
 }
Пример #8
0
        private bool PullVersions(SharedNetwork.SharedNetworkInfo sharedInfo, out bool receivedData)
        {
            bool importResult = sharedInfo.Workspace.RunLocked(() =>
            {
                return SharedNetwork.ImportRecords(sharedInfo, true);
            }, false);
            receivedData = false;
            if (!importResult)
                return false;
            if (sharedInfo.PushedVersions.Count == 0 && sharedInfo.ReceivedBranchJournals.Count == 0 && sharedInfo.ReceivedBranches.Count == 0)
                return true;
            receivedData = true;
            return sharedInfo.Workspace.RunLocked(() =>
            {
                lock (sharedInfo.Workspace)
                {
                    try
                    {
                        sharedInfo.Workspace.BeginDatabaseTransaction();
                        if (!SharedNetwork.ImportBranchJournal(sharedInfo, true))
                            return false;
                        SharedNetwork.ImportBranches(sharedInfo);
                        Dictionary<Guid, List<Head>> temporaryHeads = new Dictionary<Guid, List<Head>>();
                        Dictionary<Guid, Guid> pendingMerges = new Dictionary<Guid, Guid>();
                        Dictionary<Guid, HashSet<Guid>> headAncestry = new Dictionary<Guid, HashSet<Guid>>();
                        HashSet<Guid> terminatedBranches = new HashSet<Guid>();
                        List<Guid> mergeResults = new List<Guid>();
                        foreach (var x in ((IEnumerable<VersionInfo>)sharedInfo.PushedVersions).Reverse())
                        {
                            if (terminatedBranches.Contains(x.Version.Branch))
                                continue;
                            List<Head> heads;
                            if (!temporaryHeads.TryGetValue(x.Version.Branch, out heads))
                            {
                                Branch branch = sharedInfo.Workspace.GetBranch(x.Version.Branch);
                                if (branch.Terminus.HasValue)
                                {
                                    terminatedBranches.Add(branch.ID);
                                    continue;
                                }
                                heads = new List<Head>();
                                var bheads = sharedInfo.Workspace.GetBranchHeads(branch);
                                if (bheads.Count == 0)
                                    heads.Add(new Head() { Branch = branch.ID, Version = x.Version.ID });
                                else
                                {
                                    foreach (var h in bheads)
                                        heads.Add(h);
                                }
                                temporaryHeads[branch.ID] = heads;
                            }
                            mergeResults.Clear();
                            for (int i = 0; i < heads.Count; i++)
                            {
                                if (heads[i].Version != x.Version.ID)
                                {
                                    HashSet<Guid> headAncestors = null;
                                    if (!headAncestry.TryGetValue(heads[i].Version, out headAncestors))
                                    {
                                        headAncestors = SharedNetwork.GetAncestry(heads[i].Version, sharedInfo);
                                        headAncestry[heads[i].Version] = headAncestors;
                                    }
                                    if (headAncestors.Contains(x.Version.ID))
                                    {
                                        // all best
                                        mergeResults.Add(heads[i].Version);
                                    }
                                    else if (SharedNetwork.IsAncestor(heads[i].Version, x.Version.ID, sharedInfo))
                                    {
                                        mergeResults.Add(x.Version.ID);
                                    }
                                    else
                                    {
                                        mergeResults.Add(Guid.Empty);
                                    }
                                }
                            }
                            pendingMerges[x.Version.Branch] = Guid.Empty;
                            // Remove any superceded heads
                            // Add a merge if required
                            bool unrelated = true;
                            for (int i = 0; i < mergeResults.Count; i++)
                            {
                                if (mergeResults[i] == Guid.Empty)
                                    continue;
                                else if (mergeResults[i] != heads[i].Version)
                                {
                                    headAncestry.Remove(heads[i].Version);
                                    heads[i].Version = x.Version.ID;
                                    unrelated = false;
                                }
                                else
                                    unrelated = false;
                            }
                            if (unrelated)
                            {
                                heads.Add(new Head() { Branch = x.Version.Branch, Version = x.Version.ID });
                            }
                            for (int i = 0; i < heads.Count; i++)
                            {
                                for (int j = i + 1; j < heads.Count; j++)
                                {
                                    if (heads[i].Version == heads[j].Version)
                                    {
                                        heads.RemoveAt(j);
                                        --j;
                                    }
                                }
                            }
                        }
                        List<Head> newHeads = new List<Head>();
                        List<VersionInfo> autoMerged = new List<VersionInfo>();
                        foreach (var x in pendingMerges)
                        {
                            Branch branch = sharedInfo.Workspace.GetBranch(x.Key);
                            List<Head> heads = temporaryHeads[x.Key];
                            var bheads = sharedInfo.Workspace.GetBranchHeads(branch);

                            bool headsChanged = bheads.Count != heads.Count;
                            if (!headsChanged)
                            {
                                for (int i = 0; i < bheads.Count; i++)
                                {
                                    if (bheads[i].Version != heads[i].Version)
                                        headsChanged = true;
                                }
                            }

                            if (!headsChanged)
                            {
                                temporaryHeads[x.Key] = null;
                                continue;
                            }

                            if (heads.Count == 1)
                            {
                                Printer.PrintDiagnostics("Uncontested head update for branch \"{0}\".", Workspace.GetBranch(x.Key).Name);
                                Printer.PrintDiagnostics(" - Head updated to {0}", temporaryHeads[x.Key][0].Version);
                                continue;
                            }

                            var localVersions = bheads.Where(h => heads.Any(y => y.Version != h.Version));
                            var remoteVersions = heads.Where(h => !bheads.Any(y => y.Version != h.Version));

                            if (localVersions.Count() != 1)
                            {
                                Printer.PrintDiagnostics("Too many heads in local branch to merge remote head. Please merge locally and try again to update branch \"{0}\".", Workspace.GetBranch(x.Key).Name);
                                return false;
                            }

                            Guid localVersion = localVersions.First().Version;

                            if (remoteVersions.Count() == 1)
                            {
                                VersionInfo result;
                                string error;
                                result = Workspace.MergeRemote(Workspace.GetLocalOrRemoteVersion(localVersion, sharedInfo), remoteVersions.First().Version, sharedInfo, out error, true);

                                Printer.PrintMessage("Resolved incoming merge for branch \"{0}\".", branch.Name);
                                Printer.PrintDiagnostics(" - Merge local input {0}", localVersion);
                                Printer.PrintDiagnostics(" - Merge remote input {0}", remoteVersions.First().Version);
                                Printer.PrintDiagnostics(" - Head updated to {0}", result.Version.ID);

                                for (int i = 0; i < heads.Count; i++)
                                {
                                    if ((remoteVersions.Any() && heads[i].Version == remoteVersions.First().Version) || heads[i].Version == localVersion)
                                    {
                                        heads.RemoveAt(i);
                                        --i;
                                    }
                                }
                                heads.Add(new Head() { Branch = branch.ID, Version = result.Version.ID });
                                autoMerged.Add(result);
                            }
                        }
                        var versionsToImport = sharedInfo.PushedVersions.OrderBy(x => x.Version.Timestamp).ToArray();
                        if (versionsToImport.Length != 0)
                        {
                            Dictionary<Guid, bool> importList = new Dictionary<Guid, bool>();
                            foreach (var x in versionsToImport)
                                importList[x.Version.ID] = false;
                            int importCount = versionsToImport.Length;
                            var orderedImports = versionsToImport.OrderBy(x => x.Version.Revision).ToList();
                            Printer.InteractivePrinter printer = null;
                            Printer.PrintMessage("Importing #b#{0}## versions...", orderedImports.Count);
                            printer = Printer.CreateProgressBarPrinter("Importing", string.Empty,
                                    (obj) =>
                                    {
                                        return string.Empty;
                                    },
                                    (obj) =>
                                    {
                                        return (100.0f * (int)(orderedImports.Count - importCount)) / (float)orderedImports.Count;
                                    },
                                    (pct, obj) =>
                                    {
                                        return string.Format("{0}/{1}", (int)(orderedImports.Count - importCount), orderedImports.Count);
                                    },
                                    60);
                            while (importCount > 0)
                            {
                                foreach (var x in orderedImports)
                                {
                                    if (importList[x.Version.ID] != true)
                                    {
                                        bool accept;
                                        if (!x.Version.Parent.HasValue || !importList.TryGetValue(x.Version.Parent.Value, out accept))
                                            accept = true;
                                        if (accept)
                                        {
                                            sharedInfo.Workspace.ImportVersionNoCommit(sharedInfo, x, true);
                                            importList[x.Version.ID] = true;
                                            importCount--;
                                            printer.Update(importCount);
                                        }
                                    }
                                }
                            }
                            printer.End(importCount);
                        }
                        Printer.PrintMessage("Updating internal state...");
                        foreach (var x in autoMerged)
                            Workspace.ImportVersionNoCommit(sharedInfo, x, false);
                        foreach (var x in temporaryHeads)
                        {
                            if (x.Value != null)
                                Workspace.ReplaceHeads(x.Key, x.Value);
                        }
                        Workspace.CommitDatabaseTransaction();
                        sharedInfo.Workspace.CommitDatabaseTransaction();
                        return true;
                    }
                    catch
                    {
                        sharedInfo.Workspace.RollbackDatabaseTransaction();
                        throw;
                    }
                }
            }, false);
        }
Пример #9
0
 public static StartTransaction Create(string domain, SharedNetwork.Protocol protocol)
 {
     return new StartTransaction() { ServerHandshake = Handshake.Create(protocol), Domain = domain, Encrypted = false, Accepted = true };
 }
Пример #10
0
 public static StartTransaction Create(string domain, System.Security.Cryptography.RSAParameters publicKey, SharedNetwork.Protocol protocol)
 {
     return new StartTransaction() { ServerHandshake = Handshake.Create(protocol), Domain = domain, RSAKey = publicKey, Accepted = true, Encrypted = true };
 }
Пример #11
0
 public static Handshake Create(SharedNetwork.Protocol protocol)
 {
     return new Handshake() { VersionrProtocol = GetProtocolString(protocol) };
 }
Пример #12
0
 public static string GetProtocolString(SharedNetwork.Protocol protocol)
 {
     return Protocols[protocol];
 }