Пример #1
0
        /// <summary>
        /// Sets information about an available update. If provided data is incorrect, stores "no udate" and throws.
        /// </summary>
        internal static void SetUpdate(string url, string urlHash, string fileHash,
                                       int verMajor, int verMinor, DateTime releaseDate, string releaseNotesUrl,
                                       string uiLang)
        {
            try
            {
                Uri updateUri = new Uri(url);
                if (updateUri.IsFile || (updateUri.Scheme != "http" && updateUri.Scheme != "https"))
                {
                    throw new ArgumentException("Invalid update URL.");
                }
                if (!SignatureCheck.VerifySignature(url, urlHash))
                {
                    throw new ArgumentException("Update URL signature incorrect.");
                }
                if (verMajor < 1 || verMajor > 255)
                {
                    throw new ArgumentException("Invalid major version.");
                }
                if (verMinor < 0 || verMinor > 255)
                {
                    throw new ArgumentException("Invalid minor version.");
                }
                Uri notesUri = new Uri(releaseNotesUrl);
                if (notesUri.IsFile || (notesUri.Scheme != "http" && notesUri.Scheme != "https"))
                {
                    throw new ArgumentException("Invalid release notes URL.");
                }

                // OK: store info
                int verInOne = verMajor;
                verInOne <<= 8;
                verInOne  += verMinor;

                Data.UpdateAvailable    = true;
                Data.UpdateUrl          = url;
                Data.UpdateUrlHash      = urlHash;
                Data.UpdateFileHash     = fileHash;
                Data.UpdateVersionInOne = (ushort)verInOne;
                Data.UpdateReleaseDate  = releaseDate.Year.ToString() + "-" + releaseDate.Month.ToString("00") + "-" + releaseDate.Day.ToString("00");
                Data.ReleaseNotesUrl    = releaseNotesUrl;
                Data.UILang             = uiLang;
                saveData();
            }
            catch
            {
                try { ClearUpdate(); }
                catch { }
                throw;
            }
        }
Пример #2
0
 /// <summary>
 /// Verifies downloaded file against its hash; updates state as needed.
 /// </summary>
 private bool doVerifyFile(string fname, string fhash)
 {
     try
     {
         doSetStateSafe(State.Verifying);
         Thread.Sleep(1000); // Verify can be fast
         if (!SignatureCheck.VerifySignature(new FileInfo(fname), fhash))
         {
             doSetStateSafe(State.VerifyFailed);
             return(false);
         }
     }
     catch
     {
         doSetStateSafe(State.VerifyFailed);
         return(false);
     }
     return(true);
 }
Пример #3
0
        /// <summary>
        /// <para>Signs an update URL and and update package with the provided private key.</para>
        /// <para>The private key belongs to the embedded public key that we use for verification, but it's NOT included in the code base.</para>
        /// </summary>
        private static void doSignUpdate(string[] args)
        {
            if (args.Length != 5)
            {
                throw new Exception("Expected usage: /sign <url> <installer-file> <private-key-file> <output-file>");
            }

            using (StreamReader srKey = new StreamReader(args[3]))
                using (StreamWriter srOut = new StreamWriter(args[4]))
                {
                    string keyXml  = srKey.ReadToEnd();
                    string sigUrl  = SignatureCheck.Sign(args[1], keyXml);
                    string sigFile = SignatureCheck.Sign(new FileInfo(args[2]), keyXml);
                    srOut.WriteLine("URL signature:");
                    srOut.WriteLine(sigUrl);
                    srOut.WriteLine();
                    srOut.WriteLine("File signature:");
                    srOut.WriteLine(sigFile);
                    srOut.WriteLine();
                }
        }
