Skip to content

Commit 0faad5b

Browse files
authored
fix: handle invalid ServerNames during SSL handshake (getfider#689)
1 parent e5480aa commit 0faad5b

8 files changed

+226
-3
lines changed

app/pkg/web/ssl.go

+15-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"net/http"
88
"strings"
99

10+
"github.com/getfider/fider/app/pkg/env"
1011
"github.com/getfider/fider/app/pkg/errors"
1112
"github.com/goenning/sqlcertcache"
1213
"golang.org/x/crypto/acme/autocert"
@@ -78,12 +79,23 @@ func NewCertificateManager(certFile, keyFile string, conn *sql.DB) (*Certificate
7879
//Otherwise fallsback to a automatically generated certificate by Let's Encrypt
7980
func (m *CertificateManager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error) {
8081
if m.leaf != nil {
81-
//skip autoSSL is ServerName is empty or does't contain a dot
82-
skipAutoCert := hello.ServerName == "" || !strings.Contains(strings.Trim(hello.ServerName, "."), ".")
83-
if skipAutoCert || m.leaf.VerifyHostname(hello.ServerName) == nil {
82+
serverName := strings.Trim(strings.ToLower(hello.ServerName), ".")
83+
84+
// If ServerName is empty or does't contain a dot, just return the certificate
85+
if serverName == "" || !strings.Contains(serverName, ".") {
8486
return &m.cert, nil
8587
}
88+
89+
if env.IsSingleHostMode() {
90+
return &m.cert, nil
91+
} else if strings.HasSuffix(serverName, env.MultiTenantDomain()) {
92+
if m.leaf.VerifyHostname(serverName) == nil {
93+
return &m.cert, nil
94+
}
95+
return nil, errors.New(`ssl: invalid server name "%s"`, serverName)
96+
}
8697
}
98+
8799
return m.autossl.GetCertificate(hello)
88100
}
89101

app/pkg/web/ssl_test.go

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package web
2+
3+
import (
4+
"crypto/tls"
5+
"testing"
6+
7+
"github.com/getfider/fider/app/pkg/dbx"
8+
"github.com/getfider/fider/app/pkg/env"
9+
10+
. "github.com/getfider/fider/app/pkg/assert"
11+
)
12+
13+
func Test_GetCertificate(t *testing.T) {
14+
RegisterT(t)
15+
db := dbx.New()
16+
defer db.Close()
17+
18+
var testCases = []struct {
19+
mode string
20+
cert string
21+
serverName string
22+
valid bool
23+
}{
24+
{"multi", "all-test-fider-io", "", true},
25+
{"multi", "all-test-fider-io", "fider", true},
26+
{"multi", "all-test-fider-io", "feedback.test.fider.io", true},
27+
{"multi", "all-test-fider-io", "FEEDBACK.test.fider.io", true},
28+
{"multi", "all-test-fider-io", "app.feedback.test.fider.io", false},
29+
{"multi", "all-test-fider-io", "my.app.feedback.test.fider.io", false},
30+
{"single", "test-fider-io", "test.fider.io", true},
31+
{"single", "test-fider-io", "fider.io", true},
32+
}
33+
34+
for _, testCase := range testCases {
35+
env.Config.HostMode = testCase.mode
36+
certFile := env.Path("/app/pkg/web/testdata/" + testCase.cert + ".crt")
37+
keyFile := env.Path("/app/pkg/web/testdata/" + testCase.cert + ".key")
38+
wildcardCert, _ := tls.LoadX509KeyPair(certFile, keyFile)
39+
40+
manager, err := NewCertificateManager(certFile, keyFile, db.Connection())
41+
Expect(err).IsNil()
42+
cert, err := manager.GetCertificate(&tls.ClientHelloInfo{
43+
ServerName: testCase.serverName,
44+
})
45+
46+
if testCase.valid {
47+
Expect(err).IsNil()
48+
Expect(cert.Certificate).Equals(wildcardCert.Certificate)
49+
} else {
50+
Expect(cert).IsNil()
51+
Expect(err.Error()).ContainsSubstring(`ssl: invalid server name "` + testCase.serverName + `"`)
52+
}
53+
}
54+
}
55+
56+
func Test_UseAutoCert(t *testing.T) {
57+
RegisterT(t)
58+
db := dbx.New()
59+
defer db.Close()
60+
61+
manager, err := NewCertificateManager("", "", db.Connection())
62+
Expect(err).IsNil()
63+
64+
invalidServerNames := []string{"ideas.app.com", "feedback.mysite.com"}
65+
66+
for _, serverName := range invalidServerNames {
67+
cert, err := manager.GetCertificate(&tls.ClientHelloInfo{
68+
ServerName: serverName,
69+
})
70+
Expect(err.Error()).Equals(`acme/autocert: unable to authorize "` + serverName + `"; tried ["tls-sni-02" "tls-sni-01"]`)
71+
Expect(cert).IsNil()
72+
}
73+
}
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIC/zCCAeegAwIBAgIQZvBk7RY1LHb59JC6cX5SCzANBgkqhkiG9w0BAQsFADAS
3+
MRAwDgYDVQQKEwdBY21lIENvMB4XDTE4MTIxODE5NDI1N1oXDTI4MTIxNTE5NDI1
4+
N1owEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
5+
AQoCggEBANCVxVI/JkWjWoRgssk8A/94/E6xHkyBYU7ioDNSSYD5+/wtY3B9NrLV
6+
bKM8XZ5Sjv8OztoDA0BPaPGm3vxWBudo+qGsdnlgT9zFafw/lvlaiBWX2tsYf1ef
7+
7pgMfDZusJbep1bWq73TgjRUQRIeYSmjeUOjYISVLOkS0TcpDCNQ0Ps5fg2DElBE
8+
1oxAKCFE+j5gIv7GhqmM8Y/J85Lt1yqypo4XDAYkBrrZJ6ZVE4vvsyLT1ReDM7YT
9+
bIHXAyCOCGJT/WKtkQJuj8+/M2H2Ft7T+fOEIgbI7+AK7IqVh4Dtodn0m16RKfPX
10+
GurQUhG7KgKTQmYj7v20xNuoHU60LIMCAwEAAaNRME8wDgYDVR0PAQH/BAQDAgWg
11+
MBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwGgYDVR0RBBMwEYIP
12+
Ki50ZXN0LmZpZGVyLmlvMA0GCSqGSIb3DQEBCwUAA4IBAQBqIgulNv4pzYkf8bLU
13+
e05N/pkESkWNEtUSEvGkMCh6I8pG+rn7TWvaJpj0mGDUHb9A+ZpT2jnDSr/TOsPu
14+
iUHjfqybg1zYIJ+ShSoWviEV9zKM57brjfTjP1onQvc4UOW5FrlodLkyCkFRuUHm
15+
M0M+3IDgk83g3Z0Pi3IdToSRXpVSQtACX/r87fontBAsv54SBGlnIlSxNIPCxaws
16+
EwpAh05MwuMFx13Nb23ns0dvN/4t5h6Mvim2++p9tjC+mceSbs3ebWIJYxRfCQ8S
17+
UbpGjlUro6BvEcqmx/3akF+1gzEB+FulEf94Ib/DLQi9vq9GXYFYtS2Wi9yIU1RG
18+
Dm8e
19+
-----END CERTIFICATE-----
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEowIBAAKCAQEA0JXFUj8mRaNahGCyyTwD/3j8TrEeTIFhTuKgM1JJgPn7/C1j
3+
cH02stVsozxdnlKO/w7O2gMDQE9o8abe/FYG52j6oax2eWBP3MVp/D+W+VqIFZfa
4+
2xh/V5/umAx8Nm6wlt6nVtarvdOCNFRBEh5hKaN5Q6NghJUs6RLRNykMI1DQ+zl+
5+
DYMSUETWjEAoIUT6PmAi/saGqYzxj8nzku3XKrKmjhcMBiQGutknplUTi++zItPV
6+
F4MzthNsgdcDII4IYlP9Yq2RAm6Pz78zYfYW3tP584QiBsjv4ArsipWHgO2h2fSb
7+
XpEp89ca6tBSEbsqApNCZiPu/bTE26gdTrQsgwIDAQABAoIBABzv6kQSxrh6hSBA
8+
Wg1Y6iUTH826/L0YZeuPvTHhhJkEFVVS5qzAcko1GbE7urEwOu5fm4rbSCQv4BtG
9+
T0EqniKUidDMIFOObQXvzVhVahiF2sNEIfSrXV9GrM8jTEgw6wbDNOvzNDhNk462
10+
8aAV3tzr9PLRQ56hI23iUmwYobp0R57S+FOrTIBFOIwG0TcDKUQckGQ4xhubqkuW
11+
5YoRYq9AVZXekuYQUh+Qq0HF1dhZY4haafE+5cWkCa3W8fXsOg56l77gLNLeA1UW
12+
28wIc5cGihIab3PMj38ff5xflq7fMbuubEsA9mQfRY7n5C7Fek0E31fma/MG6sLh
13+
LL+QG0ECgYEA8IIj7C7H1IJncm1u9/96faC/gXuqQWTqstS6reU1YC9Gh/B3qlvO
14+
yOOzxR4xhme/d1wEoxyqeOJWsWdf9Qec+qh5mkVoQ6S32YzOe44ph/Shb0bU5Cb+
15+
GGQCXQfoh3PsRHIkLlcuKtIDhs6GtjMKFUse6m0p8eKIy8PQZeN5NckCgYEA3gU7
16+
NgFRevjzx99QTvCs27Fl8DdHrcZUXdYrSM4TG5/FolOfXCDzXSdevrRB+KNdgz7Q
17+
e2wDN7b3ba0WUIXKMrQ0Fnyq5lb9J3nz9ZPuzq0YCynMXj9pcI2E0sCHv1V74qyf
18+
4nVGWac99pjsmuTW5KrdE3lSLfH7fkeZG0w75esCgYB18pzDWz3MzhcFWv2sybG8
19+
onTIf2lDoMYo5YKXfWzrusOQLzHAbj2+70xeQyxuibqwQoRTqd9AYV+6qMO6Wv11
20+
P+JC8f7sDX/MRO2OUm2zqxjwhYAqU6URORqfnR1AMG2SM5fi0gZmIZBxMB+IgwdS
21+
4gBLXzXO1hXYODOfhCsRYQKBgQCDouRlc8ikucCIjB4of8hthbPkBlKodMQG0vnc
22+
89oecc+THDOLQzonzDT/qw7GZc4HCBJCa1tJCGGRlKN7YKfvAisz/fyyD3ePlV4R
23+
CAH6ZmSwEbtLUhupES9kaaTSy9NlJWaytUfd1iwF7suyVuYWtDvZ1P/ln+i2Cat8
24+
pOmKuwKBgGhumPyDVTr9a/e69gfkYgkFCaRsTTna6G73gYdBUrAprfPCdh8rr+r9
25+
HZc4TACJ3mWqLaFxQFhTpkeGI2R0T1P6/axMjdHdYWKtEGrb9WZT17LyLlU1KpoB
26+
zwMIzeK2FjaZcF6pZBvC74crTlO2N+HNNY7SJVZgZuy1c/3FieXi
27+
-----END RSA PRIVATE KEY-----
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIC/jCCAeagAwIBAgIRANUSMa4sYILX7j43vG350C8wDQYJKoZIhvcNAQELBQAw
3+
EjEQMA4GA1UEChMHQWNtZSBDbzAeFw0xODEyMTgxOTQzMTZaFw0yODEyMTUxOTQz
4+
MTZaMBIxEDAOBgNVBAoTB0FjbWUgQ28wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
5+
ggEKAoIBAQDBo7fJiYGczbuoWWV/PlxGkDRny3gT6+OyRK2VE4DonktgfOJpdeJo
6+
ehLPYvAN0OZeuMrkz/6Rp9OqzmYUpyY3ah5s/sjTxz4f2ApATUNhYVqMrdWd6TKE
7+
M+kUY8sF2DGZSM1PhitksRvSuuRaw+GukpPydeEqgCZCZRDLmZuL4fOkvc4VnRtw
8+
mTjHY+AQykbcKvMe7PDDx9ZR54njGnkcVgHICuIH10RrVsidDqzCDJD+iIyDLHLA
9+
zV3jsRQTSfF5KiCpxie8VcflQEDj2hdmUFDWR8fRjqsDznL/DdUaH6HQyvoo/Fg5
10+
IdD6eiFvzeqxUhXryG/cQwwHRRL8bGTlAgMBAAGjTzBNMA4GA1UdDwEB/wQEAwIF
11+
oDATBgNVHSUEDDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBgGA1UdEQQRMA+C
12+
DXRlc3QuZmlkZXIuaW8wDQYJKoZIhvcNAQELBQADggEBACgpyFNP1i2ccF3BqPqm
13+
PrJZ/kHrLu72rWXGL/0RE1ukYsdy/SLM4yzHHcf3LUSFxg1vKeuygcN3jQVxPP3K
14+
/JLBhOdwHS67cPAvyBkXEFU3K3DzZCcHShpLe3Ry2fxYsRASFK2uNNTpPIQabB9T
15+
ZfiHp5X6Hgs85OKUUG+xJXKu6yFw9TMe0qtGXOU1dW3wnZxtX8h+0CF0phH61SQj
16+
rlqcJNPBDagcFFOmvol5tFyc8JqSJ6CGtNJjoaTo17rOM5WbCiU5lhDayMT5eIF1
17+
Sk7UtXfDG0MT7hm4P5+hxhepnlSxB0PqrTWa4iL9la0FHm+3IUIjlIckS8qNGpTg
18+
Guw=
19+
-----END CERTIFICATE-----
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEpAIBAAKCAQEAwaO3yYmBnM27qFllfz5cRpA0Z8t4E+vjskStlROA6J5LYHzi
3+
aXXiaHoSz2LwDdDmXrjK5M/+kafTqs5mFKcmN2oebP7I08c+H9gKQE1DYWFajK3V
4+
nekyhDPpFGPLBdgxmUjNT4YrZLEb0rrkWsPhrpKT8nXhKoAmQmUQy5mbi+HzpL3O
5+
FZ0bcJk4x2PgEMpG3CrzHuzww8fWUeeJ4xp5HFYByAriB9dEa1bInQ6swgyQ/oiM
6+
gyxywM1d47EUE0nxeSogqcYnvFXH5UBA49oXZlBQ1kfH0Y6rA85y/w3VGh+h0Mr6
7+
KPxYOSHQ+nohb83qsVIV68hv3EMMB0US/Gxk5QIDAQABAoIBAQCQ8l0jljOYTYQY
8+
G3rXSbXG+DDSNUNYHi4eBjytJ6FJ/xvLSRAuAxkMPbyQ0q2AmgungcoWhv82xpqx
9+
87gD466+ske+LOXlaPI+4feidHNolHg0b/dEMggnX7gsFBsn79IIvK86xOL8h3qd
10+
Plqq+o+Xno7yYny+1JhPANoWnZAKnzXmlwlSAEp/1mFRqsAvJn55Oq6dAUS8WkI/
11+
WGPuJjhAf/RjYwaror7SzUjMX2XD3gKllpPxLZMdX1NJW7bQHHVh91npYN0zjudK
12+
wFK2zPO5W9Gh4WWwy6MfZ8XkDohgoBxQ0cqi0yS1Hq79TvPuKH0vcJ1d6Te3GSiv
13+
BE7DJ81NAoGBANtqwtmUPgYqLU1l6VocTQV7XJUs0r6PnlGA1EY6qO+x5tQ+rKn8
14+
EDd410+jtvRjD/MsdTURs50RPUrpfhrhtFfOw9O5C3k3XnwirRcVDGrEOCSavKUm
15+
yZt/QWr1WqYVTndHveaMiaMF9a2cI+pM+qPImx/6NwMrgXH04qhAnYv/AoGBAOHs
16+
tiPoxsPoqFpoWdSk46HeQDp+T7petT58Iw3FD38JrFv1Nwc+v7dfbTnP4ZxqIm6D
17+
NAQ8oKpWL0OH+nUAaOg6Cbn3CMRh4yH7sptphADQqn35uTIHcnrEOgKQjVe3aOGu
18+
bhhXTMm6T9DgMovV61UFH/N7pkzZ6iJq8j+HJV8bAoGAVQrPFLexRoBoaJw8UpGv
19+
hJVor+TclcFicmKFY+bufWCtf8v+7i9lNarfgN2KVrRihTTRBM2kmRcKc5OGLfMX
20+
DAV2vwP0n3nHZEOoZM7irir5O67BuR0MfPlYqJUKGl8dt3uV7drAqe/wZeajwPcv
21+
GfXxsfYwBkmBdWKdyuqoZY8CgYEA2aMrjwoluAH/dCBEMSmqs3sjinW1nkav+IKj
22+
TheApxONe4SMvyj+jMqbsO6GWySPCMDRsicpaw3dOAPdDSsY5GVMi13jjzLxGAKc
23+
+0O5SwO4yeRwODaeXI99hozz7AUePxHGsyIeMdKOIxxm9PhdXKi0L9z0xeHCv+cg
24+
eHxbTvMCgYASVKcG5BR7SR3YEseqInETJpn+sW2fU3VeuAaHwDYjQRbUr1iK5wAK
25+
6cd0ixQ9kmDHxl/26ZepHrsy2aT5+KE2ukqtZ4MP5njNCYW4kjHcDfDTqbHB0Mc0
26+
aZND9j/jF6hPsB9h2r1L7FNHdF9nAbtUtJ9ZRMOt4QFLzuCBWQ3Flg==
27+
-----END RSA PRIVATE KEY-----

etc/all-dev-fider-io.crt

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIC/jCCAeagAwIBAgIQPHy+qrjWAli48X78lKnSPDANBgkqhkiG9w0BAQsFADAS
3+
MRAwDgYDVQQKEwdBY21lIENvMB4XDTE4MTIxOTA3MDIwOFoXDTI4MTIxNjA3MDIw
4+
OFowEjEQMA4GA1UEChMHQWNtZSBDbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
5+
AQoCggEBAMaY5Tu7pDE5Ae9ZTikVUTdy16wNh6E73coZtyekxIXYfIw3j0rw1Z+S
6+
hc8mt6RmTYJzCLPQF7wX1hBMlq5KNlYxomfkfT7qaHSSTr6FZuZiH8kiCIG1dF/i
7+
tMkVP7c+sBfqr3BnXqjMQRX2gidR8DQcX44VvIX9ivQBvbHEZ8UFXbyIp2/Bm0+G
8+
GXPQHO8EHI74biiAW1FdqNpWFkTvsmy4mVgB3pWH2ZUdIbKyHo2IBQ0it1dmu3kd
9+
EUU3Wc1GPa5u+0/9cxrmnhnZXGSXKQzcbcACTNmaWPLR0QLFkK4TDfOeiT4OelUr
10+
VglxPod189LrKbr3ij56dtWXcIqz1BcCAwEAAaNQME4wDgYDVR0PAQH/BAQDAgWg
11+
MBMGA1UdJQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwGQYDVR0RBBIwEIIO
12+
Ki5kZXYuZmlkZXIuaW8wDQYJKoZIhvcNAQELBQADggEBAEsj9hvQzeOBqVcfGVYM
13+
BFck5KWRlzDO/4w113IXVqCyqeIyp3sRmD57Td5KSirZ2Ypj6zx9XrUipGth+sd2
14+
tp5TqASDoAmaABLlFnKbXM9re4+knbHOZsbvV8fZiJqm3VHHFc33E5zBBkRx9OP0
15+
YmguZ5+y3jiNNdJp3oyZ6kjHM1ESAqYhY6lE2Lqt40e0ISenJ6ZsushGYwLbvR4U
16+
gLnGZPOP6JsCUFnX7deNyHLFJdB3BVoY9X788/LwDXmgDeL0uDUT5w4hQD9RWOeb
17+
Q9A3hpY7t+HP8YJFacDqx0z3MpsshipQ3x+vkIFWndUolfbalvcUQeP5Fh+geLGf
18+
0+U=
19+
-----END CERTIFICATE-----

etc/all-dev-fider-io.key

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEpAIBAAKCAQEAxpjlO7ukMTkB71lOKRVRN3LXrA2HoTvdyhm3J6TEhdh8jDeP
3+
SvDVn5KFzya3pGZNgnMIs9AXvBfWEEyWrko2VjGiZ+R9PupodJJOvoVm5mIfySII
4+
gbV0X+K0yRU/tz6wF+qvcGdeqMxBFfaCJ1HwNBxfjhW8hf2K9AG9scRnxQVdvIin
5+
b8GbT4YZc9Ac7wQcjvhuKIBbUV2o2lYWRO+ybLiZWAHelYfZlR0hsrIejYgFDSK3
6+
V2a7eR0RRTdZzUY9rm77T/1zGuaeGdlcZJcpDNxtwAJM2ZpY8tHRAsWQrhMN856J
7+
Pg56VStWCXE+h3Xz0uspuveKPnp21ZdwirPUFwIDAQABAoIBAQCvrQ6ScWFEHY6l
8+
oJUwaGgIqbE4xFsm+GMwZOEM04b4c1FxY7CA9VuzJZTycuheKBUGgSXAkiJ8w4Ub
9+
s/RSxtkcFBn61zcnkYnHHKlFhZJJ16EQdeeafd4s98k+W2qaeXyiG3sH7pjgrpYg
10+
jIgDqkrWfgbVFEtJJ8hkIqof94Jn189bgBHjgiruXw3fv9S+HxNV7Jeq227l5SFA
11+
fD/mx7c1XY7tnebzGYbgTFvgAl9zyYqrdWOg0dvAI860dQDTCJVY5YlGKEf/2wut
12+
VFjsxx6TcKP1YurPK7FLuzLLImfykyr/HGuvqPMUU3OZMNQylYy2cMLm7XRNiOh0
13+
cpvAlSQhAoGBAPnAsyM2cs86TdXgadisSmi9XiqoUCheOIgLWE2psQDiDHJRmiwi
14+
xbQUySpt2ks5NEjT9D743xYnXG/groB9dsOs/GHteFkNjDmooktEp3nXIHw3IbrD
15+
w5ZuT1axhUSKXQGHq0D/xe7/tL8/4/hR515lZkGKkuFs3W/TKmuKVCPxAoGBAMuQ
16+
nqk+aGleXk4wHEShvNOqdfi76GO674F/6z+j0VgKePr0PlFsWVB5AWbpx0FU96iK
17+
u7BLiP+5mzl27GcnL/BqHfW3mP6VwQlRzhi8s/+MpDqHTkSvFZUBia/CzKaAR7Gl
18+
9H9ZKy4WanM+59LtX0jDqVTxpZbNXCiaivDBAuCHAoGBAJ6/zt3uCRIRlFIDQCRa
19+
dz2WSNnCfJj8MuC+nVVYLEtMY+7yUZYGUDaEE84lX2D7LnGwUAsK8/pH8KioXyML
20+
HMeKGC5C3IF2bBBmUSqYq/91L4/lF0p4jsT6vvFzCyui6zVCwCcjrPOak5ARE13O
21+
6csFlvbIF060fRhMWCVdGthxAoGAaR+CD/x+hwuIv+/waTDtBpHc4lqHpBkBXmrk
22+
3bSHg2PFHjPLitjdNsWGh9LqZz6ttogObPhVA1qiYoabhpmiFBF470+k3rQPP/TS
23+
7ctlWO8UUHVXYfjYuF5W8EE01jcgzwjYvnsZ5W8GAgXWSgLzVexVIdy4mqvqj71f
24+
Sv0hszkCgYAmSGhDQLl2EHyRtLZx3U+mvEUR+bfxelae5Mt5CbZ1E8+5Rk1ZYOEL
25+
4pfM7wt5EP3VarzCv+7xFDTXE2fBZ/jQfqLXpLPolMgWVDLNUIH21J+R8NxAdBi4
26+
k1Qw/HpGwRaj1z45tMz9YnNEJsP/SbTWjZBKpDCccgfiqQ07t8mmjw==
27+
-----END RSA PRIVATE KEY-----

0 commit comments

Comments
 (0)