summaryrefslogtreecommitdiffstats
path: root/src/main.lib/Plugins/StorePlugins/PemFiles/PemFiles.cs
blob: 8c0adc7f4876fa0ae57c5029f5e5f8ff4afd2fa4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
using Org.BouncyCastle.Pkcs;
using PKISharp.WACS.DomainObjects;
using PKISharp.WACS.Extensions;
using PKISharp.WACS.Plugins.Interfaces;
using PKISharp.WACS.Services;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;

namespace PKISharp.WACS.Plugins.StorePlugins
{
    internal class PemFiles : IStorePlugin
    {
        private readonly ILogService _log;
        private readonly PemService _pemService;

        private readonly string _path;

        public static string? DefaultPath(ISettingsService settings)
        {
            var ret = settings.Store.PemFiles?.DefaultPath;
            if (string.IsNullOrWhiteSpace(ret))
            {
                ret = settings.Store.DefaultPemFilesPath;
            }
            return ret;
        }

        public PemFiles(
            ILogService log, ISettingsService settings,
            PemService pemService, PemFilesOptions options)
        {
            _log = log;
            _pemService = pemService;
            var path = options.Path;
            if (string.IsNullOrWhiteSpace(path))
            {
                path = DefaultPath(settings);
            }
            if (!string.IsNullOrWhiteSpace(path) && path.ValidPath(log))
            {
                _log.Debug("Using .pem files path: {path}", path);
                _path = path;
            }
            else
            {
                throw new Exception($"Specified .pem files path {path} is not valid.");
            }
        }

        public async Task Save(CertificateInfo input)
        {
            
            _log.Information("Exporting .pem files to {folder}", _path);
            try
            {
                // Determine name
                var name = input.CommonName.Replace("*", "_");

                // Base certificate
                var certificateExport = input.Certificate.Export(X509ContentType.Cert);
                var certString = _pemService.GetPem("CERTIFICATE", certificateExport);
                var chainString = "";
                await File.WriteAllTextAsync(Path.Combine(_path, $"{name}-crt.pem"), certString);

                // Rest of the chain
                foreach (var chainCertificate in input.Chain)
                {
                    // Do not include self-signed certificates, root certificates
                    // are supposed to be known already by the client.
                    if (chainCertificate.Subject != chainCertificate.Issuer)
                    {
                        var chainCertificateExport = chainCertificate.Export(X509ContentType.Cert);
                        chainString += _pemService.GetPem("CERTIFICATE", chainCertificateExport);
                    }
                }

                // Save complete chain
                await File.WriteAllTextAsync(Path.Combine(_path, $"{name}-chain.pem"), certString + chainString);
                await File.WriteAllTextAsync(Path.Combine(_path, $"{name}-chain-only.pem"), chainString);
                input.StoreInfo.TryAdd(
                    GetType(),
                    new StoreInfo()
                    {
                        Name = PemFilesOptions.PluginName,
                        Path = _path
                    });

                // Private key
                if (input.CacheFile != null)
                {
                    var pkPem = "";
                    var store = new Pkcs12Store(input.CacheFile.OpenRead(), input.CacheFilePassword?.ToCharArray());
                    var alias = store.Aliases.OfType<string>().FirstOrDefault(p => store.IsKeyEntry(p));
                    if (alias == null)
                    {
                        _log.Warning("No key entries found");
                        return;
                    }
                    var entry = store.GetKey(alias);
                    var key = entry.Key;
                    if (key.IsPrivate)
                    {
                        pkPem = _pemService.GetPem(entry.Key);
                    }
                    if (!string.IsNullOrEmpty(pkPem))
                    {
                        await File.WriteAllTextAsync(Path.Combine(_path, $"{name}-key.pem"), pkPem);
                    }
                    else
                    {
                        _log.Warning("No private key found in Pkcs12Store");
                    }
                } 
                else
                {
                    _log.Warning("No private key found in cache");
                }
            }
            catch (Exception ex)
            {
                _log.Error(ex, "Error exporting .pem files to folder");
            }
        }

        public Task Delete(CertificateInfo input) => Task.CompletedTask;

        public CertificateInfo? FindByThumbprint() => null;

        (bool, string?) IPlugin.Disabled => (false, null);
    }
}