schleuder 2.2.3 → 2.2.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c37622657ee9683d0d006af23a4fb74d53c1c697
4
+ data.tar.gz: 992426df30d2c0de1e97a9d9b611fc5dbc2d1557
5
+ SHA512:
6
+ metadata.gz: 8a4fa65cbe451d2880ef8f38201565c5672c8f41ebff22f8579f1e2ce3aef44f6aeb043e3d93610a55450e7296341ed8689bcf8bfc96dd40847b5d7ce1e987f5
7
+ data.tar.gz: 5238664faab3274a9803bc11a9ef0a91f0c46392a825c7cfe2e040efd0cfc1b3ea2d09fa2982ac8ef9419e3ba13a0ec2a6d81bed2f484fa5846a6a5cec7c666d
@@ -0,0 +1,3 @@
1
+ k�X
2
+ W
3
+ �5
data.tar.gz.sig CHANGED
Binary file
@@ -50,7 +50,7 @@ def member_key(member)
50
50
  member
51
51
  end
52
52
 
53
- def fix_list_conf(old_config,new_dir)
53
+ def fix_list_conf(old_config,new_dir,new_conf_path)
54
54
  if old_config.delete('logging').to_s == 'true' && !old_config['lists_logfile'].nil?
55
55
  old_config['log_file'] = old_config.delete('lists_logfile')
56
56
  end
@@ -69,7 +69,7 @@ def fix_list_conf(old_config,new_dir)
69
69
  end
70
70
  old_config['key_fingerprint'] = Schleuder.list.key_fingerprint
71
71
 
72
- File.open(File.join(new_dir, Schleuder.config.lists_configfile),'w') { |f| f << YAML::dump(old_config.to_hash) }
72
+ File.open(new_conf_path,'w') { |f| f << YAML::dump(old_config.to_hash) }
73
73
  # reload list config
74
74
  Schleuder.list = Schleuder::List.new(old_config['myaddr'])
75
75
  end
@@ -161,11 +161,20 @@ end
161
161
 
162
162
  ## run
163
163
 
164
-
165
164
  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)
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)
169
178
 
170
179
  files = Dir["#{old_dir}/*"].inject({}) do |files, file|
171
180
  files[File.basename(file)] = [:uid, :gid, :mode].inject({}) do |hash, sym|
@@ -178,8 +187,19 @@ end
178
187
  ENV['GNUPGHOME'] = new_dir = move_listdir(old_dir,old_config)
179
188
  ENV.delete('GPG_AGENT_INFO') # might interfer with changing uids
180
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
+
181
201
  change_pubkey(old_config)
182
- fix_list_conf(old_config, new_dir)
202
+ fix_list_conf(old_config, new_dir, new_conf_path)
183
203
  harden_members
184
204
 
185
205
  # Fix owner/modes if changed
@@ -18,6 +18,7 @@ class ListCreator
18
18
  -initmember member1@foobar.com -initmemberkey /path/to/initmember_publickey
19
19
  Optional options (flags on the same line have to be used together):
20
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)
21
22
  -privatekeyfile /path/to/privatekey -publickeyfile /path/to/publickey -passphrase key_passphrase
22
23
  -nointeractive
23
24
 
@@ -53,6 +54,8 @@ class ListCreator
53
54
  args[:list_passphrase] = ARGV.shift
54
55
  elsif nextarg == '-mailuser'
55
56
  args[:mailuser] = ARGV.shift
57
+ elsif nextarg == '-mailgroup'
58
+ args[:mailgroup] = ARGV.shift
56
59
  elsif nextarg == '-nointeractive'
57
60
  interactive = false
58
61
  else
@@ -109,6 +112,11 @@ class ListCreator
109
112
  else
110
113
  mailuser = Process::Sys.getuid
111
114
  end
115
+ unless args[:mailgroup].nil?
116
+ mailgroup = Etc.getgrnam(args[:mailgroup]).gid
117
+ else
118
+ mailgroup = Process::Sys.getuid
119
+ end
112
120
  unless (list_privatekeyfile == 'none') and
113
121
  (list_publickeyfile == 'none') and
114
122
  (list_passphrase == 'none') then
@@ -184,10 +192,11 @@ class ListCreator
184
192
  end
185
193
 
186
194
  # store the config
195
+ FileUtils.mkdir_p File.dirname(list.configfile)
187
196
  Schleuder.log.debug "Store list config..."
188
197
  list.config = list.config
189
198
  Schleuder.log.debug "Changing ownership..."
190
- ListCreator::filepermissions(list, mailuser)
199
+ ListCreator::filepermissions(list, mailuser, mailgroup)
191
200
  Schleuder.log.debug "List successfully created..."
192
201
  ListCreator::print_list_infos(list) if interactive
193
202
  end
@@ -221,7 +230,7 @@ class ListCreator
221
230
  end
222
231
  yield(var) if block_given?
223
232
  raise NewListError,"Missing mandatory variable: "+question if (var.nil? or var.empty?)
224
- var
233
+ var.to_s
225
234
  end
226
235
 
227
236
  def self.verify_emailvar(var,interactive,question)
@@ -239,7 +248,7 @@ class ListCreator
239
248
  var = ask("Filepath for "+question+": ")
240
249
  end
241
250
  raise NewListError,"Missing mandatory file: "+question if (not var.nil? and not File.exist?(var))
242
- var
251
+ var.to_s
243
252
  end
244
253
 
245
254
  def self.progfunc(hook, what, type, current, total)
@@ -358,22 +367,29 @@ Passphrase: #{pass}
358
367
  </GnupgKeyParms>"
359
368
  end
