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
@@ -0,0 +1,24 @@
1
+ module Schleuder
2
+ class Cert < Thor
3
+ extend SubcommandFix
4
+
5
+ desc 'generate', 'Generate a new TLS-certificate.'
6
+ def generate
7
+ key = Conf.api['tls_key_file']
8
+ cert = Conf.api['tls_cert_file']
9
+ fingerprint = SchleuderCertManager.generate('schleuder', key, cert)
10
+ puts "Fingerprint of generated certificate: #{fingerprint}"
11
+ puts "Have this fingerprint included into the configuration-file of all clients that want to connect to your Schleuder API."
12
+ if Process.euid == 0
13
+ puts "! Warning: this process was run as root — please make sure the above files are accessible by the user that is running `schleuder-api-daemon`."
14
+ end
15
+ end
16
+
17
+ desc 'fingerprint', 'Show fingerprint of configured certificate.'
18
+ def fingerprint
19
+ cert = Conf.api['tls_cert_file']
20
+ fingerprint = SchleuderCertManager.fingerprint(cert)
21
+ say "Fingerprint of #{Conf.api['tls_cert_file']}: #{fingerprint}"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,84 @@
1
+ require 'openssl'
2
+ require 'pathname'
3
+
4
+ class SchleuderCertManager
5
+ def self.generate(project_name, filename_key, filename_cert)
6
+ keysize = 2048
7
+ subject = "/C=MW/O=Schleuder/OU=#{project_name}"
8
+ filename_key = Pathname.new(filename_key).expand_path
9
+ filename_cert = Pathname.new(filename_cert).expand_path
10
+
11
+ key = OpenSSL::PKey::RSA.new(keysize)
12
+ cert = OpenSSL::X509::Certificate.new
13
+ cert.subject = OpenSSL::X509::Name.parse(subject)
14
+ cert.issuer = cert.subject
15
+ cert.not_before = Time.now
16
+ cert.not_after = Time.now + 10 * 365 * 24 * 60 * 60
17
+ cert.public_key = key.public_key
18
+ cert.serial = 0x0
19
+ cert.version = 2
20
+
21
+ ef = OpenSSL::X509::ExtensionFactory.new
22
+ ef.subject_certificate = cert
23
+ ef.issuer_certificate = cert
24
+ cert.extensions = [
25
+ ef.create_extension("basicConstraints","CA:TRUE", true),
26
+ ef.create_extension("subjectKeyIdentifier", "hash"),
27
+ ]
28
+ cert.add_extension ef.create_extension("authorityKeyIdentifier",
29
+ "keyid:always,issuer:always")
30
+
31
+ cert.sign key, OpenSSL::Digest::SHA256.new
32
+
33
+ filename_key = prepare_writing(filename_key)
34
+ filename_cert = prepare_writing(filename_cert)
35
+
36
+ filename_key.open('w', 400) do |fd|
37
+ fd.puts key
38
+ end
39
+ puts "Private key written to: #{filename_key}"
40
+
41
+ filename_cert.open('w') do |fd|
42
+ fd.puts cert.to_pem
43
+ end
44
+ puts "Certificate written to: #{filename_cert}"
45
+
46
+ fingerprint(cert)
47
+ rescue => exc
48
+ error exc.message
49
+ end
50
+
51
+ def self.fingerprint(cert)
52
+ if ! cert.is_a?(OpenSSL::X509::Certificate)
53
+ path = Pathname.new(cert).expand_path
54
+ if ! path.readable?
55
+ error "Error: Not a readable file: #{path}"
56
+ end
57
+ cert = OpenSSL::X509::Certificate.new(path.read)
58
+ end
59
+ OpenSSL::Digest::SHA256.new(cert.to_der).to_s
60
+ end
61
+
62
+ def self.error(msg)
63
+ $stderr.puts "Error: #{msg}"
64
+ exit 1
65
+ end
66
+
67
+ def self.note(msg)
68
+ $stdout.puts "Note: #{msg}"
69
+ end
70
+
71
+ def self.prepare_writing(filename)
72
+ if filename.exist?
73
+ note "File exists: #{filename} — writing to current directory, you should move the file manually or change the configuration file."
74
+ if filename.basename.exist?
75
+ error "File exists: #{filename.basename} — (re)move it or fix previous error and try again."
76
+ end
77
+ filename = filename.basename
78
+ end
79
+ if ! filename.dirname.exist?
80
+ filename.dirname.mkpath
81
+ end
82
+ filename
83
+ end
84
+ end
@@ -0,0 +1,11 @@
1
+ module Schleuder
2
+ module SubcommandFix
3
+
4
+ # Fixing a bug in Thor where the actual subcommand wouldn't show up
5
+ # with some invokations of the help-output.
6
+ def banner(task, namespace = true, subcommand = true)
7
+ "#{basename} #{task.formatted_usage(self, true, subcommand).split(':').join(' ')}"
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,131 @@
1
+ require 'erb'
2
+
3
+ module Schleuder
4
+ class Conf
5
+ include Singleton
6
+
7
+ EMAIL_REGEXP = /\A.+@[[:alnum:]_.-]+\z/i
8
+ FINGERPRINT_REGEXP = /\A(0x)?[a-f0-9]{32,}\z/i
9
+
10
+ DEFAULTS = {
11
+ 'lists_dir' => '/var/lib/schleuder/lists',
12
+ 'listlogs_dir' => '/var/lib/schleuder/lists',
13
+ 'plugins_dir' => '/etc/schleuder/plugins',
14
+ 'log_level' => 'warn',
15
+ 'superadmin' => 'root@localhost',
16
+ 'keyserver' => 'hkp://pool.sks-keyservers.net',
17
+ 'smtp_settings' => {
18
+ 'address' => 'localhost',
19
+ 'port' => 25,
20
+ 'domain' => 'localhost',
21
+ 'enable_starttls_auto' => true,
22
+ # Don't verify by default because most smtp servers don't include
23
+ # 'localhost' into their TLS-certificates.
24
+ 'openssl_verify_mode' => 'none',
25
+ 'authentication' => nil,
26
+ 'user_name' => nil,
27
+ 'password' => nil,
28
+ },
29
+ 'database' => {
30
+ 'production' => {
31
+ 'adapter' => 'sqlite3',
32
+ 'database' => '/var/lib/schleuder/db.sqlite',
33
+ 'timeout' => 5000
34
+ }
35
+ },
36
+ 'api' => {
37
+ 'host' => 'localhost',
38
+ 'port' => 4443,
39
+ 'tls_cert_file' => '/etc/schleuder/schleuder-certificate.pem',
40
+ 'tls_key_file' => '/etc/schleuder/schleuder-private-key.pem',
41
+ 'valid_api_keys' => []
42
+ }
43
+ }
44
+
45
+ def config
46
+ @config ||= load_config(ENV['SCHLEUDER_CONFIG'])
47
+ end
48
+
49
+ def self.lists_dir
50
+ instance.config['lists_dir']
51
+ end
52
+
53
+ def self.listlogs_dir
54
+ instance.config['listlogs_dir']
55
+ end
56
+
57
+ def self.plugins_dir
58
+ instance.config['plugins_dir']
59
+ end
60
+
61
+ def self.database
62
+ instance.config['database'][ENV['SCHLEUDER_ENV']]
63
+ end
64
+
65
+ def self.databases
66
+ instance.config['database']
67
+ end
68
+
69
+ def self.superadmin
70
+ instance.config['superadmin']
71
+ end
72
+
73
+ def self.log_level
74
+ instance.config['log_level'] || 'WARN'
75
+ end
76
+
77
+ def self.api
78
+ instance.config['api'] || {}
79
+ end
80
+
81
+ def self.api_valid_api_keys
82
+ Array(api['valid_api_keys'])
83
+ end
84
+
85
+ # Three legacy options
86
+ def self.smtp_host
87
+ instance.config['smtp_host']
88
+ end
89
+
90
+ def self.smtp_port
91
+ instance.config['smtp_port']
92
+ end
93
+
94
+ def self.smtp_helo_domain
95
+ instance.config['smtp_helo_domain']
96
+ end
97
+
98
+ def self.smtp_settings
99
+ settings = instance.config['smtp_settings'] || {}
100
+ # Support previously used config-options.
101
+ # Remove this in future versions.
102
+ {smtp_host: :address, smtp_port: :port, smtp_helo_domain: :domain}.each do |old, new|
103
+ value = self.send(old)
104
+ if value.present?
105
+ Schleuder.logger.warn "Deprecation warning: In schleuder.yml #{old} should be changed to smtp_settings[#{new}]."
106
+ settings[new] = value
107
+ end
108
+ end
109
+ settings
110
+ end
111
+
112
+ def self.keyserver
113
+ instance.config['keyserver']
114
+ end
115
+
116
+ private
117
+
118
+ def load_config(filename)
119
+ DEFAULTS.deep_merge(load_config_file(filename))
120
+ end
121
+
122
+ def load_config_file(filename)
123
+ file = Pathname.new(filename)
124
+ if file.readable?
125
+ YAML.load(ERB.new(file.read).result)
126
+ else
127
+ {}
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,15 @@
1
+ module Schleuder
2
+ module Errors
3
+ class ActiveModelError < Base
4
+ def initialize(errors)
5
+ @errors = errors
6
+ end
7
+
8
+ def message
9
+ @errors.messages.map do |message|
10
+ message.join(' ')
11
+ end.join("\n")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module Schleuder
2
+ module Errors
3
+ class Base < StandardError
4
+ def t(*args)
5
+ I18n.t(*args)
6
+ end
7
+
8
+ def to_s
9
+ super + t('errors.signoff')
10
+ end
11
+
12
+ def set_default_locale
13
+ I18n.locale = I18n.default_locale
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Schleuder
2
+ module Errors
3
+ class DecryptionFailed < Base
4
+ def initialize(list)
5
+ set_default_locale
6
+ @list = list
7
+ end
8
+
9
+ def message
10
+ t('errors.decryption_failed',
11
+ { key: @list.key.to_s,
12
+ email: @list.sendkey_address })
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ module Schleuder
2
+ module Errors
3
+ class FatalError < Base
4
+ def initialize
5
+ end
6
+
7
+ def to_s
8
+ t("errors.fatalerror")
9
+ end
10
+ end
11
+ end
12
+ end
13
+
@@ -0,0 +1,14 @@
1
+ module Schleuder
2
+ module Errors
3
+ class FileNotFound < Base
4
+ def initialize(file)
5
+ @file = file
6
+ end
7
+
8
+ def message
9
+ t('errors.file_not_found', file: @file)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,13 @@
1
+ module Schleuder
2
+ module Errors
3
+ class InvalidListname < Base
4
+ def initialize(listname)
5
+ @listname = listname
6
+ end
7
+
8
+ def message
9
+ t('errors.invalid_listname', email: @listname)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Schleuder
2
+ module Errors
3
+ class KeyAdduidFailed < Base
4
+ def initialize(errmsg)
5
+ @errmsg = errmsg
6
+ end
7
+
8
+ def message
9
+ t('errors.key_adduid_failed', { errmsg: @errmsg })
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ module Schleuder
2
+ module Errors
3
+ class KeyGenerationFailed < Base
4
+ def initialize(listdir, listname)
5
+ @listdir = listdir
6
+ @listname = listname
7
+ end
8
+
9
+ def message
10
+ t('errors.key_generation_failed',
11
+ { listdir: @listdir,
12
+ listname: @listname })
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ module Schleuder
2
+ module Errors
3
+ class KeywordAdminOnly < Base
4
+ def initialize(keyword)
5
+ @keyword = keyword
6
+ end
7
+
8
+ def message
9
+ t('errors.keyword_admin_only', keyword: @keyword)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Schleuder
2
+ module Errors
3
+ class ListExists < Base
4
+ def initialize(listname)
5
+ @listname = listname
6
+ end
7
+
8
+ def message
9
+ t('errors.list_exists', email: @listname)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Schleuder
2
+ module Errors
3
+ class ListNotFound < Base
4
+ def initialize(recipient)
5
+ @recipient = recipient
6
+ end
7
+
8
+ def message
9
+ t('errors.list_not_found', email: @recipient)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,14 @@
1
+ module Schleuder
2
+ module Errors
3
+ class ListPropertyMissing < Base
4
+ def initialize(listdir, property)
5
+ @listdir = listdir
6
+ @property = property
7
+ end
8
+
9
+ def to_s
10
+ t("errors.list_#{@property}_missing", listdir: @listdir)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module Schleuder
2
+ module Errors
3
+ class ListdirProblem < Base
4
+ def initialize(dir, problem)
5
+ @dir = dir
6
+ @problem = problem
7
+ end
8
+
9
+ def message
10
+ problem = t("errors.listdir_problem.#{@problem}")
11
+ t('errors.listdir_problem.message', dir: @dir, problem: problem)
12
+ end
13
+ end
14
+ end
15
+ end
16
+