public void Initialize()
        {
            Log.Information("Initializing ACME client");

            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

            if (!File.Exists(_options.WellKnownFilePaths[WellKnownFile.AcmeSigner]))
            {
                throw new FileNotFoundException($"Signer file '{_options.WellKnownFilePaths[WellKnownFile.AcmeSigner]}' not found");
            }
            if (!File.Exists(_options.WellKnownFilePaths[WellKnownFile.AcmeRegistration]))
            {
                throw new FileNotFoundException($"Registration file '{_options.WellKnownFilePaths[WellKnownFile.AcmeRegistration]}' not found");
            }

            _signer.Init();

            using (FileStream signerStream = File.OpenRead(_options.WellKnownFilePaths[WellKnownFile.AcmeSigner]))
                _signer.Load(signerStream);

            _client.Signer  = _signer;
            _client.RootUrl = new Uri(_options.BaseUri);

            _client.Init();
            _client.GetDirectory(true);

            using (FileStream registrationStream = File.OpenRead(_options.WellKnownFilePaths[WellKnownFile.AcmeRegistration]))
                _client.Registration = AcmeRegistration.Load(registrationStream);

            _isInitialized = true;
        }
Exemple #2
0
        private static void ConfigureAcmeClient(AcmeClient client)
        {
            if (!string.IsNullOrWhiteSpace(Properties.Settings.Default.Proxy))
            {
                client.Proxy = new WebProxy(Properties.Settings.Default.Proxy);
                Log.Warning("Proxying via {proxy}", Properties.Settings.Default.Proxy);
            }

            var signerPath = Path.Combine(_configPath, "Signer");

            if (File.Exists(signerPath))
            {
                LoadSignerFromFile(client.Signer, signerPath);
            }

            _client.Init();
            _client.BeforeGetResponseAction = (x) =>
            {
                Log.Debug("Send {method} request to {uri}", x.Method, x.RequestUri);
            };
            Log.Debug("Getting AcmeServerDirectory");
            _client.GetDirectory(true);

            var registrationPath = Path.Combine(_configPath, "Registration");

            if (File.Exists(registrationPath))
            {
                LoadRegistrationFromFile(registrationPath);
            }
            else
            {
                string email = Options.EmailAddress;
                if (string.IsNullOrWhiteSpace(email))
                {
                    email = Input.RequestString("Enter an email address (not public, used for renewal fail notices)");
                }

                string[] contacts = GetContacts(email);

                AcmeRegistration registration = CreateRegistration(contacts);

                if (!Options.AcceptTos && !Options.Renew)
                {
                    if (!Input.PromptYesNo($"Do you agree to {registration.TosLinkUri}?"))
                    {
                        return;
                    }
                }

                UpdateRegistration();
                SaveRegistrationToFile(registrationPath);
                SaveSignerToFile(_client.Signer, signerPath);
            }
        }
Exemple #3
0
        private static void ConfigureAcmeClient(AcmeClient client)
        {
            if (!string.IsNullOrWhiteSpace(Options.Proxy))
            {
                client.Proxy            = new WebProxy(Options.Proxy);
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("Proxying via " + Options.Proxy);
                Console.ResetColor();
            }

            var signerPath = Path.Combine(_configPath, "Signer");

            if (File.Exists(signerPath))
            {
                LoadSignerFromFile(client.Signer, signerPath);
            }

            _client.Init();

            Log.Information("Getting AcmeServerDirectory");
            _client.GetDirectory(true);

            var registrationPath = Path.Combine(_configPath, "Registration");

            if (File.Exists(registrationPath))
            {
                LoadRegistrationFromFile(registrationPath);
            }
            else
            {
                string email = Options.SignerEmail;
                if (string.IsNullOrWhiteSpace(email))
                {
                    Console.Write("Enter an email address (not public, used for renewal fail notices): ");
                    email = Console.ReadLine().Trim();
                }

                string[] contacts = GetContacts(email);

                AcmeRegistration registration = CreateRegistration(contacts);

                if (!Options.AcceptTos && !Options.Renew)
                {
                    if (!Input.PromptYesNo($"Do you agree to {registration.TosLinkUri}?"))
                    {
                        return;
                    }
                }

                UpdateRegistration();
                SaveRegistrationToFile(registrationPath);
                SaveSignerToFile(_client.Signer, signerPath);
            }
        }
Exemple #4
0
        public static AcmeClient CreateAcmeClient(ISigner signer, AcmeRegistration registration)
        {
            var client = new AcmeClient(new Uri(Program.GlobalConfiguration.AcmeServerBaseUri), new AcmeServerDirectory(), signer, registration);

            if (!string.IsNullOrWhiteSpace(Program.GlobalConfiguration.ProxyUri))
            {
                client.Proxy = new WebProxy(Program.GlobalConfiguration.ProxyUri, false, new string[0], new NetworkCredential(Program.GlobalConfiguration.ProxyUserName, Program.GlobalConfiguration.ProxyPassword));
            }

            client.Init();
            client.GetDirectory(true);
            return(client);
        }
