コード例 #1
0
ファイル: UpdaterManager.cs プロジェクト: rjodra/duplicati
        public static bool VerifyUnpackedFolder(string folder, UpdateInfo version = null)
        {
            try
            {
                UpdateInfo update;
                FileEntry manifest;

                var sha256 = System.Security.Cryptography.SHA256.Create();
                var md5 = System.Security.Cryptography.MD5.Create();

                using(var fs = System.IO.File.OpenRead(System.IO.Path.Combine(folder, UPDATE_MANIFEST_FILENAME)))
                {
                    using(var ss = new SignatureReadingStream(fs, SIGN_KEY))
                    using(var tr = new System.IO.StreamReader(ss))
                    using(var jr = new Newtonsoft.Json.JsonTextReader(tr))
                        update = new Newtonsoft.Json.JsonSerializer().Deserialize<UpdateInfo>(jr);

                    sha256.Initialize();
                    md5.Initialize();

                    fs.Position = 0;
                    var h1 = Convert.ToBase64String(sha256.ComputeHash(fs));
                    fs.Position = 0;
                    var h2 = Convert.ToBase64String(md5.ComputeHash(fs));

                    manifest = new FileEntry() {
                        Path = UPDATE_MANIFEST_FILENAME,
                        Ignore = false,
                        LastWriteTime = update.ReleaseTime,
                        SHA256 = h1,
                        MD5 = h2
                    };
                }

                if (version != null && (update.Displayname != version.Displayname || update.ReleaseTime != version.ReleaseTime))
                    throw new Exception("The found version was not the expected version");

                var paths = update.Files.Where(x => !x.Ignore).ToDictionary(x => x.Path.Replace('/', System.IO.Path.DirectorySeparatorChar), Library.Utility.Utility.ClientFilenameStringComparer);
                paths.Add(manifest.Path, manifest);

                var ignores = (from x in update.Files where x.Ignore select Library.Utility.Utility.AppendDirSeparator(x.Path.Replace('/', System.IO.Path.DirectorySeparatorChar))).ToList();

                folder = Library.Utility.Utility.AppendDirSeparator(folder);
                var baselen = folder.Length;

                foreach(var file in Library.Utility.Utility.EnumerateFileSystemEntries(folder))
                {
                    var relpath = file.Substring(baselen);
                    if (string.IsNullOrWhiteSpace(relpath))
                        continue;

                    FileEntry fe;
                    if (!paths.TryGetValue(relpath, out fe))
                    {
                        var ignore = false;
                        foreach(var c in ignores)
                            if (ignore = relpath.StartsWith(c))
                                break;

                        if (ignore)
                            continue;

                        throw new Exception(string.Format("Found unexpected file: {0}", file));
                    }

                    paths.Remove(relpath);

                    if (fe.Path.EndsWith("/"))
                        continue;

                    sha256.Initialize();
                    md5.Initialize();

                    using(var fs = System.IO.File.OpenRead(file))
                    {
                        if (Convert.ToBase64String(sha256.ComputeHash(fs)) != fe.SHA256)
                            throw new Exception(string.Format("Invalid sha256 hash for file: {0}", file));

                        fs.Position = 0;
                        if (Convert.ToBase64String(md5.ComputeHash(fs)) != fe.MD5)
                            throw new Exception(string.Format("Invalid md5 hash for file: {0}", file));
                    }
                }

                var filteredpaths = (from p in paths
                        where !string.IsNullOrWhiteSpace(p.Key) && !p.Key.EndsWith("/")
                        select p.Key).ToList();

                if (filteredpaths.Count == 1)
                    throw new Exception(string.Format("Folder {0} is missing: {1}", folder, filteredpaths.First()));
                else if (filteredpaths.Count > 0)
                    throw new Exception(string.Format("Folder {0} is missing {1} and {2} other file(s)", folder, filteredpaths.First(), filteredpaths.Count - 1));

                return true;
            }
            catch (Exception ex)
            {
                if (OnError != null)
                    OnError(ex);
            }

            return false;
        }
コード例 #2
0
ファイル: UpdaterManager.cs プロジェクト: rjodra/duplicati
        private static UpdateInfo ReadInstalledManifest(string folder)
        {
            var manifest = System.IO.Path.Combine(folder, UPDATE_MANIFEST_FILENAME);
            if (System.IO.File.Exists(manifest))
            {
                try
                {
                    using(var fs = System.IO.File.OpenRead(manifest))
                    using(var ss = new SignatureReadingStream(fs, SIGN_KEY))
                    using(var tr = new System.IO.StreamReader(ss))
                    using(var jr = new Newtonsoft.Json.JsonTextReader(tr))
                        return new Newtonsoft.Json.JsonSerializer().Deserialize<UpdateInfo>(jr);
                }
                catch (Exception ex)
                {
                    if (OnError != null)
                        OnError(ex);
                }
            }

            return null;
        }
