schleuder 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/LICENSE +339 -0
- data/README +32 -0
- data/bin/schleuder +96 -0
- data/bin/schleuder-fix-gem-dependencies +30 -0
- data/bin/schleuder-init-setup +37 -0
- data/bin/schleuder-migrate-v2.1-to-v2.2 +205 -0
- data/bin/schleuder-newlist +384 -0
- data/contrib/check-expired-keys.rb +59 -0
- data/contrib/mutt-schleuder-colors.rc +10 -0
- data/contrib/mutt-schleuder-resend.vim +24 -0
- data/contrib/smtpserver.rb +76 -0
- data/ext/default-list.conf +146 -0
- data/ext/default-members.conf +7 -0
- data/ext/list.conf.example +14 -0
- data/ext/schleuder.conf +62 -0
- data/lib/schleuder.rb +49 -0
- data/lib/schleuder/archiver.rb +46 -0
- data/lib/schleuder/crypt.rb +188 -0
- data/lib/schleuder/errors.rb +5 -0
- data/lib/schleuder/list.rb +177 -0
- data/lib/schleuder/list_config.rb +146 -0
- data/lib/schleuder/log/listlogger.rb +56 -0
- data/lib/schleuder/log/outputter/emailoutputter.rb +118 -0
- data/lib/schleuder/log/outputter/metaemailoutputter.rb +50 -0
- data/lib/schleuder/log/schleuderlogger.rb +23 -0
- data/lib/schleuder/mail.rb +861 -0
- data/lib/schleuder/mailer.rb +26 -0
- data/lib/schleuder/member.rb +69 -0
- data/lib/schleuder/plugin.rb +54 -0
- data/lib/schleuder/processor.rb +363 -0
- data/lib/schleuder/schleuder_config.rb +72 -0
- data/lib/schleuder/storage.rb +84 -0
- data/lib/schleuder/utils.rb +80 -0
- data/lib/schleuder/version.rb +3 -0
- data/man/schleuder-newlist.8 +191 -0
- data/man/schleuder.8 +400 -0
- data/plugins/README +20 -0
- data/plugins/manage_keys_plugin.rb +113 -0
- data/plugins/manage_members_plugin.rb +152 -0
- data/plugins/manage_self_plugin.rb +26 -0
- data/plugins/resend_plugin.rb +35 -0
- data/plugins/version_plugin.rb +12 -0
- metadata +178 -0
- metadata.gz.sig +2 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# This script checks all public keys in the keyring of the given schleuder-list
|
4
|
+
# for being expired (or otherwise unusable) and reports the output (if there
|
5
|
+
# was something found) to the list-admins.
|
6
|
+
# Key are being reported if they expire within the next 14 days.
|
7
|
+
# We suggest to run this script from cron once a week.
|
8
|
+
|
9
|
+
$VERBOSE = nil
|
10
|
+
|
11
|
+
require 'schleuder'
|
12
|
+
include Schleuder
|
13
|
+
|
14
|
+
if ARGV.size != 1
|
15
|
+
puts "Usage: #{File.basename(__FILE__)} listname"
|
16
|
+
exit 1
|
17
|
+
elsif ! File.directory?(List.listdir(ARGV.first))
|
18
|
+
puts "No such list: '#{ARGV.first}'."
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
|
22
|
+
listname = ARGV.first
|
23
|
+
Schleuder.list = List.new(listname)
|
24
|
+
|
25
|
+
now = Time.now
|
26
|
+
checkdate = now + 120960000 # two weeks
|
27
|
+
crypt = Crypt.new('')
|
28
|
+
msg = ''
|
29
|
+
unusable = []
|
30
|
+
expiring = []
|
31
|
+
|
32
|
+
crypt.list_keys.each do |key|
|
33
|
+
if (exp = key.subkeys.first.expires) > Time.utc(1971, 1, 1, 1)
|
34
|
+
# key has expiry date
|
35
|
+
if now < exp && exp < checkdate
|
36
|
+
# key expires in the near future
|
37
|
+
expdays = ((exp - now)/86400).to_i
|
38
|
+
expiring << [key, expdays]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
if not (trust = [:revoked, :expired, :disabled, :invalid].grep(key.trust)).empty?
|
43
|
+
unusable << [key, trust]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
expiring.each do |key,days|
|
48
|
+
msg << "-> Key expires in #{days} days:\n#{key.to_s}\n\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
unusable.each do |key,trust|
|
52
|
+
msg << "-> Key is #{trust.join(' and ')}:\n#{key.to_s}\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
unless msg.empty?
|
56
|
+
prefix = "Checking the public keys present in the keyring of list #{listname} for usability gave the following result:".fmt
|
57
|
+
Schleuder.log.notify_admin('keys', prefix + "\n\n" + msg)
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# insert "source /path/to/mutt-schleuder-colors.rc" into your muttrc
|
2
|
+
# metadata schleuder v2
|
3
|
+
color body red default "^From: .*"
|
4
|
+
color body red default "^To: .*"
|
5
|
+
color body red default "^Cc: .*"
|
6
|
+
color body red default "^Date: .*"
|
7
|
+
color body brightred default "^Enc: unenc.*"
|
8
|
+
color body red default "^Enc: enc.*"
|
9
|
+
color body brightred default "^Sig: [^G]?.*"
|
10
|
+
color body red default "^Sig: Good signature.*"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
" Reply-helper for mutt with schleuder (>= v2.0.0).
|
2
|
+
" Will insert a resend-line filled with the address from the quoted Text
|
3
|
+
" you're replying to.
|
4
|
+
function! SchleuderInsert(string)
|
5
|
+
let fromline = search('> From:', 'n')
|
6
|
+
let addr = matchstr(getline(fromline), '[^ <]*@[^ >]*')
|
7
|
+
let insline = search('^$', 'n')
|
8
|
+
" append after the first blank line
|
9
|
+
let foo = append(insline, a:string . addr)
|
10
|
+
" can't figure out how to append() a newline, so we simply add another
|
11
|
+
" empty line
|
12
|
+
return append(insline+1, '')
|
13
|
+
endfunction
|
14
|
+
|
15
|
+
function! SchleuderInsertResendEncrypted()
|
16
|
+
return SchleuderInsert('X-RESEND-ENCRYPTED-ONLY: ')
|
17
|
+
endfunction
|
18
|
+
|
19
|
+
function! SchleuderInsertResend()
|
20
|
+
return SchleuderInsert('X-RESEND: ')
|
21
|
+
endfunction
|
22
|
+
|
23
|
+
nmap ;sr :call SchleuderInsertResend()<CR>
|
24
|
+
nmap ;sc :call SchleuderInsertResendEncrypted()<CR>
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# defaults
|
4
|
+
port = 25
|
5
|
+
output = "/tmp"
|
6
|
+
|
7
|
+
def usage
|
8
|
+
file = File.basename(__FILE__)
|
9
|
+
puts "Usage: #{file} [-p portnum] { .../output_base_dir/ | .../bin/schleuder listname }"
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
|
13
|
+
# get args
|
14
|
+
if (not ARGV.empty?) and (ARGV.first[0..0] == '-')
|
15
|
+
arg = ARGV.shift
|
16
|
+
if arg == '-p'
|
17
|
+
port = ARGV.shift.to_i
|
18
|
+
usage if port == 0 # nil or not convertable strings convert to 0
|
19
|
+
else
|
20
|
+
usage
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
output = ARGV.join(" ") || output
|
25
|
+
|
26
|
+
|
27
|
+
# run the server
|
28
|
+
require 'socket'
|
29
|
+
server = TCPServer.new("localhost", port)
|
30
|
+
|
31
|
+
def p(msg)
|
32
|
+
#puts "o:" + msg
|
33
|
+
@s.print msg + "\r\n"
|
34
|
+
end
|
35
|
+
|
36
|
+
# receive input
|
37
|
+
while (@s = server.accept)
|
38
|
+
input = ''
|
39
|
+
#p "200 OK"
|
40
|
+
p "220 localhost SMTP"
|
41
|
+
#p "Wazzup?"
|
42
|
+
begin
|
43
|
+
while i = @s.gets.chomp
|
44
|
+
#puts "i:" + i
|
45
|
+
case i[0..3].downcase
|
46
|
+
when 'ehlo', 'helo'
|
47
|
+
p "250 localhost"
|
48
|
+
when 'mail', 'rcpt', 'rset', '.'
|
49
|
+
p "250 ok"
|
50
|
+
when 'data'
|
51
|
+
p "354 go ahead"
|
52
|
+
when 'quit'
|
53
|
+
p "221 localhost"
|
54
|
+
@s.close
|
55
|
+
else
|
56
|
+
input << i + "\n"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
rescue IOError
|
60
|
+
end
|
61
|
+
# write input to #{output}
|
62
|
+
if File.directory? output
|
63
|
+
file = output + "/schleuder-#{$$}-#{Time.now.to_f}"
|
64
|
+
File.open(file, 'w') do |f|
|
65
|
+
f.puts input
|
66
|
+
end
|
67
|
+
File.chown 1000, 10, file
|
68
|
+
puts file
|
69
|
+
else
|
70
|
+
IO.popen(output, 'w') do |p|
|
71
|
+
p.puts input
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# Setting default values for lists. Each setting can be overridden by the
|
2
|
+
# list-specific config-file.
|
3
|
+
# Options are listed alphabetically and provided with the default behaviour.
|
4
|
+
# Some options that need to be set for each list individually are listed in
|
5
|
+
# list.conf.example.
|
6
|
+
#
|
7
|
+
# The configuration format is yaml (http://www.yaml.org).
|
8
|
+
#
|
9
|
+
# Be careful with changes here once lists are running! You might change
|
10
|
+
# their behaviour!
|
11
|
+
---
|
12
|
+
# Emailaddresses and key_fingerprints of the admin(s) (aka maintainer) of the
|
13
|
+
# list, which will receive errormsgs etc. Must be a non-empty array of hashes
|
14
|
+
# (:email, :key_fingerprint).
|
15
|
+
#admins:
|
16
|
+
#- email: anna@example.org
|
17
|
+
# key_fingerprint: 01234567DEADBEE01234567DEADBEEF
|
18
|
+
#- email: arthur@example.org
|
19
|
+
# key_fingerprint: DEADBEE01234567DEADBEEF01234567
|
20
|
+
#
|
21
|
+
# Only send out enrypted emails?
|
22
|
+
#send_encrypted_only: false
|
23
|
+
#
|
24
|
+
# Allow receiving unenrypted mails? If false, any other email will be bounced.
|
25
|
+
#receive_encrypted_only: false
|
26
|
+
#
|
27
|
+
# Allow receiving mails not validly signed? If false, any other email will be
|
28
|
+
# bounced.
|
29
|
+
#receive_signed_only: false
|
30
|
+
#
|
31
|
+
# Allow receiving mails that are not validly signed by a list members key? If
|
32
|
+
# true, any other email will be bounced.
|
33
|
+
#receive_authenticated_only: false
|
34
|
+
#
|
35
|
+
# Only allow mails being sent from a members address? If true, any other sending
|
36
|
+
# address will be dropped.
|
37
|
+
# NOTE: This is a very weak restriction mechanism on which you should not rely,
|
38
|
+
# as sending addresses can easily be faked! We recommend you to rather
|
39
|
+
# rely on the `receive_authenticated_only` option. Setting the
|
40
|
+
# `receive_authenticated_only` option to true, will authenticated senders
|
41
|
+
# based on the signature on the mail, which is the strongest
|
42
|
+
# authentication mechanism you can get.
|
43
|
+
# This option could be useful, if you would like to have a closed
|
44
|
+
# mailinglist, but could not yet get all members to properly use GPG.
|
45
|
+
#receive_from_member_emailaddresses_only: false
|
46
|
+
#
|
47
|
+
# Whether to accept only emails that are validly signed by a list-admin's key
|
48
|
+
# This is useful for newsletters, announce or notification lists
|
49
|
+
#receive_admin_only: false
|
50
|
+
#
|
51
|
+
# Which pgp encoding? Chose out of PLAIN (text/plain), APPL (application/pgp)
|
52
|
+
# and MIME (pgp/mime)
|
53
|
+
#default_mime: MIME
|
54
|
+
#
|
55
|
+
# Schleuder can include various metadata from the original mail. You can tweak
|
56
|
+
# Schleuder which header fields should be included.
|
57
|
+
#headers_to_meta:
|
58
|
+
#- :from
|
59
|
+
#- :to
|
60
|
+
#- :cc
|
61
|
+
#- :date
|
62
|
+
#
|
63
|
+
# Whether to keep the msgids (In-Reply-To:, References:) or not
|
64
|
+
# Schleuder will only pass valid schleuder Message-Ids, all the others
|
65
|
+
# are filtered out.
|
66
|
+
# This setting can lead to information leakage, as replies are connectable
|
67
|
+
# and a thread of (encrypted) messages can be built by an eavesdropper.
|
68
|
+
#keep_msgid: true
|
69
|
+
#
|
70
|
+
# Schleuder can be commanded to process various plugins via keywords in signed
|
71
|
+
# emails. To restrict the usage of specific keywords to the admin (some can
|
72
|
+
# cause fatal damage) list them here.
|
73
|
+
#keywords_admin_only: ['ADD-MEMBER', 'DELETE-MEMBER', 'DELETE-KEY', 'SAVE-MEMBERS', 'DEL-KEY']
|
74
|
+
#
|
75
|
+
# For keywords listed here the list-admin(s) will receive a notice whenever a
|
76
|
+
# member triggers a command with it.
|
77
|
+
#keywords_admin_notify: ['ADD-KEY']
|
78
|
+
#
|
79
|
+
# list-specific log-level: ERROR || WARN || INFO || DEBUG
|
80
|
+
#log_level: ERROR
|
81
|
+
#
|
82
|
+
# Log to SYSLOG? To enable set to true.
|
83
|
+
#log_syslog: false
|
84
|
+
#
|
85
|
+
# Log to IO (write into STDIN of another process/executable)? To enable specify
|
86
|
+
# executable with full path and optional arguments here.
|
87
|
+
# Example: /path/to/multilog tt /var/schleuderlists/listname/log/
|
88
|
+
#log_io: false
|
89
|
+
#
|
90
|
+
# Log to a file? To enable specify a filename, optionally with full path.
|
91
|
+
#log_file: false
|
92
|
+
#
|
93
|
+
# speaks for itself, no?
|
94
|
+
#public_footer:
|
95
|
+
#
|
96
|
+
# A string that the subject of every email that *is* validly signed by a
|
97
|
+
# list-member will be prefixed with (unless the string is already present in
|
98
|
+
# the subject)
|
99
|
+
#prefix: ''
|
100
|
+
#
|
101
|
+
# A string that the subject of every email that is *not* validly signed by a
|
102
|
+
# list-member will be prefixed with.
|
103
|
+
#prefix_in: ''
|
104
|
+
#
|
105
|
+
# A string that the subject of every internal email, that has been resent to
|
106
|
+
# the outside, will be prefixed with.
|
107
|
+
#prefix_out: ''
|
108
|
+
#
|
109
|
+
# Drop any bounces (incoming email not passing the receive_*_only-rules)
|
110
|
+
#bounces_drop_all: false
|
111
|
+
#
|
112
|
+
# Drop bounces if they match one of these headers. Must be a hash, keys and
|
113
|
+
# values are case insensitive.
|
114
|
+
#bounces_drop_on_headers: {'x-spam-flag' => 'yes'}
|
115
|
+
#
|
116
|
+
# Send a notice to admin(s) on bouncing or dropping
|
117
|
+
#bounces_notify_admins: true
|
118
|
+
#
|
119
|
+
# Include RFC-compliant List-* Headers into member mails
|
120
|
+
#include_list_headers: true
|
121
|
+
#
|
122
|
+
# Include OpenPGP-Header
|
123
|
+
#include_openpgp_header: true
|
124
|
+
#
|
125
|
+
# Prefered way to receive emails to note in OpenPGP-Header ('sign'|'encrypt'|'signencrypt'|'unprotected'|'none')
|
126
|
+
# 'none' to not include a preference
|
127
|
+
# default: 'signencrypt'
|
128
|
+
#openpgp_header_preference: 'signencrypt'
|
129
|
+
#
|
130
|
+
# If we want to dump the original incoming mail.
|
131
|
+
# ATTENTION: this stores the incoming e-mail on disk!
|
132
|
+
#dump_incoming_mail: false
|
133
|
+
#
|
134
|
+
# Maximum size of message allowed on the list in kilobyte. All others will be bounced.
|
135
|
+
# Default is 10MB
|
136
|
+
#max_message_size: 10240
|
137
|
+
#
|
138
|
+
# Whether to archive messages sent to list members or not.
|
139
|
+
# Setting this option to true will archive every message sent to list members
|
140
|
+
# into <listdir>/archive/$YEAR/$MONTH/$DAY/$MESSAGEID.msg
|
141
|
+
# The messages are encrypted with the lists' public key and dumped as it would
|
142
|
+
# have been handed over to the MTA.
|
143
|
+
# Beware that this will archive every communication over that list on a remote
|
144
|
+
# box amongst the matching private key and its password!
|
145
|
+
# Default: false
|
146
|
+
#archive: false
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Configuration options for individal lists.
|
2
|
+
# Options are listed alphabetically and provided with the default behaviour.
|
3
|
+
# Beyond those options listed here all options listed in default-list.conf can be specified.
|
4
|
+
#
|
5
|
+
# The configuration format is yaml (http://www.yaml.org).
|
6
|
+
---
|
7
|
+
# The emailaddress of the list. Needed to identify headers, loops and also the GnuPG key.
|
8
|
+
# Must be a valid email address.
|
9
|
+
#myaddr: list@example.org
|
10
|
+
# Realname of this list address (mainly used for GnuPG key)
|
11
|
+
#myname: The Listname
|
12
|
+
# Password for the GnuPG private key. (You're working on an encrypted filesystem, aren't you?)
|
13
|
+
# Make it long and complicated, you won't ever need to type it.
|
14
|
+
#gpg_password: "iuttIs6flewd)#misIg5drash/#tesJor:5Quej"
|
data/ext/schleuder.conf
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# Configuration options for schleuder.
|
2
|
+
# The options are sorted alphabetically and the defaults
|
3
|
+
# are provided as commented option.
|
4
|
+
# The configuration format is yaml.
|
5
|
+
---
|
6
|
+
# Outgoing SMTP host
|
7
|
+
#smtp_host: localhost
|
8
|
+
#
|
9
|
+
# Outgoing SMTP port
|
10
|
+
#smtp_port: 25
|
11
|
+
#
|
12
|
+
# Set the type of a key we might create for new lists.
|
13
|
+
#gpg_key_type: RSA
|
14
|
+
#
|
15
|
+
# Set the length of a key we might create for new lists.
|
16
|
+
#gpg_key_length: 2048
|
17
|
+
#
|
18
|
+
# Set the type of the subkey of a key we might create
|
19
|
+
# for new lists.
|
20
|
+
#gpg_subkey_type: RSA
|
21
|
+
#
|
22
|
+
# Set the length of the subkey of a key we might create
|
23
|
+
# for new lists.
|
24
|
+
#gpg_subkey_length: 2048
|
25
|
+
#
|
26
|
+
# Name of the per list config file.
|
27
|
+
#lists_configfile: list.conf
|
28
|
+
#
|
29
|
+
# Per list logfile name. Will be written into the directory
|
30
|
+
# of the list.
|
31
|
+
#lists_logfile: list.log
|
32
|
+
#
|
33
|
+
# Name of the per list file containing all members and their
|
34
|
+
# options.
|
35
|
+
#lists_memberfile: members.conf
|
36
|
+
#
|
37
|
+
# Where we find the global options for all lists.
|
38
|
+
# Note: the following notion isn't valid. You have
|
39
|
+
# to provide a fully qualified path.
|
40
|
+
#lists_default_conf: conf_dir + '/default-list.conf'
|
41
|
+
#
|
42
|
+
# Location of the various schleuderlists' directory.
|
43
|
+
#lists_dir: /var/schleuderlists
|
44
|
+
#
|
45
|
+
# Location of the global logfile.
|
46
|
+
#log_file: /var/log/schleuder/schleuder.log
|
47
|
+
#
|
48
|
+
# Global schleuder log level, might change after the list config
|
49
|
+
# have been read.
|
50
|
+
# Possible values: ERROR || WARN || INFO || DEBUG
|
51
|
+
#log_level: ERROR
|
52
|
+
#
|
53
|
+
# Location of schleuder plugins. Note: the following notion
|
54
|
+
# isn't valid. You have to provide a fully qualified path.
|
55
|
+
#plugins_dir = schleuder_base + '/plugins'
|
56
|
+
#
|
57
|
+
# The super administrator of this schleuder installation. This
|
58
|
+
# address will receive all notices which can'tbe delivered to a certain list
|
59
|
+
# admin. It will also be used as sender for emails to list-admins and thus
|
60
|
+
# receive their bounces and be seen in public.
|
61
|
+
#superadminaddr: root@localhost
|
62
|
+
|
data/lib/schleuder.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# third party
|
2
|
+
|
3
|
+
errmsg = "For use with ruby v%s %s is required!\nPlease run schleuder-fix-gem-dependencies to fix this!"
|
4
|
+
if RUBY_VERSION =~ /1.8/
|
5
|
+
require 'rubygems'
|
6
|
+
begin
|
7
|
+
require 'tmail'
|
8
|
+
rescue LoadError
|
9
|
+
$stderr.puts errmsg % %w(1.8, tmail \(preferably v1.2.3.1\))
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
else
|
13
|
+
begin
|
14
|
+
gem 'actionmailer', '=2.3.14'
|
15
|
+
require 'action_mailer'
|
16
|
+
rescue LoadError
|
17
|
+
$stderr.puts errmsg % %w(1.9, actionmailer-2.3.14)
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
gem 'gpgme', '=1.0.8'
|
23
|
+
require 'gpgme'
|
24
|
+
|
25
|
+
require 'net/smtp'
|
26
|
+
require 'log4r'
|
27
|
+
require 'log4r/outputter/emailoutputter'
|
28
|
+
require 'log4r/outputter/fileoutputter'
|
29
|
+
require 'filemagic/ext'
|
30
|
+
|
31
|
+
# internal requires
|
32
|
+
$:.unshift File.dirname(__FILE__)
|
33
|
+
require 'schleuder/errors'
|
34
|
+
require 'schleuder/utils'
|
35
|
+
require 'schleuder/crypt'
|
36
|
+
require 'schleuder/storage'
|
37
|
+
require 'schleuder/list_config'
|
38
|
+
require 'schleuder/list'
|
39
|
+
require 'schleuder/mailer'
|
40
|
+
require 'schleuder/mail'
|
41
|
+
require 'schleuder/member'
|
42
|
+
require 'schleuder/plugin'
|
43
|
+
require 'schleuder/schleuder_config'
|
44
|
+
require 'schleuder/log/outputter/emailoutputter'
|
45
|
+
require 'schleuder/log/outputter/metaemailoutputter'
|
46
|
+
require 'schleuder/log/schleuderlogger'
|
47
|
+
require 'schleuder/log/listlogger'
|
48
|
+
require 'schleuder/archiver'
|
49
|
+
require 'schleuder/processor'
|