Пример #4
0
        /// <summary>
        /// Downloads update, reports failure and updates states as needed.
        /// </summary>
        private bool doDownload(out string fname, out string fileHash)
        {
            WebClient wc = null;
            string    url, urlHash;

            fileHash = null;
            fname    = null;
            // Start download
            try
            {
                // First, figure out what to download.
                UpdateInfo.GetDownloadInfo(out url, out urlHash, out fileHash);
                // Verify URL hash
                if (!SignatureCheck.VerifySignature(url, urlHash))
                {
                    // No good: download fails.
                    doSetStateSafe(State.DLoadFailed);
                    return(false);
                }
                // Get to download. Schedule file we'll be downloading for deletion right now.
                fname = Helper.GetTempExePath();
                scheduleFileToDelete(fname);
                dloadLastProgress = DateTime.Now;
                wc = new WebClient();
                wc.Headers["user-agent"] = "Zydeo updater";
                wc.UseDefaultCredentials = true;
                wc.Proxy = WebRequest.GetSystemWebProxy();
                wc.DownloadFileCompleted   += onDownloadCompleted;
                wc.DownloadProgressChanged += onDownloadProgressChanged;
                wc.DownloadFileAsync(new Uri(url), fname);
                // Keep waiting
                while (true)
                {
                    // If done, break out of cycle.
                    if (dloadCompleteEvent.WaitOne(100))
                    {
                        break;
                    }
                    // Check for timeout - when did we last receive progress?
                    DateTime dtLastProgress;
                    lock (dloadCompleteEvent)
                    {
                        dtLastProgress = dloadLastProgress;
                    }
                    TimeSpan elapsed = DateTime.Now.Subtract(dtLastProgress);
                    // If timeout has elapsed, cancel download and - throw.
                    if (elapsed.TotalSeconds > Magic.DownloadTimeoutSec)
                    {
                        // This will trigger "completed", but we won't check the exception reported by it anymore.
                        wc.CancelAsync();
                        // Timeout = download fails.
                        throw new Exception("Download timed out.");
                    }
                    // Did user cancel download?
                    if (cancel)
                    {
                        // This will trigger "completed", but we won't check the exception reported by it anymore.
                        wc.CancelAsync();
                        // Set state to download canceled.
                        doSetStateSafe(State.DLoadCanceled);
                        return(false);
                    }
                }
                // If completed with error, throw here
                if (dloadException != null)
                {
                    throw dloadException;
                }
            }
            catch (Exception ex)
            {
                FileLogger.Instance.LogException(ex);
                doSetStateSafe(State.DLoadFailed);
                return(false);
            }
            finally
            {
                if (wc != null)
                {
                    try { wc.Dispose(); }
                    catch { }
                }
            }
            return(true);
        }
Пример #5
0
        /// <summary>
        /// Runs as LOCAL SYSTEM from temp path; receives info from updater UI; checks package; executes installer.
        /// </summary>
        public static void Work()
        {
            // The service pipe we're listening through.
            NamedPipeStream pstream = null;

            try
            {
                // Create service pipe
                FileLogger.Instance.LogInfo("Creating named pipe.");
                FileSecurity pipeSecurity = new FileSecurity();
                pipeSecurity.AddAccessRule(new FileSystemAccessRule(new SecurityIdentifier("S-1-5-11"), FileSystemRights.FullControl, AccessControlType.Allow));
                pstream = NamedPipeStream.Create(Magic.ServiceShortName, NamedPipeStream.ServerMode.Bidirectional, pipeSecurity);

                // Wait for client (updater UI) to connect; but not too long.
                FileLogger.Instance.LogInfo("Waiting for client to connect.");
                if (!doListen(ref pstream))
                {
                    throw new Exception("Client didn't show up; tired of waiting.");
                }
                FileLogger.Instance.LogInfo("Client connected, reading paths and hash.");

                // Read location of downloaded installer and its file hash.
                string fname, fhash;
                doReadRequest(pstream, out fname, out fhash);

                // Verify signature
                FileLogger.Instance.LogInfo("Info received; verifying signature.");
                if (!SignatureCheck.VerifySignature(new FileInfo(fname), fhash))
                {
                    throw new Exception("Signature incorrect.");
                }
                FileLogger.Instance.LogInfo("Installer signature OK; launching installer");

                // Let caller know we've started installer
                pstream.WriteByte(Magic.SrvCodeInstallStarted);

                // Launch installer
                int exitCode = doRunInstaller(fname);
                FileLogger.Instance.LogInfo("Installer returned exit code " + exitCode.ToString());

                // Exit code 1 is failure
                if (exitCode == 1)
                {
                    throw new Exception("Installer failed.");
                }

                // We've succeeded; let caller know.
                pstream.WriteByte(Magic.SrvCodeSuccess);
                FileLogger.Instance.LogInfo("Finished with success; quitting.");
            }
            catch
            {
                // Upon error, return failure code to caller.
                if (pstream != null)
                {
                    try { pstream.WriteByte(Magic.SrvCodeFail); }
                    catch { }
                }
                throw;
            }
            finally
            {
                // Close & dispose of service pipe before we exit left.
                if (pstream != null)
                {
                    try
                    {
                        pstream.Close();
                        pstream.Dispose();
                        pstream = null;
                    }
                    catch { }
                }
            }
        }