Fixes #3727 - Adding private keys allows adding certificates.

This commit is contained in:
Rolf Schmidt 2021-10-20 13:04:31 +02:00
parent cb48cd2dcd
commit 274e5a849f
4 changed files with 164 additions and 42 deletions

View file

@ -42,9 +42,7 @@ class Integration::SMIMEController < ApplicationController
string = params[:file].read.force_encoding('utf-8') string = params[:file].read.force_encoding('utf-8')
end end
items = string.scan(%r{.+?-+END(?: TRUSTED)? CERTIFICATE-+}mi).each_with_object([]) do |cert, result| items = SMIMECertificate.create_certificates(string)
result << SMIMECertificate.create!(public_key: cert)
end
render json: { render json: {
result: 'ok', result: 'ok',
@ -73,14 +71,8 @@ class Integration::SMIMEController < ApplicationController
raise "Parameter 'data' or 'file' required." if string.blank? raise "Parameter 'data' or 'file' required." if string.blank?
private_key = OpenSSL::PKey.read(string, params[:secret]) SMIMECertificate.create_certificates(string)
modulus = private_key.public_key.n.to_s(16) SMIMECertificate.create_private_keys(string, params[:secret])
certificate = SMIMECertificate.find_by(modulus: modulus)
raise Exceptions::UnprocessableEntity, 'Unable for find certificate for this private key.' if !certificate
certificate.update!(private_key: string, private_key_secret: params[:secret])
render json: { render json: {
result: 'ok', result: 'ok',

View file

@ -3,6 +3,28 @@
class SMIMECertificate < ApplicationModel class SMIMECertificate < ApplicationModel
validates :fingerprint, uniqueness: { case_sensitive: true } validates :fingerprint, uniqueness: { case_sensitive: true }
def self.parts(raw)
raw.scan(%r{-----BEGIN[^-]+-----.+?-----END[^-]+-----}m)
end
def self.create_private_keys(raw, secret)
parts(raw).select { |part| part.include?('PRIVATE KEY') }.each do |part|
private_key = OpenSSL::PKey.read(part, secret)
modulus = private_key.public_key.n.to_s(16)
certificate = find_by(modulus: modulus)
raise Exceptions::UnprocessableEntity, 'Unable for find certificate for this private key.' if !certificate
certificate.update!(private_key: part, private_key_secret: secret)
end
end
def self.create_certificates(raw)
parts(raw).select { |part| part.include?('CERTIFICATE') }.each_with_object([]) do |part, result|
result << create!(public_key: part)
end
end
def self.parse(raw) def self.parse(raw)
OpenSSL::X509::Certificate.new(raw.gsub(%r{(?:TRUSTED\s)?(CERTIFICATE---)}, '\1')) OpenSSL::X509::Certificate.new(raw.gsub(%r{(?:TRUSTED\s)?(CERTIFICATE---)}, '\1'))
end end

87
spec/fixtures/smime/issue_3727.key vendored Normal file
View file

@ -0,0 +1,87 @@
-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEA5Uos3YnMM4DLyO57KSshsUFC71+OqGdmVdWRln5P5R8IFR1D
9clNsz4o/SfJQVsI2WjnHtJs/2y3GMilTm56tOChBiwY0EiB7icy5t+BTqXigZJf
3PtK2zpHe6wU6w3mO2h1DLCP+dwuiCSYLkq+Gvdb+Q3xs6O3rDw+uX868MTwMde6
Id6q5bq8po8PCdqrSLNBXBas5k8ixsMzKTDwv4DzPdh4xmml+4qfOC1GgC+27iSc
RJGNYpfXqJzoMdpXF379YAEEbHaLWr5GXQ7uHUlNiaE0fFv8pcm5OONQDn88KzKx
/24X31zyIcnAacwHyVQ1ueqP9VDK5zHV3vVVHWKqhoQC/YRy8CnjHim9NbL0pFyk
BrYbVa49bsZ39pRmljTSRxv8osoOn5NPqOnuR7EjTyOdltJvXs8R4IB3TTqNchf7
2MemJRPgyn0Dj1NOHaJ+9K1w73vy3CNhTb3VijHTT0zgJuAuaxgjD7EHL0VFnVIl
yX2kaXquhBIi1naZPA1a1acXlxYrbAWqf97BF5B95Pi0afIHdOqeFS3RD3Fpj4jK
i2HdAEzYBA7r56qpsSJNxW0eBxqUlTu4g+B37fRijyZXAW74a2yS1B530OTEzzvv
GblaaM1pb4LoeT0dvqnoq7/0J2C+ZkeWXgTH3oobcc73CdROhszSJUHmT+kCAwEA
AQKCAgA+C3JUiGMvVJzQRGgjXb6CPoykRZFO1JwGggIhXRC1iU4gmIi5S72w0RM6
XbfB7aZZXl+cIYjJHVv2YuUIcjDWHSq1ht04D0bJcOX/P1+4Ln86XKeAHqfE5uJM
/uWyLVKtpLh3tJdhH0mgIXbkn+kNVv4WSMWsvJKJEsxOWbVTTZdJhXyiiaRpAbzm
vTNukTNkOs1m4+PpdmSMsGl5rfqXd4dapucXmaMGjB5Fj0rSiRbRHisDCvfdRAVh
ZQQX6WNDwmNBxUSzLOjMp0xXBiE834cRxQN021dkbU+nqysQoTFg5xjva5UeJgKH
Tha5CjLZMeZP5r8JvNEK+ptK98wN4nLDqTlvgFr/L7RSrlj6KUWnM8e+cOMo/2T9
VQ/7XQhZ0lxvVr9xEW5pkKqlq4Tyd4YwniU/rNNJV7cyqacpDSN4go/kYFsLCb5F
wY8CIBg/jLM4a7i7nt7UXcNVh3iRvhq8CduG4paQeJbxTSmzge4VAFwKO0TXotvN
V2Um+ibFc7S/9Tzy1BeTfUUE9nAWP9sXomBBXwG59Au9graorzuAUv+y2XfzTqK+
QNtrHzL0VCODXAjOoSTr2Fhic+VR4lpxpZAzHxaOVKMHNW9+Z/QEFdgEjC4dvWXc
7geWNcrzjspz918j1CKihaVFX1tamDPSb1gk1+kgsDrwy3lI+QKCAQEA9KAxZ35/
+bJbYXFzQFlaFyBjny5VGzchfhydj66S01NofmQLdyGHcWwqVf1DdL8dWmJC0eaP
pkIzLj/F6uvowASUk80MNARkVLMRr0M2y1p+MkLHy2eabaHF8S8AuaHV1bZtchCw
L00uPM5XECFqzctJv2Rcx+TAgDz0DfLDH/+Z4qhxYP93a/4aQnEMCrLPB8lJtGu9
dzilzm7UKHddTSudX5N9XHQmwLe6lsaXaJ8F5wocRyw6/Ay3yesluNRAZ2BYGDfc
8Vh3tV9bfw8e1v8xgT3KyHSBo5kKxlHmQATBDTV490sLmK8U37my4UYeZYST4ag3
4CnX1E5A0RhVxwKCAQEA7/NvpOOGCHqL6NDK1VvEP5axX9iS9rUPHAi6bxhf9RrR
K6S+9iVHgaOZMoVguHHqYfJUO3UPZlZ7h2gGppwgp/he2743mSeURiHOK7c6JIsH
KJhCCCiUjJeonykLHvbMQV8Nf9Ci+j/N3A+pwiR+ogLJY8vPSS2Hx+X/LoF1MUX/
54LJwYFM1T8yVrDNXY29QrtBFMN+usyZ2KFyEPukfLNI0yZl+XlpHWedWHqZWcXK
DNAgOBoe5LVaAUnKatrEZH9t0tKYax+DTaDz3eA5YW8s7pKOFEjRBrZnoBW/dYfz
oF3QzEDlOb9dS+rx6+tj/ifn9RDcLFsRZs7ieK9szwKCAQEAwraDvJI3QURTckOA
bjbw+7l/MmQJwAjo8t3KGGTnX6hjYz801RVuHrzvEdTujY3VymyuLS8tJjRJUsXW
PsCaWcULkn3C+eCJD9Yc/HkuszyLeGwpZeFITX1X9jrog9mqQFrd0M4xvuTbKfE/
4YoH3liykdJL+5w8EZby1+tknyKvlXdoD8Ioh2AR/NLIt/dNzS/OJ/seKzh+2crj
unYQYO2XbU0TmrSlZ/6WWY8nU1JIu3cTvR8asCdbXzB5rR3dSaupU1Wb2ssFNev6
Ay/A53bnK61IrLf3vIWDywnDkS93jpECgSxNxbGOlunT1XYfmcSmhRaFqzsDHW1Q
MF8DXwKCAQB+S/TEpllDFzWTCmromE+YZLnhx/26yxwz1khC92JygXX9cc5tgru7
eZ/GHrwE+Tiz6zf4v6mmZPjKEbAGfAEYSDutj9Z1z4ZUz7BUBDIfT+oprNJ8ttdR
lPXVKGZJGv/xnJVfZDKUY4b4QGpK3Kimn67ez0TAsK1aQy3ojY1grQaAFbAaIPOO
/p+BT7gYeOVYPXWI90k6Cz0i7/84/yrZ1AgN05UzFXuFVadVDdqvjNLHobiDrwP5
v5arPOrFCXb7qrLkl6JQKBsVfhU+AKpTJZBR1mPgO1+CF/o9IZVPyIosK5UeHT5K
AfaaYgSJ97D+8oQ90m0BD8H+CgDcIwGzAoIBAC4KznWcLMOs7IIWu0OIfK1VWHdc
dcKwJOs+jGM4SaGWDTBUdVU2NE43fyphwJjBmj+efogeRW1JRBJJ3FNE8YULDmxO
UJEYyYvmuzsWNoF6e0uqLmn+aO6m1kbVnkF/YA5MR3ovKy6YAIVXIhGKPv8SHfea
nyLMORaVy0R8o3fyq6FMKoEf1p+2Gx3mMeKOIghhB/7clHWGZO8igKab+juGZPiK
3vd9Mg00GugWQZpIoyOIQvbdtNARVOVRCWDdtrdyb5UsfZx7fJBWnDiGhXjsGDYU
7bg30nj69KxQTuWR64tY4bBrTIifLWUP4YRm//lljcyjwzZUNP63ujD2eHI=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----

View file

@ -23,6 +23,7 @@ RSpec.describe 'Manage > Integration > S/MIME', type: :system do
click 'label[for=setting-switch]' click 'label[for=setting-switch]'
end end
context 'when doing basic tests' do
it 'enabling and adding of public and private key' do it 'enabling and adding of public and private key' do
# add cert # add cert
@ -36,9 +37,6 @@ RSpec.describe 'Manage > Integration > S/MIME', type: :system do
fill_in 'Enter Private Key secret', with: private_key_secret fill_in 'Enter Private Key secret', with: private_key_secret
click '.js-submit' click '.js-submit'
# wait for ajax
expect(page).to have_css('td', text: 'Including private key')
# check result # check result
expect(Setting.get('smime_integration')).to be true expect(Setting.get('smime_integration')).to be true
expect(SMIMECertificate.last.fingerprint).to be_present expect(SMIMECertificate.last.fingerprint).to be_present
@ -64,3 +62,26 @@ RSpec.describe 'Manage > Integration > S/MIME', type: :system do
expect(page).to have_text('RootCA') expect(page).to have_text('RootCA')
end end
end end
context 'Adding private keys allows adding certificates #3727' do
let!(:private_key) do
File.read(Rails.root.join('spec/fixtures/smime/issue_3727.key'))
end
it 'does add public and private key in one file' do
# add private key
click '.js-addPrivateKey'
fill_in 'Paste Private Key', with: private_key
click '.js-submit'
# check result
expect(Setting.get('smime_integration')).to be true
expect(SMIMECertificate.last.fingerprint).to eq('db49277070afcfc657bd71d04be4dd7e28f1685a')
expect(SMIMECertificate.last.raw).to include('CERTIFICATE')
expect(SMIMECertificate.last.raw).not_to include('PRIVATE')
expect(SMIMECertificate.last.private_key).to include('PRIVATE')
expect(SMIMECertificate.last.private_key).not_to include('CERTIFICATE')
end
end
end