Exemple #5
0
        protected override void ProcessRecord()
        {
            using (var vlt = Util.VaultHelper.GetVault(VaultProfile))
            {
                vlt.OpenStorage();
                var v = vlt.LoadVault();

                AcmeRegistration r = null;
                var ri             = new RegistrationInfo
                {
                    Id             = EntityHelper.NewId(),
                    Alias          = Alias,
                    Label          = Label,
                    Memo           = Memo,
                    SignerProvider = Signer,
                };

                try
                {
                    using (var c = ClientHelper.GetClient(v, ri))
                    {
                        c.Init();
                        c.GetDirectory(true);

                        r = c.Register(Contacts);
                        if (AcceptTos)
                        {
                            r = c.UpdateRegistration(agreeToTos: true);
                        }

                        ri.Registration = r;

                        if (v.Registrations == null)
                        {
                            v.Registrations = new EntityDictionary <RegistrationInfo>();
                        }

                        v.Registrations.Add(ri);
                    }
                }
                catch (AcmeClient.AcmeWebException ex)
                {
                    ThrowTerminatingError(PoshHelper.CreateErrorRecord(ex, ri));
                    return;
                }

                vlt.SaveVault(v);

                WriteObject(r);
            }
        }
Exemple #6
0
        protected override void ProcessRecord()
        {
            using (var vp = InitializeVault.GetVaultProvider(VaultProfile))
            {
                vp.OpenStorage();
                var v = vp.LoadVault();

                AcmeRegistration r = null;
                var ri             = new RegistrationInfo
                {
                    Id             = EntityHelper.NewId(),
                    Alias          = Alias,
                    Label          = Label,
                    Memo           = Memo,
                    SignerProvider = Signer,
                };

                using (var c = ClientHelper.GetClient(v, ri))
                {
                    c.Init();
                    c.GetDirectory(true);

                    r = c.Register(Contacts);
                    if (AcceptTos)
                    {
                        r = c.UpdateRegistration(agreeToTos: true);
                    }

                    ri.Registration = r;

                    if (v.Registrations == null)
                    {
                        v.Registrations = new EntityDictionary <RegistrationInfo>();
                    }

                    v.Registrations.Add(ri);
                }

                vp.SaveVault(v);

                WriteObject(r);
            }
        }
        private void ProcessRegistration(AcmeClient acmeClient, string[] contacts, string basePath)
        {
            var registrationPath = Path.Combine(basePath, _configuration.SignerFilename);

            if (File.Exists(registrationPath))
            {
                _logger.Information("Loading Registration from {registrationPath}", registrationPath);
                using (var registrationStream = File.OpenRead(registrationPath))
                    acmeClient.Registration = AcmeRegistration.Load(registrationStream);
            }
            else
            {
                _logger.Information("Registering AcmeClient with contacts {@contacts}", contacts);
                acmeClient.Register(contacts);
                acmeClient.UpdateRegistration(useRootUrl: true, agreeToTos: true);

                _logger.Information("Saving Registration to {registrationPath}", registrationPath);
                using (var registrationStream = File.OpenWrite(registrationPath))
                    acmeClient.Registration.Save(registrationStream);
            }
        }
Exemple #8
0
        static void SetupAcmeClient(AcmeClient client, RS256Signer signer, string registrationFile, string signerFile, string email)
        {
            client.Init();
            client.GetDirectory(true);

            if (!File.Exists(registrationFile))
            {
                client.Register(new string[] { $"mailto:{email}" });

                using (var registrationStream = File.OpenWrite(registrationFile))
                    client.Registration.Save(registrationStream);
            }

            using (var registrationStream = File.OpenRead(registrationFile))
                client.Registration = AcmeRegistration.Load(registrationStream);

            client.UpdateRegistration(true, true);

            using (var signerStream = File.OpenWrite(signerFile))
                signer.Save(signerStream);
        }
