Commit 83adf039eb86b7a04ca7fa929137f0f0dd3358bd:
check signatures
Branch: refs/heads/secmail
Author: Sam Ruby <[email protected]>
Committer: Sam Ruby <[email protected]>
Pusher: rubys <[email protected]>
------------------------------------------------------------
www/secmail/models/attachment.rb | +++++++
www/secmail/public/secmail.css | ++++
www/secmail/views/actions/check-signature.json.rb | +++++++++++++
www/secmail/views/app.js.rb | +
www/secmail/views/check-signature.js.rb | +++++++++++++
www/secmail/views/parts.js.rb | ++++++
------------------------------------------------------------
117 changes: 117 additions, 0 deletions.
------------------------------------------------------------
diff --git a/www/secmail/models/attachment.rb b/www/secmail/models/attachment.rb
index 83f98ff..4035515 100644
--- a/www/secmail/models/attachment.rb
+++ b/www/secmail/models/attachment.rb
@@ -27,6 +27,13 @@ def safe_name
name.untaint
end
+ def as_file
+ file = Tempfile.new([safe_name, '.pdf'], encoding: Encoding::BINARY)
+ file.write(body)
+ file.rewind
+ file
+ end
+
def as_pdf
file = Tempfile.new([safe_name, '.pdf'], encoding: Encoding::BINARY)
file.write(body)
diff --git a/www/secmail/public/secmail.css b/www/secmail/public/secmail.css
index 657ce65..aa2d719 100644
--- a/www/secmail/public/secmail.css
+++ b/www/secmail/public/secmail.css
@@ -15,6 +15,10 @@
background-color: yellow;
}
+.signature {
+ background-color: #FC0;
+}
+
.dragging {
opacity: 0.5;
}
diff --git a/www/secmail/views/actions/check-signature.json.rb
b/www/secmail/views/actions/check-signature.json.rb
new file mode 100644
index 0000000..1565119
--- /dev/null
+++ b/www/secmail/views/actions/check-signature.json.rb
@@ -0,0 +1,50 @@
+#
+# check signature on an attachment
+#
+
+month, hash = @message.match(%r{/(\d+)/(\w+)}).captures
+
+mbox = Mailbox.new(month)
+message = mbox.find(hash)
+
+begin
+ # fetch attachment and signature
+ attachment = message.find(@attachment).as_file
+ signature = message.find(@signature).as_file
+
+ # run gpg verify command
+ out, err, rc = Open3.capture3 'gpg', '--verify', signature.path,
+ attachment.path
+
+ # if key is not found, fetch and try again
+ if err.include? "gpg: Can't check signature: public key not found"
+ # extract and fetch key
+ keyid = err[/[RD]SA key ID (\w+)/,1].untaint
+ out2, err2, rc2 = Open3.capture3 'gpg', '--keyserver', 'pgpkeys.mit.edu',
+ '--recv-keys', keyid
+
+ # run gpg verify command again
+ out, err, rc = Open3.capture3 'gpg', '--verify', signature.path,
+ attachment.path
+
+ # if verify failed, concatenate fetch output
+ if rc.exitstatus != 0
+ out += out2
+ err += err2
+ end
+ end
+
+ # list of strings to ignore
+ ignore = [
+ /^gpg:\s+WARNING: This key is not certified with a trusted signature!$/,
+ /^gpg:\s+There is no indication that the signature belongs to the owner\.$/
+ ]
+
+ ignore.each {|re| err.gsub! re, ''}
+
+ensure
+ attachment.unlink if attachment
+ signature.unlink if signature
+end
+
+{output: out, error: err, rc: rc.exitstatus}
diff --git a/www/secmail/views/app.js.rb b/www/secmail/views/app.js.rb
index 3154739..fc30ea6 100644
--- a/www/secmail/views/app.js.rb
+++ b/www/secmail/views/app.js.rb
@@ -3,6 +3,7 @@
require_relative 'index'
require_relative 'parts'
+require_relative 'check-signature'
require_relative 'forms/icla'
require_relative 'forms/grant'
diff --git a/www/secmail/views/check-signature.js.rb
b/www/secmail/views/check-signature.js.rb
new file mode 100644
index 0000000..0e1e611
--- /dev/null
+++ b/www/secmail/views/check-signature.js.rb
@@ -0,0 +1,49 @@
+class CheckSignature < React
+ def initialize
+ @signature = nil
+ @checked = nil
+ end
+
+ def render
+ if @signature
+ _div.alert @alert, class: @flag
+ end
+ end
+
+ def componentDidMount()
+ self.componentWillReceiveProps()
+ end
+
+ def componentWillReceiveProps()
+ @signature = @@attachments.find {|attachment|
+ attachment == @@selected + '.asc' or attachment == @@selected + '.sig'
+ }
+
+ if @signature and @signature != @checked
+ @flag = 'alert-info'
+ @alert = 'checking signature'
+
+ data = {
+ message: window.parent.location.pathname,
+ attachment: @@selected,
+ signature: @signature
+ }
+
+ HTTP.post('../../actions/check-signature', data).then {|response|
+ output = response.output + response.error
+
+ if output.include? 'Good signature'
+ @flag = 'alert-success'
+ else
+ @flag = 'alert-danger'
+ end
+
+ @alert = output
+ @checked = @signature
+ }.catch {|error|
+ @alert = error
+ @flag = 'alert-warning'
+ }
+ end
+ end
+end
diff --git a/www/secmail/views/parts.js.rb b/www/secmail/views/parts.js.rb
index 365d4c8..c371f20 100644
--- a/www/secmail/views/parts.js.rb
+++ b/www/secmail/views/parts.js.rb
@@ -37,6 +37,10 @@ def render
options[:className] = 'dragging'
elsif attachment == @selected
options[:className] = 'selected'
+ elsif attachment == @selected + '.asc'
+ options[:className] = 'signature'
+ elsif attachment == @selected + '.sig'
+ options[:className] = 'signature'
else
options[:className] = nil
end
@@ -59,6 +63,8 @@ def render
if @selected and not @menu
+ _CheckSignature selected: @selected, attachments: @attachments
+
# filing options
_table.doctype do
_tr do