360
369
 
361
- def self.filepermissions(list, mailuser)
370
+ def self.filepermissions(list, mailuser, mailgroup)
362
371
  listdir = list.listdir
363
- dirs = [File.dirname(listdir), listdir]
364
- FileUtils.chown mailuser, nil, dirs
365
- FileUtils.chmod 0700, dirs
372
+ FileUtils.chown(mailuser, mailgroup, listdir)
373
+ FileUtils.chmod(0700, listdir)
366
374
  Dir.new(listdir).each{ |f|
367
375
  unless f =~ /^\./
368
- File.chown(mailuser,nil,listdir+"/"+f)
369
- File.chmod(0600,listdir+"/"+f)
376
+ file = File.join(listdir,f)
377
+ File.chown(mailuser,mailgroup,file)
378
+ File.chmod(0600,file)
370
379
  end
371
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
372
388
  if list.config.log_file
373
389
  log_file = list.config.log_file
374
390
  log_file = File.join(listdir, log_file) unless log_file.start_with?('/')
375
- FileUtils.chown mailuser, nil, log_file
376
- FileUtils.chmod 0600, log_file
391
+ FileUtils.chown(mailuser, mailgroup, log_file)
392
+ FileUtils.chmod(0600, log_file)
377
393
  end
378
394
  end
379
395
 
@@ -24,7 +24,7 @@ listname = ARGV.first
24
24
  Schleuder.list = List.new(listname)
25
25
 
26
26
  now = Time.now
27
- checkdate = now + 120960000 # two weeks
27
+ checkdate = now + (60 * 60 * 24 * 14) # two weeks
28
28
  crypt = Crypt.new('')
29
29
  msg = ''
30
30
  unusable = []
@@ -54,7 +54,7 @@ unusable.each do |key,trust|
54
54
  end
55
55
 
56
56
  unless msg.empty?
57
- prefix = "Checking the public keys present in the keyring of list #{listname} for usability gave the following result:".fmt
57
+ prefix = "Checking the public keys present in the keyring of list #{listname} for usability gave the following result:".fmt(72)
58
58
  Schleuder.log.notify_admin('keys', prefix + "\n\n" + msg)
59
59
  end
60
60
 
@@ -88,7 +88,10 @@
88
88
  #log_io: false
89
89
  #
90
90
  # Log to a file? To enable specify a filename, optionally with full path.
91
- #log_file: false
91
+ # If you specify a directory (ending with '/'), the file will be named
92
+ # "$LISTNAME.log" in that directory.
93
+ # To disable logging to a file set to false.
94
+ #log_file: 'list.log'
92
95
  #
93
96
  # speaks for itself, no?
94
97
  #public_footer:
@@ -13,7 +13,7 @@
13
13
  #gpg_key_type: RSA
14
14
  #
15
15
  # Set the length of a key we might create for new lists.
16
- #gpg_key_length: 2048
16
+ #gpg_key_length: 4096
17
17
  #
18
18
  # Set the type of the subkey of a key we might create
19
19
  # for new lists.
@@ -21,9 +21,12 @@
21
21
  #
22
22
  # Set the length of the subkey of a key we might create
23
23
  # for new lists.
24
- #gpg_subkey_length: 2048
24
+ #gpg_subkey_length: 4096
25
25
  #
26
- # Name of the per list config file.
26
+ # Name of the per list config file. Either:
27
+ # - a file name that resides in the list data directory,
28
+ # - a directory, ending with '/' holding list configs as
29
+ # "$DOMAIN/$LISTNAME.conf".
27
30
  #lists_configfile: list.conf
28
31
  #
29
32
  # Name of the per list file containing all members and their
@@ -38,7 +41,8 @@
38
41
  # Location of the various schleuderlists' directory.
39
42
  #lists_dir: /var/schleuderlists
40
43
  #
41
- # Location of the global logfile.
44
+ # Location of the global logfile. Specify "syslog" to log through
45
+ # the syslog(3) facility.
42
46
  #log_file: /var/log/schleuder/schleuder.log
43
47
  #
44
48
  # Global schleuder log level, might change after the list config
@@ -48,7 +52,9 @@
48
52
  #
49
53
  # Location of schleuder plugins. Note: the following notion
50
54
  # isn't valid. You have to provide a fully qualified path.
51
- #plugins_dir = schleuder_base + '/plugins'
55
+ # Multiple plugins directory are supported.
56
+ #plugins_dir:
57
+ #-schleuder_base + '/plugins'
52
58
  #
53
59
  # The super administrator of this schleuder installation. This
54
60
  # address will receive all notices which can'tbe delivered to a certain list
@@ -91,7 +91,7 @@ module Schleuder
91
91
  # TODO: return mailadresses or keys instead of signature-objects?
92
92
  [output, in_encrypted, in_signed]
93
93
  rescue GPGME::Error::General => exc
94
- Schleuder.log.warn = "gpgme returned a general error. Most likely this is due to unexpected input, but as you never know here's the input and the exception:\ninput:\n#{str.inspect}\n#{exc.to_s}\n#{exc.backtrace[0..9].join("\n")}"
94
+ Schleuder.log.warn "gpgme returned a general error. Most likely this is due to unexpected input, but as you never know here's the input and the exception:\ninput:\n#{str.inspect}\n#{exc.to_s}\n#{exc.backtrace[0..9].join("\n")}"
95
95
  [str, nil, nil]
96
96
  end
97
97
 
@@ -88,10 +88,27 @@ module Schleuder
88
88
  else
89
89
  @config = ListConfig.new(data)
90
90
  end
91
- _write(YAML::dump(@config.to_hash), File.join(listdir, Schleuder.config.lists_configfile))
91
+ _write(YAML::dump(@config.to_hash), configfile)
92
92
  @config
93
93
  end
94
-
94
+
95
+ # Returns path to the list configuration file
96
+ def configfile
97
+ # If `lists_configfile` ends with a '/', assume its pointing to a
98
+ # directory where configuration files are named "$DOMAIN/$LISTNAME.conf".
99
+ if Schleuder.config.lists_configfile.end_with?('/')
100
+ local_part, domain = listname.split('@')
101
+ if domain.nil?
102
+ # pre 2.2 style
103
+ File.join(Schleuder.config.lists_configfile, "#{local_part}.conf")
104
+ else
105
+ File.join(Schleuder.config.lists_configfile, domain, "#{local_part}.conf")
106
+ end
107
+ else
108
+ File.join(@listdir, Schleuder.config.lists_configfile)
109
+ end
110
+ end
111
+
95
112
  # Builds the bounce-address for the list
96
113
  def bounce_addr
97
114
  @bounce_addr ||= self.config.myaddr.gsub(/^(.*)@(.*)$/, '\1-bounce@\2')
@@ -146,7 +163,7 @@ module Schleuder
146
163
  # Loads the configuration
147
164
  def _load_config
148
165
  Schleuder.log.debug("reading list-config for: #{@listname}") unless Schleuder.log.nil?
149
- @config = ListConfig.new(File.join(listdir, Schleuder.config.lists_configfile))
166
+ @config = ListConfig.new(configfile)
150
167
  end
151
168
 
152
169
  def find_by_key(ary, key)
@@ -18,6 +18,7 @@ module Schleuder
18
18
  require 'log4r/outputter/fileoutputter'
19
19
  filename = config.log_file
20
20
  filename = File.join(listdir, filename) unless filename[0..0].eql?('/')
21
+ filename = File.join(filename, "#{listname}.log") if filename.end_with?('/')
21
22
  add Log4r::FileOutputter.new("file",
22
23
  { :level => @level,
23
24
  :filename => filename,
@@ -27,10 +28,10 @@ module Schleuder
27
28
 
28
29
  if config.log_syslog
29
30
  require 'log4r/outputter/syslogoutputter'
30
- syslogfmtr = Log4r::PatternFormatter.new(:pattern => "#{listname}\t%M")
31
+ syslogfmtr = Log4r::PatternFormatter.new(:pattern => "#{listname}: %M")
31
32
  add Log4r::SyslogOutputter.new("syslog",
32
33
  { :level => @level,
33
- :ident => 'Schleuder',
34
+ :ident => 'schleuder',
34
35
  :facility => "LOG_MAIL",
35
36
  :formatter => syslogfmtr }
36
37
  )
@@ -6,6 +6,8 @@ module Schleuder
6
6
  :from => Schleuder.config.myaddr,
7
7
  :'error-to' => Schleuder.config.superadminaddr,
8
8
  :subject => 'Error',
9
+ :server => Schleuder.config.smtp_host,
10
+ :port => Schleuder.config.smtp_port,
9
11
  :immediate_at => 'ERROR, FATAL',
10
12
  :formatter => formatter,
11
13
  :domain => 'schleuder', # necessary for log4r from debian "stable"
@@ -8,13 +8,24 @@ module Schleuder
8
8
  super 'log4r'
9
9
  # The initial log_level is inherited by all outputters.
10
10
  @level = eval("Log4r::#{Schleuder.config.log_level.upcase}")
11
- pattern = "%d Schleuder %l\t%M"
12
- formatter = Log4r::PatternFormatter.new(:pattern => pattern)
13
- add Log4r::FileOutputter.new('file',
14
- { :level => @level,
15
- :filename => Schleuder.config.log_file,
16
- :formatter => formatter }
17
- )
11
+ if Schleuder.config.log_file == 'syslog'
12
+ formatter = Log4r::PatternFormatter.new(:pattern => "%M")
13
+ require 'log4r/outputter/syslogoutputter'
14
+ add Log4r::SyslogOutputter.new('syslog',
15
+ { :level => @level,
16
+ :ident => 'schleuder',
17
+ :facility => "LOG_MAIL",
18
+ :formatter => formatter }
19
+ )
20
+ else
21
+ pattern = "%d Schleuder %l\t%M"
22
+ formatter = Log4r::PatternFormatter.new(:pattern => pattern)
23
+ add Log4r::FileOutputter.new('file',
24
+ { :level => @level,
25
+ :filename => Schleuder.config.log_file,
26
+ :formatter => formatter }
27
+ )
28
+ end
18
29
  add MetaEmailOutputter.new('email',
19
30
  {:to => Schleuder.config.superadminaddr,
20
31
  :immediate_at => 'ERROR, FATAL'})
@@ -326,7 +326,7 @@ module Schleuder
326
326
  new = Mail.new
327
327
  new.crypt = crypt
328
328
  # add some headers we want to keep
329
- new.content_type = self['content-type'].to_s if self['content-type']
329
+ new.content_type = self['content-type'].to_s if self['content-type'] && !self['content-type'].illegal?
330
330
  new.disposition = self._disposition
331
331
  new.encoding = self.encoding.to_s
332
332
  new.subject = _quote_if_necessary(self.subject.to_s,'UTF-8')
@@ -349,8 +349,9 @@ module Schleuder
349
349
 
350
350
  def individualize_member(recv)
351
351
  new = self.individualize(recv)
352
- _message_ids(new) if Schleuder.list.config.keep_msgid
353
- _list_headers(new) if Schleuder.list.config.include_list_headers
352
+ new = _message_ids(new) if Schleuder.list.config.keep_msgid
353
+ new = _list_headers(new) if Schleuder.list.config.include_list_headers
354
+ new
354
355
  end
355
356
 
356
357
  # Strips keywords from self and stores them in @+keywords+
@@ -366,7 +367,7 @@ module Schleuder
366
367
  a = b.body.split("\n")
367
368
 
368
369
  a.map! do |line|
369
- if line.match(/^X-.*/)
370
+ if line.match(/^X-.*/i)
370
371
  Schleuder.log.debug "found keyword-line: #{line.chomp}"
371
372
  key, val = $&.split(/:|: | /, 2)
372
373
  keyword = key.slice(2..-1).strip
@@ -377,7 +378,7 @@ module Schleuder
377
378
  line
378
379
  else
379
380
  # Split values to catch multiple values separated by comma or the like (deprecated).
380
- values = val.to_s.strip.split(/[ ,;]+/)
381
+ values = val.to_s.strip.split(/[,;]+/)
381
382
  values << ' ' if values.empty?
382
383
  values.each do |v|
383
384
  Schleuder.log.info "Storing keyword #{keyword} with value #{v.inspect}"
@@ -426,73 +427,77 @@ module Schleuder
426
427
  def process_plugins!
427
428
  if self.keywords.empty?
428
429
  Schleuder.log.info 'No keywords present, skipping plugins'
429
- elsif File.directory? Schleuder.config.plugins_dir
430
- replymsg = ""
431
- # We might want to replace the object later, which we can't do with self.
432
- mail = self
433
- plugins = {:request => [], :list => []}
434
- ptype = (self.request? ? :request : :list)
435
- used_keywords = []
436
- Plugin.signing_key(self)
437
- Dir[Schleuder.config.plugins_dir + '/*_plugin.rb'].each do |plugfile|
438
- Schleuder.log.debug "Instanciating #{plugfile} as plugin"
439
- require plugfile
440
- # interpreting class name from file name
441
- classname = File.basename(plugfile, '.rb').split('_').collect { |p| p.capitalize }.join
442
- plugin = instance_eval(classname).new
443
- Schleuder.log.debug "Storing plugin in plugin-list '#{plugin.plugin_type}'"
444
- plugins[plugin.plugin_type] << plugin
445
- end
446
- # This is neither elegant nor fast, but it's got to live only until the rewrite.
447
- Schleuder.log.debug "Processing #{ptype}-plugins"
448
- self.keywords.each do |kwhash|
449
- keyword = kwhash.keys.first
450
- value = kwhash.values.first
451
- Schleuder.log.debug "Looping for keyword #{keyword}"
452
- plugins[ptype].each do |plugin|
453
- command = keyword.downcase.gsub(/-/, '_')
454
- Schleuder.log.debug "Does #{plugin.class}.respond_to? '#{command}'"
455
- if plugin.respond_to?(command)
456
- Schleuder.log.debug "Yes it does, executing #{plugin.class}.#{command}"
457
- used_keywords << keyword
458
- foo = plugin.send(command, mail, value)
459
- case foo
460
- when String
461
- Schleuder.log.debug "Method returned a string, saving it for reply to sender."
462
- replymsg << foo << "\n\n\n"
463
- when Mail
464
- Schleuder.log.debug "Method returned a Mail-object, replacing myself by it."
465
- mail = foo
466
- else
467
- Schleuder.log.debug "Method returned '#{foo.inspect}', don't know how to handle, skipping."
430
+ else
431
+ Schleuder.config.plugins_dir.each do |plugins_dir|
432
+ if File.directory?(plugins_dir)
433
+ replymsg = ""
434
+ # We might want to replace the object later, which we can't do with self.
435
+ mail = self
436
+ plugins = {:request => [], :list => []}
437
+ ptype = (self.request? ? :request : :list)
438
+ used_keywords = []
439
+ Plugin.signing_key(self)
440
+ Dir[plugins_dir + '/*_plugin.rb'].each do |plugfile|
441
+ Schleuder.log.debug "Instanciating #{plugfile} as plugin"
442
+ require plugfile
443
+ # interpreting class name from file name
444
+ classname = File.basename(plugfile, '.rb').split('_').collect { |p| p.capitalize }.join
445
+ plugin = instance_eval(classname).new
446
+ Schleuder.log.debug "Storing plugin in plugin-list '#{plugin.plugin_type}'"
447
+ plugins[plugin.plugin_type] << plugin
448
+ end
449
+ # This is neither elegant nor fast, but it's got to live only until the rewrite.
450
+ Schleuder.log.debug "Processing #{ptype}-plugins"
451
+ self.keywords.each do |kwhash|
452
+ keyword = kwhash.keys.first
453
+ value = kwhash.values.first
454
+ Schleuder.log.debug "Looping for keyword #{keyword}"
455
+ plugins[ptype].each do |plugin|
456
+ command = keyword.downcase.gsub(/-/, '_')
457
+ Schleuder.log.debug "Does #{plugin.class}.respond_to? '#{command}'"
458
+ if plugin.respond_to?(command)
459
+ Schleuder.log.debug "Yes it does, executing #{plugin.class}.#{command}"
460
+ used_keywords << keyword
461
+ foo = plugin.send(command, mail, value)
462
+ case foo
463
+ when String
464
+ Schleuder.log.debug "Method returned a string, saving it for reply to sender."
465
+ replymsg << foo << "\n\n\n"
466
+ when Mail
467
+ Schleuder.log.debug "Method returned a Mail-object, replacing myself by it."
468
+ mail = foo
469
+ else
470
+ Schleuder.log.debug "Method returned '#{foo.inspect}', don't know how to handle, skipping."
471
+ end
472
+ next
473
+ else
474
+ Schleuder.log.debug "No it doesn't."
475
+ end
476
+ end
477
+ # Generate error-message if no plugin was executed
478
+ unless used_keywords.include?(keyword)
479
+ msg = "No #{ptype}-plugin responded to keyword #{keyword}"
480
+ Schleuder.log.debug msg
481
+ if mail.request?
482
+ replymsg << "Error: #{msg}.\n\n"
483
+ else
484
+ mail.metadata[:error] << msg
485
+ end
468
486
  end
469
- next
470
- else
471
- Schleuder.log.debug "No it doesn't."
472
487
  end
473
- end
474
- # Generate error-message if no plugin was executed
475
- unless used_keywords.include?(keyword)
476
- msg = "No #{ptype}-plugin responded to keyword #{keyword}"
477
- Schleuder.log.debug msg
488
+ # Decide how to go on: reply or list?
478
489
  if mail.request?
479
- replymsg << "Error: #{msg}.\n\n"
480
- else
481
- mail.metadata[:error] << msg
490
+ Schleuder.log.debug "Message is a request, sending plugins-output back to sender."
491
+ if replymsg.empty?
492
+ replymsg = 'The keywords you sent did not produce any output. If you feel this is an error please contact the adminisrators of this list.'.fmt
493
+ end
494
+ # This exits.
495
+ Plugin.reply(mail, replymsg, used_keywords)
482
496
  end
497
+ else
498
+ Schleuder.log.error "#{plugins_dir} does not exist or is not readable!"
483
499
  end
484
500
  end
485
- # Decide how to go on: reply or list?
486
- if mail.request?
487
- Schleuder.log.debug "Message is a request, sending plugins-output back to sender."
488
- if replymsg.empty?
489
- replymsg = 'The keywords you sent did not produce any output. If you feel this is an error please contact the adminisrators of this list.'.fmt
490
- end
491
- # This exits.
492
- Plugin.reply(mail, replymsg, used_keywords)
493
- end
494
- else
495
- Schleuder.log.error "#{Schleuder.config.plugins_dir} does not exist or is not readable!"
496
501
  end
497
502
  end
498
503
 
@@ -39,7 +39,7 @@ module Schleuder
39
39
 
40
40
  class Processor
41
41
  def self.run(listname, message)
42
- Schleuder.listname listname
42
+ Schleuder.listname(listname)
43
43
  Schleuder.origmsg = message
44
44
  Schleuder.log.debug "Testing if list-dir exists"
45
45
  unless File.directory?(List.listdir(listname))
@@ -127,7 +127,7 @@ module Schleuder
127
127
  end
128
128
 
129
129
  if Schleuder.list.config.receive_authenticated_only && !(mail.from_member || mail.from_admin)
130
- self.bounce_or_drop "not authenticated", "This address accepts only messages validly signed by a list-member's key.", mail
130
+ self.bounce_or_drop "not authenticated", "This address requires properly signed emails by its list-members. Either the signature can't be verified or is missing.", mail
131
131
  end
132
132
 
133
133
  if Schleuder.list.config.receive_from_member_emailaddresses_only && !(mail.from_member_address?||mail.from_admin_address?)
@@ -135,7 +135,7 @@ module Schleuder
135
135
  end
136
136
 
137
137
  if Schleuder.list.config.receive_admin_only && !mail.from_admin
138
- self.bounce_or_drop "not authenticated as admin", "This address accepts only messages validly signed by a list-admin's key.", mail
138
+ self.bounce_or_drop "not authenticated as admin", "This address requires properly signed emails by its list-admins. Either the signature can't be verified or is missing.", mail
139
139
  end
140
140
 
141
141
  if mail.to.to_a.include?(Schleuder.list.request_addr)
@@ -337,7 +337,7 @@ module Schleuder
337
337
 
338
338
  # if we're still alive: bounce message
339
339
  Schleuder.log.info "bouncing mail to sender"
340
- self.bounce_notify_admin status
340
+ self.bounce_notify_admin("#{status}. - #{bounce_msg}")
341
341
  $stdout.puts bounce_msg
342
342
  exit 100
343
343
  end
@@ -47,13 +47,13 @@ module Schleuder
47
47
  schleuder_attr :gpg_key_type, 'RSA'
48
48
 
49
49
  # GPG-Key length.
50
- schleuder_attr :gpg_key_length, 2048
50
+ schleuder_attr :gpg_key_length, 4096
51
51
 
52
52
  # GPG-Sub-Key type.
53
53
  schleuder_attr :gpg_subkey_type, 'RSA'
54
54
 
55
55
  # GPG-Sub-Key length.
56
- schleuder_attr :gpg_subkey_length, 2048
56
+ schleuder_attr :gpg_subkey_length, 4096
57
57
 
58
58
  ### END OF CONFIG OPTIONS
59
59
 
@@ -67,6 +67,9 @@ module Schleuder
67
67
 
68
68
  # overload with config
69
69
  super(config)
70
+
71
+ # turn @plugins_dir into an array if needed
72
+ @plugins_dir = [@plugins_dir] unless @plugins_dir.class == Array
70
73
  end
71
74
  end
72
75
  end
@@ -1,3 +1,3 @@
1
1
  module Schleuder
2
- VERSION = '2.2.3'
2
+ VERSION = '2.2.4'
3
3
  end
@@ -34,6 +34,9 @@
34
34
  \~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~[\-mailuser \fIschleuder\fR]
35
35
  .
36
36
  .br
37
+ \~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~[\-mailgroup \fIschleuder\fR]
38
+ .
39
+ .br
37
40
  \~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~[\-nointeractive]
38
41
  .
39
42
  .SH "DESCRIPTION"
@@ -89,6 +92,10 @@ Specify the passphrase needed to access the private key specified in \fB\-privat
89
92
  Specify the system user account under which \fBschleuder\fR(8) will be executed (when run as root, this defaults to \fBschleuder\fR)\.
90
93
  .
91
94
  .TP
95
+ \fB\-mailgroup\fR \fIschleuder\fR
96
+ Specify the system group under which \fBschleuder\fR(8) will be executed (when run as root, this defaults to \fBschleuder\fR)\.
97
+ .
98
+ .TP
92
99
  \fB\-nointeractive\fR
93
100
  When specified, no questions will be asked to complete missing information\.
94
101
  .
@@ -79,22 +79,26 @@ module Schleuder
79
79
  email, mime = string.split(' ')
80
80
  mem = Member.new({:email => email})
81
81
  mem.mime = mime if mime
82
- # TODO: test if address already subscribed
83
- Schleuder.list.members = Schleuder.list.members << mem
84
- msg = "#{mem}\n--> Member saved.\n\n"
85
- if key
86
- mail.crypt.add_key(key).imports.each do |i|
87
- msg << "#{mail.crypt.key_descr(mail.crypt.get_key(i.fpr))}\n"
88
- if i.status.eql? 1
89
- msg << "--> Key imported.\n\n"
90
- else
91
- msg << "--> Key *not* imported (no error, maybe already present?).\n\n"
82
+ if Schleuder.list.members.any?{|m| m.email == mem.email }
83
+ msg = "--> Member is already part of the list. Nothing changed!"
84
+ msg << "\nExisting members-list:"
85
+ else
86
+ Schleuder.list.members = Schleuder.list.members << mem
87
+ msg = "#{mem}\n--> Member saved.\n\n"
88
+ if key
89
+ mail.crypt.add_key(key).imports.each do |i|
90
+ msg << "#{mail.crypt.key_descr(mail.crypt.get_key(i.fpr))}\n"
91
+ if i.status.eql? 1
92
+ msg << "--> Key imported.\n\n"
93
+ else
94
+ msg << "--> Key *not* imported (no error, maybe already present?).\n\n"
95
+ end
92
96
  end
97
+ msg << "\n"
93
98
  end
94
- msg << "\n"
99
+ msg << "Updated members-list:"
95
100
  end
96
- msg << "Updated members-list:\n\n#{_list_members(mail)}"
97
- msg
101
+ msg << "\n\n#{_list_members(Schleuder.list.members)}"
98
102
  end
99
103
 
100
104
  def deletemember(mail, string)
@@ -110,7 +114,7 @@ module Schleuder
110
114
  msg = "Something failed. Please ask the maintainer of this list to figure out what\nhappened (e.g. by mailing to #{Schleuder.list.owner_addr}).\n"
111
115
  end
112
116
  end
113
- msg << "\nUpdated members-list:\n\n#{_list_members(mail)}\n"
117
+ msg << "\nUpdated members-list:\n\n#{_list_members(Schleuder.list.members)}\n"
114
118
  msg
115
119
  end
116
120
 
@@ -0,0 +1,14 @@
1
+ # Clearsigns the incoming body and sends the signed text back.
2
+ # Useful if the public key of a list is widely known: Let schleuder sign e.g.
3
+ # the fingerprints of your email servers certificates, and publish them online.
4
+ module Schleuder
5
+ class SignThisPlugin < Plugin
6
+ def initialize
7
+ @plugin_type = :request
8
+ end
9
+
10
+ def sign_this(mail)
11
+ mail.crypt.clearsign(mail.body)
12
+ end
13
+ end
14
+ end
metadata CHANGED
@@ -1,49 +1,42 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: schleuder
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.3
5
- prerelease:
4
+ version: 2.2.4
6
5
  platform: ruby
7
6
  authors:
7
+ - lunar
8
8
  - paz
9
9
  - ng
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain:
13
- - !binary |-
14
- LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUROakNDQWg2Z0F3SUJB
15
- Z0lCQURBTkJna3Foa2lHOXcwQkFRVUZBREJCTVJNd0VRWURWUVFEREFwelky
16
- aHMKWlhWa1pYSXlNUlV3RXdZS0NaSW1pWlB5TEdRQkdSWUZibUZrYVhJeEV6
17
- QVJCZ29Ka2lhSmsvSXNaQUVaRmdOdgpjbWN3SGhjTk1USXdOakEyTVRreE5E
18
- STBXaGNOTVRNd05qQTJNVGt4TkRJMFdqQkJNUk13RVFZRFZRUUREQXB6Clky
19
- aHNaWFZrWlhJeU1SVXdFd1lLQ1pJbWlaUHlMR1FCR1JZRmJtRmthWEl4RXpB
20
- UkJnb0praWFKay9Jc1pBRVoKRmdOdmNtY3dnZ0VpTUEwR0NTcUdTSWIzRFFF
21
- QkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDaEdydW9ObnEzSXI3ZApGZCtrdEcw
22
- dE1abG0yWlNPa3VITzVRUnJnWUxnYkJocFRFZjhpNkFqem9WTDBBSUMrdU1N
23
- Vlk5aUU2ZnphS1VECkI3U3ZOdGNjSHNrWDZ6SFVWVnRTcUY5VnBiUW9tV3Bj
24
- azBpQnF3UUl3NHZFTGUyaVorL1pVTEtJSkkvQlk0M3kKdFg3T3JhOGl6U3lQ
25
- R2N1NkUxZnI1UEpJNmlnRm5sRWdzL2pDalAvSllIZi9mNDlmbkl6QUpnTzBR
26
- N1lOTkpWcgpSMFpxbTFIYllFMnQrUnRvbVQyamdDakJ0RjQyaFg4K2dCNHlW
27
- NW5lZGZIS3laZkQ2emQ3ZG9QRS9wZHRwbjgwCkJyUlFiSFhsRVBEQ2FkSEgw
28
- MTNqN29MN0I1ZkpsSGVqWDZQRmZQdGVwcTNhZERRL08zbEZ2emZIdUpVR2pF
29
- TzUKUVhwN2w1K2ZBZ01CQUFHak9UQTNNQWtHQTFVZEV3UUNNQUF3SFFZRFZS
30
- ME9CQllFRklHMUc1UHhBMWxOL0JVWQprb212bHRzT1dDVGVNQXNHQTFVZER3
31
- UUVBd0lFc0RBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQWtrTDRWWVhPCmlI
32
- YzQ5bHFrMU9FL2IzWFZYWGdiQlZ1aHhvTkpYZC9oSjRlTmVxbVpydWMrZDlX
33
- bEJIYTlVVFRGZ3JmUkxOcmsKSkRaSnc5Y3E5NmI0TmxsaG54Q2xpZ21SZXQ0
34
- RkpmYWVtYS9naTZZN0lWRmZMUG5nVVhDUGN1SUNGOXBKd05HcwpLSUVndEE1
35
- TmNVMitJZFpLekowRnBoV3pIRlRpVytMd1Uyb0lTTEhwTXhXZVhZSXNLTW9x
36
- MjM4U3k3Y1l3emQ3CnZhZEhrZHMzNTRsbU4vajNhYW1kTXJyeHUyOTlvdTh1
37
- am9IbGcxK3IxNjlsa2J1VHdXbEI2RlVXT1J3emhvMWIKOFlJWWRpT29jUHdm
38
- Zi9BZ3l3UVdGZDRGV2VNV0xQeXRkK1VndzZCSmZSSXY2VC9OTVJKWWRIUDJW
39
- M1RTUVJyTApSYXNUTTVlUzIrK3EwQT09Ci0tLS0tRU5EIENFUlRJRklDQVRF
40
- LS0tLS0K
41
- date: 2012-07-04 00:00:00.000000000 Z
13
+ - |
14
+ -----BEGIN CERTIFICATE-----
15
+ MIIDeDCCAmCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDApzY2hs
16
+ ZXVkZXIyMRUwEwYKCZImiZPyLGQBGRYFbmFkaXIxEzARBgoJkiaJk/IsZAEZFgNv
17
+ cmcwHhcNMTMwOTI5MjAwNzQxWhcNMTQwOTI5MjAwNzQxWjBBMRMwEQYDVQQDDApz
18
+ Y2hsZXVkZXIyMRUwEwYKCZImiZPyLGQBGRYFbmFkaXIxEzARBgoJkiaJk/IsZAEZ
19
+ FgNvcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQChGruoNnq3Ir7d
20
+ Fd+ktG0tMZlm2ZSOkuHO5QRrgYLgbBhpTEf8i6AjzoVL0AIC+uMMVY9iE6fzaKUD
21
+ B7SvNtccHskX6zHUVVtSqF9VpbQomWpck0iBqwQIw4vELe2iZ+/ZULKIJI/BY43y
22
+ tX7Ora8izSyPGcu6E1fr5PJI6igFnlEgs/jCjP/JYHf/f49fnIzAJgO0Q7YNNJVr
23
+ R0Zqm1HbYE2t+RtomT2jgCjBtF42hX8+gB4yV5nedfHKyZfD6zd7doPE/pdtpn80
24
+ BrRQbHXlEPDCadHH013j7oL7B5fJlHejX6PFfPtepq3adDQ/O3lFvzfHuJUGjEO5
25
+ QXp7l5+fAgMBAAGjezB5MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
26
+ BBSBtRuT8QNZTfwVGJKJr5bbDlgk3jAfBgNVHREEGDAWgRRzY2hsZXVkZXIyQG5h
27
+ ZGlyLm9yZzAfBgNVHRIEGDAWgRRzY2hsZXVkZXIyQG5hZGlyLm9yZzANBgkqhkiG
28
+ 9w0BAQUFAAOCAQEAOW1oNWquxZegMjQDZF3yTDsXbDAs4JYsLEbjnD2z32nMGvat
29
+ wDxKD0g3XIPHEoEi28/3n6C4Py2J+P7gUObr+wWF8G67nwg2tDjarOia93RcpxqW
30
+ n4NKeyRmvEzQ+yU+X9xiwJ005mc2ME2j3QF+sjDxgd+uCN0ZT77qz2Kk4iuCGOrM
31
+ cuTmrcZdTiHkGhK7UtDn7nk3ShgwrtyC0SqPna+PUMYkPr5FQLVwsOHGExOtVHZX
32
+ +VhPezxtXTAQ0pIYXF5NssxnhcngHV8fPs0g4gbU0RRKar9egfgZ8cVITgVauVPt
33
+ HdW17U59V5gWNuJBqqwiV2PJubSZekUq/YMdtg==
34
+ -----END CERTIFICATE-----
35
+ date: 2013-09-30 00:00:00.000000000 Z
42
36
  dependencies:
43
37
  - !ruby/object:Gem::Dependency
44
38
  name: gpgme
45
39
  requirement: !ruby/object:Gem::Requirement
46
- none: false
47
40
  requirements:
48
41
  - - '='
49
42
  - !ruby/object:Gem::Version
@@ -51,7 +44,6 @@ dependencies:
51
44
  type: :runtime
52
45
  prerelease: false
53
46
  version_requirements: !ruby/object:Gem::Requirement
54
- none: false
55
47
  requirements:
56
48
  - - '='
57
49
  - !ruby/object:Gem::Version
@@ -59,59 +51,49 @@ dependencies:
59
51
  - !ruby/object:Gem::Dependency
60
52
  name: highline
61
53
  requirement: !ruby/object:Gem::Requirement
62
- none: false
63
54
  requirements:
64
- - - ! '>='
55
+ - - '>='
65
56
  - !ruby/object:Gem::Version
66
57
  version: 1.6.1
67
58
  type: :runtime
68
59
  prerelease: false
69
60
  version_requirements: !ruby/object:Gem::Requirement
70
- none: false
71
61
  requirements:
72
- - - ! '>='
62
+ - - '>='
73
63
  - !ruby/object:Gem::Version
74
64
  version: 1.6.1
75
65
  - !ruby/object:Gem::Dependency
76
66
  name: log4r
77
67
  requirement: !ruby/object:Gem::Requirement
78
- none: false
79
68
  requirements:
80
- - - ! '>='
69
+ - - '>='
81
70
  - !ruby/object:Gem::Version
82
71
  version: 1.1.9
83
72
  type: :runtime
84
73
  prerelease: false
85
74
  version_requirements: !ruby/object:Gem::Requirement
86
- none: false
87
75
  requirements:
88
- - - ! '>='
76
+ - - '>='
89
77
  - !ruby/object:Gem::Version
90
78
  version: 1.1.9
91
79
  - !ruby/object:Gem::Dependency
92
80
  name: ruby-filemagic
93
81
  requirement: !ruby/object:Gem::Requirement
94
- none: false
95
82
  requirements:
96
- - - ! '>='
83
+ - - '>='
97
84
  - !ruby/object:Gem::Version
98
85
  version: 0.4.2
99
86
  type: :runtime
100
87
  prerelease: false
101
88
  version_requirements: !ruby/object:Gem::Requirement
102
- none: false
103
89
  requirements:
104
- - - ! '>='
90
+ - - '>='
105
91
  - !ruby/object:Gem::Version
106
92
  version: 0.4.2
107
- description: ! 'Schleuder is a group''s gateway: subscribers can communicate encrypted
108
- (and pseudonymously) among themselves, receive emails from non-subscribers and send
109
- emails to non-subscribers via the list.
93
+ description: |-
94
+ Schleuder is a group's gateway: subscribers can communicate encrypted (and pseudonymously) among themselves, receive emails from non-subscribers and send emails to non-subscribers via the list.
110
95
 
111
-
112
- Schleuder takes care of all decryption and encryption, stripping of headers, formatting
113
- conversions, etc. Schleuder can also send out its own public key upon request and
114
- process administrative commands by email.'
96
+ Schleuder takes care of all decryption and encryption, stripping of headers, formatting conversions, etc. Schleuder can also send out its own public key upon request and process administrative commands by email.
115
97
  email: schleuder2@nadir.org
116
98
  executables:
117
99
  - schleuder
@@ -154,6 +136,7 @@ files:
154
136
  - plugins/manage_members_plugin.rb
155
137
  - plugins/manage_self_plugin.rb
156
138
  - plugins/resend_plugin.rb
139
+ - plugins/sign_this_plugin.rb
157
140
  - plugins/version_plugin.rb
158
141
  - README
159
142
  - LICENSE
@@ -165,29 +148,33 @@ files:
165
148
  - bin/schleuder-init-setup
166
149
  - bin/schleuder-migrate-v2.1-to-v2.2
167
150
  homepage: http://schleuder2.nadir.org
168
- licenses: []
169
- post_install_message: ! "\n\n Note: There's still one dependency missing, which
170
- we can't install in\n this run of rubygems. Please execute schleuder-fix-gem-dependencies
171
- to\n complete the installation!\n\n"
151
+ licenses:
152
+ - GPL-2
153
+ metadata: {}
154
+ post_install_message: |2+
155
+
156
+
157
+ Note: There's still one dependency missing, which we can't install in
158
+ this run of rubygems. Please execute schleuder-fix-gem-dependencies to
159
+ complete the installation!
160
+
172
161
  rdoc_options: []
173
162
  require_paths:
174
163
  - lib
175
164
  required_ruby_version: !ruby/object:Gem::Requirement
176
- none: false
177
165
  requirements:
178
- - - ! '>='
166
+ - - '>='
179
167
  - !ruby/object:Gem::Version
180
168
  version: '0'
181
169
  required_rubygems_version: !ruby/object:Gem::Requirement
182
- none: false
183
170
  requirements:
184
- - - ! '>='
171
+ - - '>='
185
172
  - !ruby/object:Gem::Version
186
173
  version: '0'
187
174
  requirements: []
188
- rubyforge_project: ! '[none]'
189
- rubygems_version: 1.8.24
175
+ rubyforge_project: '[none]'
176
+ rubygems_version: 2.0.3
190
177
  signing_key:
191
- specification_version: 3
192
- summary: ! 'Schleuder is a group''s gateway: a gpg-enabled mailinglist with remailing-capabilities.'
178
+ specification_version: 4
179
+ summary: 'Schleuder is a group''s gateway: a gpg-enabled mailinglist with remailing-capabilities.'
193
180
  test_files: []
metadata.gz.sig CHANGED
Binary file