Exemple #9
0
        public AcmeClient Register(RS256Signer signer)
        {
            if (!Directory.Exists(configPath))
            {
                Directory.CreateDirectory(configPath);
            }
            var email = config.RegistrationEmail;

            try
            {
                signer.Init();

                var signerPath = Path.Combine(configPath, "Signer");
                if (File.Exists(signerPath))
                {
                    Trace.TraceInformation($"Loading Signer from {signerPath}");
                    using (var signerStream = File.OpenRead(signerPath))
                        signer.Load(signerStream);
                }

                var client = new AcmeClient(new Uri(this.baseURI), new AcmeServerDirectory(), signer);

                client.Init();
                Trace.TraceInformation("\nGetting AcmeServerDirectory");
                client.GetDirectory(true);

                var registrationPath = Path.Combine(configPath, "Registration");
                if (File.Exists(registrationPath))
                {
                    Trace.TraceInformation($"Loading Registration from {registrationPath}");
                    using (var registrationStream = File.OpenRead(registrationPath))
                        client.Registration = AcmeRegistration.Load(registrationStream);
                }
                else
                {
                    var contacts = new string[] { };
                    if (!String.IsNullOrEmpty(email))
                    {
                        email    = "mailto:" + email;
                        contacts = new string[] { email };
                    }

                    Trace.TraceInformation("Calling Register");
                    var registration = client.Register(contacts);


                    Trace.TraceInformation("Updating Registration");
                    client.UpdateRegistration(true, true);

                    Trace.TraceInformation("Saving Registration");
                    using (var registrationStream = File.OpenWrite(registrationPath))
                        client.Registration.Save(registrationStream);

                    Trace.TraceInformation("Saving Signer");
                    using (var signerStream = File.OpenWrite(signerPath))
                        signer.Save(signerStream);
                }
                return(client);
            }
            catch (Exception e)
            {
                var acmeWebException = e as AcmeClient.AcmeWebException;
                if (acmeWebException != null)
                {
                    Trace.TraceError(acmeWebException.Message);
                    Trace.TraceError("ACME Server Returned:");
                    Trace.TraceError(acmeWebException.Response.ContentAsString);
                }
                else
                {
                    Trace.TraceError(e.ToString());
                }
                throw;
            }
        }
        static void Main(string[] args)
        {
            var commandLineParseResult = Parser.Default.ParseArguments <Options>(args);
            var parsed = commandLineParseResult as Parsed <Options>;

            if (parsed == null)
            {
#if DEBUG
                Console.WriteLine("Press enter to continue.");
                Console.ReadLine();
#endif
                return; // not parsed
            }
            Options = parsed.Value;

            Console.WriteLine("Let's Encrypt (Simple Windows ACME Client)");

            BaseURI = Options.BaseURI;
            if (Options.Test)
            {
                BaseURI = "https://acme-staging.api.letsencrypt.org/";
            }

            //Console.Write("\nUse production Let's Encrypt server? (Y/N) ");
            //if (PromptYesNo())
            //    BaseURI = ProductionBaseURI;

            Console.WriteLine($"\nACME Server: {BaseURI}");

            if (!string.IsNullOrWhiteSpace(Options.CentralSSLStore))
            {
                Console.WriteLine("Using Centralized SSL Path: " + Options.CentralSSLStore);
                CentralSSL = true;
            }

            settings = new Settings(clientName, BaseURI);

            configPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), clientName, CleanFileName(BaseURI));
            Console.WriteLine("Config Folder: " + configPath);
            Directory.CreateDirectory(configPath);

            try
            {
                using (var signer = new RS256Signer())
                {
                    signer.Init();

                    var signerPath = Path.Combine(configPath, "Signer");
                    if (File.Exists(signerPath))
                    {
                        Console.WriteLine($"Loading Signer from {signerPath}");
                        using (var signerStream = File.OpenRead(signerPath))
                            signer.Load(signerStream);
                    }

                    using (client = new AcmeClient(new Uri(BaseURI), new AcmeServerDirectory(), signer))
                    {
                        client.Init();
                        Console.WriteLine("\nGetting AcmeServerDirectory");
                        client.GetDirectory(true);

                        var registrationPath = Path.Combine(configPath, "Registration");
                        if (File.Exists(registrationPath))
                        {
                            Console.WriteLine($"Loading Registration from {registrationPath}");
                            using (var registrationStream = File.OpenRead(registrationPath))
                                client.Registration = AcmeRegistration.Load(registrationStream);
                        }
                        else
                        {
                            Console.Write("Enter an email address (not public, used for renewal fail notices): ");
                            var email = Console.ReadLine().Trim();

                            var contacts = new string[] { };
                            if (!String.IsNullOrEmpty(email))
                            {
                                email    = "mailto:" + email;
                                contacts = new string[] { email };
                            }

                            Console.WriteLine("Calling Register");
                            var registration = client.Register(contacts);

                            if (!Options.AcceptTOS && !Options.Renew)
                            {
                                Console.WriteLine($"Do you agree to {registration.TosLinkUri}? (Y/N) ");
                                if (!PromptYesNo())
                                {
                                    return;
                                }
                            }

                            Console.WriteLine("Updating Registration");
                            client.UpdateRegistration(true, true);

                            Console.WriteLine("Saving Registration");
                            using (var registrationStream = File.OpenWrite(registrationPath))
                                client.Registration.Save(registrationStream);

                            Console.WriteLine("Saving Signer");
                            using (var signerStream = File.OpenWrite(signerPath))
                                signer.Save(signerStream);
                        }

                        if (Options.Renew)
                        {
                            CheckRenewals();
#if DEBUG
                            Console.WriteLine("Press enter to continue.");
                            Console.ReadLine();
#endif
                            return;
                        }

                        var targets = new List <Target>();
                        foreach (var plugin in Target.Plugins.Values)
                        {
                            targets.AddRange(plugin.GetTargets());
                        }

                        if (targets.Count == 0)
                        {
                            Console.WriteLine("No targets found.");
                        }
                        else
                        {
                            var count = 1;
                            foreach (var binding in targets)
                            {
                                Console.WriteLine($" {count}: {binding}");
                                count++;
                            }
                        }

                        Console.WriteLine();
                        foreach (var plugin in Target.Plugins.Values)
                        {
                            plugin.PrintMenu();
                        }

                        Console.WriteLine(" A: Get certificates for all hosts");
                        Console.WriteLine(" Q: Quit");
                        Console.Write("Which host do you want to get a certificate for: ");
                        var response = Console.ReadLine().ToLowerInvariant();
                        switch (response)
                        {
                        case "a":
                            foreach (var target in targets)
                            {
                                Auto(target);
                            }
                            break;

                        case "q":
                            return;

                        default:
                            var targetId = 0;
                            if (Int32.TryParse(response, out targetId))
                            {
                                targetId--;
                                if (targetId >= 0 && targetId < targets.Count)
                                {
                                    var binding = targets[targetId];
                                    Auto(binding);
                                }
                            }
                            else
                            {
                                foreach (var plugin in Target.Plugins.Values)
                                {
                                    plugin.HandleMenuResponse(response, targets);
                                }
                            }
                            break;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                var acmeWebException = e as AcmeClient.AcmeWebException;
                if (acmeWebException != null)
                {
                    Console.WriteLine(acmeWebException.Message);
                    Console.WriteLine("ACME Server Returned:");
                    Console.WriteLine(acmeWebException.Response.ContentAsString);
                }
                else
                {
                    Console.WriteLine(e);
                }
                Console.ResetColor();
            }

            Console.WriteLine("Press enter to continue.");
            Console.ReadLine();
        }
Exemple #11
0
        public static string RequestAndInstallInternal(Target target)
        {
            BaseURI    = target.BaseUri ?? "https://acme-staging.api.letsencrypt.org/";
            configPath = ConfigPath(BaseURI);
            try
            {
                webSiteClient = ArmHelper.GetWebSiteManagementClient(target);
            }
            catch (Exception ex)
            {
                Trace.TraceError("Unabled to create Azure Web Site Management client " + ex.ToString());
                throw;
            }

            if (!Directory.Exists(configPath))
            {
                Directory.CreateDirectory(configPath);
            }
            var email = target.Email;

            try
            {
                using (var signer = new RS256Signer())
                {
                    signer.Init();

                    var signerPath = Path.Combine(configPath, "Signer");
                    if (File.Exists(signerPath))
                    {
                        Trace.TraceInformation($"Loading Signer from {signerPath}");
                        using (var signerStream = File.OpenRead(signerPath))
                            signer.Load(signerStream);
                    }

                    using (client = new AcmeClient(new Uri(BaseURI), new AcmeServerDirectory(), signer))
                    {
                        client.Init();
                        Trace.TraceInformation("\nGetting AcmeServerDirectory");
                        client.GetDirectory(true);

                        var registrationPath = Path.Combine(configPath, "Registration");
                        if (File.Exists(registrationPath))
                        {
                            Trace.TraceInformation($"Loading Registration from {registrationPath}");
                            using (var registrationStream = File.OpenRead(registrationPath))
                                client.Registration = AcmeRegistration.Load(registrationStream);
                        }
                        else
                        {
                            var contacts = new string[] { };
                            if (!String.IsNullOrEmpty(email))
                            {
                                email    = "mailto:" + email;
                                contacts = new string[] { email };
                            }

                            Trace.TraceInformation("Calling Register");
                            var registration = client.Register(contacts);


                            Trace.TraceInformation("Updating Registration");
                            client.UpdateRegistration(true, true);

                            Trace.TraceInformation("Saving Registration");
                            using (var registrationStream = File.OpenWrite(registrationPath))
                                client.Registration.Save(registrationStream);

                            Trace.TraceInformation("Saving Signer");
                            using (var signerStream = File.OpenWrite(signerPath))
                                signer.Save(signerStream);
                        }

                        //                        if (Options.Renew)
                        //                        {
                        //                            CheckRenewals();
                        //#if DEBUG
                        //                            Trace.TraceInformation("Press enter to continue.");
                        //                            Trace.ReadLine();
                        //#endif
                        //                            return;
                        //                        }
                        return(Auto(target));
                    }
                }
            }
            catch (Exception e)
            {
                var acmeWebException = e as AcmeClient.AcmeWebException;
                if (acmeWebException != null)
                {
                    Trace.TraceError(acmeWebException.Message);
                    Trace.TraceError("ACME Server Returned:");
                    Trace.TraceError(acmeWebException.Response.ContentAsString);
                }
                else
                {
                    Trace.TraceError(e.ToString());
                }
                throw;
            }
        }
Exemple #12
0
        internal bool MakeCertificate()
        {
            try
            {
                using (var signer = new RS256Signer())
                {
                    signer.Init();

                    var signerPath = Path.Combine(configPath, "Signer");
                    if (File.Exists(signerPath))
                    {
                        logger.Debug("Loading Signer from {0}", signerPath);
                        using (var signerStream = File.OpenRead(signerPath))
                        {
                            signer.Load(signerStream);
                        }
                    }

                    using (client = new AcmeClient(new Uri(acmeUri), new AcmeServerDirectory(), signer))
                    {
                        client.Init();
                        client.GetDirectory(true);

                        var registrationPath = Path.Combine(configPath, "Registration");
                        if (File.Exists(registrationPath))
                        {
                            logger.Debug("Loading Registration from {0}", registrationPath);
                            using (var registrationStream = File.OpenRead(registrationPath))
                            {
                                client.Registration = AcmeRegistration.Load(registrationStream);
                            }
                        }
                        else
                        {
                            var email        = "mailto:" + contactEmail;
                            var registration = client.Register(new string[] { email });

                            client.UpdateRegistration(true, true);

                            using (var registrationStream = File.OpenWrite(registrationPath))
                            {
                                client.Registration.Save(registrationStream);
                            }

                            using (var signerStream = File.OpenWrite(signerPath))
                            {
                                signer.Save(signerStream);
                            }
                        }

                        List <AuthorizationState> authStatus = Authorize();

                        if (authStatus.Any(a => a.Status == "invalid"))
                        {
                            return(false);
                        }

                        PathToCertificate = RequestCertificate();
                    }
                }
            }
            catch (Exception e)
            {
                if (e is AcmeClient.AcmeWebException acmeWebException)
                {
                    logger.Fatal(acmeWebException.Message);
                    logger.Fatal("ACME Server Returned: {0}", acmeWebException.Response.ContentAsString);
                }
                else
                {
                    logger.Fatal(e);
                }

                return(false);
            }

            return(true);
        }
 public static void SaveToFile(AcmeRegistration registration, string filePath)
 {
     using (var registrationStream = File.OpenWrite(filePath))
         registration.Save(registrationStream);
 }
 public static AcmeRegistration LoadFromFile(string filePath)
 {
     using (var registrationStream = File.OpenRead(filePath))
         return(AcmeRegistration.Load(registrationStream));
 }
        private void LoadOrCreateRegistration()
        {
            if (File.Exists(_RegistrationJsonPath))
            {
                Globals.Log($"Loading {_RegistrationJsonPath}");
                using (var FS = File.OpenRead(_RegistrationJsonPath)) _Client.Registration = AcmeRegistration.Load(FS);
            }
            else
            {
                Console.WriteLine("Enter an email address (not public, used for renewal fail notices):");
                var Email = Console.ReadLine().Trim();

                string[] Contacts = { };
                if (!string.IsNullOrWhiteSpace(Email))
                {
                    Contacts = new string[] { $"mailto:{Email}" };
                }

                Globals.Log($"Registering with email: {Email}");
                _Client.Register(Contacts);

                Globals.Log("Updating registration");
                _Client.UpdateRegistration(true, true);

                Globals.Log($"Saving {_RegistrationJsonPath}");
                using (var FS = File.OpenWrite(_RegistrationJsonPath)) _Client.Registration.Save(FS);

                Globals.Log($"Saving {_SignerXmlPath}");
                using (var FS = File.OpenWrite(_SignerXmlPath)) _Signer.Save(FS);
            }
        }
Exemple #16
0
        private bool Worker()
        {
            Log("RefreshCertificate start");
            if (!IsAdministrator())
            {
                Log("\tThis program must be run as administrator");
                Log("RefreshCertificate ended");
                return(false);
            }

            // Get all Binding from the different IIS servers, if any
            var sites = GetSiteBindings();

            if (System.Diagnostics.Debugger.IsAttached)
            {
                sites.RemoveRange(1, sites.Count - 1);                 // only use the first one
            }
            RemoveValidWebsites(sites);
            if (sites.Count == 0)
            {
                Log("RefreshCertificate ended");
                return(false);
            }

            var contacts = Properties.Settings.Default.Contacts.Cast <string>().Select(x => "mailto:" + x).ToArray();

            using (var signer = new RS256Signer())
            {
                signer.Init();

                var signerPath = "RSAKeyValue.xml";
                if (File.Exists(signerPath))
                {
                    using (var signerStream = File.OpenRead(signerPath))
                        signer.Load(signerStream);
                    Log("\tLoaded existing {0}", signerPath);
                }
                using (this.client = new AcmeClient(this.BaseUri, new AcmeServerDirectory(), signer))
                {
                    this.client.Init();
                    this.client.GetDirectory(true);

                    var registrationPath = "Registration.json";
                    if (File.Exists(registrationPath))
                    {
                        using (var registrationStream = File.OpenRead(registrationPath))
                            this.client.Registration = AcmeRegistration.Load(registrationStream);

                        Log("\tLoaded existing {0}", registrationPath);
                    }
                    else
                    {
                        var registration = this.client.Register(contacts);

                        this.client.UpdateRegistration(true, true);
                        using (var registrationStream = File.OpenWrite(registrationPath))
                            this.client.Registration.Save(registrationStream);

                        Log("\tCreated new {0}", registrationPath);

                        using (var signerStream = File.OpenWrite(signerPath))
                            signer.Save(signerStream);

                        Log("\tCreated new {0}", signerPath);
                    }

                    // ACME client is now loaded using signer and registration
                    ChallengeGetCertAndInstall(sites);
                }
            }

            Log("RefreshCertificate ended");
            return(true);
        }
        static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                         .ReadFrom.AppSettings()
                         .CreateLogger();
            Log.Information("The global logger has been configured");

            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

            var commandLineParseResult = Parser.Default.ParseArguments <Options>(args);
            var parsed = commandLineParseResult as Parsed <Options>;

            if (parsed == null)
            {
#if DEBUG
                Log.Debug("Program Debug Enabled");
                Console.WriteLine("Press enter to continue.");
                Console.ReadLine();
#endif
                return; // not parsed
            }
            Options = parsed.Value;
            Log.Debug("{@Options}", Options);
            Console.WriteLine("Let's Encrypt (Simple Windows ACME Client)");
            BaseURI = Options.BaseURI;
            if (Options.Test)
            {
                BaseURI = "https://acme-staging.api.letsencrypt.org/";
                Log.Debug("Test paramater set: {BaseURI}", BaseURI);
            }
            if (Options.SAN)
            {
                Log.Debug("SAN Option Enabled: Running per site and not per host");
            }

            Console.WriteLine($"\nACME Server: {BaseURI}");
            Log.Information("ACME Server: {BaseURI}", BaseURI);

            if (!string.IsNullOrWhiteSpace(Options.CentralSSLStore))
            {
                Console.WriteLine("Using Centralized SSL Path: " + Options.CentralSSLStore);
                Log.Information("Using Centralized SSL Path: {CentralSSLStore}", Options.CentralSSLStore);
                CentralSSL = true;
            }

            settings = new Settings(clientName, BaseURI);
            Log.Debug("{@settings}", settings);
            configPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), clientName, CleanFileName(BaseURI));
            Console.WriteLine("Config Folder: " + configPath);
            Log.Information("Config Folder: {configPath}", configPath);
            Directory.CreateDirectory(configPath);

            certificatePath = Properties.Settings.Default.CertificatePath;

            if (string.IsNullOrWhiteSpace(certificatePath))
            {
                certificatePath = configPath;
            }
            else
            {
                try
                {
                    Directory.CreateDirectory(certificatePath);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error creating the certificate directory, {certificatePath}. Defaulting to config path");
                    Log.Warning("Error creating the certificate directory, {certificatePath}. Defaulting to config path. Error: {@ex}", certificatePath, ex);

                    certificatePath = configPath;
                }
            }

            Console.WriteLine("Certificate Folder: " + certificatePath);
            Log.Information("Certificate Folder: {certificatePath}", certificatePath);

            try
            {
                using (var signer = new RS256Signer())
                {
                    signer.Init();

                    var signerPath = Path.Combine(configPath, "Signer");
                    if (File.Exists(signerPath))
                    {
                        Console.WriteLine($"Loading Signer from {signerPath}");
                        Log.Information("Loading Signer from {signerPath}", signerPath);
                        using (var signerStream = File.OpenRead(signerPath))
                            signer.Load(signerStream);
                    }

                    using (client = new AcmeClient(new Uri(BaseURI), new AcmeServerDirectory(), signer))
                    {
                        client.Init();
                        Console.WriteLine("\nGetting AcmeServerDirectory");
                        Log.Information("Getting AcmeServerDirectory");
                        client.GetDirectory(true);

                        var registrationPath = Path.Combine(configPath, "Registration");
                        if (File.Exists(registrationPath))
                        {
                            Console.WriteLine($"Loading Registration from {registrationPath}");
                            Log.Information("Loading Registration from {registrationPath}", registrationPath);
                            using (var registrationStream = File.OpenRead(registrationPath))
                                client.Registration = AcmeRegistration.Load(registrationStream);
                        }
                        else
                        {
                            Console.Write("Enter an email address (not public, used for renewal fail notices): ");
                            var email = Console.ReadLine().Trim();

                            var contacts = new string[] { };
                            if (!String.IsNullOrEmpty(email))
                            {
                                Log.Debug("Registration email: {email}", email);
                                email    = "mailto:" + email;
                                contacts = new string[] { email };
                            }

                            Console.WriteLine("Calling Register");
                            Log.Information("Calling Register");
                            var registration = client.Register(contacts);

                            if (!Options.AcceptTOS && !Options.Renew)
                            {
                                Console.WriteLine($"Do you agree to {registration.TosLinkUri}? (Y/N) ");
                                if (!PromptYesNo())
                                {
                                    return;
                                }
                            }

                            Console.WriteLine("Updating Registration");
                            Log.Information("Updating Registration");
                            client.UpdateRegistration(true, true);

                            Console.WriteLine("Saving Registration");
                            Log.Information("Saving Registration");
                            using (var registrationStream = File.OpenWrite(registrationPath))
                                client.Registration.Save(registrationStream);

                            Console.WriteLine("Saving Signer");
                            Log.Information("Saving Signer");
                            using (var signerStream = File.OpenWrite(signerPath))
                                signer.Save(signerStream);
                        }

                        if (Options.Renew)
                        {
                            CheckRenewals();
#if DEBUG
                            Console.WriteLine("Press enter to continue.");
                            Console.ReadLine();
#endif
                            return;
                        }
                        var targets = new List <Target>();
                        if (!Options.SAN)
                        {
                            foreach (var plugin in Target.Plugins.Values)
                            {
                                targets.AddRange(plugin.GetTargets());
                            }
                        }
                        else
                        {
                            foreach (var plugin in Target.Plugins.Values)
                            {
                                targets.AddRange(plugin.GetSites());
                            }
                        }

                        if (targets.Count == 0)
                        {
                            Console.WriteLine("No targets found.");
                            Log.Error("No targets found.");
                        }
                        else
                        {
                            int HostsPerPage = 50;
                            try
                            {
                                HostsPerPage = Properties.Settings.Default.HostsPerPage;
                            }
                            catch (Exception ex)
                            {
                                Log.Error("Error getting HostsPerPage setting, setting to default value. Error: {@ex}", ex);
                            }
                            var count = 1;
                            if (targets.Count > HostsPerPage)
                            {
                                do
                                {
                                    if ((count + HostsPerPage) <= targets.Count)
                                    {
                                        int stop = count + HostsPerPage;
                                        for (int i = count; i < stop; i++)
                                        {
                                            if (!Options.SAN)
                                            {
                                                Console.WriteLine($" {count}: {targets[count - 1]}");
                                            }
                                            else
                                            {
                                                Console.WriteLine($" {count}: SAN - {targets[count - 1]}");
                                            }
                                            count++;
                                        }
                                    }
                                    else
                                    {
                                        for (int i = count; i <= targets.Count; i++)
                                        {
                                            if (!Options.SAN)
                                            {
                                                Console.WriteLine($" {count}: {targets[count - 1]}");
                                            }
                                            else
                                            {
                                                Console.WriteLine($" {count}: SAN - {targets[count - 1]}");
                                            }
                                            count++;
                                        }
                                    }

                                    if (count < targets.Count)
                                    {
                                        Console.WriteLine(" Q: Quit");
                                        Console.Write("Press enter to continue to next page ");
                                        var continueResponse = Console.ReadLine().ToLowerInvariant();
                                        switch (continueResponse)
                                        {
                                        case "q":
                                            throw new Exception($"Requested to quit application");

                                        default:
                                            break;
                                        }
                                    }
                                }while (count < targets.Count);
                            }
                            else
                            {
                                foreach (var binding in targets)
                                {
                                    Console.WriteLine($" {count}: {binding}");
                                    count++;
                                }
                            }
                        }

                        Console.WriteLine();
                        foreach (var plugin in Target.Plugins.Values)
                        {
                            plugin.PrintMenu();
                        }

                        Console.WriteLine(" A: Get certificates for all hosts");
                        Console.WriteLine(" Q: Quit");
                        Console.Write("Which host do you want to get a certificate for: ");
                        var response = Console.ReadLine().ToLowerInvariant();
                        switch (response)
                        {
                        case "a":
                            foreach (var target in targets)
                            {
                                Auto(target);
                            }
                            break;

                        case "q":
                            return;

                        default:
                            var targetId = 0;
                            if (Int32.TryParse(response, out targetId))
                            {
                                targetId--;
                                if (targetId >= 0 && targetId < targets.Count)
                                {
                                    var binding = targets[targetId];
                                    Auto(binding);
                                }
                            }
                            else
                            {
                                foreach (var plugin in Target.Plugins.Values)
                                {
                                    plugin.HandleMenuResponse(response, targets);
                                }
                            }
                            break;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Log.Error("Error {@e}", e);
                Console.ForegroundColor = ConsoleColor.Red;
                var acmeWebException = e as AcmeClient.AcmeWebException;
                if (acmeWebException != null)
                {
                    Console.WriteLine(acmeWebException.Message);
                    Console.WriteLine("ACME Server Returned:");
                    Console.WriteLine(acmeWebException.Response.ContentAsString);
                }
                else
                {
                    Console.WriteLine(e);
                }
                Console.ResetColor();
            }

            Console.WriteLine("Press enter to continue.");
            Console.ReadLine();
        }
 private static void LoadRegistrationFromFile(string registrationPath)
 {
     _log.Debug("Loading registration from {registrationPath}", registrationPath);
     using (var registrationStream = File.OpenRead(registrationPath))
         _client.Registration = AcmeRegistration.Load(registrationStream);
 }
        /// <inheritdoc cref="IAcmeSharpProvider"/>
        public void InitRegistration(
            string signerPath,
            string registrationPath,
            string email)
        {
            this.Signer = new RS256Signer();
            this.Signer.Init();

            string signerBackupPath       = signerPath + ".bak";
            string registrationBackupPath = registrationPath + ".bak";

            // For some unkown reason, signer and registration files get corrupted at 0 bytes who knows
            // why during usage, so we keep backups that are restored when corruption is detected.
            // Probably due to a buggy implementation downwards in this same method...

            if (File.Exists(signerBackupPath) && File.Exists(signerPath) && new FileInfo(signerPath).Length == 0)
            {
                this.Logger.LogWarning(true, "Signer file corrupted, restoring from backup: {0}", signerBackupPath);
                File.Copy(signerBackupPath, signerPath, true);
            }

            if (File.Exists(registrationBackupPath) && File.Exists(registrationPath) && new FileInfo(registrationPath).Length == 0)
            {
                this.Logger.LogWarning(true, "Registration file corrupted, restoring from backup: {0}", registrationBackupPath);
                File.Copy(registrationBackupPath, registrationPath, true);
            }

            // Load the signer

            if (File.Exists(signerPath))
            {
                try
                {
                    this.LoadSignerFromFile(this.Signer, signerPath);
                }
                catch (Exception e)
                {
                    throw new Exception($"Could not load signer from path: {signerPath}", e);
                }
            }

            this.AcmeClient = new AcmeClient(new Uri(this.AcmeUri), new AcmeServerDirectory(), signer: this.Signer);

            this.AcmeClient.Init();
            this.AcmeClient.GetDirectory(true);

            if (File.Exists(registrationPath))
            {
                try
                {
                    using (var registrationStream = File.OpenRead(registrationPath))
                    {
                        this.AcmeClient.Registration = AcmeRegistration.Load(registrationStream);
                    }
                }
                catch (Exception e)
                {
                    throw new Exception($"Could not load registration from path: {registrationPath}", e);
                }
            }
            else
            {
                this.Logger.LogInfo(true, "Calling Register");

                AcmeRegistration registration = this.AcmeClient.Register(new string[] { "mailto:" + email });

                this.Logger.LogInfo(true, "Updating Registration");

                this.AcmeClient.UpdateRegistration(useRootUrl: true, agreeToTos: true);

                this.Logger.LogInfo(true, "Saving Registration");

                using (var registrationStream = File.OpenWrite(registrationPath))
                {
                    this.AcmeClient.Registration.Save(registrationStream);
                }

                File.Copy(registrationPath, registrationBackupPath);

                this.Logger.LogInfo(true, "Saving Signer");

                using (var signerStream = File.OpenWrite(signerPath))
                {
                    this.Signer.Save(signerStream);
                }

                File.Copy(signerPath, signerBackupPath);
            }
        }