class As2::Server
Constants
- HEADER_MAP
Attributes
logger[RW]
Public Class Methods
new(options = {}, &block)
click to toggle source
# File lib/as2/server.rb, line 21 def initialize(options = {}, &block) @block = block @info = Config.server_info @options = options end
Public Instance Methods
call(env)
click to toggle source
# File lib/as2/server.rb, line 27 def call(env) if env['HTTP_AS2_TO'] != @info.name return send_error(env, "Invalid destination name #{env['HTTP_AS2_TO']}") end partner = Config.partners[env['HTTP_AS2_FROM']] unless partner return send_error(env, "Invalid partner name #{env['HTTP_AS2_FROM']}") end smime_string = build_smime_text(env) message = Message.new(smime_string, @info.pkey, @info.certificate) unless message.valid_signature?(partner.certificate) if @options[:on_signature_failure] @options[:on_signature_failure].call({env: env, smime_string: smime_string}) else raise "Could not verify signature" end end mic = OpenSSL::Digest::SHA1.base64digest(message.decrypted_message) if @block begin @block.call message.attachment.filename, message.attachment.body rescue Exception => e return send_error(env, e.message) end end send_mdn(env, mic) end
Private Instance Methods
build_smime_text(env)
click to toggle source
# File lib/as2/server.rb, line 61 def build_smime_text(env) request = Rack::Request.new(env) smime_data = StringIO.new HEADER_MAP.each do |name, value| smime_data.puts "#{name}: #{env[value]}" end smime_data.puts 'Content-Transfer-Encoding: base64' smime_data.puts smime_data.puts Base64Helper.ensure_base64(request.body.read) return smime_data.string end
send_error(env, msg)
click to toggle source
# File lib/as2/server.rb, line 80 def send_error(env, msg) logger(env).error msg send_mdn env, nil, msg end
send_mdn(env, mic, failed = nil)
click to toggle source
# File lib/as2/server.rb, line 85 def send_mdn(env, mic, failed = nil) report = MimeGenerator::Part.new report['Content-Type'] = 'multipart/report; report-type=disposition-notification' text = MimeGenerator::Part.new text['Content-Type'] = 'text/plain' text['Content-Transfer-Encoding'] = '7bit' text.body = "The AS2 message has been received successfully" report.add_part text notification = MimeGenerator::Part.new notification['Content-Type'] = 'message/disposition-notification' notification['Content-Transfer-Encoding'] = '7bit' options = { 'Reporting-UA' => @info.name, 'Original-Recipient' => "rfc822; #{@info.name}", 'Final-Recipient' => "rfc822; #{@info.name}", 'Original-Message-ID' => env['HTTP_MESSAGE_ID'] } if failed options['Disposition'] = 'automatic-action/MDN-sent-automatically; failed' options['Failure'] = failed else options['Disposition'] = 'automatic-action/MDN-sent-automatically; processed' end options['Received-Content-MIC'] = "#{mic}, sha1" if mic notification.body = options.map{|n, v| "#{n}: #{v}"}.join("\r\n") report.add_part notification msg_out = StringIO.new report.write msg_out pkcs7 = OpenSSL::PKCS7.sign @info.certificate, @info.pkey, msg_out.string pkcs7.detached = true smime_signed = OpenSSL::PKCS7.write_smime pkcs7, msg_out.string content_type = smime_signed[/^Content-Type: (.+?)$/m, 1] smime_signed.sub!(/\A.+?^(?=---)/m, '') headers = {} headers['Content-Type'] = content_type headers['MIME-Version'] = '1.0' headers['Message-ID'] = "<#{@info.name}-#{Time.now.strftime('%Y%m%d%H%M%S')}@#{@info.domain}>" headers['AS2-From'] = @info.name headers['AS2-To'] = env['HTTP_AS2_FROM'] headers['AS2-Version'] = '1.2' headers['Connection'] = 'close' [200, headers, ["\r\n" + smime_signed]] end