Compare commits

...

28 Commits

Author SHA1 Message Date
Diskette Guy 50fef3c9be A-label 2025-10-20 22:33:08 +07:00
Diskette Guy 7bb3bd389e Add: U-label to A-label conversion 2025-10-19 03:25:23 +07:00
Diskette Guy 176ac83684 Cheatsheet addition 2025-10-18 21:24:42 +07:00
Diskette Guy ca87d7a828 Update README.md 2025-10-16 04:28:00 +07:00
diskette b1b7fea4d2 Update README.md 2025-10-15 21:07:27 +00:00
Scott Kitterman 96b8738af5 README.md: Fix macro name typo. Thanks to Victor Dukhovni for pointing it out. 2023-10-05 17:17:54 -04:00
Scott Kitterman c2409105dc Change version to 1.2.3 (these are all bug fixes) and set release date 2023-02-26 20:13:46 -05:00
Scott Kitterman 16ab67db0f Fix comma separated list processing in dkimpy_milter/config.py
(LP: #1901445)
2023-02-26 19:59:03 -05:00
Scott Kitterman 6d1c796a5e Fix subdomain signing with top-level organizational domain (LP: #1999434) 2023-02-26 19:49:12 -05:00
Scott Kitterman 84803d3779 Improve documentation of inter-relationship between Mode, InternalHosts,
MacroList, and MacroListVerify options in dkimpy-milter.conf.5 (Closes:
   #969215)
2023-02-26 19:38:53 -05:00
Scott Kitterman 815e1a612c Reset the i= signature identity in get_identities_sign() (Closes: #981157) 2023-02-26 18:39:02 -05:00
Scott Kitterman c3d6bce238 Fix formatting for MinimumKeyBits in dkimpy-milter.conf(5)
(Closes: #995335)
2023-02-26 18:35:39 -05:00
Scott Kitterman ea2ef10438 Add missing CHANGES entries 2023-02-26 18:34:30 -05:00
Scott Kitterman 039fcc54fd Finalize UTF-8 fixup, including dkimpy/pymilter version bumps 2023-02-26 18:31:36 -05:00
Scott Kitterman e378fb0266 Fixup on UTF-8 changes 2022-12-05 20:21:14 -05:00
Mike Tiainen 53368939fa Support percent in KeyTable - Thanks to Mika Tiainen 2022-12-05 20:11:38 -05:00
Casper Bruun 1a0abcddc7 Fixup UTF-8 string decoding - Thanks to Casper Bruun 2022-12-05 20:07:43 -05:00
Scott Kitterman b4da312ea7 Minimal fix for dnspython 2.0.0 compatibility (still works with 1.16.0) 2020-08-09 14:15:13 -04:00
Scott Kitterman 44d8924060 WIP for invalid UTF-8 resilience 2020-08-09 13:50:40 -04:00
Scott Kitterman 88c17516d9 Improve resilience to malformed email addresses 2020-04-20 15:51:10 -04:00
Scott Kitterman 791f8d80de CHANGES entry for Stefano Rivera's table docs improvements 2020-04-20 15:41:03 -04:00
Scott Kitterman 7b37e2cb8d Fix dnsfunc definition for test suite for compatibility with dkimpy >= 1.0 2020-04-19 02:28:22 -04:00
Stefano Rivera 7be865d7d7 Only one key name is needed for multiple signature algorithms
Clarify that key names from SigningTable apply to RSA and ed25519 keys.
The way to sign with both algorithms is to provide keys in both
KeyTables, with the same name.
2020-04-15 14:44:11 -07:00
Stefano Rivera e67a1b3745 Only the first matching identity is used
This is explicitly stated later in the section.
2020-04-15 14:42:04 -07:00
Scott Kitterman bf578e7b86 Improve README.md formating for markdown display on pypi 2020-01-06 02:07:49 -05:00
Scott Kitterman 04ef3629d7 Set release date 2020-01-04 14:43:28 -05:00
Scott Kitterman 489238dff0 Correct dkimpy-milter.conf file install location to match expand locations 2020-01-04 02:49:09 -05:00
Scott Kitterman a8bf7104bc - Fix expand option not to fail if files are missing since socket activation
service files are not shipped in the sdist
2020-01-04 01:47:24 -05:00
10 changed files with 270 additions and 102 deletions
+31
View File
@@ -1,3 +1,34 @@
1.2.3 2023-02-26
- Improve support for non-ASCII email messages. Anything UTF-8 should work
(including correct signing/verification). For messages that contain header
fields with non-ASCII or UTF-8 content, signatures are likely fail
verification, but the milter should continue to run. (Thanks to Casper
Bruun for help with this)
- Set minimum pymilter and dkimpy versions in setup.py to those that will
work reliably with non-ASCII content.
- Fixed support for percent in KeyTable - Thanks to Mika Tiainen
- Fix formatting for MinimumKeyBits in dkimpy-milter.conf(5)
(Closes: #995335)
- Reset the i= signature identity in get_identities_sign() (Closes: #981157)
- Improve documentation of inter-relationship between Mode, InternalHosts,
MacroList, and MacroListVerify options in dkimpy-milter.conf.5 (Closes:
#969215)
- Fix subdomain signing with top-level organizational domain (LP: #1999434)
- Thanks to Matthias Hunstock for the report and the fix
- Fix comma separated list processing in dkimpy_milter/config.py
(LP: #1901445)
1.2.2 2020-08-09
- Improve README.md formating for markdown display on pypi
- Improve documentation in dkimpy-milter.conf (5) and README.md for signing
for multiple domains (Thanks to Stefano Rivera)
- Minimal fix for dnspython 2.0.0 compatibility (still works with 1.16.0)
1.2.1 2020-01-04
- Fix expand option not to fail if files are missing since socket activation
service files are not shipped in the sdist
- Correct dkimpy-milter.conf file install location to match expand locations
1.2.0 2020-01-03
- Add support for SigningTable, KeyTable, and KeyTableEd25519 (LP: #1797397)
- Add support for specifying MinimumKeyBits for RSA signatures
+25
View File
@@ -0,0 +1,25 @@
Welcome to Cheatsheet.txt, licensed under CC-0. No attribution required.
But it is writen by Diskette (diskette@dailitation.xyz)
Information regarding the [] flags are in dkimpy repository.
[__init__.py]
Initialization file,
class dkimMilter, a milter for dkim
What are those
self.fp localpart
self.fdomain domain part
self.iequals i still have no idea
def header
define check_dkim, I assume that this checks dkim, how?
def sign_dkim
d = dkim.DKIM(txt)
[dnsplyug.py]
File for interfacing with DNS
+68 -54
View File
@@ -1,3 +1,11 @@
An SMTPUTF8-approved version of dkimpy-milter
Please do note that there might be some mistakes along the way... No warranty is provided!
This implements support for internationalized email address (RFC 8616)
Cheatsheet.txt is a file for my (diskette@dailitation.xyz) personal note taking.
# OVERVIEW
This is a DKIM signing and verification milter. It has been tested with both
@@ -52,22 +60,23 @@ The package includes a custom setup command called expand. It allows various
file locations in init scripts, man pages, and config files to be over-ridden
at install time.
expand: Expand @@ variables in input files, simlar to make macros.
user_options:
--sysconfigdir=, e: Specify system configuration directory.
--sbindir=, s: Specify system binary directory [not used].
--bindir=, b: Specify binary directory.
--rundir=,r: Specify run state directory.
expand: Expand @@ variables in input files, simlar to make macros.
user_options:
--sysconfigdir=, e: Specify system configuration directory.
--sbindir=, s: Specify system binary directory [not used].
--bindir=, b: Specify binary directory.
--rundir=,r: Specify run state directory.
As an example, to change the run directory to /var/run, one would do:
python3 setup.py expand --rundir=/var/run
[sudo] python3 setup.py install --single-version-externally-managed \
python3 setup.py expand --rundir=/var/run
[sudo] python3 setup.py install --single-version-externally-managed \
--record=/dev/null
or in a single step (the order matters):
[sudo] python3 setup.py expand --rundir=/var/run install \
[sudo] python3 setup.py expand --rundir=/var/run install \
--single-version-externally-managed \
--record=/dev/null
@@ -87,7 +96,7 @@ tools available to create them. Keys must (RFC 8302) have a minimum size of
1024 bits and should have a size of at least 2048 bits. The dknewkey script
that is provided with dkimpy is one such tool:
dknewkey exampleprivkey
dknewkey exampleprivkey
will produce both the private key file (.key suffix) and a file with the DKIM
public key record to be published DNS (.dns suffix). RSA is the default key
@@ -99,7 +108,7 @@ There is no standardized non-binary representation for Ed25519 private keys,
so in order to generate Ed25519 keys for dkimpy-milter, dkimpy specific tools
must be used to be compatible. The same dknewkey script support Ed25519:
dknewkey --ktype ed25519 anothernewkey
dknewkey --ktype ed25519 anothernewkey
will provide both the private key file (.key suffix) and a file with the DKIM
public key record to be published DNS (.dns suffix). Ed25519 keys do not have
@@ -135,9 +144,9 @@ for the above might look like this:
comkey example.com:bar:/usr/local/etc/dkim/keys/excom
netkey example.net:baz:/usr/local/etc/dkim/keys/exnet
If also signing with ed25519, specify a KeyTableEd25519 pointing to the keys
needed for ed25519. Both KeyTable and KeyTableEd25519 are evaluated if there
is a SigningTable (see below).
If also signing with ed25519, specify a KeyTableEd25519, with the same
names, pointing to the keys needed for ed25519. Both KeyTable and
KeyTableEd25519 are evaluated if there is a SigningTable (see below).
Per the documentation, multi-field data sets that are made of flat files have
the fields separated by colons, but the key and value(s) are separated by
@@ -185,7 +194,7 @@ The dkimpy-milter drops priviledges after setup to the user/group specified in
UserID. During initial setup, this system user needs to be manually created.
As an example, using the default dkimpy-user on Debian, the command would be:
[sudo] adduser --system --no-create-home --quiet --disabled-password \
[sudo] adduser --system --no-create-home --quiet --disabled-password \
--disabled-login --shell /bin/false --group \
--home /run/dkimpy-milter dkimpy-milter
@@ -195,10 +204,10 @@ missing, the milter will create it on startup.
To start dkimpy-milter with systemd for the first time, you will need to take
the following steps:
[sudo] systemctl daemon-reload
[sudo] systemctl enable dkimpy-milter
[sudo] systemctl start dkimpy-milter
[sudo] systemctl status dkimpy-milter (to verify it started correctly)
[sudo] systemctl daemon-reload
[sudo] systemctl enable dkimpy-milter
[sudo] systemctl start dkimpy-milter
[sudo] systemctl status dkimpy-milter (to verify it started correctly)
As with all milters, dkimpy-milter needs to be integrated with your MTA of
choice (Sendmail or Postfix). When integrating with your MTA, the risk of
@@ -214,7 +223,7 @@ Configuration is very similar to opendkim, but needs some adjustment for
dkimpy-milter. Here's an example configuration line to include in your
sendmail.mc:
INPUT_MAIL_FILTER(`dkimpy-milter', `S=local:/run/dkimpy-milter/dkimpy-milter.sock')dnl
INPUT_MAIL_FILTER(`dkimpy-milter', `S=local:/run/dkimpy-milter/dkimpy-milter.sock')dnl
Changing the sendmail.mc file requires a Make (to compile it into sendmail.cf)
and a restart of sendmail. Note that S= needs to match the value of Socket in
@@ -237,7 +246,7 @@ and deserve consideration.
By default, sendmail quotes to address header fields when there are no
quotes and the display part of the address contains a period or an
apostrophe. However, opendkim only sees the raw, unmodified form of
apostrophe. However, dkimpy-milter only sees the raw, unmodified form of
the header field, and so the content that gets verified and what gets
signed will not be the same, guaranteeing the attached signature is not
valid.
@@ -263,16 +272,16 @@ and deserve consideration.
To: very long name <a@example.org>,
anotherloo...ong name b <b@example.org>
This rewrite is also done after opendkim has seen the message, meaning
the signature opendkim attaches to the message does not match the
content it signed. There is not a known configuration change to
This rewrite is also done after dkimpy-milter has seen the message,
meaning the signature dkimpy-milter attaches to the message does not match
the content it signed. There is not a known configuration change to
mitigate this mutation.
The only known mechanism for dealing with this is to have distinct
instances of opendkim do the verifying (inbound) and signing (outbound)
so that the version that arrives at the signing instance is already
in the rewritten form, guaranteeing the input and output are the same
and thus the signature matches the payload.
instances of dkimpy-milter do the verifying (inbound) and signing
(outbound) so that the version that arrives at the signing instance is
already in the rewritten form, guaranteeing the input and output are the
same and thus the signature matches the payload.
### POSTFIX
@@ -281,15 +290,15 @@ README_FILES/MILTER_README). Here's an example master.cf excerpt that talks
to two dkimpy-milter instances, one configured for signing and one configured
for verification:
smtp inet n - - - - smtpd
...
-o smtpd_milters=inet:localhost:8892
...
smtp inet n - - - - smtpd
...
-o smtpd_milters=inet:localhost:8892
...
submission inet n - - - - smtpd
...
-o smtpd_milters=inet:localhost:8891
...
submission inet n - - - - smtpd
...
-o smtpd_milters=inet:localhost:8891
...
These need to match the Socket value for each dkimpy-milter instance.
@@ -300,28 +309,28 @@ macros to keep the mail streams segregated:
Postfix master.cf:
smtp inet n - - - - smtpd
...
-o smtpd_milters=inet:localhost:8891
-o milter_macro_daemon_name=VERIFYING
...
smtp inet n - - - - smtpd
...
-o smtpd_milters=inet:localhost:8891
-o milter_macro_daemon_name=VERIFYING
...
submission inet n - - - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
...
-o milter_macro_daemon_name=ORIGINATING
-o smtpd_milters=inet:localhost:8891
...
submission inet n - - - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
...
-o milter_macro_daemon_name=ORIGINATING
-o smtpd_milters=inet:localhost:8891
...
Dkimpy-milter.conf:
...
Mode sv
MacroList dameon_name|ORIGINATING
MacroListVerify daemon_name|VERIFYING
...
...
Mode sv
MacroList daemon_name|ORIGINATING
MacroListVerify daemon_name|VERIFYING
...
# NOTES
@@ -335,3 +344,8 @@ later support Ed25519 signing and verification. RFC 8301 removed rsa-sha1
from DKIM. dkimpy-milter does not sign with rsa-sha1, but still considers
rsa-sha1 signatures as valid for verification because they are still in
common use and are not known to be cryptographically broken.
Support for non-ASCII email messages: Anything UTF-8 should work (including
correct signing/verification). For messages that contain header fields with
non-ASCII or UTF-8 content, signatures are likely fail verification, but the
milter should continue to run. RFC 8616 is not supported.
+40 -7
View File
@@ -31,6 +31,7 @@ import tempfile
import io
import re
import codecs
import idna
from Milter.utils import parse_addr, parseaddr
import dkimpy_milter.config as config
from dkimpy_milter.util import drop_privileges
@@ -39,7 +40,7 @@ from dkimpy_milter.util import write_pid
from dkimpy_milter.util import get_keys
from dkimpy_milter.util import fold
__version__ = "1.2.0"
__version__ = "1.2.3"
FWS = re.compile(r'\r?\n[ \t]+')
@@ -101,15 +102,28 @@ class dkimMilter(Milter.Base):
if self.conf.get('Syslog') and self.conf.get('debugLevel') >= 1:
syslog.syslog("connect from {0} at {1} {2}"
.format(hostname, hostaddr, connecttype))
if self.conf.get('Syslog') and self.conf.get('debugLevel') >= 3:
syslog.syslog("internal_conn: {0}, external_conn: {1}"
.format(self.internal_connection, self.external_connection))
return Milter.CONTINUE
# multiple messages can be received on a single connection
# envfrom (MAIL FROM in the SMTP protocol) seems to mark the start
# of each message.
@Milter.noreply
def envfrom(self, f, *str):
def envfrom(self, f, *moredata):
try:
f = str(codecs.encode(f, 'UTF-8', 'replace'), 'UTF-8', 'ignore')
except TypeError:
f = codecs.encode(f, 'UTF-8', 'replace').decode()
try:
moredata = str(codecs.encode(str(moredata), 'UTF-8', 'replace'), 'UTF-8', 'ignore')
except TypeError:
moredata = codecs.encode(str(moredata), 'UTF-8', 'replace').decode()
if self.conf.get('Syslog') and self.conf.get('debugLevel') >= 2:
syslog.syslog("mail from: {0} {1}".format(f, str))
syslog.syslog("mail from: {0} {1}".format(f, moredata))
self.fp = io.BytesIO()
self.mailfrom = f
t = parse_addr(f)
@@ -136,11 +150,16 @@ class dkimMilter(Milter.Base):
syslog.syslog("{0}: {1}".format(name, val))
self.has_dkim += 1
if lname == 'from':
fname, self.author = parseaddr(val)
fname, self.author = parseaddr(idna.alabel(val))
try:
self.fdomain = self.author.split('@')[1].lower()
except IndexError as er:
pass # self.author was not a proper email address
# This keeps non-ascii characters out of the From domain
try:
self.fdomain = str(codecs.encode(self.fdomain, 'ascii', 'replace'), 'ascii', 'ignore')
except TypeError:
self.fdomain = codecs.encode(self.fdomain, 'ascii', 'replace').decode('ascii','ignore')
if (self.conf.get('Syslog') and
self.conf.get('debugLevel') >= 1):
syslog.syslog("{0}: {1}".format(name, val))
@@ -148,7 +167,11 @@ class dkimMilter(Milter.Base):
self.arheaders.append(val)
if self.fp:
try:
self.fp.write(b"%s: %s\n" % (codecs.encode(name, 'ascii'), codecs.encode(val, 'ascii')))
if lname == 'from':
# Non-ascii in email address localpart is legal, so this is a special case
self.fp.write(b"%s: %s\n" % (codecs.encode(name, 'ascii'), codecs.encode(val, 'UTF-8', 'replace')))
else:
self.fp.write(b"%s: %s\n" % (codecs.encode(name, 'ascii'), codecs.encode(val, 'ascii')))
except:
# Don't choke on header fields with non-ascii garbage in them.
pass
@@ -195,6 +218,8 @@ class dkimMilter(Milter.Base):
syslog.syslog('self.domain: {0}, self.fdomain: {1}, self.iequals: {2}'.format(self.domain, self.fdomain, self.iequals))
if ((self.fdomain in self.domain) and not self.conf.get('Mode') == 'v'
and not self.external_connection):
if (self.conf.get('Syslog') and self.conf.get('debugLevel') >= 3):
syslog.syslog("Signing DKIM")
self.sign_dkim(txt)
if ((self.has_dkim) and (not self.internal_connection) and
(self.conf.get('Mode') == 'v' or
@@ -227,7 +252,7 @@ class dkimMilter(Milter.Base):
def get_identities_sign(self):
"""Determine d= and i= identiies for signature"""
self.domain = []
iequals = None
self.iequals = None
try:
self.privkeyRSA = self.conf.get('privateRSA')
except:
@@ -280,6 +305,7 @@ class dkimMilter(Milter.Base):
keytabledata = self.conf.get('privateRSATable')[keytablekey]
try:
self.fdomain = keytabledata[0]
self.domain.append(self.fdomain)
self.selectorRSA = keytabledata[1]
self.privkeyRSA = keytabledata[2]
except:
@@ -290,11 +316,14 @@ class dkimMilter(Milter.Base):
keytabledata = self.conf.get('privateEd25519Table')[keytablekey]
try:
self.fdomain = keytabledata[0]
self.domain.append(self.fdomain)
self.selectorEd25519 = keytabledata[1]
self.privkeyEd25519 = keytabledata[2]
except:
if (self.conf.get('Syslog')):
syslog.syslog('Error: Invalid KeyTable data {0}'.format(keytabledata))
if (self.fdomain == '%'):
self.fdomain = self.author.split('@')[1].lower()
break
def sign_dkim(self, txt):
@@ -363,8 +392,12 @@ class dkimMilter(Milter.Base):
try:
dnsoverride = self.conf.get('DNSOverride')
if isinstance(dnsoverride, str):
timeout = 5
domain = self.fdomain
def dnsfunc(domain, timeout=timeout, dnsoverride=dnsoverride):
return dnsoverride
syslog.syslog("DNSOverride: {0}".format(dnsoverride))
res = d.verify(idx=y, dnsfunc=lambda _x: dnsoverride)
res = d.verify(idx=y, dnsfunc=dnsfunc)
else:
res = d.verify(idx=y)
algo = codecs.decode(d.signature_fields.get(b'a'), 'ascii')
+38 -10
View File
@@ -89,16 +89,23 @@ class HostsDataset(object):
self.item = item[1:]
self.negative = True
try:
self.item = ipaddress.ip_address(str(self.item, "utf-8"))
try:
self.item = ipaddress.ip_address(str(self.item, "utf-8"))
except TypeError:
self.item = ipaddress.ip_address(self.item)
if isinstance(self.item, ipaddress.IPv4Address):
self.isipv4 = True
elif isinstance(self.item, ipaddress.IPv6Address):
self.isipv6 = True
except ValueError as e:
try:
self.item = ipaddress.ip_network(str
(self.item, "utf-8"),
strict=False)
try:
self.item = ipaddress.ip_network(str
(self.item, "utf-8"),
strict=False)
except TypeError:
self.item = ipaddress.ip_network(self.item,
strict=False)
if isinstance(self.item, ipaddress.IPv4Network):
self.isipv4cidr = True
elif isinstance(self.item, ipaddress.IPv6Network):
@@ -114,7 +121,10 @@ class HostsDataset(object):
def match(self, connectip):
'''Check if the connect IP is part of the dataset'''
source = ipaddress.ip_address(str(connectip, "utf-8"))
try:
source = ipaddress.ip_address(str(connectip, "utf-8"))
except TypeError:
source = ipaddress.ip_address(connectip)
for item in self.dataset:
if item.isdomain or item.ishostname:
result = self.matchname(source) # Match host/domains first
@@ -164,13 +174,19 @@ class HostsDataset(object):
if isinstance(source, ipaddress.IPv4Address):
ips = s.dns(name, 'A')
for ip in ips:
ip = ipaddress.IPv4Address(str(ip, 'UTF-8'))
try:
ip = ipaddress.IPv4Address(str(ip, 'UTF-8'))
except TypeError:
ip = ipaddress.IPv4Address(ip)
if ip == source:
results.append(name)
if isinstance(source, ipaddress.IPv6Address):
ips = s.dns(name, 'AAAA')
for ip in ips:
ip = ipaddress.IPv6Address(str(ip, 'UTF-8'))
try:
ip = ipaddress.IPv6Address(str(ip, 'UTF-8'))
except TypeError:
ip = ipaddress.IPv6Address(ip)
if ip == source:
results.append(name)
return results
@@ -306,9 +322,15 @@ def _dataset_to_list(dataset):
return dsd
# If it's a str and csl, it has one value and we return a list
if dataset[:4] == 'csl:':
return [dataset[4:].strip().strip(',')]
datalist = dataset[4:].split(',')
for item in datalist:
datalist[datalist.index(item)] = item.strip().strip(',')
return datalist
else:
return [dataset.strip().strip(',')]
datalist = dataset.split(',')
for item in datalist:
datalist[datalist.index(item)] = item.strip().strip(',')
return datalist
if dataset[-3:] == '.db' or dataset[:3] == 'db:':
# This is a Sleepycat (Oracle) DB dataset, which we dont support
raise dkim.ParameterError('Unsupported dataset db datase: {0}'
@@ -439,8 +461,14 @@ def _readConfigFile(path, configData=None, configGlobal={}):
fp.close()
try:
configData['AuthservID'] = _make_authserv_id(configData.get('AuthservID', 'HOSTNAME'))
except Exception as e:
syslog.syslog("Could not make AuthservID: {}".format(e))
pass
try:
configData['IntHosts'] = HostsDataset(configData['InternalHosts'])
except:
except Exception as e:
syslog.syslog("Could not make HostDataset from InternalHosts: {}".format(e))
pass
return(configData)
+1 -1
View File
@@ -127,7 +127,7 @@ def DNSLookup_dnspython(name,qtype,tcpfallback=True,timeout=5):
elif qtype == 'PTR':
retVal.append(((name, qtype), rdata.target.to_text(True)))
elif qtype == 'TXT' or qtype == 'SPF':
retVal.append(((name, qtype), rdata.strings))
retVal.append(((name, qtype), list(rdata.strings)))
except dns.resolver.NoAnswer:
pass
except dns.resolver.NXDOMAIN:
+18 -1
View File
@@ -244,6 +244,10 @@ Naturally, providing a value here overrides the default, so if mail from
127.0.0.1 should be signed, the list provided here should include that
address explicitly. [PeerList NOT IMPLEMENTED]
Mail sent via connections from InternalHosts will not have any existing DKIM
signatures verified. This is not overridden by MacroList or Mode. If the
Mode is 'v', then no actions will be performed.
.TP
.I KeyFile (string)
Gives the location of a PEM-formatted private key to be used for RSA signing
@@ -298,6 +302,10 @@ at the time the filter receives a connection from the MTA and its availability
depends upon the version of milter used to compile the filter and the version
of the MTA making the connection.
Mail sent via connections where macros that are in MacroList are provided
will not have any existing DKIM signatures verified. If the Mode is 'v', then
no actions will be performed.
.TP
.I MacroListVerify (dataset)
Defines a set of MTA-provided
@@ -308,6 +316,10 @@ Entries in this data set follow the same form as those of the
.I MacroList
option above. [this option is not inhereted from OpenDKIM]
Mail sent via connections where macros that are in MacroListVerify are
provided will be not DKIM signed. If the Mode is 's', then no actions will
be performed.
.TP
.I Mode (string)
Selects operating modes. The string is a concatenation of characters that
@@ -327,7 +339,12 @@ be set:
(a) Domain, KeyFile, Selector, no KeyTable, no SigningTable;
(b) KeyTable, SigningTable, no Domain, no KeyFile, no Selector;
TP
The action to sign or verify is also affected by the InternalHosts, MacroList,
and MacroListVerify options. Those options may preclude signing or
verification in some cases, but will not enable signing or verifying if not
allowed by Mode.
.TP
.I MinimumKeyBits (integer)
Establishes a minimum key size for acceptable RSA signatures. Signatures with
smaller key sizes, even if they otherwise pass DKIM validation, will me marked
+19 -2
View File
@@ -244,6 +244,10 @@ Naturally, providing a value here overrides the default, so if mail from
127.0.0.1 should be signed, the list provided here should include that
address explicitly. [PeerList NOT IMPLEMENTED]
Mail sent via connections from InternalHosts will not have any existing DKIM
signatures verified. This is not overridden by MacroList or Mode. If the
Mode is 'v', then no actions will be performed.
.TP
.I KeyFile (string)
Gives the location of a PEM-formatted private key to be used for RSA signing
@@ -298,6 +302,10 @@ at the time the filter receives a connection from the MTA and its availability
depends upon the version of milter used to compile the filter and the version
of the MTA making the connection.
Mail sent via connections where macros that are in MacroList are provided
will not have any existing DKIM signatures verified. If the Mode is 'v', then
no actions will be performed.
.TP
.I MacroListVerify (dataset)
Defines a set of MTA-provided
@@ -308,6 +316,10 @@ Entries in this data set follow the same form as those of the
.I MacroList
option above. [this option is not inhereted from OpenDKIM]
Mail sent via connections where macros that are in MacroListVerify are
provided will be not DKIM signed. If the Mode is 's', then no actions will
be performed.
.TP
.I Mode (string)
Selects operating modes. The string is a concatenation of characters that
@@ -327,7 +339,12 @@ be set:
(a) Domain, KeyFile, Selector, no KeyTable, no SigningTable;
(b) KeyTable, SigningTable, no Domain, no KeyFile, no Selector;
TP
The action to sign or verify is also affected by the InternalHosts, MacroList,
and MacroListVerify options. Those options may preclude signing or
verification in some cases, but will not enable signing or verifying if not
allowed by Mode.
.TP
.I MinimumKeyBits (integer)
Establishes a minimum key size for acceptable RSA signatures. Signatures with
smaller key sizes, even if they otherwise pass DKIM validation, will me marked
@@ -428,7 +445,7 @@ of this field.
.TP
.I SigningTable (dataset)
Defines a table used to select one or more signing identities to apply to a message based on the address found in the From: header field. Keys in this table vary depending on the type of table used; values in this data set should include one field that contains a name found in the KeyTable (see above) that identifies which key should be used in generating the signature, and an optional second field naming the signer of the message that will be included in the "i=" tag in the generated signature. Note that the "i=" value will not be included in the signature if it conflicts with the signing domain (the "d=" value).
Defines a table used to select a signing identity to apply to a message based on the address found in the From: header field. Keys in this table vary depending on the type of table used; values in this data set should include one field that contains a name found in the KeyTable (see above) that identifies which key should be used in generating the signature, and an optional second field naming the signer of the message that will be included in the "i=" tag in the generated signature. Note that the "i=" value will not be included in the signature if it conflicts with the signing domain (the "d=" value).
If the first field contains only a "%" character, it will be replaced by the domain found in the From: header field. Similarly, within the optional second field, any "%" character will be replaced by the domain found in the From: header field.
+29 -26
View File
@@ -53,40 +53,43 @@ class FileMacroExpand(distutils.cmd.Command):
'system/dkimpy-milter.service', 'system/dkimpy-milter', \
'system/dkimpy-milter.openrc', \
'system/socket-activation/dkimpy-milter.service', \
'system/socket-activation/dkimpy-milter.socket',]
'system/socket-activation/dkimpy-milter.socket', ]
for infile in files:
outfile = ''
filein = open(infile + '.in')
for line in filein:
for function in ["@SYSCONFDIR@", "@CONFDIR@", "@SBINDIR@", "@BINDIR@", "@RUNSTATEDIR@"]:
splitline = line.split(function)
if len(splitline) > 1:
if function == "@SYSCONFDIR@":
line = splitline[0] + self.sysconfigdir + splitline[1]
elif function == "@CONFDIR@":
line = splitline[0] + self.configdir + splitline[1]
elif function == "@SBINDIR@":
line = splitline[0] + self.sbindir + splitline[1]
elif function == "@BINDIR@":
line = splitline[0] + self.bindir + splitline[1]
elif function == "@RUNSTATEDIR@":
line = splitline[0] + self.rundir + splitline[1]
outfile += line
out = open(infile, 'w')
for line in outfile:
out.write(line)
out.close()
try:
filein = open(infile + '.in')
for line in filein:
for function in ["@SYSCONFDIR@", "@CONFDIR@", "@SBINDIR@", "@BINDIR@", "@RUNSTATEDIR@"]:
splitline = line.split(function)
if len(splitline) > 1:
if function == "@SYSCONFDIR@":
line = splitline[0] + self.sysconfigdir + splitline[1]
elif function == "@CONFDIR@":
line = splitline[0] + self.configdir + splitline[1]
elif function == "@SBINDIR@":
line = splitline[0] + self.sbindir + splitline[1]
elif function == "@BINDIR@":
line = splitline[0] + self.bindir + splitline[1]
elif function == "@RUNSTATEDIR@":
line = splitline[0] + self.rundir + splitline[1]
outfile += line
out = open(infile, 'w')
for line in outfile:
out.write(line)
out.close()
except FileNotFoundError as x:
pass
kw = {} # Work-around for lack of 'or' requires in setuptools.
try:
import dns
kw['install_requires'] = ['dkimpy>=1.0', 'pymilter', 'authres>=1.1.0', 'PyNaCl', 'dnspython>=1.16.0']
kw['install_requires'] = ['dkimpy>=1.1.0', 'pymilter>=1.0.5', 'authres>=1.1.0', 'PyNaCl', 'dnspython>=1.16.0']
except ImportError: # If PyDNS is not installed, prefer dnspython
kw['install_requires'] = ['dkimpy>=1.0', 'pymilter', 'authres>=1.1.0', 'PyNaCl', 'Py3DNS']
kw['install_requires'] = ['dkimpy>=1.1.0', 'pymilter>=1.0.5', 'authres>=1.1.0', 'PyNaCl', 'Py3DNS']
setup(
name='dkimpy-milter',
version='1.2.0',
version='1.2.3',
author='Scott Kitterman',
author_email='scott@kitterman.com',
url='https://launchpad.net/dkimpy-milter',
@@ -115,8 +118,8 @@ setup(
include_package_data=True,
data_files=[(os.path.join('share', 'man', 'man5'),
['man/dkimpy-milter.conf.5']), (os.path.join('share', 'man', 'man8'),
['man/dkimpy-milter.8']), ('etc', ['etc/dkimpy-milter.conf']),
(os.path.join('lib', 'systemd', 'system'),
['man/dkimpy-milter.8']), (os.path.join('etc', 'dkimpy-milter'),
['etc/dkimpy-milter.conf']), (os.path.join('lib', 'systemd', 'system'),
['system/dkimpy-milter.service']),(os.path.join('etc', 'init.d'),
['system/dkimpy-milter']), (os.path.join('etc', 'init.d'),
['system/dkimpy-milter.openrc'])],
+1 -1
View File
@@ -26,7 +26,7 @@ function connect_and_send (sockname, headers, body)
end
-- mt.macro(conn, SMFIC_MAIL, "i", "simple-message")
if mt.mailfrom(conn, "<alice@example.net>") ~= nil then
if mt.mailfrom(conn, "<alicüe@example.net> (Alicþþÿÿe)") ~= nil then
error "mt.mailfrom() failed"
end
if mt.getreply(conn) ~= SMFIR_CONTINUE then