コード例 #3
0
ファイル: UpdaterManager.cs プロジェクト: rjodra/duplicati
        public static UpdateInfo CheckForUpdate()
        {
            foreach(var url in MANIFEST_URLS)
            {
                try
                {
                    using(var tmpfile = new Library.Utility.TempFile())
                    {
                        System.Net.WebClient wc = new System.Net.WebClient();
                        wc.Headers.Add(System.Net.HttpRequestHeader.UserAgent, string.Format("{0} v{1}{2}", APPNAME, SelfVersion.Version, string.IsNullOrWhiteSpace(InstallID) ? "" : " -" + InstallID));
                        wc.Headers.Add("X-Install-ID", InstallID);
                        wc.DownloadFile(url, tmpfile);

                        using(var fs = System.IO.File.OpenRead(tmpfile))
                        using(var ss = new SignatureReadingStream(fs, SIGN_KEY))
                        using(var tr = new System.IO.StreamReader(ss))
                        using(var jr = new Newtonsoft.Json.JsonTextReader(tr))
                        {
                            var update = new Newtonsoft.Json.JsonSerializer().Deserialize<UpdateInfo>(jr);

                            if (TryParseVersion(update.Version) <= TryParseVersion(SelfVersion.Version))
                                return null;

                            if (string.Equals(SelfVersion.ReleaseType, "Debug", StringComparison.InvariantCultureIgnoreCase) && !string.Equals(update.ReleaseType, SelfVersion.ReleaseType, StringComparison.CurrentCultureIgnoreCase))
                                return null;

                            LastUpdateCheckVersion = update;
                            return update;
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (OnError != null)
                        OnError(ex);
                }
            }

            return null;
        }
コード例 #4
0
ファイル: UpdaterManager.cs プロジェクト: AlexFRAN/duplicati
        public static UpdateInfo CheckForUpdate(ReleaseType channel = ReleaseType.Unknown)
        {
            if (channel == ReleaseType.Unknown)
                channel = AutoUpdateSettings.DefaultUpdateChannel;

            foreach(var rawurl in MANIFEST_URLS)
            {
                var url = rawurl;

                // Attempt to match the url to change the channel if possible
                // This allows overrides to the URLs for deployment of custom builds,
                // but does not require that they adopt the channel system
                var match = AutoUpdateSettings.MATCH_AUTOUPDATE_URL.Match(url);
                if (match.Success)
                {
                    var mg = match.Groups[AutoUpdateSettings.MATCH_UPDATE_URL_CHANNEL_GROUP];

                    // Replace the channel name with the chosen channel
                    url =
                        url.Substring(0, mg.Index)
                        +
                        channel.ToString().ToLowerInvariant()
                        +
                        url.Substring(mg.Index + mg.Length);
                }

                try
                {
                    using(var tmpfile = new Library.Utility.TempFile())
                    {
                        System.Net.WebClient wc = new System.Net.WebClient();
                        wc.Headers.Add(System.Net.HttpRequestHeader.UserAgent, string.Format("{0} v{1}{2}", APPNAME, SelfVersion.Version, string.IsNullOrWhiteSpace(InstallID) ? "" : " -" + InstallID));
                        wc.Headers.Add("X-Install-ID", InstallID);
                        wc.DownloadFile(url, tmpfile);

                        using(var fs = System.IO.File.OpenRead(tmpfile))
                        using(var ss = new SignatureReadingStream(fs, SIGN_KEY))
                        using(var tr = new System.IO.StreamReader(ss))
                        using(var jr = new Newtonsoft.Json.JsonTextReader(tr))
                        {
                            var update = new Newtonsoft.Json.JsonSerializer().Deserialize<UpdateInfo>(jr);

                            if (TryParseVersion(update.Version) <= TryParseVersion(SelfVersion.Version))
                                return null;

                            // Don't install a debug update on a release build and vice versa
                            if (string.Equals(SelfVersion.ReleaseType, "Debug", StringComparison.InvariantCultureIgnoreCase) && !string.Equals(update.ReleaseType, SelfVersion.ReleaseType, StringComparison.CurrentCultureIgnoreCase))
                                return null;

                            ReleaseType rt;
                            if (!Enum.TryParse<ReleaseType>(update.ReleaseType, true, out rt))
                                rt = ReleaseType.Unknown;

                            // If the update is too low to be considered, skip it
                            // Should never happen, but protects against mistakes in deployment
                            if (rt > channel)
                                return null;

                            LastUpdateCheckVersion = update;
                            return update;
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (OnError != null)
                        OnError(ex);
                }
            }

            return null;
        }
コード例 #5
0
ファイル: UpdaterManager.cs プロジェクト: mjtworks/duplicati
        public static bool VerifyUnpackedFolder(string folder, UpdateInfo version = null)
        {
            try
            {
                UpdateInfo update;
                FileEntry  manifest;

                var sha256 = System.Security.Cryptography.SHA256.Create();
                var md5    = System.Security.Cryptography.MD5.Create();

                using (var fs = System.IO.File.OpenRead(System.IO.Path.Combine(folder, UPDATE_MANIFEST_FILENAME)))
                {
                    using (var ss = new SignatureReadingStream(fs, SIGN_KEY))
                        using (var tr = new System.IO.StreamReader(ss))
                            using (var jr = new Newtonsoft.Json.JsonTextReader(tr))
                                update = new Newtonsoft.Json.JsonSerializer().Deserialize <UpdateInfo>(jr);

                    sha256.Initialize();
                    md5.Initialize();

                    fs.Position = 0;
                    var h1 = Convert.ToBase64String(sha256.ComputeHash(fs));
                    fs.Position = 0;
                    var h2 = Convert.ToBase64String(md5.ComputeHash(fs));

                    manifest = new FileEntry()
                    {
                        Path          = UPDATE_MANIFEST_FILENAME,
                        Ignore        = false,
                        LastWriteTime = update.ReleaseTime,
                        SHA256        = h1,
                        MD5           = h2
                    };
                }

                if (version != null && (update.Displayname != version.Displayname || update.ReleaseTime != version.ReleaseTime))
                {
                    throw new Exception("The found version was not the expected version");
                }

                var paths = update.Files.Where(x => !x.Ignore).ToDictionary(x => x.Path.Replace('/', System.IO.Path.DirectorySeparatorChar), Library.Utility.Utility.ClientFilenameStringComparer);
                paths.Add(manifest.Path, manifest);

                var ignores = (from x in update.Files where x.Ignore select Library.Utility.Utility.AppendDirSeparator(x.Path.Replace('/', System.IO.Path.DirectorySeparatorChar))).ToList();

                folder = Library.Utility.Utility.AppendDirSeparator(folder);
                var baselen = folder.Length;

                foreach (var file in Library.Utility.Utility.EnumerateFileSystemEntries(folder))
                {
                    var relpath = file.Substring(baselen);
                    if (string.IsNullOrWhiteSpace(relpath))
                    {
                        continue;
                    }

                    FileEntry fe;
                    if (!paths.TryGetValue(relpath, out fe))
                    {
                        var ignore = false;
                        foreach (var c in ignores)
                        {
                            if (ignore = relpath.StartsWith(c))
                            {
                                break;
                            }
                        }

                        if (ignore)
                        {
                            continue;
                        }

                        throw new Exception(string.Format("Found unexpected file: {0}", file));
                    }

                    paths.Remove(relpath);

                    if (fe.Path.EndsWith("/"))
                    {
                        continue;
                    }

                    sha256.Initialize();
                    md5.Initialize();

                    using (var fs = System.IO.File.OpenRead(file))
                    {
                        if (Convert.ToBase64String(sha256.ComputeHash(fs)) != fe.SHA256)
                        {
                            throw new Exception(string.Format("Invalid sha256 hash for file: {0}", file));
                        }

                        fs.Position = 0;
                        if (Convert.ToBase64String(md5.ComputeHash(fs)) != fe.MD5)
                        {
                            throw new Exception(string.Format("Invalid md5 hash for file: {0}", file));
                        }
                    }
                }

                var filteredpaths = (from p in paths
                                     where !string.IsNullOrWhiteSpace(p.Key) && !p.Key.EndsWith("/")
                                     select p.Key).ToList();


                if (filteredpaths.Count == 1)
                {
                    throw new Exception(string.Format("Folder {0} is missing: {1}", folder, filteredpaths.First()));
                }
                else if (filteredpaths.Count > 0)
                {
                    throw new Exception(string.Format("Folder {0} is missing {1} and {2} other file(s)", folder, filteredpaths.First(), filteredpaths.Count - 1));
                }

                return(true);
            }
            catch (Exception ex)
            {
                if (OnError != null)
                {
                    OnError(ex);
                }
            }

            return(false);
        }
コード例 #6
0
        public static void CreateUpdatePackage(System.Security.Cryptography.RSACryptoServiceProvider key, string inputfolder, string outputfolder, string manifest = null)
        {
            // Read the existing manifest

            UpdateInfo remoteManifest;

            var manifestpath = manifest ?? System.IO.Path.Combine(inputfolder, UPDATE_MANIFEST_FILENAME);

            using (var s = System.IO.File.OpenRead(manifestpath))
                using (var sr = new System.IO.StreamReader(s))
                    using (var jr = new Newtonsoft.Json.JsonTextReader(sr))
                        remoteManifest = new Newtonsoft.Json.JsonSerializer().Deserialize <UpdateInfo>(jr);

            if (remoteManifest.Files == null)
            {
                remoteManifest.Files = new FileEntry[0];
            }

            if (remoteManifest.ReleaseTime.Ticks == 0)
            {
                remoteManifest.ReleaseTime = DateTime.UtcNow;
            }

            var ignoreFiles = (from n in remoteManifest.Files
                               where n.Ignore
                               select n).ToArray();

            var ignoreMap = ignoreFiles.ToDictionary(k => k.Path, k => "", Duplicati.Library.Utility.Utility.ClientFilenameStringComparer);

            remoteManifest.MD5              = null;
            remoteManifest.SHA256           = null;
            remoteManifest.Files            = null;
            remoteManifest.UncompressedSize = 0;

            var localManifest = remoteManifest.Clone();

            localManifest.RemoteURLS = null;

            inputfolder = Duplicati.Library.Utility.Utility.AppendDirSeparator(inputfolder);
            var baselen = inputfolder.Length;
            var dirsep  = System.IO.Path.DirectorySeparatorChar.ToString();

            ignoreMap.Add(UPDATE_MANIFEST_FILENAME, "");

            var md5    = System.Security.Cryptography.MD5.Create();
            var sha256 = System.Security.Cryptography.SHA256.Create();

            Func <string, string> computeMD5 = (path) =>
            {
                md5.Initialize();
                using (var fs = System.IO.File.OpenRead(path))
                    return(Convert.ToBase64String(md5.ComputeHash(fs)));
            };

            Func <string, string> computeSHA256 = (path) =>
            {
                sha256.Initialize();
                using (var fs = System.IO.File.OpenRead(path))
                    return(Convert.ToBase64String(sha256.ComputeHash(fs)));
            };

            // Build a zip
            using (var archive_temp = new Duplicati.Library.Utility.TempFile())
            {
                using (var zipfile = new Duplicati.Library.Compression.FileArchiveZip(archive_temp, new Dictionary <string, string>()))
                {
                    Func <string, string, bool> addToArchive = (path, relpath) =>
                    {
                        if (ignoreMap.ContainsKey(relpath))
                        {
                            return(false);
                        }

                        if (path.EndsWith(dirsep))
                        {
                            return(true);
                        }

                        using (var source = System.IO.File.OpenRead(path))
                            using (var target = zipfile.CreateFile(relpath,
                                                                   Duplicati.Library.Interface.CompressionHint.Compressible,
                                                                   System.IO.File.GetLastAccessTimeUtc(path)))
                            {
                                source.CopyTo(target);
                                remoteManifest.UncompressedSize += source.Length;
                            }

                        return(true);
                    };

                    // Build the update manifest
                    localManifest.Files =
                        (from fse in Duplicati.Library.Utility.Utility.EnumerateFileSystemEntries(inputfolder)
                         let relpath = fse.Substring(baselen)
                                       where addToArchive(fse, relpath)
                                       select new FileEntry()
                    {
                        Path = relpath,
                        LastWriteTime = System.IO.File.GetLastAccessTimeUtc(fse),
                        MD5 = fse.EndsWith(dirsep) ? null : computeMD5(fse),
                        SHA256 = fse.EndsWith(dirsep) ? null : computeSHA256(fse)
                    })
                        .Union(ignoreFiles).ToArray();

                    // Write a signed manifest with the files

                    using (var ms = new System.IO.MemoryStream())
                        using (var sw = new System.IO.StreamWriter(ms))
                        {
                            new Newtonsoft.Json.JsonSerializer().Serialize(sw, localManifest);
                            sw.Flush();

                            using (var ms2 = new System.IO.MemoryStream())
                            {
                                SignatureReadingStream.CreateSignedStream(ms, ms2, key);
                                ms2.Position = 0;
                                using (var sigfile = zipfile.CreateFile(UPDATE_MANIFEST_FILENAME,
                                                                        Duplicati.Library.Interface.CompressionHint.Compressible,
                                                                        DateTime.UtcNow))
                                    ms2.CopyTo(sigfile);
                            }
                        }
                }

                remoteManifest.CompressedSize = new System.IO.FileInfo(archive_temp).Length;
                remoteManifest.MD5            = computeMD5(archive_temp);
                remoteManifest.SHA256         = computeSHA256(archive_temp);

                System.IO.File.Move(archive_temp, System.IO.Path.Combine(outputfolder, "package.zip"));
            }

            // Write a signed manifest for upload

            using (var tf = new Duplicati.Library.Utility.TempFile())
            {
                using (var ms = new System.IO.MemoryStream())
                    using (var sw = new System.IO.StreamWriter(ms))
                    {
                        new Newtonsoft.Json.JsonSerializer().Serialize(sw, remoteManifest);
                        sw.Flush();

                        using (var fs = System.IO.File.Create(tf))
                            SignatureReadingStream.CreateSignedStream(ms, fs, key);
                    }

                System.IO.File.Move(tf, System.IO.Path.Combine(outputfolder, UPDATE_MANIFEST_FILENAME));
            }
        }
コード例 #7
0
        public static UpdateInfo CheckForUpdate(ReleaseType channel = ReleaseType.Unknown)
        {
            if (channel == ReleaseType.Unknown)
            {
                channel = AutoUpdateSettings.DefaultUpdateChannel;
            }

            foreach (var rawurl in MANIFEST_URLS)
            {
                var url = rawurl;

                // Attempt to match the url to change the channel if possible
                // This allows overrides to the URLs for deployment of custom builds,
                // but does not require that they adopt the channel system
                var match = AutoUpdateSettings.MATCH_AUTOUPDATE_URL.Match(url);
                if (match.Success)
                {
                    var mg = match.Groups[AutoUpdateSettings.MATCH_UPDATE_URL_CHANNEL_GROUP];

                    // Replace the channel name with the chosen channel
                    url =
                        url.Substring(0, mg.Index)
                        +
                        channel.ToString().ToLowerInvariant()
                        +
                        url.Substring(mg.Index + mg.Length);
                }

                try
                {
                    using (var tmpfile = new Library.Utility.TempFile())
                    {
                        System.Net.WebClient wc = new System.Net.WebClient();
                        wc.Headers.Add(System.Net.HttpRequestHeader.UserAgent, string.Format("{0} v{1}{2}", APPNAME, SelfVersion.Version, string.IsNullOrWhiteSpace(InstallID) ? "" : " -" + InstallID));
                        wc.Headers.Add("X-Install-ID", InstallID);
                        wc.DownloadFile(url, tmpfile);

                        using (var fs = System.IO.File.OpenRead(tmpfile))
                            using (var ss = new SignatureReadingStream(fs, SIGN_KEY))
                                using (var tr = new System.IO.StreamReader(ss))
                                    using (var jr = new Newtonsoft.Json.JsonTextReader(tr))
                                    {
                                        var update = new Newtonsoft.Json.JsonSerializer().Deserialize <UpdateInfo>(jr);

                                        if (TryParseVersion(update.Version) <= TryParseVersion(SelfVersion.Version))
                                        {
                                            return(null);
                                        }

                                        // Don't install a debug update on a release build and vice versa
                                        if (string.Equals(SelfVersion.ReleaseType, "Debug", StringComparison.InvariantCultureIgnoreCase) && !string.Equals(update.ReleaseType, SelfVersion.ReleaseType, StringComparison.CurrentCultureIgnoreCase))
                                        {
                                            return(null);
                                        }

                                        ReleaseType rt;
                                        if (!Enum.TryParse <ReleaseType>(update.ReleaseType, true, out rt))
                                        {
                                            rt = ReleaseType.Unknown;
                                        }

                                        // If the update is too low to be considered, skip it
                                        // Should never happen, but protects against mistakes in deployment
                                        if (rt > channel)
                                        {
                                            return(null);
                                        }

                                        LastUpdateCheckVersion = update;
                                        return(update);
                                    }
                    }
                }
                catch (Exception ex)
                {
                    if (OnError != null)
                    {
                        OnError(ex);
                    }
                }
            }

            return(null);
        }