[-]
[+]
|
Changed |
spamdyke.spec
|
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/documentation/Changelog.txt
^
|
@@ -1,3 +1,59 @@
+VERSION 4.3.1: 1/20/2012
+ Extended smtpdummy's error response to show the command that caused the error.
+ Fixed a bug in smtpdummy that prevented it from correctly processing message
+ data received in bursts.
+ Fixed a bug in middleman() that mistook qmail's response to the DATA command
+ for its response to the end of the message when header blacklisting was in
+ use. This generated erroneous DENIED_OTHER messages when the qmail was slow
+ to respond to DATA for any reason.
+ Fixed an access violation in append_string_array() that caused crashes when
+ the header blacklist filter was active with configuration directories.
+
+VERSION 4.3.0: 1/15/2012
+ Fixed config-test message for a graylist domain folder when the domain is not
+ in the list of local domains from ERROR to INFO. Thanks to Eric Shubert
+ for reporting this one.
+ Fixed a bunch of copy-and-paste errors in the option_list array in
+ prepare_settings() where options were designated
+ CONFIG_TYPE_STRING_SINGLETON instead of CONFIG_TYPE_OPTION_SINGLETON or
+ CONFIG_TYPE_STRING_ARRAY instead of CONFIG_TYPE_OPTION_ARRAY.
+ Fixed configure script errors and compilation warnings on Debian 7, which
+ enables the new GCC flags -Waddress and -Wunused-but-set-variable by
+ default. Thanks to Steve Cole for reporting this one.
+ Added some explanitory comments to spamdyke.h and spamdyke.c.
+ Added FILTER_FLAG_RETAIN and modified middleman() to buffer any data as long
+ as it is given.
+ Added FILTER_FLAG_CHILD_RESPONSE_INTERCEPT and modified middleman() to discard
+ any input from qmail when it is given.
+ Added FILTER_FLAG_DATA_CAPTURE and modified middleman() to capture qmail's
+ response to the end of the message data when it is given.
+ Fixed output_writeln() to send the data in bursts if more than one line is
+ given and no CRs need to be inserted. Previously, all data was sent
+ line-by-line, even though middleman() was trying to send bursts of data when
+ possible.
+ Changed middleman() to buffer the names of the accepted recipients until after
+ the message data is sent, then check qmail's response to the message body
+ and print ALLOWED/DENIED for each recipient accordingly, along with the text
+ of qmail's response.
+ Added the options header-blacklist-entry and header-blacklist-file to block
+ messages based on the contents of their headers.
+ Added the option rejection-text-header-blacklist to control the message from
+ the header blacklist filter.
+ Added a flag to smtpdummy to force it to reject all message content with an
+ error.
+ Added a more complete usage message to smtpdummy.
+ Fixed a number of very serious errors in the usage of snprintf()/vsnprintf().
+ The return value was being used as the length of the string printed into
+ the buffer, but the return value really indicates the length of the string
+ that *could* be printed if the buffer were of infinite size. Because the
+ returned value could be larger than the buffer's size, this meant remotely
+ exploitable buffer overflows were possible, depending on spamdyke's
+ configuration.
+ Added options to smtpdummy to make it appear to process authentication (and
+ unconditionally succeed or fail).
+ Changed the ALLOWED log message to show the text given by qmail when the
+ message is accepted.
+
VERSION 4.2.1: 1/4/2012
Added a filter to sendrecv so input containing "\r\n" will be translated into
CRLF without being interpreted as a line terminator (so multiple commands
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/documentation/FAQ.html
^
|
@@ -22,13 +22,14 @@
<li><a href="#GEN4">How do I upgrade spamdyke? What's the significance of the version numbers?</a></li>
<li><a href="#GEN5">How do I get support for spamdyke? Is there a mailing list?</a></li>
<li><a href="#GEN6">I don't use qmail. Can I still use spamdyke?</a></li>
-<li><a href="#GEN7">Do I have to install the programs from the "utils" directory? Does spamdyke use
+<li><a href="#GEN7">I use Plesk. What is qmail? Can I still use spamdyke?</a></li>
+<li><a href="#GEN8">Do I have to install the programs from the "utils" directory? Does spamdyke use
them? Do they use spamdyke or each other?</a></li>
-<li><a href="#GEN8">When I reconfigure spamdyke, do I have to restart qmail?</a></li>
-<li><a href="#GEN9">What is the difference between a right-hand-side blacklist (RHSBL) and a realtime blackhole list (RBL)?</a></li>
-<li><a href="#GEN10">Which RBLs and/or RHSBLs do you recommend?</a></li>
-<li><a href="#GEN11">What operating systems and versions do you test spamdyke with?</a></li>
-<li><a href="#GEN12">I love spamdyke! How can I help? Can I send you money?</a></li>
+<li><a href="#GEN9">When I reconfigure spamdyke, do I have to restart qmail?</a></li>
+<li><a href="#GEN10">What is the difference between a right-hand-side blacklist (RHSBL) and a realtime blackhole list (RBL)?</a></li>
+<li><a href="#GEN11">Which RBLs and/or RHSBLs do you recommend?</a></li>
+<li><a href="#GEN12">What operating systems and versions do you test spamdyke with?</a></li>
+<li><a href="#GEN13">I love spamdyke! How can I help? Can I send you money?</a></li>
</ul>
<h2>Feature Questions</h2>
<ul>
@@ -39,7 +40,7 @@
<li><a href="#FEATURE5">I want to block all emails unless the sender authenticates. Can spamdyke do that?</a></li>
<li><a href="#FEATURE6">Does spamdyke support TLS?</a></li>
<li><a href="#FEATURE7">I want to whitelist a large number of IP addresses; can I use wildcards?</a></li>
-<li><a href="#FEATURE8">I want to disable some filters for a few domains and enable them for everyone else. Is that possible?</a></li>
+<li><a href="#FEATURE8">I want to disable some filters for a few domains (or users) and enable them for everyone else. Is that possible?</a></li>
<li><a href="#FEATURE9">My users' PCs are infected with spambots and are sending spam through my server. Can I force them to authenticate to block the spam?</a></li>
</ul>
<h2>Feature Suggestions</h2>
@@ -49,15 +50,15 @@
than text files and strange directory structures!</a></li>
<li><a href="#SUGGESTION2">Why doesn't spamdyke filter using Sender Policy Framework (SPF), Sender ID, Certified Server Validation (CSV),
DomainKeys or DomainKeys Identified Mail (DKIM)?</a></li>
-<li><a href="#SUGGESTION3">Why can't spamdyke filter based on message headers like "From:" or "Received:"?
-Why can't spamdyke block large messages or strip attachments?</a></li>
-<li><a href="#SUGGESTION4">Why can't spamdyke validate a recipient address before accepting a message?</a></li>
-<li><a href="#SUGGESTION5">My graylist directories are getting huge -- many, many entries. Is this is a problem? What can I do?</a></li>
-<li><a href="#SUGGESTION6">Why can't spamdyke automatically delete old graylist entries?</a></li>
-<li><a href="#SUGGESTION7">Instead of trying to prevent relaying itself, why doesn't spamdyke just set the <code>RELAYCLIENT</code>
+<li><a href="#SUGGESTION3">Why can't spamdyke filter based on message headers like "From:" or "Received:"?</a></li>
+<li><a href="#SUGGESTION4">Why can't spamdyke block large messages or strip attachments?</a></li>
+<li><a href="#SUGGESTION5">Why can't spamdyke validate a recipient address before accepting a message?</a></li>
+<li><a href="#SUGGESTION6">My graylist directories are getting huge -- many, many entries. Is this is a problem? What can I do?</a></li>
+<li><a href="#SUGGESTION7">Why can't spamdyke automatically delete old graylist entries?</a></li>
+<li><a href="#SUGGESTION8">Instead of trying to prevent relaying itself, why doesn't spamdyke just set the <code>RELAYCLIENT</code>
environment variable based on authentication/sender address/recipient address?</a></li>
-<li><a href="#SUGGESTION8">Why can't spamdyke automatically blacklist (or delay) servers that are rejected too many times?</a></li>
-<li><a href="#SUGGESTION9">Why doesn't spamdyke's graylist filter use the IP address of the remote server?</a></li>
+<li><a href="#SUGGESTION9">Why can't spamdyke automatically blacklist (or delay) servers that are rejected too many times?</a></li>
+<li><a href="#SUGGESTION10">Why doesn't spamdyke's graylist filter use the IP address of the remote server?</a></li>
</ul>
<h2>Troubleshooting</h2>
<ul>
@@ -78,7 +79,7 @@
<li><a href="#TROUBLE9">I can't figure out why spamdyke isn't working correctly -- some features are malfunctioning in
strange ways <b>OR</b> I'm seeing strange/impossible error messages in my logs. What's wrong?</a></li>
<li><a href="#TROUBLE10">Why are messages still being rejected even after I've added the sender's domain name to my rDNS whitelist? <b>OR</b>
-Why aren't message being rejected after I've added the sender's domain name to my rDNS blacklist?</a></li>
+Why aren't messages being rejected after I've added the sender's domain name to my rDNS blacklist?</a></li>
<li><a href="#TROUBLE11">I enabled the IP-in-rDNS filter, so why isn't spamdyke blocking connections from servers
with rDNS names that contain IP addresses?</a></li>
<li><a href="#TROUBLE12">I'm trying to run spamdyke's <code>config-test</code> feature but it only says "Missing qmail-smtpd command". What's wrong?</a></li>
@@ -178,6 +179,19 @@
</p>
<a name="GEN7"></a>
+<h2>I use Plesk. What is qmail? Can I still use spamdyke?</h2>
+<p>
+Yes. Plesk is a (large, complicated) control panel for configuring your server
+through a web interface. qmail is mail server software that handles email delivery.
+Plesk uses qmail under the hood and handles most of its configuration.
+</p><p>
+spamdyke works very well with Plesk, but there's no automated "push-button" way to
+install it. You'll need to connect to your server's command line (probably using SSH)
+to install it.
+If you're comfortable doing that, see the <a href="INSTALL.txt">INSTALL.txt file</a> for installation instructions.
+</p>
+
+<a name="GEN8"></a>
<h2>Do I have to install the programs from the "utils" directory? Does spamdyke use
them? Do they use spamdyke or each other?</h2>
<p>
@@ -192,7 +206,7 @@
else will be able to learn from them. Aren't I just a swell guy?
</p>
-<a name="GEN8"></a>
+<a name="GEN9"></a>
<h2>When I reconfigure spamdyke, do I have to restart qmail?</h2>
<p>
Usually not but it depends on what you've done.
@@ -211,7 +225,7 @@
</ul>
</p>
-<a name="GEN9"></a>
+<a name="GEN10"></a>
<h2>What is the difference between a right-hand-side blacklist (RHSBL) and a realtime blackhole list (RBL)?</h2>
<p>
<dl>
@@ -255,7 +269,7 @@
</dl>
</p>
-<a name="GEN10"></a>
+<a name="GEN11"></a>
<h2>Which RBLs and/or RHSBLs do you recommend?</h2>
<p>
None. Blacklists are a sensitive issue. Their legal status is uncertain, depending on what country
@@ -274,7 +288,7 @@
the best indicator of a list operator's true attitude.
</p>
-<a name="GEN11"></a>
+<a name="GEN12"></a>
<h2>What operating systems and versions do you test spamdyke with?</h2>
<p>
On the following systems, spamdyke's configuration script executes correctly, it compiles
@@ -283,6 +297,7 @@
<li>Apple OS X 10.6</li>
<li>CentOS 5.2 64-bit</li>
<li>CentOS 5.5</li>
+<li>Debian 7 RC2</li>
<li>Fedora Core 4</li>
<li>Fedora 11</li>
<li>FreeBSD 2.2.2</li>
@@ -303,7 +318,7 @@
be fixed and your system can be added to the list of test environments.
</p>
-<a name="GEN12"></a>
+<a name="GEN13"></a>
<h2>I love spamdyke! How can I help? Can I send you money?</h2>
<p>
Thank you for your generosity, but I must decline donations. I started writing spamdyke to meet my own needs.
@@ -347,7 +362,7 @@
more expensive than file searches, pattern matching is more expensive than
simply checking for a file's existence, etc.
</p><p>
-The remaining filters are all checked during the SMTP conversation.
+The following filters are all checked during the SMTP conversation.
<dl>
<dd>Check sender whitelists
<dd>Check right-hand-side whitelists for the sender's domain name
@@ -362,12 +377,18 @@
<dd>Check for identical sender and recipient addresses
<dd>Graylisting
</dl>
+</p><p>
+The following filters are checked while the message body is being sent.
+<dl>
+<dd>Check header blacklists
+</dl>
+</p><p>
If spamdyke is passing TLS traffic to qmail without processing (i.e.
spamdyke wasn't compiled with TLS support or doesn't have access to the server
certificate), none of these filters are run.
</p><p>
When spamdyke's <code>config-dir</code> option is in use, no filters are
-run until after the remote server gives the recipient's address. This is
+run before the remote server gives the recipient's address. This is
because spamdyke must load any additional configuration files before it
will know which filters to run.
</p>
@@ -405,7 +426,7 @@
<a name="FEATURE5"></a>
<h2>I want to block all emails unless the sender authenticates. Can spamdyke do that?</h2>
<p>
-Yes. As of version 4.0.0, spamdyke accepts the <code>smtp-auth-level</code> option. When it is set to <code>require-auth</code>,
+Yes! As of version 4.0.0, spamdyke accepts the <code>smtp-auth-level</code> option. When it is set to <code>require-auth</code>,
all connections are rejected unless the sender has authenticated.
</p><p>
Prior to version 4.0.0, the easiest way to accomplish this was to first enable SMTP AUTH. Then, create an IP blacklist file that will block all IP addresses:
@@ -452,7 +473,7 @@
</p>
<a name="FEATURE8"></a>
-<h2>I want to disable some filters for a few domains and enable them for everyone else. Is that possible?</h2>
+<h2>I want to disable some filters for a few domains (or users) and enable them for everyone else. Is that possible?</h2>
<p>
Yes, as of spamdyke version 4.0.0. Configuration directories allow per-domain
configuration of most of spamdyke's features.
@@ -478,6 +499,9 @@
<dd><code>reject-unresolvable-rdns=0</code></dd>
<dd><code>ip-in-rdns-keyword-blacklist-file=!!!</code></dd>
</dl>
+To accomplish this for a specific user instead of an entire domain, a longer filename is
+used. For example, to do the above scenario for joe@example.com instead of all users in
+example.com, the file would be named <code>/etc/spamdyke/config.d/_recipient_/com/example/_at_/joe</code>.
Configuration directories can be used to accomplish many complex tasks. For example,
if the file for a specific domain contained options to read blacklist and whitelist
files from the domain owner's home directory, the domain owner could update their own
@@ -489,7 +513,7 @@
<a name="FEATURE9"></a>
<h2>My users' PCs are infected with spambots and are sending spam through my server. Can I force them to authenticate to block the spam?</h2>
<p>
-Yes. See the above question (<a href="#FEATURE8">I want to disable some filters for a few domains and enable them for everyone else. Is that possible?</a>).
+Yes. See the above question (<a href="#FEATURE8">I want to disable some filters for a few domains (or users) and enable them for everyone else. Is that possible?</a>).
In the configuration directory for each of your local domains, add the option:
<dl>
<dd><code>filter-level=require-auth</code></dd>
@@ -606,46 +630,24 @@
</p>
<a name="SUGGESTION3"></a>
-<h2>Why can't spamdyke filter based on message headers like "From:" or "Received:"?
-Why can't spamdyke block large messages or strip attachments?</h2>
+<h2>Why can't spamdyke filter based on message headers like "From:" or "Received:"?</h2>
<p>
-To understand why, a little explanation of the SMTP protocol is necessary.
-</p><p>
-After some conversational preliminaries, an SMTP client gives the server a
-sender address. This address is referred to as the "envelope
-sender" and it's used as a return address if the message bounces. Here's the
-part most users don't understand: The "envelope sender" doesn't have to be the
-same address you see on the "From" line. The two aren't related at all; the
-"From" line is mostly for show (this is why spam "From" lines are so often
-forged).
-</p><p>
-If the server accepts the "envelope sender" address, the client sends the
-addresses of the message recipients, one at a time. The recipient addresses
-are for message delivery. The server must accept or reject each recipient individually.
-Once again, the "To" and "Cc" lines aren't related at all; they're mostly for show.
-</p><p>
-If the server accepts one or more recipients, the client sends the message.
-The server accepts or rejects the message and the conversation is over.
-</p><p>
-spamdyke makes a decision whether to accept or reject senders and recipients
-during the first two steps because those steps must be acknowleged separately.
-Once the client sends the actual message, it can't be rejected.
-</p><p>
-Well, yes, technically, according to the RFCs, it can be rejected. However, most
-MTAs don't handle this situation correctly and bounce the message if they see
-anything other than a success code after sending the message. This is a Bad
-Thing. If the rejection was for graylisting, the client won't retry delivery.
-If the rejection was for one recipient out of many, the client (and therefore
-the sending user) won't understand why the error was given. The message will
-just bounce and that's it.
-</p><p>
-There are many, many tools for filtering messages based on headers and content
-that are far, far smarter and feature-rich than spamdyke. If you really want to
-filter based on message headers, please use one of them in addition to spamdyke.
-Personally, I use (and recommend) SpamAssassin and ClamAV.
+As of version 4.3.0, it can.
+See the <a href="README.html">README page</a> for complete details.
</p>
<a name="SUGGESTION4"></a>
+<h2>Why can't spamdyke block large messages or strip attachments?</h2>
+<p>
+Since header blacklisting was added in version 4.3.0, this may now be possible.
+However, it will require buffering the incoming message into a file on disk;
+with large attachments being so common, there is no way spamdyke could possibly
+(or responsibly) buffer entire messages in memory.
+</p><p>
+Look for this feature in a future version.
+</p>
+
+<a name="SUGGESTION5"></a>
<h2>Why can't spamdyke validate a recipient address before accepting a message?</h2>
<p>
This would be very nice to have but it's not very easy to
@@ -658,13 +660,13 @@
That code hasn't been integrated into spamdyke yet because it hasn't been fully tested.
</p>
-<a name="SUGGESTION5"></a>
+<a name="SUGGESTION6"></a>
<h2>My graylist directories are getting huge -- many, many entries. Is this is a problem? What can I do?</h2>
<p>
For most servers, it isn't a problem, since most of the files contain no data. However,
it might be a problem if the server's filesystem runs out of inodes. (An inode is basically
a file index within the filesystem. The number of available inodes is large but not infinite;
-when a file system runs out of inodes, no new files can be created.)
+when a file system runs out of inodes, no new files can be created even though there is available disk space.)
</p><p>
On most Unix-like systems, the <code>df</code> command will show the amount of free
space on all of the mounted filesystems. To show the number of available inodes, use
@@ -687,7 +689,7 @@
entries that are less than two weeks old.
</p>
-<a name="SUGGESTION6"></a>
+<a name="SUGGESTION7"></a>
<h2>Why can't spamdyke automatically delete old graylist entries?</h2>
<p>
spamdyke doesn't automatically delete old graylist entries because it doesn't run as a
@@ -703,7 +705,7 @@
multiple incoming messages and place an unnecessary load on the server.
</p>
-<a name="SUGGESTION7"></a>
+<a name="SUGGESTION8"></a>
<h2>Instead of trying to prevent relaying itself, why doesn't spamdyke just set the <code>RELAYCLIENT</code>
environment variable based on authentication/sender address/recipient address?</h2>
<p>
@@ -736,7 +738,7 @@
precisely control spamdyke's relay filter.
</p>
-<a name="SUGGESTION8"></a>
+<a name="SUGGESTION9"></a>
<h2>Why can't spamdyke automatically blacklist (or delay) servers that are rejected too many times?</h2>
<p>
Technically, this is not possible because spamdyke of the way spamdyke works. Without a long-running
@@ -765,7 +767,7 @@
as effective.
</p>
-<a name="SUGGESTION9"></a>
+<a name="SUGGESTION10"></a>
<h2>Why doesn't spamdyke's graylist filter use the IP address of the remote server?</h2>
<p>
At first glance, it seems more effective to use three criteria for graylisting: the sender's email
@@ -887,8 +889,8 @@
</ol>
That's a lot of queries. If your DNS servers aren't fast enough to keep up, you're
going to see delays in spamdyke. To alleviate this, try installing a caching nameserver
-on your mail server. If you still see delays, begin disabling DNS-based filters until
-spamdyke begins running faster.
+on your mail server (most operating systems have a pre-built package for this).
+If you still see delays, begin disabling DNS-based filters until spamdyke begins running faster.
</p><p>
If you have disabled all of the filters and spamdyke is still running slowly, you may
have found a bug. Please report it!
@@ -987,17 +989,18 @@
If you're seeing strange malfunctions/errors and you suspect memory might be the issue, first try
setting it to a ridiculously high value for a short time. If the malfunctions/errors stop, you've
found the cause.
-</p><p>
Unfortunately, there doesn't seem to be a good way to determine what the limit should be. Some tutorials recommend
10 MB, others 40 MB or even 80 MB. Some guides recommend using trial-and-error to find a limit
-where everything appears to work, then doubling it.
+where everything appears to work, then doubling it. <b>A better suggestion is to simply remove
+<code>softlimit</code>.</b> Given the present maturity of qmail's code, it should be considered a "solution looking
+for a problem" (and more often creating them).
</p><p>
Good luck!
</p>
<a name="TROUBLE10"></a>
<h2>Why are messages still being rejected even after I've added the sender's domain name to my rDNS whitelist? <b>OR</b>
-Why aren't message being rejected after I've added the sender's domain name to my rDNS blacklist?</h2>
+Why aren't messages being rejected after I've added the sender's domain name to my rDNS blacklist?</h2>
<p>
The rDNS white/blacklist works by matching the remote server's reverse DNS name (the name that is found by querying
the remote server's IP address through the DNS system). The sender white/blacklist works by matching the sender's email address.
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/documentation/README.html
^
|
@@ -20,7 +20,7 @@
features and behavior. If you need documentation for an older version, each version's README
file is included in the download package for that version.
</p><p>
-<b>This document applies to spamdyke version 4.2.1.</b>
+<b>This document applies to spamdyke version 4.3.1.</b>
<ul>
<li><a href="#ABOUT">About spamdyke</a></li>
<li><a href="#SUPPORT">Support</a></li>
@@ -50,6 +50,7 @@
<li><a href="#GRAYLISTS">Graylisting / Greylisting</a></li>
<li><a href="#EARLYTALKERS">Earlytalkers</a></li>
<li><a href="#MAXRECIPIENTS">Limiting Numbers of Recipients</a></li>
+<li><a href="#HEADERS">Rejecting Messages by Header Content</a></li>
<li><a href="#TIMEOUTS">Timeouts</a></li>
<li><a href="#UTILITIES">Extra Utilities</a></li>
</ul>
@@ -63,7 +64,7 @@
<dd><a href="UPGRADING.txt">Upgrading instructions: UPGRADING.txt</a>
<dd><a href="FAQ.html">Frequently Asked Questions: FAQ.html</a>
<dd><a href="Changelog.txt">Change log: Changelog.txt</a>
-<dd><a href="TODO.txt">To-do list: TODO.txt</a>
+<dd><a href="development_notes/TODO.txt">To-do list: TODO.txt</a>
</dl>
</p>
@@ -983,6 +984,44 @@
</td>
</tr><tr>
+<td><code>header-blacklist-entry</code></td>
+<td> </td>
+<td><code>VALUE</code></td>
+<td>
+Reject any message with a header line that matches <code>VALUE</code>.
+<br /><br />
+If <code>header-blacklist-entry</code> is given multiple times, spamdyke will match the message
+headers against each <code>VALUE</code> given.
+<br /><br />
+If <code>header-blacklist-entry</code> and <code>header-blacklist-file</code> are not given,
+spamdyke will not filter any message based on their header content.
+<br /><br />
+<code>header-blacklist-entry</code> is valid within configuration directories but entries found
+there accumulate and apply to all recipients, not just one.
+<br /><br />
+See <a href="#HEADERS">Rejecting Messages by Header Content</a> for details.
+</td>
+
+</tr><tr>
+<td><code>header-blacklist-file</code></td>
+<td> </td>
+<td><code>FILE</code></td>
+<td>
+Reject any message with a header line that matches a line in <code>FILE</code>.
+<br /><br />
+If <code>header-blacklist-file</code> is given multiple times, spamdyke will match the message
+headers against each line in each given <code>FILE</code>.
+<br /><br />
+If <code>header-blacklist-entry</code> and <code>header-blacklist-file</code> are not given,
+spamdyke will not filter any message based on their header content.
+<br /><br />
+<code>header-blacklist-file</code> is valid within configuration directories but entries found
+there accumulate and apply to all recipients, not just one.
+<br /><br />
+See <a href="#HEADERS">Rejecting Messages by Header Content</a> for details.
+</td>
+
+</tr><tr>
<td><code>hostname</code></td>
<td> </td>
<td><code>NAME</code></td>
@@ -1745,6 +1784,24 @@
</td>
</tr><tr>
+<td><code>rejection-text-header-blacklist</code></td>
+<td> </td>
+<td><code>TEXT</code></td>
+<td>
+Send <code>TEXT</code> to the client as an error message if
+the message is blocked because a header line matches a header blacklist.
+<br /><br />
+If <code>rejection-text-header-blacklist</code> is given multiple times, spamdyke will use the last value it finds.
+<br /><br />
+If <code>rejection-text-header-blacklist</code> is not given, spamdyke will use the text
+<code class="breakable">Refused. Your message has been blocked due to its content.</code>
+<br /><br />
+If <code>rejection-text-header-blacklist</code> is not valid within configuration directories.
+<br /><br />
+See <a href="#SMTP_ERROR">SMTP Error Codes</a> for details.
+</td>
+
+</tr><tr>
<td><code>rejection-text-identical-sender-recipient</code></td>
<td> </td>
<td><code>TEXT</code></td>
@@ -2786,7 +2843,10 @@
<tr>
<td><code>ALLOWED</code></td>
-<td>The message passed all filters. qmail may still bounce the message for other reasons, however.</td>
+<td>The message passed all filters. qmail may still bounce the message later for other reasons, however.<br/>
+<br/>
+<code>REASON</code> will contain the text of qmail's response.
+</td>
<td> </td>
</tr>
@@ -2879,6 +2939,20 @@
</tr>
<tr>
+<td><code>DENIED_HEADER_BLACKLISTED</code></td>
+<td>The message was blocked because one or more header lines matched
+a header blacklist.<br/>
+<br/>
+<code>REASON</code> will contain the matching entry if <code>header-blacklist-entry</code> was used or the filename and matching line
+number if <code>header-blacklist-file</code> was used.
+</td>
+<td>
+<code>header-blacklist-entry</code><br />
+<code>header-blacklist-file</code>
+</td>
+</tr>
+
+<tr>
<td><code>DENIED_IDENTICAL_SENDER_RECIPIENT</code></td>
<td>The connection was blocked because the sender's email address is the same as
the recipient's email address.</td>
@@ -3155,6 +3229,7 @@
<code>rejection-text-earlytalker</code><br />
<code>rejection-text-empty-rdns</code><br />
<code>rejection-text-graylist</code><br />
+<code>rejection-text-header-blacklist</code><br />
<code>rejection-text-identical-sender-recipient</code><br />
<code>rejection-text-ip-blacklist</code><br />
<code>rejection-text-ip-in-cc-rdns</code><br />
@@ -3240,6 +3315,14 @@
</tr>
<tr>
+<td><code>DENIED_HEADER_BLACKLISTED</code></td>
+<td>
+<code>Refused. Your message has been blocked due to its content.</code>
+</td>
+<td><code>rejection-text-header-blacklist</code></td>
+</tr>
+
+<tr>
<td><code>DENIED_IDENTICAL_SENDER_RECIPIENT</code></td>
<td>
<code>Refused. Identical sender and recipient addresses are not allowed.</code>
@@ -4558,6 +4641,87 @@
and they will complain. Loudly.
</p>
+<a name="HEADERS"></a>
+<h2>Rejecting Messages by Header Content</h2>
+<h3>
+<code>blacklist-header-entry</code><br />
+<code>blacklist-header-file</code>
+</h3>
+<p>
+Email messages are divided into two parts: the header and the body. The header
+is composed of data fields that are parsed by mail agents so the data can be
+shown to the user in a useful way. For example, the subject line and the date
+are part of the header. The message body contains all of the text (often HTML
+these days) and attachment data.
+<p></p>
+spamdyke has the ability to filter incoming messages based on header content.
+Every header line is supposed to use the following format:
+<dl>
+<dd><code>NAME: VALUE</code>
+</dl>
+For example:
+<dl>
+<dd><code>Subject: Fantastic news!</code>
+</dl>
+When <code>header-blacklist-entry</code> is used, its value will be matched
+against each line in the incoming message header. If one or more lines match,
+the message will be rejected. <code>blacklist-header-file</code> works much the
+same way, except the values are read from the given file, one per line.
+<p></p>
+Before attempting to match values to headers, spamdyke first compresses any
+whitespace by converting runs of multiple whitespace characters to a single space.
+If the header line in the message occupies multiple lines, spamdyke "unfolds" it
+into a single line. The values are then compared in a case-insensitive manner.
+All values must contain at least one colon (<code>:</code>) or they will be ignored.
+<p></p>
+Shell-style wildcards are allowed ("globbing"):
+<ul>
+<li>An asterisk (<code>*</code>) will match zero or more characters.
+<li>A question mark (<code>?</code>) will match a single character.
+<li>A bracketed series of characters (e.g. <code>[abcd]</code>) will match any one of the bracketed characters.
+<li>...probably more, depending on the implementation of <code>fnmatch()</code> on your system.
+</ul>
+For example, this value:
+<dl>
+<dd><code>Subject:*c?a[i1]is*</code>
+</dl>
+Will match any of the following:
+<dl>
+<dd><code>Subject: cialis</code>
+<dd><code>Subject: Got some cialis for you</code>
+<dd><code>Subject: Need cXalis?</code>
+<dd><code>Subject: Order cia1is today</code>
+</dl>
+<p></p>
+<b>NOTE:</b> Be very careful when adding header blacklists. Spammers are very clever
+about avoiding content filtering (they have decades of experience) but normal users
+are not. It is very easy to create a blacklist entry that will block legitimate
+email without blocking any spam at all.
+<p></p>
+<b>NOTE:</b> In order to filter headers, spamdyke must buffer the header
+content in memory while the message is being delivered. It will allocate up to
+512K to do this. <b>If you are using DJB's "softlimit" program to prevent excessive
+memory allocation, you should remove it before enabling header blacklisting.</b>
+<p></p>
+When <code>header-blacklist-entry</code> or <code>header-blacklist-file</code>
+are used within per-recipient configuration directories, they don't behave like
+other options. Most options can be set per-recipient and only affect delivery to
+that recipient. Header blacklisting is an all-or-nothing affair, so when those
+options are found in a per-recipient configuration directory, they are cumulative.
+For example, suppose two recipients have configuration directories. In the first
+recipient's directory, the following option is found:
+<dl>
+<dd><code>header-blacklist-entry=Subject: Cialis</code>
+</dl>
+In the second recipient's directory, another option is found:
+<dl>
+<dd><code>header-blacklist-entry=Subject: Viagra</code>
+</dl>
+When spamdyke applies the header blacklist filter, both values will be used.
+If either one matches, the message will be rejected for both recipients (assuming
+the incoming message is being delivered to both recipients simultaneously).
+</p>
+
<a name="TIMEOUTS"></a>
<h2>Timeouts</h2>
<h3>
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/documentation/UPGRADING.txt
^
|
@@ -7,6 +7,12 @@
options and features. Be sure to check that file for full details on these
changes.
+UPGRADING FROM VERSION 4.3.0 to 4.3.1:
+ All changes are backwards compatible.
+
+UPGRADING FROM VERSION 4.2.1 to 4.3.0:
+ All changes are backwards compatible.
+
UPGRADING FROM VERSION 4.2.0 to 4.2.1:
All changes are backwards compatible.
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/documentation/development_notes/TODO.txt
^
|
@@ -8,11 +8,14 @@
Add full support for IPv6.
ALSO TODO:
- Add recipient validation. This will probably require reimplementing
- qmail's/vpopmail's .qmail file parser. DO NOT reuse code from qmail or
- vpopmail.
+ Add regex versions of the options for graylist-exception-rdns,
+ ip-in-rdns-keyword-blacklist, ip-in-rdns-keyword-whitelist,
+ rdns-blacklist, rdns-whitelist, recipient-blacklist, recipient-whitelist,
+ sender-blacklist, sender-whitelist, and header-blacklist
+ "Some people, when confronted with a problem, think 'I know, I'll use
+ regular expressions.' Now they have two problems." — Jamie Zawinski
+ Finish testing the recipient validation code and add it to the codebase.
DKIM/SPF support, including ability to use valid DKIM/SPF as whitelists
- Full log conditionality, based on IP or rDNS or more.
Make spamdyke log message information: From/To/Cc/Subject lines (better yet
make this configurable), presence of attachments and message size.
Add flags to blackhole mail instead of rejecting it. Make this work correctly
@@ -36,8 +39,6 @@
@domain. Credit goes to stephan.
Consider adding a filter to block messages where the From field doesn't match
the envelope sender.
- Consider changing the logging of DENIED_OTHER to include the rejection text
- from the downstream filter. Credit goes to David Stiller.
Make spamdyke output a message for every connection no matter what, even a
short connect/disconnect. Credit goes to Eric Shubert.
Create an IP-testing function (to check parsability and ranges) and change all
@@ -80,8 +81,6 @@
Fix the DNS spoofing "bug" by randomizing the outbound port with every query.
Try not to panic about it like CERT/CC did.
Consider adding support for Maxmind's GeoIP. Credit goes to Andras Korn.
- Implement LaBrea-style tarpitting when spamdyke is used to accept incoming
- network connections.
Add a feature to limit simultaneous (or per-time-period) connections per
IP/rDNS/sender/recipient.
Log the Message-ID field so a message can be tracked from delivery to disk.
@@ -101,11 +100,6 @@
Add a way to make the ip-in-rdns feature more or less aggressive. This would
include matching portions of the IP address or allowing multiple characters
betweeen octets. Credit goes to Marcin Orlowski.
- Consider supporting CDB files.
- Add a flag to use regexps in email address files (recipient/sender
- white/blacklists)
- "Some people, when confronted with a problem, think 'I know, I'll use
- regular expressions.' Now they have two problems." — Jamie Zawinski
After spamdyke becomes a daemon, add a feature to periodically clean out the
graylist folders.
After spamdyke becomes a daemon, add a feature to periodically write statistics
@@ -129,5 +123,3 @@
Find a way to query WHOIS for incoming domain names and reject all domains
newer than 5 days (domain tasting limit).
Add the ability to forward to multiple different servers at the same time.
- Add a way to block messages based on the character set, so foreign language
- spam can be blocked regardless of source.
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/documentation/policy.php.example
^
|
@@ -162,7 +162,7 @@
*/
$codes = array();
$codes['DENIED_RBL_MATCH']['message'] = 'Refused. Your IP address is listed in the RBL at "name"';
-$codes['DENIED_RBL_MATCH']['solution'][] = 'We are using the Real Time Blacklist mentionned above. You have to contact them in order to be unlisted.';
+$codes['DENIED_RBL_MATCH']['solution'][] = 'We are using the Real Time Blacklist mentioned above. You have to contact them in order to be unlisted.';
$codes['DENIED_RBL_MATCH']['solution'][] = 'To check where your IP address is listed, you can use <a href="http://www.blacklistalert.org/">www.blacklistalert.org</a>, <a href="http://openrbl.org/client/">www.openrbl.org/client/</a> or <a href="http://www.sorbs.net/lookup.shtml">www.sorbs.net/lookup.shtml</a>.';
$codes['TIMEOUT']['message'] = 'Timeout. Talk faster next time.';
$codes['TIMEOUT']['solution'][] = 'Our server can only wait so long for your server to send information. If your connection (or your server) is too slow, our server will hang up after a while. Lots of spam software seems to connect and just wait forever, so we have to give up at some point or we\'ll end up connected to everyone.';
@@ -213,6 +213,8 @@
$codes['DENIED_AUTH_REQUIRED']['solution'][] = 'We do not accept any email unless the sender authenticates first. Reconfigure your mail client and try again.';
$codes['DENIED_IDENTICAL_SENDER_RECIPIENT']['message'] = 'Refused. Identical sender and recipient addresses are not allowed.';
$codes['DENIED_IDENTICAL_SENDER_RECIPIENT']['solution'][] = 'You are attempting to send email both "to" and "from" the same address, which we don\'t accept. In most cases, authenticating your connection will avoid this block.';
+$codes['DENIED_HEADER_BLACKLISTED']['message'] = 'Refused. Your message has been blocked due to its content.';
+$codes['DENIED_HEADER_BLACKLISTED']['solution'][] = 'Your message contains content that we don\'t accept. Most likely (but not always), the problem is your subject line. Try rewording the subject of your message.';
/****** HTML content ******/
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/documentation/spamdyke.conf.example
^
|
@@ -1,4 +1,4 @@
-# This is an example spamdyke configuration file for spamdyke version 4.2.1.
+# This is an example spamdyke configuration file for spamdyke version 4.3.1.
#
# Without editing, this file will do nothing -- every available option is
# commented out. To enable options, edit the values and remove the comment
@@ -152,6 +152,14 @@
# Default: none
#ip-in-rdns-keyword-blacklist-file=FILE
+# Reject all messages with header lines that match VALUE.
+# Default: none
+#header-blacklist-entry=VALUE
+
+# Reject all messages sent header lines that match entries in FILE.
+# Default: none
+#header-blacklist-file=FILE
+
################################################################################
# LOCAL WHITELISTS
################################################################################
@@ -473,6 +481,11 @@
# Default: "Your address has been graylisted. Try again later."
#rejection-text-graylist=TEXT
+# Use TEXT as the rejection message when a message is blocked because it
+# contains blacklisted header content.
+# Default: "Refused. Your message has been blocked due to its content."
+#rejection-text-header-blacklist=TEXT
+
# Use TEXT as the rejection message when a recipient is blocked because it
# exactly matches the sender address.
# Default: "Refused. Identical sender and recipient addresses are not allowed."
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/config_test.c
^
|
@@ -949,7 +949,7 @@
if (S_ISREG(config_test_file_type(letter_name, sld_ent)))
{
- strlen_fqdn = snprintf(fqdn, MAX_BUF, ".%s.%s", letter_ent->d_name, top_ent->d_name);
+ snprintf(fqdn, MAX_BUF, ".%s.%s%n", letter_ent->d_name, top_ent->d_name, &strlen_fqdn);
strlen_filename = strlen(sld_ent->d_name);
if ((((strlen_fqdn - 1) != strlen_filename) ||
@@ -1156,7 +1156,7 @@
opad[j] ^= secret[j];
}
- strlen_challenge = snprintf(challenge, MAX_BUF - 64, "<%ld.%ld@%s>", random(), (long)time(NULL), (current_settings->current_options->local_server_name != NULL) ? current_settings->current_options->local_server_name : MISSING_LOCAL_SERVER_NAME);
+ snprintf(challenge, MAX_BUF - 64, "<%ld.%ld@%s>%n", random(), (long)time(NULL), (current_settings->current_options->local_server_name != NULL) ? current_settings->current_options->local_server_name : MISSING_LOCAL_SERVER_NAME, &strlen_challenge);
for (j = 0; j < strlen_challenge; j++)
ipad[j + 64] = challenge[j];
@@ -1216,8 +1216,13 @@
int config_test_tls_certificate(struct filter_settings *current_settings, struct spamdyke_option *target_option)
{
int return_value;
+
+#ifdef HAVE_LIBSSL
+
int test_result;
+#endif /* HAVE_LIBSSL */
+
return_value = 1;
#ifdef HAVE_LIBSSL
@@ -1239,8 +1244,6 @@
#else /* HAVE_LIBSSL */
- test_result = 0;
-
if (current_settings->current_options->tls_certificate_file != NULL)
{
SPAMDYKE_LOG_ERROR(current_settings, CONFIG_TEST_ERROR_TLS_CERT_DISABLED, target_option->getopt_option.name, current_settings->current_options->tls_certificate_file);
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/configuration.c
^
|
@@ -309,6 +309,7 @@
int return_value;
int continue_processing;
struct filter_settings tmp_settings;
+ struct filter_settings *current_settings;
int short_code;
int i;
int j;
@@ -359,27 +360,34 @@
* option should be read as a boolean, an integer or a string. During
* configuration testing, the values are tested to ensure they meet the
* defined purpose of the option. Must be one of the following constants:
- *
+ *
* CONFIG_TYPE_NONE: This value is only set in the last member of the
* option_list array.
* CONFIG_TYPE_BOOLEAN: A yes/no option, stored as an integer.
* CONFIG_TYPE_INTEGER: An integer value
* CONFIG_TYPE_STRING_SINGLETON: A text value, stored only once. If the
* option is encountered multiple times, only the last value will be
- * retained.
+ * retained. This is not for options that are parsed (e.g. blacklist
+ * entries) but for actual text to be displayed somewhere.
* CONFIG_TYPE_STRING_ARRAY: A text value, can be given multiple times.
- * Each value is retained in an array.
- * CONFIG_TYPE_FILE_SINGLETON: A path to a file or directory, given as
+ * Each value is retained in an array. This is not for options that are
+ * parsed (e.g. blacklist entries) but for actual text to be displayed
+ * somewhere.
+ * CONFIG_TYPE_FILE_SINGLETON: A path to a file, not a directory, given as
* text, stored only once. If the option is encountered multiple times,
* only the last value will be retained.
* CONFIG_TYPE_FILE_NOT_DIR_SINGLETON: A path that must be to a file, not
* a directory, given as text, stored only once. If the option is
* encountered multiple times, only the last value will be retained.
- * CONFIG_TYPE_FILE_ARRAY: A path to a file or directory, given as text,
- * can be given multiple times. Each value is retained in an array.
+ * This type should only be used for "-file" options that have a
+ * corresponding "-dir" option.
+ * CONFIG_TYPE_FILE_ARRAY: A path to a file, not a directory, given as
+ * text, can be given multiple times. Each value is retained in an
+ * array.
* CONFIG_TYPE_FILE_NOT_DIR_ARRAY: A path that must be to a file, not a
* directory, given as text, can be given multiple times. Each value is
- * retained in an array.
+ * retained in an array. This type should only be used for "-file"
+ * options that have a corresponding "-dir" option.
* CONFIG_TYPE_DIR_SINGLETON: A path that must be to a directory, not a
* file, given as text, stored only once. If the option is encountered
* multiple times, only the last value will be retained.
@@ -523,7 +531,7 @@
* FILTER_GRACE_AFTER_TO: spamdyke should not close qmail until after all
* recipients have been identified
* FILTER_GRACE_AFTER_DATA: spamdyke should not close qmail until the
- * remote server tries to start sending message data
+ * remote server finishes sending message data
*
* test_function: A pointer to a function that can test the value of this
* option, if it needs special handling beyond checking the input value is
@@ -660,7 +668,7 @@
" Use this option with all other options that are given during normal operation. Default: do not test configuration."
},
{
- CONFIG_TYPE_STRING_SINGLETON,
+ CONFIG_TYPE_OPTION_SINGLETON,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE,
{ "config-test-smtpauth-password", required_argument, NULL, -1 },
@@ -680,7 +688,7 @@
" appear to be executable."
},
{
- CONFIG_TYPE_STRING_SINGLETON,
+ CONFIG_TYPE_OPTION_SINGLETON,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE,
{ "config-test-smtpauth-username", required_argument, NULL, -1 },
@@ -774,7 +782,7 @@
"Forcibly disconnect after a total of SECS seconds, regardless of activity. A value of 0 disables this feature. Default: 0"
},
{
- CONFIG_TYPE_STRING_ARRAY,
+ CONFIG_TYPE_OPTION_ARRAY,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE | CONFIG_LOCATION_DIR,
{ "dns-blacklist-entry", required_argument, NULL, 'x' },
@@ -791,7 +799,7 @@
"Check the remote server's IP address against the realtime blackhole list DNSRBL. If it is found, the connection is rejected. Default: do not check any DNS RBLs."
},
{
- CONFIG_TYPE_STRING_ARRAY,
+ CONFIG_TYPE_FILE_ARRAY,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE | CONFIG_LOCATION_DIR,
{ "dns-blacklist-file", required_argument, NULL, -1 },
@@ -974,7 +982,7 @@
"Read the list of system nameservers and DNS resolver options from FILE. Default: " DEFAULT_NIHDNS_RESOLVER_FILENAME
},
{
- CONFIG_TYPE_STRING_ARRAY,
+ CONFIG_TYPE_OPTION_ARRAY,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE,
{ "dns-server-ip", required_argument, NULL, -1 },
@@ -992,7 +1000,7 @@
" on port PORT (if present, otherwise use port " STRINGIFY(DEFAULT_NIHDNS_PORT) "). Default: nameserver configuration is read from the file given with \"dns-resolv-conf\"."
},
{
- CONFIG_TYPE_STRING_ARRAY,
+ CONFIG_TYPE_OPTION_ARRAY,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE,
{ "dns-server-ip-primary", required_argument, NULL, -1 },
@@ -1074,7 +1082,7 @@
"Wait at most SECS seconds for a response to any DNS query. Default: " STRINGIFY(DEFAULT_TIMEOUT_NIHDNS_TOTAL_SECS) "."
},
{
- CONFIG_TYPE_STRING_ARRAY,
+ CONFIG_TYPE_OPTION_ARRAY,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE | CONFIG_LOCATION_DIR,
{ "dns-whitelist-entry", required_argument, NULL, -1 },
@@ -1092,7 +1100,7 @@
" Default: do not check any DNS whitelists."
},
{
- CONFIG_TYPE_STRING_ARRAY,
+ CONFIG_TYPE_FILE_ARRAY,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE | CONFIG_LOCATION_DIR,
{ "dns-whitelist-file", required_argument, NULL, -1 },
@@ -1489,6 +1497,40 @@
NULL
},
{
+ CONFIG_TYPE_OPTION_ARRAY,
+ CONFIG_ACCESS_NONE,
+ CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE | CONFIG_LOCATION_DIR,
+ { "header-blacklist-entry", required_argument, NULL, -1 },
+ { .string_value = NULL },
+ { .string_value = NULL },
+ { .get_string_array = CONFIG_ACCESSOR_STRING_ARRAY(blacklist_header) },
+ { .max_strlen = 0 },
+ FILTER_DECISION_UNDECIDED,
+ FILTER_GRACE_NONE,
+ NULL,
+ NULL,
+ CONFIG_ACTION( if (!append_string_array(current_settings, ¤t_settings->blacklist_header, ¤t_settings->current_options->blacklist_header)) return(FILTER_DECISION_ERROR); ),
+ "VALUE",
+ "Reject any message with a header line matching VALUE. Default: do not check headers."
+ },
+ {
+ CONFIG_TYPE_FILE_ARRAY,
+ CONFIG_ACCESS_READ_ONLY,
+ CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE | CONFIG_LOCATION_DIR,
+ { "header-blacklist-file", required_argument, NULL, -1 },
+ { .string_value = NULL },
+ { .string_value = NULL },
+ { .get_string_array = CONFIG_ACCESSOR_STRING_ARRAY(blacklist_header_file) },
+ { .max_strlen = 0 },
+ FILTER_DECISION_UNDECIDED,
+ FILTER_GRACE_NONE,
+ NULL,
+ NULL,
+ CONFIG_ACTION( if (!append_string_array(current_settings, ¤t_settings->blacklist_header_file, ¤t_settings->current_options->blacklist_header_file)) return(FILTER_DECISION_ERROR); ),
+ "FILE",
+ "Reject any message with a header line matching an entry in FILE. Default: do not check headers."
+ },
+ {
CONFIG_TYPE_ACTION_ONCE,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE,
@@ -2226,6 +2268,23 @@
{
CONFIG_TYPE_STRING_SINGLETON,
CONFIG_ACCESS_NONE,
+ CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE,
+ { "rejection-text-header-blacklist", required_argument, NULL, -1 },
+ { .string_value = NULL },
+ { .string_value = NULL },
+ { .get_string = CONFIG_ACCESSOR_STRING(rejection_text[REJECTION_HEADER_BLACKLISTED]) },
+ { .max_strlen = 100 },
+ FILTER_DECISION_UNDECIDED,
+ FILTER_GRACE_NONE,
+ NULL,
+ NULL,
+ NULL,
+ "TEXT",
+ "Use TEXT as the rejection message when a message is blocked because its header contains blacklisted content. Default: \"" ERROR_HEADER_BLACKLISTED "\""
+ },
+ {
+ CONFIG_TYPE_STRING_SINGLETON,
+ CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE | CONFIG_LOCATION_DIR,
{ "rejection-text-identical-sender-recipient", required_argument, NULL, -1 },
{ .string_value = NULL },
@@ -2557,7 +2616,7 @@
" not given: no-check"
},
{
- CONFIG_TYPE_STRING_ARRAY,
+ CONFIG_TYPE_OPTION_ARRAY,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE | CONFIG_LOCATION_DIR,
{ "rhs-blacklist-entry", required_argument, NULL, 'X' },
@@ -2575,7 +2634,7 @@
" Default: do not check any DNS RBLs."
},
{
- CONFIG_TYPE_STRING_ARRAY,
+ CONFIG_TYPE_FILE_ARRAY,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE | CONFIG_LOCATION_DIR,
{ "rhs-blacklist-file", required_argument, NULL, -1 },
@@ -2593,7 +2652,7 @@
" connection is rejected. Default: do not check any DNS RBLs."
},
{
- CONFIG_TYPE_STRING_ARRAY,
+ CONFIG_TYPE_OPTION_ARRAY,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE | CONFIG_LOCATION_DIR,
{ "rhs-whitelist-entry", required_argument, NULL, -1 },
@@ -2611,7 +2670,7 @@
" domains). If it is found, all filters are bypassed. Default: do not check any RHS whitelists."
},
{
- CONFIG_TYPE_STRING_ARRAY,
+ CONFIG_TYPE_FILE_ARRAY,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE | CONFIG_LOCATION_DIR,
{ "rhs-whitelist-file", required_argument, NULL, -1 },
@@ -2629,7 +2688,7 @@
" contains whitelisted domains). If it is found, all filters are bypassed. Default: do not check any RHS whitelists."
},
{
- CONFIG_TYPE_STRING_SINGLETON,
+ CONFIG_TYPE_OPTION_SINGLETON,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE,
{ "run-as-user", required_argument, NULL, -1 },
@@ -2780,7 +2839,7 @@
" Ignored if \"tls-level\" is none."
},
{
- CONFIG_TYPE_STRING_SINGLETON,
+ CONFIG_TYPE_OPTION_SINGLETON,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE,
{ "tls-cipher-list", required_argument, NULL, -1 },
@@ -2841,7 +2900,7 @@
" Default: find the private key in the certificate file given with \"tls-certificate-file\"."
},
{
- CONFIG_TYPE_STRING_SINGLETON,
+ CONFIG_TYPE_OPTION_SINGLETON,
CONFIG_ACCESS_NONE,
CONFIG_LOCATION_CMDLINE | CONFIG_LOCATION_GLOBAL_FILE,
{ "tls-privatekey-password", required_argument, NULL, -1 },
@@ -2897,6 +2956,13 @@
{ CONFIG_TYPE_NONE }
};
+ /*
+ * This is here because the new -Waddress flag in gcc 4.6 will throw warnings
+ * when &tmp_settings is used as a parameter to the SPAMDYKE_LOG_* macros. By
+ * using a pointer variable, the warning is defeated.
+ */
+ current_settings = &tmp_settings;
+
tmp_settings.option_list = option_list;
tmp_settings.num_options = (sizeof(option_list) / sizeof(struct spamdyke_option)) - 1;
@@ -2920,7 +2986,7 @@
tmp_settings.allow_relay = 1;
tmp_settings.additional_domain_text[0] = '\0';
tmp_settings.inside_data = 0;
- tmp_settings.num_rcpt_to = 0;
+ tmp_settings.inside_header = 0;
tmp_settings.local_sender = 1;
tmp_settings.local_recipient = 1;
@@ -2928,6 +2994,9 @@
tmp_settings.sender_domain[0] = '\0';
tmp_settings.recipient_username[0] = '\0';
tmp_settings.recipient_domain[0] = '\0';
+ tmp_settings.allowed_recipients = NULL;
+ tmp_settings.num_recipients = 0;
+
tmp_settings.configuration_path[0] = '\0';
tmp_settings.child_argv = NULL;
@@ -2946,6 +3015,14 @@
tmp_settings.tls_state = TLS_STATE_INACTIVE;
+ tmp_settings.reconstructed_header[0] = '\0';
+ tmp_settings.strlen_reconstructed_header = 0;
+ tmp_settings.buf_retain = NULL;
+ tmp_settings.strlen_buf_retain = 0;
+ tmp_settings.max_buf_retain = 0;
+ tmp_settings.blacklist_header = NULL;
+ tmp_settings.blacklist_header_file = NULL;
+
#ifdef HAVE_LIBSSL
tmp_settings.tls_context = NULL;
@@ -2955,7 +3032,11 @@
continue_processing = 1;
- /* Replace the -1 short codes with auto-incremented values */
+ /*
+ * Replace the -1 short codes for getopt_long() with auto-incremented values.
+ * The values have to be unique, so this is much better than trying to set
+ * them to specific values above.
+ */
tmp_settings.max_short_code = 0;
num_options = 0;
for (i = 0; option_list[i].value_type != CONFIG_TYPE_NONE; i++)
@@ -3126,43 +3207,43 @@
{
group_ptr[0] = '\0';
group_ptr += STRLEN(USER_DELIMITER);
-
+
if (sscanf(group_ptr, FORMAT_GID_T, &tmp_gid) &&
snprintf(tmp_name, MAX_BUF, FORMAT_GID_T, tmp_gid) &&
!strcmp(tmp_name, group_ptr))
tmp_group = getgrgid(tmp_gid);
else
tmp_group = getgrnam(group_ptr);
-
+
if (tmp_group != NULL)
if (setgid(tmp_group->gr_gid) == 0)
- SPAMDYKE_LOG_EXCESSIVE(&tmp_settings, LOG_DEBUGX_SETGROUP, tmp_group->gr_name, tmp_group->gr_gid);
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_SETGROUP, tmp_group->gr_name, tmp_group->gr_gid);
else
- SPAMDYKE_LOG_ERROR(&tmp_settings, LOG_ERROR_SETGROUP, tmp_group->gr_name, tmp_group->gr_gid, strerror(errno));
+ SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_SETGROUP, tmp_group->gr_name, tmp_group->gr_gid, strerror(errno));
else
- SPAMDYKE_LOG_ERROR(&tmp_settings, LOG_ERROR_GETGROUP, group_ptr);
- }
-
+ SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_GETGROUP, group_ptr);
+ }
+
if (sscanf(tmp_settings.current_options->run_user, FORMAT_UID_T, &tmp_uid) &&
snprintf(tmp_name, MAX_BUF, FORMAT_UID_T, tmp_uid) &&
!strcmp(tmp_name, tmp_settings.current_options->run_user))
tmp_passwd = getpwuid(tmp_uid);
else
tmp_passwd = getpwnam(tmp_settings.current_options->run_user);
-
+
if (tmp_passwd != NULL)
if (setuid(tmp_passwd->pw_uid) == 0)
- SPAMDYKE_LOG_EXCESSIVE(&tmp_settings, LOG_DEBUGX_SETUSER, tmp_passwd->pw_name, tmp_passwd->pw_uid);
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_SETUSER, tmp_passwd->pw_name, tmp_passwd->pw_uid);
else
- SPAMDYKE_LOG_ERROR(&tmp_settings, LOG_ERROR_SETUSER, tmp_passwd->pw_name, tmp_passwd->pw_uid, strerror(errno));
+ SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_SETUSER, tmp_passwd->pw_name, tmp_passwd->pw_uid, strerror(errno));
else
- SPAMDYKE_LOG_ERROR(&tmp_settings, LOG_ERROR_GETUSER, tmp_settings.current_options->run_user);
- }
+ SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_GETUSER, tmp_settings.current_options->run_user);
+ }
else
- SPAMDYKE_LOG_DEBUG(&tmp_settings, LOG_DEBUG_NO_SETUSER, ((tmp_passwd = getpwuid(geteuid())) != NULL) ? tmp_passwd->pw_name : LOG_MISSING_DATA, geteuid());
+ SPAMDYKE_LOG_DEBUG(current_settings, LOG_DEBUG_NO_SETUSER, ((tmp_passwd = getpwuid(geteuid())) != NULL) ? tmp_passwd->pw_name : LOG_MISSING_DATA, geteuid());
endpwent();
-
+
if (tmp_settings.current_options->config_file != NULL)
for (i = 0; tmp_settings.current_options->config_file[i] != NULL; i++)
if ((tmp_settings.current_options->filter_action = process_config_file(&tmp_settings, tmp_settings.current_options->config_file[i], tmp_settings.current_options->filter_action, CONFIG_LOCATION_GLOBAL_FILE, NULL)) == FILTER_DECISION_ERROR)
@@ -3202,6 +3283,7 @@
else
return_value = 111;
+ /* Release all of the allocated memory. Just for neatness. */
free_current_options(&tmp_settings);
for (i = 0; option_list[i].value_type != CONFIG_TYPE_NONE; i++)
@@ -3258,6 +3340,16 @@
tmp_settings.long_options = NULL;
}
+ if (tmp_settings.buf_retain != NULL)
+ {
+ free(tmp_settings.buf_retain);
+ tmp_settings.buf_retain = NULL;
+ }
+
+ free_string_array(&tmp_settings.allowed_recipients, NULL);
+ free_string_array(&tmp_settings.blacklist_header, NULL);
+ free_string_array(&tmp_settings.blacklist_header_file, NULL);
+
free_environment(tmp_settings.original_environment, &tmp_settings.current_environment, NULL);
return(return_value);
@@ -3274,7 +3366,7 @@
char ***string_array_ptr;
} ptr;
char tmp_data[MAX_BUF + 1];
- char strlen_data;
+ int strlen_data;
if (current_settings->current_options->log_dir != NULL)
{
@@ -3288,7 +3380,7 @@
((ptr.integer_ptr = (*current_settings->option_list[i].getter.get_integer)(current_settings->current_options)) != NULL) &&
((*(ptr.integer_ptr)) != current_settings->option_list[i].default_value.integer_value))
{
- strlen_data = snprintf(tmp_data, MAX_BUF, "%s" VALUE_DELIMITER "%d\n", current_settings->option_list[i].getopt_option.name, *(ptr.integer_ptr));
+ snprintf(tmp_data, MAX_BUF, "%s" VALUE_DELIMITER "%d\n%n", current_settings->option_list[i].getopt_option.name, *(ptr.integer_ptr), &strlen_data);
output_writeln(current_settings, LOG_ACTION_CURRENT_CONFIG, -1, tmp_data, strlen_data);
}
@@ -3300,7 +3392,7 @@
for (j = 0; current_settings->option_list[i].validity.string_list.strings[j] != NULL; j++)
if ((*(ptr.integer_ptr)) == current_settings->option_list[i].validity.string_list.integers[j])
{
- strlen_data = snprintf(tmp_data, MAX_BUF, "%s" VALUE_DELIMITER "%s\n", current_settings->option_list[i].getopt_option.name, current_settings->option_list[i].validity.string_list.strings[j]);
+ snprintf(tmp_data, MAX_BUF, "%s" VALUE_DELIMITER "%s\n%n", current_settings->option_list[i].getopt_option.name, current_settings->option_list[i].validity.string_list.strings[j], &strlen_data);
output_writeln(current_settings, LOG_ACTION_CURRENT_CONFIG, -1, tmp_data, strlen_data);
break;
@@ -3314,7 +3406,7 @@
for (j = 0; current_settings->option_list[i].validity.string_list.strings[j] != NULL; j++)
if (((*(ptr.integer_ptr)) & current_settings->option_list[i].validity.string_list.integers[j]) != 0)
{
- strlen_data = snprintf(tmp_data, MAX_BUF, "%s" VALUE_DELIMITER "%s\n", current_settings->option_list[i].getopt_option.name, current_settings->option_list[i].validity.string_list.strings[j]);
+ snprintf(tmp_data, MAX_BUF, "%s" VALUE_DELIMITER "%s\n%n", current_settings->option_list[i].getopt_option.name, current_settings->option_list[i].validity.string_list.strings[j], &strlen_data);
output_writeln(current_settings, LOG_ACTION_CURRENT_CONFIG, -1, tmp_data, strlen_data);
}
@@ -3331,7 +3423,7 @@
((current_settings->option_list[i].default_value.string_value == NULL) ||
(strcmp((*(ptr.string_ptr)), current_settings->option_list[i].default_value.string_value) != 0)))
{
- strlen_data = snprintf(tmp_data, MAX_BUF, "%s" VALUE_DELIMITER "%s\n", current_settings->option_list[i].getopt_option.name, *(ptr.string_ptr));
+ snprintf(tmp_data, MAX_BUF, "%s" VALUE_DELIMITER "%s\n%n", current_settings->option_list[i].getopt_option.name, *(ptr.string_ptr), &strlen_data);
output_writeln(current_settings, LOG_ACTION_CURRENT_CONFIG, -1, tmp_data, strlen_data);
}
@@ -3349,7 +3441,7 @@
if ((current_settings->option_list[i].default_value.string_value == NULL) ||
(strcmp((*(ptr.string_array_ptr))[j], current_settings->option_list[i].default_value.string_value) != 0))
{
- strlen_data = snprintf(tmp_data, MAX_BUF, "%s" VALUE_DELIMITER "%s\n", current_settings->option_list[i].getopt_option.name, (*(ptr.string_array_ptr))[j]);
+ snprintf(tmp_data, MAX_BUF, "%s" VALUE_DELIMITER "%s\n%n", current_settings->option_list[i].getopt_option.name, (*(ptr.string_array_ptr))[j], &strlen_data);
output_writeln(current_settings, LOG_ACTION_CURRENT_CONFIG, -1, tmp_data, strlen_data);
}
@@ -3415,6 +3507,62 @@
}
/*
+ * Moves the contents of *source_list onto the end of *target_list. If target_list
+ * is NULL, the pointer is just moved. If successful, *source_list will be set
+ * to NULL.
+ *
+ * Expects:
+ * *target_list must be NULL or a heap-allocated NULL terminated array of strings
+ * *source_list must be NULL or a heap-allocated NULL terminated array of strings
+ *
+ * Return value:
+ * ERROR: 0
+ * SUCCESS: 1
+ */
+int append_string_array(struct filter_settings *current_settings, char ***target_list, char ***source_list)
+ {
+ int return_value;
+ int i;
+ int target_count;
+
+ return_value = 1;
+
+ if ((target_list != NULL) &&
+ (source_list != NULL) &&
+ ((*source_list) != NULL))
+ {
+ if ((*target_list) == NULL)
+ {
+ (*target_list) = (*source_list);
+ *source_list = NULL;
+ }
+ else
+ {
+ for (target_count = 0; (*target_list)[target_count] != NULL; target_count++);
+ for (i = 0; (*source_list)[i] != NULL; i++);
+
+ if (((*target_list) = realloc((*target_list), sizeof(char *) * (target_count + i + 1))) != NULL)
+ {
+ for (i = 0; (*source_list)[i] != NULL; i++)
+ (*target_list)[target_count + i] = (*source_list)[i];
+
+ (*target_list)[target_count + i] = NULL;
+
+ free(*source_list);
+ *source_list = NULL;
+ }
+ else
+ {
+ SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_MALLOC, sizeof(char *) * (target_count + i + 1));
+ return_value = 0;
+ }
+ }
+ }
+
+ return(return_value);
+ }
+
+/*
* Return value:
* ERROR: FILTER_DECISION_ERROR
* SUCCESS: if a value was set, FILTER_DECISION from target_option. If no value was set, current_return_value
@@ -3646,9 +3794,12 @@
usage_text[0] = '\0';
if (target_option->validity.string_list.strings[0] != NULL)
{
- strlen_usage_text = snprintf(usage_text, MAX_BUF, "%s", target_option->validity.string_list.strings[0]);
+ snprintf(usage_text, MAX_BUF, "%s%n", target_option->validity.string_list.strings[0], &strlen_usage_text);
for (j = 1; target_option->validity.string_list.strings[j] != NULL; j++)
- strlen_usage_text += snprintf(usage_text + strlen_usage_text, MAX_BUF - strlen_usage_text, ", %s", target_option->validity.string_list.strings[j]);
+ {
+ snprintf(usage_text + strlen_usage_text, MAX_BUF - strlen_usage_text, ", %s", target_option->validity.string_list.strings[j]);
+ strlen_usage_text += strlen(usage_text + strlen_usage_text);
+ }
}
if ((context & CONFIG_LOCATION_MASK_ERRORS_CRITICAL) != 0)
@@ -4141,7 +4292,7 @@
{
tmp_action.data = config_filename;
tmp_action.prev = history;
-
+
if ((return_value = process_config_file(current_settings, current_settings->current_options->config_file[i], return_value, context, &tmp_action)) == FILTER_DECISION_ERROR)
break;
}
@@ -4217,11 +4368,11 @@
(ip_ints[3] >= 0) &&
(ip_ints[3] <= 255))
{
- strlen_path[0] = snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_IP DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s", target_dir, ip_octets[0], ip_octets[1], ip_octets[2], ip_octets[3]);
- strlen_path[1] = snprintf(tmp_path[1], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_IP DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s", target_dir, ip_octets[0], ip_octets[1], ip_octets[2]);
- strlen_path[2] = snprintf(tmp_path[2], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_IP DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s", target_dir, ip_octets[0], ip_octets[1]);
- strlen_path[3] = snprintf(tmp_path[3], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_IP DIR_DELIMITER_STR "%s", target_dir, ip_octets[0]);
-
+ snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_IP DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s%n", target_dir, ip_octets[0], ip_octets[1], ip_octets[2], ip_octets[3], &strlen_path[0]);
+ snprintf(tmp_path[1], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_IP DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s%n", target_dir, ip_octets[0], ip_octets[1], ip_octets[2], &strlen_path[1]);
+ snprintf(tmp_path[2], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_IP DIR_DELIMITER_STR "%s" DIR_DELIMITER_STR "%s%n", target_dir, ip_octets[0], ip_octets[1], &strlen_path[2]);
+ snprintf(tmp_path[3], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_IP DIR_DELIMITER_STR "%s%n", target_dir, ip_octets[0], &strlen_path[3]);
+
for (i = 0; i < 4; i++)
{
SPAMDYKE_LOG_DEBUG(current_settings, LOG_DEBUG_CONFIG_SEARCH, tmp_path[i]);
@@ -4283,18 +4434,20 @@
{
if (tmp_ptr[0] == '.')
{
- strlen_path[1] += snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], "%s" DIR_DELIMITER_STR, tmp_ptr + 1);
+ snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], "%s" DIR_DELIMITER_STR, tmp_ptr + 1);
+ strlen_path[1] += strlen(tmp_path[1] + strlen_path[1]);
tmp_ptr[0] = '\0';
}
tmp_ptr--;
}
- strlen_path[1] += snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], "%s", tmp_ptr);
+ snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], "%s", tmp_ptr);
+ strlen_path[1] += strlen(tmp_path[1] + strlen_path[1]);
tmp_ptr = tmp_path[1] + strlen_path[1] - 1;
while (tmp_path[1][0] != '\0')
{
- strlen_path[0] = snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_NAME DIR_DELIMITER_STR "%s", target_dir, tmp_path[1]);
+ snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_NAME DIR_DELIMITER_STR "%s%n", target_dir, tmp_path[1], &strlen_path[0]);
SPAMDYKE_LOG_DEBUG(current_settings, LOG_DEBUG_CONFIG_SEARCH, tmp_path[0]);
if (stat(tmp_path[0], &tmp_stat) == 0)
@@ -4363,16 +4516,18 @@
{
if (tmp_ptr[0] == '.')
{
- strlen_path[1] += snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_ptr + 1);
+ snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_ptr + 1);
+ strlen_path[1] += strlen(tmp_path[1] + strlen_path[1]);
tmp_ptr[0] = '\0';
}
tmp_ptr--;
}
- strlen_path[1] += snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_path[2]);
+ snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_path[2]);
+ strlen_path[1] += strlen(tmp_path[1] + strlen_path[1]);
- strlen_path[0] = snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_SENDER "%s" DIR_DELIMITER_STR CONFIG_DIR_USERNAME DIR_DELIMITER_STR "%s", target_dir, tmp_path[1], canonicalize_path(tmp_path[3], MAX_BUF, target_sender_username, -1));
+ snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_SENDER "%s" DIR_DELIMITER_STR CONFIG_DIR_USERNAME DIR_DELIMITER_STR "%s%n", target_dir, tmp_path[1], canonicalize_path(tmp_path[3], MAX_BUF, target_sender_username, -1), &strlen_path[0]);
SPAMDYKE_LOG_DEBUG(current_settings, LOG_DEBUG_CONFIG_SEARCH, tmp_path[0]);
if (stat(tmp_path[0], &tmp_stat) == 0)
@@ -4415,19 +4570,21 @@
{
if (tmp_ptr[0] == '.')
{
- strlen_path[1] += snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_ptr + 1);
+ snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_ptr + 1);
+ strlen_path[1] += strlen(tmp_path[1] + strlen_path[1]);
tmp_ptr[0] = '\0';
}
tmp_ptr--;
}
- strlen_path[1] += snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_path[2]);
+ snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_path[2]);
+ strlen_path[1] += strlen(tmp_path[1] + strlen_path[1]);
tmp_ptr = tmp_path[1] + strlen_path[1] - 1;
while (tmp_path[1][0] != '\0')
{
- strlen_path[0] = snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_SENDER "%s", target_dir, tmp_path[1]);
+ snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_SENDER "%s%n", target_dir, tmp_path[1], &strlen_path[0]);
SPAMDYKE_LOG_DEBUG(current_settings, LOG_DEBUG_CONFIG_SEARCH, tmp_path[0]);
if (stat(tmp_path[0], &tmp_stat) == 0)
@@ -4491,16 +4648,18 @@
{
if (tmp_ptr[0] == '.')
{
- strlen_path[1] += snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_ptr + 1);
+ snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_ptr + 1);
+ strlen_path[1] += strlen(tmp_path[1] + strlen_path[1]);
tmp_ptr[0] = '\0';
}
tmp_ptr--;
}
- strlen_path[1] += snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_path[2]);
+ snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_path[2]);
+ strlen_path[1] += strlen(tmp_path[1] + strlen_path[1]);
- strlen_path[0] = snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_RECIPIENT "%s" DIR_DELIMITER_STR CONFIG_DIR_USERNAME DIR_DELIMITER_STR "%s", target_dir, tmp_path[1], canonicalize_path(tmp_path[3], MAX_BUF, target_recipient_username, -1));
+ snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_RECIPIENT "%s" DIR_DELIMITER_STR CONFIG_DIR_USERNAME DIR_DELIMITER_STR "%s%n", target_dir, tmp_path[1], canonicalize_path(tmp_path[3], MAX_BUF, target_recipient_username, -1), &strlen_path[0]);
SPAMDYKE_LOG_DEBUG(current_settings, LOG_DEBUG_CONFIG_SEARCH, tmp_path[0]);
if (stat(tmp_path[0], &tmp_stat) == 0)
@@ -4543,7 +4702,8 @@
{
if (tmp_ptr[0] == '.')
{
- strlen_path[1] += snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_ptr + 1);
+ snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_ptr + 1);
+ strlen_path[1] += strlen(tmp_path[1] + strlen_path[1]);
tmp_ptr[0] = '\0';
}
@@ -4551,11 +4711,12 @@
}
strlen_path[1] += snprintf(tmp_path[1] + strlen_path[1], MAX_BUF - strlen_path[1], DIR_DELIMITER_STR "%s", tmp_path[2]);
+ strlen_path[1] += strlen(tmp_path[1] + strlen_path[1]);
tmp_ptr = tmp_path[1] + strlen_path[1] - 1;
while (tmp_path[1][0] != '\0')
{
- strlen_path[0] = snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_RECIPIENT "%s", target_dir, tmp_path[1]);
+ snprintf(tmp_path[0], MAX_BUF, "%s" DIR_DELIMITER_STR CONFIG_DIR_RECIPIENT "%s%n", target_dir, tmp_path[1], &strlen_path[0]);
SPAMDYKE_LOG_DEBUG(current_settings, LOG_DEBUG_CONFIG_SEARCH, tmp_path[0]);
if (stat(tmp_path[0], &tmp_stat) == 0)
@@ -4609,11 +4770,9 @@
int return_value;
int i;
int opt;
- int displayed_banner;
return_value = FILTER_DECISION_UNDECIDED;
opterr = 0;
- displayed_banner = 0;
while ((return_value != FILTER_DECISION_ERROR) &&
((opt = getopt_long(argc, argv, current_settings->short_options, current_settings->long_options, NULL)) != -1))
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/configuration.h
^
|
@@ -21,6 +21,7 @@
#include "spamdyke.h"
int append_string(struct filter_settings *current_settings, char ***target_list, char *target_string, int strlen_target_string);
+int append_string_array(struct filter_settings *current_settings, char ***target_list, char ***source_list);
int process_command_line(struct filter_settings *current_settings, int argc, char *argv[]);
int process_config_file(struct filter_settings *current_settings, char *config_filename, int current_return_value, int context, struct previous_action *history);
int process_config_dir(struct filter_settings *current_settings, char *target_dir, char *target_ip, char *target_name, char *target_sender_address, char *target_sender_domain, char *target_recipient_address, char *target_recipient_domain, int current_return_value, int *return_processed_file);
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/configure
^
|
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for spamdyke 4.2.1.
+# Generated by GNU Autoconf 2.61 for spamdyke 4.3.1.
#
# Report bugs to <samc (at) silence (dot) org>.
#
@@ -574,8 +574,8 @@
# Identity of this package.
PACKAGE_NAME='spamdyke'
PACKAGE_TARNAME='-spamdyke-'
-PACKAGE_VERSION='4.2.1'
-PACKAGE_STRING='spamdyke 4.2.1'
+PACKAGE_VERSION='4.3.1'
+PACKAGE_STRING='spamdyke 4.3.1'
PACKAGE_BUGREPORT='samc (at) silence (dot) org'
ac_unique_file="spamdyke.h"
@@ -1178,7 +1178,7 @@
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures spamdyke 4.2.1 to adapt to many kinds of systems.
+\`configure' configures spamdyke 4.3.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1239,7 +1239,7 @@
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of spamdyke 4.2.1:";;
+ short | recursive ) echo "Configuration of spamdyke 4.3.1:";;
esac
cat <<\_ACEOF
@@ -1332,7 +1332,7 @@
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-spamdyke configure 4.2.1
+spamdyke configure 4.3.1
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1346,7 +1346,7 @@
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by spamdyke $as_me 4.2.1, which was
+It was created by spamdyke $as_me 4.3.1, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -5020,8 +5020,8 @@
echo "${ECHO_T}no" >&6; }
{ echo "$as_me:$LINENO: Adding /usr/kerberos/include to the include file search path" >&5
echo "$as_me: Adding /usr/kerberos/include to the include file search path" >&6;}
- { echo "$as_me:$LINENO: checking Checking if openssl/ssl.h will include correctly" >&5
-echo $ECHO_N "checking Checking if openssl/ssl.h will include correctly... $ECHO_C" >&6; }
+ { echo "$as_me:$LINENO: checking if openssl/ssl.h will include correctly" >&5
+echo $ECHO_N "checking if openssl/ssl.h will include correctly... $ECHO_C" >&6; }
CFLAGS="${CFLAGS} -I/usr/kerberos/include"
fi
@@ -5938,7 +5938,7 @@
main ()
{
struct option tmp_option;
- tmp_option.name = NULL;
+ if ((tmp_option.name = NULL)) return(0);
;
return 0;
}
@@ -5986,7 +5986,7 @@
main ()
{
struct option tmp_option;
- tmp_option.name = NULL;
+ if ((tmp_option.name = NULL)) return(0);
;
return 0;
}
@@ -6334,8 +6334,11 @@
int
main ()
{
- int64_t tmp;
- tmp = 0x7777777777777777ULL;
+ int64_t foo;
+ int64_t bar;
+ foo = 0x7777777777777777ULL;
+ bar = 0x7777777777777777ULL;
+ if (foo == bar) return(0);
;
return 0;
}
@@ -6654,7 +6657,7 @@
main ()
{
char *foo;
- foo = (char *)__func__;
+ if ((foo = (char *)__func__)) return(0);
;
return 0;
}
@@ -6697,7 +6700,7 @@
main ()
{
char *foo;
- foo = (char *)__FUNCTION__;
+ if ((foo = (char *)__FUNCTION__)) return(0);
;
return 0;
}
@@ -6756,7 +6759,7 @@
main ()
{
socklen_t foo;
- foo = 0;
+ if ((foo = 0)) return(0);
;
return 0;
}
@@ -7193,7 +7196,7 @@
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by spamdyke $as_me 4.2.1, which was
+This file was extended by spamdyke $as_me 4.3.1, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -7242,7 +7245,7 @@
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-spamdyke config.status 4.2.1
+spamdyke config.status 4.3.1
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/configure.ac
^
|
@@ -17,7 +17,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
AC_PREREQ(2.59)
-AC_INIT([[spamdyke]], [[4.2.1]], [[samc (at) silence (dot) org]])
+AC_INIT([[spamdyke]], [[4.3.1]], [[samc (at) silence (dot) org]])
AC_CONFIG_SRCDIR([spamdyke.h])
AC_CONFIG_HEADER([config.h])
@@ -122,7 +122,7 @@
[],
[ AC_MSG_RESULT([no])
AC_MSG_NOTICE([Adding /usr/kerberos/include to the include file search path])
- AC_MSG_CHECKING([Checking if openssl/ssl.h will include correctly])
+ AC_MSG_CHECKING([if openssl/ssl.h will include correctly])
CFLAGS="${CFLAGS} -I/usr/kerberos/include"
])
AC_TRY_COMPILE([ #include <openssl/ssl.h> ],
@@ -205,7 +205,7 @@
#include <stdio.h>
#include <getopt.h> ],
[ struct option tmp_option;
- tmp_option.name = NULL; ],
+ if ((tmp_option.name = NULL)) return(0); ],
[ AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_GETOPT_H], [1]) ],
[ AC_MSG_RESULT([no])
@@ -213,7 +213,7 @@
AC_TRY_COMPILE([ #include <stdio.h>
#include <unistd.h> ],
[ struct option tmp_option;
- tmp_option.name = NULL; ],
+ if ((tmp_option.name = NULL)) return(0); ],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
AC_MSG_FAILURE([Unable to compile without struct option for getopt_long()])
@@ -287,8 +287,11 @@
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif ],
- [ int64_t tmp;
- tmp = 0x7777777777777777ULL; ],
+ [ int64_t foo;
+ int64_t bar;
+ foo = 0x7777777777777777ULL;
+ bar = 0x7777777777777777ULL;
+ if (foo == bar) return(0); ],
[ AC_MSG_RESULT([yes])
AC_MSG_CHECKING([whether printf()/scanf() uses %ld for 64-bit integers])
AC_RUN_IFELSE([ AC_LANG_PROGRAM([ #ifdef HAVE_INTTYPES_H
@@ -379,13 +382,13 @@
AC_MSG_CHECKING([whether __func__ is available])
AC_TRY_COMPILE([],
[ char *foo;
- foo = (char *)__func__; ],
+ if ((foo = (char *)__func__)) return(0); ],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
AC_MSG_CHECKING([whether __FUNCTION__ is available])
AC_TRY_COMPILE([],
[ char *foo;
- foo = (char *)__FUNCTION__; ],
+ if ((foo = (char *)__FUNCTION__)) return(0); ],
[ AC_MSG_RESULT([yes])
AC_DEFINE([__func__], [__FUNCTION__]) ],
[ AC_MSG_RESULT([no])
@@ -395,7 +398,7 @@
AC_MSG_CHECKING([whether socklen_t is available])
AC_TRY_COMPILE([ #include <sys/socket.h> ],
[ socklen_t foo;
- foo = 0; ],
+ if ((foo = 0)) return(0); ],
[ AC_MSG_RESULT([yes]) ],
[ AC_MSG_RESULT([no])
AC_DEFINE([socklen_t], [uint32_t])
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/dns.c
^
|
@@ -428,7 +428,7 @@
free_string_array(¤t_settings->current_options->nihdns_primary_server_list, current_settings->base_options.nihdns_primary_server_list);
free_string_array(¤t_settings->current_options->nihdns_secondary_server_list, current_settings->base_options.nihdns_secondary_server_list);
- strlen_tmp_ip = snprintf(tmp_ip, MAX_BUF, "%s:%d", LOCALHOST_IP, default_port);
+ snprintf(tmp_ip, MAX_BUF, "%s:%d%n", LOCALHOST_IP, default_port, &strlen_tmp_ip);
append_string(current_settings, ¤t_settings->current_options->nihdns_primary_server_list, tmp_ip, strlen_tmp_ip);
current_settings->current_options->nihdns_primary_server_data[0].sin_family = AF_INET;
@@ -545,9 +545,9 @@
{
static char packet_template[] = { /* ID */ 0x00, 0x00,
/* QR, OPCODE, AA, TC, RD, RA, RCODE */ 0x01, 0x00,
- /* QDCOUNT */ 0x00, 0x00,
- /* ANCOUNT */ 0x00, 0x00,
- /* NSCOUNT */ 0x00, 0x00,
+ /* QDCOUNT */ 0x00, 0x00,
+ /* ANCOUNT */ 0x00, 0x00,
+ /* NSCOUNT */ 0x00, 0x00,
/* ARCOUNT */ 0x00, 0x00 };
int return_value;
int i;
@@ -564,18 +564,18 @@
if (length_return_query > (sizeof(packet_template) + strlen_target_name + 10))
{
memcpy(return_query, packet_template, sizeof(packet_template));
-
+
tmp_num = id;
return_query[0] = ((char *)&tmp_num)[0];
return_query[1] = ((char *)&tmp_num)[1];
-
+
tmp_num = htons(1L);
return_query[4] = ((char *)&tmp_num)[0];
return_query[5] = ((char *)&tmp_num)[1];
-
+
last_ptr = return_query + sizeof(packet_template);
tmp_ptr = return_query + sizeof(packet_template) + 1;
-
+
for (i = 0; i < strlen_target_name; i++)
if (target_name[i] != '.')
{
@@ -588,21 +588,21 @@
last_ptr = tmp_ptr;
tmp_ptr++;
}
-
+
last_ptr[0] = (tmp_ptr - last_ptr) - 1;
tmp_ptr[0] = 0x00;
tmp_ptr++;
-
+
tmp_num = htons(type);
tmp_ptr[0] = ((char *)&tmp_num)[0];
tmp_ptr[1] = ((char *)&tmp_num)[1];
tmp_ptr += 2;
-
+
tmp_num = htons(NIHDNS_CLASS_INTERNET);
tmp_ptr[0] = ((char *)&tmp_num)[0];
tmp_ptr[1] = ((char *)&tmp_num)[1];
tmp_ptr += 2;
-
+
return_value = tmp_ptr - return_query;
}
else
@@ -946,13 +946,13 @@
{
response_length = 0;
answer = NULL;
-
+
if (FD_ISSET(udp_socket, &read_fds))
{
server_address_len = sizeof(struct sockaddr_in);
response_length = recvfrom(udp_socket, packet_buf, MAX_DNS_PACKET_BYTES_UDP, 0, (struct sockaddr *)&server_address, &server_address_len);
answer = packet_buf;
-
+
/*
* Safety check to prevent DNS spoofing: compare server_address to
* our DNS servers according to the value of nihdns_spoof.
@@ -965,7 +965,7 @@
((current_settings->current_options->nihdns_spoof == NIHDNS_SPOOF_ACCEPT_SAME_IP) ||
(current_settings->current_options->nihdns_primary_server_data[i].sin_port == server_address.sin_port)))
break;
-
+
if (current_settings->current_options->nihdns_primary_server_data[i].sin_addr.s_addr == INADDR_ANY)
for (i = 0; current_settings->current_options->nihdns_secondary_server_data[i].sin_addr.s_addr != INADDR_ANY; i++)
if (((current_settings->current_options->nihdns_spoof == NIHDNS_SPOOF_ACCEPT_SAME_PORT) ||
@@ -973,7 +973,7 @@
((current_settings->current_options->nihdns_spoof == NIHDNS_SPOOF_ACCEPT_SAME_IP) ||
(current_settings->current_options->nihdns_secondary_server_data[i].sin_port == server_address.sin_port)))
break;
-
+
if (current_settings->current_options->nihdns_secondary_server_data[i].sin_addr.s_addr == INADDR_ANY)
{
SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_UDP_SPOOF, inet_ntoa(server_address.sin_addr), ntohs(server_address.sin_port));
@@ -1014,7 +1014,7 @@
((char *)&tmp_num)[1] = tcp_buf[i][1];
tcp_answer_len[i] = ntohs(tmp_num) + 2;
}
-
+
if (tcp_buf_strlen[i] == tcp_answer_len[i])
{
answer = tcp_buf[i] + 2;
@@ -1036,7 +1036,7 @@
SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_MALLOC, (unsigned long)(sizeof(char) * MAX_DNS_PACKET_BYTES_TCP));
error_occurred = 1;
}
-
+
break;
}
else if (FD_ISSET(socket_list[i], &write_fds) &&
@@ -1057,25 +1057,25 @@
close(socket_list[i]);
socket_list[i] = -1;
}
-
+
break;
}
}
-
+
if (response_length > 0)
{
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_DNS_RECEIVED, response_length, answer[0], answer[1]);
-
+
((char *)&tmp_num)[0] = answer[0];
((char *)&tmp_num)[1] = answer[1];
response_id = tmp_num;
-
+
if ((response_id >= start_id) &&
(response_id < ((num_names * num_types) + start_id)) &&
(socket_list[response_id - start_id] != -1))
{
response_id -= start_id;
-
+
/*
* Examine the DNS packet header to see if the response is
* truncated
@@ -1085,12 +1085,12 @@
{
/* Skip the header */
answer_ptr = answer + sizeof(struct nihdns_header);
-
+
/* Skip the questions */
num_questions = ntohs((unsigned short)((struct nihdns_header *)answer)->qdcount);
num_answers = ntohs((unsigned short)((struct nihdns_header *)answer)->ancount);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_DNS_COUNTS, answer[0], answer[1], num_questions, num_answers);
-
+
if (num_answers > 0)
{
for (i = 0; i < num_questions; i++)
@@ -1098,7 +1098,7 @@
answer_ptr += size + sizeof(uint16_t) + sizeof(uint16_t);
else
break;
-
+
if (i == num_questions)
{
answer_start = answer_ptr;
@@ -1108,7 +1108,7 @@
answer_ptr += size;
type = NIHDNS_GETINT16(answer_ptr);
answer_ptr += sizeof(uint16_t);
-
+
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_DNS_RECEIVED_TYPE, nihdns_type_name(type), nihdns_type_name(types[response_id % num_types]));
if (type == types[response_id % num_types])
{
@@ -1117,7 +1117,7 @@
*return_answer_start = return_answer + (answer_start - answer);
if (return_target_name_index != NULL)
*return_target_name_index = response_id / num_types;
-
+
return_value = MINVAL(response_length, return_answer_length);
break;
}
@@ -1134,7 +1134,7 @@
if ((socket_list[response_id] != -1) &&
(socket_list[response_id] != udp_socket))
close(socket_list[response_id]);
-
+
socket_list[response_id] = -1;
active_types--;
}
@@ -1156,24 +1156,24 @@
}
}
}
-
+
if (active_types == 0)
{
for (i = 0; i < num_names; i++)
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_DNS_NEGATIVE, target_name_array[i]);
-
+
return_value = 0;
break;
}
-
+
if (return_value >= 0)
break;
}
}
-
+
if (return_value >= 0)
break;
-
+
tmp_timeval.tv_sec = MINVAL(current_timeout_total_secs - (time(NULL) - start_time), current_timeout_total_secs / current_settings->current_options->nihdns_attempts_total);
tmp_timeval.tv_usec = 0;
}
@@ -1756,7 +1756,6 @@
int type;
int num_answers;
int num_queries;
- int preference;
int exit_loop;
struct previous_action current_lookup;
struct previous_action *tmp_lookup;
@@ -1801,12 +1800,11 @@
switch (type)
{
case NIHDNS_TYPE_MX:
- preference = NIHDNS_GETINT16(answer_ptr);
answer_ptr += sizeof(uint16_t);
if ((size = nihdns_expand(answer, answer + answer_length, answer_ptr, (char *)host, MAX_HOSTNAME)) > 0)
{
- SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_DNS_MX, target_name, preference, host);
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_DNS_MX, target_name, NIHDNS_GETINT16(answer_ptr - sizeof(uint16_t)), host);
if ((sscanf(host, "%3[0-9].%3[0-9].%3[0-9].%3[0-9]", ip_octets[0], ip_octets[1], ip_octets[2], ip_octets[3]) == 4) &&
(sscanf(ip_octets[0], "%d", &ip_ints[0]) == 1) &&
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/environment.c
^
|
@@ -153,7 +153,7 @@
(current_settings->current_environment != NULL))
for (i = 0; current_settings->current_environment[i] != NULL; i++)
{
- tmp_strlen = snprintf(tmp_buf, MAX_BUF, "%s\n", current_settings->current_environment[i]);
+ snprintf(tmp_buf, MAX_BUF, "%s\n%n", current_settings->current_environment[i], &tmp_strlen);
output_writeln(current_settings, LOG_ACTION_CURRENT_ENVIRONMENT, -1, tmp_buf, tmp_strlen);
}
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/exec.c
^
|
@@ -113,7 +113,7 @@
close(stdout_pipe[1]);
close(stderr_pipe[1]);
- strlen_output_buf = snprintf(output_buf, MAX_CHECKPASSWORD, "%s%c%s%c%s%c", (username != NULL) ? username : "", '\0', (password != NULL) ? password : "", '\0', (timestamp != NULL) ? timestamp : "", '\0');
+ snprintf(output_buf, MAX_CHECKPASSWORD, "%s%c%s%c%s%c%n", (username != NULL) ? username : "", '\0', (password != NULL) ? password : "", '\0', (timestamp != NULL) ? timestamp : "", '\0', &strlen_output_buf);
strlen_sent_buf = 0;
start_time = time(NULL);
@@ -789,7 +789,7 @@
* Expects:
* size_return_content must contain the size of the preallocated buffer pointed to by *return_content or -1 if *return_content is to be allocated as needed.
*
- * Return value:
+ * Return value:
* ERROR: -1
* SUCCESS: length of returned string
*/
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/filter.c
^
|
@@ -256,7 +256,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%.3d.%.3d.%.3d.%.3d", ip_ints[0], ip_ints[1], ip_ints[2], ip_ints[3]);
+ snprintf(tmp_ip, MAX_IP, "%.3d.%.3d.%.3d.%.3d%n", ip_ints[0], ip_ints[1], ip_ints[2], ip_ints[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -268,7 +268,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%.3d.%.3d.%.3d", ip_octets[0], ip_ints[1], ip_ints[2], ip_ints[3]);
+ snprintf(tmp_ip, MAX_IP, "%s.%.3d.%.3d.%.3d%n", ip_octets[0], ip_ints[1], ip_ints[2], ip_ints[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -280,7 +280,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%s.%.3d.%.3d", ip_octets[0], ip_octets[1], ip_ints[2], ip_ints[3]);
+ snprintf(tmp_ip, MAX_IP, "%s.%s.%.3d.%.3d%n", ip_octets[0], ip_octets[1], ip_ints[2], ip_ints[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -292,7 +292,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%s.%s.%.3d", ip_octets[0], ip_octets[1], ip_octets[2], ip_ints[3]);
+ snprintf(tmp_ip, MAX_IP, "%s.%s.%s.%.3d%n", ip_octets[0], ip_octets[1], ip_octets[2], ip_ints[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -304,7 +304,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%s.%s.%s", ip_octets[3], ip_octets[2], ip_octets[1], ip_octets[0]);
+ snprintf(tmp_ip, MAX_IP, "%s.%s.%s.%s%n", ip_octets[3], ip_octets[2], ip_octets[1], ip_octets[0], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -316,7 +316,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%.3d.%.3d.%.3d.%.3d", ip_ints[3], ip_ints[2], ip_ints[1], ip_ints[0]);
+ snprintf(tmp_ip, MAX_IP, "%.3d.%.3d.%.3d.%.3d%n", ip_ints[3], ip_ints[2], ip_ints[1], ip_ints[0], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -328,7 +328,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%.3d.%.3d.%.3d", ip_octets[3], ip_ints[2], ip_ints[1], ip_ints[0]);
+ snprintf(tmp_ip, MAX_IP, "%s.%.3d.%.3d.%.3d%n", ip_octets[3], ip_ints[2], ip_ints[1], ip_ints[0], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -340,7 +340,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%s.%.3d.%.3d", ip_octets[3], ip_octets[2], ip_ints[1], ip_ints[0]);
+ snprintf(tmp_ip, MAX_IP, "%s.%s.%.3d.%.3d%n", ip_octets[3], ip_octets[2], ip_ints[1], ip_ints[0], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -352,7 +352,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%s.%s.%.3d", ip_octets[3], ip_octets[2], ip_octets[1], ip_ints[0]);
+ snprintf(tmp_ip, MAX_IP, "%s.%s.%s.%.3d%n", ip_octets[3], ip_octets[2], ip_octets[1], ip_ints[0], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -364,7 +364,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%s.%s.%s", ip_octets[3], ip_octets[0], ip_octets[1], ip_octets[2]);
+ snprintf(tmp_ip, MAX_IP, "%s.%s.%s.%s%n", ip_octets[3], ip_octets[0], ip_octets[1], ip_octets[2], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -376,7 +376,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%s.%s.%s", ip_octets[2], ip_octets[1], ip_octets[0], ip_octets[3]);
+ snprintf(tmp_ip, MAX_IP, "%s.%s.%s.%s%n", ip_octets[2], ip_octets[1], ip_octets[0], ip_octets[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -388,7 +388,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%s.%s%s", ip_octets[3], ip_octets[2], ip_octets[0], ip_octets[1]);
+ snprintf(tmp_ip, MAX_IP, "%s.%s.%s%s%n", ip_octets[3], ip_octets[2], ip_octets[0], ip_octets[1], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -399,7 +399,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s%s.%s.%s", ip_octets[2], ip_octets[3], ip_octets[0], ip_octets[1]);
+ snprintf(tmp_ip, MAX_IP, "%s%s.%s.%s%n", ip_octets[2], ip_octets[3], ip_octets[0], ip_octets[1], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -411,7 +411,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%s.%d", ip_octets[0], ip_octets[1], (ip_ints[2] * 256) + ip_ints[3]);
+ snprintf(tmp_ip, MAX_IP, "%s.%s.%d%n", ip_octets[0], ip_octets[1], (ip_ints[2] * 256) + ip_ints[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -423,7 +423,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s%s%s%s", ip_octets[0], ip_octets[1], ip_octets[2], ip_octets[3]);
+ snprintf(tmp_ip, MAX_IP, "%s%s%s%s%n", ip_octets[0], ip_octets[1], ip_octets[2], ip_octets[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
if (strstr(target_name, tmp_ip) != NULL)
@@ -437,7 +437,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%s.%s%s", ip_octets[0], ip_octets[1], ip_octets[2], ip_octets[3]);
+ snprintf(tmp_ip, MAX_IP, "%s.%s.%s%s%n", ip_octets[0], ip_octets[1], ip_octets[2], ip_octets[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -449,7 +449,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s.%s%s%s", ip_octets[0], ip_octets[1], ip_octets[2], ip_octets[3]);
+ snprintf(tmp_ip, MAX_IP, "%s.%s%s%s%n", ip_octets[0], ip_octets[1], ip_octets[2], ip_octets[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
return_value = search_ip(tmp_ip, tmp_strlen, target_name, strlen_target_name);
}
@@ -461,7 +461,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%.3d%.3d%.3d%.3d", ip_ints[0], ip_ints[1], ip_ints[2], ip_ints[3]);
+ snprintf(tmp_ip, MAX_IP, "%.3d%.3d%.3d%.3d%n", ip_ints[0], ip_ints[1], ip_ints[2], ip_ints[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
if (strstr(target_name, tmp_ip) != NULL)
@@ -475,7 +475,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s%.3d%.3d%.3d", ip_octets[0], ip_ints[1], ip_ints[2], ip_ints[3]);
+ snprintf(tmp_ip, MAX_IP, "%s%.3d%.3d%.3d%n", ip_octets[0], ip_ints[1], ip_ints[2], ip_ints[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
if (strstr(target_name, tmp_ip) != NULL)
@@ -489,7 +489,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s%s%.3d%.3d", ip_octets[0], ip_octets[1], ip_ints[2], ip_ints[3]);
+ snprintf(tmp_ip, MAX_IP, "%s%s%.3d%.3d%n", ip_octets[0], ip_octets[1], ip_ints[2], ip_ints[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
if (strstr(target_name, tmp_ip) != NULL)
@@ -503,7 +503,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s%s%s%.3d", ip_octets[0], ip_octets[1], ip_octets[2], ip_ints[3]);
+ snprintf(tmp_ip, MAX_IP, "%s%s%s%.3d%n", ip_octets[0], ip_octets[1], ip_octets[2], ip_ints[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
if (strstr(target_name, tmp_ip) != NULL)
@@ -517,7 +517,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%s%s%s%s", ip_octets[3], ip_octets[2], ip_octets[1], ip_octets[0]);
+ snprintf(tmp_ip, MAX_IP, "%s%s%s%s%n", ip_octets[3], ip_octets[2], ip_octets[1], ip_octets[0], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
if (strstr(target_name, tmp_ip) != NULL)
@@ -531,7 +531,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%.3d%.3d%.3d%.3d", ip_ints[3], ip_ints[2], ip_ints[1], ip_ints[0]);
+ snprintf(tmp_ip, MAX_IP, "%.3d%.3d%.3d%.3d%n", ip_ints[3], ip_ints[2], ip_ints[1], ip_ints[0], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
if (strstr(target_name, tmp_ip) != NULL)
@@ -546,7 +546,7 @@
if (!return_value &&
inet_aton(target_ip, &tmp_addr))
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%lu", (long unsigned int)tmp_addr.s_addr);
+ snprintf(tmp_ip, MAX_IP, "%lu%n", (long unsigned int)tmp_addr.s_addr, &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
if (strstr(target_name, tmp_ip) != NULL)
@@ -560,7 +560,7 @@
*/
if (!return_value)
{
- tmp_strlen = snprintf(tmp_ip, MAX_IP, "%.2x%.2x%.2x%.2x", ip_ints[0], ip_ints[1], ip_ints[2], ip_ints[3]);
+ snprintf(tmp_ip, MAX_IP, "%.2x%.2x%.2x%.2x%n", ip_ints[0], ip_ints[1], ip_ints[2], ip_ints[3], &tmp_strlen);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_IP_IN_RDNS, tmp_strlen, tmp_ip, strlen_target_name, target_name);
if (strstr(target_name, tmp_ip) != NULL)
@@ -827,7 +827,7 @@
* This means 10.0.0.1.dialup3.example.com will get through but the
* alternative is worse.
*
- * In pseudo-code:
+ * In pseudo-code:
* (((keyword is at start of name) ||
* (first character in keyword is not a number or letter) ||
* (character in name before keyword is not a number or letter)) &&
@@ -2418,9 +2418,9 @@
!(*return_action_locked)) &&
(current_settings->current_options->max_rcpt_to > 0))
{
- SPAMDYKE_LOG_DEBUG(current_settings, LOG_DEBUG_FILTER_RECIPIENT_MAX, current_settings->current_options->max_rcpt_to, current_settings->num_rcpt_to);
+ SPAMDYKE_LOG_DEBUG(current_settings, LOG_DEBUG_FILTER_RECIPIENT_MAX, current_settings->current_options->max_rcpt_to, current_settings->num_recipients);
- if (current_settings->num_rcpt_to >= current_settings->current_options->max_rcpt_to)
+ if (current_settings->num_recipients >= current_settings->current_options->max_rcpt_to)
{
if (target_action != NULL)
*target_action = FILTER_DECISION_TRANSIENT_DO_FILTER;
@@ -2748,9 +2748,9 @@
{
/* User was graylisted but is now allowed. Log the name of their sending host to the file. */
if (current_settings->strlen_server_name > 0)
- strlen_log_entry = snprintf(log_entry, MAX_BUF, "%s %s", current_settings->server_ip, current_settings->server_name);
+ snprintf(log_entry, MAX_BUF, "%s %s%n", current_settings->server_ip, current_settings->server_name, &strlen_log_entry);
else
- strlen_log_entry = snprintf(log_entry, MAX_BUF, "%s", current_settings->server_ip);
+ snprintf(log_entry, MAX_BUF, "%s%n", current_settings->server_ip, &strlen_log_entry);
search_return = search_file(current_settings, graylist_path, log_entry, strlen_log_entry, '\0', NULL, '\0', NULL);
if ((tmp_file = fopen(graylist_path, "a")) != NULL)
@@ -2857,6 +2857,56 @@
}
return(return_value);
+ }
+
+int filter_header_blacklist(struct filter_settings *current_settings, int *target_action, int *return_action_locked, struct rejection_data **target_rejection, struct rejection_data *target_rejection_buf, char *target_message_buf, int size_target_message_buf, char *target_reason_buf, int size_target_reason_buf)
+ {
+ int return_value;
+ int i;
+ int search_return;
+ char tmp_buf[MAX_BUF + 1];
+
+ return_value = FILTER_DECISION_UNDECIDED;
+
+ if (((target_action == NULL) ||
+ ((*target_action) < FILTER_DECISION_DO_FILTER)) &&
+ ((return_action_locked == NULL) ||
+ !(*return_action_locked)) &&
+ ((current_settings->blacklist_header != NULL) ||
+ (current_settings->blacklist_header_file != NULL)))
+ {
+ SPAMDYKE_LOG_DEBUG(current_settings, LOG_DEBUG_FILTER_HEADER_BLACKLIST, current_settings->reconstructed_header);
+
+ if (current_settings->blacklist_header != NULL)
+ for (i = 0; current_settings->blacklist_header[i] != NULL; i++)
+ if (examine_header(current_settings, current_settings->reconstructed_header, current_settings->strlen_reconstructed_header, current_settings->blacklist_header[i], strlen(current_settings->blacklist_header[i])))
+ {
+ if (target_action != NULL)
+ *target_action = FILTER_DECISION_DO_FILTER;
+ set_rejection(current_settings, REJECTION_HEADER_BLACKLISTED, target_rejection, target_rejection_buf, target_message_buf, size_target_message_buf, NULL, current_settings->blacklist_header[i], target_reason_buf, size_target_reason_buf);
+
+ SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_FILTER_HEADER_BLACKLIST, current_settings->reconstructed_header, current_settings->blacklist_header[i]);
+ return_value = FILTER_DECISION_DO_FILTER;
+ break;
+ }
+
+ if ((return_value == FILTER_DECISION_UNDECIDED) &&
+ (current_settings->blacklist_header_file != NULL))
+ for (i = 0; current_settings->blacklist_header_file[i] != NULL; i++)
+ if ((search_return = search_header_file(current_settings, current_settings->blacklist_header_file[i], current_settings->reconstructed_header, current_settings->strlen_reconstructed_header)) > 0)
+ {
+ if (target_action != NULL)
+ *target_action = FILTER_DECISION_DO_FILTER;
+ snprintf(tmp_buf, MAX_BUF, "%s:%d", current_settings->blacklist_header_file[i], search_return);
+ set_rejection(current_settings, REJECTION_HEADER_BLACKLISTED, target_rejection, target_rejection_buf, target_message_buf, size_target_message_buf, NULL, tmp_buf, target_reason_buf, size_target_reason_buf);
+
+ SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_FILTER_HEADER_BLACKLIST_FILE, current_settings->reconstructed_header, current_settings->blacklist_header_file[i], search_return);
+ return_value = FILTER_DECISION_DO_FILTER;
+ break;
+ }
+ }
+
+ return(return_value);
}
/*
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/filter.h
^
|
@@ -51,6 +51,7 @@
int filter_recipient_blacklist(struct filter_settings *current_settings, int *target_action, int *return_action_locked, struct rejection_data **target_rejection, struct rejection_data *target_rejection_buf, char *target_message_buf, int size_target_message_buf, char *target_reason_buf, int size_target_reason_buf);
int filter_recipient_graylist(struct filter_settings *current_settings, int *target_action, int *return_action_locked, struct rejection_data **target_rejection, struct rejection_data *target_rejection_buf, char *target_message_buf, int size_target_message_buf);
int filter_identical_from_to(struct filter_settings *current_settings, int *target_action, int *return_action_locked, struct rejection_data **target_rejection, struct rejection_data *target_rejection_buf, char *target_message_buf, int size_target_message_buf);
+int filter_header_blacklist(struct filter_settings *current_settings, int *target_action, int *return_action_locked, struct rejection_data **target_rejection, struct rejection_data *target_rejection_buf, char *target_message_buf, int size_target_message_buf, char *target_reason_buf, int size_target_reason_buf);
void reset_rejection(struct filter_settings *current_settings, int rejection_index, struct rejection_data **target_rejection, struct rejection_data *target_rejection_buf, char *target_message_buf, int size_target_message_buf, char *input_reason, char *target_reason_buf, int size_target_reason_buf);
void set_rejection(struct filter_settings *current_settings, int rejection_index, struct rejection_data **target_rejection, struct rejection_data *target_rejection_buf, char *target_message_buf, int size_target_message_buf, char *append_message, char *input_reason, char *target_reason_buf, int size_target_reason_buf);
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/log.c
^
|
@@ -23,6 +23,7 @@
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
+#include <ctype.h>
#include <errno.h>
#include "config.h"
@@ -85,12 +86,11 @@
struct tm *tmp_tm;
time_t tmp_time;
char *data_ptr;
+ char *data_last;
int inserted_data_length;
- char tmp_last_char;
return_value = 0;
inserted_data_length = 0;
- tmp_last_char = last_char;
if ((target_fd >= 0) &&
(data_length > 0))
@@ -98,7 +98,9 @@
if ((action == LOG_ACTION_CHILD_FROM) ||
(action == LOG_ACTION_FILTER_FROM))
{
- if ((return_value = NETWORK_WRITE(current_settings, target_fd, data, data_length)) == -1)
+ if ((return_value = NETWORK_WRITE(current_settings, target_fd, data, data_length)) != -1)
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_REMOTE_WRITE, return_value, target_fd, data_length, MINVAL(data_length, LOG_DEBUGX_STRLEN_PREVIEW), data);
+ else
SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_WRITE "%s", data_length, target_fd, strerror(errno));
}
else if (current_settings->tls_state == TLS_STATE_ACTIVE_PASSTHROUGH)
@@ -108,31 +110,38 @@
}
else
{
+ /*
+ * This loop examines the data as it is sent and turns any bare LFs into
+ * CRLF. The data_last pointer tracks the start of the data that hasn't
+ * been sent yet -- the data is only sent line-by-line if CRs must be
+ * inserted. Otherwise it is bursted (assuming data contains more than
+ * one line).
+ */
data_ptr = data;
+ data_last = data;
while ((data_ptr - data) < data_length)
{
for (i = 0; (((data_ptr - data) + i) < data_length) && (data_ptr[i] != CHAR_LF); i++);
if (((data_ptr - data) + i) < data_length)
{
- if ((i > 0) &&
- (data_ptr[i - 1] == CHAR_CR))
- {
- if ((return_value = write(target_fd, data_ptr, i + 1)) == -1)
- {
- SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_WRITE "%s", i + 1, target_fd, strerror(errno));
- break;
- }
- }
- else if ((i > 0) ||
- (last_char != CHAR_CR))
+ if (((((data_ptr - data) + i) > 0) &&
+ (data[(data_ptr - data) + (i - 1)] != CHAR_CR)) ||
+ ((((data_ptr - data) + i) == 0) &&
+ (last_char != CHAR_CR)))
{
- if ((i > 0) &&
- ((return_value = write(target_fd, data_ptr, i)) == -1))
+ if (i > 0)
{
- SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_WRITE "%s", i, target_fd, strerror(errno));
- break;
+ if ((return_value = write(target_fd, data_last, (data_ptr - data_last) + i)) != -1)
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_CHILD_WRITE_CRLF, return_value, target_fd, data_length, MINVAL((data_ptr - data_last) + i, LOG_DEBUGX_STRLEN_PREVIEW), data_last);
+ else
+ {
+ SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_WRITE "%s", i, target_fd, strerror(errno));
+ break;
+ }
}
+ data_last = data_ptr + i + 1;
+
if ((return_value = write(target_fd, STR_CRLF, STRLEN(STR_CRLF))) == -1)
{
SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_WRITE "%s", STRLEN(STR_CRLF), target_fd, strerror(errno));
@@ -142,9 +151,14 @@
inserted_data_length++;
}
else
- if ((return_value = write(target_fd, data_ptr, 1)) == -1)
+ if ((return_value = write(target_fd, data_last, (data_ptr - data_last) + i + 1)) != -1)
{
- SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_WRITE "%s", 1, target_fd, strerror(errno));
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_CHILD_WRITE, return_value, target_fd, data_length, MINVAL((data_ptr - data_last) + i + 1, LOG_DEBUGX_STRLEN_PREVIEW), data_last);
+ data_last = data_ptr + i + 1;
+ }
+ else
+ {
+ SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_WRITE "%s", i + 1, target_fd, strerror(errno));
break;
}
@@ -152,7 +166,9 @@
}
else
{
- if ((return_value = write(target_fd, data_ptr, i)) == -1)
+ if ((return_value = write(target_fd, data_last, (data_ptr - data_last) + i)) != -1)
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_CHILD_WRITE, return_value, target_fd, data_length, MINVAL((data_ptr - data_last) + i, LOG_DEBUGX_STRLEN_PREVIEW), data_last);
+ else
SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_WRITE "%s", i, target_fd, strerror(errno));
break;
@@ -356,35 +372,36 @@
}
else
{
+ /*
+ * This loop examines the data as it is sent and turns any bare LFs into
+ * CRLF. The data_last pointer tracks the start of the data that hasn't
+ * been sent yet -- the data is only sent line-by-line if CRs must be
+ * inserted. Otherwise it is bursted (assuming data contains more than
+ * one line).
+ */
data_ptr = data;
+ data_last = data;
while ((data_ptr - data) < data_length)
{
for (i = 0; (((data_ptr - data) + i) < data_length) && (data_ptr[i] != CHAR_LF); i++);
if (((data_ptr - data) + i) < data_length)
{
- if ((i > 0) &&
- (data_ptr[i - 1] == CHAR_CR))
- {
- if (fprintf(log_file, "%.*s", i + 1, data_ptr) == -1)
- {
- SPAMDYKE_RELOG_ERROR(current_settings, LOG_ERROR_FPRINTF_BYTES "%s", i + 1, log_filename, strerror(errno));
- fclose(log_file);
- log_file = NULL;
- break;
- }
- }
- else if ((i > 0) ||
- (tmp_last_char != CHAR_CR))
+ if (((((data_ptr - data) + i) > 0) &&
+ (data[(data_ptr - data) + (i - 1)] != CHAR_CR)) ||
+ ((((data_ptr - data) + i) == 0) &&
+ (last_char != CHAR_CR)))
{
if ((i > 0) &&
- (fprintf(log_file, "%.*s", i, data_ptr) == -1))
+ (fprintf(log_file, "%.*s", (int)((data_ptr - data_last) + i), data_last) == -1))
{
- SPAMDYKE_RELOG_ERROR(current_settings, LOG_ERROR_FPRINTF_BYTES "%s", i, log_filename, strerror(errno));
+ SPAMDYKE_RELOG_ERROR(current_settings, LOG_ERROR_FPRINTF_BYTES "%s", (data_ptr - data_last) + i, log_filename, strerror(errno));
fclose(log_file);
log_file = NULL;
break;
}
+ data_last = data_ptr + i + 1;
+
if (fprintf(log_file, "%.*s", STRLEN(STR_CRLF), STR_CRLF) == -1)
{
SPAMDYKE_RELOG_ERROR(current_settings, LOG_ERROR_FPRINTF_BYTES "%s", STRLEN(STR_CRLF), log_filename, strerror(errno));
@@ -392,11 +409,15 @@
log_file = NULL;
break;
}
+
+ inserted_data_length++;
}
else
- if (fprintf(log_file, "%.*s", 1, data_ptr) == -1)
+ if (fprintf(log_file, "%.*s", (int)((data_ptr - data_last) + i + 1), data_last) != -1)
+ data_last = data_ptr + i + 1;
+ else
{
- SPAMDYKE_RELOG_ERROR(current_settings, LOG_ERROR_FPRINTF_BYTES "%s", 1, log_filename, strerror(errno));
+ SPAMDYKE_RELOG_ERROR(current_settings, LOG_ERROR_FPRINTF_BYTES "%s", (data_ptr - data_last) + i + 1, log_filename, strerror(errno));
fclose(log_file);
log_file = NULL;
break;
@@ -406,9 +427,9 @@
}
else
{
- if (fprintf(log_file, "%.*s", i, data_ptr) == -1)
+ if (fprintf(log_file, "%.*s", (int)((data_ptr - data_last) + i), data_last) == -1)
{
- SPAMDYKE_RELOG_ERROR(current_settings, LOG_ERROR_FPRINTF_BYTES "%s", i, log_filename, strerror(errno));
+ SPAMDYKE_RELOG_ERROR(current_settings, LOG_ERROR_FPRINTF_BYTES "%s", (data_ptr - data_last) + i, log_filename, strerror(errno));
fclose(log_file);
log_file = NULL;
}
@@ -416,6 +437,8 @@
break;
}
}
+
+ last_char = data[data_length - 1];
}
}
@@ -501,7 +524,8 @@
{
va_start(tmp_va, format);
- if ((strlen_data = vsnprintf(tmp_data, MAX_BUF - 1, format, tmp_va)) > 0)
+ vsnprintf(tmp_data, MAX_BUF - 1, format, tmp_va);
+ if ((strlen_data = strlen(tmp_data)) > 0)
{
if (tmp_data[strlen_data - 1] != '\n')
{
@@ -536,3 +560,27 @@
return;
}
+
+char *canonicalize_log_text(char *target_buf, int strlen_target_buf, char *input_text, int strlen_input_text)
+ {
+ char *return_value;
+ int i;
+ int tmp_strlen;
+
+ return_value = target_buf;
+
+ if ((input_text != NULL) &&
+ (target_buf != NULL) &&
+ (strlen_target_buf > 0))
+ {
+ tmp_strlen = MINVAL(strlen_input_text, strlen_target_buf - 1);
+ memcpy(target_buf, input_text, tmp_strlen);
+ target_buf[tmp_strlen] = '\0';
+
+ for (i = 0; i < tmp_strlen; i++)
+ if (target_buf[i] == REASON_REPLACE_TARGET)
+ target_buf[i] = REASON_REPLACE_REPLACEMENT;
+ }
+
+ return(return_value);
+ }
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/log.h
^
|
@@ -22,5 +22,6 @@
int output_writeln(struct filter_settings *current_settings, int action, int target_fd, char *data, int data_length);
void spamdyke_log(struct filter_settings *current_settings, int target_level, int output_to_full_log, char *format, ...);
+char *canonicalize_log_text(char *target_buf, int strlen_target_buf, char *input_text, int strlen_input_text);
#endif /* LOG_H */
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/search_fs.c
^
|
@@ -24,6 +24,7 @@
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
+#include <fnmatch.h>
#include "spamdyke.h"
#include "environment.h"
#include "log.h"
@@ -100,12 +101,12 @@
{
if ((tmp_end = strchr(tmp_start, ':')) != NULL)
{
- strlen_filename = snprintf(new_filename, MAX_BUF, "%.*s" DIR_DELIMITER_STR "%s", (int)(tmp_end - tmp_start), tmp_start, filename);
+ snprintf(new_filename, MAX_BUF, "%.*s" DIR_DELIMITER_STR "%s%n", (int)(tmp_end - tmp_start), tmp_start, filename, &strlen_filename);
tmp_start = tmp_end + 1;
}
else
{
- strlen_filename = snprintf(new_filename, MAX_BUF, "%s" DIR_DELIMITER_STR "%s", tmp_start, filename);
+ snprintf(new_filename, MAX_BUF, "%s" DIR_DELIMITER_STR "%s%n", tmp_start, filename, &strlen_filename);
tmp_start = NULL;
}
@@ -197,7 +198,7 @@
while ((tmp_string != NULL) &&
(return_value == 0))
- if (((check_start &&
+ if (((check_start &&
((start_wildcard_matches == NULL) ||
(strchr(start_wildcard_matches, (tmp_string - 1)[0]) != NULL))) ||
(!check_start &&
@@ -1003,14 +1004,14 @@
(target_username[0] != '\0'))
if ((target_domain != NULL) &&
(target_domain[0] != '\0'))
- tmp_strlen = snprintf(return_address, max_return_address, "%s@%s", target_username, target_domain);
+ snprintf(return_address, max_return_address, "%s@%s%n", target_username, target_domain, &tmp_strlen);
else
- tmp_strlen = snprintf(return_address, max_return_address, "%s", target_username);
+ snprintf(return_address, max_return_address, "%s%n", target_username, &tmp_strlen);
else if ((target_domain != NULL) &&
(target_domain[0] != '\0'))
- tmp_strlen = snprintf(return_address, max_return_address, "@%s", target_domain);
+ snprintf(return_address, max_return_address, "@%s%n", target_domain, &tmp_strlen);
else if (missing_data != NULL)
- tmp_strlen = snprintf(return_address, max_return_address, "%s", missing_data);
+ snprintf(return_address, max_return_address, "%s%n", missing_data, &tmp_strlen);
else
return_address[0] = '\0';
}
@@ -1020,3 +1021,143 @@
return(return_address);
}
+
+/*
+ * Reduces any sequences of one or more whitespace characters to a single space
+ * and also converts the text to lowercase.
+ *
+ * Return value:
+ * -1: error
+ * number of characters copied to target_buf
+ */
+int collapse_whitespace(struct filter_settings *current_settings, char *target_buf, int strlen_target_buf, char *input_buf, int strlen_input_buf)
+ {
+ int return_value;
+ int i;
+ int tmp_strlen;
+
+ return_value = -1;
+
+ if ((target_buf != NULL) &&
+ (strlen_target_buf > 0))
+ {
+ tmp_strlen = 0;
+
+ for (i = 0; (i < strlen_input_buf) && (i < strlen_target_buf); i++)
+ if (isspace((int)input_buf[i]))
+ {
+ if ((tmp_strlen == 0) ||
+ (target_buf[tmp_strlen - 1] != ' '))
+ {
+ target_buf[tmp_strlen] = ' ';
+ tmp_strlen++;
+ }
+ }
+ else
+ {
+ target_buf[tmp_strlen] = tolower((int)input_buf[i]);
+ tmp_strlen++;
+ }
+
+ for (i = (tmp_strlen - 1); (i >= 0) && (target_buf[i] == ' '); i--)
+ tmp_strlen--;
+
+ target_buf[tmp_strlen] = '\0';
+ return_value = tmp_strlen;
+
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_COLLAPSE_WHITESPACE, strlen_input_buf, strlen_input_buf, input_buf, tmp_strlen, tmp_strlen, target_buf);
+ }
+
+ return(return_value);
+ }
+
+/*
+ * Return value:
+ * 0: no match
+ * 1: match found
+ */
+int examine_header(struct filter_settings *current_settings, char *target_header, int strlen_target_header, char *target_entry, int strlen_target_entry)
+ {
+ int return_value;
+ char tmp_header[MAX_NETWORK_BUF + 1];
+ int strlen_tmp_header;
+ char tmp_entry[MAX_NETWORK_BUF + 1];
+ int strlen_tmp_entry;
+
+ return_value = 0;
+
+ if ((target_header != NULL) &&
+ (strlen_target_header > 0) &&
+ (target_entry != NULL) &&
+ (strlen_target_entry > 0) &&
+ (strchr(target_entry, HEADER_DELIMITER) != NULL) &&
+ (strchr(target_header, HEADER_DELIMITER) != NULL) &&
+ ((strlen_tmp_header = collapse_whitespace(current_settings, tmp_header, MAX_NETWORK_BUF, target_header, strlen_target_header)) > 0) &&
+ ((strlen_tmp_entry = collapse_whitespace(current_settings, tmp_entry, MAX_NETWORK_BUF, target_entry, strlen_target_entry)) > 0) &&
+ (fnmatch(tmp_entry, tmp_header, 0) == 0))
+ return_value = 1;
+
+ return(return_value);
+ }
+
+/*
+ * Return value:
+ * ERROR: -1
+ * NOT FOUND: 0
+ * FOUND: matching line number
+ */
+int search_header_file(struct filter_settings *current_settings, char *search_filename, char *target_header, int strlen_target_header)
+ {
+ int return_value;
+ FILE *tmp_file;
+ char tmp_buf[MAX_FILE_BUF + 1];
+ int line_num;
+ int strlen_buf;
+ char tmp_header[MAX_NETWORK_BUF + 1];
+ int strlen_tmp_header;
+ char tmp_entry[MAX_NETWORK_BUF + 1];
+ int strlen_tmp_entry;
+
+ return_value = 0;
+
+ if ((target_header != NULL) &&
+ (strlen_target_header > 0) &&
+ (strchr(target_header, HEADER_DELIMITER) != NULL) &&
+ ((strlen_tmp_header = collapse_whitespace(current_settings, tmp_header, MAX_NETWORK_BUF, target_header, strlen_target_header)) > 0))
+ {
+ if ((tmp_file = fopen(search_filename, "r")) != NULL)
+ {
+ line_num = 0;
+
+ while (!feof(tmp_file) &&
+ (line_num < MAX_FILE_LINES))
+ {
+ if ((fscanf(tmp_file, "%" STRINGIFY(MAX_FILE_BUF) "[^\r\n]", tmp_buf) == 1) &&
+ (tmp_buf[0] != COMMENT_DELIMITER) &&
+ ((strlen_buf = strlen(tmp_buf)) > 0) &&
+ (strchr(tmp_buf, HEADER_DELIMITER) != NULL) &&
+ ((strlen_tmp_entry = collapse_whitespace(current_settings, tmp_entry, MAX_NETWORK_BUF, tmp_buf, strlen_buf)) > 0) &&
+ (fnmatch(tmp_entry, tmp_header, 0) == 0))
+ {
+ return_value = line_num + 1;
+ break;
+ }
+
+ fscanf(tmp_file, "%*1[\r\n]");
+ line_num++;
+ }
+
+ if (line_num == MAX_FILE_LINES)
+ SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_FILE_TOO_LONG "%s", MAX_FILE_LINES, search_filename);
+
+ fclose(tmp_file);
+ }
+ else
+ {
+ SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_OPEN_SEARCH "%s: %s", search_filename, strerror(errno));
+ return_value = -1;
+ }
+ }
+
+ return(return_value);
+ }
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/search_fs.h
^
|
@@ -31,5 +31,7 @@
int read_file_first_line(struct filter_settings *current_settings, char *target_filename, char **return_content);
int load_resolver_file(struct filter_settings *current_settings, char *target_filename, int *return_default_port);
char *reassemble_address(char *target_username, char *target_domain, char *missing_data, char *return_address, int max_return_address, int *strlen_return_address);
+int examine_header(struct filter_settings *current_settings, char *target_header, int strlen_target_header, char *target_entry, int strlen_target_entry);
+int search_header_file(struct filter_settings *current_settings, char *search_filename, char *target_header, int strlen_target_header);
#endif /* SEARCH_FS_H */
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/spamdyke.c
^
|
@@ -849,11 +849,11 @@
if ((current_settings->current_options->policy_location != NULL) &&
target_rejection->append_policy)
if (current_settings->current_options->policy_location[current_settings->current_options->strlen_policy_location - 1] == ERROR_URL_DELIMITER_DYNAMIC)
- strlen_buf = snprintf(output_buf, MAX_BUF, "%.*s%.*s" ERROR_URL "%.*s%s" REJECT_CRLF, STRLEN_REJECT_SEVERITY, (substitute_reject_severity == NULL) ? target_rejection->reject_severity : substitute_reject_severity, target_rejection->strlen_reject_message, target_rejection->reject_message, current_settings->current_options->strlen_policy_location, current_settings->current_options->policy_location, target_rejection->short_reject_message);
+ snprintf(output_buf, MAX_BUF, "%.*s%.*s" ERROR_URL "%.*s%s" REJECT_CRLF "%n", STRLEN_REJECT_SEVERITY, (substitute_reject_severity == NULL) ? target_rejection->reject_severity : substitute_reject_severity, target_rejection->strlen_reject_message, target_rejection->reject_message, current_settings->current_options->strlen_policy_location, current_settings->current_options->policy_location, target_rejection->short_reject_message, &strlen_buf);
else
- strlen_buf = snprintf(output_buf, MAX_BUF, "%.*s%.*s" ERROR_URL "%.*s" ERROR_URL_DELIMITER_STATIC "%s" REJECT_CRLF, STRLEN_REJECT_SEVERITY, (substitute_reject_severity == NULL) ? target_rejection->reject_severity : substitute_reject_severity, target_rejection->strlen_reject_message, target_rejection->reject_message, current_settings->current_options->strlen_policy_location, current_settings->current_options->policy_location, target_rejection->short_reject_message);
+ snprintf(output_buf, MAX_BUF, "%.*s%.*s" ERROR_URL "%.*s" ERROR_URL_DELIMITER_STATIC "%s" REJECT_CRLF "%n", STRLEN_REJECT_SEVERITY, (substitute_reject_severity == NULL) ? target_rejection->reject_severity : substitute_reject_severity, target_rejection->strlen_reject_message, target_rejection->reject_message, current_settings->current_options->strlen_policy_location, current_settings->current_options->policy_location, target_rejection->short_reject_message, &strlen_buf);
else
- strlen_buf = snprintf(output_buf, MAX_BUF, "%.*s%.*s" REJECT_CRLF, STRLEN_REJECT_SEVERITY, (substitute_reject_severity == NULL) ? target_rejection->reject_severity : substitute_reject_severity, target_rejection->strlen_reject_message, target_rejection->reject_message);
+ snprintf(output_buf, MAX_BUF, "%.*s%.*s" REJECT_CRLF "%n", STRLEN_REJECT_SEVERITY, (substitute_reject_severity == NULL) ? target_rejection->reject_severity : substitute_reject_severity, target_rejection->strlen_reject_message, target_rejection->reject_message, &strlen_buf);
return_value = output_writeln(current_settings, LOG_ACTION_FILTER_FROM, target_fd, output_buf, strlen_buf);
@@ -882,6 +882,7 @@
static struct rejection_data smtp_auth_success = SUCCESS_AUTH;
static char *smtp_auth_types[] = SMTP_AUTH_TYPES;
static int strlen_smtp_auth_types[] = STRLEN_SMTP_AUTH_TYPES;
+ static struct rejection_data data_success = SUCCESS_DATA;
int return_value;
int i;
int j;
@@ -904,9 +905,99 @@
{
if ((strlen_input_line == STRLEN(SMTP_DATA_END)) &&
(strncasecmp(SMTP_DATA_END, input_line, STRLEN(SMTP_DATA_END)) == 0))
+ {
+ if ((current_settings->inside_header) &&
+ ((current_settings->blacklist_header != NULL) ||
+ (current_settings->blacklist_header_file != NULL)) &&
+ (current_settings->strlen_reconstructed_header > 0))
+ {
+ filter_header_blacklist(current_settings, ¤t_settings->current_options->filter_action, ¤t_settings->current_options->filter_action_locked, ¤t_settings->current_options->rejection, ¤t_settings->current_options->rejection_buf, current_settings->current_options->reject_message_buf, MAX_BUF, current_settings->current_options->reject_reason_buf, MAX_BUF);
+
+ current_settings->reconstructed_header[0] = '\0';
+ current_settings->strlen_reconstructed_header = 0;
+ }
+
+ if ((current_settings->current_options->filter_action == FILTER_DECISION_DO_FILTER) &&
+ (current_settings->current_options->filter_grace <= FILTER_GRACE_AFTER_DATA) &&
+ (current_settings->current_options->rejection != NULL))
+ {
+ output_write_rejection(current_settings, current_settings->current_options->rejection, outbound_fd, NULL);
+ current_settings->current_options->filter_grace = FILTER_GRACE_EXPIRED;
+ return_value = FILTER_FLAG_INTERCEPT | FILTER_FLAG_CHILD_QUIT;
+
+ for (i = 0; i < current_settings->num_recipients; i++)
+ SPAMDYKE_LOG_INFO(current_settings, "%s from: %s to: %s origin_ip: %s origin_rdns: %s auth: %s encryption: %s reason: %s",
+ (current_settings->current_options->transient_rejection != NULL) ? current_settings->current_options->transient_rejection->short_reject_message : ((current_settings->current_options->rejection != NULL) ? current_settings->current_options->rejection->short_reject_message : SHORT_SUCCESS),
+ reassemble_address(current_settings->sender_username, current_settings->sender_domain, LOG_MISSING_DATA, tmp_sender_address, MAX_ADDRESS, NULL),
+ current_settings->allowed_recipients[i],
+ (current_settings->server_ip != NULL) ? current_settings->server_ip : LOG_MISSING_DATA,
+ (current_settings->strlen_server_name > 0) ? current_settings->server_name : LOG_MISSING_DATA,
+ (current_settings->smtp_auth_username[0] != '\0') ? current_settings->smtp_auth_username : LOG_MISSING_DATA,
+ tls_state_desc(current_settings),
+ (current_settings->current_options->transient_rejection != NULL) ? ((current_settings->current_options->transient_rejection->reject_reason != NULL) ? current_settings->current_options->transient_rejection->reject_reason : LOG_EMPTY_DATA) : (((current_settings->current_options->rejection != NULL) && (current_settings->current_options->rejection->reject_reason != NULL)) ? current_settings->current_options->rejection->reject_reason : LOG_EMPTY_DATA)
+ );
+ }
+ else
+ return_value = FILTER_FLAG_PASS | FILTER_FLAG_DATA_CAPTURE;
+
current_settings->inside_data = 0;
+ current_settings->inside_header = 0;
+ }
else
- return_value = FILTER_FLAG_PASS | FILTER_FLAG_CHILD_RESPONSE_NOT_NEEDED;
+ {
+ if (current_settings->inside_header)
+ {
+ for (i = 0; (i < strlen_input_line) && isspace((int)input_line[i]); i++);
+ if ((strlen_input_line == 0) ||
+ (i == strlen_input_line))
+ current_settings->inside_header = 0;
+ else
+ return_value = FILTER_FLAG_RETAIN;
+
+ if ((current_settings->blacklist_header != NULL) ||
+ (current_settings->blacklist_header_file != NULL))
+ {
+ if (((i == 0) ||
+ (i == strlen_input_line)) &&
+ (current_settings->strlen_reconstructed_header > 0))
+ {
+ filter_header_blacklist(current_settings, ¤t_settings->current_options->filter_action, ¤t_settings->current_options->filter_action_locked, ¤t_settings->current_options->rejection, ¤t_settings->current_options->rejection_buf, current_settings->current_options->reject_message_buf, MAX_BUF, current_settings->current_options->reject_reason_buf, MAX_BUF);
+
+ current_settings->reconstructed_header[0] = '\0';
+ current_settings->strlen_reconstructed_header = 0;
+ }
+
+ if ((current_settings->current_options->filter_action == FILTER_DECISION_DO_FILTER) &&
+ (current_settings->current_options->filter_grace <= FILTER_GRACE_AFTER_DATA) &&
+ (current_settings->current_options->rejection != NULL))
+ return_value = FILTER_FLAG_INTERCEPT | FILTER_FLAG_CHILD_QUIT;
+ else
+ {
+ if ((current_settings->strlen_reconstructed_header < MAX_NETWORK_BUF) &&
+ (current_settings->buf_retain != NULL))
+ {
+ memcpy(current_settings->reconstructed_header + current_settings->strlen_reconstructed_header, input_line, MINVAL(MAX_NETWORK_BUF - current_settings->strlen_reconstructed_header, strlen_input_line));
+ current_settings->strlen_reconstructed_header += MINVAL(MAX_NETWORK_BUF - current_settings->strlen_reconstructed_header, strlen_input_line);
+ current_settings->reconstructed_header[current_settings->strlen_reconstructed_header] = '\0';
+
+ if (current_settings->strlen_reconstructed_header == MAX_NETWORK_BUF)
+ {
+ SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_HEADER_TOO_LONG, current_settings->strlen_reconstructed_header, current_settings->strlen_reconstructed_header, current_settings->reconstructed_header);
+ memcpy(current_settings->reconstructed_header + current_settings->strlen_reconstructed_header, STR_CRLF, STRLEN(STR_CRLF));
+ current_settings->strlen_reconstructed_header += STRLEN(STR_CRLF);
+ current_settings->reconstructed_header[current_settings->strlen_reconstructed_header] = '\0';
+ }
+ }
+
+ return_value = FILTER_FLAG_RETAIN;
+ }
+ }
+ else
+ return_value = FILTER_FLAG_PASS | FILTER_FLAG_CHILD_RESPONSE_NOT_NEEDED;
+ }
+ else
+ return_value = FILTER_FLAG_PASS | FILTER_FLAG_CHILD_RESPONSE_NOT_NEEDED;
+ }
}
else if (((current_settings->current_options->smtp_auth_level & SMTP_AUTH_LEVEL_MASK) >= SMTP_AUTH_LEVEL_VALUE_OBSERVE) &&
(current_settings->smtp_auth_state == SMTP_AUTH_STATE_CHALLENGE_1_SENT))
@@ -993,7 +1084,7 @@
if ((current_settings->smtp_auth_origin == SMTP_AUTH_ORIGIN_SPAMDYKE) ||
((current_settings->current_options->smtp_auth_level & SMTP_AUTH_LEVEL_MASK) >= SMTP_AUTH_LEVEL_VALUE_ALWAYS))
{
- strlen_content = snprintf(current_settings->smtp_auth_challenge, MAX_BUF, "%s%s%s", REJECT_SEVERITY_AUTH_CHALLENGE, SMTP_AUTH_LOGIN_CHALLENGE_2, REJECT_CRLF);
+ snprintf(current_settings->smtp_auth_challenge, MAX_BUF, "%s%s%s%n", REJECT_SEVERITY_AUTH_CHALLENGE, SMTP_AUTH_LOGIN_CHALLENGE_2, REJECT_CRLF, &strlen_content);
output_writeln(current_settings, LOG_ACTION_FILTER_FROM, outbound_fd, current_settings->smtp_auth_challenge, strlen_content);
current_settings->smtp_auth_state = SMTP_AUTH_STATE_CHALLENGE_2_SENT;
@@ -1318,7 +1409,7 @@
}
else
{
- strlen_content = snprintf(current_settings->smtp_auth_challenge, MAX_BUF, "%s%s", REJECT_SEVERITY_AUTH_CHALLENGE, REJECT_CRLF);
+ snprintf(current_settings->smtp_auth_challenge, MAX_BUF, "%s%s%n", REJECT_SEVERITY_AUTH_CHALLENGE, REJECT_CRLF, &strlen_content);
output_writeln(current_settings, LOG_ACTION_FILTER_FROM, outbound_fd, current_settings->smtp_auth_challenge, strlen_content);
current_settings->smtp_auth_state = SMTP_AUTH_STATE_CHALLENGE_1_SENT;
}
@@ -1332,13 +1423,13 @@
memcpy(current_settings->smtp_auth_response, input_line + i, sizeof(char) * MINVAL(MAX_BUF, strlen_input_line - i));
current_settings->smtp_auth_response[MINVAL(MAX_BUF, strlen_input_line - i)] = '\0';
- strlen_content = snprintf(current_settings->smtp_auth_challenge, MAX_BUF, "%s%s%s", REJECT_SEVERITY_AUTH_CHALLENGE, SMTP_AUTH_LOGIN_CHALLENGE_2, REJECT_CRLF);
+ snprintf(current_settings->smtp_auth_challenge, MAX_BUF, "%s%s%s%n", REJECT_SEVERITY_AUTH_CHALLENGE, SMTP_AUTH_LOGIN_CHALLENGE_2, REJECT_CRLF, &strlen_content);
output_writeln(current_settings, LOG_ACTION_FILTER_FROM, outbound_fd, current_settings->smtp_auth_challenge, strlen_content);
current_settings->smtp_auth_state = SMTP_AUTH_STATE_CHALLENGE_2_SENT;
}
else
{
- strlen_content = snprintf(current_settings->smtp_auth_challenge, MAX_BUF, "%s%s%s", REJECT_SEVERITY_AUTH_CHALLENGE, SMTP_AUTH_LOGIN_CHALLENGE_1, REJECT_CRLF);
+ snprintf(current_settings->smtp_auth_challenge, MAX_BUF, "%s%s%s%n", REJECT_SEVERITY_AUTH_CHALLENGE, SMTP_AUTH_LOGIN_CHALLENGE_1, REJECT_CRLF, &strlen_content);
output_writeln(current_settings, LOG_ACTION_FILTER_FROM, outbound_fd, current_settings->smtp_auth_challenge, strlen_content);
current_settings->smtp_auth_state = SMTP_AUTH_STATE_CHALLENGE_1_SENT;
}
@@ -1376,7 +1467,7 @@
if (current_settings->current_options->filter_action != FILTER_DECISION_ERROR)
{
- strlen_content = snprintf(decoded_content, MAX_BUF, "<%ld.%ld@%s>", random(), (long)time(NULL), (current_settings->current_options->local_server_name != NULL) ? current_settings->current_options->local_server_name : MISSING_LOCAL_SERVER_NAME);
+ snprintf(decoded_content, MAX_BUF, "<%ld.%ld@%s>%n", random(), (long)time(NULL), (current_settings->current_options->local_server_name != NULL) ? current_settings->current_options->local_server_name : MISSING_LOCAL_SERVER_NAME, &strlen_content);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_AUTH_CRAMMD5_CHALLENGE, decoded_content);
snprintf(current_settings->smtp_auth_challenge, MAX_BUF - STRLEN(REJECT_CRLF), "%s ", SMTP_AUTH_CHALLENGE);
@@ -1698,8 +1789,39 @@
else if ((strlen_input_line >= STRLEN(SMTP_DATA)) &&
(strncasecmp(SMTP_DATA, input_line, STRLEN(SMTP_DATA)) == 0))
{
- if (current_settings->num_rcpt_to > 0)
+ if (current_settings->num_recipients > 0)
+ {
current_settings->inside_data = 1;
+ current_settings->inside_header = 1;
+
+ /*
+ * If num_recipients is non-zero, then at least one recipient address was
+ * accepted for some reason. In case it was accepted because for a
+ * transient reason (e.g. recipient whitelist), any non-transient
+ * rejection (e.g. missing rDNS) must be erased so the message body can
+ * come through. All of the unaccpted recipients have already been
+ * rejected and logged at this point.
+ */
+ if (current_settings->current_options->filter_action <= FILTER_DECISION_DO_FILTER)
+ {
+ current_settings->current_options->filter_action = FILTER_DECISION_UNDECIDED;
+ current_settings->current_options->filter_grace = FILTER_GRACE_NONE;
+ current_settings->current_options->rejection = NULL;
+ }
+
+ current_settings->reconstructed_header[0] = '\0';
+ current_settings->strlen_reconstructed_header = 0;
+
+ if (current_settings->current_options->filter_action == FILTER_DECISION_UNDECIDED)
+ {
+ if ((current_settings->blacklist_header != NULL) ||
+ (current_settings->blacklist_header_file != NULL))
+ {
+ output_write_rejection(current_settings, &data_success, outbound_fd, NULL);
+ return_value = FILTER_FLAG_RETAIN | FILTER_FLAG_CHILD_RESPONSE_INTERCEPT;
+ }
+ }
+ }
else if ((current_settings->current_options->filter_action == FILTER_DECISION_DO_FILTER) &&
(current_settings->current_options->filter_grace <= FILTER_GRACE_AFTER_DATA) &&
(current_settings->current_options->rejection != NULL))
@@ -1733,7 +1855,7 @@
(current_settings->current_options->filter_grace != FILTER_GRACE_EXPIRED) ||
(current_settings->current_options->rejection == NULL))
{
- current_settings->num_rcpt_to = 0;
+ current_settings->num_recipients = 0;
current_settings->local_sender = 1;
current_settings->sender_username[0] = '\0';
current_settings->sender_domain[0] = '\0';
@@ -1773,6 +1895,7 @@
{
char buf_input[MAX_NETWORK_BUF + 1];
char buf_childinput[MAX_NETWORK_BUF + 1];
+ int i;
int strlen_buf_input;
int strlen_buf_childinput;
int strlen_buf_trim;
@@ -1781,7 +1904,8 @@
struct timeval listen_timeout;
int more_stdinput;
int more_childinput;
- int discard_childinput;
+ int discard_childinput_all;
+ int discard_childinput_once;
long current_time;
int filter_return;
int network_ready;
@@ -1803,6 +1927,7 @@
char tmp_sender_address[MAX_ADDRESS + 1];
char tmp_recipient_address[MAX_ADDRESS + 1];
char tmp_buf[MAX_BUF + 1];
+ int capture_data;
strlen_buf_input = 0;
usable_buf_input = 0;
@@ -1815,15 +1940,19 @@
child_response_needed = (child_pid != -1) ? 1 : 0;
timeout_printed = 0;
child_stopped = 0;
+ capture_data = 0;
more_stdinput = 1;
more_childinput = ((*inbound_fd >= 0) && (*outbound_fd >= 0)) ? 1 : 0;
- discard_childinput = !more_childinput;
+ discard_childinput_all = !more_childinput;
+ discard_childinput_once = 0;
current_settings->connection_start = time(NULL);
current_settings->command_start = time(NULL);
#ifdef HAVE_LIBSSL
+
+ /* Start SSL for SMTPS */
if ((current_settings->current_options->tls_certificate_file != NULL) &&
(current_settings->current_options->tls_level == TLS_LEVEL_SMTPS))
{
@@ -1850,11 +1979,12 @@
more_stdinput = 0;
more_childinput = 0;
- discard_childinput = 1;
+ discard_childinput_all = 1;
child_response_needed = 0;
}
}
else
+
#endif /* HAVE_LIBSSL */
if (current_settings->current_options->tls_level == TLS_LEVEL_SMTPS)
@@ -1863,25 +1993,28 @@
more_stdinput = 0;
more_childinput = 0;
- discard_childinput = 1;
+ discard_childinput_all = 1;
child_response_needed = 0;
}
/*
+ * This is the main processing loop. Everything happens here.
+ *
* Deciding when to stop looping and disconnect is tricky and this code gets
* updated with almost every version. more_childinput should indicate if
* the qmail child process is still running and thus if spamdyke should
- * continue to accept input from it. discard_childinput should indicate if
+ * continue to accept input from it. discard_childinput_all should indicate if
* spamdyke is discarding qmail's output. This happens when a filter is
* triggered and qmail is cut off. more_stdinput should indicate if the
* remote host is still connected and sending data.
*/
while (more_childinput ||
- (discard_childinput &&
+ (discard_childinput_all &&
more_stdinput))
{
current_time = time(NULL);
+ /* Check both the timeout and idle timeout and disconnect if either one has been reached. */
if (!timeout_printed &&
((!child_response_needed &&
(current_settings->current_options->timeout_connection > 0) &&
@@ -1904,7 +2037,7 @@
output_write_rejection(current_settings, current_settings->current_options->rejection, STDOUT_FD, NULL);
more_stdinput = 0;
- discard_childinput = 1;
+ discard_childinput_all = 1;
child_response_needed = 0;
SPAMDYKE_LOG_INFO(current_settings, "%s from: %s to: %s origin_ip: %s origin_rdns: %s auth: %s encryption: %s reason: %s",
@@ -1924,6 +2057,15 @@
listen_timeout.tv_sec = 0;
listen_timeout.tv_usec = 0;
+ /*
+ * Set the amount of time select() should wait for input.
+ * If a timeout or idle timeout is set, calculate the remaining time, then
+ * reset to a value within 0.5-2 seconds. This is done so spamdyke won't
+ * loop too fast (and consume 100% CPU) or loop too slowly (and miss a
+ * notification that qmail has exited).
+ *
+ * If there are no timeouts set, use some reasonable values.
+ */
if ((current_settings->current_options->timeout_connection > 0) ||
(current_settings->current_options->timeout_command > 0))
{
@@ -2000,13 +2142,21 @@
/*
* Accept and buffer input from qmail.
+ *
+ * buf_childinput is a rotating buffer, where data is typically written
+ * somewhere in the middle of the buffer. Some code at the bottom of the
+ * loop moves the data to the front of the buffer if space is tight.
+ *
+ * This setup is necessary because it's common to have to hold data that
+ * hasn't been processed yet, because the command wasn't completely
+ * delivered in a single packet/read.
*/
if ((*inbound_fd >= 0) &&
FD_ISSET(*inbound_fd, &listen_set))
{
if ((read_result = read(*inbound_fd, buf_childinput + strlen_buf_childinput, MAX_NETWORK_BUF - strlen_buf_childinput)) > 0)
{
- SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_CHILD_READ, read_result, *inbound_fd, strlen_buf_childinput + read_result, (start_buf_childinput != NULL) ? (start_buf_childinput - buf_childinput) : 0);
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_CHILD_READ, read_result, *inbound_fd, strlen_buf_childinput + read_result, (start_buf_childinput != NULL) ? (start_buf_childinput - buf_childinput) : 0, MINVAL(read_result, LOG_DEBUGX_STRLEN_PREVIEW), buf_childinput + strlen_buf_childinput);
strlen_buf_childinput += read_result;
buf_childinput[strlen_buf_childinput] = '\0';
@@ -2015,6 +2165,7 @@
}
else
{
+ /* No more data -- qmail has closed the pipe. */
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_CHILD_FD_EOF, *inbound_fd, strlen_buf_childinput, (start_buf_childinput != NULL) ? (start_buf_childinput - buf_childinput) : 0);
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_CHILD_IN_CLOSE, *inbound_fd);
@@ -2026,6 +2177,10 @@
/*
* Examine qmail's input and take action if necessary.
+ * Necessary actions include injecting text into qmail's greeting (e.g. to
+ * offer authentication or TLS), hiding text in qmail's greeting (e.g. to
+ * block authentication or TLS) and watching qmail's response to
+ * recipients as they are given.
*/
if (strlen_buf_childinput > 0)
{
@@ -2043,12 +2198,14 @@
(start_buf_childinput[strlen_buf_trim - 1] == '\n')))
strlen_buf_trim--;
- if (!discard_childinput)
+ if (!discard_childinput_all &&
+ !discard_childinput_once)
{
if ((line_terminator != '\0') &&
(((filter_return & FILTER_MASK_AUTH) != FILTER_FLAG_AUTH_NONE) ||
((filter_return & FILTER_MASK_TLS) != FILTER_FLAG_TLS_NONE) ||
- ((filter_return & FILTER_MASK_RCPT) != FILTER_FLAG_RCPT_NONE)) &&
+ ((filter_return & FILTER_MASK_RCPT) != FILTER_FLAG_RCPT_NONE) ||
+ capture_data) &&
(strlen_buf_trim > 0))
{
if ((filter_return & FILTER_MASK_RCPT) == FILTER_FLAG_RCPT_CAPTURE)
@@ -2058,7 +2215,29 @@
(strncasecmp(start_buf_childinput, SMTP_RCPT_SUCCESS, STRLEN(SMTP_RCPT_SUCCESS)) == 0))
{
/* qmail said "250". Log success. */
- current_settings->num_rcpt_to++;
+ if ((current_settings->allowed_recipients = realloc(current_settings->allowed_recipients, sizeof(char *) * (current_settings->num_recipients + 2))) != NULL)
+ {
+ if ((current_settings->allowed_recipients[current_settings->num_recipients] = malloc(sizeof(char) * (MAX_ADDRESS + 1))) != NULL)
+ {
+ reassemble_address(current_settings->recipient_username, current_settings->recipient_domain, LOG_MISSING_DATA, current_settings->allowed_recipients[current_settings->num_recipients], MAX_ADDRESS, NULL);
+ current_settings->num_recipients++;
+ current_settings->allowed_recipients[current_settings->num_recipients] = NULL;
+ }
+ else
+ {
+ SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_MALLOC, sizeof(char) * (MAX_ADDRESS + 1));
+ more_stdinput = 0;
+ discard_childinput_all = 1;
+ child_response_needed = 0;
+ }
+ }
+ else
+ {
+ SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_MALLOC, sizeof(char *) * (current_settings->num_recipients + 2));
+ more_stdinput = 0;
+ discard_childinput_all = 1;
+ child_response_needed = 0;
+ }
}
else
{
@@ -2071,16 +2250,19 @@
output_writeln(current_settings, LOG_ACTION_CHILD_FROM, STDOUT_FD, start_buf_childinput, next_terminator - start_buf_childinput);
filter_return ^= FILTER_FLAG_RCPT_CAPTURE;
- SPAMDYKE_LOG_INFO(current_settings, "%s from: %s to: %s origin_ip: %s origin_rdns: %s auth: %s encryption: %s reason: %s",
- (current_settings->current_options->transient_rejection != NULL) ? current_settings->current_options->transient_rejection->short_reject_message : ((current_settings->current_options->rejection != NULL) ? current_settings->current_options->rejection->short_reject_message : SHORT_SUCCESS),
- reassemble_address(current_settings->sender_username, current_settings->sender_domain, LOG_MISSING_DATA, tmp_sender_address, MAX_ADDRESS, NULL),
- reassemble_address(current_settings->recipient_username, current_settings->recipient_domain, LOG_MISSING_DATA, tmp_recipient_address, MAX_ADDRESS, NULL),
- (current_settings->server_ip != NULL) ? current_settings->server_ip : LOG_MISSING_DATA,
- (current_settings->strlen_server_name > 0) ? current_settings->server_name : LOG_MISSING_DATA,
- (current_settings->smtp_auth_username[0] != '\0') ? current_settings->smtp_auth_username : LOG_MISSING_DATA,
- tls_state_desc(current_settings),
- (current_settings->current_options->transient_rejection != NULL) ? ((current_settings->current_options->transient_rejection->reject_reason != NULL) ? current_settings->current_options->transient_rejection->reject_reason : LOG_EMPTY_DATA) : (((current_settings->current_options->rejection != NULL) && (current_settings->current_options->rejection->reject_reason != NULL)) ? current_settings->current_options->rejection->reject_reason : LOG_EMPTY_DATA)
- );
+ if ((current_settings->current_options->transient_rejection != NULL) ||
+ (current_settings->current_options->rejection != NULL))
+ SPAMDYKE_LOG_INFO(current_settings, "%s from: %s to: %s origin_ip: %s origin_rdns: %s auth: %s encryption: %s reason: %s",
+ (current_settings->current_options->transient_rejection != NULL) ? current_settings->current_options->transient_rejection->short_reject_message : ((current_settings->current_options->rejection != NULL) ? current_settings->current_options->rejection->short_reject_message : SHORT_SUCCESS),
+ reassemble_address(current_settings->sender_username, current_settings->sender_domain, LOG_MISSING_DATA, tmp_sender_address, MAX_ADDRESS, NULL),
+ reassemble_address(current_settings->recipient_username, current_settings->recipient_domain, LOG_MISSING_DATA, tmp_recipient_address, MAX_ADDRESS, NULL),
+ (current_settings->server_ip != NULL) ? current_settings->server_ip : LOG_MISSING_DATA,
+ (current_settings->strlen_server_name > 0) ? current_settings->server_name : LOG_MISSING_DATA,
+ (current_settings->smtp_auth_username[0] != '\0') ? current_settings->smtp_auth_username : LOG_MISSING_DATA,
+ tls_state_desc(current_settings),
+ (current_settings->current_options->transient_rejection != NULL) ? ((current_settings->current_options->transient_rejection->reject_reason != NULL) ? current_settings->current_options->transient_rejection->reject_reason : LOG_EMPTY_DATA) : (((current_settings->current_options->rejection != NULL) && (current_settings->current_options->rejection->reject_reason != NULL)) ? current_settings->current_options->rejection->reject_reason : LOG_EMPTY_DATA)
+ );
+
current_settings->current_options->transient_rejection = NULL;
}
else if ((((filter_return & FILTER_FLAG_AUTH_ADD) == FILTER_FLAG_AUTH_ADD) ||
@@ -2090,7 +2272,11 @@
(strlen_buf_trim >= STRLEN(SMTP_EHLO_SUCCESS)) &&
(strncasecmp(start_buf_childinput, SMTP_EHLO_SUCCESS, STRLEN(SMTP_EHLO_SUCCESS)) == 0))
{
- /* The server said "250". */
+ /*
+ * Watching for qmail's response to a EHLO command in order to
+ * inject or hide a feature. The server said "250", so it's
+ * done responding.
+ */
added_ehlo_continuation = 0;
if (((filter_return & FILTER_FLAG_AUTH_ADD) == FILTER_FLAG_AUTH_ADD) &&
@@ -2123,7 +2309,12 @@
}
else
{
- /* The server said "250 AUTH ". Hopefully it doesn't support an algorithm spamdyke can't handle... */
+ /*
+ * spamdyke isn't supposed to overwrite qmail's
+ * authentication and it said "250 AUTH", so it's got it
+ * covered. Hopefully it doesn't support an algorithm
+ * spamdyke can't handle...
+ */
if (((filter_return & FILTER_MASK_TLS) == FILTER_FLAG_TLS_ADD) &&
(start_buf_childinput[STRLEN(SMTP_EHLO_SUCCESS)] != SMTP_CONTINUATION))
{
@@ -2259,6 +2450,7 @@
(strlen_buf_trim >= STRLEN(SMTP_AUTH_CHALLENGE)) &&
(strncasecmp(start_buf_childinput, SMTP_AUTH_CHALLENGE, STRLEN(SMTP_AUTH_CHALLENGE)) == 0))
{
+ /* Watching for authentication to take place; qmail has issued the challenge. */
memcpy(current_settings->smtp_auth_challenge, start_buf_childinput, sizeof(char) * MINVAL(MAX_BUF, strlen_buf_trim));
current_settings->smtp_auth_challenge[MINVAL(MAX_BUF, strlen_buf_trim)] = '\0';
current_settings->smtp_auth_state = SMTP_AUTH_STATE_CHALLENGE_1_SENT;
@@ -2269,14 +2461,24 @@
(strlen_buf_trim >= STRLEN(SMTP_AUTH_CHALLENGE)) &&
(strncasecmp(start_buf_childinput, SMTP_AUTH_CHALLENGE, STRLEN(SMTP_AUTH_CHALLENGE)) == 0))
{
+ /* Watching for authentication to take place; qmail has issued a second challenge. */
current_settings->smtp_auth_state = SMTP_AUTH_STATE_CHALLENGE_2_SENT;
output_writeln(current_settings, LOG_ACTION_CHILD_FROM, STDOUT_FD, start_buf_childinput, next_terminator - start_buf_childinput);
}
else if (((filter_return & FILTER_FLAG_AUTH_CAPTURE) == FILTER_FLAG_AUTH_CAPTURE) &&
- (current_settings->smtp_auth_state == SMTP_AUTH_STATE_RESPONSE_2_SEEN) &&
+ ((current_settings->smtp_auth_state == SMTP_AUTH_STATE_UNKNOWN) ||
+ (current_settings->smtp_auth_state == SMTP_AUTH_STATE_RESPONSE_2_SEEN)) &&
(strlen_buf_trim >= STRLEN(SMTP_AUTH_SUCCESS)) &&
(strncasecmp(start_buf_childinput, SMTP_AUTH_SUCCESS, STRLEN(SMTP_AUTH_SUCCESS)) == 0))
{
+ /* Watching for authentication to take place; qmail has signaled a successful authentication. */
+ if (current_settings->smtp_auth_state == SMTP_AUTH_STATE_UNKNOWN)
+ {
+ tmp_strlen = strlen(current_settings->smtp_auth_response);
+ memcpy(current_settings->smtp_auth_username, current_settings->smtp_auth_response, sizeof(char) * MINVAL(tmp_strlen, MAX_BUF));
+ current_settings->smtp_auth_username[MINVAL(tmp_strlen, MAX_BUF)] = '\0';
+ }
+
current_settings->smtp_auth_state = SMTP_AUTH_STATE_AUTHENTICATED;
if (!current_settings->current_options->filter_action_locked)
{
@@ -2293,27 +2495,7 @@
(strlen_buf_trim >= STRLEN(SMTP_AUTH_PROMPT)) &&
(strncasecmp(start_buf_childinput, SMTP_AUTH_PROMPT, STRLEN(SMTP_AUTH_PROMPT)) == 0))
{
- // Continue watching the AUTH conversation.
- output_writeln(current_settings, LOG_ACTION_CHILD_FROM, STDOUT_FD, start_buf_childinput, next_terminator - start_buf_childinput);
- }
- else if (((filter_return & FILTER_FLAG_AUTH_CAPTURE) == FILTER_FLAG_AUTH_CAPTURE) &&
- (current_settings->smtp_auth_state == SMTP_AUTH_STATE_UNKNOWN) &&
- (strlen_buf_trim >= STRLEN(SMTP_AUTH_SUCCESS)) &&
- (strncasecmp(start_buf_childinput, SMTP_AUTH_SUCCESS, STRLEN(SMTP_AUTH_SUCCESS)) == 0))
- {
- tmp_strlen = strlen(current_settings->smtp_auth_response);
- memcpy(current_settings->smtp_auth_username, current_settings->smtp_auth_response, sizeof(char) * MINVAL(tmp_strlen, MAX_BUF));
- current_settings->smtp_auth_username[MINVAL(tmp_strlen, MAX_BUF)] = '\0';
-
- current_settings->smtp_auth_state = SMTP_AUTH_STATE_AUTHENTICATED;
- if (!current_settings->current_options->filter_action_locked)
- {
- current_settings->current_options->filter_action = FILTER_DECISION_DO_NOT_FILTER;
- current_settings->current_options->rejection = NULL;
- }
-
- filter_return ^= FILTER_FLAG_AUTH_CAPTURE;
- output_writeln(current_settings, LOG_ACTION_AUTH_SUCCESS, -1, NULL, -1);
+ /* Watching for authentication to take place; keep watching. */
output_writeln(current_settings, LOG_ACTION_CHILD_FROM, STDOUT_FD, start_buf_childinput, next_terminator - start_buf_childinput);
}
else if (((filter_return & FILTER_FLAG_AUTH_CAPTURE) == FILTER_FLAG_AUTH_CAPTURE) &&
@@ -2321,6 +2503,7 @@
(strlen_buf_trim >= STRLEN(SMTP_AUTH_FAILURE)) &&
(strncasecmp(start_buf_childinput, SMTP_AUTH_FAILURE, STRLEN(SMTP_AUTH_FAILURE)) == 0))
{
+ /* Watching for authentication to take place; qmail just signaled failure. */
current_settings->smtp_auth_state = SMTP_AUTH_STATE_NONE;
filter_return ^= FILTER_FLAG_AUTH_CAPTURE;
output_writeln(current_settings, LOG_ACTION_AUTH_FAILURE, -1, (current_settings->smtp_auth_response[0] != '\0') ? current_settings->smtp_auth_response : LOG_MISSING_DATA, -1);
@@ -2330,6 +2513,7 @@
(strlen_buf_trim >= STRLEN(SMTP_TLS_SUCCESS)) &&
(strncasecmp(start_buf_childinput, SMTP_TLS_SUCCESS, STRLEN(SMTP_TLS_SUCCESS)) == 0))
{
+ /* The client is starting TLS with qmail; begin passthrough. */
output_writeln(current_settings, LOG_ACTION_CHILD_FROM, STDOUT_FD, start_buf_childinput, next_terminator - start_buf_childinput);
current_settings->tls_state = TLS_STATE_ACTIVE_PASSTHROUGH;
filter_return ^= FILTER_FLAG_TLS_CAPTURE;
@@ -2353,8 +2537,56 @@
LOG_EMPTY_DATA
);
}
+ else if (capture_data)
+ {
+ /* The client sent the entire message through; see how qmail responds and print log messages. */
+ if ((strlen_buf_trim >= STRLEN(SMTP_DATA_SUCCESS)) &&
+ (strncasecmp(start_buf_childinput, SMTP_DATA_SUCCESS, STRLEN(SMTP_DATA_SUCCESS)) == 0))
+ {
+ /* Message accepted */
+ output_writeln(current_settings, LOG_ACTION_CHILD_FROM, STDOUT_FD, start_buf_childinput, next_terminator - start_buf_childinput);
+
+ for (i = 0; i < current_settings->num_recipients; i++)
+ SPAMDYKE_LOG_INFO(current_settings, "%s from: %s to: %s origin_ip: %s origin_rdns: %s auth: %s encryption: %s reason: %s",
+ SHORT_SUCCESS,
+ reassemble_address(current_settings->sender_username, current_settings->sender_domain, LOG_MISSING_DATA, tmp_sender_address, MAX_ADDRESS, NULL),
+ current_settings->allowed_recipients[i],
+ (current_settings->server_ip != NULL) ? current_settings->server_ip : LOG_MISSING_DATA,
+ (current_settings->strlen_server_name > 0) ? current_settings->server_name : LOG_MISSING_DATA,
+ (current_settings->smtp_auth_username[0] != '\0') ? current_settings->smtp_auth_username : LOG_MISSING_DATA,
+ tls_state_desc(current_settings),
+ canonicalize_log_text(tmp_buf, MAX_BUF, start_buf_childinput, strlen_buf_trim)
+ );
+ }
+ else
+ {
+ /* Message rejected */
+ SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_FILTER_OTHER_REJECTION, strlen_buf_trim, start_buf_childinput);
+ canonicalize_log_text(tmp_buf, MAX_BUF, start_buf_childinput, strlen_buf_trim);
+ set_rejection(current_settings, REJECTION_OTHER, ¤t_settings->current_options->rejection, ¤t_settings->current_options->rejection_buf, current_settings->current_options->reject_message_buf, MAX_BUF, NULL, tmp_buf, current_settings->current_options->reject_reason_buf, MAX_BUF);
+ output_writeln(current_settings, LOG_ACTION_CHILD_FROM, STDOUT_FD, start_buf_childinput, next_terminator - start_buf_childinput);
+
+ for (i = 0; i < current_settings->num_recipients; i++)
+ SPAMDYKE_LOG_INFO(current_settings, "%s from: %s to: %s origin_ip: %s origin_rdns: %s auth: %s encryption: %s reason: %s",
+ (current_settings->current_options->transient_rejection != NULL) ? current_settings->current_options->transient_rejection->short_reject_message : ((current_settings->current_options->rejection != NULL) ? current_settings->current_options->rejection->short_reject_message : SHORT_SUCCESS),
+ reassemble_address(current_settings->sender_username, current_settings->sender_domain, LOG_MISSING_DATA, tmp_sender_address, MAX_ADDRESS, NULL),
+ current_settings->allowed_recipients[i],
+ (current_settings->server_ip != NULL) ? current_settings->server_ip : LOG_MISSING_DATA,
+ (current_settings->strlen_server_name > 0) ? current_settings->server_name : LOG_MISSING_DATA,
+ (current_settings->smtp_auth_username[0] != '\0') ? current_settings->smtp_auth_username : LOG_MISSING_DATA,
+ tls_state_desc(current_settings),
+ canonicalize_log_text(tmp_buf, MAX_BUF, start_buf_childinput, strlen_buf_trim)
+ );
+ }
+
+ capture_data = 0;
+ }
else
{
+ /*
+ * Waiting for authentication or TLS, but neither one happened.
+ * Clear the flags and send the buffer to the client.
+ */
if ((filter_return & FILTER_FLAG_AUTH_CAPTURE) == FILTER_FLAG_AUTH_CAPTURE)
{
filter_return ^= FILTER_FLAG_AUTH_CAPTURE;
@@ -2370,7 +2602,10 @@
output_writeln(current_settings, LOG_ACTION_CHILD_FROM, STDOUT_FD, start_buf_childinput, next_terminator - start_buf_childinput);
}
else
+ {
output_writeln(current_settings, LOG_ACTION_CHILD_FROM_DISCARDED, -1, start_buf_childinput, next_terminator - start_buf_childinput);
+ discard_childinput_once = 0;
+ }
start_buf_childinput = next_terminator;
}
@@ -2431,14 +2666,16 @@
next_terminator = NULL;
/*
- * Accept and buffer input from the remote server
+ * Accept and buffer input from the remote server.
+ *
+ * buf_input is a rotating buffer, just like buf_childinput above.
*/
if (FD_ISSET(STDIN_FD, &listen_set) ||
NETWORK_CAN_READ(current_settings))
{
if ((read_result = NETWORK_READ(current_settings, STDIN_FD, buf_input + strlen_buf_input, MAX_NETWORK_BUF - strlen_buf_input)) > 0)
{
- SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_NETWORK_READ, read_result, STDIN_FD, strlen_buf_input + read_result, (start_buf_input != NULL) ? (start_buf_input - buf_input) : 0);
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_NETWORK_READ, read_result, STDIN_FD, strlen_buf_input + read_result, (start_buf_input != NULL) ? (start_buf_input - buf_input) : 0, MINVAL(read_result, LOG_DEBUGX_STRLEN_PREVIEW), buf_input + strlen_buf_input);
strlen_buf_input += read_result;
buf_input[strlen_buf_input] = '\0';
usable_buf_input = 1;
@@ -2490,7 +2727,8 @@
* attachments, this can be a big win (assuming the remote server
* also sends the data in large chunks).
*/
- if ((current_settings->inside_data) &&
+ if (current_settings->inside_data &&
+ !current_settings->inside_header &&
(strncmp(start_buf_input, SMTP_DATA_END, STRLEN(SMTP_DATA_END)) != 0))
while ((tmp_terminator = memchr(next_terminator, line_terminator, strlen_buf_input - (next_terminator - buf_input))) != NULL)
{
@@ -2522,15 +2760,87 @@
}
filter_return = smtp_filter(STDIN_FD, STDOUT_FD, start_buf_input, strlen_buf_trim, current_settings);
+
+ if ((filter_return & FILTER_MASK_CHILD_RESPONSE) == FILTER_FLAG_CHILD_RESPONSE_INTERCEPT)
+ {
+ discard_childinput_once = 1;
+ filter_return ^= FILTER_FLAG_CHILD_RESPONSE_INTERCEPT;
+ }
+ if ((filter_return & FILTER_MASK_DATA) == FILTER_FLAG_DATA_CAPTURE)
+ {
+ capture_data = 1;
+ filter_return ^= FILTER_FLAG_DATA_CAPTURE;
+ }
+
switch (filter_return & FILTER_MASK_PASS)
{
case FILTER_FLAG_PASS:
- child_response_needed = (((filter_return & FILTER_MASK_CHILD_RESPONSE) == FILTER_FLAG_CHILD_RESPONSE_NEEDED) && !discard_childinput) ? 1 : 0;
+ /* Pass the buffered data through to qmail. */
+ if (current_settings->strlen_buf_retain > 0)
+ {
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_RELEASE_DATA, current_settings->strlen_buf_retain, current_settings->strlen_buf_retain, current_settings->buf_retain);
+ output_writeln(current_settings, LOG_ACTION_NONE, *outbound_fd, current_settings->buf_retain, current_settings->strlen_buf_retain);
+ current_settings->strlen_buf_retain = 0;
+ }
+
+ child_response_needed = (((filter_return & FILTER_MASK_CHILD_RESPONSE) == FILTER_FLAG_CHILD_RESPONSE_NEEDED) && !discard_childinput_all && !discard_childinput_once) ? 1 : 0;
output_writeln(current_settings, LOG_ACTION_NONE, *outbound_fd, start_buf_input, next_terminator - start_buf_input);
break;
+ case FILTER_FLAG_RETAIN:
+ /* Retain the data in a buffer. */
+ if ((current_settings->max_buf_retain >= 0) &&
+ ((current_settings->max_buf_retain - current_settings->strlen_buf_retain) <= (next_terminator - start_buf_input)) &&
+ ((current_settings->max_buf_retain += MAX_NETWORK_BUF) <= MAX_RETAIN_BUF))
+ if ((current_settings->buf_retain = (char *)realloc(current_settings->buf_retain, sizeof(char) * (current_settings->max_buf_retain + 1))) != NULL)
+ current_settings->buf_retain[current_settings->strlen_buf_retain] = '\0';
+ else
+ {
+ SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_MALLOC, sizeof(char) * (current_settings->max_buf_retain + 1));
+ current_settings->max_buf_retain = -2;
+ }
+ else if (current_settings->max_buf_retain > MAX_RETAIN_BUF)
+ {
+ /* Too much retained data; can't save any more. Send everything to qmail and don't retain any more. */
+ SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_BUFFER_OVERSIZE, current_settings->strlen_buf_retain, current_settings->strlen_buf_retain + (next_terminator - start_buf_input), MAX_RETAIN_BUF);
+ child_response_needed = (((filter_return & FILTER_MASK_CHILD_RESPONSE) == FILTER_FLAG_CHILD_RESPONSE_NEEDED) && !discard_childinput_all && !discard_childinput_once) ? 1 : 0;
+ output_writeln(current_settings, LOG_ACTION_NONE, *outbound_fd, current_settings->buf_retain, current_settings->strlen_buf_retain);
+
+ current_settings->strlen_buf_retain = 0;
+ current_settings->max_buf_retain = -1;
+ if (current_settings->buf_retain != NULL)
+ {
+ free(current_settings->buf_retain);
+ current_settings->buf_retain = NULL;
+ }
+
+ if (discard_childinput_once)
+ discard_childinput_once = 0;
+ }
+
+ if (current_settings->buf_retain != NULL)
+ {
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_RETAIN_DATA, next_terminator - start_buf_input, current_settings->strlen_buf_retain + (next_terminator - start_buf_input), current_settings->max_buf_retain);
+ memcpy(current_settings->buf_retain + current_settings->strlen_buf_retain, start_buf_input, next_terminator - start_buf_input);
+ current_settings->strlen_buf_retain += next_terminator - start_buf_input;
+ current_settings->buf_retain[current_settings->strlen_buf_retain] = '\0';
+
+ break;
+ }
+ else if (current_settings->max_buf_retain != -2)
+ {
+ output_writeln(current_settings, LOG_ACTION_NONE, *outbound_fd, start_buf_input, next_terminator - start_buf_input);
+
+ break;
+ }
+
+ child_response_needed = (((filter_return & FILTER_MASK_CHILD_RESPONSE) == FILTER_FLAG_CHILD_RESPONSE_NEEDED) && !discard_childinput_all && !discard_childinput_once) ? 1 : 0;
+
+ /* ELSE An error occurred - fall through to the next case */
+
case FILTER_FLAG_QUIT:
+ /* Close everything and exit gracefully. */
more_stdinput = 0;
- discard_childinput = 1;
+ discard_childinput_all = 1;
child_response_needed = 0;
if ((current_settings->current_options->rejection != NULL) &&
@@ -2550,20 +2860,32 @@
break;
case FILTER_FLAG_INTERCEPT:
+ /*
+ * Don't send the client's data to qmail. If a non-transient
+ * filter has been triggered, close qmail and intercept
+ * everything from now on. smtp_filter() will send bogus
+ * responses as needed until the client quits.
+ */
child_response_needed = 0;
if (((filter_return & FILTER_MASK_CHILD) == FILTER_FLAG_CHILD_QUIT) &&
(current_settings->current_options->rejection != NULL) &&
(*outbound_fd >= 0) &&
- !discard_childinput)
+ !discard_childinput_all)
{
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_CHILD_OUT_CLOSE, *outbound_fd);
close(*outbound_fd);
*outbound_fd = -1;
- discard_childinput = 1;
+ discard_childinput_all = 1;
+ /*
+ * By itself, qmail has an idle timeout. If no timeout is set
+ * for spamdyke, set one here. Otherwise a remote server
+ * could easily DoS the server by opening a few hundred idle
+ * connections.
+ */
if (current_settings->current_options->timeout_command == 0)
{
current_settings->current_options->timeout_command = TIMEOUT_IDLE_AFTER_QUIT_SECS;
@@ -2572,18 +2894,34 @@
}
}
+ /*
+ * If a command has been issued that shouldn't be followed by any
+ * other buffered commands (e.g. "STARTTLS"), clear the buffer and
+ * wait for more input from the client.
+ */
if ((filter_return & FILTER_MASK_CLEAR) == FILTER_FLAG_CLEAR)
{
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_CLEAR_INPUT, strlen_buf_input - strlen_buf_trim);
strlen_buf_input = 0;
buf_input[strlen_buf_input] = '\0';
start_buf_input = NULL;
+
+ if (current_settings->strlen_buf_retain > 0)
+ {
+ SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_CLEAR_BUFFER, current_settings->strlen_buf_retain);
+ current_settings->strlen_buf_retain = 0;
+ }
}
else
start_buf_input = next_terminator;
}
else
{
+ /*
+ * Couldn't find a line terminator, so just wait for more input.
+ * If no more input is coming, send the remaining buffered data
+ * to qmail and close.
+ */
if (!more_stdinput)
{
if ((*outbound_fd) >= 0)
@@ -2605,6 +2943,7 @@
usable_buf_input = 0;
}
+ /* Rotate the buf_input buffer. */
if (strlen_buf_input > 0)
{
if ((start_buf_input - buf_input) >= strlen_buf_input)
@@ -2658,13 +2997,17 @@
close(*outbound_fd);
*outbound_fd = -1;
- discard_childinput = 1;
+ discard_childinput_all = 1;
}
if (strlen_buf_input == 0)
usable_buf_input = 0;
}
+ /*
+ * If qmail is supposed to have quit, wait() for it. If this isn't done,
+ * qmail will stay in a zombie state until spamdyke exits.
+ */
if (child_pid != -1)
{
if (waitpid(child_pid, &wait_status, WNOHANG) == child_pid)
@@ -2697,6 +3040,12 @@
}
}
+ if (current_settings->buf_retain != NULL)
+ {
+ free(current_settings->buf_retain);
+ current_settings->buf_retain = NULL;
+ }
+
return;
}
@@ -2942,12 +3291,14 @@
if ((current_settings->server_ip != NULL) &&
(current_settings->server_ip[0] != '\0'))
{
+ /* If the remote server's IP is "localhost", don't look it up. */
if (!strncasecmp(current_settings->server_ip, LOCALHOST_NAME, STRLEN(LOCALHOST_NAME)))
{
SPAMDYKE_LOG_VERBOSE(current_settings, LOG_VERBOSE_REMOTEIP_LOCALHOST, current_settings->server_ip, LOCALHOST_IP);
current_settings->server_ip = LOCALHOST_IP;
current_settings->strlen_server_ip = STRLEN(LOCALHOST_IP);
}
+ /* If the remote server's IP address is not a dotted quad, assume it is a name and look it up in DNS. */
else if ((sscanf(current_settings->server_ip, "%3[0-9].%3[0-9].%3[0-9].%3[0-9]", ip_octets[0], ip_octets[1], ip_octets[2], ip_octets[3]) != 4) ||
(sscanf(ip_octets[0], "%d", &ip_ints[0]) != 1) ||
(ip_ints[0] < 0) ||
@@ -2966,7 +3317,9 @@
if (nihdns_a(current_settings, current_settings->server_ip, ip_ints, NULL, 0))
{
- current_settings->strlen_server_ip = snprintf(current_settings->tmp_server_ip, MAX_BUF, "%.*s%c%d.%d.%d.%d", strlen_environment_remote_ip[i], environment_remote_ip[i], ENVIRONMENT_DELIMITER, ip_ints[0], ip_ints[1], ip_ints[2], ip_ints[3]) - (strlen_environment_remote_ip[i] + 1);
+ /* Found a correct IP address; fix the environment variable. */
+ snprintf(current_settings->tmp_server_ip, MAX_BUF, "%.*s%c%d.%d.%d.%d%n", strlen_environment_remote_ip[i], environment_remote_ip[i], ENVIRONMENT_DELIMITER, ip_ints[0], ip_ints[1], ip_ints[2], ip_ints[3], ¤t_settings->strlen_server_ip);
+ current_settings->strlen_server_ip -= (strlen_environment_remote_ip[i] + 1);
current_settings->server_ip = current_settings->tmp_server_ip + strlen_environment_remote_ip[i] + 1;
SPAMDYKE_LOG_DEBUG(current_settings, LOG_DEBUG_REMOTEIP_DNS_FOUND, current_settings->server_ip);
@@ -3036,6 +3389,7 @@
if (current_settings->current_options->configuration_dir == NULL)
{
+ /* Here we go. The remote client is connected, so run these filters, if they're enabled. */
filter_level(current_settings, ¤t_settings->current_options->filter_action, ¤t_settings->current_options->filter_action_locked, ¤t_settings->current_options->rejection, ¤t_settings->current_options->rejection_buf, current_settings->current_options->reject_message_buf, MAX_BUF);
filter_rdns_missing(current_settings, ¤t_settings->current_options->filter_action, ¤t_settings->current_options->filter_action_locked, ¤t_settings->current_options->rejection, ¤t_settings->current_options->rejection_buf, current_settings->current_options->reject_message_buf, MAX_BUF);
filter_ip_in_rdns_cc(current_settings, ¤t_settings->current_options->filter_action, ¤t_settings->current_options->filter_action_locked, ¤t_settings->current_options->rejection, ¤t_settings->current_options->rejection_buf, current_settings->current_options->reject_message_buf, MAX_BUF);
@@ -3057,11 +3411,20 @@
filter_earlytalker(current_settings, 1, ¤t_settings->current_options->filter_action, ¤t_settings->current_options->filter_action_locked, ¤t_settings->current_options->rejection, ¤t_settings->current_options->rejection_buf, current_settings->current_options->reject_message_buf, MAX_BUF);
}
else
+ /*
+ * A configuration directory is available, so most of the tests must wait
+ * until the sender and recipient have been specified. Otherwise a test
+ * could be run (or skipped) that a configuration directory entry disables
+ * (or enables). The earlytalker filter must be run now, though, or it
+ * won't make any sense later. If a configuration directory disables the
+ * earlytalker filter, the result of this test will be ignored.
+ */
filter_earlytalker(current_settings, 1, NULL, ¤t_settings->current_options->filter_action_locked, NULL, NULL, NULL, 0);
}
#ifdef HAVE_LIBSSL
+ /* Initialize OpenSSL */
if ((current_settings->current_options->tls_certificate_file != NULL) &&
!tls_init(current_settings))
{
@@ -3072,6 +3435,7 @@
#endif /* HAVE_LIBSSL */
+ /* Look for the TCPLOCALPORT environment variable and set it if it's not found. */
found_match = 0;
if (current_settings->current_environment != NULL)
{
@@ -3125,6 +3489,7 @@
}
}
+ /* Look for the SMTPS environment variable and remove it if found. */
if (current_settings->current_options->filter_action != FILTER_DECISION_ERROR)
for (i = 0; current_settings->current_environment[i] != NULL; i++)
if (strncasecmp(current_settings->current_environment[i], ENVIRONMENT_SMTPS, STRLEN(ENVIRONMENT_SMTPS)) == 0)
@@ -3143,6 +3508,7 @@
input_pipe[0] = -1;
input_pipe[1] = -1;
+ /* Start qmail */
if (find_path(current_settings, current_settings->child_argv[0], current_settings->current_environment, new_filename, MAX_BUF))
{
if ((current_settings->current_options->filter_action == FILTER_DECISION_DO_FILTER) &&
@@ -3238,8 +3604,10 @@
SPAMDYKE_LOG_ERROR(current_settings, LOG_ERROR_EXEC "%s: %s", current_settings->child_argv[0], strerror(errno));
#ifdef HAVE_LIBSSL
+
if (tls_end(current_settings, STDIN_FD))
output_writeln(current_settings, LOG_ACTION_TLS_END, -1, NULL, -1);
+
#endif /* HAVE_LIBSSL */
}
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/spamdyke.h
^
|
@@ -184,10 +184,14 @@
#define REASON_REPLACE_TARGET ' '
#define REASON_REPLACE_REPLACEMENT '_'
+#define HEADER_DELIMITER ':'
+
#define MAX_ADDRESS 511
#define MAX_PATH 4095
#define MAX_BUF 1023
#define MAX_NETWORK_BUF 16383
+/* MAX_RETAIN_BUF should be evenly divisible by MAX_NETWORK_BUF */
+#define MAX_RETAIN_BUF 524256
#define MAX_FILE_BUF 65535
#define MAX_FILE_LINES 65536
#define MAX_POLICY 100
@@ -229,46 +233,84 @@
#define USAGE_MESSAGE_FOOTER_SHORT "Use -h for an option summary or see README.html for complete option details.\n\n"
#define USAGE_MESSAGE_FOOTER_LONG "\nSee README.html for a complete explanation of these options.\n"
-#define FILTER_MASK_PASS 0x03
+/*
+ * The FILTER_* values are returned by smtp_filter() and interpreted by
+ * middleman(). These values are ORed together and separated by ANDing the
+ * FILTER_MASK_* value to reveal the set value. For that reason, it is very
+ * important that none of the FILTER_FLAG_* values use bits that aren't
+ * covered by its FILTER_MASK_* value. And of course none of them should
+ * overlap.
+ */
+#define FILTER_MASK_PASS 0x07
/* PASS is implied in assignments if another flag is not specified. */
+/* PASS = send the data to qmail */
#define FILTER_FLAG_PASS 0x00
+/* INTERCEPT = delete the data; do not send to qmail */
#define FILTER_FLAG_INTERCEPT 0x01
-#define FILTER_FLAG_QUIT 0x02
+/* RETAIN = buffer the data for future processing; do not send to qmail yet */
+#define FILTER_FLAG_RETAIN 0x02
+/* QUIT = exit spamdyke entirely (due to error) */
+#define FILTER_FLAG_QUIT 0x04
-#define FILTER_MASK_CHILD 0x04
+#define FILTER_MASK_CHILD 0x08
/* CHILD_CONTINUE is implied in assignments if CHILD_QUIT is not specified. */
+/* CHILD_CONTINUE = maintain connection with qmail process */
#define FILTER_FLAG_CHILD_CONTINUE 0x00
-#define FILTER_FLAG_CHILD_QUIT 0x04
+/* CHILD_QUIT = signal qmail to quit and close the connection; intercept all future data */
+#define FILTER_FLAG_CHILD_QUIT 0x08
-#define FILTER_MASK_AUTH 0x38
-/* AUTH_NONE is implied in assignments if another flag is not specified. */
/* AUTH values allow multiple flags to be set simultaneously. */
+#define FILTER_MASK_AUTH 0x70
+/* AUTH_NONE is implied in assignments if another flag is not specified. */
+/* AUTH_NONE = ignore SMTP AUTH commands */
#define FILTER_FLAG_AUTH_NONE 0x00
-#define FILTER_FLAG_AUTH_ADD 0x08
-#define FILTER_FLAG_AUTH_CAPTURE 0x10
-#define FILTER_FLAG_AUTH_REMOVE 0x20
+/* AUTH_ADD = add an SMTP AUTH banner if none is sent by qmail (or if qmail's is removed by spamdyke) */
+#define FILTER_FLAG_AUTH_ADD 0x10
+/* AUTH_CAPTURE = monitor/process SMTP AUTH data to determine if authentication succeeds */
+#define FILTER_FLAG_AUTH_CAPTURE 0x20
+/* AUTH_REMOVE = remove all SMTP AUTH banners and commands */
+#define FILTER_FLAG_AUTH_REMOVE 0x40
-#define FILTER_MASK_TLS 0xC0
+#define FILTER_MASK_TLS 0x0180
/* TLS_NONE is implied in assignments if another flag is not specified. */
-#define FILTER_FLAG_TLS_NONE 0x00
-#define FILTER_FLAG_TLS_ADD 0x40
-#define FILTER_FLAG_TLS_CAPTURE 0x80
-#define FILTER_FLAG_TLS_REMOVE 0xC0
+/* TLS_NONE = ignore TLS commands */
+#define FILTER_FLAG_TLS_NONE 0x0000
+/* TLS_ADD = add a TLS banner if none is sent by qmail */
+#define FILTER_FLAG_TLS_ADD 0x0080
+/* TLS_CAPTURE = monitor TLS commands and pass encrypted traffic through without processing */
+#define FILTER_FLAG_TLS_CAPTURE 0x0100
+/* TLS_REMOVE = remove all TLS banners and commands */
+#define FILTER_FLAG_TLS_REMOVE 0x0180
-#define FILTER_MASK_RCPT 0x0100
+#define FILTER_MASK_RCPT 0x0200
/* RCPT_NONE is implied in assignments if another flag is not specified. */
+/* RCPT_NONE = ignore recipient commands */
#define FILTER_FLAG_RCPT_NONE 0x0000
-#define FILTER_FLAG_RCPT_CAPTURE 0x0100
+/* RCPT_CAPTURE = monitor qmail's response to a recipient command */
+#define FILTER_FLAG_RCPT_CAPTURE 0x0200
-#define FILTER_MASK_CHILD_RESPONSE 0x0200
+#define FILTER_MASK_CHILD_RESPONSE 0x0C00
/* CHILD_RESPONSE_NEEDED is implied in assignments if another flag is not specified. */
+/* CHILD_RESPONSE_NEEDED = middleman() should expect a response from qmail before processing any more commands from the remote server */
#define FILTER_FLAG_CHILD_RESPONSE_NEEDED 0x0000
-#define FILTER_FLAG_CHILD_RESPONSE_NOT_NEEDED 0x0200
+/* CHILD_RESPONSE_NOT_NEEDED = middleman() should continue sending commands from the remote server without waiting for qmail's response */
+#define FILTER_FLAG_CHILD_RESPONSE_NOT_NEEDED 0x0400
+/* CHILD_RESPONSE_INTERCEPT = middleman() should discard the next response from qmail */
+#define FILTER_FLAG_CHILD_RESPONSE_INTERCEPT 0x0800
-#define FILTER_MASK_CLEAR 0x0400
+#define FILTER_MASK_CLEAR 0x1000
/* KEEP is implied in assignments if another flag is not specified. */
+/* KEEP = retain any buffered data from the remote server and continue processing it */
#define FILTER_FLAG_KEEP 0x0000
-#define FILTER_FLAG_CLEAR 0x0400
+/* CLEAR = delete any buffered data from the remote server and wait for more */
+#define FILTER_FLAG_CLEAR 0x1000
+
+#define FILTER_MASK_DATA 0x2000
+/* DATA_NONE is implied in assignments if another flag is not specified. */
+/* DATA_NONE = ignore data commands */
+#define FILTER_FLAG_DATA_NONE 0x0000
+/* DATA_CAPTURE = monitor qmail's response to a data command */
+#define FILTER_FLAG_DATA_CAPTURE 0x2000
/*
* The values of these constants are significant. set_config_value() and
@@ -279,13 +321,21 @@
* When FILTER_DECISION_TRANSIENT_DO_FILTER is set, transient_rejection must also be set.
* When FILTER_DECISION_DO_FILTER is set, rejection must also be set.
*/
+/* UNDECIDED: processing should continue, no decision has been reached yet. */
#define FILTER_DECISION_UNDECIDED 0
+/* TRANSIENT_DO_FILTER: block the incoming message for the current recipient only, then revert back to UNDECIDED. */
#define FILTER_DECISION_TRANSIENT_DO_FILTER 1
+/* DO_FILTER: block the entire incoming message. */
#define FILTER_DECISION_DO_FILTER 2
+/* TRANSIENT_DO_NOT_FILTER: allow the incoming message for the current recipient only, then revert back to the previous value. */
#define FILTER_DECISION_TRANSIENT_DO_NOT_FILTER 3
+/* DO_NOT_FILTER: allow the entire incoming message. */
#define FILTER_DECISION_DO_NOT_FILTER 4
+/* CONFIG_TEST: the config-test option was used; run the tests and exit. */
#define FILTER_DECISION_CONFIG_TEST 5
+/* FORK_ERROR: an error occurred while trying to start qmail; log the error and try to start qmail without spamdyke. */
#define FILTER_DECISION_FORK_ERROR 6
+/* ERROR: a serious error occurred, probably unable to allocate memory; log the error (if possible) and exit. */
#define FILTER_DECISION_ERROR 7
/*
@@ -348,6 +398,7 @@
#define REJECT_SEVERITY_PERMANENT "554 "
#define REJECT_SEVERITY_TLS_SUCCESS "220 "
#define REJECT_SEVERITY_TLS_FAILURE "454 "
+#define REJECT_SEVERITY_DATA_SUCCESS "354 "
#define STRLEN_REJECT_SEVERITY 4
#define REJECT_CRLF "\r\n"
@@ -431,6 +482,7 @@
#define SMTP_TLS_SUCCESS "220"
#define SMTP_TLS_REGREETING "220 ESMTP\r\n"
#define SMTP_RCPT_SUCCESS "250"
+#define SMTP_DATA_SUCCESS "250"
#define CHILD_QUIT ".\r\nQUIT\r\n"
@@ -459,6 +511,7 @@
#define SUCCESS_AUTH { -1, REJECT_SEVERITY_AUTH_SUCCESS, "Proceed.", 8, SHORT_SUCCESS "_AUTHENTICATED", 0, NULL, 0 }
#define SUCCESS_TLS { -2, REJECT_SEVERITY_TLS_SUCCESS, "Proceed.", 8, SHORT_SUCCESS "_TLS", 0, NULL, 0 }
+#define SUCCESS_DATA { -3, REJECT_SEVERITY_DATA_SUCCESS, "Proceed.", 8, SHORT_SUCCESS "_DATA", 0, NULL, 0 }
#define REJECTION_RCPT_TO 0
#define ERROR_RCPT_TO "Too many recipients. Try the remaining addresses again later."
@@ -560,7 +613,11 @@
#define ERROR_IDENTICAL_FROM_TO "Refused. Identical sender and recipient addresses are not allowed."
#define REJECTION_DATA_IDENTICAL_FROM_TO { REJECTION_IDENTICAL_FROM_TO, REJECT_SEVERITY_PERMANENT, ERROR_IDENTICAL_FROM_TO, STRLEN(ERROR_IDENTICAL_FROM_TO), "DENIED_IDENTICAL_SENDER_RECIPIENT", 1, NULL, 0 }
-#define FAILURE_TLS 25
+#define REJECTION_HEADER_BLACKLISTED 25
+#define ERROR_HEADER_BLACKLISTED "Refused. Your message has been blocked due to its content."
+#define REJECTION_DATA_HEADER_BLACKLISTED { REJECTION_HEADER_BLACKLISTED, REJECT_SEVERITY_PERMANENT, ERROR_HEADER_BLACKLISTED, STRLEN(ERROR_HEADER_BLACKLISTED), "DENIED_HEADER_BLACKLISTED", 1, NULL, 0 }
+
+#define FAILURE_TLS 26
#define ERROR_FAILURE_TLS "Failed to negotiate TLS connection."
#define FAILURE_DATA_TLS { FAILURE_TLS, REJECT_SEVERITY_TLS_FAILURE, ERROR_FAILURE_TLS, STRLEN(ERROR_FAILURE_TLS), "FAILED_TLS", 0, NULL, 0 }
@@ -590,6 +647,7 @@
REJECTION_DATA_AUTH_REQUIRED, \
REJECTION_DATA_UNCONDITIONAL, \
REJECTION_DATA_IDENTICAL_FROM_TO, \
+ REJECTION_DATA_HEADER_BLACKLISTED, \
FAILURE_DATA_TLS \
}
@@ -662,8 +720,8 @@
#define NIHDNS_SPOOF_ACCEPT_SAME_PORT 3
#define NIHDNS_SPOOF_REJECT 4
-#define NIHDNS_GETINT16(buffer) (uint16_t)((buffer[0] << 8) | buffer[1])
-#define NIHDNS_GETINT32(buffer) (uint32_t)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3])
+#define NIHDNS_GETINT16(buffer) (uint16_t)(((buffer)[0] << 8) | (buffer)[1])
+#define NIHDNS_GETINT32(buffer) (uint32_t)(((buffer)[0] << 24) | ((buffer)[1] << 16) | ((buffer)[2] << 8) | (buffer)[3])
#define NIHDNS_RESOLV_NAMESERVER "nameserver"
#define NIHDNS_RESOLV_PORT "port"
@@ -857,6 +915,10 @@
#define LOG_VERBOSE_FILTER_IDENTICAL_FROM_TO "FILTER_IDENTICAL_SENDER_RECIPIENT sender: %s recipient: %s"
#define LOG_VERBOSE_MX_IP "ERROR: found IP address in MX record where only are legal: %s domain: %s"
#define LOG_VERBOSE_DNS_OVERSIZE_QUERY "ERROR: unable to create DNS query packet in %d bytes, name: %s type %s"
+#define LOG_VERBOSE_BUFFER_OVERSIZE "ERROR: unable to continue buffering message data, %d bytes of data retained, need %d bytes, maximum %d bytes allowed; emptying buffer"
+#define LOG_VERBOSE_FILTER_HEADER_BLACKLIST "FILTER_HEADER_BLACKLIST header: %s entry: %s"
+#define LOG_VERBOSE_FILTER_HEADER_BLACKLIST_FILE "FILTER_HEADER_BLACKLIST header: %s file: %s(%d)"
+#define LOG_VERBOSE_HEADER_TOO_LONG "ERROR: header line too long, truncated at %d bytes: %.*s"
#define LOG_DEBUG_AUTH_SUCCESS "DEBUG(%s()@%s:%d): authentication successful: "
#define LOG_DEBUG_EXEC "DEBUG(%s()@%s:%d): executing command: %s"
@@ -908,7 +970,9 @@
#define LOG_DEBUG_ADDRESS_ROUTING "DEBUG(%s()@%s:%d): reparsing address from routing symbol at position %d: %s"
#define LOG_DEBUG_ADDRESS_USERNAME "DEBUG(%s()@%s:%d): searching for username between positions %d and %d: %s"
#define LOG_DEBUG_ADDRESS_DOMAIN "DEBUG(%s()@%s:%d): searching for domain between positions %d and %d: %s"
+#define LOG_DEBUG_FILTER_HEADER_BLACKLIST "DEBUG(%s()@%s:%d): searching header blacklist(s); header: %s"
+#define LOG_DEBUGX_STRLEN_PREVIEW 30
#define LOG_DEBUGX_EXEC "EXCESSIVE(%s()@%s:%d): preparing to start child process: %s"
#define LOG_DEBUGX_DNS_QUERY "EXCESSIVE(%s()@%s:%d): sending %d byte query (ID %d/%d) for %s(%s) to DNS server %s:%d (attempt %d)"
#define LOG_DEBUGX_DNS_RECEIVED "EXCESSIVE(%s()@%s:%d): received DNS packet: %d bytes, ID %d/%d"
@@ -951,9 +1015,9 @@
#define LOG_DEBUGX_TEST_GRAYLIST_SENDER_FILE "EXCESSIVE(%s()@%s:%d): found graylist sender user file: %s"
#define LOG_DEBUGX_OPEN_FILE "EXCESSIVE(%s()@%s:%d): opened file for reading: %s"
#define LOG_DEBUGX_READ_LINE "EXCESSIVE(%s()@%s:%d): read %d bytes from %s, line %d: %s"
-#define LOG_DEBUGX_CHILD_READ "EXCESSIVE(%s()@%s:%d): read %d bytes from child input file descriptor %d, buffer contains %d bytes, current position is %d"
+#define LOG_DEBUGX_CHILD_READ "EXCESSIVE(%s()@%s:%d): read %d bytes from child input file descriptor %d, buffer contains %d bytes, current position is %d: %.*s"
#define LOG_DEBUGX_CHILD_FD_EOF "EXCESSIVE(%s()@%s:%d): child input file descriptor %d indicates EOF, buffer contains %d bytes, current position is %d"
-#define LOG_DEBUGX_NETWORK_READ "EXCESSIVE(%s()@%s:%d): read %d bytes from network input file descriptor %d, buffer contains %d bytes, current position is %d"
+#define LOG_DEBUGX_NETWORK_READ "EXCESSIVE(%s()@%s:%d): read %d bytes from network input file descriptor %d, buffer contains %d bytes, current position is %d: %.*s"
#define LOG_DEBUGX_NETWORK_FD_EOF "EXCESSIVE(%s()@%s:%d): network input file descriptor %d indicates EOF, buffer contains %d bytes, current position is %d"
#define LOG_DEBUGX_CHILD_IN_CLOSE "EXCESSIVE(%s()@%s:%d): child input file descriptor %d closed"
#define LOG_DEBUGX_CHILD_OUT_CLOSE "EXCESSIVE(%s()@%s:%d): child output file descriptor %d closed"
@@ -1006,6 +1070,14 @@
#define LOG_DEBUGX_AUTH_CRAMMD5_CHALLENGE "EXCESSIVE(%s()@%s:%d): created CRAM-MD5 challenge text: %s"
#define LOG_DEBUGX_SOCKET_NONBLOCK "EXCESSIVE(%s()@%s:%d): setting socket to nonblocking mode: %d"
#define LOG_DEBUGX_CLEAR_INPUT "EXCESSIVE(%s()@%s:%d): discarding %d bytes of cached input"
+#define LOG_DEBUGX_CLEAR_BUFFER "EXCESSIVE(%s()@%s:%d): discarding %d bytes of buffered input"
+#define LOG_DEBUGX_RETAIN_DATA "EXCESSIVE(%s()@%s:%d): retaining %d new bytes of input, total %d bytes retained, max %d bytes allocated"
+#define LOG_DEBUGX_RELEASE_DATA "EXCESSIVE(%s()@%s:%d): sending %d bytes of buffered input: %.*s"
+#define LOG_DEBUGX_FILTER_HEADER "EXCESSIVE(%s()@%s:%d): examining reconstructed header (%d bytes): %.*s"
+#define LOG_DEBUGX_COLLAPSE_WHITESPACE "EXCESSIVE(%s()@%s:%d): collapsing whitespace from: (%d)%.*s to: (%d)%.*s"
+#define LOG_DEBUGX_REMOTE_WRITE "EXCESSIVE(%s()@%s:%d): wrote %d bytes to network file descriptor %d, buffer contained %d bytes: %.*s"
+#define LOG_DEBUGX_CHILD_WRITE_CRLF "EXCESSIVE(%s()@%s:%d): wrote %d bytes to child file descriptor %d, inserted CRLF, buffer contained %d bytes: %.*s"
+#define LOG_DEBUGX_CHILD_WRITE "EXCESSIVE(%s()@%s:%d): wrote %d bytes to child file descriptor %d, buffer contained %d bytes: %.*s"
#define ERROR_CONFIG_NO_COMMAND "ERROR: Missing qmail-smtpd command"
#define ERROR_CONFIG_UNKNOWN_OPTION "ERROR: Unknown or incomplete option: %s"
@@ -1149,7 +1221,7 @@
#define CONFIG_TEST_ERROR_GRAYLIST_TOP_EMPTY "ERROR(%s): No domain directories found in graylist directory: %s"
#define CONFIG_TEST_ERROR_GRAYLIST_TOP_DIR "ERROR(%s): Unable to read graylist directory %s: %s"
#define CONFIG_TEST_ERROR_GRAYLIST_TOP_OTHER "ERROR(%s): Found %s in graylist directory where only domain directories should be: %s"
-#define CONFIG_TEST_ERROR_GRAYLIST_TOP_ORPHAN "ERROR(%s): Found domain directory for a domain that is not in the list of local domains; the domain directory will not be used: %s"
+#define CONFIG_TEST_ERROR_GRAYLIST_TOP_ORPHAN "INFO(%s): Found domain directory for a domain that is not in the list of local domains; the domain directory will not be used: %s"
#define CONFIG_TEST_ERROR_GRAYLIST_DOMAIN_DIR "ERROR(%s): Unable to read graylist domain directory %s: %s"
#define CONFIG_TEST_ERROR_GRAYLIST_DOMAIN_OTHER "ERROR(%s): Found %s in graylist domain directory where only user directories should be: %s"
#define CONFIG_TEST_ERROR_GRAYLIST_USER_DIR "ERROR(%s): Unable to read graylist user directory %s: %s"
@@ -1242,16 +1314,16 @@
#define CONFIG_TYPE_BOOLEAN 0
/* Numeric option */
#define CONFIG_TYPE_INTEGER 1
-/* Text values */
+/* Text values ONLY - option values (like blacklist entries should use OPTION_*) */
#define CONFIG_TYPE_STRING_SINGLETON 2
#define CONFIG_TYPE_STRING_ARRAY 3
/* A single filename, can only be set once */
#define CONFIG_TYPE_FILE_SINGLETON 4
-/* A single filename that has an alternate directory option */
+/* A single filename that has an alternate directory option ("-file" vs "-dir") */
#define CONFIG_TYPE_FILE_NOT_DIR_SINGLETON 5
/* Multiple filenames, stored in an array */
#define CONFIG_TYPE_FILE_ARRAY 6
-/* Multiple filenames that have an alternate directory option */
+/* Multiple filenames that have an alternate directory option ("-file" vs "-dir") */
#define CONFIG_TYPE_FILE_NOT_DIR_ARRAY 7
/* A single directory, can only be set once */
#define CONFIG_TYPE_DIR_SINGLETON 8
@@ -1443,6 +1515,8 @@
char **graylist_exception_rdns;
char **graylist_exception_rdns_file;
char **graylist_exception_rdns_dir;
+ char **blacklist_header;
+ char **blacklist_header_file;
char **smtp_auth_command;
int smtp_auth_level;
@@ -1562,7 +1636,7 @@
int allow_relay;
char additional_domain_text[MAX_BUF + 1];
int inside_data;
- int num_rcpt_to;
+ int inside_header;
int local_sender;
int local_recipient;
@@ -1570,6 +1644,9 @@
char sender_domain[MAX_ADDRESS + 1];
char recipient_username[MAX_ADDRESS + 1];
char recipient_domain[MAX_ADDRESS + 1];
+ char **allowed_recipients;
+ int num_recipients;
+
char configuration_path[MAX_PATH + 1];
char **child_argv;
@@ -1586,6 +1663,14 @@
int tls_state;
+ char reconstructed_header[MAX_NETWORK_BUF + STRLEN(STR_CRLF) + 1];
+ int strlen_reconstructed_header;
+ char *buf_retain;
+ int strlen_buf_retain;
+ int max_buf_retain;
+ char **blacklist_header;
+ char **blacklist_header_file;
+
#ifdef HAVE_LIBSSL
SSL_CTX *tls_context;
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/tls.c
^
|
@@ -58,7 +58,14 @@
*/
int tls_password_callback(char *buf, int size, int rwflag, void *userdata)
{
- return((((struct option_set *)userdata)->strlen_tls_privatekey_password > 0) ? snprintf(buf, size, "%.*s", ((struct option_set *)userdata)->strlen_tls_privatekey_password, ((struct option_set *)userdata)->tls_privatekey_password) : 0);
+ int return_value;
+
+ return_value = 0;
+
+ if (((struct option_set *)userdata)->strlen_tls_privatekey_password > 0)
+ snprintf(buf, size, "%.*s%n", ((struct option_set *)userdata)->strlen_tls_privatekey_password, ((struct option_set *)userdata)->tls_privatekey_password, &return_value);
+
+ return(return_value);
}
char *tls_error(struct filter_settings *current_settings, int return_code)
@@ -117,9 +124,15 @@
error_text[strlen_error_text] = '\0';
if (return_code == 0)
- strlen_error_text += snprintf(error_text + strlen_error_text, MAX_BUF - strlen_error_text, ", %s", LOG_MSG_TLS_EOF_FOUND);
+ {
+ snprintf(error_text + strlen_error_text, MAX_BUF - strlen_error_text, ", %s", LOG_MSG_TLS_EOF_FOUND);
+ strlen_error_text += strlen(error_text + strlen_error_text);
+ }
else if (return_code == -1)
- strlen_error_text += snprintf(error_text + strlen_error_text, MAX_BUF - strlen_error_text, ", %s", strerror(saved_errno));
+ {
+ snprintf(error_text + strlen_error_text, MAX_BUF - strlen_error_text, ", %s", strerror(saved_errno));
+ strlen_error_text += strlen(error_text + strlen_error_text);
+ }
break;
case SSL_ERROR_SSL:
@@ -141,7 +154,10 @@
(strlen_error_text < MAX_BUF))
{
if (strlen_error_text > 0)
- strlen_error_text += snprintf(error_text + strlen_error_text, MAX_BUF - strlen_error_text, ", ");
+ {
+ snprintf(error_text + strlen_error_text, MAX_BUF - strlen_error_text, ", ");
+ strlen_error_text += strlen(error_text + strlen_error_text);
+ }
ERR_error_string_n(tls_error, error_text + strlen_error_text, MAX_BUF - strlen_error_text);
strlen_error_text += strlen(error_text + strlen_error_text);
@@ -219,7 +235,7 @@
error_occurred = 1;
}
}
-
+
if (!error_occurred &&
(current_settings->current_options->tls_privatekey_file != NULL))
{
@@ -242,7 +258,7 @@
error_occurred = 1;
}
}
-
+
if (SSL_CTX_check_private_key(*target_tls_context))
SPAMDYKE_LOG_EXCESSIVE(current_settings, LOG_DEBUGX_TLS_CERT_CHECK, NULL);
else
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/spamdyke/usage.c
^
|
@@ -98,9 +98,12 @@
(current_settings->option_list[i].value_type == CONFIG_TYPE_NAME_MULTIPLE)) &&
(current_settings->option_list[i].validity.string_list.strings[0] != NULL))
{
- strlen_values_text = snprintf(values_text, MAX_BUF, "%s", current_settings->option_list[i].validity.string_list.strings[0]);
+ snprintf(values_text, MAX_BUF, "%s%n", current_settings->option_list[i].validity.string_list.strings[0], &strlen_values_text);
for (j = 1; current_settings->option_list[i].validity.string_list.strings[j] != NULL; j++)
- strlen_values_text += snprintf(values_text + strlen_values_text, MAX_BUF - strlen_values_text, USAGE_MESSAGE_NAME_VALUE_DELIMITER "%s", current_settings->option_list[i].validity.string_list.strings[j]);
+ {
+ snprintf(values_text + strlen_values_text, MAX_BUF - strlen_values_text, USAGE_MESSAGE_NAME_VALUE_DELIMITER "%s", current_settings->option_list[i].validity.string_list.strings[j]);
+ strlen_values_text += strlen(values_text + strlen_values_text);
+ }
}
if (current_settings->option_list[i].getopt_option.val <= current_settings->max_short_code)
@@ -195,7 +198,7 @@
break;
}
}
-
+
fprintf(stderr, USAGE_MESSAGE_FOOTER_LONG);
}
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/tests/run
^
|
@@ -200,48 +200,57 @@
if [ "$0" != "./subrun" ]
then
pushd ${SPAMDYKE_DIR}
+ touch *
make distclean
./configure --enable-tls --with-excessive-output --with-debug-symbols
make
popd
pushd ../utils
+ touch *
make distclean
./configure
make
popd
pushd sendrecv
+ touch *
make clean
make
popd
pushd smtpdummy
+ touch *
make clean
make
popd
pushd addsecs
+ touch *
make clean
make
popd
pushd smtpauth
+ touch *
make clean
make
popd
pushd exitvalue
+ touch *
make clean
make
popd
pushd cputime
+ touch *
make clean
make
popd
pushd dnsdummy
+ touch *
make clean
make
popd
@@ -346,12 +355,15 @@
target=$*
fi
- rm -f ${TMPDIR}/success.txt
- rm -f ${TMPDIR}/skipped.txt
- rm -f ${TMPDIR}/failure.txt
- touch ${TMPDIR}/success.txt
- touch ${TMPDIR}/skipped.txt
- touch ${TMPDIR}/failure.txt
+ if [ "$0" != "./subrun" ]
+ then
+ rm -f ${TMPDIR}/success.txt
+ rm -f ${TMPDIR}/skipped.txt
+ rm -f ${TMPDIR}/failure.txt
+ touch ${TMPDIR}/success.txt
+ touch ${TMPDIR}/skipped.txt
+ touch ${TMPDIR}/failure.txt
+ fi
for dir in ${target}
do
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/tests/smtpdummy/smtpdummy.c
^
|
@@ -33,12 +33,25 @@
#define STDIN_FD 0
#define STDOUT_FD 1
+#define TYPE_AUTH_PLAIN 0
+#define TYPE_AUTH_LOGIN 1
+#define TYPE_AUTH_CRAM_MD5 2
+
#define GREETING_BANNER "220 smtpdummy ESMTP\r\n"
#define COMMAND_HELO "HELO"
#define RESPONSE_HELO "250 HELO received\r\n"
#define COMMAND_EHLO "EHLO"
-#define RESPONSE_EHLO_AUTH "250-AUTH LOGIN PLAIN\r\n250-AUTH=LOGIN PLAIN\r\n250-PIPELINING\r\n250 8BITMIME\r\n"
+#define RESPONSE_EHLO_AUTH "250-AUTH LOGIN PLAIN CRAM-MD5\r\n250-AUTH=LOGIN PLAIN CRAM-MD5\r\n250-PIPELINING\r\n250 8BITMIME\r\n"
#define RESPONSE_EHLO_NO_AUTH "250-X-NOTHING\r\n250-PIPELINING\r\n250 8BITMIME\r\n"
+#define COMMAND_AUTH_LOGIN "AUTH LOGIN"
+#define RESPONSE_AUTH_LOGIN_1 "334 VXNlcm5hbWU6\r\n"
+#define RESPONSE_AUTH_LOGIN_2 "334 UGFzc3dvcmQ6\r\n"
+#define COMMAND_AUTH_PLAIN "AUTH PLAIN"
+#define RESPONSE_AUTH_PLAIN "334 AUTH PLAIN received\r\n"
+#define COMMAND_AUTH_CRAM_MD5 "AUTH CRAM-MD5"
+#define RESPONSE_AUTH_CRAM_MD5 "334 AUTH-CRAM-MD5-received\r\n"
+#define RESPONSE_AUTH "235 AUTH success\r\n"
+#define RESPONSE_AUTH_REJECT "554 AUTH failure\r\n"
#define COMMAND_MAIL "MAIL"
#define RESPONSE_MAIL "250 MAIL received\r\n"
#define COMMAND_RCPT "RCPT"
@@ -50,13 +63,45 @@
#define RESPONSE_DATA "354 DATA received\r\n"
#define COMMAND_DATA_END "."
#define RESPONSE_DATA_END "250 DATA END received\r\n"
+#define RESPONSE_DATA_REJECT "554 DATA END rejected\r\n"
#define COMMAND_QUIT "QUIT"
#define RESPONSE_QUIT "221 QUIT received\r\n"
-#define RESPONSE_ERROR "554 error\r\n"
+#define RESPONSE_ERROR "554 error: %.*s\r\n"
void usage()
{
- printf("USAGE: smtpdummy [ -a ] [ -T IDLE_TIMEOUT_SECS ] [ -h HELO_DELAY_SECS ] [ -m MAIL_DELAY_SECS ] [ -r RCPT_DELAY_SECS ] [ -d DATA_DELAY_SECS ] [ -e DATA_END_DELAY_SECS ] [ -q QUIT_DELAY_SECS ]\n");
+ printf(
+ "USAGE: smtpdummy [ -aDlLR ] [ -T IDLE_TIMEOUT_SECS ] [ -h HELO_DELAY_SECS ] [ -A AUTH_DELAY_SECS ] [ -m MAIL_DELAY_SECS ] [ -r RCPT_DELAY_SECS ] [ -d DATA_DELAY_SECS ] [ -e DATA_END_DELAY_SECS ] [ -q QUIT_DELAY_SECS ] [ -o FILENAME ]\n"
+ "\n"
+ "-a\n"
+ " Advertise authentication in response to EHLO\n"
+ "-A SECS\n"
+ " Wait SECS seconds before responding to AUTH\n"
+ "-d SECS\n"
+ " Wait SECS seconds before responding to DATA\n"
+ "-D\n"
+ " Reject message content with an error\n"
+ "-e SECS\n"
+ " Wait SECS seconds before responding to the end of the message\n"
+ "-h SECS\n"
+ " Wait SECS seconds before responding to HELO\n"
+ "-l\n"
+ " Process authentication and return success\n"
+ "-L\n"
+ " Process authentication and return failure\n"
+ "-m SECS\n"
+ " Wait SECS seconds before responding to MAIL\n"
+ "-o FILENAME\n"
+ " Save message content into FILENAME\n"
+ "-q SECS\n"
+ " Wait SECS seconds before responding to QUIT\n"
+ "-r SECS\n"
+ " Wait SECS seconds before responding to RCPT\n"
+ "-R\n"
+ " Reject all recipients with an error\n"
+ "-T SECS\n"
+ " Quit after SECS seconds of inactivity (default: no timeout)\n"
+ );
exit(0);
}
@@ -75,6 +120,7 @@
int tmp_int;
int idle_timeout_secs;
int delay_helo;
+ int delay_auth;
int delay_mail;
int delay_rcpt;
int delay_data;
@@ -86,10 +132,17 @@
fd_set read_fdset;
int ehlo_auth;
int reject_all;
+ int reject_message;
+ int auth_success;
+ int auth_step;
+ int auth_type;
+ char tmp_format[MAX_BUF + 1];
+ int strlen_tmp_format;
return_value = 0;
idle_timeout_secs = 0;
delay_helo = 0;
+ delay_auth = 0;
delay_mail = 0;
delay_rcpt = 0;
delay_data = 0;
@@ -99,20 +152,33 @@
output_file = NULL;
ehlo_auth = 0;
reject_all = 0;
+ reject_message = 0;
+ auth_success = 0;
+ auth_step = 0;
+ auth_type = 0;
- while ((opt = getopt(argc, argv, "ad:e:h:m:o:q:r:RT:")) != -1)
+ while ((opt = getopt(argc, argv, "aA:d:De:h:lLm:o:q:r:RT:")) != -1)
{
switch (opt)
{
case 'a':
ehlo_auth = 1;
break;
+ case 'A':
+ if ((sscanf(optarg, "%d", &tmp_int) == 1) &&
+ (tmp_int >= 0))
+ delay_auth = tmp_int;
+
+ break;
case 'd':
if ((sscanf(optarg, "%d", &tmp_int) == 1) &&
(tmp_int >= 0))
delay_data = tmp_int;
break;
+ case 'D':
+ reject_message = 1;
+ break;
case 'e':
if ((sscanf(optarg, "%d", &tmp_int) == 1) &&
(tmp_int >= 0))
@@ -125,6 +191,12 @@
delay_helo = tmp_int;
break;
+ case 'l':
+ auth_success = 1;
+ break;
+ case 'L':
+ auth_success = 0;
+ break;
case 'm':
if ((sscanf(optarg, "%d", &tmp_int) == 1) &&
(tmp_int >= 0))
@@ -202,7 +274,7 @@
{
if (next_terminator != NULL)
{
- strlen_trim = strlen_buf - 1;
+ strlen_trim = next_terminator - start_buf;
if ((strlen_buf > 1) &&
(next_terminator[-1] == '\r'))
strlen_trim--;
@@ -214,10 +286,46 @@
if (!inside_data)
{
- if (((strlen_trim == STRLEN(COMMAND_HELO)) ||
- ((strlen_trim > STRLEN(COMMAND_HELO)) &&
- isspace(start_buf[STRLEN(COMMAND_HELO)]))) &&
- (strncasecmp(start_buf, COMMAND_HELO, STRLEN(COMMAND_HELO)) == 0))
+ if (auth_step > 0)
+ switch (auth_type)
+ {
+ case TYPE_AUTH_LOGIN:
+ if (auth_step == 1)
+ {
+ sleep(delay_auth);
+ write(STDOUT_FD, RESPONSE_AUTH_LOGIN_2, STRLEN(RESPONSE_AUTH_LOGIN_2));
+ auth_step = 2;
+ }
+ else if (auth_step == 2)
+ {
+ sleep(delay_auth);
+
+ if (auth_success)
+ write(STDOUT_FD, RESPONSE_AUTH, STRLEN(RESPONSE_AUTH));
+ else
+ write(STDOUT_FD, RESPONSE_AUTH_REJECT, STRLEN(RESPONSE_AUTH_REJECT));
+
+ auth_step = 0;
+ }
+
+ break;
+ case TYPE_AUTH_PLAIN:
+ case TYPE_AUTH_CRAM_MD5:
+ sleep(delay_auth);
+
+ if (auth_success)
+ write(STDOUT_FD, RESPONSE_AUTH, STRLEN(RESPONSE_AUTH));
+ else
+ write(STDOUT_FD, RESPONSE_AUTH_REJECT, STRLEN(RESPONSE_AUTH_REJECT));
+
+ auth_step = 0;
+
+ break;
+ }
+ else if (((strlen_trim == STRLEN(COMMAND_HELO)) ||
+ ((strlen_trim > STRLEN(COMMAND_HELO)) &&
+ isspace(start_buf[STRLEN(COMMAND_HELO)]))) &&
+ (strncasecmp(start_buf, COMMAND_HELO, STRLEN(COMMAND_HELO)) == 0))
{
sleep(delay_helo);
write(STDOUT_FD, RESPONSE_HELO, STRLEN(RESPONSE_HELO));
@@ -234,6 +342,36 @@
else
write(STDOUT_FD, RESPONSE_EHLO_NO_AUTH, STRLEN(RESPONSE_EHLO_NO_AUTH));
}
+ else if (((strlen_trim == STRLEN(COMMAND_AUTH_LOGIN)) ||
+ ((strlen_trim > STRLEN(COMMAND_AUTH_LOGIN)) &&
+ isspace(start_buf[STRLEN(COMMAND_AUTH_LOGIN)]))) &&
+ (strncasecmp(start_buf, COMMAND_AUTH_LOGIN, STRLEN(COMMAND_AUTH_LOGIN)) == 0))
+ {
+ sleep(delay_auth);
+ write(STDOUT_FD, RESPONSE_AUTH_LOGIN_1, STRLEN(RESPONSE_AUTH_LOGIN_1));
+ auth_type = TYPE_AUTH_LOGIN;
+ auth_step = 1;
+ }
+ else if (((strlen_trim == STRLEN(COMMAND_AUTH_PLAIN)) ||
+ ((strlen_trim > STRLEN(COMMAND_AUTH_PLAIN)) &&
+ isspace(start_buf[STRLEN(COMMAND_AUTH_PLAIN)]))) &&
+ (strncasecmp(start_buf, COMMAND_AUTH_PLAIN, STRLEN(COMMAND_AUTH_PLAIN)) == 0))
+ {
+ sleep(delay_auth);
+ write(STDOUT_FD, RESPONSE_AUTH_PLAIN, STRLEN(RESPONSE_AUTH_PLAIN));
+ auth_type = TYPE_AUTH_PLAIN;
+ auth_step = 1;
+ }
+ else if (((strlen_trim == STRLEN(COMMAND_AUTH_CRAM_MD5)) ||
+ ((strlen_trim > STRLEN(COMMAND_AUTH_CRAM_MD5)) &&
+ isspace(start_buf[STRLEN(COMMAND_AUTH_CRAM_MD5)]))) &&
+ (strncasecmp(start_buf, COMMAND_AUTH_CRAM_MD5, STRLEN(COMMAND_AUTH_CRAM_MD5)) == 0))
+ {
+ sleep(delay_auth);
+ write(STDOUT_FD, RESPONSE_AUTH_CRAM_MD5, STRLEN(RESPONSE_AUTH_CRAM_MD5));
+ auth_type = TYPE_AUTH_CRAM_MD5;
+ auth_step = 1;
+ }
else if (((strlen_trim == STRLEN(COMMAND_MAIL)) ||
((strlen_trim > STRLEN(COMMAND_MAIL)) &&
isspace(start_buf[STRLEN(COMMAND_MAIL)]))) &&
@@ -280,18 +418,29 @@
continue_looping = 0;
}
else
- write(STDOUT_FD, RESPONSE_ERROR, STRLEN(RESPONSE_ERROR));
+ {
+ snprintf(tmp_format, MAX_BUF, RESPONSE_ERROR "%n", strlen_trim, start_buf, &strlen_tmp_format);
+ write(STDOUT_FD, tmp_format, strlen_tmp_format);
+ }
}
else
if ((strlen_trim == STRLEN(COMMAND_DATA_END)) &&
(strncasecmp(start_buf, COMMAND_DATA_END, STRLEN(COMMAND_DATA_END)) == 0))
{
sleep(delay_data_end);
- write(STDOUT_FD, RESPONSE_DATA_END, STRLEN(RESPONSE_DATA_END));
+
+ if (!reject_message)
+ write(STDOUT_FD, RESPONSE_DATA_END, STRLEN(RESPONSE_DATA_END));
+ else
+ write(STDOUT_FD, RESPONSE_DATA_REJECT, STRLEN(RESPONSE_DATA_REJECT));
+
inside_data = 0;
}
else if (output_file != NULL)
+ {
fprintf(output_file, "%.*s", (int)(next_terminator - start_buf), start_buf);
+ fflush(NULL);
+ }
strlen_buf -= next_terminator - start_buf;
start_buf = next_terminator;
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/tests/test-log_032-encryption_tls/input.txt
^
|
@@ -2,4 +2,10 @@
starttls
mail from:<FROM_ADDRESS>
rcpt to:<TARGET_EMAIL>
+data
+Subject: TEST_NUM
+Date: today
+
+FOO!
+.
quit
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/tests/test-log_034-encryption_ssl/input.txt
^
|
@@ -1,4 +1,10 @@
helo me
mail from:<FROM_ADDRESS>
rcpt to:<TARGET_EMAIL>
+data
+Subject: TEST_NUM
+Date: today
+
+FOO!
+.
quit
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/tests/test-log_035-encryption_none/input.txt
^
|
@@ -1,4 +1,10 @@
helo me
mail from:<FROM_ADDRESS>
rcpt to:<TARGET_EMAIL>
+data
+Subject: TEST_NUM
+Date: today
+
+FOO!
+.
quit
|
[-]
[+]
|
Added |
spamdyke-4.3.1.tar.bz2/tests/test-protocol_014-allowed_reason
^
|
+(directory)
|
[-]
[+]
|
Added |
spamdyke-4.3.1.tar.bz2/tests/test-protocol_014-allowed_reason/input.txt
^
|
@@ -0,0 +1,10 @@
+helo me
+mail from:<FROM_ADDRESS>
+rcpt to:<TARGET_EMAIL>
+data
+To: <TARGET_EMAIL>
+Subject: Test-TEST_NUM
+
+FOO!
+.
+quit
|
[-]
[+]
|
Added |
spamdyke-4.3.1.tar.bz2/tests/test-protocol_014-allowed_reason/run.sh
^
|
@@ -0,0 +1,30 @@
+# This test delivers a small test message and looks for the correct qmail status
+# code and reason code.
+
+export TCPREMOTEIP=${TESTSD_MISSING_RDNS_IP}
+
+FROM_ADDRESS=test-${TEST_NUM}.${RANDOM}.${RANDOM}@example.com
+
+cat input.txt | sed -e "s/TEST_NUM/${TEST_NUM}/g" -e "s/TARGET_EMAIL/$1/g" -e "s/FROM_ADDRESS/${FROM_ADDRESS}/g" > ${TMPDIR}/${TEST_NUM}-input.txt
+echo "${SENDRECV_PATH} -t 30 -r 221 -- ${SPAMDYKE_PATH} -linfo --log-target stderr ${QMAIL_CMDLINE} < ${TMPDIR}/${TEST_NUM}-input.txt > ${TMPDIR}/${TEST_NUM}-output.txt 2>&1"
+${SENDRECV_PATH} -t 30 -r 221 -- ${SPAMDYKE_PATH} -linfo --log-target stderr ${QMAIL_CMDLINE} < ${TMPDIR}/${TEST_NUM}-input.txt > ${TMPDIR}/${TEST_NUM}-output.txt 2>&1
+
+output=`grep -E "250 ok [0-9]* qp [0-9]*" ${TMPDIR}/${TEST_NUM}-output.txt`
+if [ ! -z "${output}" ]
+then
+ output=`grep -E "reason: 250_ok_[0-9]*_qp_[0-9]*" ${TMPDIR}/${TEST_NUM}-output.txt | grep ALLOWED`
+ if [ ! -z "${output}" ]
+ then
+ outcome="success"
+ else
+ echo OUTPUT IN tmp/${TEST_NUM}-output.txt:
+ cat ${TMPDIR}/${TEST_NUM}-output.txt
+
+ outcome="failure"
+ fi
+else
+ echo OUTPUT IN tmp/${TEST_NUM}-output.txt:
+ cat ${TMPDIR}/${TEST_NUM}-output.txt
+
+ outcome="failure"
+fi
|
[-]
[+]
|
Added |
spamdyke-4.3.1.tar.bz2/tests/test-protocol_015-content_denied_reason
^
|
+(directory)
|
[-]
[+]
|
Added |
spamdyke-4.3.1.tar.bz2/tests/test-protocol_015-content_denied_reason/input.txt
^
|
@@ -0,0 +1,10 @@
+helo me
+mail from:<FROM_ADDRESS>
+rcpt to:<TARGET_EMAIL>
+data
+To: <TARGET_EMAIL>
+Subject: Test-TEST_NUM
+
+FOO!
+.
+quit
|
[-]
[+]
|
Added |
spamdyke-4.3.1.tar.bz2/tests/test-protocol_015-content_denied_reason/run.sh
^
|
@@ -0,0 +1,31 @@
+# This test delivers a small test message and looks for a rejection message
+# after the message data is sent. The rejection message should be logged
+# in the reason.
+
+export TCPREMOTEIP=${TESTSD_MISSING_RDNS_IP}
+
+FROM_ADDRESS=test-${TEST_NUM}.${RANDOM}.${RANDOM}@example.com
+
+cat input.txt | sed -e "s/TEST_NUM/${TEST_NUM}/g" -e "s/TARGET_EMAIL/$1/g" -e "s/FROM_ADDRESS/${FROM_ADDRESS}/g" > ${TMPDIR}/${TEST_NUM}-input.txt
+echo "${SENDRECV_PATH} -t 30 -r 221 -- ${SPAMDYKE_PATH} -linfo --log-target stderr ${SMTPDUMMY_PATH} -D < ${TMPDIR}/${TEST_NUM}-input.txt > ${TMPDIR}/${TEST_NUM}-output.txt 2>&1"
+${SENDRECV_PATH} -t 30 -r 221 -- ${SPAMDYKE_PATH} -linfo --log-target stderr ${SMTPDUMMY_PATH} -D < ${TMPDIR}/${TEST_NUM}-input.txt > ${TMPDIR}/${TEST_NUM}-output.txt 2>&1
+
+output=`grep "554 DATA END rejected" ${TMPDIR}/${TEST_NUM}-output.txt`
+if [ ! -z "${output}" ]
+then
+ output=`grep "reason: 554_DATA_END_rejected" ${TMPDIR}/${TEST_NUM}-output.txt | grep DENIED_OTHER`
+ if [ ! -z "${output}" ]
+ then
+ outcome="success"
+ else
+ echo OUTPUT IN tmp/${TEST_NUM}-output.txt:
+ cat ${TMPDIR}/${TEST_NUM}-output.txt
+
+ outcome="failure"
+ fi
+else
+ echo OUTPUT IN tmp/${TEST_NUM}-output.txt:
+ cat ${TMPDIR}/${TEST_NUM}-output.txt
+
+ outcome="failure"
+fi
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/tests/test-regression_040-tcpremoteip_name/input.txt
^
|
@@ -1,4 +1,9 @@
helo me
mail from:<FROM_ADDRESS>
rcpt to:<TARGET_EMAIL>
+data
+Subject: TEST_NUM
+
+FOO!
+.
quit
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/tests/test-regression_040-tcpremoteip_name/run.sh
^
|
@@ -6,7 +6,7 @@
FROM_ADDRESS=test-${TEST_NUM}.${RANDOM}.${RANDOM}@example.com
-cat input.txt | sed -e "s/TARGET_EMAIL/$1/g" -e "s/FROM_ADDRESS/${FROM_ADDRESS}/g" > ${TMPDIR}/${TEST_NUM}-input.txt
+cat input.txt | sed -e "s/TEST_NUM/${TEST_NUM}/g" -e "s/TARGET_EMAIL/$1/g" -e "s/FROM_ADDRESS/${FROM_ADDRESS}/g" > ${TMPDIR}/${TEST_NUM}-input.txt
echo "${SENDRECV_PATH} -t 30 -r 554 -- ${SPAMDYKE_PATH} --ip-blacklist-entry ${TESTSD_RDNS_IP} ${QMAIL_CMDLINE} < ${TMPDIR}/${TEST_NUM}-input.txt > ${TMPDIR}/${TEST_NUM}-output.txt"
${SENDRECV_PATH} -t 30 -r 554 -- ${SPAMDYKE_PATH} --ip-blacklist-entry ${TESTSD_RDNS_IP} ${QMAIL_CMDLINE} < ${TMPDIR}/${TEST_NUM}-input.txt > ${TMPDIR}/${TEST_NUM}-output.txt
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/tests/test-regression_044-symbol_address_start/input.txt
^
|
@@ -1,4 +1,10 @@
helo me
mail from:<FROM_ADDRESS>
rcpt to:<TARGET_EMAIL>
+data
+Subject: TEST_NUM
+Date: today
+
+FOO!
+.
quit
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/tests/test-regression_063-recipient_whitelist_allows_only_one_2/input.txt
^
|
@@ -2,4 +2,10 @@
mail from:<FROM_ADDRESS>
rcpt to:<TARGET_EMAIL1>
rcpt to:<TARGET_EMAIL2>
+data
+To: <TARGET_EMAIL1>
+Subject: Test-TEST_NUM
+
+FOO!
+.
quit
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/tests/test-regression_063-recipient_whitelist_allows_only_one_2/run.sh
^
|
@@ -11,10 +11,8 @@
echo $1 > ${TMPDIR}/${TEST_NUM}-recipient_whitelist.txt
-mkdir -p ${TMPDIR}/${TEST_NUM}-graylist.d/example.com
-
cat input.txt | sed -e "s/TEST_NUM/${TEST_NUM}/g" -e "s/TARGET_EMAIL1/$1/g" -e "s/TARGET_EMAIL2/${TO_ADDRESS}/g" -e "s/FROM_ADDRESS/${FROM_ADDRESS}/g" > ${TMPDIR}/${TEST_NUM}-input.txt
-echo "${SENDRECV_PATH} -t 30 -r 221 -- ${SPAMDYKE_PATH} -linfo --log-target stderr --recipient-whitelist-file -r --local-domains-entry ${RANDOM}.net ${QMAIL_CMDLINE} < ${TMPDIR}/${TEST_NUM}-input.txt > ${TMPDIR}/${TEST_NUM}-output.txt 2>&1"
+echo "${SENDRECV_PATH} -t 30 -r 221 -- ${SPAMDYKE_PATH} -linfo --log-target stderr --recipient-whitelist-file ${TMPDIR}/${TEST_NUM}-recipient_whitelist.txt -r --local-domains-entry ${RANDOM}.net ${QMAIL_CMDLINE} < ${TMPDIR}/${TEST_NUM}-input.txt > ${TMPDIR}/${TEST_NUM}-output.txt 2>&1"
${SENDRECV_PATH} -t 30 -r 221 -- ${SPAMDYKE_PATH} -linfo --log-target stderr --recipient-whitelist-file ${TMPDIR}/${TEST_NUM}-recipient_whitelist.txt -r --local-domains-entry ${RANDOM}.net ${QMAIL_CMDLINE} < ${TMPDIR}/${TEST_NUM}-input.txt > ${TMPDIR}/${TEST_NUM}-output.txt 2>&1
output=`grep -i "ALLOWED from: ${FROM_ADDRESS} to: $1" ${TMPDIR}/${TEST_NUM}-output.txt`
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/utils/configure
^
|
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.61 for spamdyke 4.2.1.
+# Generated by GNU Autoconf 2.61 for spamdyke 4.3.1.
#
# Report bugs to <samc (at) silence (dot) org>.
#
@@ -574,8 +574,8 @@
# Identity of this package.
PACKAGE_NAME='spamdyke'
PACKAGE_TARNAME='-spamdyke-'
-PACKAGE_VERSION='4.2.1'
-PACKAGE_STRING='spamdyke 4.2.1'
+PACKAGE_VERSION='4.3.1'
+PACKAGE_STRING='spamdyke 4.3.1'
PACKAGE_BUGREPORT='samc (at) silence (dot) org'
ac_unique_file="dnsa.c"
@@ -1177,7 +1177,7 @@
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures spamdyke 4.2.1 to adapt to many kinds of systems.
+\`configure' configures spamdyke 4.3.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1238,7 +1238,7 @@
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of spamdyke 4.2.1:";;
+ short | recursive ) echo "Configuration of spamdyke 4.3.1:";;
esac
cat <<\_ACEOF
@@ -1321,7 +1321,7 @@
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-spamdyke configure 4.2.1
+spamdyke configure 4.3.1
generated by GNU Autoconf 2.61
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -1335,7 +1335,7 @@
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by spamdyke $as_me 4.2.1, which was
+It was created by spamdyke $as_me 4.3.1, which was
generated by GNU Autoconf 2.61. Invocation command line was
$ $0 $@
@@ -4361,7 +4361,7 @@
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by spamdyke $as_me 4.2.1, which was
+This file was extended by spamdyke $as_me 4.3.1, which was
generated by GNU Autoconf 2.61. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -4410,7 +4410,7 @@
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-spamdyke config.status 4.2.1
+spamdyke config.status 4.3.1
configured by $0, generated by GNU Autoconf 2.61,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
[-]
[+]
|
Changed |
spamdyke-4.3.1.tar.bz2/utils/configure.ac
^
|
@@ -17,7 +17,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
AC_PREREQ(2.59)
-AC_INIT([[spamdyke]], [[4.2.1]], [[samc (at) silence (dot) org]])
+AC_INIT([[spamdyke]], [[4.3.1]], [[samc (at) silence (dot) org]])
AC_CONFIG_SRCDIR([dnsa.c])
AC_CONFIG_HEADER([config.h])
|