handler.rb 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. module SecureMailing::PGP::Tool::Error::Handler
  3. extend ActiveSupport::Concern
  4. PGP_CALL_RESULT = Struct.new(:stdout, :stderr, :status)
  5. included do # rubocop:disable Metrics/BlockLength
  6. private
  7. def log(cmd, env, stdin, result)
  8. log_level = result[:status].success? ? :debug : :error
  9. Rails.logger.send(log_level) { "PGP: Version: #{SecureMailing::PGP::Tool.version}" }
  10. Rails.logger.send(log_level) { "PGP: Exec: #{cmd.join(' ')}" }
  11. Rails.logger.send(log_level) { "PGP: Env: #{env}" }
  12. Rails.logger.send(log_level) { "PGP: Stderr: #{result[:stderr]}" }
  13. Rails.logger.send(log_level) { "PGP: Status: #{result[:status]}" }
  14. return if !Rails.logger.debug?
  15. Rails.logger.debug { "PGP: Stdin: #{stdin}" } if stdin
  16. Rails.logger.debug { "PGP: Stdout: #{result[:stdout]}" }
  17. end
  18. def error!(stderr)
  19. stderr.each_line do |line|
  20. next if !line.start_with?('[GNUPG:]')
  21. next if !(exception = SecureMailing::PGP::Tool::Error.exception(line.split.second))
  22. raise exception, nil, [sanitize_stderr(stderr)]
  23. end
  24. raise SecureMailing::PGP::Tool::Error::UnknownError, nil, [sanitize_stderr(stderr)]
  25. end
  26. def error_export!(stderr, secret)
  27. exception = secret ? 'NoSecretKey' : 'NoPublicKey'
  28. raise "SecureMailing::PGP::Tool::Error::#{exception}".constantize, nil, [stderr]
  29. end
  30. def error_passphrase!(stderr)
  31. ['no passphrase', 'bad passphrase'].each do |phrase|
  32. next if stderr.downcase.exclude?(phrase)
  33. exception = "SecureMailing::PGP::Tool::Error::#{phrase.tr(' ', '_').camelize}".constantize
  34. raise exception, nil, [stderr]
  35. end
  36. end
  37. def error_algorithm!(stderr)
  38. raise SecureMailing::PGP::Tool::Error::UnknownError, __('This PGP email was encrypted with a potentially unknown encryption algorithm.'), [stderr] if stderr.downcase.exclude?('encrypted data')
  39. end
  40. def result!(cmd, env, stdin, result)
  41. log(cmd, env, stdin, result)
  42. error_passphrase!(sanitize_stderr(result[:stderr])) if result[:stderr].present?
  43. return PGP_CALL_RESULT.new(result[:stdout], sanitize_stderr(result[:stderr]), result[:status]) if result[:status].success?
  44. error!(result[:stderr])
  45. end
  46. def sanitize_stderr(string)
  47. string.split("\n").reject { |chunk| chunk.start_with?('[GNUPG:]') }.join("\n")
  48. end
  49. end
  50. end