1- // Copyright (c) Microsoft Corporation.
2- // Licensed under the MIT License.
3-
4- using System . Security . Cryptography . X509Certificates ;
5- using Titanium . Web . Proxy . Certificates . Cache ;
6- using Titanium . Web . Proxy . Helpers ;
7-
8- namespace Microsoft . DevProxy ;
9-
10- // based on https://github.com/justcoding121/titanium-web-proxy/blob/9e71608d204e5b67085656dd6b355813929801e4/src/Titanium.Web.Proxy/Certificates/Cache/DefaultCertificateDiskCache.cs
11- public sealed class CertificateDiskCache : ICertificateCache
12- {
13- private const string DefaultCertificateDirectoryName = "crts" ;
14- private const string DefaultCertificateFileExtension = ".pfx" ;
15- private const string DefaultRootCertificateFileName = "rootCert" + DefaultCertificateFileExtension ;
16- private const string ProxyConfigurationFolderName = "dev-proxy" ;
17-
18- private string ? rootCertificatePath ;
19-
20- public Task < X509Certificate2 ? > LoadRootCertificateAsync ( string pathOrName , string password , X509KeyStorageFlags storageFlags , CancellationToken cancellationToken )
21- {
22- var path = GetRootCertificatePath ( pathOrName , false ) ;
23- return Task . FromResult ( LoadCertificate ( path , password , storageFlags ) ) ;
24- }
25-
26- public Task SaveRootCertificateAsync ( string pathOrName , string password , X509Certificate2 certificate , CancellationToken cancellationToken )
27- {
28- var path = GetRootCertificatePath ( pathOrName , true ) ;
29- var exported = certificate . Export ( X509ContentType . Pkcs12 , password ) ;
30- File . WriteAllBytes ( path , exported ) ;
31- return Task . CompletedTask ;
32- }
33-
34- public Task < X509Certificate2 ? > LoadCertificateAsync ( string subjectName , X509KeyStorageFlags storageFlags , CancellationToken cancellationToken )
35- {
36- var filePath = Path . Combine ( GetCertificatePath ( false ) , subjectName + DefaultCertificateFileExtension ) ;
37- return Task . FromResult ( LoadCertificate ( filePath , string . Empty , storageFlags ) ) ;
38- }
39-
40- public Task SaveCertificateAsync ( string subjectName , X509Certificate2 certificate , CancellationToken cancellationToken )
41- {
42- var filePath = Path . Combine ( GetCertificatePath ( true ) , subjectName + DefaultCertificateFileExtension ) ;
43- var exported = certificate . Export ( X509ContentType . Pkcs12 ) ;
44- File . WriteAllBytes ( filePath , exported ) ;
45- return Task . CompletedTask ;
46- }
47-
48- public void Clear ( )
49- {
50- try
51- {
52- var path = GetCertificatePath ( false ) ;
53- if ( Directory . Exists ( path ) ) Directory . Delete ( path , true ) ;
54- }
55- catch ( Exception )
56- {
57- // do nothing
58- }
59- }
60-
61- private static X509Certificate2 ? LoadCertificate ( string path , string password , X509KeyStorageFlags storageFlags )
62- {
63- byte [ ] exported ;
64-
65- if ( ! File . Exists ( path ) ) return null ;
66-
67- try
68- {
69- exported = File . ReadAllBytes ( path ) ;
70- }
71- catch ( IOException )
72- {
73- // file or directory not found
74- return null ;
75- }
76-
77- return new X509Certificate2 ( exported , password , storageFlags ) ;
78- }
79-
80- private string GetRootCertificatePath ( string pathOrName , bool create )
81- {
82- if ( Path . IsPathRooted ( pathOrName ) ) return pathOrName ;
83-
84- return Path . Combine ( GetRootCertificateDirectory ( create ) ,
85- string . IsNullOrEmpty ( pathOrName ) ? DefaultRootCertificateFileName : pathOrName ) ;
86- }
87-
88- private string GetCertificatePath ( bool create )
89- {
90- var path = GetRootCertificateDirectory ( create ) ;
91-
92- var certPath = Path . Combine ( path , DefaultCertificateDirectoryName ) ;
93- if ( create && ! Directory . Exists ( certPath ) ) Directory . CreateDirectory ( certPath ) ;
94-
95- return certPath ;
96- }
97-
98- private string GetRootCertificateDirectory ( bool create )
99- {
100- if ( rootCertificatePath == null )
101- {
102- if ( RunTime . IsUwpOnWindows )
103- {
104- rootCertificatePath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . LocalApplicationData ) , ProxyConfigurationFolderName ) ;
105- }
106- else if ( RunTime . IsLinux )
107- {
108- rootCertificatePath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) , ProxyConfigurationFolderName ) ;
109- }
110- else if ( RunTime . IsMac )
111- {
112- rootCertificatePath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) , ProxyConfigurationFolderName ) ;
113- }
114- else
115- {
116- var assemblyLocation = AppContext . BaseDirectory ;
117-
118- var path = Path . GetDirectoryName ( assemblyLocation ) ;
119-
120- rootCertificatePath = path ?? throw new NullReferenceException ( ) ;
121- }
122- }
123-
124- if ( create && ! Directory . Exists ( rootCertificatePath ) )
125- {
126- Directory . CreateDirectory ( rootCertificatePath ) ;
127- }
128-
129- return rootCertificatePath ;
130- }
1+ // Copyright (c) Microsoft Corporation.
2+ // Licensed under the MIT License.
3+
4+ using System . Security . Cryptography . X509Certificates ;
5+ using Titanium . Web . Proxy . Certificates . Cache ;
6+ using Titanium . Web . Proxy . Helpers ;
7+
8+ namespace Microsoft . DevProxy ;
9+
10+ // based on https://github.com/justcoding121/titanium-web-proxy/blob/9e71608d204e5b67085656dd6b355813929801e4/src/Titanium.Web.Proxy/Certificates/Cache/DefaultCertificateDiskCache.cs
11+ public sealed class CertificateDiskCache : ICertificateCache
12+ {
13+ private const string DefaultCertificateDirectoryName = "crts" ;
14+ private const string DefaultCertificateFileExtension = ".pfx" ;
15+ private const string DefaultRootCertificateFileName = "rootCert" + DefaultCertificateFileExtension ;
16+ private const string ProxyConfigurationFolderName = "dev-proxy" ;
17+
18+ private string ? rootCertificatePath ;
19+
20+ public Task < X509Certificate2 ? > LoadRootCertificateAsync ( string pathOrName , string password , X509KeyStorageFlags storageFlags , CancellationToken cancellationToken )
21+ {
22+ var path = GetRootCertificatePath ( pathOrName , false ) ;
23+ return Task . FromResult ( LoadCertificate ( path , password , storageFlags ) ) ;
24+ }
25+
26+ public Task SaveRootCertificateAsync ( string pathOrName , string password , X509Certificate2 certificate , CancellationToken cancellationToken )
27+ {
28+ var path = GetRootCertificatePath ( pathOrName , true ) ;
29+ var exported = certificate . Export ( X509ContentType . Pkcs12 , password ) ;
30+ File . WriteAllBytes ( path , exported ) ;
31+ return Task . CompletedTask ;
32+ }
33+
34+ public Task < X509Certificate2 ? > LoadCertificateAsync ( string subjectName , X509KeyStorageFlags storageFlags , CancellationToken cancellationToken )
35+ {
36+ var filePath = Path . Combine ( GetCertificatePath ( false ) , subjectName + DefaultCertificateFileExtension ) ;
37+ return Task . FromResult ( LoadCertificate ( filePath , string . Empty , storageFlags ) ) ;
38+ }
39+
40+ public Task SaveCertificateAsync ( string subjectName , X509Certificate2 certificate , CancellationToken cancellationToken )
41+ {
42+ var filePath = Path . Combine ( GetCertificatePath ( true ) , subjectName + DefaultCertificateFileExtension ) ;
43+ var exported = certificate . Export ( X509ContentType . Pkcs12 ) ;
44+ File . WriteAllBytes ( filePath , exported ) ;
45+ return Task . CompletedTask ;
46+ }
47+
48+ public void Clear ( )
49+ {
50+ try
51+ {
52+ var path = GetCertificatePath ( false ) ;
53+ if ( Directory . Exists ( path ) ) Directory . Delete ( path , true ) ;
54+ }
55+ catch ( Exception )
56+ {
57+ // do nothing
58+ }
59+ }
60+
61+ private static X509Certificate2 ? LoadCertificate ( string path , string password , X509KeyStorageFlags storageFlags )
62+ {
63+ byte [ ] exported ;
64+
65+ if ( ! File . Exists ( path ) ) return null ;
66+
67+ try
68+ {
69+ exported = File . ReadAllBytes ( path ) ;
70+ }
71+ catch ( IOException )
72+ {
73+ // file or directory not found
74+ return null ;
75+ }
76+
77+ return X509CertificateLoader . LoadPkcs12 ( exported , password , storageFlags ) ;
78+ }
79+
80+ private string GetRootCertificatePath ( string pathOrName , bool create )
81+ {
82+ if ( Path . IsPathRooted ( pathOrName ) ) return pathOrName ;
83+
84+ return Path . Combine ( GetRootCertificateDirectory ( create ) ,
85+ string . IsNullOrEmpty ( pathOrName ) ? DefaultRootCertificateFileName : pathOrName ) ;
86+ }
87+
88+ private string GetCertificatePath ( bool create )
89+ {
90+ var path = GetRootCertificateDirectory ( create ) ;
91+
92+ var certPath = Path . Combine ( path , DefaultCertificateDirectoryName ) ;
93+ if ( create && ! Directory . Exists ( certPath ) ) Directory . CreateDirectory ( certPath ) ;
94+
95+ return certPath ;
96+ }
97+
98+ private string GetRootCertificateDirectory ( bool create )
99+ {
100+ if ( rootCertificatePath == null )
101+ {
102+ if ( RunTime . IsUwpOnWindows )
103+ {
104+ rootCertificatePath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . LocalApplicationData ) , ProxyConfigurationFolderName ) ;
105+ }
106+ else if ( RunTime . IsLinux )
107+ {
108+ rootCertificatePath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) , ProxyConfigurationFolderName ) ;
109+ }
110+ else if ( RunTime . IsMac )
111+ {
112+ rootCertificatePath = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) , ProxyConfigurationFolderName ) ;
113+ }
114+ else
115+ {
116+ var assemblyLocation = AppContext . BaseDirectory ;
117+
118+ var path = Path . GetDirectoryName ( assemblyLocation ) ;
119+
120+ rootCertificatePath = path ?? throw new NullReferenceException ( ) ;
121+ }
122+ }
123+
124+ if ( create && ! Directory . Exists ( rootCertificatePath ) )
125+ {
126+ Directory . CreateDirectory ( rootCertificatePath ) ;
127+ }
128+
129+ return rootCertificatePath ;
130+ }
131131}
0 commit comments