schleuder 2.2.4 → 3.2.2

Sign up to get free protection for your applications and to get access to all the features.
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