schleuder 2.2.4 → 3.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +138 -0
- data/Rakefile +136 -0
- data/bin/pinentry-clearpassphrase +72 -0
- data/bin/schleuder +9 -89
- data/bin/schleuder-api-daemon +4 -0
- data/db/migrate/20140501103532_create_lists.rb +39 -0
- data/db/migrate/20140501112859_create_subscriptions.rb +21 -0
- data/db/migrate/201508092100_add_language_to_lists.rb +11 -0
- data/db/migrate/20150812165700_change_keywords_admin_only_defaults.rb +8 -0
- data/db/migrate/20150813235800_add_forward_all_incoming_to_admins.rb +11 -0
- data/db/migrate/201508141727_change_send_encrypted_only_default.rb +8 -0
- data/db/migrate/201508222143_add_logfiles_to_keep_to_lists.rb +11 -0
- data/db/migrate/201508261723_rename_delivery_disabled_to_delivery_enabled_and_change_default.rb +14 -0
- data/db/migrate/201508261815_strip_gpg_passphrase.rb +11 -0
- data/db/migrate/201508261827_remove_default_mime.rb +9 -0
- data/db/migrate/20160501172700_fix_headers_to_meta_defaults.rb +8 -0
- data/db/migrate/20170713215059_add_internal_footer_to_list.rb +11 -0
- data/db/schema.rb +62 -0
- data/etc/init.d/schleuder-api-daemon +87 -0
- data/etc/list-defaults.yml +123 -0
- data/etc/postfix/schleuder_sqlite.cf +28 -0
- data/etc/schleuder-api-daemon.service +10 -0
- data/etc/schleuder.cron.weekly +6 -0
- data/etc/schleuder.yml +61 -0
- data/lib/schleuder-api-daemon.rb +420 -0
- data/lib/schleuder.rb +81 -47
- data/lib/schleuder/cli.rb +334 -0
- data/lib/schleuder/cli/cert.rb +24 -0
- data/lib/schleuder/cli/schleuder_cert_manager.rb +84 -0
- data/lib/schleuder/cli/subcommand_fix.rb +11 -0
- data/lib/schleuder/conf.rb +131 -0
- data/lib/schleuder/errors/active_model_error.rb +15 -0
- data/lib/schleuder/errors/base.rb +17 -0
- data/lib/schleuder/errors/decryption_failed.rb +16 -0
- data/lib/schleuder/errors/fatal_error.rb +13 -0
- data/lib/schleuder/errors/file_not_found.rb +14 -0
- data/lib/schleuder/errors/invalid_listname.rb +13 -0
- data/lib/schleuder/errors/key_adduid_failed.rb +13 -0
- data/lib/schleuder/errors/key_generation_failed.rb +16 -0
- data/lib/schleuder/errors/keyword_admin_only.rb +13 -0
- data/lib/schleuder/errors/list_exists.rb +13 -0
- data/lib/schleuder/errors/list_not_found.rb +14 -0
- data/lib/schleuder/errors/list_property_missing.rb +14 -0
- data/lib/schleuder/errors/listdir_problem.rb +16 -0
- data/lib/schleuder/errors/loading_list_settings_failed.rb +14 -0
- data/lib/schleuder/errors/message_empty.rb +14 -0
- data/lib/schleuder/errors/message_not_from_admin.rb +13 -0
- data/lib/schleuder/errors/message_sender_not_subscribed.rb +13 -0
- data/lib/schleuder/errors/message_too_big.rb +14 -0
- data/lib/schleuder/errors/message_unauthenticated.rb +13 -0
- data/lib/schleuder/errors/message_unencrypted.rb +13 -0
- data/lib/schleuder/errors/message_unsigned.rb +13 -0
- data/lib/schleuder/errors/standard_error.rb +5 -0
- data/lib/schleuder/errors/too_many_keys.rb +17 -0
- data/lib/schleuder/errors/unknown_list_option.rb +14 -0
- data/lib/schleuder/filters/auth_filter.rb +39 -0
- data/lib/schleuder/filters/bounces_filter.rb +12 -0
- data/lib/schleuder/filters/forward_filter.rb +17 -0
- data/lib/schleuder/filters/forward_incoming.rb +13 -0
- data/lib/schleuder/filters/hotmail_message_filter.rb +25 -0
- data/lib/schleuder/filters/max_message_size.rb +14 -0
- data/lib/schleuder/filters/request_filter.rb +26 -0
- data/lib/schleuder/filters/send_key_filter.rb +20 -0
- data/lib/schleuder/filters/strip_alternative_filter.rb +21 -0
- data/lib/schleuder/filters_runner.rb +83 -0
- data/lib/schleuder/gpgme/ctx.rb +274 -0
- data/lib/schleuder/gpgme/import_status.rb +27 -0
- data/lib/schleuder/gpgme/key.rb +212 -0
- data/lib/schleuder/gpgme/sub_key.rb +13 -0
- data/lib/schleuder/gpgme/user_id.rb +22 -0
- data/lib/schleuder/list.rb +318 -127
- data/lib/schleuder/list_builder.rb +139 -0
- data/lib/schleuder/listlogger.rb +31 -0
- data/lib/schleuder/logger.rb +23 -0
- data/lib/schleuder/logger_notifications.rb +69 -0
- data/lib/schleuder/mail/message.rb +482 -0
- data/lib/schleuder/mail/parts_list.rb +9 -0
- data/lib/schleuder/plugin_runners/base.rb +91 -0
- data/lib/schleuder/plugin_runners/list_plugins_runner.rb +24 -0
- data/lib/schleuder/plugin_runners/request_plugins_runner.rb +27 -0
- data/lib/schleuder/plugins/attach_listkey.rb +17 -0
- data/lib/schleuder/plugins/get_version.rb +7 -0
- data/lib/schleuder/plugins/key_management.rb +113 -0
- data/lib/schleuder/plugins/list_management.rb +15 -0
- data/lib/schleuder/plugins/resend.rb +196 -0
- data/lib/schleuder/plugins/sign_this.rb +46 -0
- data/lib/schleuder/plugins/subscription_management.rb +140 -0
- data/lib/schleuder/runner.rb +130 -0
- data/lib/schleuder/subscription.rb +98 -0
- data/lib/schleuder/validators/boolean_validator.rb +7 -0
- data/lib/schleuder/validators/email_validator.rb +7 -0
- data/lib/schleuder/validators/fingerprint_validator.rb +7 -0
- data/lib/schleuder/validators/greater_than_zero_validator.rb +7 -0
- data/lib/schleuder/validators/no_line_breaks_validator.rb +7 -0
- data/lib/schleuder/version.rb +1 -1
- data/locales/de.yml +179 -0
- data/locales/en.yml +179 -0
- metadata +305 -108
- checksums.yaml.gz.sig +0 -3
- data.tar.gz.sig +0 -2
- data/LICENSE +0 -339
- data/README +0 -32
- data/bin/schleuder-fix-gem-dependencies +0 -37
- data/bin/schleuder-init-setup +0 -37
- data/bin/schleuder-migrate-v2.1-to-v2.2 +0 -225
- data/bin/schleuder-newlist +0 -413
- data/contrib/check-expired-keys.rb +0 -60
- data/contrib/mutt-schleuder-colors.rc +0 -10
- data/contrib/mutt-schleuder-resend.vim +0 -24
- data/contrib/smtpserver.rb +0 -76
- data/ext/default-list.conf +0 -149
- data/ext/default-members.conf +0 -7
- data/ext/list.conf.example +0 -14
- data/ext/schleuder.conf +0 -64
- data/lib/schleuder/archiver.rb +0 -46
- data/lib/schleuder/crypt.rb +0 -210
- data/lib/schleuder/errors.rb +0 -5
- data/lib/schleuder/list_config.rb +0 -146
- data/lib/schleuder/log/listlogger.rb +0 -57
- data/lib/schleuder/log/outputter/emailoutputter.rb +0 -120
- data/lib/schleuder/log/outputter/metaemailoutputter.rb +0 -50
- data/lib/schleuder/log/schleuderlogger.rb +0 -34
- data/lib/schleuder/mail.rb +0 -873
- data/lib/schleuder/mailer.rb +0 -26
- data/lib/schleuder/member.rb +0 -69
- data/lib/schleuder/plugin.rb +0 -54
- data/lib/schleuder/processor.rb +0 -363
- data/lib/schleuder/schleuder_config.rb +0 -75
- data/lib/schleuder/storage.rb +0 -84
- data/lib/schleuder/utils.rb +0 -80
- data/man/schleuder-newlist.8 +0 -174
- data/man/schleuder.8 +0 -416
- data/plugins/README +0 -20
- data/plugins/manage_keys_plugin.rb +0 -113
- data/plugins/manage_members_plugin.rb +0 -156
- data/plugins/manage_self_plugin.rb +0 -26
- data/plugins/resend_plugin.rb +0 -35
- data/plugins/sign_this_plugin.rb +0 -14
- data/plugins/version_plugin.rb +0 -12
- metadata.gz.sig +0 -0
@@ -1,225 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
$:.unshift File.dirname(__FILE__) + '/../lib'
|
4
|
-
require 'schleuder'
|
5
|
-
require 'fileutils'
|
6
|
-
require 'yaml'
|
7
|
-
require 'open3'
|
8
|
-
require 'highline/system_extensions'
|
9
|
-
|
10
|
-
def usage
|
11
|
-
puts "Usage: #{File.basename(__FILE__)} [-c /path/to/base/schleuder.conf] /path/to/a/list.config"
|
12
|
-
exit 1
|
13
|
-
end
|
14
|
-
|
15
|
-
usage if ![1,3].include?(ARGV.length)
|
16
|
-
|
17
|
-
if (list_config = ARGV.shift) == '-c'
|
18
|
-
baseconfig = File.expand_path(ARGV.shift)
|
19
|
-
usage unless File.exist?(baseconfig)
|
20
|
-
Schleuder.config(baseconfig)
|
21
|
-
list_config = ARGV.shift
|
22
|
-
end
|
23
|
-
|
24
|
-
usage unless File.exist?(list_config = File.expand_path(list_config))
|
25
|
-
|
26
|
-
def notice(msg)
|
27
|
-
puts msg.fmt
|
28
|
-
end
|
29
|
-
|
30
|
-
def move_listdir(old_dir,old_config)
|
31
|
-
list_dir = old_config['myaddr'].split('@').reverse
|
32
|
-
if old_dir =~ /#{list_dir.join('\/')}/
|
33
|
-
notice("The current directory of the list seems already to match the new style. Did you already migrate that list? As I can't be sure what might be right or wrong, I exit here.")
|
34
|
-
exit 1
|
35
|
-
end
|
36
|
-
|
37
|
-
hostdir = File.expand_path(File.join(Schleuder.config.lists_dir, list_dir.first))
|
38
|
-
FileUtils.mkdir_p(hostdir) unless File.directory?(hostdir)
|
39
|
-
|
40
|
-
FileUtils.mv(old_dir, hostdir)
|
41
|
-
notice("Moved list-dir to #{File.join(hostdir, Schleuder.list.listname)}.")
|
42
|
-
File.expand_path(File.join(Schleuder.config.lists_dir, list_dir.join('/')))
|
43
|
-
end
|
44
|
-
|
45
|
-
def member_key(member)
|
46
|
-
key,msg = member.key
|
47
|
-
unless key
|
48
|
-
notice("Can't find unique key for #{member}. Reason: #{msg}")
|
49
|
-
end
|
50
|
-
member
|
51
|
-
end
|
52
|
-
|
53
|
-
def fix_list_conf(old_config,new_dir,new_conf_path)
|
54
|
-
if old_config.delete('logging').to_s == 'true' && !old_config['lists_logfile'].nil?
|
55
|
-
old_config['log_file'] = old_config.delete('lists_logfile')
|
56
|
-
end
|
57
|
-
|
58
|
-
unless old_config['loglevel'].nil?
|
59
|
-
old_config['log_level'] = old_config.delete('loglevel')
|
60
|
-
end
|
61
|
-
|
62
|
-
if old_config.delete('log_rotate_keep')
|
63
|
-
notice("Schleuder doesn't care about log-rotation anymore, please set up logrotate.conf or similar instead.")
|
64
|
-
end
|
65
|
-
|
66
|
-
old_config['admins'] = old_config.delete('adminaddr').collect do |admin|
|
67
|
-
m = member_key(Schleuder::Member.new(:email => admin))
|
68
|
-
m.to_hash
|
69
|
-
end
|
70
|
-
old_config['key_fingerprint'] = Schleuder.list.key_fingerprint
|
71
|
-
|
72
|
-
File.open(new_conf_path,'w') { |f| f << YAML::dump(old_config.to_hash) }
|
73
|
-
# reload list config
|
74
|
-
Schleuder.list = Schleuder::List.new(old_config['myaddr'])
|
75
|
-
end
|
76
|
-
|
77
|
-
def harden_members
|
78
|
-
Schleuder.list.members = Schleuder.list.members.collect { |member| member_key(member) }
|
79
|
-
end
|
80
|
-
|
81
|
-
def change_pubkey(old_config)
|
82
|
-
_name = old_config['myname']
|
83
|
-
_email = old_config['myaddr']
|
84
|
-
_pass = old_config['gpg_password']
|
85
|
-
|
86
|
-
# Fix for gpgme-ruby >= 1.0.8
|
87
|
-
GPGME::check_version('0.0.0') if GPGME.respond_to?('check_version')
|
88
|
-
|
89
|
-
# Add listname-request@ and listname-ownerhostname as UID.
|
90
|
-
gpg_adduid = "gpg --no-tty --command-fd 0 --status-fd 1 --yes --edit-key #{_email} adduid"
|
91
|
-
Open3.popen3(gpg_adduid) do |stdin, stdout, stderr|
|
92
|
-
owner_done = false
|
93
|
-
request_done = false
|
94
|
-
while line = stdout.readline rescue nil;
|
95
|
-
case line.chomp
|
96
|
-
when '[GNUPG:] GET_LINE keygen.name' then
|
97
|
-
reply = _name
|
98
|
-
when '[GNUPG:] GET_LINE keygen.email' then
|
99
|
-
if !request_done
|
100
|
-
email = _email.sub(/@/, '-request@')
|
101
|
-
request_done = true
|
102
|
-
else
|
103
|
-
email = _email.sub(/@/, '-owner@')
|
104
|
-
end
|
105
|
-
reply = email
|
106
|
-
when '[GNUPG:] GET_LINE keygen.comment' then
|
107
|
-
reply = 'schleuder list'
|
108
|
-
when '[GNUPG:] GET_HIDDEN passphrase.enter' then
|
109
|
-
reply = _pass
|
110
|
-
when '[GNUPG:] GET_LINE keyedit.prompt' then
|
111
|
-
if !owner_done
|
112
|
-
reply = "adduid"
|
113
|
-
owner_done = true
|
114
|
-
else
|
115
|
-
reply = "save"
|
116
|
-
end
|
117
|
-
else
|
118
|
-
reply = nil
|
119
|
-
end
|
120
|
-
#$stderr.puts line
|
121
|
-
if reply
|
122
|
-
#$stderr.puts reply
|
123
|
-
stdin.puts reply
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
# Make list@host the primary UID to avoid confusion.
|
129
|
-
# For some f***** up reason these two time calling gpg do not work in one run.
|
130
|
-
gpg_adduid = "gpg --no-tty --command-fd 0 --status-fd 1 --yes --edit-key #{_email}"
|
131
|
-
Open3.popen3(gpg_adduid) do |stdin, stdout,stderr|
|
132
|
-
uid_done = false
|
133
|
-
primary_done = false
|
134
|
-
while line = stdout.readline rescue nil;
|
135
|
-
case line.chomp
|
136
|
-
when '[GNUPG:] GET_LINE keyedit.prompt' then
|
137
|
-
if ! uid_done
|
138
|
-
reply = "uid 2"
|
139
|
-
uid_done = true
|
140
|
-
elsif ! primary_done
|
141
|
-
reply = "primary"
|
142
|
-
primary_done = true
|
143
|
-
else
|
144
|
-
reply = "save"
|
145
|
-
end
|
146
|
-
when '[GNUPG:] GET_HIDDEN passphrase.enter' then
|
147
|
-
reply = _pass
|
148
|
-
else
|
149
|
-
reply = nil
|
150
|
-
end
|
151
|
-
#$stderr.puts line
|
152
|
-
if reply
|
153
|
-
#$stderr.puts reply
|
154
|
-
stdin.puts reply
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
$stderr.puts
|
159
|
-
notice("Added address-extensions as UIDs to public key of list.")
|
160
|
-
end
|
161
|
-
|
162
|
-
## run
|
163
|
-
|
164
|
-
old_config = YAML.load_file(list_config)
|
165
|
-
|
166
|
-
if Schleuder.config.lists_configfile.end_with?('/')
|
167
|
-
# Common configuration for all lists
|
168
|
-
old_name = File.basename(list_config).gsub(/\.conf\Z/, '')
|
169
|
-
common_list_config_dir = true
|
170
|
-
else
|
171
|
-
# Configuration in list directory
|
172
|
-
old_name = File.basename(File.dirname(list_config))
|
173
|
-
end
|
174
|
-
|
175
|
-
old_config['myname'] ||= old_name
|
176
|
-
Schleuder.list = Schleuder::List.new(old_name)
|
177
|
-
old_dir = File.join(Schleuder.config.lists_dir, old_name)
|
178
|
-
|
179
|
-
files = Dir["#{old_dir}/*"].inject({}) do |files, file|
|
180
|
-
files[File.basename(file)] = [:uid, :gid, :mode].inject({}) do |hash, sym|
|
181
|
-
hash[sym] = File.stat(file).send(sym)
|
182
|
-
hash
|
183
|
-
end
|
184
|
-
files
|
185
|
-
end
|
186
|
-
|
187
|
-
ENV['GNUPGHOME'] = new_dir = move_listdir(old_dir,old_config)
|
188
|
-
ENV.delete('GPG_AGENT_INFO') # might interfer with changing uids
|
189
|
-
|
190
|
-
if common_list_config_dir
|
191
|
-
# Move list configuration file to its new location
|
192
|
-
local_part, domain = old_config['myaddr'].split('@')
|
193
|
-
domain_dir = File.join(Schleuder.config.lists_configfile, domain)
|
194
|
-
FileUtils.mkdir_p domain_dir
|
195
|
-
new_conf_path = "#{domain_dir}/#{local_part}.conf"
|
196
|
-
FileUtils.mv list_config, new_conf_path
|
197
|
-
else
|
198
|
-
new_conf_path = File.join(new_dir, Schleuder.config.lists_configfile)
|
199
|
-
end
|
200
|
-
|
201
|
-
change_pubkey(old_config)
|
202
|
-
fix_list_conf(old_config, new_dir, new_conf_path)
|
203
|
-
harden_members
|
204
|
-
|
205
|
-
# Fix owner/modes if changed
|
206
|
-
files.each do |file, stat|
|
207
|
-
file = File.join(new_dir,file)
|
208
|
-
[file, "#{file}~"].each do |f|
|
209
|
-
if File.exist?(f)
|
210
|
-
File.chown(stat[:uid], stat[:gid], f) if File.stat(f).uid != stat[:uid] || File.stat(f).gid != stat[:gid]
|
211
|
-
File.chmod(stat[:mode], f) if File.stat(f).mode != stat[:mode]
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
puts "There're some manual steps required to finalize the migration:
|
217
|
-
- add two aliases for the list to your MTA:
|
218
|
-
#{Schleuder.list.request_addr}
|
219
|
-
and
|
220
|
-
#{Schleuder.list.owner_addr}
|
221
|
-
|
222
|
-
Running now the Schleuder test routine, which might give additional hints if something might be wrong"
|
223
|
-
|
224
|
-
Schleuder::Processor.test(old_config['myaddr'])
|
225
|
-
|
data/bin/schleuder-newlist
DELETED
@@ -1,413 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
trap ("INT") { exit 1 }
|
4
|
-
|
5
|
-
$:.unshift File.dirname(__FILE__) + '/../lib'
|
6
|
-
require 'schleuder'
|
7
|
-
require 'etc'
|
8
|
-
require 'open3'
|
9
|
-
|
10
|
-
class ListCreator
|
11
|
-
def self.usage
|
12
|
-
puts "Usage:
|
13
|
-
Required options:
|
14
|
-
listname@hostname.tld
|
15
|
-
Not required options (user will be promted unless -nointeractive is set or not run in a terminal),
|
16
|
-
-realname \"Foo List\"
|
17
|
-
-adminaddress listadmin@foobar.com
|
18
|
-
-initmember member1@foobar.com -initmemberkey /path/to/initmember_publickey
|
19
|
-
Optional options (flags on the same line have to be used together):
|
20
|
-
-mailuser mail (The user, which will invoke schleuder from your MTA, if non is supplied, the current user is taken)
|
21
|
-
-mailgroup mail (The group, with which schleuder will be invoked from your MTA, if non is supplied, the current group is taken)
|
22
|
-
-privatekeyfile /path/to/privatekey -publickeyfile /path/to/publickey -passphrase key_passphrase
|
23
|
-
-nointeractive
|
24
|
-
|
25
|
-
#{File.basename($0)} listname@hostname.tld (-realname \"Foo List\") (-adminaddress listadmin@foobar.com) (-initmember member1@foobar.com -initmemberkey /path/to/initmember_publickey) [-privatekeyfile /path/to/privatekey -publickeyfile /path/to/publickey -passphrase key_passphrase] [-nointeractive]"
|
26
|
-
exit 1
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
def self.process(arg)
|
31
|
-
# set safe umask
|
32
|
-
File.umask(0077)
|
33
|
-
|
34
|
-
listname = ARGV.shift.to_s
|
35
|
-
usage unless listname.split('@').size == 2
|
36
|
-
args = Hash.new
|
37
|
-
interactive = STDIN.tty?
|
38
|
-
while nextarg = ARGV.shift
|
39
|
-
if nextarg == '-realname'
|
40
|
-
args[:list_realname] = ARGV.shift
|
41
|
-
elsif nextarg == '-c'
|
42
|
-
Schleuder.config(ARGV.shift)
|
43
|
-
elsif nextarg == '-adminaddress'
|
44
|
-
args[:list_adminaddress] = ARGV.shift
|
45
|
-
elsif nextarg == '-initmember'
|
46
|
-
args[:list_initmember] = ARGV.shift
|
47
|
-
elsif nextarg == '-initmemberkey'
|
48
|
-
args[:list_initmemberkey] = ARGV.shift
|
49
|
-
elsif nextarg == '-privatekeyfile'
|
50
|
-
args[:list_privatekeyfile] = ARGV.shift
|
51
|
-
elsif nextarg == '-publickeyfile'
|
52
|
-
args[:list_publickeyfile] = ARGV.shift
|
53
|
-
elsif nextarg == '-passphrase'
|
54
|
-
args[:list_passphrase] = ARGV.shift
|
55
|
-
elsif nextarg == '-mailuser'
|
56
|
-
args[:mailuser] = ARGV.shift
|
57
|
-
elsif nextarg == '-mailgroup'
|
58
|
-
args[:mailgroup] = ARGV.shift
|
59
|
-
elsif nextarg == '-nointeractive'
|
60
|
-
interactive = false
|
61
|
-
else
|
62
|
-
usage
|
63
|
-
end
|
64
|
-
end
|
65
|
-
Schleuder.log.debug "Calling Processor.newlist(#{listname})"
|
66
|
-
begin
|
67
|
-
ListCreator::create(listname,interactive,args)
|
68
|
-
rescue NewListError => e
|
69
|
-
puts "Error while creating new list: " + e.message
|
70
|
-
exit 1
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
# Creates a new list
|
75
|
-
# listname: name of the list
|
76
|
-
# interactive: Wether we can ask for missing informations. This requires ruby-highline! (Default: true)
|
77
|
-
# args: additional parameters as hash
|
78
|
-
def self.create(listname,interactive=true,args=nil)
|
79
|
-
|
80
|
-
# verfiy all arguments quite in a huge block
|
81
|
-
Schleuder.log.debug "Verifying arguments..."
|
82
|
-
args = Hash.new if args.nil?
|
83
|
-
begin
|
84
|
-
require 'highline/import' if interactive
|
85
|
-
rescue LoadError => ex
|
86
|
-
puts "Unable to load 'highline'.\n\n"
|
87
|
-
puts "Please install the highline gem before trying to use"
|
88
|
-
puts "#{$0} in interactive mode."
|
89
|
-
exit 1
|
90
|
-
end
|
91
|
-
|
92
|
-
# verify basic information
|
93
|
-
Schleuder.log.debug "Verifying basic information..."
|
94
|
-
listname = ListCreator::verify_strvar(listname,interactive,"The listname")
|
95
|
-
listdir = File.join([Schleuder.config.lists_dir, listname.split('@').reverse].flatten)
|
96
|
-
raise NewListError, "List or parts of a list named: #{listname} already exists!" if File.directory?(listdir)
|
97
|
-
list_email = ListCreator::verify_emailvar(listname,interactive,"The lists's email address")
|
98
|
-
list_realname = ListCreator::verify_strvar(args[:list_realname],interactive,"'Realname' (for GPG-key and email-headers)") do |var|
|
99
|
-
raise NewListError, "Realname must be at least 5 characters long (requirement of GnuPG)" if var.size < 5
|
100
|
-
end
|
101
|
-
list_adminaddress = ListCreator::verify_emailvar(args[:list_adminaddress],interactive,"Admin email address")
|
102
|
-
|
103
|
-
raise NewListError,"Lists' email address and the admin address can't be the same" if list_email == list_adminaddress
|
104
|
-
|
105
|
-
# verify keyfiles
|
106
|
-
Schleuder.log.debug "Verifying keyfiles..."
|
107
|
-
list_privatekeyfile = args[:list_privatekeyfile] || 'none'
|
108
|
-
list_publickeyfile = args[:list_publickeyfile] || 'none'
|
109
|
-
list_passphrase = args[:list_passphrase] || 'none'
|
110
|
-
unless args[:mailuser].nil?
|
111
|
-
mailuser = Etc.getpwnam(args[:mailuser]).uid
|
112
|
-
else
|
113
|
-
mailuser = Process::Sys.getuid
|
114
|
-
end
|
115
|
-
unless args[:mailgroup].nil?
|
116
|
-
mailgroup = Etc.getgrnam(args[:mailgroup]).gid
|
117
|
-
else
|
118
|
-
mailgroup = Process::Sys.getuid
|
119
|
-
end
|
120
|
-
unless (list_privatekeyfile == 'none') and
|
121
|
-
(list_publickeyfile == 'none') and
|
122
|
-
(list_passphrase == 'none') then
|
123
|
-
list_privatekeyfile = ListCreator::verify_filevar(
|
124
|
-
args[:list_privatekeyfile] || '',
|
125
|
-
interactive,
|
126
|
-
"the lists' private key file"
|
127
|
-
)
|
128
|
-
list_publickeyfile = ListCreator::verify_filevar(
|
129
|
-
args[:list_publickeyfile] || '',
|
130
|
-
interactive,
|
131
|
-
"the lists' public key file"
|
132
|
-
)
|
133
|
-
list_passphrase = ListCreator::verify_strvar(
|
134
|
-
args[:list_passphrase] || '',
|
135
|
-
interactive,
|
136
|
-
"the lists' key passphrase",
|
137
|
-
false
|
138
|
-
)
|
139
|
-
end
|
140
|
-
|
141
|
-
# Verify init member
|
142
|
-
Schleuder.log.debug "Verifying init member..."
|
143
|
-
list_initmember = ListCreator::verify_emailvar(
|
144
|
-
args[:list_initmember] || '',
|
145
|
-
interactive,
|
146
|
-
"Email address of the lists' initial member"
|
147
|
-
)
|
148
|
-
list_initmemberkey = ListCreator::verify_filevar(
|
149
|
-
args[:list_initmemberkey] || '',
|
150
|
-
interactive,
|
151
|
-
"the public key of the lists' initial member"
|
152
|
-
)
|
153
|
-
Schleuder.log.debug "Arguments verified..."
|
154
|
-
|
155
|
-
Schleuder.log.debug "Initialize list..."
|
156
|
-
list = ListCreator::init_list(listname,listdir)
|
157
|
-
|
158
|
-
Schleuder.log.debug "Set list options..."
|
159
|
-
list.config.myaddr = list_email.to_s
|
160
|
-
list.config.myname = list_realname.to_s
|
161
|
-
|
162
|
-
if list_passphrase == 'none' then
|
163
|
-
list.config.gpg_password = Schleuder::Utils::random_password.to_s
|
164
|
-
else
|
165
|
-
list.config.gpg_password = list_passphrase.to_s
|
166
|
-
end
|
167
|
-
|
168
|
-
if (list_privatekeyfile == 'none' and list_publickeyfile == 'none') then
|
169
|
-
Schleuder.log.debug "Generate list's keypair..."
|
170
|
-
puts "Creating list key, this can take some time..." if interactive
|
171
|
-
ListCreator::generate_fresh_keypair(listdir,list.config,interactive)
|
172
|
-
else
|
173
|
-
Schleuder.log.debug "Import list's keypair..."
|
174
|
-
ListCreator::import_keypair(list,list_privatekeyfile,list_publickeyfile)
|
175
|
-
end
|
176
|
-
if (list_initmember != 'none' and list_initmemberkey != 'none') then
|
177
|
-
Schleuder.log.debug "Add initmember to list..."
|
178
|
-
ListCreator::add_init_member(list,list_initmember,list_initmemberkey)
|
179
|
-
end
|
180
|
-
|
181
|
-
# set the lists key_fingerprint
|
182
|
-
list.config.key_fingerprint = list.key_fingerprint
|
183
|
-
|
184
|
-
# add the admin here, as we should have already imported the key at this point
|
185
|
-
new_admin = Schleuder::Member.new(:email => list_adminaddress.to_s)
|
186
|
-
key, msg = new_admin.key
|
187
|
-
if key
|
188
|
-
new_admin.key_fingerprint = key.subkeys.first.fingerprint
|
189
|
-
list.config.admins = new_admin
|
190
|
-
else
|
191
|
-
raise NewListError,"Could not find a suitable key for the list admin. Reason: #{msg}"
|
192
|
-
end
|
193
|
-
|
194
|
-
# store the config
|
195
|
-
FileUtils.mkdir_p File.dirname(list.configfile)
|
196
|
-
Schleuder.log.debug "Store list config..."
|
197
|
-
list.config = list.config
|
198
|
-
Schleuder.log.debug "Changing ownership..."
|
199
|
-
ListCreator::filepermissions(list, mailuser, mailgroup)
|
200
|
-
Schleuder.log.debug "List successfully created..."
|
201
|
-
ListCreator::print_list_infos(list) if interactive
|
202
|
-
end
|
203
|
-
|
204
|
-
private
|
205
|
-
|
206
|
-
def self.init_list(listname,listdir)
|
207
|
-
require 'fileutils'
|
208
|
-
FileUtils.mkdir_p(listdir)
|
209
|
-
list = Schleuder::List.new(listname,true)
|
210
|
-
ENV['GNUPGHOME'] = listdir
|
211
|
-
list
|
212
|
-
end
|
213
|
-
|
214
|
-
def self.add_init_member(list,list_initmember,list_initmemberkey)
|
215
|
-
if key = Schleuder::Crypt.new(list.config.gpg_password).add_key_from_file(list_initmemberkey).imports.first
|
216
|
-
list.members = Array.new(1,Schleuder::Member.new({ :email => list_initmember, :key_fingerprint => key.fingerprint }))
|
217
|
-
else
|
218
|
-
raise NewListError,"Importing the init member key failed for some reason. Please verify the passed keyfile!"
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
def self.verify_strvar(var,interactive,question, echo=true, &block)
|
223
|
-
if (var.nil? or var.empty?) and interactive then
|
224
|
-
str = question+": "
|
225
|
-
if echo
|
226
|
-
var = ask(str)
|
227
|
-
else
|
228
|
-
var = ask(str) { |question| question.echo = '*' }
|
229
|
-
end
|
230
|
-
end
|
231
|
-
yield(var) if block_given?
|
232
|
-
raise NewListError,"Missing mandatory variable: "+question if (var.nil? or var.empty?)
|
233
|
-
var.to_s
|
234
|
-
end
|
235
|
-
|
236
|
-
def self.verify_emailvar(var,interactive,question)
|
237
|
-
var = ListCreator::verify_strvar(var,interactive,question)
|
238
|
-
begin
|
239
|
-
Schleuder::Utils::verify_addr(question,var)
|
240
|
-
rescue Exception => e
|
241
|
-
raise NewListError,"Mandatory emailaddress (#{question}) is not valid: " + e.message
|
242
|
-
end
|
243
|
-
var
|
244
|
-
end
|
245
|
-
|
246
|
-
def self.verify_filevar(var,interactive,question)
|
247
|
-
if (not var.nil? and not File.exist?(var)) and interactive then
|
248
|
-
var = ask("Filepath for "+question+": ")
|
249
|
-
end
|
250
|
-
raise NewListError,"Missing mandatory file: "+question if (not var.nil? and not File.exist?(var))
|
251
|
-
var.to_s
|
252
|
-
end
|
253
|
-
|
254
|
-
def self.progfunc(hook, what, type, current, total)
|
255
|
-
$stderr.write("#{what}: #{current}/#{total}\r")
|
256
|
-
$stderr.flush
|
257
|
-
end
|
258
|
-
|
259
|
-
|
260
|
-
def self.generate_fresh_keypair(listdir,listconfig,interactive)
|
261
|
-
_name = listconfig.myname
|
262
|
-
_email = listconfig.myaddr
|
263
|
-
_pass = listconfig.gpg_password
|
264
|
-
_type = Schleuder.config.gpg_key_type
|
265
|
-
_length = Schleuder.config.gpg_key_length
|
266
|
-
_sub_type = Schleuder.config.gpg_subkey_type
|
267
|
-
_sub_length = Schleuder.config.gpg_subkey_length
|
268
|
-
if GPGME.respond_to? 'check_version'
|
269
|
-
GPGME::check_version('0.0.0')
|
270
|
-
end
|
271
|
-
GPGME::Ctx.new.genkey(
|
272
|
-
ListCreator::create_gnupg_params_template(_name,_email,_pass,_type,_length,_sub_type,_sub_length),
|
273
|
-
nil,nil
|
274
|
-
)
|
275
|
-
|
276
|
-
# Add listname-request@hostname as UID.
|
277
|
-
gpg_adduid = "gpg --no-tty --command-fd 0 --status-fd 1 --yes --edit-key #{_email} adduid"
|
278
|
-
Open3.popen3(gpg_adduid) do |stdin, stdout|
|
279
|
-
owner_done = false
|
280
|
-
request_done = false
|
281
|
-
while line = stdout.readline rescue nil;
|
282
|
-
case line.chomp
|
283
|
-
when '[GNUPG:] GET_LINE keygen.name' then
|
284
|
-
reply = _name
|
285
|
-
when '[GNUPG:] GET_LINE keygen.email' then
|
286
|
-
if ! request_done
|
287
|
-
email = _email.sub(/@/, '-request@')
|
288
|
-
request_done = true
|
289
|
-
else
|
290
|
-
email = _email.sub(/@/, '-owner@')
|
291
|
-
end
|
292
|
-
reply = email
|
293
|
-
when '[GNUPG:] GET_LINE keygen.comment' then
|
294
|
-
reply = 'schleuder list'
|
295
|
-
when '[GNUPG:] GET_HIDDEN passphrase.enter' then
|
296
|
-
reply = _pass
|
297
|
-
when '[GNUPG:] GET_LINE keyedit.prompt' then
|
298
|
-
if ! owner_done
|
299
|
-
reply = "adduid"
|
300
|
-
owner_done = true
|
301
|
-
else
|
302
|
-
reply = "save"
|
303
|
-
end
|
304
|
-
else
|
305
|
-
reply = nil
|
306
|
-
end
|
307
|
-
$stderr.puts line if $DEBUG
|
308
|
-
if reply
|
309
|
-
$stderr.puts reply if $DEBUG
|
310
|
-
stdin.puts reply
|
311
|
-
end
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
# Make list@host the primary UID to avoid confusion.
|
316
|
-
# For some f***** up reason these two time calling gpg do not work in one run.
|
317
|
-
gpg_adduid = "gpg --no-tty --command-fd 0 --status-fd 1 --yes --edit-key #{_email}"
|
318
|
-
Open3.popen3(gpg_adduid) do |stdin, stdout|
|
319
|
-
uid_done = false
|
320
|
-
primary_done = false
|
321
|
-
while line = stdout.readline rescue nil;
|
322
|
-
case line.chomp
|
323
|
-
when '[GNUPG:] GET_LINE keyedit.prompt' then
|
324
|
-
if ! uid_done
|
325
|
-
reply = "uid 2"
|
326
|
-
uid_done = true
|
327
|
-
elsif ! primary_done
|
328
|
-
reply = "primary"
|
329
|
-
primary_done = true
|
330
|
-
else
|
331
|
-
reply = "save"
|
332
|
-
end
|
333
|
-
when '[GNUPG:] GET_HIDDEN passphrase.enter' then
|
334
|
-
reply = _pass
|
335
|
-
else
|
336
|
-
reply = nil
|
337
|
-
end
|
338
|
-
#$stderr.puts line
|
339
|
-
if reply
|
340
|
-
#$stderr.puts reply
|
341
|
-
stdin.puts reply
|
342
|
-
end
|
343
|
-
end
|
344
|
-
end
|
345
|
-
$stderr.puts
|
346
|
-
end
|
347
|
-
|
348
|
-
def self.import_keypair(list,list_privatekeyfile,list_publickeyfile)
|
349
|
-
crypt = Schleuder::Crypt.new(list.config.gpg_password, :new_keyring => true)
|
350
|
-
Schleuder.log.debug "Importing private key from #{list_privatekeyfile}"
|
351
|
-
crypt.add_key_from_file(list_privatekeyfile)
|
352
|
-
Schleuder.log.debug "Importing public key from #{list_publickeyfile}"
|
353
|
-
crypt.add_key_from_file(list_publickeyfile)
|
354
|
-
end
|
355
|
-
|
356
|
-
def self.create_gnupg_params_template(name,email,pass,type,length,sub_type,sub_length)
|
357
|
-
"<GnupgKeyParms format=\"internal\">
|
358
|
-
Key-Type: #{type}
|
359
|
-
Key-Length: #{length}
|
360
|
-
Subkey-Type: #{sub_type}
|
361
|
-
Subkey-Length: #{sub_length}
|
362
|
-
Name-Real: #{name}
|
363
|
-
Name-Comment: schleuder list
|
364
|
-
Name-Email: #{email}
|
365
|
-
Expire-Date: 0
|
366
|
-
Passphrase: #{pass}
|
367
|
-
</GnupgKeyParms>"
|
368
|
-
end
|
369
|
-
|
370
|
-
def self.filepermissions(list, mailuser, mailgroup)
|
371
|
-
listdir = list.listdir
|
372
|
-
FileUtils.chown(mailuser, mailgroup, listdir)
|
373
|
-
FileUtils.chmod(0700, listdir)
|
374
|
-
Dir.new(listdir).each{ |f|
|
375
|
-
unless f =~ /^\./
|
376
|
-
file = File.join(listdir,f)
|
377
|
-
File.chown(mailuser,mailgroup,file)
|
378
|
-
File.chmod(0600,file)
|
379
|
-
end
|
380
|
-
}
|
381
|
-
FileUtils.chown mailuser, mailgroup, list.configfile
|
382
|
-
FileUtils.chmod 0600, list.configfile
|
383
|
-
# do we have a shared directory?
|
384
|
-
# otherwise it's the listdir itself
|
385
|
-
if Schleuder.config.lists_configfile.end_with?('/')
|
386
|
-
FileUtils.chmod 0750, File.dirname(list.configfile)
|
387
|
-
end
|
388
|
-
if list.config.log_file
|
389
|
-
log_file = list.config.log_file
|
390
|
-
log_file = File.join(listdir, log_file) unless log_file.start_with?('/')
|
391
|
-
FileUtils.chown(mailuser, mailgroup, log_file)
|
392
|
-
FileUtils.chmod(0600, log_file)
|
393
|
-
end
|
394
|
-
end
|
395
|
-
|
396
|
-
def self.print_list_infos(list)
|
397
|
-
puts "A new schleuder list called '#{list.config.myname}' has been created.".fmt
|
398
|
-
puts
|
399
|
-
puts "To get a working list you have to tell your MTA to handle this list. For various examples have a look at <http://schleuder.nadir.org/documentation/creating_lists.html>".fmt
|
400
|
-
puts
|
401
|
-
puts "Lists' key fingerprint:".fmt
|
402
|
-
crypt = Schleuder::Crypt.new(list.config.gpg_password)
|
403
|
-
key = crypt.get_key(list.config.myaddr).first
|
404
|
-
puts Schleuder::Utils::get_pretty_fingerprint(key)
|
405
|
-
end
|
406
|
-
end
|
407
|
-
|
408
|
-
begin
|
409
|
-
ListCreator.process(ARGV)
|
410
|
-
rescue NewListError => e
|
411
|
-
puts "Error while creating new list: " + e.message
|
412
|
-
exit 1
|
413
|
-
end
|