trabajo-afectivo/app/controllers/integration/smime_controller.rb

179 lines
4.3 KiB
Ruby

# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
class Integration::SMIMEController < ApplicationController
prepend_before_action { authentication_check && authorize! }
def certificate_download
cert = SMIMECertificate.find(params[:id])
send_data(
cert.raw,
filename: "#{cert.doc_hash}.crt",
type: 'text/plain',
disposition: 'attachment'
)
end
def private_key_download
cert = SMIMECertificate.find(params[:id])
send_data(
cert.private_key,
filename: "#{cert.doc_hash}.key",
type: 'text/plain',
disposition: 'attachment'
)
end
def certificate_list
render json: SMIMECertificate.all
end
def certificate_delete
SMIMECertificate.find(params[:id]).destroy!
render json: {
result: 'ok',
}
end
def certificate_add
string = params[:data]
if string.blank? && params[:file].present?
string = params[:file].read.force_encoding('utf-8')
end
items = string.scan(%r{.+?-+END(?: TRUSTED)? CERTIFICATE-+}mi).each_with_object([]) do |cert, result|
result << SMIMECertificate.create!(public_key: cert)
end
render json: {
result: 'ok',
response: items,
}
rescue => e
unprocessable_entity(e)
end
def private_key_delete
SMIMECertificate.find(params[:id]).update!(
private_key: nil,
private_key_secret: nil,
)
render json: {
result: 'ok',
}
end
def private_key_add
string = params[:data]
if string.blank? && params[:file].present?
string = params[:file].read.force_encoding('utf-8')
end
raise "Parameter 'data' or 'file' required." if string.blank?
private_key = OpenSSL::PKey.read(string, params[:secret])
modulus = private_key.public_key.n.to_s(16)
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: {
result: 'ok',
}
rescue => e
unprocessable_entity(e)
end
def search
result = {
type: 'S/MIME',
}
result[:encryption] = article_encryption(params[:article])
result[:sign] = article_sign(params[:ticket])
render json: result
end
def article_encryption(article)
result = {
success: false,
comment: 'no recipient found',
}
return result if article.blank?
return result if article[:to].blank? && article[:cc].blank?
recipient = [ article[:to], article[:cc] ].compact.join(',').to_s
recipients = []
begin
list = Mail::AddressList.new(recipient)
list.addresses.each do |address|
recipients.push address.address
end
rescue # rubocop:disable Lint/SuppressedException
end
return result if recipients.blank?
begin
certs = SMIMECertificate.for_recipipent_email_addresses!(recipients)
if certs
if certs.any?(&:expired?)
result[:success] = false
result[:comment] = "certificates found for #{recipients.join(',')} but expired"
else
result[:success] = true
result[:comment] = "certificates found for #{recipients.join(',')}"
end
end
rescue => e
result[:comment] = e.message
end
result
end
def article_sign(ticket)
result = {
success: false,
comment: 'certificate not found',
}
return result if ticket.blank? || !ticket[:group_id]
group = Group.find_by(id: ticket[:group_id])
return result if !group
email_address = group.email_address
begin
list = Mail::AddressList.new(email_address.email)
from = list.addresses.first.to_s
cert = SMIMECertificate.for_sender_email_address(from)
if cert
if cert.expired?
result[:success] = false
result[:comment] = "certificate for #{email_address.email} found but expired"
else
result[:success] = true
result[:comment] = "certificate for #{email_address.email} found"
end
else
result[:success] = false
result[:comment] = "no certificate for #{email_address.email} found"
end
rescue => e
result[:comment] = e.message
end
result
end
end