Revision c7904e2c
Added by Marc Dequènes over 15 years ago
- ID c7904e2c61b6eaa81c193b40bf87c9332410cf9a
.gitignore | ||
---|---|---|
\#*#
|
||
config
|
||
log
|
||
run
|
||
var
|
lib/cyborghood/base.rb | ||
---|---|---|
include Singleton
|
||
|
||
CFG_DIR = './config/'
|
||
WORK_DIR = './var/lib/cyborghood/'
|
||
|
||
CONFFILE_GLOBAL = "cyborghood.conf"
|
||
CONFFILE_BOT = "cyborghood_%s.conf"
|
||
... | ... | |
end
|
||
end
|
||
|
||
# temporary
|
||
def work_dir
|
||
WORK_DIR
|
||
end
|
||
|
||
private
|
||
|
||
def self.fetch_config(name = nil)
|
lib/cyborghood/mail.rb | ||
---|---|---|
require 'action_mailer/quoting'
|
||
require 'action_mailer/utils'
|
||
require 'net/smtp'
|
||
require 'fileutils'
|
||
require 'digest/md5'
|
||
|
||
|
||
# This class handles RFC3156 signed messages, validates them, and extract orders properly.
|
||
# Encrypted content are not implemented yet.
|
||
... | ... | |
end
|
||
|
||
def parse
|
||
if is_marked?
|
||
logger.info "Replay detected"
|
||
return nil
|
||
end
|
||
|
||
return parse_signed() if is_pgp_signed?
|
||
return parse_encrypted() if is_pgp_encrypted?
|
||
{:ok => false, :msg => "mail not RFC3156 compliant"}.to_ostruct
|
||
... | ... | |
|
||
drift = Time.new.to_i - sig_check.timestamp.to_i
|
||
logger.debug "Signature drift time: #{drift}"
|
||
if drift > 0 and drift < MAX_DRIFT_TIME
|
||
if drift.abs < MAX_DRIFT_TIME
|
||
signed_content = pgp_signed_part()
|
||
if signed_content.multipart?
|
||
if signed_content.parts[0].content_type == "text/plain"
|
||
... | ... | |
end
|
||
|
||
logger.debug "Mail OK"
|
||
mark_processed(sig_check.timestamp)
|
||
order = {:ok => true, :user => user, :commands => commands, :refs => refs}
|
||
else
|
||
order[:user] = user
|
||
logger.info "Mail does not contain a proper MIME part for commands"
|
||
end
|
||
else
|
||
logger.info "Mail rejected as it may be a replay (signature timestamp is too old)"
|
||
order = {:ok => false, :user => user, :msg => "The signature was made too long ago (perhaps your system clock is not up-to-date). Rejected message to avoid replay attacks."}
|
||
if drift > 0
|
||
logger.info "Mail rejected as it may be a replay (signature timestamp is too old)"
|
||
order = {:ok => false, :user => user, :msg => "The signature was made too long ago (perhaps your system clock is not up-to-date). Rejected message to avoid replay attacks."}
|
||
else
|
||
# mark message to prevent later replay of the message
|
||
mark_processed(sig_check.timestamp)
|
||
logger.info "Mail rejected as it is coming from the future (and may allow later replay)"
|
||
order = {:ok => false, :user => user, :msg => "The signature was made in the future (perhaps your system clock is not up-to-date). Rejected message to avoid replay attacks."}
|
||
end
|
||
end
|
||
end
|
||
else
|
||
... | ... | |
|
||
# create a fake mail and chain parsing operations
|
||
clear_mail = self.class.new(clear_message)
|
||
# propagate message_id to be able to mark messages (replay protection)
|
||
clear_mail.message_id = @mail.message_id
|
||
return clear_mail.parse
|
||
rescue GPGME::Error, NotImplementedError => e
|
||
raise CyberError.new(:unrecoverable, "protocol/mail", e.message)
|
||
... | ... | |
|
||
order.to_ostruct
|
||
end
|
||
|
||
def mark_dir
|
||
File.join(@config.work_dir, "marks")
|
||
end
|
||
|
||
def mark_filename
|
||
File.join(mark_dir(), Digest::MD5.hexdigest(self.message_id))
|
||
end
|
||
|
||
def mark_processed(time)
|
||
FileUtils.mkdir_p(mark_dir())
|
||
File.open(mark_filename(), "w") do |fp|
|
||
fp.write self.message_id
|
||
end
|
||
File.utime(Time.now.to_i, time.to_i, mark_filename())
|
||
end
|
||
|
||
def is_marked?
|
||
File.exists?(mark_filename())
|
||
end
|
||
end
|
||
end
|
postman_daemon | ||
---|---|---|
options = {
|
||
:app_name => "CyborgHood_Postman",
|
||
:dir_mode => :normal,
|
||
:dir => "/opt/cyborghood/run",
|
||
:dir => "/opt/cyborghood/var/run",
|
||
:multiple => false,
|
||
:mode => :exec,
|
||
:monitor => true
|
Also available in: Unified diff
[evol] replay protection #2 (should be done), and moved 'run' directory in the new workdir (temporary code until real path configuration)