schleuder 2.2.4 → 3.2.2

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.
Files changed (141) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +138 -0
  3. data/Rakefile +136 -0
  4. data/bin/pinentry-clearpassphrase +72 -0
  5. data/bin/schleuder +9 -89
  6. data/bin/schleuder-api-daemon +4 -0
  7. data/db/migrate/20140501103532_create_lists.rb +39 -0
  8. data/db/migrate/20140501112859_create_subscriptions.rb +21 -0
  9. data/db/migrate/201508092100_add_language_to_lists.rb +11 -0
  10. data/db/migrate/20150812165700_change_keywords_admin_only_defaults.rb +8 -0
  11. data/db/migrate/20150813235800_add_forward_all_incoming_to_admins.rb +11 -0
  12. data/db/migrate/201508141727_change_send_encrypted_only_default.rb +8 -0
  13. data/db/migrate/201508222143_add_logfiles_to_keep_to_lists.rb +11 -0
  14. data/db/migrate/201508261723_rename_delivery_disabled_to_delivery_enabled_and_change_default.rb +14 -0
  15. data/db/migrate/201508261815_strip_gpg_passphrase.rb +11 -0
  16. data/db/migrate/201508261827_remove_default_mime.rb +9 -0
  17. data/db/migrate/20160501172700_fix_headers_to_meta_defaults.rb +8 -0
  18. data/db/migrate/20170713215059_add_internal_footer_to_list.rb +11 -0
  19. data/db/schema.rb +62 -0
  20. data/etc/init.d/schleuder-api-daemon +87 -0
  21. data/etc/list-defaults.yml +123 -0
  22. data/etc/postfix/schleuder_sqlite.cf +28 -0
  23. data/etc/schleuder-api-daemon.service +10 -0
  24. data/etc/schleuder.cron.weekly +6 -0
  25. data/etc/schleuder.yml +61 -0
  26. data/lib/schleuder-api-daemon.rb +420 -0
  27. data/lib/schleuder.rb +81 -47
  28. data/lib/schleuder/cli.rb +334 -0
  29. data/lib/schleuder/cli/cert.rb +24 -0
  30. data/lib/schleuder/cli/schleuder_cert_manager.rb +84 -0
  31. data/lib/schleuder/cli/subcommand_fix.rb +11 -0
  32. data/lib/schleuder/conf.rb +131 -0
  33. data/lib/schleuder/errors/active_model_error.rb +15 -0
  34. data/lib/schleuder/errors/base.rb +17 -0
  35. data/lib/schleuder/errors/decryption_failed.rb +16 -0
  36. data/lib/schleuder/errors/fatal_error.rb +13 -0
  37. data/lib/schleuder/errors/file_not_found.rb +14 -0
  38. data/lib/schleuder/errors/invalid_listname.rb +13 -0
  39. data/lib/schleuder/errors/key_adduid_failed.rb +13 -0
  40. data/lib/schleuder/errors/key_generation_failed.rb +16 -0
  41. data/lib/schleuder/errors/keyword_admin_only.rb +13 -0
  42. data/lib/schleuder/errors/list_exists.rb +13 -0
  43. data/lib/schleuder/errors/list_not_found.rb +14 -0
  44. data/lib/schleuder/errors/list_property_missing.rb +14 -0
  45. data/lib/schleuder/errors/listdir_problem.rb +16 -0
  46. data/lib/schleuder/errors/loading_list_settings_failed.rb +14 -0
  47. data/lib/schleuder/errors/message_empty.rb +14 -0
  48. data/lib/schleuder/errors/message_not_from_admin.rb +13 -0
  49. data/lib/schleuder/errors/message_sender_not_subscribed.rb +13 -0
  50. data/lib/schleuder/errors/message_too_big.rb +14 -0
  51. data/lib/schleuder/errors/message_unauthenticated.rb +13 -0
  52. data/lib/schleuder/errors/message_unencrypted.rb +13 -0
  53. data/lib/schleuder/errors/message_unsigned.rb +13 -0
  54. data/lib/schleuder/errors/standard_error.rb +5 -0
  55. data/lib/schleuder/errors/too_many_keys.rb +17 -0
  56. data/lib/schleuder/errors/unknown_list_option.rb +14 -0
  57. data/lib/schleuder/filters/auth_filter.rb +39 -0
  58. data/lib/schleuder/filters/bounces_filter.rb +12 -0
  59. data/lib/schleuder/filters/forward_filter.rb +17 -0
  60. data/lib/schleuder/filters/forward_incoming.rb +13 -0
  61. data/lib/schleuder/filters/hotmail_message_filter.rb +25 -0
  62. data/lib/schleuder/filters/max_message_size.rb +14 -0
  63. data/lib/schleuder/filters/request_filter.rb +26 -0
  64. data/lib/schleuder/filters/send_key_filter.rb +20 -0
  65. data/lib/schleuder/filters/strip_alternative_filter.rb +21 -0
  66. data/lib/schleuder/filters_runner.rb +83 -0
  67. data/lib/schleuder/gpgme/ctx.rb +274 -0
  68. data/lib/schleuder/gpgme/import_status.rb +27 -0
  69. data/lib/schleuder/gpgme/key.rb +212 -0
  70. data/lib/schleuder/gpgme/sub_key.rb +13 -0
  71. data/lib/schleuder/gpgme/user_id.rb +22 -0
  72. data/lib/schleuder/list.rb +318 -127
  73. data/lib/schleuder/list_builder.rb +139 -0
  74. data/lib/schleuder/listlogger.rb +31 -0
  75. data/lib/schleuder/logger.rb +23 -0
  76. data/lib/schleuder/logger_notifications.rb +69 -0
  77. data/lib/schleuder/mail/message.rb +482 -0
  78. data/lib/schleuder/mail/parts_list.rb +9 -0
  79. data/lib/schleuder/plugin_runners/base.rb +91 -0
  80. data/lib/schleuder/plugin_runners/list_plugins_runner.rb +24 -0
  81. data/lib/schleuder/plugin_runners/request_plugins_runner.rb +27 -0
  82. data/lib/schleuder/plugins/attach_listkey.rb +17 -0
  83. data/lib/schleuder/plugins/get_version.rb +7 -0
  84. data/lib/schleuder/plugins/key_management.rb +113 -0
  85. data/lib/schleuder/plugins/list_management.rb +15 -0
  86. data/lib/schleuder/plugins/resend.rb +196 -0
  87. data/lib/schleuder/plugins/sign_this.rb +46 -0
  88. data/lib/schleuder/plugins/subscription_management.rb +140 -0
  89. data/lib/schleuder/runner.rb +130 -0
  90. data/lib/schleuder/subscription.rb +98 -0
  91. data/lib/schleuder/validators/boolean_validator.rb +7 -0
  92. data/lib/schleuder/validators/email_validator.rb +7 -0
  93. data/lib/schleuder/validators/fingerprint_validator.rb +7 -0
  94. data/lib/schleuder/validators/greater_than_zero_validator.rb +7 -0
  95. data/lib/schleuder/validators/no_line_breaks_validator.rb +7 -0
  96. data/lib/schleuder/version.rb +1 -1
  97. data/locales/de.yml +179 -0
  98. data/locales/en.yml +179 -0
  99. metadata +305 -108
  100. checksums.yaml.gz.sig +0 -3
  101. data.tar.gz.sig +0 -2
  102. data/LICENSE +0 -339
  103. data/README +0 -32
  104. data/bin/schleuder-fix-gem-dependencies +0 -37
  105. data/bin/schleuder-init-setup +0 -37
  106. data/bin/schleuder-migrate-v2.1-to-v2.2 +0 -225
  107. data/bin/schleuder-newlist +0 -413
  108. data/contrib/check-expired-keys.rb +0 -60
  109. data/contrib/mutt-schleuder-colors.rc +0 -10
  110. data/contrib/mutt-schleuder-resend.vim +0 -24
  111. data/contrib/smtpserver.rb +0 -76
  112. data/ext/default-list.conf +0 -149
  113. data/ext/default-members.conf +0 -7
  114. data/ext/list.conf.example +0 -14
  115. data/ext/schleuder.conf +0 -64
  116. data/lib/schleuder/archiver.rb +0 -46
  117. data/lib/schleuder/crypt.rb +0 -210
  118. data/lib/schleuder/errors.rb +0 -5
  119. data/lib/schleuder/list_config.rb +0 -146
  120. data/lib/schleuder/log/listlogger.rb +0 -57
  121. data/lib/schleuder/log/outputter/emailoutputter.rb +0 -120
  122. data/lib/schleuder/log/outputter/metaemailoutputter.rb +0 -50
  123. data/lib/schleuder/log/schleuderlogger.rb +0 -34
  124. data/lib/schleuder/mail.rb +0 -873
  125. data/lib/schleuder/mailer.rb +0 -26
  126. data/lib/schleuder/member.rb +0 -69
  127. data/lib/schleuder/plugin.rb +0 -54
  128. data/lib/schleuder/processor.rb +0 -363
  129. data/lib/schleuder/schleuder_config.rb +0 -75
  130. data/lib/schleuder/storage.rb +0 -84
  131. data/lib/schleuder/utils.rb +0 -80
  132. data/man/schleuder-newlist.8 +0 -174
  133. data/man/schleuder.8 +0 -416
  134. data/plugins/README +0 -20
  135. data/plugins/manage_keys_plugin.rb +0 -113
  136. data/plugins/manage_members_plugin.rb +0 -156
  137. data/plugins/manage_self_plugin.rb +0 -26
  138. data/plugins/resend_plugin.rb +0 -35
  139. data/plugins/sign_this_plugin.rb +0 -14
  140. data/plugins/version_plugin.rb +0 -12
  141. 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
-
@@ -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