mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
ssl: Add Client Side Certificate Auth
Add Client Side Certificate Auth feature and handling to puma's MiniSSL. Also exposes SSL errors to puma/apps. compatibility notes: MRI only shell example: puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&ca=path_to_ca&verify_mode=force_peer' code example: (examples/client_side_ssl) app = proc {|env| p env['puma.peercert']; [200, {}, ["hey"]] } events = SSLEvents.new($stdout, $stderr) server = Puma::Server.new(app, events) admin_context = Puma::MiniSSL::Context.new admin_context.key = KEY_PATH admin_context.cert = CERT_PATH admin_context.ca = CA_CERT_PATH admin_context.verify_mode = Puma::MiniSSL::VERIFY_PEER | Puma::MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT server.add_ssl_listener("0.0.0.0", ADMIN_PORT, admin_context) server.min_threads = MIN_THREADS server.max_threads = MAX_THREADS server.persistent_timeout = IDLE_TIMEOUT server.run.join additional credits: Andy Alness <andy.alness@gmail.com>
This commit is contained in:
parent
6479e6b26b
commit
e8d25b30f3
21 changed files with 675 additions and 14 deletions
19
examples/puma/client-certs/ca.crt
Normal file
19
examples/puma/client-certs/ca.crt
Normal file
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDEDCCAfigAwIBAgIBATANBgkqhkiG9w0BAQUFADA4MRMwEQYKCZImiZPyLGQB
|
||||
GRYDbmV0MRQwEgYKCZImiZPyLGQBGRYEcHVtYTELMAkGA1UEAwwCY2EwIBcNMTQw
|
||||
MjAyMjAwODI3WhgPMjExNTAxMDkyMDA4MjdaMDgxEzARBgoJkiaJk/IsZAEZFgNu
|
||||
ZXQxFDASBgoJkiaJk/IsZAEZFgRwdW1hMQswCQYDVQQDDAJjYTCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBAN0u8/heGbkoFDDsx6uidE6DKPvjIPnZPFzR
|
||||
CMkzrNgIeq/hfAItIJAO0m8YZivkUWeE3ut4ibSL+OVTvLRWDL/L736LILUxrD2f
|
||||
joKHHLSVIUWl3H0VjYDE2RCiVkvxP4sAo7EYecZesTtb7W7DdAjHztFZIl+wT+ri
|
||||
MlxDRmYxwsOPQtL0/wJZF80uTpC29V47NY9ITd/A+1xMblPAuQKO3vqZ4Yq07mO/
|
||||
KKSbepo07v7jMhNOSHf8VBFlTzzG5AHmxZUW0qjCkJBV8N1MiT9cIk81ZuSqOZu3
|
||||
A+aDAlOYPJe2WVpGskCme9HkJaHTeP87tQUsLqRsLgq/AXh5R58CAwEAAaMjMCEw
|
||||
DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQAD
|
||||
ggEBAKiGZ57rSAlL9slQ0FklVjpe+YrfZvmaXTRPl+9YhikoVI91u1r/qA9PrXKn
|
||||
cL6u66SU6kJwI5572uT1TpKO7jQLXJZV0LO17WuF3P7y44QnNb53Em2GYi8DD/gq
|
||||
X0Y1u8QzIxo4uomWiE73fnao2I9eErKNi/xCySaX/SLQ/9tcEgUyeLlTtJZ3feVF
|
||||
7K0llR+hSb0Wy/uWnP7qP59YsyCJl1H23j7IEVCTMsOQ4tyIK16+qRA+aVLtE9f5
|
||||
orsrOWWGJOdAn1nCJweKqhG1vd3GKGRW3Rf/iugCbvgJy0NFLfTpeJ4fJosC3A/K
|
||||
6K+pe9hNsi2kBPwC67QeVjnbqd4=
|
||||
-----END CERTIFICATE-----
|
27
examples/puma/client-certs/ca.key
Normal file
27
examples/puma/client-certs/ca.key
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA3S7z+F4ZuSgUMOzHq6J0ToMo++Mg+dk8XNEIyTOs2Ah6r+F8
|
||||
Ai0gkA7SbxhmK+RRZ4Te63iJtIv45VO8tFYMv8vvfosgtTGsPZ+OgocctJUhRaXc
|
||||
fRWNgMTZEKJWS/E/iwCjsRh5xl6xO1vtbsN0CMfO0VkiX7BP6uIyXENGZjHCw49C
|
||||
0vT/AlkXzS5OkLb1Xjs1j0hN38D7XExuU8C5Ao7e+pnhirTuY78opJt6mjTu/uMy
|
||||
E05Id/xUEWVPPMbkAebFlRbSqMKQkFXw3UyJP1wiTzVm5Ko5m7cD5oMCU5g8l7ZZ
|
||||
WkayQKZ70eQlodN4/zu1BSwupGwuCr8BeHlHnwIDAQABAoIBABjXyj1OTHNYhhQM
|
||||
tEyZ3Zhn8PWByFVnyfje3a7DqBlHsogIuoYADZVApPAnfGpXpbEL4oHuMwFda2JO
|
||||
qnZS5/Gu9UJwXAceAiuVvUr55AaAbZFGFOLTxeX9tifBJBI5kZqKQtiEWEEop510
|
||||
MNHtEB5gWuF2sn6u7fsC1wc34zNdE/4hR1njsppIlJ1GP0ICQUI/YKybipF6+pI7
|
||||
+vg7bF5DU93/uUoRY83NjREeAswFE67OOHi592YIyr5TLu06NDqJ2EBneXyO63Q7
|
||||
pAakX84SI7k8p8t9XBW6D56pT23JYcrDXwayH1P+SAA4FdDhPlZlGPWjXqQc0biA
|
||||
l1HlfiECgYEA8bwVsukWSGE+XdRnilVATP4zTS7ZpcYzUufS9+pa5w0sVIkDScgL
|
||||
3YrB0rY7BS/kImOg+xrFz7ILCoIyjDCEVtly0Hc1aZw9SWu545lfFWcd7s7nN5nQ
|
||||
iM9jGxoAWu/VT2GKIfhxMK89CzLD1DGgqsiyYxmPMyplekupUEkkiHECgYEA6jxl
|
||||
uNddzzfKZKHEWS1Tax0hgchOaVMyML35ySz5kgw1tSO8G64eKtrSCq7wcSvb4uc3
|
||||
hz1yl5Ydxqa+1qX5Qi+UcoRhZZHqGTsbid1aiQJKltk4ImtlptBbX+NTvEDIDblQ
|
||||
fzse/a+upesutwaTchlXtuPG2F53UZeQ831GWQ8CgYAqKdtDDILVdxiwtwakS0Be
|
||||
7Yu3L6/IyWxUTpkuotLeMB8GU6ueJ+Vh6/zoqt5ahkLteKEwizfrhSuF1rXIXAIJ
|
||||
P/5VvCU12YmbD84pk6vRCN5gs/gCa7LC2iF4La3YLrLvGJ1GVZYwnrAwDte3YDyc
|
||||
7UqoHGIs031FuoK6vTdBEQKBgHG5bz3mOqKgGMDxFY6ihgzMcPc9FGzousaVhhAZ
|
||||
qPYyvWS7+9mImRb/dNlBBHY98B1jWz9rIxbcCIrpbGB05ucuiKltAoi45mrnmsA9
|
||||
23YHycUho7J6aDkskiClE4OkBD09iwqq3qoWwPnHjL/KDo5oJYEjZ+inPNE9gF/n
|
||||
o98bAoGBAMLZ7BYOXU1svCwuEz9RdAyXsrOX+Z9DW9i6WMVlfk9K1IxwpXYCvOjO
|
||||
J+wJuQtuNbwKqNPw1DUEp/25cDVoekRAxaKgYGlJFib8vEGtbQ7GQK9bDA11/sIz
|
||||
PQSfc92Y4+qpQ9WzhsZXip49itzBFgmN7/4eaohpvyHCFkVCZVpf
|
||||
-----END RSA PRIVATE KEY-----
|
19
examples/puma/client-certs/client.crt
Normal file
19
examples/puma/client-certs/client.crt
Normal file
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDAzCCAeugAwIBAgIBAzANBgkqhkiG9w0BAQUFADA4MRMwEQYKCZImiZPyLGQB
|
||||
GRYDbmV0MRQwEgYKCZImiZPyLGQBGRYEcHVtYTELMAkGA1UEAwwCY2EwIBcNMTQw
|
||||
MjAyMjAwODI3WhgPMjExNTAxMDkyMDA4MjdaMDwxEzARBgoJkiaJk/IsZAEZFgNu
|
||||
ZXQxFDASBgoJkiaJk/IsZAEZFgRwdW1hMQ8wDQYDVQQDDAZjbGllbnQwggEiMA0G
|
||||
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGnFKNrNj9pvHIK+iUf1UoDJ0O7hpj
|
||||
jn7QWd65xnHWN9YF9RfBVRxg7HLcPls6GL4c+e5KQP1W0o4gSzwbUc3a/LyqkTEA
|
||||
dligEjXTkQY6tCn/51CuClynreQ98wdgQrayzobKhWMALG7IRLraprZmiQJpxWOF
|
||||
evd7WkF32AwSklZMEdWcLdI36swTV0UzuR9IDUnIh5GGPbikF/6hQ1E1+rL/sZkh
|
||||
czYNEniJGk2pD3MqJguTvYTF24k1KEOV5koSuAPnyl4E/dX9g3AIHWo8OhqVs/4P
|
||||
hrX6++qmrsVz9LIvPw3+SMAE3QU49J7uAANRQMBlxWhlbIpeFi8zNig7AgMBAAGj
|
||||
EjAQMA4GA1UdDwEB/wQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEAtxbX3CfQgMwa
|
||||
CWYTjupyTC+KDajbkLLsNXw49PeTIj0FOjAdKA1zyEZcrxtaU+flJr8QHdI8HyZH
|
||||
hpofnOTSBg5k9y4Qz8gjI1Nsh0H8WU/d7F//2l2fUDOhVAb6JtTAKnMpU4snb0GD
|
||||
bxcO6QxfNh50Qdb7KoJH7baJ3aAnsRrLVGqQ7jH20iMu163j/pYw4dDskFMr65Le
|
||||
bMB3NeQ5pHwtYf2J5EliKCtH+Df/BTIl9u1vviZs84gA0Odai/YaMZWCqFiWqIax
|
||||
lkMHNSDWh2G++qMn9erLjRtYDAbIt3VhMncUpEBx3lBEIaVg7qyfpWQ4EkkkylH6
|
||||
WRv06vukVg==
|
||||
-----END CERTIFICATE-----
|
27
examples/puma/client-certs/client.key
Normal file
27
examples/puma/client-certs/client.key
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAxpxSjazY/abxyCvolH9VKAydDu4aY45+0FneucZx1jfWBfUX
|
||||
wVUcYOxy3D5bOhi+HPnuSkD9VtKOIEs8G1HN2vy8qpExAHZYoBI105EGOrQp/+dQ
|
||||
rgpcp63kPfMHYEK2ss6GyoVjACxuyES62qa2ZokCacVjhXr3e1pBd9gMEpJWTBHV
|
||||
nC3SN+rME1dFM7kfSA1JyIeRhj24pBf+oUNRNfqy/7GZIXM2DRJ4iRpNqQ9zKiYL
|
||||
k72ExduJNShDleZKErgD58peBP3V/YNwCB1qPDoalbP+D4a1+vvqpq7Fc/SyLz8N
|
||||
/kjABN0FOPSe7gADUUDAZcVoZWyKXhYvMzYoOwIDAQABAoIBAA7C+aPMEAiyStAs
|
||||
60l2OVcTsOy2J8H0ilpkA5jdNgLM/ZxNvilBcS2HBXZ3MAKeairvLJXaRLoaRjQC
|
||||
Q4JoTxuSo1cuGW1GXonvMI77/XGJiIGbqLR20rIny4oLMSYnbzrU/NG6nkQaCVXb
|
||||
PeQYdgAi+MnxwNbf79r8N1d3+FW85vjczo2aobWnJpir8U+xp5pe4xpqP8nddP7v
|
||||
tdfIku8HBt76pu4ZfZynO6z9C+ZKS1s7YmBkGNuE46kwl9dhdmZGawAHxNYNAAJS
|
||||
FPLHR11f3syjtPUUm3MAr5BlCFd6vgWYJFrdKv8/uH++WAiVvApnG/FjPh90i42p
|
||||
muGHJbECgYEA+eiHPNzlCwYpPzY+n/AfBQ48G7sYeHk/yEDvhkJOnwAQEQMMw1s9
|
||||
AGHFTaKa2rb6fruZp8qCXiuzhWq2x7e5+W2Buj+VU15fI1JCJW1s2GdlGOAclvEW
|
||||
HvhcmlwtmSOWgTv1bbVSgQZB9hjbVK+81yQ9hn6AxJUT9k1IU3HALGkCgYEAy3Ow
|
||||
DBX97AVn+1h4I/7cTqzjjLCaBn4UVcy0s3hsbvW/b+aYb8a3F4wJ7mWXvFk9Lb4h
|
||||
uMfka6DYHszma1Bp7BEr63QIAhf936PXAljgtBBCron+9Y6DD83mz/9sX/MTo/pE
|
||||
2J/qHOqYwoboDoscgtVXZxNM3UX70RJ6RBKAKwMCgYEAxpX+kWC/KWl18WM7lICN
|
||||
Rckv/qFIKsO+6XSgYcHjE/pKyhnwVHT2Ho2S6cRi5ZYtq/OLgIgt3INBnq1UHZRj
|
||||
1k8snUHVeXAujbTaFz/DFJvk/EVqso9Vkrqta4QAQAbFnGB3APzrWNgOJm9OKxeT
|
||||
KisEMRHpZU1JlZmH9bcYjLECgYAPb1tvz0tQWKim3PNgZ7l3Do7E4bENxQrt53Xe
|
||||
F8jCMkqvxqLR+BVz59/pAjQcyfhmPAJ67k9aCv3aeFkS0yr2Ced3GXpyDjfoe5mY
|
||||
R/3kK0ejzjxVjNZMoKZeKVajgOGAk0Ad3yP3xaSJPYrlb5BeLKlQ3Jn8P473MZut
|
||||
BmpK2QKBgQCr7aaFL5Ypv21kBKVI478jk7v/6PcYOztkFbOsje5A4SlkhlaE5u0h
|
||||
iK0jON8MnAieLeP5QvyXy5n6wL/6THUSxpm3ZJRXpNgKHqENJrZBh3HpmrtzXjxF
|
||||
WLMGl20yrsNUE8WR8wAJ5ECxwUPGZazDY9CD6C0Vm0LUWYdgZQnjnA==
|
||||
-----END RSA PRIVATE KEY-----
|
19
examples/puma/client-certs/client_expired.crt
Normal file
19
examples/puma/client-certs/client_expired.crt
Normal file
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDCTCCAfGgAwIBAgIBBDANBgkqhkiG9w0BAQUFADA4MRMwEQYKCZImiZPyLGQB
|
||||
GRYDbmV0MRQwEgYKCZImiZPyLGQBGRYEcHVtYTELMAkGA1UEAwwCY2EwHhcNMTQw
|
||||
MjAyMjAwODI3WhcNMTQwODA0MDgwODI3WjBEMRMwEQYKCZImiZPyLGQBGRYDbmV0
|
||||
MRQwEgYKCZImiZPyLGQBGRYEcHVtYTEXMBUGA1UEAwwOY2xpZW50LWV4cGlyZWQw
|
||||
ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZQSVfI4KNwus/+9gE9Rww
|
||||
+cehxzw80fNi4tmruSApitTIk1u1r1rYVexkBkVTtl6Fg/aNAAdsI4aATanyGj0m
|
||||
yRqEMxYMt8RtzAYHY6ZEJBm4WUAa44W7WNG2ZA/e0bCDq4Sn+hlPJw0e4iQimJqi
|
||||
8+iitgyTdicTKDR+9kTS3W/33PZqSwqqnN55m9n9A5FIKwd8fbPsO8k6xIhFS2sL
|
||||
KZ2TkAYLNXu2vFGJR7b37U8mYcHObB1p7U7WYJ2JCf21WZOC4iI25Xk7MFSUYPqb
|
||||
W/iV+41EcslbHwAZHEjqeNynKNlnZokVrviOFeFrHqXbVKp43027L3RZr/JXfxMl
|
||||
AgMBAAGjEjAQMA4GA1UdDwEB/wQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEAdCLR
|
||||
jmHeQDrtl9w0cr8Vls+clhoWSDIEj2NC7PRUbDS5T0kAnF/N64n9RJFPS+4bpZaT
|
||||
c9v3DXzdaTTp7moUrwVc3EKVLV5EJcm+TcuUhbL2ZnRgFHggVaoePShBHkDJGLz9
|
||||
lR30KJnKsyFKEDEyD4rYtYvg98858EtkuxKLsD8efQ/9V8WDLAJJWTsJweEbEpIq
|
||||
GqblQnBeNrLZ7yS32NAM9jnB9wPsMXPZnAAV/o/U6TTwIO9ChApWX+qer1/mIoc7
|
||||
90/XhxEVw6EcXfGPnsLJ85n9FNGbWnLFRxvFAYcD0z6KQYxVHDiUAMSKqAkpENYO
|
||||
k3gVOw5YNxNpPmUrjw==
|
||||
-----END CERTIFICATE-----
|
27
examples/puma/client-certs/client_expired.key
Normal file
27
examples/puma/client-certs/client_expired.key
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA2UElXyOCjcLrP/vYBPUcMPnHocc8PNHzYuLZq7kgKYrUyJNb
|
||||
ta9a2FXsZAZFU7ZehYP2jQAHbCOGgE2p8ho9JskahDMWDLfEbcwGB2OmRCQZuFlA
|
||||
GuOFu1jRtmQP3tGwg6uEp/oZTycNHuIkIpiaovPoorYMk3YnEyg0fvZE0t1v99z2
|
||||
aksKqpzeeZvZ/QORSCsHfH2z7DvJOsSIRUtrCymdk5AGCzV7trxRiUe29+1PJmHB
|
||||
zmwdae1O1mCdiQn9tVmTguIiNuV5OzBUlGD6m1v4lfuNRHLJWx8AGRxI6njcpyjZ
|
||||
Z2aJFa74jhXhax6l21SqeN9Nuy90Wa/yV38TJQIDAQABAoIBAQDOhvSc7aflVZ/H
|
||||
koT3qX8kO78AVuM3uiqSHa7pZTJi63x+ND9hhxJoR75SE/gBrYNLj3ho79cegOMS
|
||||
w0HEShdJ8LFJbTsP2f5cljBBBAUCEAN3UTj0lsgBolyx84t2uYYAlaOk/8bhjPEX
|
||||
I8lQLhwKvq2vSDrKT+6zcmv9KeWhQWoQavq+QAkTVO9gAqmlkdMEjZntT8hau/qC
|
||||
jkgW7MG/U/CkbALcrbhAWBtMSvUDSKHrrva7XPaMq5nDvX0Wj6PZhY9KaaweR8ZR
|
||||
xfrgzbFfRSKdbT5dD7IcwQhjV51hev6+q8pIFgTiFimeNq4TvKgH5MMwixBnVM+3
|
||||
djBTB4+dAoGBAO5BYdbpEuVDlwMfHo//R/BJEGJn9dwc3ZpBmJ6vQGmLGjf/oXBr
|
||||
9tDf/yZKDLwVAgnRdVkllMxpEWrFjD3OpnukbvzTijBi0AQAljRSwNlMTsLwAifi
|
||||
EBXvENFG/7iJKssCQBD6rkeNir3VRlMa5khI9jHahZ0B53RtQCYYDzZ/AoGBAOlv
|
||||
W005wD3g9K2P5BIo+qXB43ZFFsAFOnhu7jUyTciu/95iJ+zw/AGHI/JhNy+jSHnw
|
||||
ZCARLy1c2CImAshadYuWDqR5okR+xHHj3Lgf9ig7lbSf+skn3R4y6fTlxxNdbbU7
|
||||
dbZbiMm5CyUHTR6957BQaS7mfQZJG0OP5G9fl0xbAoGAOSNa+HRbALqN68S5yqTZ
|
||||
Nsn+8OqnrssJZiYXGO9Ejks61XUr3U83GO6vPRqDJVQQchRWhTObFM6Zy7ZmpKf7
|
||||
iylrKJz+xg3cfyk43IGAGFzRgrSWf8QaQXhc2yOgzjuvFJKMlMXZp/VM8avFOsb3
|
||||
tRwyVtBmPLopLOXKfZhFhbcCgYA/etbbU18h9LDVGhItlhNDTEys9vDO2x0hbxk8
|
||||
QifA8UYHla3B027Ug4mU+jblr4OgFW1FAydPMLZd4vRSw7a/dNkahTFJayfEyPBW
|
||||
6eoo2rtFWVP7q+mHstTIkkvmyjtxU3AZXR7/rGCJe0jPmVkOK2/PH0LUmMDfSJwY
|
||||
ZWhhjQKBgDCB823bmF6+7J0mtNFFKvRMz6k0wKz7Qe6+AkwmyR3v9IBpL4UMFgIq
|
||||
xdRR7iGhlRHaWVZyzG3WQ1ZgLmVUsfmk9OrD5PfhKaElKvaRr8e+MHOesQ6AgWW2
|
||||
YXr6vgr6tykVtjG4/v98r05+9q10HH0xOhbuBz+1P7IyLfTCWxbE
|
||||
-----END RSA PRIVATE KEY-----
|
19
examples/puma/client-certs/client_unknown.crt
Normal file
19
examples/puma/client-certs/client_unknown.crt
Normal file
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDEzCCAfugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBAMRMwEQYKCZImiZPyLGQB
|
||||
GRYDbmV0MRQwEgYKCZImiZPyLGQBGRYEcHVtYTETMBEGA1UEAwwKY2EtdW5rbm93
|
||||
bjAgFw0xNDAyMDIyMDA4MjdaGA8yMTE1MDEwOTIwMDgyN1owRDETMBEGCgmSJomT
|
||||
8ixkARkWA25ldDEUMBIGCgmSJomT8ixkARkWBHB1bWExFzAVBgNVBAMMDmNsaWVu
|
||||
dC11bmtub3duMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0Ewf7nWJ
|
||||
WcHI3NB+gjz5jWnpNwnU47hjIWq+S41iIymN7FsNdssfzeGb3ZElcQAfofvNf75F
|
||||
6mE7YEpbKRU7t/Nptvx+Rd1YGOS2N/PWdj3IcJgvQ2guiU0aYkdB7lC1vlI0QzHT
|
||||
dte9pGK/ZPp/mvRZGwi9WmwlNhBwOzvdyRuLyi63dmZ8vgyZrfbmGhZYdhCZ77Uv
|
||||
i+VYqYv5X30I2gQkV6YQMj/AF5Fmt9a4TNGfIjXb6FKmNhlsDMduovrfQMh2umMK
|
||||
YYQ4A+Vi2yMAZkKeD5cogGLS8wmg76n7miPaKLVU9xTEf55IO+HjIBIqz6VG8qbg
|
||||
iBV4Lr6BkkaKTQIDAQABoxIwEDAOBgNVHQ8BAf8EBAMCBLAwDQYJKoZIhvcNAQEF
|
||||
BQADggEBAGGaA7fZLOqxx1wIIay0Ewni3ljzR+RAlpTHAh4x+NilcaQ2ils+JoGH
|
||||
/DCdX2iD5nevGVm1DANBhfAuFxXGGBjoOLqtg/sO7Rk51IV9WjDVB2rGeH3hoTCk
|
||||
Qi6Bazdlcvvs3SyFEKcJm2zXizR7O9I+tDv++F6bbaHSBWB6tB9g93pZuMR+smvR
|
||||
Ll2+/jRGPe1Pif1UFs5DR8QshpvxrIwCmO1vznLhDeA5Pde6CtahGJvi1Y25L1h0
|
||||
9l0LjMxxqgVh8h4A5AR8VufCcDiaT8lzCkz4G4jQYFhrJXmBn8Em6NZfdP/LmM9I
|
||||
0zEB2Y3lp32ng+WMyaqNh6nfpxEfBoY=
|
||||
-----END CERTIFICATE-----
|
27
examples/puma/client-certs/client_unknown.key
Normal file
27
examples/puma/client-certs/client_unknown.key
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA0Ewf7nWJWcHI3NB+gjz5jWnpNwnU47hjIWq+S41iIymN7FsN
|
||||
dssfzeGb3ZElcQAfofvNf75F6mE7YEpbKRU7t/Nptvx+Rd1YGOS2N/PWdj3IcJgv
|
||||
Q2guiU0aYkdB7lC1vlI0QzHTdte9pGK/ZPp/mvRZGwi9WmwlNhBwOzvdyRuLyi63
|
||||
dmZ8vgyZrfbmGhZYdhCZ77Uvi+VYqYv5X30I2gQkV6YQMj/AF5Fmt9a4TNGfIjXb
|
||||
6FKmNhlsDMduovrfQMh2umMKYYQ4A+Vi2yMAZkKeD5cogGLS8wmg76n7miPaKLVU
|
||||
9xTEf55IO+HjIBIqz6VG8qbgiBV4Lr6BkkaKTQIDAQABAoIBAC41pSPWqWjjJ7ds
|
||||
/ZPRCR/JLjbKlJMMVdmU/7BtJidc0aJstLj06RJYiaaGy8Kc32elH/rF8GbFuVFs
|
||||
TXr4ve3aL0qsCytepmunWZFiI+LJZA0uhdWzaBeHpmHFIyhGeXtGa1e41wvXYrf0
|
||||
PDefpu1uZdIshy1nLn4m+W76ogI6FrcyUQ+XRN6f5x6af70Kfi414qf9NLOvajnl
|
||||
JCx90WpdwBp1jC8totKDp9kvILCymFnGBl93NUl8F3Tz7zLkh2SIhaKxQIHTc9g0
|
||||
LPNkd1Q5tIl/rG3lZ6vw2/UlCVB1NdLsItlJVIJhu6ChIrSXeoDg0GNlJFp7op6W
|
||||
jlJDoRUCgYEA67Nuzrv/lkVljRFDVw97DTiCbLL7SDXDH6Jf43+Bz6prGLqd4Nfd
|
||||
LTO7AdLGd5UTWB1Oj2U94pFXNFkucGv65ck6QAPZ4UrCk9lyjx/dN7d6CxUBDeu2
|
||||
4zPeHy/mAgkVmKSzEy5L2ERwoQqK8A/g6HtuThB87gtKUpnG+QSfz6sCgYEA4jyE
|
||||
kPRudqne0VXWL/Mhnrls2PNo4MDIOxUp+KcFLGY/44RIEoit3WLRDXULAgT3U20Z
|
||||
lY7nQJyU+/CaEH6rIpADp6VRPA0XJo7HCuMGEO7bk8AAXkXTplVs+XbsD0221AKl
|
||||
GRpS0CtcvHllHiwG8iL+zHAJzL4wbNY36L97decCgYB0UuHk9bN2Hlm3/UUWunUo
|
||||
WTNFIjARuzbJbgGU7WDLdHfWhINWbDKkFFu+0p9QdSpO2mfjLTwVjVVUaI8avK/e
|
||||
qCkvXrcxEQxmm3KGYFt1HAAHaB5VGHfyOa7uBV2ms4UNCHu4g6i620warnFTeQKu
|
||||
ufv+WvTNJpVPnsUsMLQOcQKBgQDcfgDxydjTPDIWseLjrsGIkc29EFaaHinIM5NJ
|
||||
bXbEVA9WbflUXvOc/g8jX3xQBokKPR2fPryxoyos9c0h4GJoeBWn0Z5/uX5jrOne
|
||||
+W5TGIjW0l1JhCKITV+9LqNZMvPKY52G/rnRe0GRy3q60kwet+6/Tz6t1nsZyBqL
|
||||
c/we5wKBgQDc0rE459diZTpxKzumgUGlutKWhqPDGO+NwMa8xaaPvn/k6bg5avx2
|
||||
8by3BSWhc/YEK7qtVcO1sDr7m9dHtqxrk8+2CC+ZI6wfc359xB9uImrbs9Jqz3VZ
|
||||
+Ji2VOirgm/oZNzhpi2l7yG2atXg0PqLMkS/ft6gWyAjzy/Q8WDSjQ==
|
||||
-----END RSA PRIVATE KEY-----
|
78
examples/puma/client-certs/generate.rb
Normal file
78
examples/puma/client-certs/generate.rb
Normal file
|
@ -0,0 +1,78 @@
|
|||
require "bundler/setup"
|
||||
require "puma"
|
||||
require "puma/minissl"
|
||||
|
||||
case ARGV[0]
|
||||
|
||||
when "s"
|
||||
|
||||
app = proc {|env|
|
||||
p env['puma.peercert']
|
||||
[200, {}, [ env['puma.peercert'] ]]
|
||||
}
|
||||
events = Puma::Events.new($stdout, $stderr)
|
||||
server = Puma::Server.new(app, events)
|
||||
|
||||
context = Puma::MiniSSL::Context.new
|
||||
context.key = "certs/server.key"
|
||||
context.cert = "certs/server.crt"
|
||||
context.ca = "certs/ca.crt"
|
||||
#context.verify_mode = Puma::MiniSSL::VERIFY_NONE
|
||||
#context.verify_mode = Puma::MiniSSL::VERIFY_PEER
|
||||
context.verify_mode = Puma::MiniSSL::VERIFY_PEER | Puma::MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
||||
|
||||
server.add_ssl_listener("127.0.0.1", 4000, context)
|
||||
|
||||
server.run
|
||||
sleep
|
||||
#server.stop(true)
|
||||
|
||||
when "g"
|
||||
|
||||
def issue_cert(dn, key, serial, not_before, not_after, extensions, issuer, issuer_key, digest)
|
||||
cert = OpenSSL::X509::Certificate.new
|
||||
issuer = cert unless issuer
|
||||
issuer_key = key unless issuer_key
|
||||
cert.version = 2
|
||||
cert.serial = serial
|
||||
cert.subject = dn
|
||||
cert.issuer = issuer.subject
|
||||
cert.public_key = key.public_key
|
||||
cert.not_before = not_before
|
||||
cert.not_after = not_after
|
||||
ef = OpenSSL::X509::ExtensionFactory.new
|
||||
ef.subject_certificate = cert
|
||||
ef.issuer_certificate = issuer
|
||||
extensions.each{|oid, value, critical|
|
||||
cert.add_extension(ef.create_extension(oid, value, critical))
|
||||
}
|
||||
cert.sign(issuer_key, digest)
|
||||
cert
|
||||
end
|
||||
|
||||
@ca_key = OpenSSL::PKey::RSA.generate(2048)
|
||||
@svr_key = OpenSSL::PKey::RSA.generate(2048)
|
||||
@cli_key = OpenSSL::PKey::RSA.generate(2048)
|
||||
@ca = OpenSSL::X509::Name.parse("/DC=net/DC=client-cbhq/CN=CA")
|
||||
@svr = OpenSSL::X509::Name.parse("/DC=net/DC=client-cbhq/CN=localhost")
|
||||
@cli = OpenSSL::X509::Name.parse("/DC=net/DC=client-cbhq/CN=localhost")
|
||||
now = Time.at(Time.now.to_i)
|
||||
ca_exts = [
|
||||
["basicConstraints","CA:TRUE",true],
|
||||
["keyUsage","cRLSign,keyCertSign",true],
|
||||
]
|
||||
ee_exts = [
|
||||
#["keyUsage","keyEncipherment,digitalSignature",true],
|
||||
["keyUsage","keyEncipherment,dataEncipherment,digitalSignature",true],
|
||||
]
|
||||
@ca_cert = issue_cert(@ca, @ca_key, 1, now, now+3600_000, ca_exts, nil, nil, OpenSSL::Digest::SHA1.new)
|
||||
@svr_cert = issue_cert(@svr, @svr_key, 2, now, now+1800_000, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
|
||||
@cli_cert = issue_cert(@cli, @cli_key, 3, now, now+1800_000, ee_exts, @ca_cert, @ca_key, OpenSSL::Digest::SHA1.new)
|
||||
|
||||
File.open("ca.crt","wb"){|f| f.print @ca_cert.to_pem }
|
||||
File.open("ca.key","wb"){|f| f.print @ca_key.to_pem }
|
||||
File.open("server.crt","wb"){|f| f.print @svr_cert.to_pem }
|
||||
File.open("server.key","wb"){|f| f.print @svr_key.to_pem }
|
||||
File.open("client1.crt","wb"){|f| f.print @cli_cert.to_pem }
|
||||
File.open("client1.key","wb"){|f| f.print @cli_key.to_pem }
|
||||
end
|
19
examples/puma/client-certs/server.crt
Normal file
19
examples/puma/client-certs/server.crt
Normal file
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDBjCCAe6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA4MRMwEQYKCZImiZPyLGQB
|
||||
GRYDbmV0MRQwEgYKCZImiZPyLGQBGRYEcHVtYTELMAkGA1UEAwwCY2EwIBcNMTQw
|
||||
MjAyMjAwODI3WhgPMjExNTAxMDkyMDA4MjdaMD8xEzARBgoJkiaJk/IsZAEZFgNu
|
||||
ZXQxFDASBgoJkiaJk/IsZAEZFgRwdW1hMRIwEAYDVQQDDAkxMjcuMC4wLjEwggEi
|
||||
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDK2ioejidqPJzhGgYh9Nc/CD8g
|
||||
n/vFqchULvmG796R01Rx0Xk5v7OgWs4GMhvJ8o4soCxTmACyPStdemDlocdzZf2d
|
||||
yfv1alVVfBBwqSsiekiB7IiSvpyg5t3h8XqWJcKtP00tPEYmAkVuMbVSxQPrsEi5
|
||||
47kxu7zyiV0RavaZbODgxkupSjEr0DHa1h7pkip53ekz/rnoceVcvSnCdOahUVj6
|
||||
ZwMkOQtay/b6746ttbfQh1ygbqTbV/lcV9erldlDkqKG0gQ6gxaBcbIiom1p+ohu
|
||||
CcoTDGZu431KOU6ZygbGxaIEZY9Zbyg9Dp+o6Zyyd7UTY/0JcCWUq7O/XaN5AgMB
|
||||
AAGjEjAQMA4GA1UdDwEB/wQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEAIfMqanJJ
|
||||
aVD6XuS3aj0I31L4RiPSfKhkPiuO+lqBGzZhUEKwnEqVWLosFF1SK8Inbu1c1uyP
|
||||
zRb0tB4nSO01L8Oc5kTfuN9lr3nNaWDpGksa/S5e9WndQk95XF3FLt7FJii8wWnM
|
||||
9xGW27lurskbpuZc1M7IkD5W90y2fF19qB8fY8B2RGovPJEsDKSZ7pwSozijGR4Q
|
||||
2iIY4Lk9/vYxEYMRixE2+exYiKTNfaPt+CgxHxXksn0LvbYYQTxUmDgvSxXdrnCc
|
||||
4Kb1BbxOmB8XF17aJuRdUJxDxlnQK5LpoUWGfW7jFPbfX4d3nzpxjPaxvr3peRQV
|
||||
DNtRoD9mFvocbQ==
|
||||
-----END CERTIFICATE-----
|
27
examples/puma/client-certs/server.key
Normal file
27
examples/puma/client-certs/server.key
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAytoqHo4najyc4RoGIfTXPwg/IJ/7xanIVC75hu/ekdNUcdF5
|
||||
Ob+zoFrOBjIbyfKOLKAsU5gAsj0rXXpg5aHHc2X9ncn79WpVVXwQcKkrInpIgeyI
|
||||
kr6coObd4fF6liXCrT9NLTxGJgJFbjG1UsUD67BIueO5Mbu88oldEWr2mWzg4MZL
|
||||
qUoxK9Ax2tYe6ZIqed3pM/656HHlXL0pwnTmoVFY+mcDJDkLWsv2+u+OrbW30Idc
|
||||
oG6k21f5XFfXq5XZQ5KihtIEOoMWgXGyIqJtafqIbgnKEwxmbuN9SjlOmcoGxsWi
|
||||
BGWPWW8oPQ6fqOmcsne1E2P9CXAllKuzv12jeQIDAQABAoIBABBL4JBd2TrGrc/D
|
||||
uHRn6BbvQasMTzy8/BQPRgqaIKZUdPdD3dpO1U5vnReQVP0vWE6re4QntP6cvWwg
|
||||
FcK88XoK2oofnPdFWJ+qfOOgI4/8hPCzIPGxEII4qeCp9rAzTmV+rWOR8QzCp/NH
|
||||
WQrSOxNnMSCF8+3T6EUP1gM9NZxzpycvoa3Xk4QduPdSN9+ifLOohvRwq0PsP8z5
|
||||
6tPIxEyHTmUjJhDh0en2fXFs6ncxvzQJ+p8R3cSaACDDmAR3uuKgpinC7zLKRyIB
|
||||
rqThVMOO+yxMYNNZ+JIJbuaAAAQy1znPfPsy8syFEvOBhZXJNLEpTqr7n4kHvxpW
|
||||
MI8ukTUCgYEA6zCSMEb9lH/z/qgJPYbZcUuT/M9/EJdiDlazfYrzAHsmwL/FRXjc
|
||||
vAJCeayy3A/oMBWJ+tQrRCPb0e/LU2kqLJRWENKN7uTAHGntDJOtM94ZWDLcAySv
|
||||
zo6usr7BhLmP8ySVojjbWoWI4+SHONYcxsk1v5O7f0ZbzMoDoQPPcl8CgYEA3M0Y
|
||||
l8mDcPlm90r0/CKq5egpzWvb6dvz5Sly83bJIK1CnjyZUbmQZSO2fp9fFFffZ3SG
|
||||
tbgDJ5xQ5Ie+H2mTCsCqkIRqi8tCnbHCXcN40N3SXxcS4e4UcMhVCAHrGODqHrAb
|
||||
if8uTxwozxZtYklaZwhszdtY0lWRG2BzILfOKScCgYBOjyvVqnDboJ3cyz5C6f9J
|
||||
48fr41d7MEXVqkpMPhSLbZd1PNllKkj5F/wibnhUH5AcN6WePi6xlRTBHEsbcn5e
|
||||
47GX7uzwBkLReuRulgl90MtAdcSd3CxJX8mk9Sjo757QxcChrkI/C2m9TcGJT6PP
|
||||
Fri4ZF111wek8TmjGAW8GwKBgDhuuvBgcpW3SJe/sqmWerNUCQsVnBlDPCy/0T9k
|
||||
hrcxUSt8NXtrv/n5jLUEKpracqDQaXWcWEIRc6NVBkSlCQ3gfDd/gHPGOXpwakro
|
||||
oMJRT2k6TnssDFFfAkyPoPS012GMhR1Z+Q4DFnMHOmG6eb6HqrdabnMjp3ilyAb+
|
||||
s1RVAoGAQCGfhL3j9ShiTlpbOcL6CdERk4Jzw7mD4g6gVvyKLJWwACl5Y7YgVcfU
|
||||
Bsm9c3GM2OkAAHDlYd8oBvaWArI5eN93zLgD4uU/Bm08SKpQqOOghqrFQy3B9Ngr
|
||||
eEgVYYvmHikJfcUzOYfotRdH4APGt8EAL2007oyox7Yucv5pzNA=
|
||||
-----END RSA PRIVATE KEY-----
|
19
examples/puma/client-certs/unknown_ca.crt
Normal file
19
examples/puma/client-certs/unknown_ca.crt
Normal file
|
@ -0,0 +1,19 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDIDCCAgigAwIBAgIBATANBgkqhkiG9w0BAQUFADBAMRMwEQYKCZImiZPyLGQB
|
||||
GRYDbmV0MRQwEgYKCZImiZPyLGQBGRYEcHVtYTETMBEGA1UEAwwKY2EtdW5rbm93
|
||||
bjAgFw0xNDAyMDIyMDA4MjdaGA8yMTE1MDEwOTIwMDgyN1owQDETMBEGCgmSJomT
|
||||
8ixkARkWA25ldDEUMBIGCgmSJomT8ixkARkWBHB1bWExEzARBgNVBAMMCmNhLXVu
|
||||
a25vd24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDlvCM8F2q9vE7d
|
||||
PMgao53q0U3MIJgNMOw4eZGDfxZrbGM3x5Zws3/7jzngE8BFc/Y+RhC73T/dN6E9
|
||||
ZT2jfwlRRSUxx8Pq2OUMA9Pb8fj8TAoLGwC6txKaqy/UqKqhVGjQ3FUS3cXBzR85
|
||||
PGN9mhIB72+ftcWzw0KSNb+pYG8tg+1p6Nb+UlSrjS9/Z0KM8zKnteMG75qhtKnC
|
||||
rtD6RBiqp98c5r/JJ+LANODaCjtVj5SJTVd/MyshvrNlfYPlMgt+/tU8qSlKzwMa
|
||||
HcN7KA+oT0blOojaUNJMjgqwCI8QeTP1/DEDfvJvTtzPkaz/ctrmbHzQvLS8Lh6f
|
||||
KVv32cg9AgMBAAGjIzAhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
|
||||
MA0GCSqGSIb3DQEBBQUAA4IBAQCpp/LR62GvtZVrscMVKMfHtlotU67g1nP+FESE
|
||||
7nJ5Av4rhaxRFHkF1YdQINyB6mL4fHzDu1g4aLdZmTRjOZcYw6Y2xrJZ/X1lIg29
|
||||
7X4s5AlyHJUstWJnk/FrycPBJqZ75b5SJOayaMiAW+fEsQM2wETISkLitQyVlU3V
|
||||
CtITVjcvgrnsFmnN/qi75EnxxkohZFZGtC2f/NZufYmbpB2FHMt9hhddG7nMawGK
|
||||
dnpbEAiDiQO757Td3vSfAQN6ahopwe2YbrgirrwMQpScoy5pKdbrhMXTLCuwXZmj
|
||||
KR6n2WyS0IzminNy1M4FeB4Pq82VH4rFPwl+t6PWjSHaF87V
|
||||
-----END CERTIFICATE-----
|
27
examples/puma/client-certs/unknown_ca.key
Normal file
27
examples/puma/client-certs/unknown_ca.key
Normal file
|
@ -0,0 +1,27 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA5bwjPBdqvbxO3TzIGqOd6tFNzCCYDTDsOHmRg38Wa2xjN8eW
|
||||
cLN/+4854BPARXP2PkYQu90/3TehPWU9o38JUUUlMcfD6tjlDAPT2/H4/EwKCxsA
|
||||
urcSmqsv1KiqoVRo0NxVEt3Fwc0fOTxjfZoSAe9vn7XFs8NCkjW/qWBvLYPtaejW
|
||||
/lJUq40vf2dCjPMyp7XjBu+aobSpwq7Q+kQYqqffHOa/ySfiwDTg2go7VY+UiU1X
|
||||
fzMrIb6zZX2D5TILfv7VPKkpSs8DGh3DeygPqE9G5TqI2lDSTI4KsAiPEHkz9fwx
|
||||
A37yb07cz5Gs/3La5mx80Ly0vC4enylb99nIPQIDAQABAoIBAQCbxT6K30HkFsvO
|
||||
nQj9bxWDg5nhn/QZdaOmA2AULlbwTdTUnIM4Na3Az3OpqRrEvQUpYm60Qyergq3U
|
||||
qFHsCxYxQdYfc9k24wwjYnEDgIWX5KMmto9/CuUVdJ+A7UCNFWPgwpT4ruEJMGFM
|
||||
eNLo9k/heg1Q2HqOEgaQhttHKHkZ/UJaR6XXeucBfJtXSIWf42omeDRNhlwsQ+LY
|
||||
WbTv3XmiFbu1Bhkk67xlpyuGEL1g9Auz9P2z+2Q2LV66kNhfInIFtUYFeNpkjgUJ
|
||||
TtDRU7UBOm+YPMjDfjVUzPbzvCVAtxG4t0ZSJJcQF3N4+HfpoL1c33CCqYwkh1KI
|
||||
xJi1CgjtAoGBAPR3u8OovMmSJ6tdee0WyTahYmK6VOtmSm4IJf1t/wUvf/u6X/Q6
|
||||
U06TxUAiAs8rMwvvtgPeLYxtaEKO0PSD0rHNL1MHnBwYAmLvAFyCc5tuuyb3ZIyg
|
||||
1oAz/hW5bYgAL32nmDrlwq0W+KU478SRWWYZA2raO3Ha08I1YVbgkSHPAoGBAPCS
|
||||
fIexjEPxeyZJe4+iKQcmWW42HA9rWIpu/9FDZxvn+PpWhBwMzlxjTlQS2V3nMSHp
|
||||
Jtzyj+Y2R1SO8OQoqZ6s7G+cv8Ni+FqOidcUPUH6aDc2A0ihb0FANp4FQsrv7riP
|
||||
W12mWfniTxZri+nKAwpXjEjko8yi05go3y0dTjQzAoGAJq+n6/+Q2Ikjc+/X8pfv
|
||||
gZCqZBs+gv3t+1mYwXEdsTFiHHDS7HAqbL3fshVvwl8AtfvaHuSS6q0JmbbGBFu0
|
||||
BOUGfyouHxgBkKxnrzwJlWhBf5oYtFRjfWg85i0w0xvMaCMUaQWg+AkxkdvfvYiO
|
||||
0CRXMRqV25+YcRxHahshfGsCgYEAus9Vql1B6YS8N4f6ThgDOg0ahw23jnWyJJV7
|
||||
SznG+JGS8np6TfnXyUBIE9srNdMQgR+20P3+piriCxSQlOvKg3AOjcEv2/6fklp7
|
||||
SSvrQa+8e5sSw7SwWwANKXo2WrYkLucLcNZ7qiKFfYh39kyrPb2sLvJ1C7QpEVAz
|
||||
tam7D6cCgYBdqh+SlwryiX351eh+tLOlysAPJ1cb3JotnZY1WYKfR9r5PlJsisut
|
||||
dcjOOaz5/Uo/UlVKOjOxxUuB8FIIJGPvx6lo0hq8ornS0CdqhDspUx4aAD0iZ6+y
|
||||
iccYnG0CLW3HpS4B1B7a8ktXW59m+tT9Fl+usOmwdPNIzcdAMqff+A==
|
||||
-----END RSA PRIVATE KEY-----
|
|
@ -5,6 +5,7 @@
|
|||
#include <openssl/ssl.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
typedef struct {
|
||||
BIO* read;
|
||||
|
@ -13,7 +14,17 @@ typedef struct {
|
|||
SSL_CTX* ctx;
|
||||
} ms_conn;
|
||||
|
||||
typedef struct {
|
||||
unsigned char* buf;
|
||||
int bytes;
|
||||
} ms_cert_buf;
|
||||
|
||||
void engine_free(ms_conn* conn) {
|
||||
ms_cert_buf* cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
|
||||
if(cert_buf) {
|
||||
OPENSSL_free(cert_buf->buf);
|
||||
free(cert_buf);
|
||||
}
|
||||
SSL_free(conn->ssl);
|
||||
SSL_CTX_free(conn->ctx);
|
||||
|
||||
|
@ -73,6 +84,32 @@ DH *get_dh1024() {
|
|||
return dh;
|
||||
}
|
||||
|
||||
static int engine_verify_callback(int preverify_ok, X509_STORE_CTX* ctx) {
|
||||
X509* err_cert;
|
||||
SSL* ssl;
|
||||
int bytes;
|
||||
unsigned char* buf = NULL;
|
||||
|
||||
if(!preverify_ok) {
|
||||
err_cert = X509_STORE_CTX_get_current_cert(ctx);
|
||||
if(err_cert) {
|
||||
/*
|
||||
* Save the failed certificate for inspection/logging.
|
||||
*/
|
||||
bytes = i2d_X509(err_cert, &buf);
|
||||
if(bytes > 0) {
|
||||
ms_cert_buf* cert_buf = (ms_cert_buf*)malloc(sizeof(ms_cert_buf));
|
||||
cert_buf->buf = buf;
|
||||
cert_buf->bytes = bytes;
|
||||
ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
||||
SSL_set_app_data(ssl, cert_buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return preverify_ok;
|
||||
}
|
||||
|
||||
VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
||||
VALUE obj;
|
||||
SSL_CTX* ctx;
|
||||
|
@ -86,11 +123,21 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|||
ID sym_cert = rb_intern("cert");
|
||||
VALUE cert = rb_funcall(mini_ssl_ctx, sym_cert, 0);
|
||||
|
||||
ID sym_ca = rb_intern("ca");
|
||||
VALUE ca = rb_funcall(mini_ssl_ctx, sym_ca, 0);
|
||||
|
||||
ID sym_verify_mode = rb_intern("verify_mode");
|
||||
VALUE verify_mode = rb_funcall(mini_ssl_ctx, sym_verify_mode, 0);
|
||||
|
||||
ctx = SSL_CTX_new(SSLv23_server_method());
|
||||
conn->ctx = ctx;
|
||||
|
||||
SSL_CTX_use_certificate_file(ctx, RSTRING_PTR(cert), SSL_FILETYPE_PEM);
|
||||
SSL_CTX_use_PrivateKey_file(ctx, RSTRING_PTR(key), SSL_FILETYPE_PEM);
|
||||
|
||||
if (!NIL_P(ca)) {
|
||||
SSL_CTX_load_verify_locations(ctx, RSTRING_PTR(ca), NULL);
|
||||
}
|
||||
|
||||
SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE);
|
||||
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
|
||||
|
@ -106,10 +153,15 @@ VALUE engine_init_server(VALUE self, VALUE mini_ssl_ctx) {
|
|||
EC_KEY_free(ecdh);
|
||||
}
|
||||
|
||||
ssl = SSL_new(ctx);
|
||||
ssl = SSL_new(ctx);
|
||||
conn->ssl = ssl;
|
||||
SSL_set_app_data(ssl, NULL);
|
||||
|
||||
/* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
|
||||
if (NIL_P(verify_mode)) {
|
||||
/* SSL_set_verify(ssl, SSL_VERIFY_NONE, NULL); */
|
||||
} else {
|
||||
SSL_set_verify(ssl, NUM2INT(verify_mode), engine_verify_callback);
|
||||
}
|
||||
|
||||
SSL_set_bio(ssl, conn->read, conn->write);
|
||||
|
||||
|
@ -123,6 +175,7 @@ VALUE engine_init_client(VALUE klass) {
|
|||
|
||||
conn->ctx = SSL_CTX_new(DTLSv1_method());
|
||||
conn->ssl = SSL_new(conn->ctx);
|
||||
SSL_set_app_data(conn->ssl, NULL);
|
||||
SSL_set_verify(conn->ssl, SSL_VERIFY_NONE, NULL);
|
||||
|
||||
SSL_set_bio(conn->ssl, conn->read, conn->write);
|
||||
|
@ -151,11 +204,36 @@ VALUE engine_inject(VALUE self, VALUE str) {
|
|||
static VALUE eError;
|
||||
|
||||
void raise_error(SSL* ssl, int result) {
|
||||
int error = SSL_get_error(ssl, result);
|
||||
char* msg = ERR_error_string(error, NULL);
|
||||
char buf[512];
|
||||
char msg[512];
|
||||
const char* err_str;
|
||||
int err = errno;
|
||||
int ssl_err = SSL_get_error(ssl, result);
|
||||
int verify_err = SSL_get_verify_result(ssl);
|
||||
|
||||
if(SSL_ERROR_SYSCALL == ssl_err) {
|
||||
strerror_r(err, buf, sizeof(buf));
|
||||
snprintf(msg, sizeof(msg), "System error: %s - %d", buf, err);
|
||||
|
||||
} else if(SSL_ERROR_SSL == ssl_err) {
|
||||
if(X509_V_OK != verify_err) {
|
||||
err_str = X509_verify_cert_error_string(verify_err);
|
||||
snprintf(msg, sizeof(msg),
|
||||
"OpenSSL certificate verification error: %s - %d",
|
||||
err_str, verify_err);
|
||||
|
||||
} else {
|
||||
err = ERR_get_error();
|
||||
ERR_error_string_n(err, buf, sizeof(buf));
|
||||
snprintf(msg, sizeof(msg), "OpenSSL error: %s - %d", buf, err);
|
||||
|
||||
}
|
||||
} else {
|
||||
snprintf(msg, sizeof(msg), "Unknown OpenSSL error: %d", ssl_err);
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
rb_raise(eError, "OpenSSL error: %s - %d", msg, error);
|
||||
rb_raise(eError, msg);
|
||||
}
|
||||
|
||||
VALUE engine_read(VALUE self) {
|
||||
|
@ -165,6 +243,8 @@ VALUE engine_read(VALUE self) {
|
|||
|
||||
Data_Get_Struct(self, ms_conn, conn);
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
bytes = SSL_read(conn->ssl, (void*)buf, sizeof(buf));
|
||||
|
||||
if(bytes > 0) {
|
||||
|
@ -174,24 +254,26 @@ VALUE engine_read(VALUE self) {
|
|||
if(SSL_want_read(conn->ssl)) return Qnil;
|
||||
|
||||
error = SSL_get_error(conn->ssl, bytes);
|
||||
if(error == SSL_ERROR_ZERO_RETURN || error == SSL_ERROR_SSL) {
|
||||
rb_eof_error();
|
||||
}
|
||||
|
||||
raise_error(conn->ssl, bytes);
|
||||
if(error == SSL_ERROR_ZERO_RETURN) {
|
||||
rb_eof_error();
|
||||
} else {
|
||||
raise_error(conn->ssl, bytes);
|
||||
}
|
||||
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE engine_write(VALUE self, VALUE str) {
|
||||
ms_conn* conn;
|
||||
char buf[512];
|
||||
int bytes;
|
||||
|
||||
Data_Get_Struct(self, ms_conn, conn);
|
||||
|
||||
StringValue(str);
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
bytes = SSL_write(conn->ssl, (void*)RSTRING_PTR(str), (int)RSTRING_LEN(str));
|
||||
if(bytes > 0) {
|
||||
return INT2FIX(bytes);
|
||||
|
@ -225,6 +307,45 @@ VALUE engine_extract(VALUE self) {
|
|||
return Qnil;
|
||||
}
|
||||
|
||||
VALUE engine_peercert(VALUE self) {
|
||||
ms_conn* conn;
|
||||
X509* cert;
|
||||
int bytes;
|
||||
unsigned char* buf = NULL;
|
||||
ms_cert_buf* cert_buf = NULL;
|
||||
VALUE rb_cert_buf;
|
||||
|
||||
Data_Get_Struct(self, ms_conn, conn);
|
||||
|
||||
cert = SSL_get_peer_certificate(conn->ssl);
|
||||
if(!cert) {
|
||||
/*
|
||||
* See if there was a failed certificate associated with this client.
|
||||
*/
|
||||
cert_buf = (ms_cert_buf*)SSL_get_app_data(conn->ssl);
|
||||
if(!cert_buf) {
|
||||
return Qnil;
|
||||
}
|
||||
buf = cert_buf->buf;
|
||||
bytes = cert_buf->bytes;
|
||||
|
||||
} else {
|
||||
bytes = i2d_X509(cert, &buf);
|
||||
X509_free(cert);
|
||||
|
||||
if(bytes < 0) {
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
|
||||
rb_cert_buf = rb_str_new(buf, bytes);
|
||||
if(!cert_buf) {
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
|
||||
return rb_cert_buf;
|
||||
}
|
||||
|
||||
void Init_mini_ssl(VALUE puma) {
|
||||
VALUE mod, eng;
|
||||
|
||||
|
@ -246,4 +367,6 @@ void Init_mini_ssl(VALUE puma) {
|
|||
|
||||
rb_define_method(eng, "write", engine_write, 1);
|
||||
rb_define_method(eng, "extract", engine_extract, 0);
|
||||
|
||||
rb_define_method(eng, "peercert", engine_peercert, 0);
|
||||
}
|
||||
|
|
|
@ -155,9 +155,28 @@ module Puma
|
|||
end
|
||||
|
||||
ctx.cert = params['cert']
|
||||
end
|
||||
|
||||
ctx.verify_mode = MiniSSL::VERIFY_NONE
|
||||
if ['peer', 'force_peer'].include?(params['verify_mode'])
|
||||
unless params['ca']
|
||||
@events.error "Please specify the SSL ca via 'ca='"
|
||||
end
|
||||
ctx.ca = params['ca']
|
||||
end
|
||||
|
||||
if params['verify_mode']
|
||||
ctx.verify_mode = case params['verify_mode']
|
||||
when "peer"
|
||||
MiniSSL::VERIFY_PEER
|
||||
when "force_peer"
|
||||
MiniSSL::VERIFY_PEER | MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
||||
when "none"
|
||||
MiniSSL::VERIFY_NONE
|
||||
else
|
||||
@events.error "Please specify a valid verify_mode="
|
||||
MiniSSL::VERIFY_NONE
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if fd = @inherited_fds.delete(str)
|
||||
logger.log "* Inherited #{str}"
|
||||
|
|
|
@ -129,6 +129,7 @@ module Puma
|
|||
RACK_AFTER_REPLY = "rack.after_reply".freeze
|
||||
PUMA_SOCKET = "puma.socket".freeze
|
||||
PUMA_CONFIG = "puma.config".freeze
|
||||
PUMA_PEERCERT = "puma.peercert".freeze
|
||||
|
||||
HTTP = "http".freeze
|
||||
HTTPS = "https".freeze
|
||||
|
|
|
@ -96,6 +96,15 @@ module Puma
|
|||
@stderr.puts "#{Time.now}: ENV: #{env.inspect}\n---\n"
|
||||
end
|
||||
|
||||
# An SSL error has occured.
|
||||
# +server+ is the Server object, +peeraddr+ peer address, +peercert+
|
||||
# any peer certificate (if present), and +error+ an exception object.
|
||||
#
|
||||
def ssl_error(server, peeraddr, peercert, error)
|
||||
subject = peercert ? peercert.subject : nil
|
||||
@stderr.puts "#{Time.now}: SSL error, peer: #{peeraddr}, peer cert: #{subject}, #{error.inspect}"
|
||||
end
|
||||
|
||||
# An unknown error has occured.
|
||||
# +server+ is the Server object, +env+ the request, +error+ an exception
|
||||
# object, and +kind+ some additional info.
|
||||
|
|
|
@ -4,6 +4,7 @@ module Puma
|
|||
def initialize(socket, engine)
|
||||
@socket = socket
|
||||
@engine = engine
|
||||
@peercert = nil
|
||||
end
|
||||
|
||||
def to_io
|
||||
|
@ -86,6 +87,21 @@ module Puma
|
|||
def peeraddr
|
||||
@socket.peeraddr
|
||||
end
|
||||
|
||||
def peercert
|
||||
return @peercert if @peercert
|
||||
|
||||
raw = @engine.peercert
|
||||
return nil unless raw
|
||||
|
||||
@peercert = OpenSSL::X509::Certificate.new raw
|
||||
end
|
||||
end
|
||||
|
||||
if defined?(JRUBY_VERSION)
|
||||
class SSLError < StandardError
|
||||
# Define this for jruby even though it isn't used.
|
||||
end
|
||||
end
|
||||
|
||||
class Context
|
||||
|
@ -104,6 +120,7 @@ module Puma
|
|||
# non-jruby Context properties
|
||||
attr_reader :key
|
||||
attr_reader :cert
|
||||
attr_reader :ca
|
||||
|
||||
def key=(key)
|
||||
raise ArgumentError, "No such key file '#{key}'" unless File.exist? key
|
||||
|
@ -114,11 +131,17 @@ module Puma
|
|||
raise ArgumentError, "No such cert file '#{cert}'" unless File.exist? cert
|
||||
@cert = cert
|
||||
end
|
||||
|
||||
def ca=(ca)
|
||||
raise ArgumentError, "No such ca file '#{ca}'" unless File.exist? ca
|
||||
@ca = ca
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
VERIFY_NONE = 0
|
||||
VERIFY_PEER = 1
|
||||
VERIFY_FAIL_IF_NO_PEER_CERT = 2
|
||||
|
||||
class Server
|
||||
def initialize(socket, ctx)
|
||||
|
|
|
@ -74,6 +74,17 @@ module Puma
|
|||
sockets.delete c
|
||||
end
|
||||
|
||||
# SSL handshake failure
|
||||
rescue MiniSSL::SSLError => e
|
||||
ssl_socket = c.io
|
||||
addr = ssl_socket.peeraddr.last
|
||||
cert = ssl_socket.peercert
|
||||
|
||||
c.close
|
||||
sockets.delete c
|
||||
|
||||
@events.ssl_error @server, addr, cert, e
|
||||
|
||||
# The client doesn't know HTTP well
|
||||
rescue HttpParserError => e
|
||||
c.write_400
|
||||
|
|
|
@ -250,6 +250,14 @@ module Puma
|
|||
client.finish
|
||||
process_now = true
|
||||
end
|
||||
rescue MiniSSL::SSLError => e
|
||||
ssl_socket = client.io
|
||||
addr = ssl_socket.peeraddr.last
|
||||
cert = ssl_socket.peercert
|
||||
|
||||
client.close
|
||||
|
||||
@events.ssl_error self, addr, cert, e
|
||||
rescue HttpParserError => e
|
||||
client.write_400
|
||||
client.close
|
||||
|
@ -395,6 +403,16 @@ module Puma
|
|||
rescue ConnectionError
|
||||
# Swallow them. The ensure tries to close +client+ down
|
||||
|
||||
# SSL handshake error
|
||||
rescue MiniSSL::SSLError => e
|
||||
ssl_socket = client.io
|
||||
addr = ssl_socket.peeraddr.last
|
||||
cert = ssl_socket.peercert
|
||||
|
||||
close_socket = true
|
||||
|
||||
@events.ssl_error self, addr, cert, e
|
||||
|
||||
# The client doesn't know HTTP well
|
||||
rescue HttpParserError => e
|
||||
client.write_400
|
||||
|
@ -467,6 +485,7 @@ module Puma
|
|||
end
|
||||
|
||||
def default_server_port(env)
|
||||
return PORT_443 if env[HTTPS_KEY] == 'on' || env[HTTPS_KEY] == 'https'
|
||||
env['HTTP_X_FORWARDED_PROTO'] == 'https' ? PORT_443 : PORT_80
|
||||
end
|
||||
|
||||
|
@ -487,6 +506,10 @@ module Puma
|
|||
|
||||
env[PUMA_SOCKET] = client
|
||||
|
||||
if env[HTTPS_KEY] && client.peercert
|
||||
env[PUMA_PEERCERT] = client.peercert
|
||||
end
|
||||
|
||||
env[HIJACK_P] = true
|
||||
env[HIJACK] = req
|
||||
|
||||
|
|
|
@ -8,6 +8,16 @@ require 'puma/server'
|
|||
|
||||
require 'net/https'
|
||||
|
||||
class SSLEventsHelper < ::Puma::Events
|
||||
attr_accessor :addr, :cert, :error
|
||||
|
||||
def ssl_error(server, peeraddr, peercert, error)
|
||||
self.addr = peeraddr
|
||||
self.cert = peercert
|
||||
self.error = error
|
||||
end
|
||||
end
|
||||
|
||||
class TestPumaServerSSL < Test::Unit::TestCase
|
||||
|
||||
def setup
|
||||
|
@ -28,7 +38,7 @@ class TestPumaServerSSL < Test::Unit::TestCase
|
|||
|
||||
@ctx.verify_mode = Puma::MiniSSL::VERIFY_NONE
|
||||
|
||||
@events = Puma::Events.new STDOUT, STDERR
|
||||
@events = SSLEventsHelper.new STDOUT, STDERR
|
||||
@server = Puma::Server.new @app, @events
|
||||
@server.add_ssl_listener @host, @port, @ctx
|
||||
@server.run
|
||||
|
@ -95,6 +105,94 @@ class TestPumaServerSSL < Test::Unit::TestCase
|
|||
Net::HTTP::Get.new '/'
|
||||
end
|
||||
end
|
||||
unless defined?(JRUBY_VERSION)
|
||||
assert_match("wrong version number", @events.error.message) if @events.error
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
# client-side TLS authentication tests
|
||||
unless defined?(JRUBY_VERSION)
|
||||
class TestPumaServerSSLClient < Test::Unit::TestCase
|
||||
|
||||
def assert_ssl_client_error_match(error, subject=nil, &blk)
|
||||
@port = 3212
|
||||
@host = "127.0.0.1"
|
||||
|
||||
@app = lambda { |env| [200, {}, [env['rack.url_scheme']]] }
|
||||
|
||||
@ctx = Puma::MiniSSL::Context.new
|
||||
@ctx.key = File.expand_path "../../examples/puma/client-certs/server.key", __FILE__
|
||||
@ctx.cert = File.expand_path "../../examples/puma/client-certs/server.crt", __FILE__
|
||||
@ctx.ca = File.expand_path "../../examples/puma/client-certs/ca.crt", __FILE__
|
||||
@ctx.verify_mode = Puma::MiniSSL::VERIFY_PEER | Puma::MiniSSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
||||
|
||||
events = SSLEventsHelper.new STDOUT, STDERR
|
||||
@server = Puma::Server.new @app, events
|
||||
@server.add_ssl_listener @host, @port, @ctx
|
||||
@server.run
|
||||
|
||||
@http = Net::HTTP.new @host, @port
|
||||
@http.use_ssl = true
|
||||
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
||||
|
||||
blk.call(@http)
|
||||
|
||||
client_error = false
|
||||
begin
|
||||
@http.start do
|
||||
req = Net::HTTP::Get.new "/", {}
|
||||
@http.request(req)
|
||||
end
|
||||
rescue OpenSSL::SSL::SSLError
|
||||
client_error = true
|
||||
end
|
||||
|
||||
sleep 0.1
|
||||
assert_equal !!error, client_error
|
||||
assert_match error, events.error.message if error
|
||||
assert_equal @host, events.addr if error
|
||||
assert_equal subject, events.cert.subject.to_s if subject
|
||||
ensure
|
||||
@server.stop(true)
|
||||
end
|
||||
|
||||
def test_verify_fail_if_no_client_cert
|
||||
assert_ssl_client_error_match 'peer did not return a certificate' do |http|
|
||||
# nothing
|
||||
end
|
||||
end
|
||||
|
||||
def test_verify_fail_if_client_unknown_ca
|
||||
assert_ssl_client_error_match('self signed certificate in certificate chain', '/DC=net/DC=puma/CN=ca-unknown') do |http|
|
||||
key = File.expand_path "../../examples/puma/client-certs/client_unknown.key", __FILE__
|
||||
crt = File.expand_path "../../examples/puma/client-certs/client_unknown.crt", __FILE__
|
||||
http.key = OpenSSL::PKey::RSA.new File.read(key)
|
||||
http.cert = OpenSSL::X509::Certificate.new File.read(crt)
|
||||
http.ca_file = File.expand_path "../../examples/puma/client-certs/unknown_ca.crt", __FILE__
|
||||
end
|
||||
end
|
||||
|
||||
def test_verify_fail_if_client_expired_cert
|
||||
assert_ssl_client_error_match('certificate has expired', '/DC=net/DC=puma/CN=client-expired') do |http|
|
||||
key = File.expand_path "../../examples/puma/client-certs/client_expired.key", __FILE__
|
||||
crt = File.expand_path "../../examples/puma/client-certs/client_expired.crt", __FILE__
|
||||
http.key = OpenSSL::PKey::RSA.new File.read(key)
|
||||
http.cert = OpenSSL::X509::Certificate.new File.read(crt)
|
||||
http.ca_file = File.expand_path "../../examples/puma/client-certs/ca.crt", __FILE__
|
||||
end
|
||||
end
|
||||
|
||||
def test_verify_client_cert
|
||||
assert_ssl_client_error_match(nil) do |http|
|
||||
key = File.expand_path "../../examples/puma/client-certs/client.key", __FILE__
|
||||
crt = File.expand_path "../../examples/puma/client-certs/client.crt", __FILE__
|
||||
http.key = OpenSSL::PKey::RSA.new File.read(key)
|
||||
http.cert = OpenSSL::X509::Certificate.new File.read(crt)
|
||||
http.ca_file = File.expand_path "../../examples/puma/client-certs/ca.crt", __FILE__
|
||||
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Reference in a new issue