smime.rb 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. class Certificate::X509::SMIME < Certificate::X509
  3. include Certificate::X509::SMIME::Attributes
  4. attr_reader :email_addresses, :fingerprint, :issuer_hash, :uid, :subject_hash
  5. def self.parse(pem)
  6. begin
  7. new(pem)
  8. rescue OpenSSL::X509::CertificateError
  9. raise Exceptions::UnprocessableEntity, __('The certificate is not valid for S/MIME usage. Please check the certificate format.')
  10. end
  11. end
  12. def initialize(pem)
  13. super(pem)
  14. @email_addresses = fetch_email_addresses
  15. @subject_hash = subject.hash.to_s(16)
  16. @issuer_hash = issuer.hash.to_s(16)
  17. @uid = determine_uid
  18. end
  19. def rsa?
  20. public_key.class.name.end_with?('RSA')
  21. end
  22. def ec?
  23. public_key.class.name.end_with?('EC')
  24. end
  25. def applicable?
  26. return false if ca?
  27. # This is necessary because some legacy certificates may not have an extended key usage.
  28. extensions_as_hash.fetch('extendedKeyUsage', ['E-mail Protection']).include?('E-mail Protection')
  29. end
  30. def signature?
  31. return false if ca? || !applicable?
  32. # This is necessary because some legacy certificates may not have a key usage.
  33. extensions_as_hash.fetch('keyUsage', ['Digital Signature']).include?('Digital Signature')
  34. end
  35. def encryption?
  36. return false if ca? || !applicable?
  37. # This is necessary because some legacy certificates may not have a key usage.
  38. extensions_as_hash.fetch('keyUsage', ['Key Encipherment']).include?('Key Encipherment')
  39. end
  40. def valid_smime_certificate?
  41. return true if ca?
  42. return false if !applicable?
  43. return false if !signature? && !encryption?
  44. return false if @email_addresses.blank?
  45. return false if !rsa? && !ec?
  46. true
  47. end
  48. def valid_smime_certificate!
  49. return if valid_smime_certificate?
  50. message = __('The certificate is not valid for S/MIME usage. Please check the key usage, subject alternative name and public key cryptographic algorithm.')
  51. Rails.logger.error { "Certificate::X509::SMIME: #{message}" }
  52. Rails.logger.error { "Certificate::X509::SMIME:\n #{to_text}" }
  53. raise Exceptions::UnprocessableEntity, message
  54. end
  55. end