mirror of
https://github.com/zammad/zammad
synced 2026-05-24 09:48:36 +00:00
94 lines
2.2 KiB
Ruby
94 lines
2.2 KiB
Ruby
# Copyright (C) 2012-2026 Zammad Foundation, https://zammad-foundation.org/
|
|
|
|
class Setting::Validation::Saml::Security < Setting::Validation::Base
|
|
|
|
def run
|
|
return result_success if value.blank? || disabled_security?
|
|
|
|
%w[check_security_prerequisites check_private_key].each do |method|
|
|
msg = send(method)
|
|
next if msg.nil?
|
|
|
|
return result_failed(msg)
|
|
end
|
|
|
|
cert = read_certificate
|
|
return result_failed(__('The certificate could not be parsed.')) if cert.nil?
|
|
|
|
msg = check_certificate(cert)
|
|
|
|
{
|
|
success: msg.nil?,
|
|
message: msg,
|
|
}
|
|
end
|
|
|
|
private
|
|
|
|
def disabled_security?
|
|
value.fetch('security', 'off').eql?('off')
|
|
end
|
|
|
|
def check_security_prerequisites
|
|
return __('No certificate found.') if certificate_pem.blank?
|
|
return __('No private key found.') if private_key_pem.blank?
|
|
|
|
nil
|
|
end
|
|
|
|
def check_private_key
|
|
begin
|
|
private_key = OpenSSL::PKey.read(private_key_pem, private_key_secret)
|
|
|
|
return __('The type of the private key is wrong.') if !private_key.class.name.end_with?('RSA')
|
|
return __('The length of the private key is too short.') if private_key.n.num_bits < 2048
|
|
rescue => e
|
|
return e.message
|
|
end
|
|
|
|
nil
|
|
end
|
|
|
|
def read_certificate
|
|
begin
|
|
cert = Certificate::X509.new(certificate_pem)
|
|
rescue
|
|
return nil
|
|
end
|
|
|
|
cert
|
|
end
|
|
|
|
def check_certificate(cert)
|
|
return __('The certificate is not usable due to being a CA certificate.') if cert.ca?
|
|
return __('The certificate is not usable (e.g. expired).') if !cert.usable?
|
|
return __('The certificate is not usable for signing and encryption.') if !cert.signature? || !cert.encryption?
|
|
|
|
msg = check_cert_key_match(cert)
|
|
return msg if !msg.nil?
|
|
|
|
nil
|
|
end
|
|
|
|
def check_cert_key_match(cert)
|
|
begin
|
|
return __('The certificate does not match the given private key.') if !cert.key_match?(private_key_pem, private_key_secret)
|
|
rescue => e
|
|
return e.message
|
|
end
|
|
|
|
nil
|
|
end
|
|
|
|
def certificate_pem
|
|
@certificate_pem ||= value.fetch('certificate', '')
|
|
end
|
|
|
|
def private_key_pem
|
|
@private_key_pem ||= value.fetch('private_key', '')
|
|
end
|
|
|
|
def private_key_secret
|
|
@private_key_secret ||= value.fetch('private_key_secret', '')
|
|
end
|
|
end
|