schleuder 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# We need to install one more gem depending on the used ruby-version.
|
4
|
+
# Unfortunately this isn't possible inside of rubygems, therefore we do it
|
5
|
+
# here.
|
6
|
+
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubygems/dependency_installer.rb'
|
9
|
+
|
10
|
+
inst = Gem::DependencyInstaller.new
|
11
|
+
spec = Gem::Specification.find_by_name 'schleuder'
|
12
|
+
|
13
|
+
begin
|
14
|
+
if RUBY_VERSION < "1.9"
|
15
|
+
name = 'tmail'
|
16
|
+
ver = '=1.2.3.1'
|
17
|
+
else
|
18
|
+
name = 'actionmailer'
|
19
|
+
ver = '=2.3.14'
|
20
|
+
end
|
21
|
+
inst.install name, ver
|
22
|
+
spec.add_dependency name, ver
|
23
|
+
# Write spec back to file, from rubygems/installer.rb
|
24
|
+
File.open(spec.spec_file.untaint, "w") do |f|
|
25
|
+
f << spec.to_ruby_for_cache
|
26
|
+
end
|
27
|
+
rescue Gem::FilePermissionError => e
|
28
|
+
$stderr.puts "Error: #{e.message}"
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$VERBOSE = nil
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
require 'schleuder/utils'
|
7
|
+
require 'highline/system_extensions'
|
8
|
+
|
9
|
+
def usage
|
10
|
+
puts "Usage: #{File.basename(__FILE__)} --gem | /path/to/schleuder"
|
11
|
+
puts "Creates neccessary directories and copies default configurations to /etc/schleuder.\n".fmt
|
12
|
+
end
|
13
|
+
|
14
|
+
def copy(basedir)
|
15
|
+
%w(/etc/schleuder /var/log/schleuder).each do |dir|
|
16
|
+
FileUtils.mkdir(dir) unless File.directory?(dir)
|
17
|
+
end
|
18
|
+
files = Dir.glob(File.join(basedir, 'ext', '*')).reject { |f| ['Rakefile'].include?(f) }
|
19
|
+
FileUtils.cp(files, '/etc/schleuder/')
|
20
|
+
rescue Errno::EACCES => e
|
21
|
+
puts "#{e.message}"
|
22
|
+
puts "Please retry with appropriate privileges!"
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
|
26
|
+
case ARGV.first
|
27
|
+
when nil,/-h|--help/
|
28
|
+
usage
|
29
|
+
exit 1
|
30
|
+
when /--gem/
|
31
|
+
require 'rubygems'
|
32
|
+
spec = Gem::Specification.find_by_name('schleuder')
|
33
|
+
copy(spec.gem_dir)
|
34
|
+
else
|
35
|
+
copy(ARGV.first)
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,205 @@
|
|
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)
|
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(File.join(new_dir, Schleuder.config.lists_configfile),'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
|
+
|
165
|
+
old_config = YAML.load_file(list_config)
|
166
|
+
old_config['myname']||=File.basename(File.dirname(list_config))
|
167
|
+
Schleuder.list = Schleuder::List.new(File.basename(File.dirname(list_config)))
|
168
|
+
old_dir = File.dirname(list_config)
|
169
|
+
|
170
|
+
files = Dir["#{old_dir}/*"].inject({}) do |files, file|
|
171
|
+
files[File.basename(file)] = [:uid, :gid, :mode].inject({}) do |hash, sym|
|
172
|
+
hash[sym] = File.stat(file).send(sym)
|
173
|
+
hash
|
174
|
+
end
|
175
|
+
files
|
176
|
+
end
|
177
|
+
|
178
|
+
ENV['GNUPGHOME'] = new_dir = move_listdir(old_dir,old_config)
|
179
|
+
ENV.delete('GPG_AGENT_INFO') # might interfer with changing uids
|
180
|
+
|
181
|
+
change_pubkey(old_config)
|
182
|
+
fix_list_conf(old_config, new_dir)
|
183
|
+
harden_members
|
184
|
+
|
185
|
+
# Fix owner/modes if changed
|
186
|
+
files.each do |file, stat|
|
187
|
+
file = File.join(new_dir,file)
|
188
|
+
[file, "#{file}~"].each do |f|
|
189
|
+
if File.exist?(f)
|
190
|
+
File.chown(stat[:uid], stat[:gid], f) if File.stat(f).uid != stat[:uid] || File.stat(f).gid != stat[:gid]
|
191
|
+
File.chmod(stat[:mode], f) if File.stat(f).mode != stat[:mode]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
puts "There're some manual steps required to finalize the migration:
|
197
|
+
- add two aliases for the list to your MTA:
|
198
|
+
#{Schleuder.list.request_addr}
|
199
|
+
and
|
200
|
+
#{Schleuder.list.owner_addr}
|
201
|
+
|
202
|
+
Running now the Schleuder test routine, which might give additional hints if something might be wrong"
|
203
|
+
|
204
|
+
Schleuder::Processor.test(old_config['myaddr'])
|
205
|
+
|
@@ -0,0 +1,384 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
4
|
+
require 'schleuder'
|
5
|
+
require 'etc'
|
6
|
+
require 'open3'
|
7
|
+
|
8
|
+
class ListCreator
|
9
|
+
def self.usage
|
10
|
+
puts "Usage:
|
11
|
+
Required options:
|
12
|
+
listname@hostname.tld
|
13
|
+
Not required options (user will be promted unless -nointeractive is set or not run in a terminal),
|
14
|
+
-realname \"Foo List\"
|
15
|
+
-adminaddress listadmin@foobar.com
|
16
|
+
-initmember member1@foobar.com -initmemberkey /path/to/initmember_publickey
|
17
|
+
Optional options (flags on the same line have to be used together):
|
18
|
+
-mailuser mail (The user, which will invoke schleuder from your MTA, if non is supplied, the current user is taken)
|
19
|
+
-privatekeyfile /path/to/privatekey -publickeyfile /path/to/publickey -passphrase key_passphrase
|
20
|
+
-nointeractive
|
21
|
+
|
22
|
+
#{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]"
|
23
|
+
exit 1
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def self.process(arg)
|
28
|
+
# set safe umask
|
29
|
+
File.umask(0077)
|
30
|
+
|
31
|
+
listname = ARGV.shift.to_s
|
32
|
+
usage unless listname.split('@').size == 2
|
33
|
+
args = Hash.new
|
34
|
+
interactive = STDIN.tty?
|
35
|
+
while nextarg = ARGV.shift
|
36
|
+
if nextarg == '-realname'
|
37
|
+
args[:list_realname] = ARGV.shift
|
38
|
+
elsif nextarg == '-c'
|
39
|
+
Schleuder.config(ARGV.shift)
|
40
|
+
elsif nextarg == '-adminaddress'
|
41
|
+
args[:list_adminaddress] = ARGV.shift
|
42
|
+
elsif nextarg == '-initmember'
|
43
|
+
args[:list_initmember] = ARGV.shift
|
44
|
+
elsif nextarg == '-initmemberkey'
|
45
|
+
args[:list_initmemberkey] = ARGV.shift
|
46
|
+
elsif nextarg == '-privatekeyfile'
|
47
|
+
args[:list_privatekeyfile] = ARGV.shift
|
48
|
+
elsif nextarg == '-publickeyfile'
|
49
|
+
args[:list_publickeyfile] = ARGV.shift
|
50
|
+
elsif nextarg == '-passphrase'
|
51
|
+
args[:list_passphrase] = ARGV.shift
|
52
|
+
elsif nextarg == '-mailuser'
|
53
|
+
args[:mailuser] = ARGV.shift
|
54
|
+
elsif nextarg == '-nointeractive'
|
55
|
+
interactive = false
|
56
|
+
else
|
57
|
+
usage
|
58
|
+
end
|
59
|
+
end
|
60
|
+
Schleuder.log.debug "Calling Processor.newlist(#{listname})"
|
61
|
+
begin
|
62
|
+
ListCreator::create(listname,interactive,args)
|
63
|
+
rescue NewListError => e
|
64
|
+
puts "Error while creating new list: " + e.message
|
65
|
+
exit 1
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Creates a new list
|
70
|
+
# listname: name of the list
|
71
|
+
# interactive: Wether we can ask for missing informations. This requires ruby-highline! (Default: true)
|
72
|
+
# args: additional parameters as hash
|
73
|
+
def self.create(listname,interactive=true,args=nil)
|
74
|
+
|
75
|
+
# verfiy all arguments quite in a huge block
|
76
|
+
Schleuder.log.debug "Verifying arguments..."
|
77
|
+
args = Hash.new if args.nil?
|
78
|
+
begin
|
79
|
+
require 'highline/import' if interactive
|
80
|
+
rescue LoadError => ex
|
81
|
+
puts "Unable to load 'highline'.\n\n"
|
82
|
+
puts "Please install the highline gem before trying to use"
|
83
|
+
puts "#{$0} in interactive mode."
|
84
|
+
exit 1
|
85
|
+
end
|
86
|
+
|
87
|
+
# verify basic information
|
88
|
+
Schleuder.log.debug "Verifying basic information..."
|
89
|
+
listname = ListCreator::verify_strvar(listname,interactive,"The listname")
|
90
|
+
listdir = File.join([Schleuder.config.lists_dir, listname.split('@').reverse].flatten)
|
91
|
+
raise NewListError, "List or parts of a list named: #{listname} already exists!" if File.directory?(listdir)
|
92
|
+
list_email = ListCreator::verify_emailvar(listname,interactive,"The lists's email address")
|
93
|
+
list_realname = ListCreator::verify_strvar(args[:list_realname],interactive,"'Realname' (for GPG-key and email-headers)")
|
94
|
+
list_adminaddress = ListCreator::verify_emailvar(args[:list_adminaddress],interactive,"Admin email address")
|
95
|
+
|
96
|
+
raise NewListError,"Lists' email address and the admin address can't be the same" if list_email == list_adminaddress
|
97
|
+
|
98
|
+
# verify keyfiles
|
99
|
+
Schleuder.log.debug "Verifying keyfiles..."
|
100
|
+
list_privatekeyfile = args[:list_privatekeyfile] || 'none'
|
101
|
+
list_publickeyfile = args[:list_publickeyfile] || 'none'
|
102
|
+
list_passphrase = args[:list_passphrase] || 'none'
|
103
|
+
unless args[:mailuser].nil?
|
104
|
+
mailuser = Etc.getpwnam(args[:mailuser]).uid
|
105
|
+
else
|
106
|
+
mailuser = Process::Sys.getuid
|
107
|
+
end
|
108
|
+
unless (list_privatekeyfile == 'none') and
|
109
|
+
(list_publickeyfile == 'none') and
|
110
|
+
(list_passphrase == 'none') then
|
111
|
+
list_privatekeyfile = ListCreator::verify_filevar(
|
112
|
+
args[:list_privatekeyfile] || '',
|
113
|
+
interactive,
|
114
|
+
"the lists' private key file"
|
115
|
+
)
|
116
|
+
list_publickeyfile = ListCreator::verify_filevar(
|
117
|
+
args[:list_publickeyfile] || '',
|
118
|
+
interactive,
|
119
|
+
"the lists' public key file"
|
120
|
+
)
|
121
|
+
list_passphrase = ListCreator::verify_strvar(
|
122
|
+
args[:list_passphrase] || '',
|
123
|
+
interactive,
|
124
|
+
"the lists' key passphrase",
|
125
|
+
false
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Verify init member
|
130
|
+
Schleuder.log.debug "Verifying init member..."
|
131
|
+
list_initmember = ListCreator::verify_emailvar(
|
132
|
+
args[:list_initmember] || '',
|
133
|
+
interactive,
|
134
|
+
"Email address of the lists' initial member"
|
135
|
+
)
|
136
|
+
list_initmemberkey = ListCreator::verify_filevar(
|
137
|
+
args[:list_initmemberkey] || '',
|
138
|
+
interactive,
|
139
|
+
"the public key of the lists' initial member"
|
140
|
+
)
|
141
|
+
Schleuder.log.debug "Arguments verified..."
|
142
|
+
|
143
|
+
Schleuder.log.debug "Initialize list..."
|
144
|
+
list = ListCreator::init_list(listname,listdir)
|
145
|
+
|
146
|
+
Schleuder.log.debug "Set list options..."
|
147
|
+
list.config.myaddr = list_email.to_s
|
148
|
+
list.config.myname = list_realname.to_s
|
149
|
+
|
150
|
+
if list_passphrase == 'none' then
|
151
|
+
list.config.gpg_password = Schleuder::Utils::random_password.to_s
|
152
|
+
else
|
153
|
+
list.config.gpg_password = list_passphrase.to_s
|
154
|
+
end
|
155
|
+
|
156
|
+
if (list_privatekeyfile == 'none' and list_publickeyfile == 'none') then
|
157
|
+
Schleuder.log.debug "Generate list's keypair..."
|
158
|
+
puts "Creating list key, this can take some time..." if interactive
|
159
|
+
ListCreator::generate_fresh_keypair(listdir,list.config,interactive)
|
160
|
+
else
|
161
|
+
Schleuder.log.debug "Import list's keypair..."
|
162
|
+
ListCreator::import_keypair(list,list_privatekeyfile,list_publickeyfile)
|
163
|
+
end
|
164
|
+
if (list_initmember != 'none' and list_initmemberkey != 'none') then
|
165
|
+
Schleuder.log.debug "Add initmember to list..."
|
166
|
+
ListCreator::add_init_member(list,list_initmember,list_initmemberkey)
|
167
|
+
end
|
168
|
+
|
169
|
+
# set the lists key_fingerprint
|
170
|
+
list.config.key_fingerprint = list.key_fingerprint
|
171
|
+
|
172
|
+
# add the admin here, as we should have already imported the key at this point
|
173
|
+
new_admin = Schleuder::Member.new(:email => list_adminaddress.to_s)
|
174
|
+
key, msg = new_admin.key
|
175
|
+
if key
|
176
|
+
new_admin.key_fingerprint = key.subkeys.first.fingerprint
|
177
|
+
list.config.admins = new_admin
|
178
|
+
else
|
179
|
+
raise NewListError,"Could not find a suitable key for the list admin. Reason: #{msg}"
|
180
|
+
end
|
181
|
+
|
182
|
+
# store the config
|
183
|
+
Schleuder.log.debug "Store list config..."
|
184
|
+
list.config = list.config
|
185
|
+
Schleuder.log.debug "Changing ownership..."
|
186
|
+
ListCreator::filepermissions(listdir,mailuser)
|
187
|
+
Schleuder.log.debug "List successfully created..."
|
188
|
+
ListCreator::print_list_infos(list) if interactive
|
189
|
+
end
|
190
|
+
|
191
|
+
private
|
192
|
+
|
193
|
+
def self.init_list(listname,listdir)
|
194
|
+
require 'fileutils'
|
195
|
+
FileUtils.mkdir_p(listdir)
|
196
|
+
list = Schleuder::List.new(listname,true)
|
197
|
+
ENV['GNUPGHOME'] = listdir
|
198
|
+
list
|
199
|
+
end
|
200
|
+
|
201
|
+
def self.add_init_member(list,list_initmember,list_initmemberkey)
|
202
|
+
if key = Schleuder::Crypt.new(list.config.gpg_password).add_key_from_file(list_initmemberkey).imports.first
|
203
|
+
list.members = Array.new(1,Schleuder::Member.new({ :email => list_initmember, :key_fingerprint => key.fingerprint }))
|
204
|
+
else
|
205
|
+
raise NewListError,"Importing the init member key failed for some reason. Please verify the passed keyfile!"
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def self.verify_strvar(var,interactive,question, echo=true)
|
210
|
+
if (var.nil? or var.empty?) and interactive then
|
211
|
+
str = question+": "
|
212
|
+
if echo
|
213
|
+
var = ask(str)
|
214
|
+
else
|
215
|
+
var = ask(str) { |question| question.echo = '*' }
|
216
|
+
end
|
217
|
+
end
|
218
|
+
raise NewListError,"Missing mandatory variable: "+question if (var.nil? or var.empty?)
|
219
|
+
var
|
220
|
+
end
|
221
|
+
|
222
|
+
def self.verify_emailvar(var,interactive,question)
|
223
|
+
var = ListCreator::verify_strvar(var,interactive,question)
|
224
|
+
begin
|
225
|
+
Schleuder::Utils::verify_addr(question,var)
|
226
|
+
rescue Exception => e
|
227
|
+
raise NewListError,"Mandatory emailaddress (#{question}) is not valid: " + e.message
|
228
|
+
end
|
229
|
+
var
|
230
|
+
end
|
231
|
+
|
232
|
+
def self.verify_filevar(var,interactive,question)
|
233
|
+
if (not var.nil? and not File.exist?(var)) and interactive then
|
234
|
+
var = ask("Filepath for "+question+": ")
|
235
|
+
end
|
236
|
+
raise NewListError,"Missing mandatory file: "+question if (not var.nil? and not File.exist?(var))
|
237
|
+
var
|
238
|
+
end
|
239
|
+
|
240
|
+
def self.progfunc(hook, what, type, current, total)
|
241
|
+
$stderr.write("#{what}: #{current}/#{total}\r")
|
242
|
+
$stderr.flush
|
243
|
+
end
|
244
|
+
|
245
|
+
|
246
|
+
def self.generate_fresh_keypair(listdir,listconfig,interactive)
|
247
|
+
_name = listconfig.myname
|
248
|
+
_email = listconfig.myaddr
|
249
|
+
_pass = listconfig.gpg_password
|
250
|
+
_type = Schleuder.config.gpg_key_type
|
251
|
+
_length = Schleuder.config.gpg_key_length
|
252
|
+
_sub_type = Schleuder.config.gpg_subkey_type
|
253
|
+
_sub_length = Schleuder.config.gpg_subkey_length
|
254
|
+
if GPGME.respond_to? 'check_version'
|
255
|
+
GPGME::check_version('0.0.0')
|
256
|
+
end
|
257
|
+
GPGME::Ctx.new.genkey(
|
258
|
+
ListCreator::create_gnupg_params_template(_name,_email,_pass,_type,_length,_sub_type,_sub_length),
|
259
|
+
nil,nil
|
260
|
+
)
|
261
|
+
|
262
|
+
# Add listname-request@hostname as UID.
|
263
|
+
gpg_adduid = "gpg --no-tty --command-fd 0 --status-fd 1 --yes --edit-key #{_email} adduid"
|
264
|
+
Open3.popen3(gpg_adduid) do |stdin, stdout|
|
265
|
+
owner_done = false
|
266
|
+
request_done = false
|
267
|
+
while line = stdout.readline rescue nil;
|
268
|
+
case line.chomp
|
269
|
+
when '[GNUPG:] GET_LINE keygen.name' then
|
270
|
+
reply = _name
|
271
|
+
when '[GNUPG:] GET_LINE keygen.email' then
|
272
|
+
if ! request_done
|
273
|
+
email = _email.sub(/@/, '-request@')
|
274
|
+
request_done = true
|
275
|
+
else
|
276
|
+
email = _email.sub(/@/, '-owner@')
|
277
|
+
end
|
278
|
+
reply = email
|
279
|
+
when '[GNUPG:] GET_LINE keygen.comment' then
|
280
|
+
reply = 'schleuder list'
|
281
|
+
when '[GNUPG:] GET_HIDDEN passphrase.enter' then
|
282
|
+
reply = _pass
|
283
|
+
when '[GNUPG:] GET_LINE keyedit.prompt' then
|
284
|
+
if ! owner_done
|
285
|
+
reply = "adduid"
|
286
|
+
owner_done = true
|
287
|
+
else
|
288
|
+
reply = "save"
|
289
|
+
end
|
290
|
+
else
|
291
|
+
reply = nil
|
292
|
+
end
|
293
|
+
#$stderr.puts line
|
294
|
+
if reply
|
295
|
+
#$stderr.puts reply
|
296
|
+
stdin.puts reply
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# Make list@host the primary UID to avoid confusion.
|
302
|
+
# For some f***** up reason these two time calling gpg do not work in one run.
|
303
|
+
gpg_adduid = "gpg --no-tty --command-fd 0 --status-fd 1 --yes --edit-key #{_email}"
|
304
|
+
Open3.popen3(gpg_adduid) do |stdin, stdout|
|
305
|
+
uid_done = false
|
306
|
+
primary_done = false
|
307
|
+
while line = stdout.readline rescue nil;
|
308
|
+
case line.chomp
|
309
|
+
when '[GNUPG:] GET_LINE keyedit.prompt' then
|
310
|
+
if ! uid_done
|
311
|
+
reply = "uid 2"
|
312
|
+
uid_done = true
|
313
|
+
elsif ! primary_done
|
314
|
+
reply = "primary"
|
315
|
+
primary_done = true
|
316
|
+
else
|
317
|
+
reply = "save"
|
318
|
+
end
|
319
|
+
when '[GNUPG:] GET_HIDDEN passphrase.enter' then
|
320
|
+
reply = _pass
|
321
|
+
else
|
322
|
+
reply = nil
|
323
|
+
end
|
324
|
+
#$stderr.puts line
|
325
|
+
if reply
|
326
|
+
#$stderr.puts reply
|
327
|
+
stdin.puts reply
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
$stderr.puts
|
332
|
+
end
|
333
|
+
|
334
|
+
def self.import_keypair(list,list_privatekeyfile,list_publickeyfile)
|
335
|
+
crypt = Schleuder::Crypt.new(list.config.gpg_password)
|
336
|
+
Schleuder.log.debug "Importing private key from #{list_privatekeyfile}"
|
337
|
+
crypt.add_key_from_file(list_privatekeyfile)
|
338
|
+
Schleuder.log.debug "Importing public key from #{list_publickeyfile}"
|
339
|
+
crypt.add_key_from_file(list_publickeyfile)
|
340
|
+
end
|
341
|
+
|
342
|
+
def self.create_gnupg_params_template(name,email,pass,type,length,sub_type,sub_length)
|
343
|
+
"<GnupgKeyParms format=\"internal\">
|
344
|
+
Key-Type: #{type}
|
345
|
+
Key-Length: #{length}
|
346
|
+
Subkey-Type: #{sub_type}
|
347
|
+
Subkey-Length: #{sub_length}
|
348
|
+
Name-Real: #{name}
|
349
|
+
Name-Comment: schleuder list
|
350
|
+
Name-Email: #{email}
|
351
|
+
Expire-Date: 0
|
352
|
+
Passphrase: #{pass}
|
353
|
+
</GnupgKeyParms>"
|
354
|
+
end
|
355
|
+
|
356
|
+
def self.filepermissions(listdir, mailuser)
|
357
|
+
File.chown(mailuser,nil,listdir)
|
358
|
+
File.chmod(0700,listdir)
|
359
|
+
Dir.new(listdir).each{ |f|
|
360
|
+
unless f =~ /^\./
|
361
|
+
File.chown(mailuser,nil,listdir+"/"+f)
|
362
|
+
File.chmod(0600)
|
363
|
+
end
|
364
|
+
}
|
365
|
+
end
|
366
|
+
|
367
|
+
def self.print_list_infos(list)
|
368
|
+
puts "A new schleuder list called '#{list.config.myname}' has been created.".fmt
|
369
|
+
puts
|
370
|
+
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
|
371
|
+
puts
|
372
|
+
puts "Lists' key fingerprint:".fmt
|
373
|
+
crypt = Schleuder::Crypt.new(list.config.gpg_password)
|
374
|
+
key = crypt.get_key(list.config.myaddr).first
|
375
|
+
puts Schleuder::Utils::get_pretty_fingerprint(key)
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
begin
|
380
|
+
ListCreator.process(ARGV)
|
381
|
+
rescue NewListError => e
|
382
|
+
puts "Error while creating new list: " + e.message
|
383
|
+
exit 1
|
384
|
+
end
|