1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-27 11:55:06 +00:00

Merge commit '850ef5ae11d69ea3381bd310f564f025fc8caea3'

Merge vendor sendmail 8.18.1 into HEAD
This commit is contained in:
Gregory Neil Shapiro 2024-01-31 23:53:48 +00:00
commit d39bd2c138
115 changed files with 6704 additions and 2167 deletions

View File

@ -25,7 +25,7 @@ This list is not guaranteed to be complete.
For Linux the default is to use fcntl() for file locking. However,
this does not work with Berkeley DB 5.x and probably later.
Switching to flock(), i.e., compile with -DHASFLOCK fixes this
(however, the have been problems with flock() on some Linux
(however, there have been problems with flock() on some Linux
versions). Alternatively, use CDB or an earlier BDB version.
* Delivery to programs that generate too much output may cause problems
@ -105,11 +105,6 @@ Kresolve sequence dnsmx canon
DSN does not contain the illegal address, but only the valid
address(es).
* \231 considered harmful.
Header addresses that have the \231 character (and possibly others
in the range \201 - \237) behave in odd and usually unexpected ways.
* AuthRealm for Cyrus SASL may not work as expected. The man page
and the actual usage for sasl_server_new() seem to differ.
Feedback for the "correct" usage is welcome, a patch to match
@ -178,11 +173,11 @@ Kresolve sequence dnsmx canon
* Client ignores SIZE parameter.
When sendmail acts as client and the server specifies a limit
for the mail size, sendmail will ignore this and try to send the
mail anyway. The server will usually reject the MAIL command
which specifies the size of the message and hence this problem
is not significant.
When sendmail acts as client and the server specifies a limit for
the mail size, sendmail will ignore this and try to send the mail
anyway (unless _FFR_CLIENT_SIZE is used). The server will usually
reject the MAIL command which specifies the size of the message
and hence this problem is not significant.
* Paths to programs being executed and the mode of program files are
not checked. Essentially, the RunProgramInUnsafeDirPath and

View File

@ -187,6 +187,625 @@ mk6wxhyuojEHuR7it6IU5BP8vaAGrL1jb1c2EeAe+pdJwpAb1Aq6MU6uWqOGup8t
=xY3m
-----END PGP PUBLIC KEY BLOCK-----
pub rsa4096/0xC4065A87C71F6844 2024-01-02 [SC]
Key fingerprint = 8AB0 63D7 A4C5 939D A9C0 1E38 C406 5A87 C71F 6844
uid [ultimate] Sendmail Signing Key/2024 <sendmail@Sendmail.ORG>
sub rsa4096/0x8DBCFBC42AF9E161 2024-01-02 [E]
Key fingerprint = 2B52 755B 17D4 44EB EC39 5497 8DBC FBC4 2AF9 E161
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
=2S83
-----END PGP PUBLIC KEY BLOCK-----
pub rsa4096/0xCFF9F96740ED9550 2023-01-12 [SC]
Key fingerprint = 8186 4A03 75F2 7810 64FE 8E4D CFF9 F967 40ED 9550
uid [ full ] Sendmail Signing Key/2023 <sendmail@Sendmail.ORG>
sub rsa4096/0x592DCD45F765BAB2 2023-01-12 [E]
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
kYi0
=c0eH
-----END PGP PUBLIC KEY BLOCK-----
pub 4096R/81D9210A 2022-01-22
Key fingerprint = 6327 DDCB 5E7E 80E4 987E A3B7 FD79 DC0C 81D9 210A
uid Sendmail Signing Key/2022 <sendmail@Sendmail.ORG>
sub 4096R/03142938 2022-01-22
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
0Kb4rGd12E5b+czXoxg=
=LSBA
-----END PGP PUBLIC KEY BLOCK-----
pub 4096R/4BEE1BEE 2021-01-24
Key fingerprint = F4CE 2263 2102 53D6 A9F9 79B0 4C66 EA8D 4BEE 1BEE
@ -363,7 +982,6 @@ ra/bqVWSpZTlHZ0xT9seCUSs1urxGw9Z
=3HCo
-----END PGP PUBLIC KEY BLOCK-----
pub rsa4096/0xD583210EF51471A7 2020-04-08 [SC]
Key fingerprint = ADFD B709 FE1E A682 E585 5971 D583 210E F514 71A7
uid [ full ] Sendmail Signing Key/2020 <sendmail@Sendmail.ORG>
@ -557,7 +1175,6 @@ gmOJ78JKVfONBpmdVsw/emTMU5I/C/8m9l0nO0P4Q6diao23krgWk73x7dBoBqDn
=jgHV
-----END PGP PUBLIC KEY BLOCK-----
pub rsa4096/0x09E01FA03C0C504E 2019-01-09 [SC]
Key fingerprint = 50A3 0309 8EA2 DD7B CBEE 2ADA 09E0 1FA0 3C0C 504E
uid Sendmail Signing Key/2019 <sendmail@Sendmail.ORG>
@ -739,7 +1356,6 @@ HcRQfq7rqZkS3NE+iD9D/lUyXVYfH9A=
=jN/3
-----END PGP PUBLIC KEY BLOCK-----
pub 4096R/0xF06059FD5DC7CC3F 2018-04-24 [SC]
Key fingerprint = A687 3D24 A4D6 D628 4AE4 2A75 F060 59FD 5DC7 CC3F
uid Sendmail Signing Key/2018 <sendmail@Sendmail.ORG>
@ -883,7 +1499,6 @@ fvZ+LS/6hJ9C77uOaBqoDPmtpn0WDqc3oDeT81Ans73BZhwhFAjzpHp+XnJQ
=K0Kz
-----END PGP PUBLIC KEY BLOCK-----
pub 4096R/6BF726AD 2016-12-31
Key fingerprint = 3C8A 1E8E 7F44 CADE 114F ED46 4BC9 BDA6 6BF7 26AD
uid Sendmail Signing Key/2017 <sendmail@Sendmail.ORG>
@ -1069,7 +1684,6 @@ FtJxkIHVIx/VvvBqS3HEm8QCRvr+o10/Ue7NljolDV13B7fljxgvLFyJ8T91jWsz
=Lt+h
-----END PGP PUBLIC KEY BLOCK-----
pub 2048R/29FB03DE 2016-01-04
fingerprint: 0F5C 96AE C8E6 9E9C 8E54 2E5C 6D4C D194 29FB 03DE
uid Sendmail Signing Key/2016 <sendmail@Sendmail.ORG>
@ -1269,7 +1883,6 @@ j68I
=MdUt
-----END PGP PUBLIC KEY BLOCK-----
pub 2048R/0xAAF5B5DE05BDCC53 2015-01-02
fingerprint: 30BC A747 05FA 4154 5573 1D7B AAF5 B5DE 05BD CC53
uid Sendmail Signing Key/2015 <sendmail@Sendmail.ORG>

View File

@ -4,11 +4,12 @@
This directory has the latest sendmail(TM) software from Proofpoint, Inc.
Report any bugs to sendmail-bugs-YYYY@support.sendmail.org
where YYYY is the current year, e.g., 2005.
where YYYY is the current year, e.g., 2023.
There is a web site at http://www.sendmail.org/ -- see that site for
There is a web site at https://www.sendmail.org/ -- see that site for
the latest updates.
+--------------+
| INTRODUCTION |
+--------------+
@ -40,6 +41,7 @@ the latest updates.
Sendmail is a trademark of Proofpoint, Inc.
US Patent Numbers 6865671, 6986037.
+-----------------------+
| DIRECTORY PERMISSIONS |
+-----------------------+
@ -197,14 +199,6 @@ There are other files you should read. Rooted in this directory are:
This sets a word in a smaller pointsize.
- with new groff versions (1.18 seems affected)
GROFF_NO_SGR=1
needs to be set, e.g., in doc/op/Makefile:
ROFF_CMD= GROFF_NO_SGR=1 groff
+--------------+
| RELATED RFCS |
@ -248,6 +242,13 @@ Important RFCs for electronic mail are:
RFC2822 Internet Message Format
RFC2852 Deliver By SMTP Service Extension
RFC2920 SMTP Service Extension for Command Pipelining
RFC5321 Simple Mail Transfer Protocol
RFC5322 Internet Message Format
RFC6530 Overview and Framework for Internationalized Email
RFC6531 SMTP Extension for Internationalized Email
RFC6532 Internationalized Email Headers
RFC6533 Internationalized Delivery Status and Disposition Notifications
RFC8461 SMTP MTA Strict Transport Security (MTA-STS)
Other standards that may be of interest (but which are less directly
relevant to sendmail) are:
@ -325,6 +326,10 @@ DB 2.X and 3.X. If you are upgrading from one of those versions, you must
recreate your database file(s). Do this by rebuilding all maps with
makemap and rebuilding the alias file with newaliases.
File locking using fcntl() does not interoperate with Berkeley DB
5.x (and probably later). Use CDB, flock() (-DHASFLOCK), or an
earlier Berkeley DB version.
+--------------------+
| HOST NAME SERVICES |
@ -391,6 +396,7 @@ CommuniGate Pro
in .mc file if you have compiled sendmail with Cyrus SASL
and you communicate with CommuniGate Pro servers.
+---------------------+
| DIRECTORY STRUCTURE |
+---------------------+

View File

@ -5,6 +5,187 @@ This listing shows the version of the sendmail binary, the version
of the sendmail configuration files, the date of release, and a
summary of the changes in that release.
8.18.1/8.18.1 2024/01/31
sendmail is now stricter in following the RFCs and rejects
some invalid input with respect to line endings
and pipelining:
- Prevent transaction stuffing by ensuring SMTP clients
wait for the HELO/EHLO and DATA response before sending
further SMTP commands. This can be disabled using
the new srv_features option 'F'. Issue reported by
Yepeng Pan and Christian Rossow from CISPA Helmholtz
Center for Information Security.
- Accept only CRLF . CRLF as end of an SMTP message
as required by the RFCs, which can disabled by the
new srv_features option 'O'.
- Do not accept a CR or LF except in the combination
CRLF (as required by the RFCs). These checks can
be disabled by the new srv_features options
'U' and 'G', respectively. In this case it is
suggested to use 'u2' and 'g2' instead so the server
replaces offending bare CR or bare LF with a space.
It is recommended to only turn these protections off
for trusted networks due to the potential for abuse.
Full DANE support is available if OpenSSL versions 1.1.1 or 3.x
are used, i.e., TLSA RR 2-x-y and 3-x-y are supported
as required by RFC 7672.
OpenSSL version 3.0.x is supported. Note: OpenSSL 3 loads by
default an openssl.cnf file from a location specified
in the library which may cause unwanted behaviour
in sendmail. Hence sendmail sets the environment
variable OPENSSL_CONF to /etc/mail/sendmail.ossl
to override the default. The file name can be
changed by defining confOPENSSL_CNF in the mc file;
using an empty value prevents setting OPENSSL_CONF.
Note: referring to a file which does not exist does
not cause an an error.
Two new values have been added for {verify}:
"DANE_TEMP": DANE verification failed temporarily.
"DANE_NOTLS": DANE was required but STARTTLS was not
offered by the server.
The default rules return a temporary error for these
cases, so delivery is not attempted.
If the TLS setup code in the client fails and DANE requirements
exist then {verify} will be set to "DANE_TEMP" thus
preventing delivery by default.
DANE related logging has been slightly changed for clarification:
"DANE configured in DNS but no STARTTLS available"
changed to
"DANE configured in DNS but STARTTLS not offered"
When the compile time option USE_EAI is enabled, vacation could
fail to respond when it should (the code change in
8.17.2 was incomplete). Problem reported by Alex
Hautequest.
If SMTPUTF8 BODY=7BIT are used as parameters for the MAIL command
the parsing of UTF8 addresses could fail (USE_EAI).
If a reply to a previous RCPT was received while sending
another RCPT in pipelining mode then parts of the
reply could have been assigned to the wrong RCPT.
New DontBlameSendmail option CertOwner to relax requirement
for certificate public and private key ownership.
Based on suggestion from Marius Strobl of the
FreeBSD project.
clt_features was not checked for connections via Unix domain
sockets.
CONFIG: FEATURE(`enhdnsbl') did not handle multiple replies
from DNS lookups thus potentially causing random
"false negatives".
Note: the fix creates an incompatibility:
the arguments must not have a trailing dot anymore
because the -a. option has been removed (as it only
applies to the entire result, not individual values).
CONFIG: New FEATURE(`fips3') for basic FIPS support in OpenSSL 3.
VACATION: Add support for Return-Path header to set sender
to match OpenBSD and NetBSD functionality.
VACATION: Honor RFC3834 and avoid an auto-reply if
'Auto-Submitted: no' is found in the headers to
match OpenBSD and NetBSD functionality.
VACATION: Avoid an auto-reply if a 'List-Id:' is found in
the headers to match OpenBSD functionality.
VACATION: Add support for $SUBJECT in .vacation.msg which
is replaced with the first line of the subject of the
original message to match OpenBSD and NetBSD
functionality.
Portability:
Add support for Darwin 23.
New Files:
cf/feature/fips3.m4
devtools/OS/Darwin.23.x
8.17.2/8.17.2 2023/06/03
Make sure DANE checks (if enabled) are performed even if
CACertPath or CACertFile are not set or unusable.
Note: if the code to set up TLS in the client fails, then
{verify} will be set to TEMP but DANE requirements
will be ignored, i.e., by default mail will be sent
without STARTTLS. This can be changed via a
LOCAL_TLS_SERVER ruleset.
Pass server name to clt_features ruleset instead of client
name to account for limitations in macro availability
described below in CONFIG section. This may break
custom clt_features rulesets which expect to receive
the client name as input.
Fix a regression introduced in 8.17.1: aliases file which
contain continuation lines caused parsing errors.
Add an FFR (for future release) compile time option _FFR_LOG_STAGE
to log the protocol stage as stage= for some errors during
delivery attempts to make troubleshooting simpler. This
new logging may be enabled in a future release.
When EAI is enabled, milters also got the arguments of MAIL/RCPT
commands in argv[0] for xxfi_envfrom()/xxfi_envrcpt()
callbacks instead of just the mail address.
Problem reported by Dilyan Palauzo.
When EAI is enabled, mailq prints UTF-8 addresses as such
if SMTPUTF8 was used.
When EAI is enabled, the $h macro is now in the correct format.
Previously this could cause wrong values for relay=
in log entries and the mailer argument vector.
When the compile time option USE_EAI is enabled, vacation could
fail to respond when it should. Problem reported by
Alex Hautequest.
When EAI was enabled, header truncation might not have been
logged even when it happened. Problem reported by
Werner Wiethege.
Handle a possible change in an upcoming release of Cyrus-SASL
(2.1.28) by changing the definition of an internal flag.
Patch from Dilyan Palauzo.
Avoid an assertion failure when an smtps connection is made
to the server and a milter is unavailable.
Problem reported by Dilyan Palauzo.
Fixed some spelling errors in documentation and comments,
based on a codespell report by Jens Schleusener
of fossies.org.
The result of try_tls is now logged using status= instead
of reject=.
If tls_rcpt rejected the delivery of a recipient then a bogus
dsn= entry might have been logged under some circumstances.
If a server replied with 421 to a RCPT command then a bogus reply=
might have been logged.
When quoting the value for ${currHeader} avoid causing a syntax
error (Unbalanced '"') when truncating a header value
which is too long. Problem reported by Werner Wiethege.
Reduce the performance impact of a change introduced in
8.12.9: the default for MaxMimeHeaderLength was
set to 2048/1024. Problem reported by Tabata
Shintaro of Internet Initiative Japan Inc.
CONFIG: The default clt_features ruleset tried to access
${server_name} and ${server_addr} which are not set
when the ruleset is invoked. Only the server name
is available which is passed as an argument.
CONFIG: Properly quote host variable to prevent cf build
breakage when a hostname contains 'dnl'. Problem
reported by Maxim Shalomikhin of Kaspersky.
DEVTOOLS: Add configure.sh support for BSD's mandoc as an
alternative man page formatting tool.
DOC: Document that USAGE is a possible value for {verify}.
LIBMILTER: The macros for the EOH and EOM callbacks are
sent in reverse order which means accessing macros
in the EOM callback got the macro for the EOH
callback. Store those macros in the expected order
in libmilter. Note: this does not affect sendmail
because the macros for both callbacks are the same
because the message is sent to libmilter after it
is completely read by sendmail. Fix and problem
report from David Buergin.
Portability:
Make use of IN_LOOPBACK, if defined, to determine if
using a loopback address. Patch from Mike Karels of
FreeBSD.
On Linux use gethostbyname2(3) if glibc 2.19 or newer
is used to avoid potential problems with IPv6 lookups.
Patch from Werner Wiethege.
Add support for Darwin 21 and Darwin 22.
Solaris 12 has been renamed to Solaris 11.4, hence
adapt a condition for sigwait(2) taking one argument.
Patch from John Beck.
New Files:
devtools/M4/UNIX/sharedlib.m4
devtools/OS/Darwin.21.x
devtools/OS/Darwin.22.x
sendmail/sched.c
libsm/notify.h
8.17.1/8.17.1 2021/08/17
Deprecation notice: due to compatibility problems with some
third party code, we plan to finally switch from K&R
@ -37,6 +218,9 @@ summary of the changes in that release.
in the SMTP client per server. Currently only two
flags are available: D/M to disable DANE/MTA-STS,
respectively.
New compile time option NO_EOH_FIELDS to disable the special
meaning of the headers Message: and Text: to denote the
end of the message header.
Avoid leaking session macros for an envelope between
delivery attempts to different servers. This problem
could have affected check_compat.
@ -76,10 +260,17 @@ summary of the changes in that release.
properly, as the persistent macro applies to all
RCPTs and hence implicitly to all destinations (servers).
The option TLSFallbacktoClear should be used if needed.
CONTRIB: AuthRealm.p0 has been modified for 8.16.1 by Anne Bennett.
CONTRIB: Added cidrexpand -O option for suppressing duplicates from
a CIDR expansion that overlaps a later entry and -S option
for skipping comments exactly like makemap does.
MAIL.LOCAL: Enhance some error messages to simplify
troubleshooting.
Portability:
Add support for Darwin 19 & 20.
Use proper FreeBSD version define to allow for cross
compiling. Fix from Brooks Davis of the FreeBSD
project.
NOTE: File locking using fcntl() does not interoperate
with Berkeley DB 5.x (and probably later). Use
CDB, flock() (-DHASFLOCK), or an earlier Berkeley
@ -104,22 +295,6 @@ summary of the changes in that release.
libsmutil/t-lockfile-0.sh
libsmutil/t-maplock-0.sh
8.16.2/8.16.2 202X/XX/XX
New compile time option NO_EOH_FIELDS to disable the special
meaning of the headers Message: and Text: to denote the
end of the message header.
CONTRIB: AuthRealm.p0 has been modified for 8.16.1 by Anne Bennett.
CONTRIB: Added cidrexpand -O option for suppressing duplicates from
a CIDR expansion that overlaps a later entry and -S option
for skipping comments exactly like makemap does.
Portability:
Add support for Darwin 19 (Mac OS X 10.15).
Use proper FreeBSD version define to allow for cross
compiling. Fix from Brooks Davis of the FreeBSD
project.
New Files:
devtools/OS/Darwin.19.x
8.16.1/8.16.1 2020/07/05
SECURITY: If sendmail tried to reuse an SMTP session which had
already been closed by the server, then the connection
@ -5392,7 +5567,7 @@ summary of the changes in that release.
characters (in LMTP mode), mail.local split the incoming
line up into 2046-character output lines (excluding the
newline). If an input line was 2047 characters long
(excluding CR-LF) and the last character was a '.',
(excluding CRLF) and the last character was a '.',
mail.local saw it as the end of input, transferred it to the
user mailbox and tried to write an `ok' back to sendmail.
If the message was much longer, both sendmail and
@ -7675,7 +7850,7 @@ summary of the changes in that release.
files that are group writable are considered "unsafe" -- that
is, programs and files referenced from such files are not
valid recipients.
Delete bogosity test for FallBackMX host; this prevented it to be a
Delete bogosity test for FallBackMXhost; this prevented it to be a
name that was not in DNS or was a domain-literal. Problem
noted by Tom May.
Change the introduction to error messages to more clearly delineate
@ -8414,7 +8589,7 @@ summary of the changes in that release.
should show the pathname rather than hex bytes.
Restore ``-ba'' mode -- this reads a file from stdin and parses
the header for envelope sender information and uses
CR-LF as message terminators. It was thought to be
CRLF as message terminators. It was thought to be
obsolete (used only for Arpanet NCP protocols), but it
turns out that the UK ``Grey Book'' protocols require
that functionality.
@ -10742,7 +10917,7 @@ summary of the changes in that release.
as well as the effective. The program test/t_setreuid.c
will test to see if your implementation of setreuid(2)
is appropriately functional.
The FallBackMX (option V) handling failed to properly identify
The FallBackMXhost (option V) handling failed to properly identify
fallback to yourself -- most of the code was there,
but it wasn't being enabled. Problem noted by Murray
Kucherawy of the University of Waterloo.

View File

@ -1301,6 +1301,8 @@ dnsbl Turns on rejection, discarding, or quarantining of hosts
definition from `host'. Set the DNSBL_MAP_OPT mc option
to add additional options to the map specification used.
Note: currently only IPv4 addresses are checked.
Some DNS based rejection lists cause failures if asked
for AAAA records. If your sendmail version is compiled
with IPv6 support (NETINET6) and you experience this
@ -1326,10 +1328,10 @@ enhdnsbl Enhanced version of dnsbl (see above). Further arguments
compared with the supplied argument(s), and only if a match
occurs an error is generated. For example,
FEATURE(`enhdnsbl', `dnsbl.example.com', `', `t', `127.0.0.2.')
FEATURE(`enhdnsbl', `dnsbl.example.com', `', `t', `127.0.0.2')
will reject the e-mail if the lookup returns the value
``127.0.0.2.'', or generate a 451 response if the lookup
``127.0.0.2'', or generate a 451 response if the lookup
temporarily failed. The arguments can contain metasymbols
as they are allowed in the LHS of rules. As the example
shows, the default values are also used if an empty argument,
@ -1616,6 +1618,12 @@ sts Experimental support for Strict Transport Security
for the default value).
For more information see doc/op/op.me.
fips3 Basic support for FIPS in OpenSSL 3 by setting
the environment variables OPENSSL_CONF and
OPENSSL_MODULES to the first and second argument,
respectively. For details, see the file and
the OpenSSL documentation.
+-------+
| HACKS |
+-------+
@ -1688,6 +1696,7 @@ The macro LOCAL_UUCP can be used to add rules into the generated
cf file at the place where MAILER(`uucp') inserts its rules. This
should only be used if really necessary.
+--------------------+
| USING UUCP MAILERS |
+--------------------+
@ -3183,8 +3192,8 @@ VERIFY:bits verification must have succeeded and ${cipher_bits} must
ENCR:bits ${cipher_bits} must be greater than or equal bits.
The RHS can optionally be prefixed by TEMP+ or PERM+ to select a temporary
or permanent error. The default is a temporary error code (403 4.7.0)
unless the macro TLS_PERM_ERR is set during generation of the .cf file.
or permanent error. The default is a temporary error code unless
the macro TLS_PERM_ERR is set during generation of the .cf file.
If a certain level of encryption is required, then it might also be
possible that this level is provided by the security layer from a SASL
@ -3256,9 +3265,10 @@ default TLS options are not modified.
About 2): the rulesets try_tls, srv_features, and clt_features can
be used together with the access map. Entries for the access map
must be tagged with Try_TLS, Srv_Features, Clt_Features and refer
to the hostname or IP address of the connecting system. A default
case can be specified by using just the tag. For example, the
following entries in the access map:
to the hostname or IP address of the connecting system (the latter
is not available for clt_features). A default case can be specified
by using just the tag. For example, the following entries in the
access map:
Try_TLS:broken.server NO
Srv_Features:my.domain v
@ -3376,6 +3386,7 @@ or FEATURE(`authinfo') must be used which provides a separate map.
Notice: It is not checked whether the map is actually
group/world-unreadable, this is left to the user.
+--------------------------------+
| ADDING NEW MAILERS OR RULESETS |
+--------------------------------+
@ -3461,6 +3472,7 @@ groups can be defined using the command:
For details about queue groups, please see doc/op/op.{me,ps,txt}.
+-------------------------------+
| NON-SMTP BASED CONFIGURATIONS |
+-------------------------------+
@ -4406,6 +4418,9 @@ confCERT_FINGERPRINT_ALGORITHM CertFingerprintAlgorithm
confSSL_ENGINE SSLEngine [undefined] Name of SSLEngine.
confSSL_ENGINE_PATH SSLEnginePath [undefined] Path to dynamic library
for SSLEngine.
confOPENSSL_CNF [/etc/mail/sendmail.ossl] Set the
environment variable OPENSSL_CONF.
An empty value disables setting it.
confNICE_QUEUE_RUN NiceQueueRun [undefined] If set, the priority of
queue runners is set the given value
(nice(3)).

View File

@ -16,8 +16,8 @@
#####
##### SENDMAIL CONFIGURATION FILE
#####
##### built by ca@lab.smi.sendmail.com on Sun Aug 15 23:05:00 PDT 2021
##### in /var/tmp/ca/sm8.head/sendmail/OpenSource/sendmail-8.17.1/cf/cf
##### built by xbuild@xenon14.us.proofpoint.com on Tue Jan 30 22:39:25 PST 2024
##### in /export/jenkins/jenkins3/workspace/pps-sendmail/OpenSource/sendmail-8.18.1/cf/cf
##### using ../ as configuration include directory
#####
######################################################################
@ -111,11 +111,13 @@ Kdequote dequote
DnMAILER-DAEMON
D{MTAHost}[127.0.0.1]
EOPENSSL_CONF=/etc/mail/sendmail.ossl
# Configuration version number
DZ8.17.1/Submit
DZ8.18.1/Submit
###############
@ -1248,6 +1250,7 @@ Stry_tls
######################################################################
### tls_rcpt: is connection with server "good" enough?
### (done in client, per recipient)
@ -1256,7 +1259,10 @@ Stry_tls
### $1: recipient
######################################################################
Stls_rcpt
R$* $: $1 $| $&{verify}
R$* $| DANE_NOTLS $#error $@ 4.7.0 $: "454 DANE: missing STARTTLS."
R$* $| DANE_TEMP $#error $@ 4.7.0 $: "454 DANE check failed temporarily."
R$* $| DANE_FAIL $#error $@ 4.7.0 $: "454 DANE check failed."
######################################################################
### tls_client: is connection with client "good" enough?
@ -1288,7 +1294,6 @@ R$* $@ $>"TLS_connection" $1
######################################################################
STLS_connection
RSOFTWARE $#error $@ 4.7.0 $: "454 TLS handshake failed."
RDANE_FAIL $#error $@ 4.7.0 $: "454 DANE check failed."
RPROTOCOL $#error $@ 4.7.0 $: "454 STARTTLS failed."
RCONFIG $#error $@ 4.7.0 $: "454 STARTTLS temporarily not possible."

View File

@ -13,5 +13,5 @@ divert(0)dnl
VERSIONID(`$Id: check_cert_altnames.m4 1.0 2019-01-01 01:01:01 ca Exp $')
divert(-1)
define(`_FFR_TLS_ALTNAMES', `1')
divert(6)dnl
LOCAL_CONFIG
O SetCertAltnames=true

View File

@ -17,7 +17,7 @@ VERSIONID(`$Id: enhdnsbl.m4,v 1.13 2013-11-22 20:51:11 ca Exp $')
LOCAL_CONFIG
define(`_EDNSBL_R_',`')dnl
# map for enhanced DNS based blocklist lookups
Kednsbl dns -R A -a. -T<TMP> -r`'ifdef(`EDNSBL_TO',`EDNSBL_TO',`5')
Kednsbl dns -R A -T<TMP> -z -Z32 -r`'ifdef(`EDNSBL_TO',`EDNSBL_TO',`5')
')
divert(-1)
define(`_EDNSBL_SRV_', `_ARG_')dnl
@ -39,15 +39,15 @@ R<?>OK $: OKSOFAR
ifelse(len(X`'_ARG3_),`1',
`R<?>$+<TMP> $: TMPOK',
`R<?>$+<TMP> $#error $@ 4.4.3 $: _EDNSBL_MSG_TMP_')
R<?>_EDNSBL_MATCH_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_
R<?>$* patsubst(_EDNSBL_MATCH_, `\.$', `') $* _EDNSBL_ACTION_ $: _EDNSBL_MSG_
ifelse(len(X`'_ARG5_),`1',`dnl',
`R<?>_ARG5_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
`R<?>$* patsubst(_ARG5_, `\.$', `') $* _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
ifelse(len(X`'_ARG6_),`1',`dnl',
`R<?>_ARG6_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
`R<?>$* patsubst(_ARG6_, `\.$', `') $* _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
ifelse(len(X`'_ARG7_),`1',`dnl',
`R<?>_ARG7_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
`R<?>$* patsubst(_ARG7_, `\.$', `') $* _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
ifelse(len(X`'_ARG8_),`1',`dnl',
`R<?>_ARG8_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
`R<?>$* patsubst(_ARG8_, `\.$', `') $* _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
ifelse(len(X`'_ARG9_),`1',`dnl',
`R<?>_ARG9_ _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
`R<?>$* patsubst(_ARG9_, `\.$', `') $* _EDNSBL_ACTION_ $: _EDNSBL_MSG_')
divert(-1)

View File

@ -0,0 +1,16 @@
divert(-1)
#
# Copyright (c) 2023 Proofpoint, Inc. and its suppliers.
# All rights reserved.
#
# By using this file, you agree to the terms and conditions set
# forth in the LICENSE file which can be found at the top level of
# the sendmail distribution.
#
#
divert(0)
define(`confOPENSSL_CNF', dnl
ifelse(defn(`_ARG_'), `', `/etc/mail/fips.ossl', `_ARG_'))dnl
ifelse(len(X`'_ARG2_),`1',`',`LOCAL_CONFIG
EOPENSSL_MODULES=_ARG2_')

View File

@ -18,7 +18,7 @@ ifelse(len(X`'_ARG1_), `1', `define(`_LDAP_ROUTING_WARN_', `yes')')
ifelse(len(X`'_ARG2_), `1', `define(`_LDAP_ROUTING_WARN_', `yes')')
ifelse(len(X`'_ARG5_), `1', `', `define(`_LDAP_ROUTE_NODOMAIN_', `yes')')
# Check for third argument to indicate how to deal with non-existant
# Check for third argument to indicate how to deal with non-existent
# LDAP records
ifelse(len(X`'_ARG3_), `1', `define(`_LDAP_ROUTING_', `_PASS_THROUGH_')',
_ARG3_, `passthru', `define(`_LDAP_ROUTING_', `_PASS_THROUGH_')',

View File

@ -20,6 +20,8 @@ LOCAL_RULESETS
#
# x_connect ruleset for looking up XConnect: tag in access DB to enable
# XCONNECT support in MTA
# if the RHS of the map entry is haproxy1,
# then HAproxy protocol version 1 is used
#
Sx_connect
dnl workspace: {client_name} $| {client_addr}
@ -32,6 +34,6 @@ R<?> <$+> $: $>A < $1 > <?> <! XConnect> <> no: another lookup
dnl workspace: <result-of-lookup> (<>|<{client_addr}>)
R<?> <$*> $# no found nothing
dnl workspace: <result-of-lookup> (<>|<{client_addr}>) | OK
R<$+> <$*> $@ yes found in access DB',
R<$+> <$*> $@ $1 found in access DB',
`errprint(`*** ERROR: HACK(xconnect) requires FEATURE(access_db)
')')

View File

@ -247,7 +247,9 @@ DM`'MASQUERADE_NAME')
# my name for error messages
ifdef(`confMAILER_NAME', `Dn`'confMAILER_NAME', `#DnMAILER-DAEMON')
ifdef(`confOPENSSL_CNF',, `define(`confOPENSSL_CNF', `/etc/mail/sendmail.ossl')')
undivert(6)dnl LOCAL_CONFIG
ifelse(defn(`confOPENSSL_CNF'), `', `', `EOPENSSL_CONF=confOPENSSL_CNF')
include(_CF_DIR_`m4/version.m4')
###############
@ -938,7 +940,7 @@ ifdef(`_CANONIFY_HOSTS_', `dnl
dnl this should only apply to unqualified hostnames
dnl but if a valid character inside an unqualified hostname is an OperatorChar
dnl then $- does not work.
# lookup unqualified hostnames
# look up unqualified hostnames
R$* $| $* < @ $* > $* $: $2 < @ $[ $3 $] > $4', `dnl')', `dnl
dnl _NO_CANONIFY_ is not set: canonify unless:
dnl {daemon_flags} contains CC (do not canonify)
@ -1234,7 +1236,7 @@ R$+ . USENET $#usenet $@ usenet $: $1',
ifdef(`_LOCAL_RULES_',
`# figure out what should stay in our local mail system
undivert(1)', `dnl')
undivert(1)dnl LOCAL_NET_CONFIG', `dnl')
# pass names that still have a host to a smarthost (if defined)
R$* < @ $* > $* $: $>MailerToTriple < $S > $1 < @ $2 > $3 glue on smarthost name
@ -1436,11 +1438,12 @@ dnl if generics should be applied add a @ as mark
R$+ < @ *LOCAL* > $: < $1@$j > $1 < @ *LOCAL* > @ mark
dnl workspace: either user<@domain> or <user@domain> user <@domain> @
dnl ignore the first case for now
dnl if it has the mark lookup full address
dnl if it has the mark look up full address
dnl broken: %1 is full address not just detail
R< $+ > $+ < $* > @ $: < $(generics $1 $: @ $1 $) > $2 < $3 >
dnl workspace: ... or <match|@user@domain> user <@domain>
dnl no match, try user+detail@domain
dnl no match, try user+detail@domain:
dnl look up user+*@domain and user@domain
R<@$+ + $* @ $+> $+ < @ $+ >
$: < $(generics $1+*@$3 $@ $2 $:@$1 + $2@$3 $) > $4 < @ $5 >
R<@$+ + $* @ $+> $+ < @ $+ >
@ -1527,7 +1530,7 @@ R$={SMTPOpModes} $| TMPF <e r> $| $+ $#error $@ 4.3.0 $: _TMPFMSG_(`OPM')')
# ... return original address for MTA to queue up
R$* $| TMPF <$*> $| $+ $@ $3
# if mailRoutingAddress and local or non-existant mailHost,
# if mailRoutingAddress and local or non-existent mailHost,
# return the new mailRoutingAddress
ifelse(_LDAP_ROUTE_DETAIL_, `_PRESERVE_', `dnl
R<$+@$+> <$=w> <$+> <$+> <$*> $@ $>Parse0 $>canonify $1 $6 @ $2
@ -1610,14 +1613,14 @@ dnl <result> <passthru>
SD
dnl workspace <key> <default> <passthru> <mark>
dnl lookup with tag (in front, no delimiter here)
dnl look up with tag (in front, no delimiter here)
dnl 2 3 4 5
R<$*> <$+> <$- $-> <$*> $: < $(access $4`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3 $4> <$5>
dnl workspace <result-of-lookup|?> <key> <default> <passthru> <mark>
dnl lookup without tag?
dnl look up without tag?
dnl 1 2 3 4
R<?> <$+> <$+> <+ $-> <$*> $: < $(access $1 $: ? $) > <$1> <$2> <+ $3> <$4>
ifdef(`_LOOKUPDOTDOMAIN_', `dnl omit first component: lookup .rest
ifdef(`_LOOKUPDOTDOMAIN_', `dnl omit first component: look up .rest
dnl XXX apply this also to IP addresses?
dnl currently it works the wrong way round for [1.2.3.4]
dnl 1 2 3 4 5 6
@ -1640,7 +1643,7 @@ R<?> <[$+:$-]> <$+> <$- $-> <$*> $: $>D <[$1]> <$3> <$4 $5> <$6>')
dnl not found, but subdomain: try again
dnl 1 2 3 4 5 6
R<?> <$+.$+> <$+> <$- $-> <$*> $@ $>D <$2> <$3> <$4 $5> <$6>
ifdef(`_FFR_LOOKUPTAG_', `dnl lookup Tag:
ifdef(`_FFR_LOOKUPTAG_', `dnl look up Tag:
dnl 1 2 3 4
R<?> <$+> <$+> <! $-> <$*> $: < $(access $3`'_TAG_DELIM_ $: ? $) > <$1> <$2> <! $3> <$4>', `dnl')
dnl not found, no subdomain: return <default> and <passthru>
@ -1669,10 +1672,10 @@ dnl <result> <passthru>
######################################################################
SA
dnl lookup with tag
dnl look up with tag
dnl 2 3 4 5
R<$+> <$+> <$- $-> <$*> $: < $(access $4`'_TAG_DELIM_`'$1 $: ? $) > <$1> <$2> <$3 $4> <$5>
dnl lookup without tag
dnl look up without tag
dnl 1 2 3 4
R<?> <$+> <$+> <+ $-> <$*> $: < $(access $1 $: ? $) > <$1> <$2> <+ $3> <$4>
dnl workspace <result-of-lookup|?> <key> <default> <mark> <passthru>
@ -2402,7 +2405,7 @@ dnl otherwise call tls_client; see above
R$+ $| $#$* $@ $>"Delay_TLS_Clt" $2
R$+ $| $* $: <?> $>FullAddr $>CanonAddr $1
ifdef(`_SPAM_FH_',
`dnl lookup user@ and user@address
`dnl look up user@ and user@address
ifdef(`_ACCESS_TABLE_', `',
`errprint(`*** ERROR: FEATURE(`delay_checks', `argument') requires FEATURE(`access_db')
')')dnl
@ -2412,7 +2415,7 @@ dnl and simplified by omitting some < >.
R<?> $+ < @ $=w > $: <> $1 < @ $2 > $| <F: $1@$2 > <D: $2 > <U: $1@>
R<?> $+ < @ $* > $: <> $1 < @ $2 > $| <F: $1@$2 > <D: $2 >
dnl R<?> $@ something_is_very_wrong_here
# lookup the addresses only with Spam tag
# look up the addresses only with Spam tag
R<> $* $| <$+> $: <@> $1 $| $>SearchList <! Spam> $| <$2> <>
R<@> $* $| $* $: $2 $1 reverse result
dnl', `dnl')
@ -2608,16 +2611,16 @@ R<$+> <$*> <$- $-> <$*> $@ <$1> <$5>
### Parameters:
### <exact tag> $| <mark:address> <mark:address> ... <>
dnl maybe we should have a @ (again) in front of the mark to
dnl avoid errorneous matches (with error messages?)
dnl avoid erroneous matches (with error messages?)
dnl if we can make sure that tag is always a single token
dnl then we can omit the delimiter $|, otherwise we need it
dnl to avoid errorneous matchs (first rule: D: if there
dnl to avoid erroneous matches (first rule: D: if there
dnl is that mark somewhere in the list, it will be taken).
dnl moreover, we can do some tricks to enforce lookup with
dnl the tag only, e.g.:
### where "exact" is either "+" or "!":
### <+ TAG> lookup with and w/o tag
### <! TAG> lookup with tag
### <+ TAG> look up with and w/o tag
### <! TAG> look up with tag
dnl Warning: + and ! should be in OperatorChars (otherwise there must be
dnl a blank between them and the tag.
### possible values for "mark" are:
@ -2706,8 +2709,9 @@ R$* $: $1 $| $>"Local_clt_features" $1
R$* $| $#$* $#$2
R$* $| $* $: $1', `dnl')
ifdef(`_ACCESS_TABLE_', `dnl
R$* $: $>D <$&{client_name}> <?> <! CLT_FEAT_TAG> <>
R<?>$* $: $>A <$&{client_addr}> <?> <! CLT_FEAT_TAG> <>
dnl the servername can have a trailing dot from canonification
R$* . $1
R$+ $: $>D <$1> <?> <! CLT_FEAT_TAG> <>
R<?>$* $: <$(access CLT_FEAT_TAG`'_TAG_DELIM_ $: ? $)>
R<?>$* $@ OK
ifdef(`_ATMPF_', `dnl tempfail?
@ -2802,6 +2806,18 @@ R:$* $| $-.$+ $: $(macro {TLS_Name} $@ .$3 $) $>TLS_NameInList :$1
R$* ok $@ $>STS_SAN
R:$*: $#error $@ 4.7.0 $: 450 $&{server_name} not found in " "$1', `dnl')
ifdef(`TLS_PERM_ERR', `dnl
define(`TLS_DSNCODE', `5.7.0')dnl
define(`TLS_ERRCODE', `554')',`dnl
define(`TLS_DSNCODE', `4.7.0')dnl
define(`TLS_ERRCODE', `454')')dnl
define(`SW_MSG', `TLS handshake failed.')dnl
define(`DANE_MSG', `DANE check failed.')dnl
define(`DANE_TEMP_MSG', `DANE check failed temporarily.')dnl
define(`DANE_NOTLS_MSG', `DANE: missing STARTTLS.')dnl
define(`PROT_MSG', `STARTTLS failed.')dnl
define(`CNF_MSG', `STARTTLS temporarily not possible.')dnl
######################################################################
### tls_rcpt: is connection with server "good" enough?
### (done in client, per recipient)
@ -2833,12 +2849,22 @@ R<?> $+ $: $1 $| <U:$1@> <E:>
dnl look it up
dnl also look up a default value via E:
R$* $| $+ $: $1 $| $>SearchList <! TLS_RCPT_TAG> $| $2 <>
dnl no applicable requirements; trigger an error on DANE_FAIL
dnl note: this allows to disable DANE per RCPT.
R$* $| <?> $: $1 $| $&{verify} $| <?>
R$* $| DANE_FAIL $| <?> $#error $@ TLS_DSNCODE $: "TLS_ERRCODE DANE_MSG"
R$* $| DANE_NOTLS $| <?> $#error $@ TLS_DSNCODE $: "TLS_ERRCODE DANE_NOTLS_MSG"
R$* $| DANE_TEMP $| <?> $#error $@ TLS_DSNCODE $: "TLS_ERRCODE DANE_TEMP_MSG"
dnl found nothing: stop here
R$* $| <?> $@ OK
ifdef(`_ATMPF_', `dnl tempfail?
R$* $| <$* _ATMPF_> $#error $@ 4.3.0 $: _TMPFMSG_(`TR')', `dnl')
dnl use the generic routine (for now)
R$* $| <$+> $@ $>"TLS_connection" $&{verify} $| <$2>')
R$* $| <$+> $@ $>"TLS_connection" $&{verify} $| <$2>', `dnl
R$* $: $1 $| $&{verify}
R$* $| DANE_NOTLS $#error $@ TLS_DSNCODE $: "TLS_ERRCODE DANE_NOTLS_MSG"
R$* $| DANE_TEMP $#error $@ TLS_DSNCODE $: "TLS_ERRCODE DANE_TEMP_MSG"
R$* $| DANE_FAIL $#error $@ TLS_DSNCODE $: "TLS_ERRCODE DANE_MSG"')
######################################################################
### tls_client: is connection with client "good" enough?
@ -2915,22 +2941,14 @@ dnl [(PERM|TEMP)+] (VERIFY[:bits]|ENCR:bits) [+extensions]
dnl extensions: could be a list of further requirements
dnl for now: CN:string {cn_subject} == string
######################################################################
ifdef(`TLS_PERM_ERR', `dnl
define(`TLS_DSNCODE', `5.7.0')dnl
define(`TLS_ERRCODE', `554')',`dnl
define(`TLS_DSNCODE', `4.7.0')dnl
define(`TLS_ERRCODE', `454')')dnl
define(`SW_MSG', `TLS handshake failed.')dnl
define(`DANE_MSG', `DANE check failed.')dnl
define(`PROT_MSG', `STARTTLS failed.')dnl
define(`CNF_MSG', `STARTTLS temporarily not possible.')dnl
STLS_connection
ifdef(`_FULL_TLS_CONNECTION_CHECK_', `dnl', `dnl use default error
dnl deal with TLS handshake failures: abort
RSOFTWARE $#error $@ TLS_DSNCODE $: "TLS_ERRCODE SW_MSG"
RDANE_FAIL $#error $@ TLS_DSNCODE $: "TLS_ERRCODE DANE_MSG"
dnl RDANE_FAIL $#error $@ TLS_DSNCODE $: "TLS_ERRCODE DANE_MSG"
RPROTOCOL $#error $@ TLS_DSNCODE $: "TLS_ERRCODE PROT_MSG"
RCONFIG $#error $@ TLS_DSNCODE $: "TLS_ERRCODE CNF_MSG"
dnl RDANE_TEMP $#error $@ 4.7.0 $: "454 DANE_TEMP_MSG"
divert(-1)')
dnl common ruleset for tls_{client|server}
dnl input: ${verify} $| <ResultOfLookup> [<>]
@ -2953,10 +2971,12 @@ R`'$1 $| $`'* $`'#error $`'@ TLS_DSNCODE $: "TLS_ERRCODE $2"')dnl
TLS_ERRORS(SOFTWARE,SW_MSG)
# deal with TLS protocol errors: abort
TLS_ERRORS(PROTOCOL,PROT_MSG)
# deal with DANE errors: abort
TLS_ERRORS(DANE_FAIL,DANE_MSG)
dnl # deal with DANE errors: abort
dnl TLS_ERRORS(DANE_FAIL,DANE_MSG)
# deal with CONFIG (tls_clt_features) errors: abort
TLS_ERRORS(CONFIG,CNF_MSG)
dnl # deal with DANE tempfail: abort
dnl TLS_ERRORS(DANE_TEMP,DANE_TEMP_MSG)
R$* $| <$*> <VERIFY> $: <$2> <VERIFY> <> $1
dnl separate optional requirements
R$* $| <$*> <VERIFY + $+> $: <$2> <VERIFY> <$3> $1

View File

@ -15,4 +15,4 @@ VERSIONID(`$Id: version.m4,v 8.237 2014-01-27 12:55:17 ca Exp $')
#
divert(0)
# Configuration version number
DZ8.17.1`'ifdef(`confCF_VERSION', `/confCF_VERSION')
DZ8.18.1`'ifdef(`confCF_VERSION', `/confCF_VERSION')

View File

@ -57,4 +57,4 @@ fi
echo '#####' built by $user@$host
echo '#####' in `pwd` | sed 's/\/tmp_mnt//'
echo '#####' using $1 as configuration include directory | sed 's/\/tmp_mnt//'
echo "define(\`__HOST__', $host)dnl"
echo "define(\`__HOST__', \`$host')dnl"

View File

@ -170,7 +170,7 @@ LINE: while (<DOMAIN>)
warn "Bogus line $line in $virts/$domain\n";
}
# Variable subsitution
# Variable substitution
$key =~ s/\$DOMAIN/$domain/g;
$value =~ s/\$DOMAIN/$domain/g;
$value =~ s/\$LHS/$lhs/g;

View File

@ -13,9 +13,12 @@ PIC= ${PIC_CMD} -C
EQNASCII= ${EQN_CMD} -C -Tascii
EQNPS= ${EQN_CMD} -C -Tps
ROFFASCII= ${ROFF_CMD} -Tascii ${MACROS}
ROFFNOSGR= GROFF_NO_SGR=1 ${ROFFASCII}
ROFFPS= ${ROFF_CMD} -Tps -mps ${MACROS}
ULASCII= ${UL_CMD} -t dumb
PS2PDF= ${PS2PDF_CMD}
OPTXT_CMD= ${PIC} ${SRCS} | ${EQNASCII} | ${ROFFASCII} | ${ULASCII} 2>/dev/null
OPTXTNS_CMD= ${PIC} ${SRCS} | ${EQNASCII} | ${ROFFNOSGR} | ${ULASCII}
all: ${OBJS}
@ -26,8 +29,7 @@ op.ps: ${SRCS}
op.txt: ${SRCS}
rm -f $@
@echo "Note: see README file in case of errors."
${PIC} ${SRCS} | ${EQNASCII} | ${ROFFASCII} | ${ULASCII} > $@
${OPTXT_CMD} > $@ || ${OPTXTNS_CMD} > $@
op.pdf: op.ps
rm -f $@

View File

@ -92,7 +92,7 @@ Version \\$2
..
.rm Ve
.sp
For Sendmail Version 8.17
For Sendmail Version 8.18
.)l
.(f
Sendmail is a trademark of Proofpoint, Inc.
@ -1690,22 +1690,17 @@ Blank lines and lines beginning with a sharp sign
.q # )
are comments.
.pp
The second form is processed by the
The second form is processed by one of the available map types,
e.g.,
.i ndbm \|(3)\**
.(f
\**The
.i gdbm
package does not work.
.)f
or the Berkeley DB library.
This form is in the file
.i /etc/mail/aliases.db
(if using NEWDB)
the Berkeley DB library,
or
.i /etc/mail/aliases.dir
and
.i /etc/mail/aliases.pag
(if using NDBM).
.i cdb .
This is the form that
.i sendmail
actually uses to resolve aliases.
@ -3246,6 +3241,9 @@ often cannot assume that a given file was created by the owner,
particularly when it is in a writable directory.
You can set this flag if you know that file giveaway is restricted
on your system.
.ip CertOwner
Accept certificate public and private key files
which are not owned by RunAsUser for STARTTLS.
.ip ClassFileInUnsafeDirPath
When reading class files (using the
.b F
@ -4415,17 +4413,18 @@ It can accept or reject the command.
The
.i clt_features
ruleset is called with the server's host name
when sendmail connects to it.
before sendmail connects to it
(only if sendmail is compiled with STARTTLS or SASL).
This ruleset should return
.b $#
followed by a list of options
(single characters delimited by white space).
(in general, single characters delimited by white space).
If the return value starts with anything else it is silently ignored.
Generally upper case characters turn off a feature
while lower case characters turn it on.
Options `D'/`M' cause the client to not use DANE/MTA-STS,
respectively,
which is useful to interact with MTAs/MUs that have broken
which is useful to interact with MTAs that have broken
DANE/MTA-STS setups by simply not using it.
Note:
The
@ -4454,15 +4453,18 @@ not passed on to the next relay.
.pp
The
.i tls_client
ruleset is called when sendmail acts as server, after a STARTTLS command
has been issued, and from
ruleset is called when sendmail acts as server:
after a STARTTLS command has been issued and the TLS handshake
was performed,
and from
.i check_mail.
The parameter is the value of
.b ${verify}
and STARTTLS or MAIL, respectively.
If the ruleset does resolve to the
.q error
mailer, the appropriate error code is returned to the client.
mailer, the appropriate error code is returned to the client,
for STARTTLS this happens for (most) subsequent commands.
.sh 4 "tls_server"
.pp
The
@ -4506,8 +4508,8 @@ ruleset is called with the connecting client's host name
when a client connects to sendmail.
This ruleset should return
.b $#
followed by a list of options (single characters
delimited by white space).
followed by a list of options
(in general, single characters delimited by white space).
If the return value starts with anything else it is silently ignored.
Generally upper case characters turn off a feature
while lower case characters turn it on.
@ -4526,6 +4528,40 @@ If a client sends one of the (HTTP) commands GET, POST, CONNECT, or USER
the connection is immediately terminated in the following cases:
if sent as first command, if sent as first command after STARTTLS,
or if the 'h' option is set.
Option 'F' disables SMTP transaction stuffing protection which is
enabled by default.
The protection checks for clients which try to send commands
without waiting for the server HELO/EHLO and DATA response.
Option 'o' causes the server to accept only
CRLF . CRLF
as end of an SMTP message as required by the RFCs
which is also a defense against SMTP smuggling (CVE-2023-51765).
Option 'O' allows the server to accept a single dot on a line by itself
as end of an SMTP message.
Option 'g' instructs the server to fail SMTP messages
which have a LF without a CR directly before it ("bare LF")
by dropping the session with a 421 error.
Option 'G' accepts SMTP messages which have a "bare LF".
Option 'u' instructs the server to fail SMTP messages
which have a CR without a LF directly after it ("bare CR")
by dropping the session with a 421 error.
Option 'U' accepts SMTP messages which have a "bare CR".
There is a variant for the options 'u' and 'g':
a '2' can be appended to the single character,
in which case the server will replace the offending bare CR
or bare LF with a space.
This allows to accept mail from broken systems,
but the message is modified to avoid SMTP smuggling.
If needed, systems with broken SMTP implementations
can be allowed some violations, e.g., a combination of
.(b
G U g2 u2 O
.)b
A command like
.(b
egrep 'Bare.*(CR|LF).*not allowed' $MAILLOG
.)b
can be used to find hosts which send bare CR or LF.
.(b
.ta 9n
A Do not offer AUTH
@ -4539,13 +4575,24 @@ D Do not offer DSN
d Offer DSN (default)
E Do not offer ETRN
e Offer ETRN (default)
F Disable transaction stuffing protection
f Enforce transaction stuffing protection (default)
G Accept "bare LF"s in a message
g Do not accept "bare LF"s in a message (default)
g2 Replace "bare LF" in a message with space
h Terminate session after HTTP commands
L Do not require AUTH (default)
l Require AUTH
O Accept a single dot on a line by itself
as end of an SMTP message
o Require CRLF . CRLF as end of an SMTP message (default)
P Do not offer PIPELINING
p Offer PIPELINING (default)
S Do not offer STARTTLS
s Offer STARTTLS (default)
U Accept "bare CR"s in a message
u Do not accept "bare CR"s in a message (default)
u2 Replace "bare CR" in a message with space
V Do not request a client certificate
v Request a client certificate (default)
X Do not offer EXPN
@ -4566,6 +4613,7 @@ accept email.
The
.i try_tls
ruleset is called when sendmail connects to another MTA.
The argument for the ruleset is the name of the server.
If the ruleset does resolve to the
.q error
mailer, sendmail does not try STARTTLS even if it is offered.
@ -4667,6 +4715,10 @@ specifying only one is an error.
The
.i authinfo
ruleset is called when sendmail tries to authenticate to another MTA.
The arguments for the ruleset are the host name and IP address
of the server separated by
.b $|
(which is a metacharacter).
It should return
.b $#
followed by a list of tokens that are used for SMTP AUTH.
@ -4713,6 +4765,10 @@ The
.i greet_pause
ruleset is used to specify the amount of time to pause before sending the
initial SMTP 220 greeting.
The arguments for the ruleset are the host name and IP address
of the client separated by
.b $|
(which is a metacharacter).
If any traffic is received during that pause, an SMTP 554 rejection
response is given instead of the 220 greeting and all SMTP commands are
rejected during that connection.
@ -4967,26 +5023,6 @@ a richer set of operators is
which adds support for UUCP, the %-hack, and X.400 addresses.
.ip $p
Sendmail's process id.
.ip $q\(dg
Default format of sender address.
The
.b $q
macro specifies how an address should appear in a message
when it is defaulted.
Defaults to
.q "<$g>" .
It is commonly redefined to be
.q "$?x$x <$g>$|$g$."
or
.q "$g$?x ($x)$." ,
corresponding to the following two formats:
.(b
Eric Allman <eric@CS.Berkeley.EDU>
eric@CS.Berkeley.EDU (Eric Allman)
.)b
.i Sendmail
properly quotes names that have special characters
if the first form is used.
.ip $r
Protocol used to receive the message.
Set from the
@ -5356,16 +5392,21 @@ Possible values are:
.(b
.ta 13n
TRUSTED verification via DANE succeeded.
DANE_FAIL verification via DANE failed.
DANE_TEMP verification via DANE failed temporarily.
DANE_NOTLS DANE required but STARTTLS was not available.
OK verification succeeded.
NO no cert presented.
NOT no cert requested.
FAIL cert presented but could not be verified,
e.g., the signing CA is missing.
NONE STARTTLS has not been performed.
CLEAR STARTTLS has been disabled internally for a clear text delivery attempt.
CLEAR STARTTLS has been disabled internally
for a clear text delivery attempt.
TEMP temporary error occurred.
PROTOCOL some protocol error occurred
at the ESMTP level (not TLS).
CONFIG tls_*_features failed due to a syntax error.
SOFTWARE STARTTLS handshake failed,
which is a fatal error for this session,
the e-mail will be queued.
@ -5670,7 +5711,7 @@ will fill the class
.b $={VirtHosts}
from an LDAP map lookup and
.b $={MyClass}
from a hash database map lookup of the
from a hash database map lookup of the key
.b foo .
There is also a built-in schema that can be accessed by only specifying:
.(b
@ -5703,7 +5744,7 @@ Some classes have internal meaning to
.nr ii 0.5i
.\".ip $=b
.\"A set of Content-Types that will not have the newline character
.\"translated to CR-LF before encoding into base64 MIME.
.\"translated to CRLF before encoding into base64 MIME.
.\"The class can have major times
.\"(e.g.,
.\".q image )
@ -5793,6 +5834,24 @@ file into a class, use
FL/etc/passwd %[^:]
.)b
which reads every line up to the first colon.
.sh 2 "E \*- Set or Propagate Environment Variables"
.pp
.b E
configuration lines set or propagate environment variables into children.
.(b F
.b E \c
.i name
.)b
will propagate the named variable from the environment when
.i sendmail
was invoked into any children it calls;
.(b F
.b E \c
.i name =\c
.i value
.)b
sets the named variable to the indicated value.
Any variables not explicitly named will not be in the child environment.
.sh 2 "M \*- Define Mailer"
.pp
Programs and interfaces to mailers
@ -5819,7 +5878,7 @@ Path The pathname of the mailer
Flags Special flags for this mailer
Sender Rewriting set(s) for sender addresses
Recipient Rewriting set(s) for recipient addresses
recipients Maximum number of recipients per connection
recipients Maximum number of recipients per envelope
Argv An argument vector to pass to this mailer
Eol The end-of-line string for this mailer
Maxsize The maximum message length to this mailer
@ -6146,7 +6205,7 @@ Do not apply
.b FallbackMXhost
either.
.ip 1
Don't send null characters ('\\0') to this mailer.
Strip null characters ('\\0') when sending to this mailer.
.ip 2
Don't use ESMTP even if offered; this is useful for broken
systems that offer ESMTP but fail on EHLO (without recovering
@ -6187,7 +6246,7 @@ do
7\(->8 bit MIME conversions.
These conversions are limited to text/plain data.
.ip :
Check addresses to see if they begin
Check addresses to see if they begin with
.q :include: ;
if they do, convert them to the
.q *include*
@ -6679,13 +6738,11 @@ If it does not appear in the
.i timeout
interval issue a warning.
.ip AllowBogusHELO
[no short name]
If set, allow HELO SMTP commands that don't include a host name.
Setting this violates RFC 1123 section 5.2.5,
but is necessary to interoperate with several SMTP clients.
If there is a value, it is still checked for legitimacy.
.ip AuthMaxBits=\fIN\fP
[no short name]
Limit the maximum encryption strength for the security layer in
SMTP AUTH (SASL). Default is essentially unlimited.
This allows to turn off additional encryption in SASL if
@ -6698,7 +6755,6 @@ Hence setting
.b AuthMaxBits
to 168 will disable any encryption in SASL.
.ip AuthMechanisms
[no short name]
List of authentication mechanisms for AUTH (separated by spaces).
The advertised list of authentication mechanisms will be the
intersection of this list and the list of available mechanisms as
@ -6706,7 +6762,6 @@ determined by the Cyrus SASL library.
If STARTTLS is active, EXTERNAL will be added to this list.
In that case, the value of {cert_subject} is used as authentication id.
.ip AuthOptions
[no short name]
List of options for SMTP AUTH consisting of single characters
with intervening white space or commas.
.(b
@ -6743,14 +6798,12 @@ The options 'a', 'c', 'd', 'f', 'p', and 'y' refer to properties of the
selected SASL mechanisms.
Explanations of these properties can be found in the Cyrus SASL documentation.
.ip AuthRealm
[no short name]
The authentication realm that is passed to the Cyrus SASL library.
If no realm is specified,
.b $j
is used.
See also KNOWNBUGS.
.ip BadRcptThrottle=\fIN\fP
[no short name]
If set and the specified number of recipients in a single SMTP
transaction have been rejected, sleep for one second after each subsequent
RCPT command in that transaction.
@ -6761,12 +6814,10 @@ Set the blank substitution character to
Unquoted spaces in addresses are replaced by this character.
Defaults to space (i.e., no change is made).
.ip CACertPath
[no short name]
Path to directory with certificates of CAs.
This directory directory must contain the hashes of each CA certificate
as filenames (or as links to them).
.ip CACertFile
[no short name]
File containing one or more CA certificates;
see section about STARTTLS for more information.
.ip CertFingerprintAlgorithm
@ -6811,19 +6862,16 @@ and subtracted from the priority.
Thus, messages with a higher Priority: will be favored.
Defaults to 1800.
.ip ClientCertFile
[no short name]
File containing the certificate of the client, i.e., this certificate
is used when
.i sendmail
acts as client (for STARTTLS).
.ip ClientKeyFile
[no short name]
File containing the private key belonging to the client certificate
(for STARTTLS if
.i sendmail
runs as client).
.ip ClientPortOptions=\fIoptions\fP
[no short name]
Set client SMTP options.
The options are
.i key=value
@ -6886,7 +6934,6 @@ Options can be cleared by preceding them with a minus sign.
It is also possible to specify numerical values, e.g.,
.b -0x0010 .
.ip ColonOkInAddr
[no short name]
If set, colons are acceptable in e-mail addresses
(e.g.,
.q host:user ).
@ -6935,11 +6982,9 @@ and avoid using up excessive resources
on the other end.
The default is five minutes.
.ip ConnectOnlyTo=\fIaddress\fP
[no short name]
This can be used to
override the connection address (for testing purposes).
.ip ConnectionRateThrottle=\fIN\fP
[no short name]
If set to a positive value,
allow no more than
.i N
@ -6948,12 +6993,10 @@ This is intended to flatten out peaks
and allow the load average checking to cut in.
Defaults to zero (no limits).
.ip ConnectionRateWindowSize=\fIN\fP
[no short name]
Define the length of the interval for which
the number of incoming connections is maintained.
The default is 60 seconds.
.ip ControlSocketName=\fIname\fP
[no short name]
Name of the control socket for daemon management.
A running
.i sendmail
@ -6974,13 +7017,11 @@ and the load average of the machine expressed as an integer.
If not set, no control socket will be available.
Solaris and pre-4.4BSD kernel users should see the note in sendmail/README .
.ip CRLFile=\fIname\fP
[no short name]
Name of file that contains certificate
revocation status, useful for X.509v3 authentication.
Note: if a CRLFile is specified but the file is unusable,
STARTTLS is disabled.
.ip CRLPath=\fIname\fP
[no short name]
Name of directory that contains hashes pointing to
certificate revocation status files.
Symbolic links can be generated with the following
@ -7142,7 +7183,6 @@ The modifier ``O'' causes sendmail to ignore a socket
if it can't be opened.
This applies to failures from the socket(2) and bind(2) calls.
.ip DefaultAuthInfo
[no short name]
Filename that contains default authentication information for outgoing
connections. This file must contain the user id, the authorization id,
the password (plain text), the realm and the list of mechanisms to use
@ -7162,7 +7202,6 @@ will complain).
Use the authinfo ruleset instead which provides more control over
the usage of the data anyway.
.ip DefaultCharSet=\fIcharset\fP
[no short name]
When a message that has 8-bit characters but is not in MIME format
is converted to MIME
(see the EightBitMode option)
@ -7174,7 +7213,6 @@ If this option is not set, the value
.q unknown-8bit
is used.
.ip DataFileBufferSize=\fIthreshold\fP
[no short name]
Set the
.i threshold ,
in bytes,
@ -7183,7 +7221,6 @@ queue data file
becomes disk-based.
The default is 4096 bytes.
.ip DeadLetterDrop=\fIfile\fP
[no short name]
Defines the location of the system-wide dead.letter file,
formerly hardcoded to /usr/tmp/dead.letter.
If this option is not set (the default),
@ -7224,14 +7261,12 @@ option has been combined into the
option.
.)f
.ip DelayLA=\fILA\fP
[no short name]
When the system load average exceeds
.i LA ,
.i sendmail
will sleep for one second on most SMTP commands and
before accepting connections.
.ip DeliverByMin=\fItime\fP
[no short name]
Set minimum time for Deliver By SMTP Service Extension (RFC 2852).
If 0, no time is listed, if less than 0, the extension is not offered,
if greater than 0, it is listed as minimum time
@ -7260,7 +7295,6 @@ Note: for internal reasons,
if a milter is enabled which can reject or delete recipients.
In that case the mode will be changed to ``b''.
.ip DialDelay=\fIsleeptime\fP
[no short name]
Dial-on-demand network connections can see timeouts
if a connection is opened before the call is set up.
If this is set to an interval and a connection times out
@ -7287,7 +7321,6 @@ is either "CC f" if the option
is used or "c u" otherwise.
Note that only the "CC", "c", "f", and "u" flags are checked.
.ip DontBlameSendmail=\fIoption,option,...\fP
[no short name]
In order to avoid possible cracking attempts
caused by world- and group-writable files and directories,
.i sendmail
@ -7304,7 +7337,6 @@ The details of these flags are described above.
.\"XXX should have more here!!! XXX
.b "Use of this option is not recommended."
.ip DontExpandCnames
[no short name]
The standards say that all host addresses used in a mail message
must be fully canonical.
For example, if your host is named
@ -7322,7 +7354,6 @@ so the behavior may become acceptable.
Please note that hosts downstream may still rewrite the address
to be the true canonical name however.
.ip DontInitGroups
[no short name]
If set,
.i sendmail
will avoid using the initgroups(3) call.
@ -7334,7 +7365,6 @@ will be their primary group (the one in the password file),
which will make file access permissions somewhat more restrictive.
Has no effect on systems that don't have group lists.
.ip DontProbeInterfaces
[no short name]
.i Sendmail
normally finds the names of all interfaces active on your machine
when it starts up
@ -7375,7 +7405,6 @@ and the mail will be sent to the first address in the route,
even if later addresses are known.
This may be useful if you are caught behind a firewall.
.ip DoubleBounceAddress=\fIerror-address\fP
[no short name]
If an error occurs when sending an error message,
send the error report
(termed a
@ -7483,7 +7512,7 @@ background delivery.
If specified, the
.i fallbackhost
acts like a very low priority MX
on every host.
on a host.
MX records will be looked up for this host,
unless the name is surrounded by square brackets.
This is intended to be used by sites with poor network connectivity.
@ -7493,12 +7522,11 @@ also go to the FallbackMXhost.
.ip FallBackSmartHost=\fIhostname\fP
If specified, the
.i FallBackSmartHost
will be used in a last-ditch effort for each host.
will be used in a last-ditch effort for a host.
This is intended to be used by sites with "fake internal DNS",
e.g., a company whose DNS accurately reflects the world
inside that company's domain but not outside.
.ip FastSplit
[no short name]
If set to a value greater than zero (the default is one),
it suppresses the MX lookups on addresses
when they are initially sorted, i.e., for the first delivery attempt.
@ -7538,7 +7566,6 @@ and then in
.i ~username /.forward
(but only if the first file does not exist).
.ip HeloName=\fIname\fP
[no short name]
Set the name to be used for HELO/EHLO (instead of $j).
.ip HelpFile=\fIfile\fP
[H]
@ -7555,7 +7582,6 @@ To avoid providing this information to a client specify an empty file.
If an outgoing mailer is marked as being expensive,
don't connect immediately.
.ip HostsFile=\fIpath\fP
[no short name]
The path to the hosts database,
normally
.q /etc/hosts .
@ -7573,7 +7599,6 @@ that is under the control of the system
.i gethostbyname (3)
routine.
.ip HostStatusDirectory=\fIpath\fP
[no short name]
The location of the long term host status information.
When set,
information about the status of hosts
@ -7592,16 +7617,15 @@ A suggested value for sites desiring persistent host status is
(i.e., a subdirectory of the queue directory).
.ip IgnoreDots
[i]
Ignore dots in incoming messages.
This is always disabled (that is, dots are always accepted)
when reading SMTP mail.
Do not treat leading dots in incoming messages in a special way,
e.g., as end of a message if it is the only character in a line.
This is always disabled when reading SMTP mail.
.ip InputMailFilters=\fIname,name,...\fP
A comma separated list of filters which determines which filters
(see the "X \*- Mail Filter (Milter) Definitions" section)
and the invocation sequence are contacted for incoming SMTP messages.
If none are set, no filters will be contacted.
.ip LDAPDefaultSpec=\fIspec\fP
[no short name]
Sets a default map specification for LDAP maps.
The value should only contain LDAP specific settings
such as
@ -7625,14 +7649,12 @@ The
.b \-M
flag is preferred.
.ip MailboxDatabase
[no short name]
Type of lookup to find information about local mailboxes,
defaults to ``pw'' which uses
.i getpwnam .
Other types can be introduced by adding them to the source code,
see libsm/mbdb.c for details.
.ip UseMSP
[no short name]
Use as mail submission program, i.e.,
allow group writable queue files
if the group is the same as that of a set-group-ID sendmail binary.
@ -7653,10 +7675,8 @@ This also requires that MATCHGECOS
be turned on during compilation.
This option is not recommended.
.ip MaxAliasRecursion=\fIN\fP
[no short name]
The maximum depth of alias recursion (default: 10).
.ip MaxDaemonChildren=\fIN\fP
[no short name]
If set,
.i sendmail
will refuse connections when it has more than
@ -7676,7 +7696,6 @@ other than background must be used.
If not set, there is no limit to the number of children --
that is, the system load average controls this.
.ip MaxHeadersLength=\fIN\fP
[no short name]
If set to a value greater than zero it specifies
the maximum length of the sum of all headers.
This can be used to prevent a denial of service attack.
@ -7689,7 +7708,6 @@ Messages that have been processed more than
times are assumed to be in a loop and are rejected.
Defaults to 25.
.ip MaxMessageSize=\fIN\fP
[no short name]
Specify the maximum message size
to be advertised in the ESMTP EHLO response.
Messages larger than this will be rejected.
@ -7698,7 +7716,6 @@ that value will be listed in the SIZE response,
otherwise SIZE is advertised in the ESMTP EHLO response
without a parameter.
.ip MaxMimeHeaderLength=\fIN[/M]\fP
[no short name]
Sets the maximum length of certain MIME header field values to
.i N
characters.
@ -7724,7 +7741,6 @@ for the number of
commands, see Section
"Measures against Denial of Service Attacks".
.ip MaxQueueChildren=\fIN\fP
[no short name]
When set, this limits the number of concurrent queue runner processes to
.i N.
This helps to control the amount of system resources used when processing
@ -7748,7 +7764,6 @@ imposed by
This discrepancy can be large if some queue runners have to wait
for a slow server and if short intervals are used.
.ip MaxQueueRunSize=\fIN\fP
[no short name]
The maximum number of jobs that will be processed
in a single queue run.
If not set, there is no limit on the size.
@ -7773,14 +7788,12 @@ then only
.b N
entries are printed per queue group.
.ip MaxRecipientsPerMessage=\fIN\fP
[no short name]
The maximum number of recipients that will be accepted per message
in an SMTP transaction.
Note: setting this too low can interfere with sending mail from
MUAs that use SMTP for initial submission.
If not set, there is no limit on the number of recipients per envelope.
.ip MaxRunnersPerQueue=\fIN\fP
[no short name]
This sets the default maximum number of queue runners for queue groups.
Up to
.i N
@ -7799,7 +7812,6 @@ even if I am in an alias expansion.
This option is deprecated
and will be removed from a future version.
.ip Milter
[no short name]
This option has several sub(sub)options.
The names of the suboptions are separated by dots.
At the first level the following options are available:
@ -7840,14 +7852,12 @@ gives a 452 response
to the MAIL command.
This invites the sender to try again later.
.ip MaxQueueAge=\fIage\fP
[no short name]
If this is set to a value greater than zero,
entries in the queue will be retried during a queue run
only if the individual retry time has been reached
which is doubled for each attempt.
The maximum retry time is limited by the specified value.
.ip MinQueueAge=\fIage\fP
[no short name]
Don't process any queued jobs
that have been in the queue less than the indicated time interval.
This is intended to allow you to get responsiveness
@ -7859,7 +7869,6 @@ This option is ignored for queue runs that select a subset
of the queue, i.e.,
.q \-q[!][I|R|S|Q][string]
.ip MustQuoteChars=\fIs\fP
[no short name]
Sets the list of characters that must be quoted if used in a full name
that is in the phrase part of a ``phrase <address>'' syntax.
The default is ``\'.''.
@ -7871,11 +7880,9 @@ O MustQuoteChars=.
.)b
Moreover, relaxed header signing should be used for DKIM signatures.
.ip NiceQueueRun
[no short name]
The priority of queue runners (nice(3)).
This value must be greater or equal zero.
.ip NoRecipientAction
[no short name]
The action to take when you receive a message that has no valid
recipient headers (To:, Cc:, Bcc:, or Apparently-To: \(em
the last included for back compatibility with old
@ -7933,7 +7940,6 @@ are always operators.
Note that OperatorChars must be set in the
configuration file before any rulesets.
.ip PidFile=\fIfilename\fP
[no short name]
Filename of the pid file.
(default is _PATH_SENDMAILPID).
The
@ -8029,7 +8035,6 @@ Authentication Warnings add warnings about various conditions
that may indicate attempts to spoof the mail system,
such as using a non-standard queue directory.
.ip ProcessTitlePrefix=\fIstring\fP
[no short name]
Prefix the process title shown on 'ps' listings with
.i string .
The
@ -8092,12 +8097,10 @@ Defaults to 8 multiplied by
the number of processors online on the system
(if that can be determined).
.ip QueueFileMode=\fImode\fP
[no short name]
Default permissions for queue files (octal).
If not set, sendmail uses 0600 unless its real
and effective uid are different in which case it uses 0644.
.ip QueueSortOrder=\fIalgorithm\fP
[no short name]
Sets the
.i algorithm
used for sorting the queue.
@ -8142,7 +8145,6 @@ Use that form instead of the
.q QueueTimeout
form.
.ip RandFile
[no short name]
Name of file containing random data or the name of the UNIX socket
if EGD is used.
A (required) prefix "egd:" or "file:" specifies the type.
@ -8191,7 +8193,6 @@ Notice: it might be necessary to apply the same (or similar) options to
.i submit.cf
too.
.ip RequiresDirfsync
[no short name]
This option can be used to override the compile time flag
.b REQUIRES_DIR_FSYNC
at runtime by setting it to
@ -8205,14 +8206,12 @@ it is enabled by default for Linux.
According to some information this flag is not needed
anymore for kernel 2.4.16 and newer.
.ip RrtImpliesDsn
[no short name]
If this option is set, a
.q Return-Receipt-To:
header causes the request of a DSN, which is sent to
the envelope sender as required by RFC 1891,
not to the address given in the header.
.ip RunAsUser=\fIuser\fP
[no short name]
The
.i user
parameter may be a user name
@ -8276,7 +8275,6 @@ Defaults to 12 multiplied by
the number of processors online on the system
(if that can be determined).
.ip RejectLogInterval=\fItimeout\fP
[no short name]
Log interval when refusing connections for this long
(default: 3h).
.ip RetryFactor=\fIfact\fP
@ -8292,7 +8290,6 @@ In most environments this should be positive,
since hosts that are down are all too often down for a long time.
Defaults to 90000.
.ip SafeFileEnvironment=\fIdir\fP
[no short name]
If this option is set,
.i sendmail
will do a
@ -8332,12 +8329,10 @@ will not return the DSN keyword in response to an EHLO
and will not do Delivery Status Notification processing as described in
RFC 1891.
.ip ServerCertFile
[no short name]
File containing the certificate of the server, i.e., this certificate
is used when sendmail acts as server
(used for STARTTLS).
.ip ServerKeyFile
[no short name]
File containing the private key belonging to the server certificate
(used for STARTTLS).
.ip ServerSSLOptions
@ -8357,7 +8352,6 @@ Options can be cleared by preceding them with a minus sign.
It is also possible to specify numerical values, e.g.,
.b -0x0010 .
.ip ServiceSwitchFile=\fIfilename\fP
[no short name]
If your host operating system has a service switch abstraction
(e.g., /etc/nsswitch.conf on Solaris
or /etc/svc.conf on Ultrix and DEC OSF/1)
@ -8397,7 +8391,6 @@ The default file is
Strip input to seven bits for compatibility with old systems.
This shouldn't be necessary.
.ip SharedMemoryKey
[no short name]
Key to use for shared memory segment;
if not set (or 0), shared memory will not be used.
If set to
@ -8417,7 +8410,6 @@ This allows for more efficient program execution, since only
one process needs to update the data instead of each individual
process gathering the data each time it is required.
.ip SharedMemoryKeyFile
[no short name]
If
.b SharedMemoryKey
is set to
@ -8425,13 +8417,11 @@ is set to
then the automatically selected shared memory key will be stored
in the specified file.
.ip SingleLineFromHeader
[no short name]
If set, From: lines that have embedded newlines are unwrapped
onto one line.
This is to get around a botch in Lotus Notes
that apparently cannot understand legally wrapped RFC 822 headers.
.ip SingleThreadDelivery
[no short name]
If set, a client machine will never try to open two SMTP connections
to a single server machine at the same time,
even in different processes.
@ -8532,7 +8522,6 @@ PostMilter is useful only when
is running as an SMTP server; in all other situations it
acts the same as True.
.ip TLSFallbacktoClear
[no short name]
If set,
.i sendmail
immediately tries an outbound connection again without STARTTLS
@ -8548,7 +8537,6 @@ Hence such requirements will cause an error on a retry without STARTTLS.
Therefore they should only trigger a temporary failure so the connection
is later on tried again.
.ip TLSSrvOptions
[no short name]
List of options for SMTP STARTTLS for the server
consisting of single characters
with intervening white space or commas.
@ -8587,7 +8575,6 @@ the TZ environment variable is cleared (so the system default is used);
if set but null, the user's TZ variable is used,
and if set and non-null the TZ variable is set to this value.
.ip TrustedUser=\fIuser\fP
[no short name]
The
.i user
parameter may be a user name
@ -8633,7 +8620,6 @@ Defaults to
Don't change this unless your system uses a different UNIX mailbox format
(very unlikely).
.ip UnsafeGroupWrites
[no short name]
If set (default),
:include: and .forward files that are group writable are considered
.q unsafe ,
@ -8645,7 +8631,6 @@ Note: use
.b DontBlameSendmail
instead; this option is deprecated.
.ip UseCompressedIPv6Addresses
[no short name]
If set, the compressed format of IPv6 addresses,
such as IPV6:::1, will be used,
instead of the uncompressed format,
@ -8699,7 +8684,6 @@ SMTP command with a suitable
.b PrivacyOptions
setting.
.ip XscriptFileBufferSize=\fIthreshold\fP
[no short name]
Set the
.i threshold ,
in bytes,
@ -9004,7 +8988,7 @@ For example, the rule
.ta 1.5i
R$\- ! $+ $: $(uucp $1 $@ $2 $: $2 @ $1 . UUCP $)
.)b
Looks up the UUCP name in a (user defined) UUCP map;
looks up the UUCP name in a (user defined) UUCP map;
if not found it turns it into
.q \&.UUCP
form.
@ -10226,7 +10210,7 @@ the new version of the DBM library
that allows multiple databases will be used.
If neither CDB, NDBM, nor NEWDB are set,
a much less efficient method of alias lookup is used.
.ip CWDB
.ip CDB
If set, use the cdb (tinycdb) package.
.ip NEWDB
If set, use the new database package from Berkeley (from 4.4BSD).
@ -11251,12 +11235,30 @@ as well as
{auth_authen} and {auth_author}.
.sh 2 "DANE"
.pp
Initial support for DANE (see RFC 7672 et.al.)
Support for DANE (see RFC 7672 et.al.)
is available if
.i sendmail
is compiled with the option
.b DANE .
Only TLSA RR 3-1-x (DANE-EE) is currently implemented.
If OpenSSL 1.1.1 or at least 3.0.0 are used,
then full DANE support for DANE-EE and DANE-TA
(as required by RFC 7672)
is available via the functions
provided by those OpenSSL versions
(run
.(b
sendmail -bt -d0.3 < /dev/null
.)b
and check that HAVE_SSL_CTX_dane_enable is in the output),
otherwise support for TLSA RR 3-1-x
is implemented directly in
.i sendmail .
Note: if OpenSSL functions related to DANE cause a failure,
then the macro
.b ${verify}
is set to
.b DANE_TEMP .
This also applies if TLS cannot be initialized at all.
The option
.(b
O DANE=true
@ -11270,8 +11272,10 @@ to
.(b
O ResolverOptions
.)b
This requires a (preferrably local)
validating DNS resolver which supports those options.
This requires a DNSSEC-validating recursive resolver
which supports those options.
The resolver must be reachable via a trusted connection,
hence it is best to run it locally.
If the client finds a usable TLSA RR and the check
succeeds the macro
@ -11281,9 +11285,8 @@ is set to
All non-DNS maps are considered
.i secure
just like DNS lookups with DNSSEC.
Be aware that the implementation might not handle all
error conditions as required by the RFCs.
Moreover, TLSA RRs are not looked up for some features,
Be aware that
TLSA RRs are not looked up for some features,
e.g.,
.i FallBackSmartHost .
.sh 2 "EAI"
@ -11943,6 +11946,8 @@ and
.ip Z
The original envelope id (from the ESMTP transaction).
For Deliver Status Notifications only.
.ip !
Information for Deliver-By SMTP extension.
.pp
As an example,
the following is a queue file sent to

View File

@ -117,7 +117,7 @@ typedef int (*db_get_func) __P((SMDB_DATABASE *db,
** key -- The key to use.
** data -- The data to store.
** flags -- put options:
** SMDBF_NO_OVERWRITE - Return an error if key alread
** SMDBF_NO_OVERWRITE - Return an error if key already
** exists.
**
** Returns:

View File

@ -118,6 +118,7 @@ extern bool filechanged __P((char *, int, struct stat *));
#define DBS_WORLDWRITABLEINCLUDEFILE 40
#define DBS_GROUPREADABLEKEYFILE 41
#define DBS_GROUPREADABLEAUTHINFOFILE 42
#define DBS_CERTOWNER 43
/* struct defining such things */
struct dbsval

View File

@ -473,8 +473,8 @@ typedef int pid_t;
# ifndef HASGETUSERSHELL
# define HASGETUSERSHELL 0 /* getusershell(3) causes core dumps pre-2.7 */
# endif
# if SOLARIS < 21200
# define SIGWAIT_TAKES_1_ARG 1 /* S12 moves to UNIX V7 semantic */
# if SOLARIS < 21140
# define SIGWAIT_TAKES_1_ARG 1 /* S11.4 moves to UNIX V7 semantic */
# endif
# else /* SOLARIS */
@ -1575,9 +1575,11 @@ extern void *malloc();
# if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,36)) && !defined(HASFCHMOD)
# define HASFCHMOD 1 /* fchmod(2) */
# endif
# if (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 19) && !defined(HAS_GETHOSTBYNAME2)
# define HAS_GETHOSTBYNAME2 1
# endif
# endif /* __linux__ */
/*
** DELL SVR4 Issue 2.2, and others
** From Kimmo Suominen <kim@grendel.lut.fi>

View File

@ -17,6 +17,7 @@
** before.
*/
#define SM_FD_CLR(fd, pfdset) FD_CLR(fd, pfdset)
#define SM_FD_SET(fd, pfdset) FD_SET(fd, pfdset)
#define SM_FD_ISSET(fd, pfdset) FD_ISSET(fd, pfdset)
#define SM_FD_SETSIZE FD_SETSIZE

View File

@ -89,4 +89,8 @@ typedef unsigned int SM_ATOMIC_UINT_T;
# define _FFR_8BITENVADDR 1
#endif
#if _FFR_HAPROXY && !defined(_FFR_XCNCT)
# define _FFR_XCNCT 1
#endif
#endif /* SM_GEN_H */

View File

@ -27,6 +27,7 @@ extern int xleni __P((const char *));
# if USE_EAI
extern bool asciistr __P((const char *));
extern bool asciinstr __P((const char *, size_t));
extern int uxtext_unquote __P((const char *, char *, int));
extern char *sm_lowercase __P((const char *));
extern bool utf8_valid __P((const char *, size_t));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016 Proofpoint, Inc. and its suppliers.
* Copyright (c) 2021 Proofpoint, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@ -10,13 +10,10 @@
#ifndef SM_NOTIFY_H
#define SM_NOTIFY_H
/* microseconds */
#define SM_MICROS 1000000L
int sm_notify_init __P((int));
int sm_notify_start __P((bool, int));
int sm_notify_stop __P((bool, int));
int sm_notify_rcv __P((char *, size_t, long));
int sm_notify_snd __P((char *, size_t));
#endif /* ! SM_MSG_H */
#endif /* ! SM_NOTIFY_H */

View File

@ -18,20 +18,6 @@
#define SM_OS_NAME "openbsd"
/*
** Temporary HACK for newer icu4c versions which include stdbool.h:
** pretend that it is already included
** otherwise compilation will break because bool is then
** redefined between the prototype declaration and
** the function definition, e.g.,
** lowercase.c: error: conflicting types for 'asciistr'
** ../../include/sm/ixlen.h:29:13: note: previous declaration is here
*/
#if USE_EAI && !SM_CONF_STDBOOL_H
# define _STDBOOL_H_ 1
#endif
#define SM_CONF_SYS_CDEFS_H 1
#ifndef SM_CONF_SHM
# define SM_CONF_SHM 1

View File

@ -163,6 +163,8 @@ extern void *
sm_rpool_malloc __P((
SM_RPOOL_T *_rpool,
size_t _size));
# define sm_rpool_malloc_tagged(rpool, size, file, line, group) sm_rpool_malloc(rpool, size)
# define sm_rpool_malloc_tagged_x(rpool, size, file, line, group) sm_rpool_malloc_x(rpool, size)
# endif /* SM_HEAP_CHECK */
#if DO_NOT_USE_STRCPY

View File

@ -15,6 +15,7 @@ the milter API.
Note: if you want to write a milter in Java, then see
http://sendmail-jilter.sourceforge.net/
+----------------+
| SECURITY HINTS |
+----------------+
@ -26,6 +27,7 @@ if really necessary. A milter should probably check first whether
it runs as root and refuse to start in that case. libmilter will
not unlink a socket when running as root.
+----------------------+
| CONFIGURATION MACROS |
+----------------------+
@ -36,6 +38,7 @@ features of the C compiler and standard C libraries.
SM_CONF_POLL
Set to 1 if poll(2) should be used instead of select(2).
+-------------------+
| BUILDING A FILTER |
+-------------------+

View File

@ -60,7 +60,7 @@ returns to <CODE>MESSAGE</CODE>.
For each of N connections
{
For each filter
egotiate MTA/milter capabilities/requirements (<A HREF="xxfi_negotiate.html">xxfi_negotiate</A>)
negotiate MTA/milter capabilities/requirements (<A HREF="xxfi_negotiate.html">xxfi_negotiate</A>)
For each filter
process connection (<A HREF="xxfi_connect.html">xxfi_connect</A>)
For each filter

View File

@ -76,13 +76,18 @@ By default, the following macros are valid in the given contexts:
<TR><TD>xxfi_eom</TD> <TD>msg_id</TD></TR>
</TABLE>
<P>
All macros stay in effect from the point they are received
until the end of the connection for the first two sets,
the end of the message for the third (xxfi_envfrom) and last (xxfi_eom),
and just for each recipient for xxfi_envrcpt.
All macros stay in effect from the point they are received until
<UL>
<LI>the end of the connection for the first two sets,
<LI>just for each recipient for xxfi_envrcpt.
<LI>and the end of the message for the rest.
</UL>
<P>
The macro list can be changed using the confMILTER_MACROS_* options in
sendmail.mc.
The macro list can be changed using
the confMILTER_MACROS_* options in sendmail.mc
or via the
<A HREF="smfi_setsymlist.html">smfi_setsymlist</A>
function.
The scopes of such macros will be determined by when they are set by sendmail.
For descriptions of macros' values,
please see the

View File

@ -45,7 +45,7 @@ body.
<TD>Opaque context structure.
</TD></TR>
<TR valign="top"><TD>bodyp</TD>
<TD>A pointer to the start of the new body data, which does not have to be null-terminated. If bodyp is NULL, it is treated as having length == 0. Body data should be in CR/LF form.
<TD>A pointer to the start of the new body data, which does not have to be null-terminated. If bodyp is NULL, it is treated as having length == 0. Body data should be in CRLF form.
</TD></TR>
<TR valign="top"><TD>bodylen</TD>
<TD>The number of data bytes pointed to by bodyp.

View File

@ -64,7 +64,7 @@ Hence even if a trailing '\0' is added, C string functions may still fail
to work as expected.
<LI>Since message bodies can be very large, defining xxfi_body can
significantly impact filter performance.
<LI>End-of-lines are represented as received from SMTP (normally CR/LF).
<LI>End-of-lines are represented as received from SMTP (normally CRLF).
<LI>Later filters will see body changes made by earlier ones.
<LI>Message bodies may be sent in multiple chunks, with one call to
xxfi_body per chunk.

View File

@ -48,8 +48,8 @@ Handle a message header.
<TD>Header field value.
The content of the header may include folded white space,
i.e., multiple lines with following white space
where lines are separated by LF (not CR/LF).
The trailing line terminator (CR/LF) is removed.
where lines are separated by LF (not CRLF).
The trailing line terminator (CRLF) is removed.
</TD></TR>
</TABLE>
</TD></TR>

View File

@ -60,32 +60,32 @@ typedef struct cmdfct_t cmdfct;
#define CI_MAIL 2
#define CI_RCPT 3
#define CI_DATA 4
#define CI_EOM 5
#define CI_EOH 6
#define CI_LAST CI_EOH
#define CI_EOH 5
#define CI_EOM 6
#define CI_LAST CI_EOM
#if CI_LAST < CI_DATA
# ERROR "do not compile with CI_LAST < CI_DATA"
# error "do not compile with CI_LAST < CI_DATA"
#endif
#if CI_LAST < CI_EOM
# ERROR "do not compile with CI_LAST < CI_EOM"
# error "do not compile with CI_LAST < CI_EOM"
#endif
#if CI_LAST < CI_EOH
# ERROR "do not compile with CI_LAST < CI_EOH"
# error "do not compile with CI_LAST < CI_EOH"
#endif
#if CI_LAST < CI_RCPT
# ERROR "do not compile with CI_LAST < CI_RCPT"
# error "do not compile with CI_LAST < CI_RCPT"
#endif
#if CI_LAST < CI_MAIL
# ERROR "do not compile with CI_LAST < CI_MAIL"
# error "do not compile with CI_LAST < CI_MAIL"
#endif
#if CI_LAST < CI_HELO
# ERROR "do not compile with CI_LAST < CI_HELO"
# error "do not compile with CI_LAST < CI_HELO"
#endif
#if CI_LAST < CI_CONN
# ERROR "do not compile with CI_LAST < CI_CONN"
# error "do not compile with CI_LAST < CI_CONN"
#endif
#if CI_LAST >= MAX_MACROS_ENTRIES
# ERROR "do not compile with CI_LAST >= MAX_MACROS_ENTRIES"
# error "do not compile with CI_LAST >= MAX_MACROS_ENTRIES"
#endif
/* function prototypes */
@ -111,7 +111,7 @@ static int dec_arg2 __P((char *, size_t, char **, char **));
static void mi_clr_symlist __P((SMFICTX_PTR));
#if _FFR_WORKERS_POOL
static bool mi_rd_socket_ready __P((int));
static bool mi_rd_socket_ready __P((int));
#endif
/* states */

View File

@ -45,7 +45,6 @@ dnl ? smcheck(`t-isprint', `compile-run')
smcheck(`t-ixlen', `compile')
smcheck(`t-ixlen.sh', `run')
smcheck(`t-streq', `compile')
smcheck(`t-utf8_valid', `compile')
smcheck(`t-streq.sh', `run')
divert(bldTARGETS_SECTION)
divert(0)

View File

@ -34,6 +34,7 @@ The programs are:
b-strcmp.c tests strcasecmp().
+----------------------+
| CONFIGURATION MACROS |
+----------------------+
@ -106,9 +107,6 @@ SM_CONF_SEM
SM_CONF_BROKEN_STRTOD
Set to 1 if your strtod() does not work properly.
SM_CONF_GETOPT
Set to 1 if your operating system does not include getopt(3).
SM_CONF_LDAP_INITIALIZE
Set to 1 if your LDAP client libraries include ldap_initialize(3).

View File

@ -101,7 +101,7 @@ main(argc, argv)
** the copy.
*/
(void) strlcpy(source,
" This is the longer string that will be used for catenation and copying for the the performace testing. The longer the string being catenated or copied the greater the difference in measureable performance\n",
" This is the longer string that will be used for catenation and copying for the the performance testing. The longer the string being catenated or copied the greater the difference in measureable performance\n",
SRC_SIZE - 1);
/* Run-time comments to the user */

View File

@ -350,7 +350,7 @@ of type SM_EXC_TYPE_T, which has the following members:
<dt><tt>"E"</tt>
<dd>The function could not complete its task because an error occurred.
(It might be useful to define subclasses of this category,
in which case our taxonony becomes a tree, and 'F' becomes
in which case our taxonomy becomes a tree, and 'F' becomes
a subclass of 'E'.)
<dt><tt>"J"</tt>

View File

@ -242,7 +242,7 @@ size_t SmHeapMaxTotal = 0;
*/
SM_DEBUG_T SmHeapLimit = SM_DEBUG_INITIALIZER("sm_heap_limit",
"@(#)$Debug: sm_heap_limit - max # of bytes permitted in heap $");
"@(#)$Debug: sm_heap_limit - max # of bytes permitted in heap $");
/*
** This is the data structure that keeps track of all currently

View File

@ -481,7 +481,7 @@ close file descriptors 0, 1 and 2).
Thus <tt>sm_io_open()</tt> should
never be called: the named file pointers should be used directly.
Calls to <b>stdio</b> are safe to make when using these three<b>sm_io</b>
file pointers though no code is shared between the two libaries.
file pointers though no code is shared between the two libraries.
However, the input and output between <i>sm_io</i> and <i>stdio</i> is
coordinated for these three file pointers: <i>smiostdin</i>,
<i>smiostdout</i> and <i>smiostderr</i> are layered on-top-of
@ -574,10 +574,12 @@ SM_FILE_T. The file pointer content (internal structure members) of an active
file should only be set and observed with the "info" functions.
The two exceptions to the above statement are the structure members
<i>cookie</i> and <i>ival</i>. <i>Cookie</i> is of type <tt>void *</tt>
while <i>ival</i> is of type <tt>int</tt>. These two structure members exist
specificly for your created file type to use. The <i>sm_io</i> functions
will not change or set these two structure members; only specific file type
will change or set these variables.
while <i>ival</i> is of type <tt>int</tt>.
These two structure members exist specifically
for your created file type to use.
The <i>sm_io</i> functions
will not change or set these two structure members;
only specific file type will change or set these variables.
</p>
<p>
For maintaining information privately about status for a file type the
@ -598,7 +600,7 @@ For the <i>cookie</i> to be passed to all members of a function type
cleanly the location of the cookie must assigned during
the call to open. The file type functions should not attempt to
maintain the <i>cookie</i> internally since the file type may have
serveral instances (file pointers).
several instances (file pointers).
</p>
<p>
The SM_FILE_T's member <i>ival</i> may be used in a manner similar to

View File

@ -36,6 +36,8 @@ SM_DEBUG_T SmLDAPTrace = SM_DEBUG_INITIALIZER("sm_trace_ldap",
static bool sm_ldap_has_objectclass __P((SM_LDAP_STRUCT *, LDAPMessage *, char *));
static SM_LDAP_RECURSE_ENTRY *sm_ldap_add_recurse __P((SM_LDAP_RECURSE_LIST **, char *, int, SM_RPOOL_T *));
static char *sm_ldap_geterror __P((LDAP *));
/*
** SM_LDAP_CLEAR -- set default values for SM_LDAP_STRUCT
**
@ -49,10 +51,10 @@ static SM_LDAP_RECURSE_ENTRY *sm_ldap_add_recurse __P((SM_LDAP_RECURSE_LIST **,
# if _FFR_LDAP_VERSION
# if defined(LDAP_VERSION_MAX) && _FFR_LDAP_VERSION > LDAP_VERSION_MAX
# ERROR "_FFR_LDAP_VERSION > LDAP_VERSION_MAX"
# error "_FFR_LDAP_VERSION > LDAP_VERSION_MAX"
# endif
# if defined(LDAP_VERSION_MIN) && _FFR_LDAP_VERSION < LDAP_VERSION_MIN
# ERROR "_FFR_LDAP_VERSION < LDAP_VERSION_MAX"
# error "_FFR_LDAP_VERSION < LDAP_VERSION_MAX"
# endif
# define SM_LDAP_VERSION_DEFAULT _FFR_LDAP_VERSION
# else /* _FFR_LDAP_VERSION */
@ -79,6 +81,9 @@ sm_ldap_clear(lmap)
lmap->ldap_options = 0;
# endif
lmap->ldap_attrsep = '\0';
# if LDAP_NETWORK_TIMEOUT
lmap->ldap_networktmo = 0;
# endif
lmap->ldap_binddn = NULL;
lmap->ldap_secret = NULL;
lmap->ldap_method = LDAP_AUTH_SIMPLE;
@ -229,6 +234,23 @@ sm_ldap_setopts(ld, lmap)
# ifdef LDAP_OPT_RESTART
ldap_set_option(ld, LDAP_OPT_RESTART, LDAP_OPT_ON);
# endif
# if _FFR_TESTS
if (sm_debug_active(&SmLDAPTrace, 101))
{
char *cert;
char buf[PATH_MAX];
cert = getcwd(buf, sizeof(buf));
if (NULL != cert)
{
int r;
(void) sm_strlcat(buf, "/ldaps.pem", sizeof(buf));
r = ldap_set_option(ld, LDAP_OPT_X_TLS_CACERTFILE, cert);
sm_dprintf("LDAP_OPT_X_TLS_CACERTFILE(%s)=%d\n", cert, r);
}
}
# endif /* _FFR_TESTS */
# else /* USE_LDAP_SET_OPTION */
/* From here on in we can use ldap internal timelimits */
@ -305,6 +327,7 @@ sm_ldap_start(name, lmap)
{
int save_errno = 0;
char *id;
char *errmsg;
# if !USE_LDAP_INIT || !LDAP_NETWORK_TIMEOUT
SM_EVENT *ev = NULL;
# endif
@ -312,6 +335,7 @@ sm_ldap_start(name, lmap)
struct timeval tmo;
int msgid, err, r;
errmsg = NULL;
if (sm_debug_active(&SmLDAPTrace, 2))
sm_dprintf("ldapmap_start(%s)\n", name == NULL ? "" : name);
@ -439,37 +463,66 @@ sm_ldap_start(name, lmap)
lmap->ldap_method);
save_errno = errno;
if (sm_debug_active(&SmLDAPTrace, 9))
sm_dprintf("ldap_bind(%s)=%d, errno=%d, tmo=%ld\n",
{
errmsg = sm_ldap_geterror(ld);
sm_dprintf("ldap_bind(%s)=%d, errno=%d, ldaperr=%d, ld_error=%s, tmo=%lld\n",
lmap->ldap_uri, msgid, save_errno,
(long) tmo.tv_sec);
sm_ldap_geterrno(ld), errmsg, (long long) tmo.tv_sec);
if (NULL != errmsg)
{
ldap_memfree(errmsg);
errmsg = NULL;
}
}
if (-1 == msgid)
{
r = -1;
err = sm_ldap_geterrno(ld);
if (LDAP_SUCCESS != err)
save_errno = err + E_LDAPBASE;
goto fail;
}
errno = 0;
r = ldap_result(ld, msgid, LDAP_MSG_ALL,
tmo.tv_sec == 0 ? NULL : &(tmo), &(lmap->ldap_res));
save_errno = errno;
if (sm_debug_active(&SmLDAPTrace, 9))
sm_dprintf("ldap_result(%s)=%d, errno=%d\n", lmap->ldap_uri, r, errno);
{
errmsg = sm_ldap_geterror(ld);
sm_dprintf("ldap_result(%s)=%d, errno=%d, ldaperr=%d, ld_error=%s\n",
lmap->ldap_uri, r, errno,
sm_ldap_geterrno(ld), errmsg);
if (NULL != errmsg)
{
ldap_memfree(errmsg);
errmsg = NULL;
}
}
if (-1 == r)
{
err = sm_ldap_geterrno(ld);
if (LDAP_SUCCESS != err)
save_errno = err + E_LDAPBASE;
goto fail;
}
if (0 == r)
{
save_errno = ETIMEDOUT;
r = -1;
goto fail;
}
r = ldap_parse_result(ld, lmap->ldap_res, &err, NULL, NULL, NULL, NULL,
1);
r = ldap_parse_result(ld, lmap->ldap_res, &err, NULL, &errmsg, NULL,
NULL, 1);
save_errno = errno;
if (sm_debug_active(&SmLDAPTrace, 9))
sm_dprintf("ldap_parse_result(%s)=%d, err=%d\n", lmap->ldap_uri, r, err);
sm_dprintf("ldap_parse_result(%s)=%d, err=%d, errmsg=%s\n",
lmap->ldap_uri, r, err, errmsg);
if (r != LDAP_SUCCESS)
goto fail;
if (err != LDAP_SUCCESS)
{
r = -1;
r = err;
goto fail;
}
@ -487,12 +540,22 @@ sm_ldap_start(name, lmap)
errno = save_errno;
else
errno = r + E_LDAPBASE;
if (NULL != errmsg)
{
ldap_memfree(errmsg);
errmsg = NULL;
}
return false;
}
/* Save PID to make sure only this PID closes the LDAP connection */
lmap->ldap_pid = getpid();
lmap->ldap_ld = ld;
if (NULL != errmsg)
{
ldap_memfree(errmsg);
errmsg = NULL;
}
return true;
}
@ -536,7 +599,7 @@ sm_ldap_search_m(lmap, argv)
if (lmap->ldap_multi_args)
{
# if SM_LDAP_ARGS < 10
# ERROR _SM_LDAP_ARGS must be 10
# error _SM_LDAP_ARGS must be 10
# endif
if (q[1] == 's')
key = argv[0];
@ -1559,7 +1622,6 @@ sm_ldap_results(lmap, msgid, flags, delim, rpool, result,
**
** Returns:
** None.
**
*/
void
@ -1574,6 +1636,7 @@ sm_ldap_close(lmap)
lmap->ldap_ld = NULL;
lmap->ldap_pid = 0;
}
/*
** SM_LDAP_GETERRNO -- get ldap errno value
**
@ -1582,7 +1645,6 @@ sm_ldap_close(lmap)
**
** Returns:
** LDAP errno.
**
*/
int
@ -1614,4 +1676,28 @@ sm_ldap_geterrno(ld)
# endif /* defined(LDAP_VERSION_MAX) && LDAP_VERSION_MAX >= 3 */
return err;
}
/*
** SM_LDAP_GETERROR -- get ldap error value
**
** Parameters:
** ld -- LDAP session handle
**
** Returns:
** LDAP error
*/
static char *
sm_ldap_geterror(ld)
LDAP *ld;
{
char *error = NULL;
# if defined(LDAP_OPT_DIAGNOSTIC_MESSAGE)
(void) ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, &error);
# endif
return error;
}
#endif /* LDAPMAP */

View File

@ -15,10 +15,11 @@
#include <sm/string.h>
#include <sm/heap.h>
#if USE_EAI
# include <sm/ixlen.h>
# include <sm/limits.h>
# include <unicode/ucasemap.h>
# include <unicode/ustring.h>
# include <unicode/uchar.h>
# include <sm/ixlen.h>
/*
** ASCIISTR -- check whether a string is printable ASCII
@ -42,6 +43,38 @@ asciistr(str)
str++;
return ch == '\0';
}
/*
** ASCIINSTR -- check whether a string is printable ASCII up to len
**
** Parameters:
** str -- string
** len -- length to check
**
** Returns:
** TRUE iff printable ASCII
*/
bool
asciinstr(str, len)
const char *str;
size_t len;
{
unsigned char ch;
int n;
if (str == NULL)
return true;
SM_REQUIRE(len < INT_MAX);
n = 0;
while (n < len && (ch = (unsigned char)*str) != '\0'
&& ch >= 32 && ch < 127)
{
n++;
str++;
}
return n == len || ch == '\0';
}
#endif /* USE_EAI */
/*

View File

@ -314,7 +314,7 @@ sendmail_mpe_getpwnam(name)
/*
** SENDMAIL_MPE_GETPWUID -- shadow function for getpwuid()
**
** Initializes the uninitalized fields in the passwd struct.
** Initializes the uninitialized fields in the passwd struct.
**
** Parameters:
** uid -- uid to obtain passwd data for

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016 Proofpoint, Inc. and its suppliers.
* Copyright (c) 2020 Proofpoint, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@ -10,11 +10,12 @@
#include <sm/gen.h>
#if _FFR_DMTRIGGER
#if _FFR_DMTRIGGER && _FFR_NOTIFY < 2
#include <sm/conf.h> /* FDSET_CAST */
#include <sm/fdset.h>
#include <sm/assert.h>
#include <sm/notify.h>
#include "notify.h"
#include <sm/time.h>
#include <sm/string.h>
@ -28,12 +29,6 @@
#include <fcntl.h>
#include <string.h> /* for memset() */
#if SM_NOTIFY_DEBUG
#define SM_DBG(p) fprintf p
#else
#define SM_DBG(p)
#endif
static int Notifypipe[2];
#define NotifyRDpipe Notifypipe[0]
#define NotifyWRpipe Notifypipe[1]
@ -129,9 +124,6 @@ sm_notify_stop(owner, flags)
** <0: -errno
*/
#define MAX_NETSTR 1024
#define NETSTRPRE 5
int
sm_notify_snd(buf, buflen)
char *buf;
@ -152,7 +144,7 @@ sm_notify_snd(buf, buflen)
len = sm_snprintf(netstr, sizeof(netstr), "%04d:%s,", (int)buflen, buf);
r = write(NotifyWRpipe, netstr, len);
save_errno = errno;
SM_DBG((stderr, "write=%d, fd=%d, e=%d\n", r, NotifyWRpipe, save_errno));
SM_DBG((stderr, "pid=%ld, write=%d, fd=%d, e=%d\n", (long)getpid(), r, NotifyWRpipe, save_errno));
return r >= 0 ? 0 : -save_errno;
}
@ -165,7 +157,8 @@ sm_notify_snd(buf, buflen)
** tmo -- timeout (micro seconds)
**
** Returns:
** 0: success
** 0: EOF (XXX need to provide info about client)
** >0: length of received data
** <0: -errno
*/
@ -186,55 +179,14 @@ sm_notify_rcv(buf, buflen, tmo)
return -EINVAL;
FD_ZERO(&readfds);
SM_FD_SET(NotifyRDpipe, &readfds);
if (tmo < 0)
tval = NULL;
else
{
timeout.tv_sec = (long) (tmo / SM_MICROS);
timeout.tv_usec = tmo % SM_MICROS;
tval = &timeout;
}
SM_MICROS2TVAL(tmo, tval, timeout);
do {
r = select(NotifyRDpipe + 1, FDSET_CAST &readfds, NULL, NULL, tval);
save_errno = errno;
SM_DBG((stderr, "select=%d, fd=%d, e=%d\n", r, NotifyRDpipe, save_errno));
SM_DBG((stderr, "pid=%ld, select=%d, fd=%d, e=%d\n", (long)getpid(), r, NotifyRDpipe, save_errno));
} while (r < 0 && save_errno == EINTR);
if (r <= 0)
{
SM_DBG((stderr, "select=%d, e=%d\n", r, save_errno));
return -ETIMEDOUT;
}
/* bogus... need to check again? */
if (!FD_ISSET(NotifyRDpipe, &readfds))
return -ETIMEDOUT;
r = read(NotifyRDpipe, buf, NETSTRPRE);
if (NETSTRPRE != r)
return -1; /* ??? */
if (sm_io_sscanf(buf, "%4u:", &len) != 1)
return -EINVAL; /* ??? */
if (len >= MAX_NETSTR)
return -E2BIG; /* ??? */
if (len >= buflen - 1)
return -E2BIG; /* ??? */
if (len <= 0)
return -EINVAL; /* ??? */
r = read(NotifyRDpipe, buf, len + 1);
save_errno = errno;
SM_DBG((stderr, "read=%d, e=%d\n", r, save_errno));
if (r == 0)
return -1; /* ??? */
if (r < 0)
return -save_errno;
if (len + 1 != r)
return -1; /* ??? */
if (buf[len] != ',')
return -EINVAL; /* ??? */
buf[len] = '\0';
return r;
RDNETSTR(r, NotifyRDpipe, (void)0);
}
#endif /* _FFR_DMTRIGGER */
#endif /* _FFR_DMTRIGGER && _FFR_NOTIFY < 2 */

View File

@ -0,0 +1,111 @@
/*
* Copyright (c) 2021 Proofpoint, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#ifndef LIBSM_NOTIFY_H
#define LIBSM_NOTIFY_H
#if SM_NOTIFY_DEBUG
#define SM_DBG(p) fprintf p
#else
#define SM_DBG(p)
#endif
/* microseconds */
#define SM_MICROS 1000000L
#define SM_MICROS2TVAL(tmo, tval, timeout) \
do \
{ \
if (tmo < 0) \
tval = NULL; \
else \
{ \
timeout.tv_sec = (long) (tmo / SM_MICROS); \
timeout.tv_usec = tmo % SM_MICROS; \
tval = &timeout; \
} \
} while (0)
#define MAX_NETSTR 1024
#define NETSTRPRE 5
/* flow through code, be careful how to use! */
#define RDNETSTR(rc, fd, SM_NOTIFY_EOF) \
if ((rc) <= 0) \
{ \
SM_DBG((stderr, "pid=%ld, select=%d, e=%d\n", (long)getpid(), (rc), save_errno)); \
return -ETIMEDOUT; \
} \
\
/* bogus... need to check again? */ \
if (!FD_ISSET(fd, &readfds)) \
{ \
SM_DBG((stderr, "pid=%ld, fd=%d, isset=false\n", (long)getpid(), fd)); \
return -ETIMEDOUT; \
} \
r = read(fd, buf, NETSTRPRE); \
if (0 == r) \
{ \
SM_DBG((stderr, "pid=%ld, fd=%d, read1=EOF, e=%d\n", (long)getpid(), fd, errno)); \
SM_NOTIFY_EOF; \
return r; \
} \
if (NETSTRPRE != r) \
{ \
SM_DBG((stderr, "pid=%ld, fd=%d, read1=%d, e=%d\n", (long)getpid(), fd, r, errno)); \
return -1; /* ??? */ \
} \
\
if (sm_io_sscanf(buf, "%4u:", &len) != 1) \
{ \
SM_DBG((stderr, "pid=%ld, scanf, e=%d\n", (long)getpid(), errno)); \
return -EINVAL; /* ??? */ \
} \
if (len >= MAX_NETSTR) \
{ \
SM_DBG((stderr, "pid=%ld, 1: len=%d\n", (long)getpid(), len)); \
return -E2BIG; /* ??? */ \
} \
if (len >= buflen - 1) \
{ \
SM_DBG((stderr, "pid=%ld, 2: len=%d\n", (long)getpid(), len)); \
return -E2BIG; /* ??? */ \
} \
if (len <= 0) \
{ \
SM_DBG((stderr, "pid=%ld, 3: len=%d\n", (long)getpid(), len)); \
return -EINVAL; /* ??? */ \
} \
r = read(fd, buf, len + 1); \
save_errno = errno; \
SM_DBG((stderr, "pid=%ld, fd=%d, read=%d, len=%d, e=%d\n", (long)getpid(), fd, r, len+1, save_errno)); \
if (r == 0) \
{ \
SM_DBG((stderr, "pid=%ld, fd=%d, read2=%d, e=%d\n", (long)getpid(), fd, r, save_errno)); \
return -1; /* ??? */ \
} \
if (r < 0) \
{ \
SM_DBG((stderr, "pid=%ld, fd=%d, read3=%d, e=%d\n", (long)getpid(), fd, r, save_errno)); \
return -save_errno; \
} \
if (len + 1 != r) \
{ \
SM_DBG((stderr, "pid=%ld, fd=%d, read4=%d, len=%d\n", (long)getpid(), fd, r, len)); \
return -1; /* ??? */ \
} \
if (buf[len] != ',') \
{ \
SM_DBG((stderr, "pid=%ld, fd=%d, read5=%d, f=%d\n", (long)getpid(), fd, r, buf[len])); \
return -EINVAL; /* ??? */ \
} \
buf[len] = '\0'; \
return r
#endif /* ! LIBSM_MSG_H */

View File

@ -25,7 +25,7 @@ SM_RCSID("@(#)$Id: rewind.c,v 1.19 2013-11-22 20:51:43 ca Exp $")
** Seeks the file to the beginning and clears any outstanding errors.
**
** Parameters:
** fp -- the flie pointer for rewind
** fp -- the file pointer for rewind
** timeout -- time to complete the rewind
**
** Returns:

View File

@ -17,6 +17,7 @@ SM_RCSID("@(#)$Id: setvbuf.c,v 1.33 2013-11-22 20:51:43 ca Exp $")
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sm/limits.h>
#include <sm/io.h>
#include <sm/heap.h>
#include <sm/assert.h>
@ -67,7 +68,7 @@ sm_io_setvbuf(fp, timeout, buf, mode, size)
if (mode != SM_IO_NBF)
if ((mode != SM_IO_FBF && mode != SM_IO_LBF &&
mode != SM_IO_NOW) || (int) size < 0)
mode != SM_IO_NOW) || size > INT_MAX)
return SM_IO_EOF;
/*

View File

@ -162,7 +162,7 @@ sm_stdwrite(fp, buf, n)
/*
** SM_STDSEEK -- set the file offset position
**
** Parmeters:
** Parameters:
** fp -- file pointer to position
** offset -- how far to position from "base" (set by 'whence')
** whence -- indicates where the "base" of the 'offset' to start

View File

@ -17,7 +17,7 @@
#include <sm/ixlen.h>
/*
** SM_STRCASEEQ -- are two strings equal (case-insenstive)?
** SM_STRCASEEQ -- are two strings equal (case-insensitive)?
**
** Parameters:
** s1 -- string
@ -63,7 +63,7 @@ sm_strcaseeq(s1, s2)
}
/*
** SM_STRNCASEEQ -- are two strings (up to a length) equal (case-insenstive)?
** SM_STRNCASEEQ -- are two strings (up to a length) equal (case-insensitive)?
**
** Parameters:
** s1 -- string
@ -86,13 +86,13 @@ sm_strncaseeq(s1, s2, n)
if (0 == n)
return true;
if (asciistr(s1))
if (asciinstr(s1, n))
{
if (!asciistr(s2))
if (!asciinstr(s2, n))
return false;
return (sm_strncasecmp(s1, s2, n) == 0);
}
if (asciistr(s2))
if (asciinstr(s2, n))
return false;
l1 = sm_lowercase(s1);
if (l1 != s1)
@ -104,7 +104,7 @@ sm_strncaseeq(s1, s2, n)
f1 = NULL;
l2 = sm_lowercase(s2);
while (*l1 == *l2 && '\0' != *l1 && n-- > 0)
while (*l1 == *l2 && '\0' != *l1 && --n > 0)
l1++, l2++;
same = *l1 == *l2;

View File

@ -19,6 +19,7 @@ SM_IDSTR(id, "@(#)$Id: t-qic.c,v 1.10 2013-11-22 20:51:43 ca Exp $")
#if _FFR_8BITENVADDR
extern bool SmTestVerbose;
static int Verbose = 0;
static void
chkilenx(str, len)
@ -30,10 +31,41 @@ chkilenx(str, len)
xlen = ilenx(str);
SM_TEST(len == xlen);
if (len != xlen)
fprintf(stderr, "str=\"%s\", len=%d, excpected=%d\n",
fprintf(stderr, "str=\"%s\", len=%d, expected=%d\n",
str, xlen, len);
}
static void
chkilen(str)
char *str;
{
char *obp;
int outlen, leni, lenx, ilen;
char line_in[1024];
XLENDECL
lenx = strlen(str);
sm_strlcpy(line_in, str, sizeof(line_in));
obp = quote_internal_chars(str, NULL, &outlen, NULL);
leni = strlen(obp);
for (ilen = 0; *obp != '\0'; obp++, ilen++)
{
XLEN(*obp);
}
if (Verbose)
fprintf(stderr, "str=\"%s\", ilen=%d, xlen=%d\n",
str, ilen, xlen);
SM_TEST(ilen == leni);
if (ilen != leni)
fprintf(stderr, "str=\"%s\", ilen=%d, leni=%d\n",
str, ilen, leni);
SM_TEST(xlen == lenx);
if (xlen != lenx)
fprintf(stderr, "str=\"%s\", xlen=%d, lenx=%d\n",
str, xlen, lenx);
}
static void
chkxleni(str, len)
const char *str;
@ -44,7 +76,7 @@ chkxleni(str, len)
ilen = xleni(str);
SM_TEST(len == ilen);
if (len != ilen)
fprintf(stderr, "str=\"%s\", len=%d, excpected=%d\n",
fprintf(stderr, "str=\"%s\", len=%d, expected=%d\n",
str, ilen, len);
}
@ -64,18 +96,26 @@ main(argc, argv)
char *argv[];
{
int o, len;
bool x;
bool x, both;
char line[1024];
x = false;
while ((o = getopt(argc, argv, "x")) != -1)
x = both = false;
while ((o = getopt(argc, argv, "bxV")) != -1)
{
switch ((char) o)
{
case 'b':
both = true;
break;
case 'x':
x = true;
break;
case 'V':
Verbose++;
break;
default:
usage(argv[0]);
exit(1);
@ -84,6 +124,12 @@ main(argc, argv)
sm_test_begin(argc, argv, "test ilenx");
if (both)
{
while (fscanf(stdin, "%s\n", line) == 1)
chkilen(line);
return sm_test_end();
}
while (fscanf(stdin, "%d:%s\n", &len, line) == 2)
{
if (x)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016 Proofpoint, Inc. and its suppliers.
* Copyright (c) 2020 Proofpoint, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@ -8,7 +8,6 @@
*/
#include <sm/gen.h>
#include <stdio.h>
#if _FFR_DMTRIGGER || _FFR_NOTIFY
@ -20,23 +19,32 @@
# include <sm/test.h>
# include <sm/notify.h>
# include <sm/conf.h>
# include "notify.h"
static int Verbose = 0;
#define MAX_CHILDREN 256
#define MAX_MSGS 1024
static pid_t pids[MAX_CHILDREN];
static char msgs[MAX_CHILDREN][MAX_MSGS];
/*
** NOTIFY_WR -- test of notify feature
** NOTIFY_WR -- test of notify write feature
**
** Parameters:
** pid -- pid of process
** nmsgs -- number of messages to write
**
** Returns:
** 0 on success
** >=0 on success
** < 0 on failure
*/
static int
notify_wr(pid)
notify_wr(pid, nmsgs)
pid_t pid;
int nmsgs;
{
int r;
int r, i;
size_t len;
char buf[64];
#define TSTSTR "qf0001"
@ -48,16 +56,38 @@ notify_wr(pid)
return -1;
}
len = sm_snprintf(buf, sizeof(buf), "%s-%ld", TSTSTR, (long) pid);
r = sm_notify_snd(buf, len);
SM_TEST(r >= 0);
for (i = 0; i < nmsgs; i++)
{
len = sm_snprintf(buf, sizeof(buf), "%s-%ld_%d", TSTSTR,
(long) pid, i);
r = sm_notify_snd(buf, len);
SM_TEST(r >= 0);
}
return r;
}
static int
validpid(nproc, cpid)
int nproc;
pid_t cpid;
{
int i;
for (i = 0; i < nproc; i++)
if (cpid == pids[i])
return i;
if (Verbose > 0)
fprintf(stderr, "pid=%ld not found, nproc=%d\n",
(long) cpid, nproc);
return -1;
}
/*
** NOTIFY_RD -- test of notify feature
** NOTIFY_RD -- test of notify read feature
**
** Parameters:
** nproc -- number of processes started
** nmsgs -- number of messages to read for each process
**
** Returns:
** 0 on success
@ -65,11 +95,13 @@ notify_wr(pid)
*/
static int
notify_rd(nproc)
notify_rd(nproc, nmsgs)
int nproc;
int nmsgs;
{
int r, i;
char buf[64];
int r, i, pidx;
long cpid;
char buf[64], *p;
#define TSTSTR "qf0001"
r = sm_notify_start(true, 0);
@ -79,21 +111,52 @@ notify_rd(nproc)
return -1;
}
for (i = 0; i < nproc; i++)
for (i = 0; i < nmsgs * nproc; i++)
{
r = sm_notify_rcv(buf, sizeof(buf), 5 * SM_MICROS);
SM_TEST(r >= 0);
do
{
r = sm_notify_rcv(buf, sizeof(buf), 5 * SM_MICROS);
SM_TEST(r >= 0);
} while (0 == r);
if (r < 0)
{
fprintf(stderr, "rcv=%d\n", r);
fprintf(stderr, "pid=%ld, rcv=%d, i=%d\n",
(long)getpid(), r, i);
return r;
}
if (r > 0 && r < sizeof(buf))
buf[r] = '\0';
buf[sizeof(buf) - 1] = '\0';
if (Verbose > 0)
fprintf(stderr, "pid=%ld, buf=\"%s\", i=%d\n",
(long)getpid(), buf, i);
SM_TEST(strncmp(buf, TSTSTR, sizeof(TSTSTR) - 1) == 0);
SM_TEST(r > sizeof(TSTSTR));
fprintf(stderr, "buf=\"%s\"\n", buf);
r = sscanf(buf + sizeof(TSTSTR), "%ld", &cpid);
SM_TEST(1 == r);
pidx = validpid(nproc, (pid_t)cpid);
SM_TEST(pidx >= 0);
SM_TEST(pidx < nproc);
p = strchr(buf, '_');
SM_TEST(NULL != p);
if (NULL != p && pidx < nproc && pidx >= 0)
{
int n;
r = sscanf(p + 1, "%d", &n);
SM_TEST(1 == r);
SM_TEST(n >= 0);
SM_TEST(n < nmsgs);
if (1 == r && n < nmsgs && n >= 0)
{
SM_TEST('\0' == msgs[pidx][n]);
msgs[pidx][n] = 'f';
}
}
}
return 0;
}
@ -106,27 +169,53 @@ main(argc, argv)
int i;
int r = 0;
int nproc = 1;
int nmsgs = 1;
pid_t pid;
# define OPTIONS "p:"
# define OPTIONS "n:p:V"
while ((i = getopt(argc, argv, OPTIONS)) != -1)
{
switch ((char) i)
{
case 'n':
nmsgs = atoi(optarg);
if (nmsgs < 1)
{
errno = EINVAL;
fprintf(stderr, "-%c: must be >0\n", (char) i);
return 1;
}
if (nmsgs >= MAX_MSGS)
{
errno = EINVAL;
fprintf(stderr, "-%c: must be <%d\n", (char) i, MAX_MSGS);
return 1;
}
break;
case 'p':
nproc = atoi(optarg);
if (nproc < 1)
{
errno = EINVAL;
perror("-p: must be >0\n");
return r;
fprintf(stderr, "-%c: must be >0\n", (char) i);
return 1;
}
if (nproc >= MAX_CHILDREN)
{
errno = EINVAL;
fprintf(stderr, "-%c: must be <%d\n", (char) i, MAX_CHILDREN);
return 1;
}
break;
case 'V':
++Verbose;
break;
default:
break;
}
}
memset(msgs, '\0', sizeof(msgs));
sm_test_begin(argc, argv, "test notify");
r = sm_notify_init(0);
SM_TEST(r >= 0);
@ -149,12 +238,14 @@ main(argc, argv)
{
/* give the parent the chance to set up data */
sleep(1);
r = notify_wr(getpid());
r = notify_wr(getpid(), nmsgs);
break;
}
if (pid > 0)
pids[i] = pid;
}
if (pid > 0)
r = notify_rd(nproc);
r = notify_rd(nproc, nmsgs);
SM_TEST(r >= 0);
return sm_test_end();
}
@ -164,7 +255,7 @@ main(argc, argv)
int argc;
char *argv[];
{
printf("SKIPPED: no _FFR_DMTRIGGER\n");
printf("SKIPPED: no _FFR_DMTRIGGER || _FFR_NOTIFY\n");
return 0;
}
#endif /* _FFR_DMTRIGGER */
#endif /* _FFR_DMTRIGGER || _FFR_NOTIFY */

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006 Proofpoint, Inc. and its suppliers.
* Copyright (c) 2006, 2023 Proofpoint, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
@ -19,7 +19,6 @@ SM_IDSTR(id, "@(#)$Id: t-qic.c,v 1.10 2013-11-22 20:51:43 ca Exp $")
extern bool SmTestVerbose;
void
show_diff(s1, s2)
const char *s1;
@ -107,6 +106,8 @@ main(argc, argv)
int i, los, cmp, mode;
sm_qic_T inout[] = {
{ "", "", 0 }
, { "\t", "\t", 0 }
, { "\tuser", "\tuser", 0 }
, { "abcdef", "abcdef", 0 }
, { "01234567890123456789", "01234567890123456789", 0 }
, { "\\", "\\", 0 }
@ -242,5 +243,16 @@ main(argc, argv)
}
}
los = -1;
obp = quote_internal_chars(NULL, NULL, &los, NULL);
SM_TEST(NULL == obp);
SM_TEST(-1 == los);
sm_strlcpy(line_in, "nothing", sizeof(line_in));
los = -123;
obp = quote_internal_chars(line_in, NULL, &los, NULL);
SM_TEST(NULL != obp);
SM_TEST(los > 0);
return sm_test_end();
}

View File

@ -17,7 +17,6 @@ SM_IDSTR(id, "@(#)$Id: t-qic.c,v 1.10 2013-11-22 20:51:43 ca Exp $")
#include <sm/ixlen.h>
#include <sm/test.h>
#if _FFR_8BITENVADDR
extern bool SmTestVerbose;
static int
@ -37,6 +36,32 @@ usage(prg)
fprintf(stderr, "options:\n");
}
static void
hack(str)
char *str;
{
char c;
/* replace just one \x char */
while ((c = *str++) != '\0')
{
if (c != '\\')
continue;
c = *str;
switch (c)
{
case 'n': c ='\n'; break;
case 't': c ='\t'; break;
case 'r': c ='\r'; break;
/* case 'X': c ='\X'; break; */
default: c ='\0'; break;
}
*(str - 1) = c;
*str = '\0';
break;
}
}
int
main(argc, argv)
int argc;
@ -61,17 +86,14 @@ main(argc, argv)
while (fscanf(stdin, "%d:%s\n", &len, s1) == 2 &&
fscanf(stdin, "%d:%s\n", &o,s2) == 2)
{
int r;
hack(s1);
hack(s2);
SM_TEST(tstrncaseeq(s1, s2, len) == o);
if ((r = tstrncaseeq(s1, s2, len)) != o)
fprintf(stderr, "\"%s\"\n\"%s\"\n%d!=%d\n", s1, s2, o, r);
}
return sm_test_end();
}
#else /* _FFR_8BITENVADDR */
int
main(argc, argv)
int argc;
char *argv[];
{
return 0;
}
#endif /* _FFR_8BITENVADDR */

View File

@ -12,6 +12,13 @@
PRG=./t-streq
R=0
# format:
# two lines:
# len:string1
# result:string2
# result:
# 1: equal
# 0: not equal
${PRG} <<EOF
0:a
1:X
@ -23,6 +30,18 @@ ${PRG} <<EOF
1:AC
2:aB
0:AC
2:aB\n
1:AB
20:xabcez@uabcey.por.az\n
1:xabcez@uabcey.por.az
7:ünchen\n
1:ünchen
7:ünchen\n
0:üncheX
22:iseadmin@somest.sld.br>\n
1:iseadmin@somest.sld.br
22:iseadmin@somest.sld.br
1:iseadmin@somest.sld.br>\n
EOF
R=$?

View File

@ -96,7 +96,7 @@ sm_test_begin(argc, argv, testname)
** SM_TEST -- single test.
**
** Parameters:
** success -- did test succeeed?
** success -- did test succeed?
** expr -- expression that has been evaluated.
** filename -- guess...
** lineno -- line number.

View File

@ -132,10 +132,11 @@ str2prt(s)
** ibp -- a pointer to the string to translate [x]
** obp -- a pointer to an output buffer [i][m:A]
** bsp -- pointer to the length of the output buffer
** rpool -- rpool for allocations
**
** Returns:
** A possibly new bp (if the buffer needed to grow); if
** it is different, *bsp will updated to the size of
** A possibly new obp (if the buffer needed to grow);
** if it is different, *bsp will updated to the size of
** the new buffer and the caller is responsible for
** freeing the memory.
*/
@ -171,7 +172,12 @@ quote_internal_chars
int bufused, olen;
bool buffer_same, needs_quoting;
if (NULL == ibp)
return NULL;
buffer_same = ibp == obp;
SM_REQUIRE(NULL != bsp);
if (NULL == obp)
*bsp = 0;
needs_quoting = false;
/* determine length of output string (starts at 1 for trailing '\0') */

View File

@ -74,7 +74,7 @@ sm_print(fp, timeout, uio)
}
/*
** SM_BPRINTF -- allow formating to an unbuffered file.
** SM_BPRINTF -- allow formatting to an unbuffered file.
**
** Helper function for `fprintf to unbuffered unix file': creates a
** temporary buffer (via a "fake" file pointer).
@ -84,11 +84,11 @@ sm_print(fp, timeout, uio)
** Parameters:
** fp -- the file to send the o/p to
** fmt -- format instructions for the o/p
** ap -- vectors of data units used for formating
** ap -- vectors of data units used for formatting
**
** Results:
** Failure: SM_IO_EOF and errno set
** Success: number of data units used in the formating
** Success: number of data units used in the formatting
**
** Side effects:
** formatted o/p can be SM_IO_BUFSIZ length maximum
@ -156,13 +156,13 @@ sm_bprintf(fp, fmt, ap)
#define FPT 0x100 /* Floating point number */
/*
** SM_IO_VFPRINTF -- performs actual formating for o/p
** SM_IO_VFPRINTF -- performs actual formatting for o/p
**
** Parameters:
** fp -- file pointer for o/p
** timeout -- time to complete the print
** fmt0 -- formating directives
** ap -- vectors with data units for formating
** fmt0 -- formatting directives
** ap -- vectors with data units for formatting
**
** Results:
** Success: number of data units used for formatting
@ -816,8 +816,8 @@ number: if ((dprec = prec) >= 0)
** It will be replaced with a malloc-ed one if it overflows.
**
** Parameters:
** fmt0 -- formating directives
** ap -- vector list of data unit for formating consumption
** fmt0 -- formatting directives
** ap -- vector list of data unit for formatting consumption
** argtable -- an indexable table (returned) of 'ap'
**
** Results:

View File

@ -655,7 +655,7 @@ again: c = *fmt++;
c = *fp->f_p;
/*
** This code mimicks the integer conversion
** This code mimics the integer conversion
** code, but is much simpler.
*/

View File

@ -409,7 +409,7 @@ smcdb_cursor(database, cursor, flags)
** Parameters:
** database -- An unallocated database pointer to a pointer.
** db_name -- The name of the database without extension.
** mode -- File permisions for a created database.
** mode -- File permissions for a created database.
** mode_mask -- Mode bits that must match on an opened database.
** sff -- Flags for safefile.
** type -- The type of database to open

View File

@ -333,10 +333,9 @@ smdb_lock_file(lock_fd, db_name, mode, sff, extension)
return SMDBE_OK;
}
/*
** SMDB_UNLOCK_FILE -- Unlocks a file
**
** Unlocks a file.
** SMDB_UNLOCK_FILE -- Unlocks a file - via close()
**
** Parameters:
** lock_fd -- The descriptor for the locked file.
@ -488,7 +487,7 @@ smdb_filechanged(db_name, extension, db_fd, stat_info)
** SMDB_PRINT_AVAILABLE_TYPES -- Prints the names of the available types.
**
** Parameters:
** None
** ext - also show extension?
**
** Returns:
** None

View File

@ -423,7 +423,7 @@ smdb1_cursor(database, cursor, flags)
** Parameters:
** database -- An unallocated database pointer to a pointer.
** db_name -- The name of the database without extension.
** mode -- File permisions on the database if created.
** mode -- File permissions on the database if created.
** mode_mask -- Mode bits that must match on an existing database.
** sff -- Flags for safefile.
** type -- The type of database to open

View File

@ -549,7 +549,7 @@ smdb_db_open_internal(db_name, db_type, db_flags, db_params, db)
** Parameters:
** database -- An unallocated database pointer to a pointer.
** db_name -- The name of the database without extension.
** mode -- File permisions for a created database.
** mode -- File permissions for a created database.
** mode_mask -- Mode bits that must match on an opened database.
** sff -- Flags for safefile.
** type -- The type of database to open

View File

@ -17,7 +17,7 @@ SM_RCSID("@(#)$Id: smndbm.c,v 8.55 2013-11-22 20:51:49 ca Exp $")
#include <sendmail/sendmail.h>
#include <libsmdb/smdb.h>
#ifdef NDBM
#if NDBM
# define SMNDB_PAG_FILE_EXTENSION "pag"
@ -465,7 +465,7 @@ smdbm_cursor(database, cursor, flags)
** Parameters:
** database -- An unallocated database pointer to a pointer.
** db_name -- The name of the database without extension.
** mode -- File permisions on a created database.
** mode -- File permissions on a created database.
** mode_mask -- Mode bits that much match on an opened database.
** sff -- Flags to safefile.
** type -- The type of database to open.

View File

@ -21,7 +21,20 @@ char iobuf[IOBUFSZ];
static int noio, chk;
static pid_t pid;
int
/*
** OPENFILE -- open a file
**
** Parameters:
** owner -- create file?
** filename -- name of file.
** flags -- flags for open(2)
**
** Returns:
** >=0 fd
** <0 on failure.
*/
static int
openfile(owner, filename, flags)
int owner;
char *filename;
@ -36,10 +49,21 @@ openfile(owner, filename, flags)
return fd;
fprintf(stderr, "%d: %ld: owner=%d, open(%s) failed\n",
(int) pid, (long) time(NULL), owner, filename);
return 1;
return -1;
}
int
/*
** WRBUF -- write iobuf to fd
**
** Parameters:
** fd -- file descriptor.
**
** Returns:
** ==0 write was ok
** !=0 on failure.
*/
static int
wrbuf(fd)
int fd;
{
@ -55,7 +79,19 @@ wrbuf(fd)
return 1;
}
int
/*
** RDBUF -- read from fd
**
** Parameters:
** fd -- file descriptor.
** xbuf -- expected content.
**
** Returns:
** ==0 read was ok and content matches
** !=0 otherwise
*/
static int
rdbuf(fd, xbuf)
int fd;
const char *xbuf;
@ -81,7 +117,7 @@ rdbuf(fd, xbuf)
}
/*
** LOCKTEST -- test of file locking
** LOCKTESTWR -- test WR/EX file locking
**
** Parameters:
** owner -- create file?
@ -102,7 +138,7 @@ rdbuf(fd, xbuf)
fprintf(stderr, str, filename, shared ? "RD" : "EX"); \
} while (0)
int
static int
locktestwr(filename, flags, delay)
char *filename;
int flags;
@ -128,7 +164,8 @@ locktestwr(filename, flags, delay)
sm_strlcpy(iobuf, FIRSTLINE, sizeof(iobuf));
if (wrbuf(fd))
return 1;
sleep(delay);
if (delay > 0)
sleep(delay);
sm_strlcpy(iobuf, LASTLINE, sizeof(iobuf));
if (wrbuf(fd))
return 1;
@ -149,7 +186,22 @@ locktestwr(filename, flags, delay)
return 0;
}
long
/*
** CHKLCK -- check whether fd is locked (only for fcntl())
**
** Parameters:
** owner -- create file?
** filename -- name of file.
** flags -- flags for open(2)
** delay -- how long to keep file locked?
**
** Returns:
** 0 if not locked
** >0 pid of process which holds a WR lock
** <0 error
*/
static long
chklck(fd)
int fd;
{
@ -168,13 +220,27 @@ chklck(fd)
return (long)lfd.l_pid;
return 0L;
#else /* !HASFLOCK */
fprintf(stderr, "%d: %ld: flock: no lock test\n",
fprintf(stderr, "%d: %ld: flock(): no lock test\n",
(int) pid, (long) time(NULL));
return -1L;
#endif /* !HASFLOCK */
}
int
/*
** LOCKTESTRD -- test file locking for reading
**
** Parameters:
** filename -- name of file.
** flags -- flags for open(2)
** delay -- how long is file locked by owner?
** shared -- LOCK_{EX/SH}
**
** Returns:
** 0 on success
** != 0 on failure.
*/
static int
locktestrd(filename, flags, delay, shared)
char *filename;
int flags;
@ -252,6 +318,16 @@ locktestrd(filename, flags, delay, shared)
return 0;
}
/*
** USAGE -- show usage
**
** Parameters:
** prg -- name of program
**
** Returns:
** nothing.
*/
static void
usage(prg)
const char *prg;
@ -264,6 +340,12 @@ usage(prg)
"-r use shared locking for reader\n"
"-s delay sleep delay seconds before unlocking\n"
"-W only start writer process\n"
#if !HASFLOCK
"uses fcntl()\n"
#else
"uses flock()\n"
#endif
, prg);
}
@ -335,7 +417,7 @@ main(argc, argv)
r = 0;
if (reader || fpid == 0)
{
/* give the parent the chance to setup data */
/* give the parent the chance to set up data */
pid = getpid();
sleep(1);
r = locktestrd(filename, flags, nb ? delay : 0, shared);

View File

@ -1702,7 +1702,7 @@ hashname(name)
MD5_CTX ctx;
unsigned char md5[18];
# if MAXPATHLEN <= 24
# ERROR "MAXPATHLEN <= 24"
# error "MAXPATHLEN <= 24"
# endif
char b64[24];
MD5_LONG bits;

View File

@ -26,6 +26,8 @@ makemap
.IR commentchar ]
.RB [ \-e ]
.RB [ \-f ]
.RB [ \-i
.IR type ]
.RB [ \-l ]
.RB [ \-o ]
.RB [ \-r ]
@ -144,6 +146,12 @@ This is intended to mesh with the
line in sendmail.cf.
The value is never case folded.
.TP
.B \-i
Use the specified type as fallback
if the given
.I maptype
is not available.
.TP
.B \-l
List supported map types.
.TP

View File

@ -53,12 +53,17 @@ bool DontInitGroups = false;
uid_t TrustedUid = 0;
BITMAP256 DontBlameSendmail;
static bool verbose = false;
static int exitstat;
#define BUFSIZE 1024
#define ISASCII(c) isascii((unsigned char)(c))
#define ISSPACE(c) (ISASCII(c) && isspace(c))
#define ISSEP(c) (sep == '\0' ? ISASCII(c) && isspace(c) : (c) == sep)
static void usage __P((const char *));
static char *readcf __P((const char *, char *, bool));
static void db_put __P((SMDB_DATABASE *, SMDB_DBENT, SMDB_DBENT, int, const char *, int, const char *));
static void
usage(progname)
@ -68,7 +73,7 @@ usage(progname)
"Usage: %s [-C cffile] [-N] [-c cachesize] [-D commentchar]\n",
progname);
sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
" %*s [-d] [-e] [-f] [-l] [-o] [-r] [-s] [-t delimiter]\n",
" %*s [-d] [-e] [-f] [-i type] [-l] [-o] [-r] [-s] [-t delimiter]\n",
(int) strlen(progname), "");
#if _FFR_TESTS
sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
@ -81,6 +86,69 @@ usage(progname)
exit(EX_USAGE);
}
/*
** DB_PUT -- do the DB insert
**
** Parameters:
** database -- DB to use
** db_key -- key
** db_val -- value
** putflags -- flags for smdb_put()
** mapname -- name of map (for error reporting)
** lineno -- line number (for error reporting)
** progname -- name of program (for error reporting)
**
** Returns:
** none.
**
** Side effects:
** Sets exitstat so makemap exits with error if put fails
*/
static void
db_put(database, db_key, db_val, putflags, mapname, lineno, progname)
SMDB_DATABASE *database;
SMDB_DBENT db_key, db_val;
int putflags;
const char *mapname;
int lineno;
const char *progname;
{
int errcode;
if (verbose)
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"key=`%s', val=`%s'\n",
(char *) db_key.data,
(char *) db_val.data);
}
errcode = database->smdb_put(database, &db_key, &db_val, putflags);
if (0 == errcode)
return;
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s: %s: ",
progname, mapname);
if (lineno >= 0)
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "line %u: ",
lineno);
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "key %s: ",
(char *) db_key.data);
if (SMDBE_KEY_EXIST == errcode)
{
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"duplicate key\n");
exitstat = EX_DATAERR;
}
else
{
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"put error: %s\n", sm_errstring(errcode));
exitstat = EX_IOERR;
}
}
/*
** READCF -- read some settings from configuration file.
**
@ -106,7 +174,7 @@ readcf(cfile, mapfile, fullpath)
SM_FILE_T *cfp;
char buf[MAXLINE];
static char classbuf[MAXLINE];
char *classname;
char *classname, *mapname;
char *p;
if ((cfp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, cfile,
@ -120,13 +188,21 @@ readcf(cfile, mapfile, fullpath)
classname = NULL;
classbuf[0] = '\0';
mapname = mapfile;
if (!fullpath && mapfile != NULL)
{
p = strrchr(mapfile, '/');
if (p != NULL)
mapfile = ++p;
p = strrchr(mapfile, '.');
if (p != NULL)
mapname = strdup(mapfile);
if (NULL == mapname)
{
sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"makemap: strdup(%s) failed: %s\n",
mapfile, sm_errstring(errno));
exit(EX_OSERR);
}
if ((p = strchr(mapname, '.')) != NULL)
*p = '\0';
}
@ -184,18 +260,19 @@ readcf(cfile, mapfile, fullpath)
case 'K': /* Keyfile (map) */
if (classname != NULL) /* found it already */
continue;
if (mapfile == NULL || *mapfile == '\0')
if (mapname == NULL || *mapname == '\0')
continue;
/* cut off trailing spaces */
for (p = buf + strlen(buf) - 1; ISASCII(*p) && isspace(*p) && p > buf; p--)
for (p = buf + strlen(buf) - 1;
ISASCII(*p) && isspace(*p) && p > buf; p--)
*p = '\0';
/* find the last argument */
p = strrchr(buf, ' ');
if (p == NULL)
continue;
b = strstr(p, mapfile);
b = strstr(p, mapname);
if (b == NULL)
continue;
if (b <= buf)
@ -208,7 +285,7 @@ readcf(cfile, mapfile, fullpath)
}
/* allow trailing white space? */
if (strcmp(mapfile, b) != 0)
if (strcmp(mapname, b) != 0)
continue;
/* SM_ASSERT(b > buf); */
--b;
@ -253,6 +330,12 @@ readcf(cfile, mapfile, fullpath)
}
(void) sm_io_close(cfp, SM_TIME_DEFAULT);
/* not really needed because it is just a "one time leak" */
if (mapname != mapfile && mapname != NULL)
{
free(mapname);
mapname = NULL;
}
return classbuf;
}
@ -267,19 +350,24 @@ main(argc, argv)
bool notrunc = false;
bool allowreplace = false;
bool allowempty = false;
bool verbose = false;
bool foldcase = true;
bool unmake = false;
#if _FFR_MM_ALIASES
/*
** NOTE: this does not work properly:
** sendmail does address rewriting which is not done here.
*/
bool aliases = false;
#endif
bool didreadcf = false;
char sep = '\0';
char comment = '#';
int exitstat;
int opt;
char *typename = NULL;
char *fallback = NULL;
char *mapname = NULL;
unsigned int lineno;
int st;
int mode;
int smode;
int putflags = 0;
@ -327,12 +415,17 @@ main(argc, argv)
SMDB_MAX_USER_NAME_LEN);
#define OPTIONS "C:D:Nc:defi:Llorst:uvx"
#if _FFR_MM_ALIASES
# define A_OPTIONS "a"
#else
# define A_OPTIONS
#endif
#if _FFR_TESTS
# define X_OPTIONS "S:"
#else
# define X_OPTIONS
#endif
while ((opt = getopt(argc, argv, OPTIONS X_OPTIONS)) != -1)
while ((opt = getopt(argc, argv, A_OPTIONS OPTIONS X_OPTIONS)) != -1)
{
switch (opt)
{
@ -344,6 +437,14 @@ main(argc, argv)
inclnull = true;
break;
#if _FFR_MM_ALIASES
case 'a':
/* Note: this doesn't verify e-mail addresses */
sep = ':';
aliases = true;
break;
#endif
case 'c':
params.smdbp_cache_size = atol(optarg);
break;
@ -669,6 +770,10 @@ main(argc, argv)
*p++ = '\0';
while (*p != '\0' && ISSEP(*p))
p++;
#if _FFR_MM_ALIASES
while (aliases && *p != '\0' && ISSPACE(*p))
p++;
#endif
if (!allowempty && *p == '\0')
{
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
@ -688,50 +793,22 @@ main(argc, argv)
** Do the database insert.
*/
if (verbose)
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"key=`%s', val=`%s'\n",
(char *) db_key.data,
(char *) db_val.data);
}
errno = database->smdb_put(database, &db_key, &db_val,
putflags);
switch (errno)
{
case SMDBE_KEY_EXIST:
st = 1;
break;
case 0:
st = 0;
break;
default:
st = -1;
break;
}
if (st < 0)
{
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"%s: %s: line %u: key %s: put error: %s\n",
progname, mapname, lineno,
(char *) db_key.data,
sm_errstring(errno));
exitstat = EX_IOERR;
}
else if (st > 0)
{
(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
"%s: %s: line %u: key %s: duplicate key\n",
progname, mapname,
lineno,
(char *) db_key.data);
exitstat = EX_DATAERR;
}
db_put(database, db_key, db_val, putflags, mapname,
lineno, progname);
}
#if _FFR_MM_ALIASES
if (aliases)
{
char magic[2] = "@";
db_key.data = magic;
db_val.data = magic;
db_key.size = 1;
db_val.size = 1;
db_put(database, db_key, db_val, putflags, mapname, -1,
progname);
}
#endif /* _FFR_MM_ALIASES */
}
#if _FFR_TESTS

View File

@ -51,7 +51,7 @@ the bin directory used by smrsh.
path.
-DSMRSH_CMDDIR=\"dir\" \"/usr/adm/sm.bin\" The default smrsh
program directory
These can be added to the devtools/Site/site.config.m4 file using the
global M4 macro confENVDEF or the smrsh specific M4 macro
conf_smrsh_ENVDEF.

View File

@ -6,7 +6,7 @@ define(`confREQUIRE_SM_OS_H', `true')
bldPRODUCT_START(`executable', `sendmail')
define(`bldBIN_TYPE', `G')
define(`bldINSTALL_DIR', `')
define(`bldSOURCES', `main.c alias.c arpadate.c bf.c collect.c conf.c control.c convtime.c daemon.c deliver.c domain.c envelope.c err.c headers.c macro.c map.c mci.c milter.c mime.c parseaddr.c queue.c ratectrl.c readcf.c recipient.c sasl.c savemail.c sfsasl.c shmticklib.c sm_resolve.c srvrsmtp.c stab.c stats.c sysexits.c timers.c tlsh.c tls.c trace.c udb.c usersmtp.c util.c version.c ')
define(`bldSOURCES', `main.c alias.c arpadate.c bf.c collect.c conf.c control.c convtime.c daemon.c deliver.c domain.c envelope.c err.c headers.c macro.c map.c mci.c milter.c mime.c parseaddr.c queue.c ratectrl.c readcf.c recipient.c sasl.c savemail.c sched.c sfsasl.c shmticklib.c sm_resolve.c srvrsmtp.c stab.c stats.c sysexits.c timers.c tlsh.c tls.c trace.c udb.c usersmtp.c util.c version.c ')
PREPENDDEF(`confENVDEF', `confMAPDEF')
bldPUSH_SMLIB(`sm')
bldPUSH_SMLIB(`smutil')

View File

@ -232,8 +232,8 @@ HASFLOCK Set this if you prefer to use the flock(2) system call
rather than using fcntl-based locking. Fcntl locking
has some semantic gotchas, but many vendor systems
also interface it to lockd(8) to do NFS-style locking.
Unfortunately, may vendors implementations of fcntl locking
is just plain broken (e.g., locks are never released,
Unfortunately, many vendor implementations of fcntl locking
are just plain broken (e.g., locks are never released,
causing your sendmail to deadlock; when the kernel runs
out of locks your system crashes). For this reason, I
recommend always defining this unless you are absolutely
@ -309,9 +309,9 @@ HASSTRERROR Define this if you have the libc strerror(3) function (which
HASCLOSEFROM Define this if your system has closefrom(3).
HASFDWALK Define this if your system has fdwalk(3).
SM_CONF_GETOPT Define this as 0 if you need a reimplementation of getopt(3).
On some systems, getopt does very odd things if called
On some systems, getopt() does very odd things if called
to scan the arguments twice. This flag will ask sendmail
to compile in a local version of getopt that works
to compile in a local version of getopt() that works
properly. You may also need this if you build with
another library that introduces a non-standard getopt(3).
NEEDSTRTOL Define this if your standard C library does not define
@ -625,7 +625,7 @@ SHARE_V1 Support for the fair share scheduler, version 1. Setting to
resource limitations. So far as I know, this is only
supported on ConvexOS.
SASL Enables SMTP AUTH (RFC 2554). This requires the Cyrus SASL
library (ftp://ftp.andrew.cmu.edu/pub/cyrus-mail/). Please
library (https://github.com/cyrusimap/cyrus-sasl). Please
install at least version 1.5.13. See below for further
information: SASL COMPILATION AND CONFIGURATION. If your
SASL library is older than 1.5.10, you have to set this
@ -640,7 +640,9 @@ EGD Define this if your system has EGD installed, see
http://egd.sourceforge.net/ . It should be used to
seed the PRNG for STARTTLS if HASURANDOMDEV is not defined.
STARTTLS Enables SMTP STARTTLS (RFC 2487). This requires OpenSSL
(http://www.OpenSSL.org/); use OpenSSL 0.9.8zc or later.
(http://www.OpenSSL.org/); use an OpenSSL version
which is supported by sendmail and preferably your
OS distribution or OpenSSL.
See STARTTLS COMPILATION AND CONFIGURATION for further
information.
TLS_EC Enable use of elliptic curve cryptography in STARTTLS.
@ -765,6 +767,10 @@ From: Garrett Wollman <wollman@lcs.mit.edu>
certificate authentication -- even some of those which already support
SSL/TLS for confidentiality.
OpenSSL 3 deprecated a lot of functionality which sendmail uses by
default. However, the code can be disabled via compile time options
if needed:
-DNO_DH: related to DH and DSA.
+------------------------------------+
| SASL COMPILATION AND CONFIGURATION |
@ -1804,6 +1810,7 @@ conf.h Configuration that must be known everywhere.
control.c Routines to implement control socket.
convtime.c A routine to sanely process times.
daemon.c Routines to implement daemon mode.
daemon.h Header file for daemon.c.
deliver.c Routines to deliver mail.
domain.c Routines that interface with DNS (the Domain Name
System).
@ -1818,17 +1825,21 @@ main.c The main routine to sendmail. This file also
contains some miscellaneous routines.
makesendmail A convenience for calling ./Build.
map.c Support for database maps.
map.h Header file for map.c.
mci.c Routines that handle mail connection information caching.
milter.c MTA portions of the mail filter API.
mime.c MIME conversion routines.
newaliases.1 Man page for the newaliases command.
parseaddr.c The routines which do address parsing.
queue.c Routines to implement message queueing.
ratectrl.c Routines for rate/connnection control.
ratectrl.h Header file for rate/connnection control.
readcf.c The routine that reads the configuration file and
translates it to internal form.
recipient.c Routines that manipulate the recipient list.
sasl.c Routines to interact with Cyrys-SASL.
savemail.c Routines which save the letter on processing errors.
sched.c Routines for scheduling queue management.
sendmail.8 Man page for the sendmail command.
sendmail.h Main header file for sendmail.
sfsasl.c I/O interface between SASL/TLS and the MTA.
@ -1846,6 +1857,8 @@ sysexits.h List of error codes for systems that lack their own.
timers.c Routines to provide microtimers.
timers.h Data structure and function declarations for timers.h.
tls.c Routines for TLS.
tls.h Header file for tls*.c
tlsh.c Helper routines for TLS, mostly DANE.
trace.c The trace package. These routines allow setting and
testing of trace flags with a high granularity.
udb.c The user database interface module.

View File

@ -14,12 +14,12 @@ people who are very security conscious (you should be...).
Even though sendmail goes through great lengths to assure that it
can't be compromised even if the system it is running on is
incorrectly or insecurely configured, it can't work around everything.
This has been demonstrated by recent OS problems which have
subsequently been used to compromise the root account using sendmail
as a vector. One way to minimize the possibility of such problems
is to install sendmail without set-user-ID root, which avoids local
exploits. This configuration, which is the default starting with
8.12, is described in the first section of this security guide.
This has been demonstrated by OS problems which have subsequently
been used to compromise the root account using sendmail as a vector.
One way to minimize the possibility of such problems is to install
sendmail without set-user-ID root, which avoids local exploits.
This configuration, which is the default starting with 8.12, is
described in the first section of this security guide.
*****************************************************
@ -112,6 +112,7 @@ information.) You can start this program as root, it will change
its user id to RunAsUser (smmsp by default, recommended uid: 25).
This way smmsp does not need a valid shell.
Summary
-------
@ -186,6 +187,7 @@ You can use
to install a sendmail program to act as daemon etc under the name
sm-mta.
Set-User-Id
-----------

View File

@ -71,15 +71,14 @@
57 util.c snprintf
58 bf.c bf* routines
59 parseaddr.c cataddr
60 map.c
60 parseaddr.c map_lookup
61 conf.c sm_gethostbyname
62 multiple file descriptor checking
63 queue.c runqueue process watching
64 multiple Milter
65 main.c permission checks
#if DANE
66 domain.c force port=25 for TLSA RR lookups
67 domain.c TLSA RR lookups
66,>99 domain.c force port=25 for TLSA RR lookups
#endif
68 unused
#if _FFR_QUEUE_SCHED_DBG
@ -105,19 +104,26 @@
83 collect.c timeout
84 deliver.c timeout
85 map.c dprintf map
#if _FFR_TESTS
86,>99 milter.c macro tests
#endif
#if _FFR_PROXY
87 srvrsmtp.c proxy mode
#endif
88,>99 tls.c disable the effect of _FFR_VRFY_TRUSTED_FIRST
89 conf.c >=8 use sm_dprintf() instead of syslog()
90 unused
#if _FFR_TESTS
90,>99 tls.c deliver.c Simulate error for OpenSSL functions related to DANE
#endif
91 mci.c syslogging of MCI cache information
92 EF_LOGSENDER
93,>99 * Prevent daemon connection fork for profiling/debugging
94,>99 srvrsmtp.c cause commands to fail (for protocol testing)
95 srvrsmtp.c AUTH
95 usersmtp.c AUTH
96 tls.c DHparam info, Activate SSL_CTX_set_info_callback()
96 tls.c DHparam info, activate SSL_CTX_set_info_callback(), etc
97 srvrsmtp.c Trace automode settings for I/O
#if _FFR_TIMERS
98 * timers
#endif
99 main.c avoid backgrounding (no printed output)

View File

@ -381,10 +381,11 @@ setalias(spec)
}
}
}
/*
** ALIASWAIT -- wait for distinguished @:@ token to appear.
**
** This can decide to reopen or rebuild the alias file
** This can decide to reopen the alias file
**
** Parameters:
** map -- a pointer to the map descriptor for this alias file.
@ -402,7 +403,7 @@ setalias(spec)
bool
aliaswait(map, ext, isopen)
MAP *map;
char *ext;
const char *ext;
bool isopen;
{
bool attimeout = false;
@ -411,13 +412,14 @@ aliaswait(map, ext, isopen)
char buf[MAXPATHLEN];
if (tTd(27, 3))
sm_dprintf("aliaswait(%s:%s)\n",
map->map_class->map_cname, map->map_file);
sm_dprintf("aliaswait(%s:%s), open=%d, wait=%d\n",
map->map_class->map_cname, map->map_file,
isopen, bitset(MF_ALIASWAIT, map->map_mflags));
if (bitset(MF_ALIASWAIT, map->map_mflags))
return isopen;
map->map_mflags |= MF_ALIASWAIT;
if (SafeAlias > 0)
if (isopen && SafeAlias > 0)
{
auto int st;
unsigned int sleeptime = 2;
@ -448,7 +450,7 @@ aliaswait(map, ext, isopen)
map->map_mflags |= MF_CLOSING;
map->map_class->map_close(map);
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING|MF_CHKED_CHGD);
(void) sleep(sleeptime);
sleeptime *= 2;
if (sleeptime > 60)
@ -456,6 +458,7 @@ aliaswait(map, ext, isopen)
isopen = map->map_class->map_open(map, O_RDONLY);
}
}
map->map_mflags &= ~MF_CHKED_CHGD;
/* see if we need to go into auto-rebuild mode */
if (!bitset(MCF_REBUILDABLE, map->map_class->map_cflags))
@ -499,20 +502,17 @@ aliaswait(map, ext, isopen)
**
** Parameters:
** map -- the database to rebuild.
** automatic -- set if this was automatically generated.
**
** Returns:
** true if successful; false otherwise.
**
** Side Effects:
** Reads the text version of the database, builds the
** DBM or DB version.
** Reads the text version of the database, builds the map.
*/
bool
rebuildaliases(map, automatic)
rebuildaliases(map)
register MAP *map;
bool automatic;
{
SM_FILE_T *af;
bool nolock = false;
@ -538,7 +538,7 @@ rebuildaliases(map, automatic)
{
struct stat stb;
if ((errno != EACCES && errno != EROFS) || automatic ||
if ((errno != EACCES && errno != EROFS) ||
(af = safefopen(map->map_file, O_RDONLY, 0, sff)) == NULL)
{
int saveerr = errno;
@ -546,7 +546,7 @@ rebuildaliases(map, automatic)
if (tTd(27, 1))
sm_dprintf("Can't open %s: %s\n",
map->map_file, sm_errstring(saveerr));
if (!automatic && !bitset(MF_OPTIONAL, map->map_mflags))
if (!bitset(MF_OPTIONAL, map->map_mflags))
message("newaliases: cannot open %s: %s",
map->map_file, sm_errstring(saveerr));
errno = 0;
@ -590,13 +590,12 @@ rebuildaliases(map, automatic)
if (LogLevel > 7)
{
sm_syslog(LOG_NOTICE, NOQID,
"alias database %s %srebuilt by %s",
map->map_file, automatic ? "auto" : "",
username());
"alias database %s rebuilt by %s",
map->map_file, username());
}
map->map_mflags |= MF_OPEN|MF_WRITABLE;
map->map_pid = CurrentPid;
readaliases(map, af, !automatic, true);
readaliases(map, af, true, true);
success = true;
}
else
@ -604,9 +603,8 @@ rebuildaliases(map, automatic)
if (tTd(27, 1))
sm_dprintf("Can't create database for %s: %s\n",
map->map_file, sm_errstring(errno));
if (!automatic)
syserr("Cannot create database for alias file %s",
map->map_file);
syserr("Cannot create database for alias file %s",
map->map_file);
}
/* close the file, thus releasing locks */
@ -621,8 +619,10 @@ rebuildaliases(map, automatic)
int sl;
sl = tTdlevel(78) - 100;
sm_dprintf("rebuildaliases: sleep=%d\n", sl);
sm_dprintf("rebuildaliases: sleep=%d, file=%s\n",
sl, map->map_file);
sleep(sl);
sm_dprintf("rebuildaliases: done\n");
}
#endif
map->map_mflags |= MF_CLOSING;
@ -638,6 +638,54 @@ rebuildaliases(map, automatic)
#endif
return success;
}
/*
** CONTLINE -- handle potential continuation line
**
** Parameters:
** fp -- file to read
** line -- current line
**
** Returns:
** pointer to end of current line if there is a continuation line
** NULL otherwise
**
** Side Effects:
** Modifies line if it is a continuation line
*/
static char *contline __P((SM_FILE_T *, char *));
static char *
contline(fp, line)
SM_FILE_T *fp;
char *line;
{
char *p;
int c;
if ((p = strchr(line, '\n')) != NULL && p > line && p[-1] == '\\')
{
*p = '\0';
*--p = '\0';
return p;
}
c = sm_io_getc(fp, SM_TIME_DEFAULT);
if (!sm_io_eof(fp))
(void) sm_io_ungetc(fp, SM_TIME_DEFAULT, c);
if (c == ' ' || c == '\t')
{
char *nlp;
p = line;
nlp = &p[strlen(p)];
if (nlp > p && nlp[-1] == '\n')
*--nlp = '\0';
return nlp;
}
return NULL;
}
/*
** READALIASES -- read and process the alias file.
**
@ -688,48 +736,74 @@ readaliases(map, af, announcestats, logstats)
naliases = bytes = longest = 0;
skipping = false;
line = NULL;
while (sm_io_fgets(af, SM_TIME_DEFAULT, lbuf, sizeof(lbuf)) >= 0)
{
int lhssize, rhssize;
int c;
char *newp;
LineNumber++;
#if _FFR_8BITENVADDR
if (line != lbuf)
SM_FREE(line);
len = 0;
line = quote_internal_chars(lbuf, NULL, &len, NULL);
#else
line = lbuf;
#endif
p = strchr(line, '\n');
/* XXX what if line="a\\" ? */
while (p != NULL && p > line && p[-1] == '\\')
line = lbuf;
p = line;
while ((newp = contline(af, line)) != NULL)
{
p--;
if (sm_io_fgets(af, SM_TIME_DEFAULT, p,
SPACELEFT(line, p)) < 0)
p = newp;
if ((c = sm_io_fgets(af, SM_TIME_DEFAULT, p,
SPACELEFT(lbuf, p))) < 0)
{
break;
}
LineNumber++;
p = strchr(p, '\n');
}
#if _FFR_8BITENVADDR
if (SMTP_UTF8 || EightBitAddrOK)
{
if (line != lbuf)
SM_FREE(line);
line = quote_internal_chars(lbuf, NULL, &len, NULL);
}
else
#endif
/* "else" in #if code above */
line = lbuf;
p = strchr(line, '\n');
if (p != NULL)
*p = '\0';
else if (!sm_io_eof(af))
{
int prev;
bool cl;
errno = 0;
syserr("554 5.3.0 alias line too long");
/* flush to end of line */
while ((c = sm_io_getc(af, SM_TIME_DEFAULT)) !=
SM_IO_EOF && c != '\n')
continue;
prev = '\0';
cl = false;
do {
/* flush to end of "virtual" line */
while ((c = sm_io_getc(af, SM_TIME_DEFAULT)) !=
SM_IO_EOF && c != '\n')
{
prev = c;
}
cl = ('\\' == prev && '\n' == c);
if (!cl)
{
c = sm_io_getc(af, SM_TIME_DEFAULT);
if (!sm_io_eof(af))
(void) sm_io_ungetc(af, SM_TIME_DEFAULT, c);
cl = (c == ' ' || c == '\t');
}
} while (cl);
/* skip any continuation lines */
skipping = true;
continue;
}
switch (line[0])
{
case '#':
@ -779,7 +853,6 @@ readaliases(map, af, announcestats, logstats)
while (SM_ISSPACE(*p))
p++;
rhs = p;
for (;;)
{
register char *nlp;
@ -810,31 +883,7 @@ readaliases(map, af, announcestats, logstats)
{
p = nlp;
}
/* see if there should be a continuation line */
c = sm_io_getc(af, SM_TIME_DEFAULT);
if (!sm_io_eof(af))
(void) sm_io_ungetc(af, SM_TIME_DEFAULT, c);
if (c != ' ' && c != '\t')
break;
/* read continuation line */
if (sm_io_fgets(af, SM_TIME_DEFAULT, p,
sizeof(line) - (p-line)) < 0)
break;
LineNumber++;
/* check for line overflow */
if (strchr(p, '\n') == NULL && !sm_io_eof(af))
{
usrerr("554 5.3.5 alias too long");
while ((c = sm_io_getc(af, SM_TIME_DEFAULT))
!= SM_IO_EOF && c != '\n')
continue;
skipping = true;
break;
}
}
} while (0);
if (skipping)
continue;
@ -868,17 +917,20 @@ readaliases(map, af, announcestats, logstats)
{
syserr("554 5.3.5 %.40s... missing value for alias",
line);
}
else
{
#if _FFR_8BITENVADDR
dequote_internal_chars(al.q_user, lhsbuf, sizeof(lhsbuf));
dequote_internal_chars(rhs, rhsbuf, sizeof(rhsbuf));
map->map_class->map_store(map, lhsbuf, rhsbuf);
#else
map->map_class->map_store(map, al.q_user, rhs);
if (SMTP_UTF8 || EightBitAddrOK)
{
dequote_internal_chars(al.q_user, lhsbuf, sizeof(lhsbuf));
dequote_internal_chars(rhs, rhsbuf, sizeof(rhsbuf));
map->map_class->map_store(map, lhsbuf, rhsbuf);
}
else
#endif
/* "else" in #if code above */
map->map_class->map_store(map, al.q_user, rhs);
/* statistics */
naliases++;
@ -947,7 +999,16 @@ forward(user, sendq, aliaslevel, e)
/* good address -- look for .forward file in home */
macdefine(&e->e_macro, A_PERM, 'z', user->q_home);
macdefine(&e->e_macro, A_PERM, 'u', user->q_user);
macdefine(&e->e_macro, A_PERM, 'h', user->q_host);
pp = user->q_host;
#if _FFR_8BITENVADDR
if (NULL != pp)
{
int len;
pp = quote_internal_chars(pp, NULL, &len, NULL);
}
#endif
macdefine(&e->e_macro, A_PERM, 'h', pp);
if (ForwardPath == NULL)
ForwardPath = newstr("\201z/.forward");

View File

@ -61,7 +61,7 @@ struct bf
int bf_buffilled; /* Bytes of buffer actually filled */
char *bf_filename; /* Name of buffered file, if ever committed */
MODE_T bf_filemode; /* Mode of buffered file, if ever committed */
off_t bf_offset; /* Currect file offset */
off_t bf_offset; /* Current file offset */
int bf_size; /* Total current size of file */
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2006, 2008 Proofpoint, Inc. and its suppliers.
* Copyright (c) 1998-2006, 2008, 2023, 2024 Proofpoint, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@ -34,7 +34,7 @@ static SM_FILE_T *collect_eoh __P((ENVELOPE *, int, int));
** numhdrs -- number of headers
** hdrslen -- length of headers
**
** Results:
** Returns:
** NULL, or handle to open data file
**
** Side Effects:
@ -82,7 +82,7 @@ collect_eoh(e, numhdrs, hdrslen)
** Parameters:
** e -- envelope
**
** Results:
** Returns:
** none.
**
** Side Effects:
@ -179,7 +179,7 @@ collect_doheader(e)
** Parameters:
** e -- envelope
**
** Results:
** Returns:
** NULL, or a pointer to an open data file,
** into which the message body will be written by collect().
**
@ -232,6 +232,70 @@ collect_dfopen(e)
return df;
}
/*
** INCBUFLEN -- increase buflen for the header buffer in collect()
**
** Parameters:
** buflen -- current size of buffer
**
** Returns:
** new buflen
*/
static int incbuflen __P((int));
static int
incbuflen(buflen)
int buflen;
{
int newlen;
/* this also handles the case of MaxMessageSize == 0 */
if (MaxMessageSize <= MEMCHUNKSIZE)
{
if (buflen < MEMCHUNKSIZE)
return buflen * 2;
else
return buflen + MEMCHUNKSIZE;
}
/* MaxMessageSize > MEMCHUNKSIZE */
newlen = buflen * 2;
if (newlen > 0 && newlen < MaxMessageSize)
return newlen;
else
return MaxMessageSize;
}
#if _FFR_TESTS
/* just for testing/debug output */
static const char *
makeprint(c)
char c;
{
static char prt[6];
prt[1] = '\0';
prt[2] = '\0';
if (isprint((unsigned char)c))
prt[0] = c;
else if ('\n' == c)
{
prt[0] = 'L';
prt[1] = 'F';
}
else if ('\r' == c)
{
prt[0] = 'C';
prt[1] = 'R';
}
else
snprintf(prt, sizeof(prt), "%o", c);
return prt;
}
#else /* _FFR_TESTS */
# define makeprint(c) "X"
#endif /* _FFR_TESTS */
/*
** COLLECT -- read & parse message header & make temp file.
**
@ -241,10 +305,10 @@ collect_dfopen(e)
**
** Parameters:
** fp -- file to read.
** smtpmode -- if set, we are running SMTP: give an RFC821
** style message to say we are ready to collect
** input, and never ignore a single dot to mean
** end of message.
** smtpmode -- if >= SMTPMODE_LAX we are running SMTP:
** give an RFC821 style message to say we are
** ready to collect input, and never ignore
** a single dot to mean end of message.
** hdrp -- the location to stash the header.
** e -- the current envelope.
** rsetsize -- reset e_msgsize?
@ -267,20 +331,26 @@ collect_dfopen(e)
/* values for input state machine */
#define IS_NORM 0 /* middle of line */
#define IS_BOL 1 /* beginning of line */
#define IS_DOT 2 /* read a dot at beginning of line */
#define IS_DOT 2 /* read "." at beginning of line */
#define IS_DOTCR 3 /* read ".\r" at beginning of line */
#define IS_CR 4 /* read a carriage return */
#define IS_CR 4 /* read "\r" */
/* hack to enhance readability of debug output */
static const char *istates[] = { "NORM", "BOL", "DOT", "DOTCR", "CR" };
#define ISTATE istates[istate]
/* values for message state machine */
#define MS_UFROM 0 /* reading Unix from line */
#define MS_HEADER 1 /* reading message header */
#define MS_BODY 2 /* reading message body */
#define MS_DISCARD 3 /* discarding rest of message */
#define BARE_LF_MSG "Bare linefeed (LF) not allowed"
#define BARE_CR_MSG "Bare carriage return (CR) not allowed"
void
collect(fp, smtpmode, hdrp, e, rsetsize)
SM_FILE_T *fp;
bool smtpmode;
int smtpmode;
HDR **hdrp;
register ENVELOPE *e;
bool rsetsize;
@ -306,12 +376,26 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
#if _FFR_REJECT_NUL_BYTE
bool hasNUL; /* has at least one NUL input byte */
#endif
int bare_lf, bare_cr;
#define SMTPMODE (smtpmode >= SMTPMODE_LAX)
#define SMTPMODE_STRICT ((smtpmode & SMTPMODE_CRLF) != 0)
#define BARE_LF_421 ((smtpmode & SMTPMODE_LF_421) != 0)
#define BARE_CR_421 ((smtpmode & SMTPMODE_CR_421) != 0)
#define BARE_LF_SP ((smtpmode & SMTPMODE_LF_SP) != 0)
#define BARE_CR_SP ((smtpmode & SMTPMODE_CR_SP) != 0)
/* for bare_{lf,cr} */
#define BARE_IN_HDR 0x01
#define BARE_IN_BDY 0x02
#define BARE_WHERE ((MS_BODY == mstate) ? BARE_IN_BDY : BARE_IN_HDR)
df = NULL;
ignrdot = smtpmode ? false : IgnrDot;
ignrdot = SMTPMODE ? false : IgnrDot;
bare_lf = bare_cr = 0;
/* timeout for I/O functions is in milliseconds */
dbto = smtpmode ? ((int) TimeOuts.to_datablock * 1000)
dbto = SMTPMODE ? ((int) TimeOuts.to_datablock * 1000)
: SM_TIME_FOREVER;
sm_io_setinfo(fp, SM_IO_WHAT_TIMEOUT, &dbto);
old_rd_tmo = set_tls_rd_tmo(TimeOuts.to_datablock);
@ -334,15 +418,15 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
** Tell ARPANET to go ahead.
*/
if (smtpmode)
message("354 Enter mail, end with \".\" on a line by itself");
if (SMTPMODE)
message("354 End data with <CR><LF>.<CR><LF>");
/* simulate an I/O timeout when used as sink */
if (tTd(83, 101))
sleep(319);
if (tTd(30, 2))
sm_dprintf("collect\n");
sm_dprintf("collect, smtpmode=%#x\n", smtpmode);
/*
** Read the message.
@ -358,7 +442,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
for (;;)
{
if (tTd(30, 35))
sm_dprintf("top, istate=%d, mstate=%d\n", istate,
sm_dprintf("top, istate=%s, mstate=%d\n", ISTATE,
mstate);
for (;;)
{
@ -379,7 +463,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
/* timeout? */
if (c == SM_IO_EOF && errno == EAGAIN
&& smtpmode)
&& SMTPMODE)
{
/*
** Override e_message in
@ -417,15 +501,32 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
hasNUL = true;
#endif
if (c == SM_IO_EOF)
goto readerr;
if (SevenBitInput)
goto readdone;
if (SevenBitInput ||
bitset(EF_7BITBODY, e->e_flags))
c &= 0x7f;
else
HasEightBits |= bitset(0x80, c);
}
if (tTd(30, 94))
sm_dprintf("istate=%d, c=%c (0x%x)\n",
istate, (char) c, c);
sm_dprintf("istate=%s, c=%s (0x%x)\n",
ISTATE, makeprint((char) c), c);
if ('\n' == c && SMTPMODE &&
!(IS_CR == istate || IS_DOTCR == istate))
{
bare_lf |= BARE_WHERE;
if (BARE_LF_421)
{
inputerr = true;
goto readabort;
}
if (BARE_LF_SP)
{
if (TTD(30, 64))
sm_dprintf("LF: c=%s %#x\n", makeprint((char) c), c);
c = ' ';
}
}
switch (istate)
{
case IS_BOL:
@ -437,8 +538,8 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
break;
case IS_DOT:
if (c == '\n' && !ignrdot)
goto readerr;
if (c == '\n' && !ignrdot && !SMTPMODE_STRICT)
goto readdone;
else if (c == '\r')
{
istate = IS_DOTCR;
@ -460,7 +561,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
case IS_DOTCR:
if (c == '\n' && !ignrdot)
goto readerr;
goto readdone;
else
{
/* push back the ".\rx" */
@ -483,12 +584,30 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
case IS_CR:
if (c == '\n')
{
if (TTD(30, 64))
sm_dprintf("state=CR, c=%s %#x -> BOL\n", makeprint((char) c), c);
istate = IS_BOL;
}
else
{
if (TTD(30, 64))
sm_dprintf("state=CR, c=%s %#x -> NORM\n", makeprint((char) c), c);
if (SMTPMODE)
{
bare_cr |= BARE_WHERE;
if (BARE_CR_421)
{
inputerr = true;
goto readabort;
}
}
(void) sm_io_ungetc(fp, SM_TIME_DEFAULT,
c);
c = '\r';
if (BARE_CR_SP)
c = ' ';
else
c = '\r';
istate = IS_NORM;
}
goto bufferchar;
@ -499,7 +618,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
istate = IS_CR;
continue;
}
else if (c == '\n')
else if (c == '\n' && !SMTPMODE_STRICT)
istate = IS_BOL;
else
istate = IS_NORM;
@ -524,7 +643,8 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
if (!bitset(EF_TOOBIG, e->e_flags))
(void) sm_io_putc(df, SM_TIME_DEFAULT,
c);
if (TTD(30, 64))
sm_dprintf("state=%s, put=%s %#x\n", ISTATE, makeprint((char) c), c);
/* FALLTHROUGH */
case MS_DISCARD:
@ -540,10 +660,9 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
/* out of space for header */
obuf = buf;
if (buflen < MEMCHUNKSIZE)
buflen *= 2;
else
buflen += MEMCHUNKSIZE;
buflen = incbuflen(buflen);
if (tTd(30, 32))
sm_dprintf("buflen=%d, hdrslen=%d\n", buflen, hdrslen);
if (buflen <= 0)
{
sm_syslog(LOG_NOTICE, e->e_id,
@ -592,8 +711,8 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
nextstate:
if (tTd(30, 35))
sm_dprintf("nextstate, istate=%d, mstate=%d, line=\"%s\"\n",
istate, mstate, buf);
sm_dprintf("nextstate, istate=%s, mstate=%d, line=\"%s\"\n",
ISTATE, mstate, buf);
switch (mstate)
{
case MS_UFROM:
@ -624,7 +743,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
/* timeout? */
if (c == SM_IO_EOF && errno == EAGAIN
&& smtpmode)
&& SMTPMODE)
{
/*
** Override e_message in
@ -653,7 +772,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
/* guaranteed by isheader(buf) */
SM_ASSERT(*(bp - 1) != '\n' || bp > buf + 1);
/* trim off trailing CRLF or NL */
/* trim off trailing CRLF or LF */
if (*--bp != '\n' || *--bp != '\r')
bp++;
*bp = '\0';
@ -673,7 +792,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
sm_dprintf("EOH\n");
if (headeronly)
goto readerr;
goto readdone;
df = collect_eoh(e, numhdrs, hdrslen);
if (df == NULL)
@ -700,8 +819,8 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
bp = buf;
}
readerr:
if ((sm_io_eof(fp) && smtpmode) || sm_io_error(fp))
readdone:
if ((sm_io_eof(fp) && SMTPMODE) || sm_io_error(fp))
{
const char *errmsg;
@ -741,7 +860,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
}
else if (SuperSafe == SAFE_NO ||
SuperSafe == SAFE_INTERACTIVE ||
(SuperSafe == SAFE_REALLY_POSTMILTER && smtpmode))
(SuperSafe == SAFE_REALLY_POSTMILTER && SMTPMODE))
{
/* skip next few clauses */
/* EMPTY */
@ -806,33 +925,43 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
readabort:
if (inputerr && (OpMode == MD_SMTP || OpMode == MD_DAEMON))
{
char *host;
char *problem;
ADDRESS *q;
host = RealHostName;
if (host == NULL)
host = "localhost";
if (sm_io_eof(fp))
problem = "unexpected close";
else if (sm_io_error(fp))
problem = "I/O error";
else if (0 != bare_lf)
problem = BARE_LF_MSG;
else if (0 != bare_cr)
problem = BARE_CR_MSG;
else
problem = "read timeout";
if (LogLevel > 0 && sm_io_eof(fp))
#define LOG_CLT ((NULL != RealHostName) ? RealHostName: "localhost")
#define CONN_ERR_TXT "collect: relay=%s, from=%s, info=%s%s%s%s"
#define CONN_ERR_CODE "421 4.4.1 "
#define CONN_LOG_FROM shortenstring(e->e_from.q_paddr, MAXSHORTSTR)
#define CONN_ERR_BARE (0 != bare_lf) ? BARE_LF_MSG : ((0 != bare_cr) ? BARE_CR_MSG : "")
#define CONN_ERR_WHERE(bare_xy) (BARE_IN_HDR==(bare_xy) ? "header" : \
(BARE_IN_BDY==(bare_xy) ? "body" : "header+body"))
#define HAS_BARE_XY (0 != (bare_lf | bare_cr))
#define CONN_ERR_ARGS LOG_CLT, CONN_LOG_FROM, problem, \
HAS_BARE_XY ? ", where=" : "", \
HAS_BARE_XY ? CONN_ERR_WHERE(bare_lf|bare_cr) : "", \
HAS_BARE_XY ? ", status=tempfail" : ""
if (LogLevel > 0 && (sm_io_eof(fp) || (0 != (bare_lf | bare_cr))))
sm_syslog(LOG_NOTICE, e->e_id,
"collect: %s on connection from %.100s, sender=%s",
problem, host,
shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
if (sm_io_eof(fp))
usrerr("421 4.4.1 collect: %s on connection from %s, from=%s",
problem, host,
shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
CONN_ERR_TXT, CONN_ERR_ARGS);
if (0 != (bare_lf | bare_cr))
usrerr("421 4.5.0 %s", CONN_ERR_BARE);
else if (sm_io_eof(fp))
usrerr(CONN_ERR_CODE CONN_ERR_TXT, CONN_ERR_ARGS);
else
syserr("421 4.4.1 collect: %s on connection from %s, from=%s",
problem, host,
shortenstring(e->e_from.q_paddr, MAXSHORTSTR));
syserr(CONN_ERR_CODE CONN_ERR_TXT, CONN_ERR_ARGS);
flush_errors(true);
/* don't return an error indication */
@ -863,6 +992,21 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
e->e_flags &= ~EF_LOGSENDER;
}
#define LOG_BARE_XY(bare_xy, bare_xy_sp, bare_xy_msg) \
do \
{ \
if ((0 != bare_xy) && LogLevel > 8) \
sm_syslog(LOG_NOTICE, e->e_id, \
"collect: relay=%s, from=%s, info=%s, where=%s%s" \
, LOG_CLT, CONN_LOG_FROM, bare_xy_msg \
, CONN_ERR_WHERE(bare_xy) \
, bare_xy_sp ? ", status=replaced" : "" \
); \
} while (0)
LOG_BARE_XY(bare_lf, BARE_LF_SP, BARE_LF_MSG);
LOG_BARE_XY(bare_cr, BARE_CR_SP, BARE_CR_MSG);
/* check for message too large */
if (bitset(EF_TOOBIG, e->e_flags))
{
@ -947,7 +1091,7 @@ collect(fp, smtpmode, hdrp, e, rsetsize)
/*
** DFERROR -- signal error on writing the data file.
**
** Called by collect(). Collect() always terminates the process
** Called by collect(). collect() always terminates the process
** immediately after calling dferror(), which means that the SMTP
** session will be terminated, which means that any error message
** issued by dferror must be a 421 error, as per RFC 821.

View File

@ -81,7 +81,6 @@ static struct hostent *sm_getipnodebyaddr __P((const void *, size_t, int, int *)
** this file too much, you may be making a mistake!
*/
/*
** Header info table
** Final (null) entry contains the flags used for any other field.
@ -164,14 +163,14 @@ struct prival PrivacyValues[] =
{ "needvrfyhelo", PRIV_NEEDVRFYHELO },
{ "noexpn", PRIV_NOEXPN },
{ "novrfy", PRIV_NOVRFY },
{ "restrictexpand", PRIV_RESTRICTEXPAND },
{ "authwarnings", PRIV_AUTHWARNINGS },
{ "noverb", PRIV_NOVERB },
{ "restrictmailq", PRIV_RESTRICTMAILQ },
{ "restrictqrun", PRIV_RESTRICTQRUN },
{ "restrictexpand", PRIV_RESTRICTEXPAND },
{ "noetrn", PRIV_NOETRN },
{ "noverb", PRIV_NOVERB },
{ "authwarnings", PRIV_AUTHWARNINGS },
{ "noreceipts", PRIV_NORECEIPTS },
{ "nobodyreturn", PRIV_NOBODYRETN },
{ "noreceipts", PRIV_NORECEIPTS },
{ "goaway", PRIV_GOAWAY },
{ "noactualrecipient", PRIV_NOACTUALRECIPIENT },
#if _FFR_NOREFLECT
@ -196,7 +195,6 @@ struct dbsval DontBlameSendmailValues[] =
{ "groupwritablealiasfile", DBS_GROUPWRITABLEALIASFILE },
{ "worldwritablealiasfile", DBS_WORLDWRITABLEALIASFILE },
{ "forwardfileinunsafedirpath", DBS_FORWARDFILEINUNSAFEDIRPATH },
{ "includefileinunsafedirpath", DBS_INCLUDEFILEINUNSAFEDIRPATH },
{ "mapinunsafedirpath", DBS_MAPINUNSAFEDIRPATH },
{ "linkedaliasfileinwritabledir",
DBS_LINKEDALIASFILEINWRITABLEDIR },
@ -228,6 +226,7 @@ struct dbsval DontBlameSendmailValues[] =
DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE },
{ "runprograminunsafedirpath", DBS_RUNPROGRAMINUNSAFEDIRPATH },
{ "runwritableprogram", DBS_RUNWRITABLEPROGRAM },
{ "includefileinunsafedirpath", DBS_INCLUDEFILEINUNSAFEDIRPATH },
{ "nonrootsafeaddr", DBS_NONROOTSAFEADDR },
{ "truststickybit", DBS_TRUSTSTICKYBIT },
{ "dontwarnforwardfileinunsafedirpath",
@ -242,6 +241,7 @@ struct dbsval DontBlameSendmailValues[] =
{ "groupreadablekeyfile", DBS_GROUPREADABLEKEYFILE },
{ "groupreadabledefaultauthinfofile",
DBS_GROUPREADABLEAUTHINFOFILE },
{ "certowner", DBS_CERTOWNER },
{ NULL, 0 }
};
@ -1409,7 +1409,6 @@ init_md(argc, argv)
# endif /* _SCO_unix_ */
#endif /* SECUREWARE || defined(_SCO_unix_) */
#ifdef VENDOR_DEFAULT
VendorCode = VENDOR_DEFAULT;
#else
@ -2317,7 +2316,6 @@ refuseconnections(e, dn, active)
conncnt[dn] = 0;
}
#if _FFR_MEMSTAT
if (RefuseLowMem > 0 &&
sm_memstat_get(MemoryResource, &memfree) >= 0 &&
@ -2432,7 +2430,6 @@ refuseconnections(e, dn, active)
# define SPT_TYPE SPT_REUSEARGV
#endif
#if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
# if SPT_TYPE == SPT_PSTAT
@ -3057,7 +3054,6 @@ dgux_inet_addr(host)
* specifies the terms and conditions for redistribution.
*/
/*
** this version hacked to add `atend' flag to allow state machine
** to reset if invoked by the program to scan args for a 2nd time
@ -3637,8 +3633,11 @@ lockfile(fd, filename, ext, type)
action = F_SETLKW;
if (tTd(55, 60))
sm_dprintf("lockfile(%s%s, action=%d, type=%d): ",
filename, ext, action, lfd.l_type);
sm_dprintf("lockfile(%s%s, fd=%d, action=%s, type=%s): ",
filename, ext, fd,
bitset(LOCK_NB, type) ? "nb" : "block",
bitset(LOCK_UN, type) ? "unlock" :
(bitset(LOCK_EX, type) ? "wr" : "rd"));
while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
continue;
if (i >= 0)
@ -3684,7 +3683,9 @@ lockfile(fd, filename, ext, type)
ext = "";
if (tTd(55, 60))
sm_dprintf("lockfile(%s%s, type=%o): ", filename, ext, type);
sm_dprintf("lockfile(%s%s, fd=%d, type=%s): ", filename, ext,
fd, bitset(LOCK_UN, type) ? "unlock" :
(bitset(LOCK_EX, type) ? "wr" : "rd"));
while ((i = flock(fd, type)) < 0 && errno == EINTR)
continue;
@ -3981,7 +3982,6 @@ vendor_pre_defaults(e)
#endif /* apollo */
}
void
vendor_post_defaults(e)
ENVELOPE *e;
@ -4701,7 +4701,7 @@ add_hostnames(sa)
char **ha;
char hnb[MAXHOSTNAMELEN];
/* lookup name with IP address */
/* look up name with IP address */
switch (sa->sa.sa_family)
{
#if NETINET
@ -5290,8 +5290,12 @@ isloopback(sa)
SOCKADDR sa;
{
/* XXX how to correctly extract IN_LOOPBACKNET part? */
#define SM_IS_IPV4_LOOP(a) (((ntohl(a) & IN_CLASSA_NET) \
#ifdef IN_LOOPBACK
# define SM_IS_IPV4_LOOP(a) IN_LOOPBACK(ntohl(a))
#else /* IN_LOOPBACK */
# define SM_IS_IPV4_LOOP(a) (((ntohl(a) & IN_CLASSA_NET) \
>> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
# endif /* IN_LOOPBACK */
#if NETINET6
if (sa.sa.sa_family == AF_INET6 &&
IN6_IS_ADDR_V4MAPPED(&sa.sin6.sin6_addr) &&
@ -5524,7 +5528,7 @@ sm_syslog(level, id, fmt, va_alist)
/* clean up buf after it has been expanded with args */
#if _FFR_LOGASIS >= 5
/* for testing! */
/* for testing! maybe make it an -d option (hence runtime)? */
newstring = buf;
#else
newstring = str2prt(buf);
@ -5850,6 +5854,12 @@ char *CompileOptions[] =
#if DANE
"DANE",
#endif
#if HAVE_SSL_CTX_dane_enable
"HAVE_SSL_CTX_dane_enable",
#endif
#if MAX_TLSA_RR
"MAX_TLSA_RR=" SM_XSTR(MAX_TLSA_RR),
#endif
#if NAMED_BIND
# if DNSMAP
"DNSMAP",
@ -5875,19 +5885,11 @@ char *CompileOptions[] =
"LDAPMAP",
#endif
#if LDAP_NETWORK_TIMEOUT
# if LDAPMAP
/* set LDAP_OPT_NETWORK_TIMEOUT if available (-c) */
"LDAP_NETWORK_TIMEOUT",
# else
# ERROR "LDAP_NETWORK_TIMEOUT requires LDAPMAP"
# endif
#endif
#if LDAP_REFERRALS
# if LDAPMAP
"LDAP_REFERRALS",
# else
# ERROR "LDAP_REFERRALS requires LDAPMAP"
# endif
#endif
#if LOG
"LOG",
@ -5921,6 +5923,10 @@ char *CompileOptions[] =
#endif
#if NAMED_BIND
"NAMED_BIND",
#else
# if DANE
# error "DANE requires NAMED_BIND"
# endif
#endif
#if NDBM
"NDBM",
@ -5951,8 +5957,23 @@ char *CompileOptions[] =
#endif
#if NEWDB
# if defined(DB_VERSION_MAJOR) && defined(DB_VERSION_MINOR)
# if DB_VERSION_MAJOR >= 5 && !HASFLOCK
# ERROR "Berkeley DB file locking needs flock() for version 5.x (and greater?)"
# if DB_VERSION_MAJOR >= 5 && !defined(SOLARIS) && !HASFLOCK && !ACCEPT_BROKEN_BDB_LOCKING
/*
** NOTE: disabling this check by setting ACCEPT_BROKEN_BDB_LOCKING
** means you are taking full responsibility for any problems
** which may arise!
**
** Map locking will not work, and making a change to a map
** while sendmail is using it can break mail handling.
** At least you must stop all sendmail processes when using
** makemap or newaliases - but there might be other things
** which could break.
**
** You have been warned - use at your own risk!
*/
# error "Berkeley DB file locking needs flock() for version 5.x (and greater?)"
# endif
"NEWDB=" SM_XSTR(DB_VERSION_MAJOR) "." SM_XSTR(DB_VERSION_MINOR),
# else
@ -6015,8 +6036,12 @@ char *CompileOptions[] =
"TLS_NO_RSA",
#endif
#if TLS_EC
# if NO_DH
# error "NO_DH disables TLS_EC"
# else
/* elliptic curves */
"TLS_EC",
# endif
#endif
#if TLS_VRFY_PER_CTX
"TLS_VRFY_PER_CTX",
@ -6033,10 +6058,10 @@ char *CompileOptions[] =
*/
# if !ALLOW_255
# ERROR "USE_EAI requires ALLOW_255"
# error "USE_EAI requires ALLOW_255"
# endif
# if _FFR_EIGHT_BIT_ADDR_OK
# ERROR "Cannot enable both USE_EAI and _FFR_EIGHT_BIT_ADDR_OK"
# error "Cannot enable both USE_EAI and _FFR_EIGHT_BIT_ADDR_OK"
# endif
"USE_EAI",
#endif
@ -6055,7 +6080,6 @@ char *CompileOptions[] =
NULL
};
/*
** OS compile options.
*/
@ -6333,7 +6357,7 @@ char *FFRCompileOptions[] =
#endif
#if _FFR_ALLOW_SASLINFO
/* DefaultAuthInfo can be specified by user. */
/* DefaultAuthInfo doesn't really work in 8.13 anymore. */
/* DefaultAuthInfo doesn't really work in 8.13ff anymore. */
"_FFR_ALLOW_SASLINFO",
#endif
#if _FFR_BADRCPT_SHUTDOWN
@ -6361,6 +6385,10 @@ char *FFRCompileOptions[] =
/* Stricter checks about queue directory permissions. */
"_FFR_CHK_QUEUE",
#endif
#if _FFR_CLASS_RM_ENTRY
/* WIP: remove entries from a class: C-{name}entry */
"_FFR_CLASS_RM_ENTRY",
#endif
#if _FFR_CLIENTCA
/*
** Allow to set client specific CA values.
@ -6441,8 +6469,17 @@ char *FFRCompileOptions[] =
"_FFR_DROP_TRUSTUSER_WARNING",
#endif
#if _FFR_DYN_CLASS
/* dynamic classes based on maps */
"_FFR_DYN_CLASS",
#endif
#if _FFR_EIGHT_BIT_ADDR_OK
/* EightBitAddrOK: allow 8-bit e-mail addresses */
/*
** EightBitAddrOK: allow all 8-bit e-mail addresses.
** By default only ((ch & 0340) == 0200) is blocked
** because that range is used for "META" chars.
*/
"_FFR_EIGHT_BIT_ADDR_OK",
#endif
#if _FFR_EXPAND_HELONAME
@ -6523,6 +6560,10 @@ char *FFRCompileOptions[] =
/* Local daemon mode (-bl) which only accepts loopback connections */
"_FFR_LOCAL_DAEMON",
#endif
#if _FFR_LOG_FAILOVER
/* WIP: log reason why trying another host */
"_FFR_LOG_FAILOVER",
#endif
#if _FFR_LOG_MORE1
/* log some TLS/AUTH info in from= too */
"_FFR_LOG_MORE1=" SM_XSTR(_FFR_LOG_MORE1),
@ -6531,10 +6572,18 @@ char *FFRCompileOptions[] =
/* log some TLS info in to= too */
"_FFR_LOG_MORE2=" SM_XSTR(_FFR_LOG_MORE2),
#endif
#if _FFR_LOG_STAGE
/* log protocol stage for delivery problems */
"_FFR_LOG_STAGE",
#endif
#if _FFR_MAIL_MACRO
/* make the "real" sender address available in {mail_from} */
"_FFR_MAIL_MACRO",
#endif
#if _FFR_MAP_CHK_FILE
/* check whether the underlying map file was changed */
"_FFR_MAP_CHK_FILE=" SM_XSTR(_FFR_MAP_CHK_FILE),
#endif
#if _FFR_MAXDATASIZE
/*
** It is possible that a header is larger than MILTER_CHUNK_SIZE,
@ -6564,6 +6613,7 @@ char *FFRCompileOptions[] =
"_FFR_MEMSTAT",
#endif
#if _FFR_MILTER_CHECK
/* for (lib)milter testing */
"_FFR_MILTER_CHECK",
#endif
#if _FFR_MILTER_CONNECT_REPLYCODE
@ -6619,13 +6669,13 @@ char *FFRCompileOptions[] =
#endif
#if _FFR_MTA_STS
# if !MAP_REGEX
# ERROR "_FFR_MTA_STS requires MAP_REGEX"
# error "_FFR_MTA_STS requires MAP_REGEX"
# endif
# if !STARTTLS
# ERROR "_FFR_MTA_STS requires STARTTLS"
# error "_FFR_MTA_STS requires STARTTLS"
# endif
# if !_FFR_TLS_ALTNAMES
# ERROR "_FFR_MTA_STS requires _FFR_TLS_ALTNAMES"
# error "_FFR_MTA_STS requires _FFR_TLS_ALTNAMES"
# endif
/* MTA STS support */
"_FFR_MTA_STS",
@ -6667,7 +6717,7 @@ char *FFRCompileOptions[] =
/* outgoing connection control (not yet working) */
"_FFR_OCC",
# else
# ERROR "_FFR_OCC requires SM_CONF_SHM"
# error "_FFR_OCC requires SM_CONF_SHM"
# endif
#endif
#if _FFR_PROXY
@ -6741,12 +6791,19 @@ char *FFRCompileOptions[] =
"_FFR_SESSID",
#endif
#if _FFR_SETANYOPT
/*
** if _FFR_SETOPT_MAP is used: allow to set any option
** (which probably does not work as expected for many options).
*/
"_FFR_SETANYOPT",
#endif
#if _FFR_SETDEBUG_MAP
/* enable setdebug map to set debug levels from rules */
"_FFR_SETDEBUG_MAP",
#endif
#if _FFR_SETOPT_MAP
/* enable setopt map to set options from rules */
"_FFR_SETOPT_MAP",
#endif
#if _FFR_SHM_STATUS
@ -6762,11 +6819,11 @@ char *FFRCompileOptions[] =
"_FFR_SLEEP_USE_SELECT",
#endif
#if _FFR_SM_LDAP_DBG
# if LDAPMAP && defined(LBER_OPT_LOG_PRINT_FN)
# if defined(LBER_OPT_LOG_PRINT_FN)
/* LDAP debugging */
"_FFR_SM_LDAP_DBG",
# else
# ERROR "_FFR_SM_LDAP_DBG requires LDAPMAP and LBER_OPT_LOG_PRINT_FN"
# error "_FFR_SM_LDAP_DBG requires LBER_OPT_LOG_PRINT_FN"
# endif
#endif
#if _FFR_SPT_ALIGN
@ -6846,7 +6903,7 @@ char *FFRCompileOptions[] =
# if defined(X509_V_FLAG_TRUSTED_FIRST)
"_FFR_VRFY_TRUSTED_FIRST",
# else
# ERROR "_FFR_VRFY_TRUSTED_FIRST set but X509_V_FLAG_TRUSTED_FIRST not defined"
# error "_FFR_VRFY_TRUSTED_FIRST set but X509_V_FLAG_TRUSTED_FIRST not defined"
# endif
#endif
@ -6863,11 +6920,20 @@ char *FFRCompileOptions[] =
/* X-Connect support */
"_FFR_XCNCT",
#endif
#if _FFR_HAPROXY
/* HAproxy support */
"_FFR_HAPROXY",
#endif
#if _FFR_LOGASIS
/* only convert char <= 31 to something printable for logging etc */
"_FFR_LOGASIS=" SM_XSTR(_FFR_LOGASIS),
#endif
#if _FFR_NAMESERVER
/* Allow to override nameserver set by OS */
"_FFR_NAMESERVER",
#endif
#if _FFR_NOREFLECT
/* Don't forget to update docs for "goaway" to include this */
/* Do not include input from a client in a reply of the server */
"_FFR_NOREFLECT",
#endif
#if _FFR_AUTH_PASSING
@ -6880,8 +6946,8 @@ char *FFRCompileOptions[] =
#endif
#if _FFR_MSP_PARANOIA
/*
** Forbid queue groups, multiple queues, and dangerous queue permissions
** when operating as an MSP
** Forbid queue groups, multiple queues, and
** dangerous queue permissions when operating as an MSP
*/
"_FFR_MSP_PARANOIA",
@ -6901,6 +6967,14 @@ char *FFRCompileOptions[] =
*/
"_FFR_MIME_CR_OK",
#endif
#if _FFR_M_ONLY_IPV4
/* mailer flag 4: use only IPv4 for delivery attempts */
"_FFR_M_ONLY_IPV4",
#endif
#if _FFR_SMTPS_CLIENT
/* SMTP over TLS client (defaults to port 465/tcp outbound) */
"_FFR_SMTPS_CLIENT",
#endif
NULL
};

View File

@ -78,7 +78,11 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */
#define SMTPLINELIM 990 /* max SMTP line length */
#define MAXUDBKEY 128 /* max size of a database key (udb only) */
#define MAXKEY 1024 /* max size of a database key */
#define MEMCHUNKSIZE 1024 /* chunk size for memory allocation */
#define MEMCHUNKSIZE 4096 /* chunk size for memory allocation */
#if MEMCHUNKSIZE < MAXLINE
/* see usage in collect.c */
# error "MEMCHUNKSIZE must be at least MAXLINE"
#endif
#define MAXUSERENVIRON 100 /* max envars saved, must be >= 3 */
#define MAXMAPSTACK 12 /* max # of stacked or sequenced maps */
#if MILTER
@ -132,7 +136,7 @@ struct rusage; /* forward declaration to get gcc to shut up in wait.h */
/* must be less than BITMAPBITS for DoQueueRun */
#endif
#if MAXQUEUEGROUPS >= BITMAPBITS
# ERROR "MAXQUEUEGROUPS must be less than BITMAPBITS"
# error "MAXQUEUEGROUPS must be less than BITMAPBITS"
#endif
#ifndef MAXWORKGROUPS

View File

@ -41,8 +41,6 @@ static struct cmd CmdTab[] =
{ NULL, CMDERROR }
};
static void controltimeout __P((int));
int ControlSocket = -1;

View File

@ -25,12 +25,7 @@ SM_RCSID("@(#)$Id: daemon.c,v 8.698 2013-11-22 20:51:55 ca Exp $")
# if NETINET || NETINET6
# include <arpa/inet.h>
# endif
# if NAMED_BIND
# ifndef NO_DATA
# define NO_DATA NO_ADDRESS
# endif
# endif /* NAMED_BIND */
#endif /* defined(USE_SOCK_STREAM) */
#endif
#if STARTTLS
# include <openssl/rand.h>
@ -170,7 +165,6 @@ getrequests(e)
#endif
extern ENVELOPE BlankEnvelope;
/* initialize data for function that generates queue ids */
init_qid_alg();
for (idx = 0; idx < NDaemons; idx++)
@ -868,7 +862,6 @@ getrequests(e)
}
else
setbitn(t, Daemons[curdaemon].d_flags);
#endif /* _FFR_XCNCT */
#if XLA
@ -1871,12 +1864,18 @@ static struct dflags DaemonFlags[] =
{ "UNQUALOK", D_UNQUALOK },
{ "NOAUTH", D_NOAUTH },
{ "NOCANON", D_NOCANON },
{ "NODANE", D_NODANE },
{ "NOETRN", D_NOETRN },
{ "NOSTS", D_NOSTS },
{ "NOTLS", D_NOTLS },
{ "ETRNONLY", D_ETRNONLY },
{ "OPTIONAL", D_OPTIONAL },
{ "DISABLE", D_DISABLE },
{ "ISSET", D_ISSET },
#if _FFR_XCNCT
{ "XCNCT", D_XCNCT },
{ "XCNCT_M", D_XCNCT_M },
#endif
{ NULL, 0 }
};
@ -2160,7 +2159,7 @@ makeconnection(host, port, mci, e, enough
#if NETINET6
volatile bool v6found = false;
#endif
volatile int family = InetMode;
volatile int family;
SOCKADDR_LEN_T len;
volatile SOCKADDR_LEN_T socksize = 0;
volatile bool clt_bind;
@ -2179,8 +2178,14 @@ makeconnection(host, port, mci, e, enough
#if DANE
SM_REQUIRE(ptlsa_flags != NULL);
tlsa_flags = *ptlsa_flags;
*ptlsa_flags &= ~(TLSAFLALWAYS|TLSAFLSECURE);
*ptlsa_flags &= ~TLSAFLADIP;
#endif
#if _FFR_M_ONLY_IPV4
if (bitnset(M_ONLY_IPV4, mci->mci_mailer->m_flags))
family = AF_INET;
else
#endif
family = InetMode;
/* retranslate {daemon_flags} into bitmap */
clrbitmap(d_flags);
@ -2385,7 +2390,7 @@ makeconnection(host, port, mci, e, enough
p = &host[strlen(host) - 1];
#if DANE
if (tTd(16, 40))
sm_dprintf("makeconnection: tlsa_flags=%lX, host=%s\n",
sm_dprintf("makeconnection: tlsa_flags=%#lx, host=%s\n",
tlsa_flags, host);
if (DANEMODE(tlsa_flags) == DANE_SECURE
# if DNSSEC_TEST
@ -2408,13 +2413,16 @@ makeconnection(host, port, mci, e, enough
if (rr != NULL && rr->dns_r_h.ad == 1)
{
*ptlsa_flags |= DANE_SECURE;
*ptlsa_flags |= TLSAFLADIP;
if ((TLSAFLTEMP & *ptlsa_flags) != 0)
{
dns_free_data(rr);
rr = NULL;
return EX_TEMPFAIL;
}
}
if (rr != NULL)
{
hp = dns2he(rr, family);
# if NETINET6
hs = hp;
@ -2428,7 +2436,7 @@ makeconnection(host, port, mci, e, enough
dns_free_data(rr);
rr = NULL;
}
#endif
#endif /* DANE */
if (hp == NULL)
hp = sm_gethostbyname(host, family);
if (hp == NULL && *p == '.')
@ -2544,21 +2552,21 @@ makeconnection(host, port, mci, e, enough
}
#if _FFR_TESTS
/*
** Hack for testing.
** Hardcoded:
** 10.1.1.12: see meta1.tns XREF IP address
** 8754: see common.sh XREF SNKPORT2
*/
/*
** Hack for testing.
** Hardcoded:
** 10.1.1.12: see meta1.tns XREF IP address
** 8754: see common.sh XREF SNKPORT2
*/
if (tTd(77, 101) && hp != NULL && hp->h_addrtype == AF_INET &&
addr.sin.sin_addr.s_addr == inet_addr("10.1.1.12"))
{
addr.sin.sin_addr.s_addr = inet_addr("127.0.0.1");
port = htons(8754);
sm_dprintf("hack host=%s addr=[%s].%d\n", host,
anynet_ntoa(&addr), ntohs(port));
}
if (tTd(77, 101) && hp != NULL && hp->h_addrtype == AF_INET &&
addr.sin.sin_addr.s_addr == inet_addr("10.1.1.12"))
{
addr.sin.sin_addr.s_addr = inet_addr("127.0.0.1");
port = htons(8754);
sm_dprintf("hack host=%s addr=[%s].%d\n", host,
anynet_ntoa(&addr), ntohs(port));
}
#endif
/*
@ -2568,16 +2576,34 @@ makeconnection(host, port, mci, e, enough
if (port == 0)
{
#ifdef NO_GETSERVBYNAME
port = htons(25);
# if _FFR_SMTPS_CLIENT
if (bitnset(M_SMTPS_CLIENT, mci->mci_mailer->m_flags))
port = htons(465);
else
# endif /* _FFR_SMTPS_CLIENT */
port = htons(25);
#else /* NO_GETSERVBYNAME */
register struct servent *sp = getservbyname("smtp", "tcp");
register struct servent *sp;
# if _FFR_SMTPS_CLIENT
if (bitnset(M_SMTPS_CLIENT, mci->mci_mailer->m_flags))
p = "smtps";
else
# endif /* _FFR_SMTPS_CLIENT */
p = "smtp";
sp = getservbyname(p, "tcp");
if (sp == NULL)
{
if (LogLevel > 2)
sm_syslog(LOG_ERR, NOQID,
"makeconnection: service \"smtp\" unknown");
port = htons(25);
"makeconnection: service \"%s\" unknown", p);
# if _FFR_SMTPS_CLIENT
if (bitnset(M_SMTPS_CLIENT, mci->mci_mailer->m_flags))
port = htons(465);
else
# endif /* _FFR_SMTPS_CLIENT */
port = htons(25);
}
else
port = sp->s_port;
@ -2787,6 +2813,9 @@ makeconnection(host, port, mci, e, enough
if (setjmp(CtxConnectTimeout) == 0)
{
int i;
#if _FFR_TESTS
int c_errno;
#endif
if (e->e_ntries <= 0 && TimeOuts.to_iconnect != 0)
ev = sm_setevent(TimeOuts.to_iconnect,
@ -2796,6 +2825,28 @@ makeconnection(host, port, mci, e, enough
connecttimeout, 0);
else
ev = NULL;
#if _FFR_TESTS
i = 0;
c_errno = 0;
if (tTd(77, 101)
/* && AF_INET == addr.sin.sin_family */
&& ntohl(addr.sin.sin_addr.s_addr) >=
ntohl(inet_addr("255.255.255.1"))
&& ntohl(addr.sin.sin_addr.s_addr) <=
ntohl(inet_addr("255.255.255.255"))
)
{
i = -1;
c_errno = ntohl(addr.sin.sin_addr.s_addr) -
ntohl(inet_addr("255.255.255.0"));
sm_dprintf("hack: fail connection=%d, ip=%#x, lower=%#x\n",
c_errno
, ntohl(addr.sin.sin_addr.s_addr)
, ntohl(inet_addr("255.255.255.0")));
}
else
#endif /* _FFR_TESTS */
/* "else" in #if code above */
switch (ConnectOnlyTo.sa.sa_family)
{
@ -2829,24 +2880,11 @@ makeconnection(host, port, mci, e, enough
anynet_ntoa(&addr), ntohs(port));
#if _FFR_TESTS
if (tTd(77, 101)
/* && AF_INET == addr.sin.sin_family */
&& addr.sin.sin_addr.s_addr >=
inet_addr("255.255.255.1")
&& addr.sin.sin_addr.s_addr <=
inet_addr("255.255.255.255")
)
{
i = -1;
save_errno = ntohl(addr.sin.sin_addr.s_addr) -
ntohl(inet_addr("255.255.255.0"));
sm_dprintf("hack: fail connection=%d\n",
save_errno);
errno = save_errno;
}
if (-1 == i)
errno = c_errno;
else
/* Watch out of changes below! */
#endif /* _FFR_TESTS */
#endif
/* "else" in #if code above */
i = connect(s, (struct sockaddr *) &addr, addrlen);
save_errno = errno;
if (ev != NULL)
@ -4200,7 +4238,7 @@ host_map_lookup(map, name, av, statp)
#if USE_EAI
bool utf8;
utf8 = !addr_is_ascii(name);
utf8 = !str_is_print(name);
if (utf8)
{
(void) sm_strlcpy(hbuf, hn2alabel(name), sizeof(hbuf));
@ -4314,7 +4352,6 @@ host_map_lookup(map, name, av, statp)
return cp;
}
/* No match found */
s->s_namecanon.nc_errno = errno;
#if NAMED_BIND

View File

@ -13,7 +13,7 @@
#define DAEMON_H 1
#if DAEMON_C
# define EXTERN
# define EXTERN
#else
# define EXTERN extern
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2004, 2006, 2010 Proofpoint, Inc. and its suppliers.
* Copyright (c) 1998-2004, 2006, 2010, 2020-2023 Proofpoint, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1986, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@ -13,9 +13,6 @@
#include <sendmail.h>
#include "map.h"
#if USE_EAI
#include <unicode/uidna.h>
#endif
#if NAMED_BIND
SM_RCSID("@(#)$Id: domain.c,v 8.205 2013-11-22 20:51:55 ca Exp $ (with name server)")
@ -27,7 +24,7 @@ SM_RCSID("@(#)$Id: domain.c,v 8.205 2013-11-22 20:51:55 ca Exp $ (without name s
#if NAMED_BIND
# include <arpa/inet.h>
# include <sm_resolve.h>
# include "sm_resolve.h"
# if DANE
# include <tls.h>
# ifndef SM_NEG_TTL
@ -35,6 +32,10 @@ SM_RCSID("@(#)$Id: domain.c,v 8.205 2013-11-22 20:51:55 ca Exp $ (without name s
# endif
# endif
#if USE_EAI
#include <unicode/uidna.h>
#endif
# ifndef MXHOSTBUFSIZE
# define MXHOSTBUFSIZE (128 * MAXMXHOSTS)
@ -53,10 +54,6 @@ static char MXHostBuf[MXHOSTBUFSIZE];
# define RES_DNSRCH_VARIABLE _res.dnsrch
# endif
# ifndef NO_DATA
# define NO_DATA NO_ADDRESS
# endif
# ifndef HFIXEDSZ
# define HFIXEDSZ 12 /* sizeof(HEADER) */
# endif
@ -74,6 +71,230 @@ static int fallbackmxrr __P((int, unsigned short *, char **));
# if DANE
static void tlsa_rr_print __P((const unsigned char *, unsigned int));
static void
tlsa_rr_print(rr, len)
const unsigned char *rr;
unsigned int len;
{
unsigned int i, l;
if (!tTd(8, 2))
return;
sm_dprintf("len=%u, %02x-%02x-%02x",
len, (int)rr[0], (int)rr[1], (int)rr[2]);
l = tTd(8, 8) ? len : 4;
for (i = 3; i < l; i++)
sm_dprintf(":%02X", (int)rr[i]);
sm_dprintf("\n");
}
/*
** TLSA_RR_CMP -- Compare two TLSA RRs
**
** Parameters:
** rr1 -- TLSA RR (entry to be added)
** l1 -- length of rr1
** rr2 -- TLSA RR
** l2 -- length of rr2
**
** Returns:
** 0: rr1 == rr2
** 1: rr1 is unsupported
*/
static int tlsa_rr_cmp __P((unsigned char *, int, unsigned char *, int));
static int
tlsa_rr_cmp(rr1, l1, rr2, l2)
unsigned char *rr1;
int l1;
unsigned char *rr2;
int l2;
{
/* temporary #if while investigating the implications of the alternative */
#if FULL_COMPARE
unsigned char r1, r2;
int cmp;
#endif /* FULL_COMPARE */
SM_REQUIRE(NULL != rr1);
SM_REQUIRE(NULL != rr2);
SM_REQUIRE(l1 > 3);
SM_REQUIRE(l2 > 3);
#if FULL_COMPARE
/*
** certificate usage
** 3: cert/fp must match
** 2: cert/fp must be trust anchor
*/
/* preference[]: lower value: higher preference */
r1 = rr1[0];
r2 = rr2[0];
if (r1 != r2)
{
int preference[] = { 3, 2, 1, 0 };
SM_ASSERT(r1 <= SM_ARRAY_SIZE(preference));
SM_ASSERT(r2 <= SM_ARRAY_SIZE(preference));
return preference[r1] - preference[r2];
}
/*
** selector:
** 0: full cert
** 1: fp
*/
r1 = rr1[1];
r2 = rr2[1];
if (r1 != r2)
{
int preference[] = { 1, 0 };
SM_ASSERT(r1 <= SM_ARRAY_SIZE(preference));
SM_ASSERT(r2 <= SM_ARRAY_SIZE(preference));
return preference[r1] - preference[r2];
}
/*
** matching type:
** 0 -- Exact match
** 1 -- SHA-256 hash
** 2 -- SHA-512 hash
*/
r1 = rr1[2];
r2 = rr2[2];
if (r1 != r2)
{
int preference[] = { 2, 0, 1 };
SM_ASSERT(r1 <= SM_ARRAY_SIZE(preference));
SM_ASSERT(r2 <= SM_ARRAY_SIZE(preference));
return preference[r1] - preference[r2];
}
/* not the same length despite the same type? */
if (l1 != l2)
return 1;
cmp = memcmp(rr1, rr2, l1);
if (0 == cmp)
return 0;
return 1;
#else /* FULL_COMPARE */
/* identical? */
if (l1 == l2 && 0 == memcmp(rr1, rr2, l1))
return 0;
/* new entry is unsupported? -> append */
if (TLSA_UNSUPP == dane_tlsa_chk(rr1, l1, "", false))
return 1;
/* current entry is unsupported? -> insert new one */
if (TLSA_UNSUPP == dane_tlsa_chk(rr2, l2, "", false))
return -1;
/* default: preserve order */
return 1;
#endif /* FULL_COMPARE */
}
/*
** TLSAINSERT -- Insert a TLSA RR
**
** Parameters:
** dane_tlsa -- dane_tlsa entry
** rr -- TLSA RR
** pn -- (point to) number of entries
**
** Returns:
** SM_SUCCESS: rr inserted
** SM_NOTDONE: rr not inserted: exists
** SM_FULL: rr not inserted: no space left
*/
static int tlsainsert __P((dane_tlsa_P, RESOURCE_RECORD_T *, int *));
static int
tlsainsert(dane_tlsa, rr, pn)
dane_tlsa_P dane_tlsa;
RESOURCE_RECORD_T *rr;
int *pn;
{
int i, l1, ret;
unsigned char *r1;
SM_ASSERT(pn != NULL);
SM_ASSERT(*pn <= MAX_TLSA_RR);
r1 = rr->rr_u.rr_data;
l1 = rr->rr_size;
ret = SM_SUCCESS;
for (i = 0; i < *pn; i++)
{
int r, j;
r = tlsa_rr_cmp(r1, l1, dane_tlsa->dane_tlsa_rr[i],
dane_tlsa->dane_tlsa_len[i]);
if (0 == r)
{
if (tTd(8, 80))
sm_dprintf("func=tlsainsert, i=%d, n=%d, status=exists\n", i, *pn);
ret = SM_NOTDONE;
goto done;
}
if (r > 0)
continue;
if (*pn + 1 >= MAX_TLSA_RR)
{
j = MAX_TLSA_RR - 1;
SM_FREE(dane_tlsa->dane_tlsa_rr[j]);
dane_tlsa->dane_tlsa_len[j] = 0;
}
else
(*pn)++;
for (j = MAX_TLSA_RR - 2; j >= i; j--)
{
dane_tlsa->dane_tlsa_rr[j + 1] = dane_tlsa->dane_tlsa_rr[j];
dane_tlsa->dane_tlsa_len[j + 1] = dane_tlsa->dane_tlsa_len[j];
}
SM_ASSERT(i < MAX_TLSA_RR);
dane_tlsa->dane_tlsa_rr[i] = r1;
dane_tlsa->dane_tlsa_len[i] = l1;
if (tTd(8, 80))
sm_dprintf("func=tlsainsert, i=%d, n=%d, status=inserted\n", i, *pn);
goto added;
}
if (*pn + 1 <= MAX_TLSA_RR)
{
dane_tlsa->dane_tlsa_rr[*pn] = r1;
dane_tlsa->dane_tlsa_len[*pn] = l1;
(*pn)++;
if (tTd(8, 80))
sm_dprintf("func=tlsainsert, n=%d, status=appended\n", *pn);
}
else
{
if (tTd(8, 80))
sm_dprintf("func=tlsainsert, n=%d, status=full\n", *pn);
return SM_FULL;
}
added:
/* hack: instead of copying the data, just "take it over" */
rr->rr_u.rr_data = NULL;
done:
return ret;
}
/*
** TLSAADD -- add TLSA records to dane_tlsa entry
**
@ -82,24 +303,27 @@ static int fallbackmxrr __P((int, unsigned short *, char **));
** dr -- DNS reply
** dane_tlsa -- dane_tlsa entry
** dnsrc -- DNS lookup return code (h_errno)
** n -- current number of TLSA records in dane_tlsa entry
** nr -- current number of TLSA records in dane_tlsa entry
** pttl -- (pointer to) TTL (in/out)
** level -- recursion level (CNAMEs)
**
** Returns:
** new number of TLSA records
**
** NOTE: the array for TLSA RRs could be "full" which is not
** handled well (yet).
*/
static int tlsaadd __P((const char *, DNS_REPLY_T *, dane_tlsa_P, int, int,
unsigned int *, int));
static int
tlsaadd(name, dr, dane_tlsa, dnsrc, n, pttl, level)
tlsaadd(name, dr, dane_tlsa, dnsrc, nr, pttl, level)
const char *name;
DNS_REPLY_T *dr;
dane_tlsa_P dane_tlsa;
int dnsrc;
int n;
int nr;
unsigned int *pttl;
int level;
{
@ -110,7 +334,7 @@ tlsaadd(name, dr, dane_tlsa, dnsrc, n, pttl, level)
if (dnsrc != 0)
{
if (tTd(8, 2))
sm_dprintf("tlsaadd(%s), prev=%d, dnsrc=%d\n",
sm_dprintf("tlsaadd, name=%s, prev=%d, dnsrc=%d\n",
name, dane_tlsa->dane_tlsa_dnsrc, dnsrc);
/* check previous error and keep the "most important" one? */
@ -122,61 +346,79 @@ tlsaadd(name, dr, dane_tlsa, dnsrc, n, pttl, level)
# endif
/* "else" in #if code above */
*pttl = SM_NEG_TTL;
return n;
return nr;
}
if (dr == NULL)
return n;
return nr;
if (dr->dns_r_h.ad != 1 && Dane == DANE_SECURE) /* not secure? */
return n;
return nr;
ttl = *pttl;
/* first: try to find TLSA records */
nprev = n;
for (rr = dr->dns_r_head; rr != NULL && n < MAX_TLSA_RR;
rr = rr->rr_next)
nprev = nr;
for (rr = dr->dns_r_head; rr != NULL; rr = rr->rr_next)
{
int tlsa_chk;
int tlsa_chk, r;
if (rr->rr_type != T_TLSA)
{
if (rr->rr_type != T_CNAME && tTd(8, 8))
sm_dprintf("tlsaadd(%s), type=%s\n", name,
sm_dprintf("tlsaadd: name=%s, type=%s\n", name,
dns_type_to_string(rr->rr_type));
continue;
}
tlsa_chk = dane_tlsa_chk(rr->rr_u.rr_data, rr->rr_size, name,
true);
if (TLSA_UNSUPP == tlsa_chk)
TLSA_SET_FL(dane_tlsa, TLSAFLUNS);
if (!TLSA_IS_VALID(tlsa_chk))
continue;
if (TLSA_IS_SUPPORTED(tlsa_chk))
TLSA_SET_FL(dane_tlsa, TLSAFLSUP);
/*
** To do: the RRs should be sorted (by "complexity") --
** when more than one type is supported.
** Note: rr_u.rr_data might be NULL after tlsainsert()
** for nice debug output: print the data into a string
** and then use it after tlsainsert().
*/
dane_tlsa->dane_tlsa_rr[n] = rr->rr_u.rr_data;
dane_tlsa->dane_tlsa_len[n] = rr->rr_size;
if (tTd(8, 2))
{
unsigned char *p;
p = rr->rr_u.rr_data;
sm_dprintf("tlsaadd(%s), n=%d, %d-%d-%d:%02x\n", name,
n, (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
sm_dprintf("tlsaadd: name=%s, nr=%d, ", name, nr);
tlsa_rr_print(rr->rr_u.rr_data, rr->rr_size);
}
r = tlsainsert(dane_tlsa, rr, &nr);
if (SM_FULL == r)
TLSA_SET_FL(dane_tlsa, TLSAFL2MANY);
if (tTd(8, 2))
sm_dprintf("tlsainsert=%d, nr=%d\n", r, nr);
/* require some minimum TTL? */
if (ttl > rr->rr_ttl && rr->rr_ttl > 0)
ttl = rr->rr_ttl;
}
/* hack: instead of copying the data, just "take it over" */
rr->rr_u.rr_data = NULL;
++n;
if (tTd(8, 2))
{
unsigned int ui;
SM_ASSERT(nr <= MAX_TLSA_RR);
for (ui = 0; ui < (unsigned int)nr; ui++)
{
sm_dprintf("tlsaadd: name=%s, ui=%u, ", name, ui);
tlsa_rr_print(dane_tlsa->dane_tlsa_rr[ui],
dane_tlsa->dane_tlsa_len[ui]);
}
}
if (TLSA_IS_FL(dane_tlsa, TLSAFL2MANY))
{
if (tTd(8, 20))
sm_dprintf("tlsaadd: name=%s, rr=%p, nr=%d, toomany=%d\n", name, rr, nr, TLSA_IS_FL(dane_tlsa, TLSAFL2MANY));
}
/* second: check for CNAME records, but only if no TLSA RR was added */
for (rr = dr->dns_r_head; rr != NULL && n < MAX_TLSA_RR && nprev == n;
rr = rr->rr_next)
for (rr = dr->dns_r_head; rr != NULL && nprev == nr; rr = rr->rr_next)
{
DNS_REPLY_T *drc;
int err, herr;
@ -186,30 +428,35 @@ tlsaadd(name, dr, dane_tlsa, dnsrc, n, pttl, level)
if (level > 1)
{
if (tTd(8, 2))
sm_dprintf("tlsaadd(%s), CNAME=%s, level=%d\n",
sm_dprintf("tlsaadd: name=%s, CNAME=%s, level=%d\n",
name, rr->rr_u.rr_txt, level);
continue;
}
drc = dns_lookup_int(rr->rr_u.rr_txt, C_IN, T_TLSA, 0, 0,
(Dane == DANE_SECURE &&
!TLSA_IS_FL(dane_tlsa, TLSAFLNOADMX))
? SM_RES_DNSSEC : 0,
Dane == DANE_SECURE ? SM_RES_DNSSEC : 0,
RR_RAW, &err, &herr);
if (tTd(8, 2))
sm_dprintf("tlsaadd(%s), CNAME=%s, level=%d, dr=%p, ad=%d, err=%d, herr=%d\n",
sm_dprintf("tlsaadd: name=%s, CNAME=%s, level=%d, dr=%p, ad=%d, err=%d, herr=%d\n",
name, rr->rr_u.rr_txt, level,
(void *)drc, drc != NULL ? drc->dns_r_h.ad : -1,
err, herr);
nprev = n = tlsaadd(name, drc, dane_tlsa, herr, n, pttl,
nprev = nr = tlsaadd(name, drc, dane_tlsa, herr, nr, pttl,
level + 1);
dns_free_data(drc);
drc = NULL;
}
if (TLSA_IS_FL(dane_tlsa, TLSAFLUNS) &&
!TLSA_IS_FL(dane_tlsa, TLSAFLSUP) && LogLevel > 9)
{
sm_syslog(LOG_NOTICE, NOQID,
"TLSA=%s, records=%d%s",
name, nr, ONLYUNSUPTLSARR);
}
*pttl = ttl;
return n;
return nr;
}
/*
@ -221,7 +468,7 @@ tlsaadd(name, dr, dane_tlsa, dnsrc, n, pttl, level)
** pste -- (pointer to) stab entry (output)
** flags -- TLSAFL*
** mxttl -- TTL of MX (or host)
** port -- port
** port -- port number used in TLSA queries (_PORT._tcp.)
**
** Returns:
** The number of TLSA records found.
@ -248,7 +495,7 @@ gettlsa(host, name, pste, flags, mxttl, port)
time_t now;
unsigned int ttl;
int n_rrs, len, err, herr;
bool isrname;
bool isrname, expired;
char nbuf[MAXDNAME];
char key[MAXDNAME];
@ -258,9 +505,26 @@ gettlsa(host, name, pste, flags, mxttl, port)
if ('\0' == *host)
return 0;
expired = false;
isrname = NULL == name;
if (isrname)
name = host;
/*
** If host->MX lookup was not secure then do not look up TLSA RRs.
** Note: this is currently a hack: TLSAFLADMX is used as input flag,
** it is (SHOULD!) NOT stored in dane_tlsa->dane_tlsa_flags
*/
if (DANE_SECURE == Dane && 0 == (TLSAFLADMX & flags) &&
0 != (TLSAFLNEW & flags))
{
if (tTd(8, 2))
sm_dprintf("gettlsa: host=%s, flags=%#lx, no ad but Dane=Secure\n",
host, flags);
return 0;
}
now = 0;
n_rrs = 0;
dr = NULL;
@ -273,35 +537,37 @@ gettlsa(host, name, pste, flags, mxttl, port)
}
else
len = -1;
if (0 == port || tTd(66, 10))
if (0 == port || tTd(66, 101))
port = 25;
(void) sm_snprintf(key, sizeof(key), "_%u..%s", port, name);
(void) sm_snprintf(key, sizeof(key), "_%u.%s", port, name);
ste = stab(key, ST_TLSA_RR, ST_FIND);
if (tTd(8, 2))
sm_dprintf("gettlsa(%s, %s, ste=%p, pste=%p, flags=%lX, port=%d)\n",
sm_dprintf("gettlsa: host=%s, %s, ste=%p, pste=%p, flags=%#lx, port=%d\n",
host, isrname ? "" : name, (void *)ste, (void *)pste,
flags, port);
if (ste != NULL)
{
dane_tlsa = ste->s_tlsa;
if ((TLSAFLADMX & flags) != 0)
TLSA_CLR_FL(ste->s_tlsa, TLSAFLNOADMX);
}
/* Do not reload TLSA RRs if the MX RRs were not securely retrieved. */
if (pste != NULL
&& dane_tlsa != NULL && TLSA_IS_FL(dane_tlsa, TLSAFLNOADMX)
&& DANE_SECURE == Dane)
goto end;
#if 0
// /* Do not reload TLSA RRs if the MX RRs were not securely retrieved. */
// if (pste != NULL
// && dane_tlsa != NULL && TLSA_IS_FL(dane_tlsa, TLSAFLNOADMX)
// && DANE_SECURE == Dane)
// goto end;
#endif
if (ste != NULL)
{
SM_ASSERT(dane_tlsa != NULL);
now = curtime();
if (tTd(8, 20))
sm_dprintf("gettlsa: host=%s, found-ste=%p, ste_flags=%#lx, expired=%d\n", host, ste, ste->s_tlsa->dane_tlsa_flags, dane_tlsa->dane_tlsa_exp <= now);
if (dane_tlsa->dane_tlsa_exp <= now
&& 0 == (TLSAFLNOEXP & flags))
{
dane_tlsa_clr(dane_tlsa);
expired = true;
}
else
{
n_rrs = dane_tlsa->dane_tlsa_n;
@ -309,6 +575,10 @@ gettlsa(host, name, pste, flags, mxttl, port)
}
}
/* get entries if none exist yet? */
if ((0 == (TLSAFLNEW & flags)) && !expired)
goto end;
if (dane_tlsa == NULL)
{
dane_tlsa = (dane_tlsa_P) sm_malloc(sizeof(*dane_tlsa));
@ -330,11 +600,38 @@ gettlsa(host, name, pste, flags, mxttl, port)
(void) sm_snprintf(nbuf, sizeof(nbuf), "_%u._tcp.%s", port, host);
dr = dns_lookup_int(nbuf, C_IN, T_TLSA, 0, 0,
TLSA_IS_FL(dane_tlsa, TLSAFLNOADMX) ? 0 : SM_RES_DNSSEC,
(TLSAFLADMX & flags) ? SM_RES_DNSSEC : 0,
RR_RAW, &err, &herr);
if (tTd(8, 2))
sm_dprintf("gettlsa(%s), dr=%p, ad=%d, err=%d, herr=%d\n", host,
(void *)dr, dr != NULL ? dr->dns_r_h.ad : -1, err, herr);
{
#if 0
/* disabled -- what to do with these two counters? log them "somewhere"? */
// if (NULL != dr && tTd(8, 12))
// {
// RESOURCE_RECORD_T *rr;
// unsigned int ntlsarrs, usable;
//
// ntlsarrs = usable = 0;
// for (rr = dr->dns_r_head; rr != NULL; rr = rr->rr_next)
// {
// int tlsa_chk;
//
// if (rr->rr_type != T_TLSA)
// continue;
// ++ntlsarrs;
// tlsa_chk = dane_tlsa_chk(rr->rr_u.rr_data,
// rr->rr_size, name, false);
// if (TLSA_IS_SUPPORTED(tlsa_chk))
// ++usable;
//
// }
// sm_dprintf("gettlsa: host=%s, ntlsarrs=%u, usable\%u\n", host, ntlsarrs, usable);
// }
#endif /* 0 */
sm_dprintf("gettlsa: host=%s, dr=%p, ad=%d, err=%d, herr=%d\n",
host, (void *)dr,
dr != NULL ? dr->dns_r_h.ad : -1, err, herr);
}
ttl = UINT_MAX;
n_rrs = tlsaadd(key, dr, dane_tlsa, herr, n_rrs, &ttl, 0);
@ -342,7 +639,7 @@ gettlsa(host, name, pste, flags, mxttl, port)
if (n_rrs == 0 && !TLSA_RR_TEMPFAIL(dane_tlsa))
{
if (tTd(8, 2))
sm_dprintf("gettlsa(%s), n_rrs=%d, herr=%d, status=NOT_ADDED\n",
sm_dprintf("gettlsa: host=%s, n_rrs=%d, herr=%d, status=NOT_ADDED\n",
host, n_rrs, dane_tlsa->dane_tlsa_dnsrc);
goto cleanup;
}
@ -370,7 +667,7 @@ gettlsa(host, name, pste, flags, mxttl, port)
error:
if (tTd(8, 2))
sm_dprintf("gettlsa(%s, %s), status=error\n", host, key);
sm_dprintf("gettlsa: host=%s, key=%s, status=error\n", host, key);
n_rrs = -1;
cleanup:
if (NULL == ste)
@ -426,15 +723,18 @@ getfallbackmxrr(host)
if (NumFallbackMXHosts > 0 && renew > curtime())
return NumFallbackMXHosts;
/* for DANE we need to invoke getmxrr() to get the TLSA RRs. */
# if !DANE
if (host[0] == '[')
/*
** For DANE we need to invoke getmxrr() to get the TLSA RRs.
** Hack: don't do that if its not a FQHN (e.g., [localhost])
** This also triggers for IPv4 addresses, but not IPv6!
*/
if (host[0] == '[' && (!Dane || strchr(host, '.') == NULL))
{
fbhosts[0] = host;
NumFallbackMXHosts = 1;
}
else
# endif
{
/* free old data */
for (i = 0; i < NumFallbackMXHosts; i++)
@ -448,10 +748,9 @@ getfallbackmxrr(host)
NumFallbackMXHosts = getmxrr(host, fbhosts, NULL,
# if DANE
(DANE_SECURE == Dane) ? ISAD :
(DANE_SECURE == Dane) ? ISAD :
# endif
0,
&rcode, &ttl, 0);
0, &rcode, &ttl, 0, NULL);
renew = curtime() + ttl;
for (i = 0; i < NumFallbackMXHosts; i++)
fbhosts[i] = newstr(fbhosts[i]);
@ -518,7 +817,7 @@ hn2alabel(hostname)
UIDNA *idna;
static char buf[MAXNAME_I]; /* XXX ??? */
if (addr_is_ascii(hostname))
if (str_is_print(hostname))
return hostname;
idna = uidna_openUTS46(UIDNA_NONTRANSITIONAL_TO_ASCII, &error);
(void) uidna_nameToASCII_UTF8(idna, hostname, strlen(hostname),
@ -538,13 +837,15 @@ hn2alabel(hostname)
** mxprefs -- a pointer to a return buffer of MX preferences.
** If NULL, don't try to populate.
** flags -- flags:
** DROPLOCALHOSt -- If true, all MX records less preferred
** DROPLOCALHOST -- If true, all MX records less preferred
** than the local host (as determined by $=w) will
** be discarded.
** TRYFALLBACK -- add also fallback MX host?
** ISAD -- host lookup was secure?
** rcode -- a pointer to an EX_ status code.
** pttl -- pointer to return TTL (can be NULL).
** port -- port number used in TLSA queries (_PORT._tcp.)
** pad -- (output parameter, pointer to) AD flag (can be NULL)
**
** Returns:
** The number of MX records found.
@ -559,7 +860,7 @@ hn2alabel(hostname)
*/
int
getmxrr(host, mxhosts, mxprefs, flags, rcode, pttl, port)
getmxrr(host, mxhosts, mxprefs, flags, rcode, pttl, port, pad)
char *host;
char **mxhosts;
unsigned short *mxprefs;
@ -567,6 +868,7 @@ getmxrr(host, mxhosts, mxprefs, flags, rcode, pttl, port)
int *rcode;
int *pttl;
int port;
int *pad;
{
register unsigned char *eom, *cp;
register int i, j, n;
@ -640,7 +942,7 @@ getmxrr(host, mxhosts, mxprefs, flags, rcode, pttl, port)
# endif /* DANE */
# if USE_EAI
if (!addr_is_ascii(host))
if (!str_is_print(host))
{
/* XXX memory leak? */
host = sm_rpool_strdup_x(CurEnv->e_rpool, hn2alabel(host));
@ -727,6 +1029,8 @@ getmxrr(host, mxhosts, mxprefs, flags, rcode, pttl, port)
ad = ad && hp->ad;
if (tTd(8, 2))
sm_dprintf("getmxrr(%s), hp=%p, ad=%d\n", host, (void*)hp, ad);
if (pad != NULL)
*pad = ad;
/* avoid problems after truncation in tcp packets */
if (n > sizeof(answer))
@ -813,14 +1117,22 @@ getmxrr(host, mxhosts, mxprefs, flags, rcode, pttl, port)
int nrr;
unsigned long flags;
flags = ad ? TLSAFLADMX : TLSAFLNOADMX;
flags = TLSAFLNEW;
if (pad != NULL && *pad)
flags |= TLSAFLADMX;
if (tTd(8, 20))
sm_dprintf("getmxrr: 1: host=%s, mx=%s, flags=%#lx\n", host, bp, flags);
nrr = gettlsa(bp, NULL, NULL, flags, ttl, port);
/* Only check qname if no TLSA RRs were found */
if (0 == nrr && cname2mx && '\0' != qname[0] &&
strcmp(qname, bp))
{
if (tTd(8, 20))
sm_dprintf("getmxrr: 2: host=%s, qname=%s, flags=%#lx\n", host, qname, flags);
gettlsa(qname, bp, NULL, flags, ttl, port);
/* XXX is this the right ad flag? */
}
}
# endif
@ -1009,7 +1321,7 @@ getmxrr(host, mxhosts, mxprefs, flags, rcode, pttl, port)
char *hn;
hn = MXHostBuf + 1;
if (!addr_is_ascii(hn))
if (!str_is_print(hn))
{
const char *ahn;
@ -1058,8 +1370,16 @@ getmxrr(host, mxhosts, mxprefs, flags, rcode, pttl, port)
else
cttl = SM_DEFAULT_TTL;
flags = (ad && n == HOST_SECURE)
? TLSAFLADMX : TLSAFLNOADMX;
flags = TLSAFLNEW;
if (ad && HOST_SECURE == n)
{
flags |= TLSAFLADMX;
if (pad != NULL)
*pad = ad;
}
if (TTD(8, 20))
sm_dprintf("getmxrr: 3: host=%s, mx=%s, flags=%#lx, ad=%d\n",
host, mxhosts[0], flags, ad);
nrr = gettlsa(mxhosts[0], NULL, NULL, flags,
cttl, port);
@ -1070,9 +1390,13 @@ getmxrr(host, mxhosts, mxprefs, flags, rcode, pttl, port)
if (0 == nrr && '\0' != qname[0] &&
strcmp(qname, mxhosts[0]))
{
gettlsa(qname, mxhosts[0], NULL, flags,
cttl, port);
if (tTd(8, 20))
sm_dprintf("getmxrr: 4: host=%s, qname=%s, flags=%#lx\n", host, qname, flags);
/* XXX is this the right ad flag? */
}
}
# endif
}
@ -1081,7 +1405,7 @@ getmxrr(host, mxhosts, mxprefs, flags, rcode, pttl, port)
/* if we have a default lowest preference, include that */
if (fallbackMX != NULL && !seenlocal)
{
/* TODO: DNSsec status of fallbacks */
/* TODO: DNSSEC status of fallbacks */
nmx = fallbackmxrr(nmx, prefs, mxhosts);
}
done:
@ -1175,7 +1499,7 @@ bestmx_map_lookup(map, name, av, statp)
# endif
_res.options &= ~(RES_DNSRCH|RES_DEFNAMES);
nmx = getmxrr(name, mxhosts, NULL, 0, statp, NULL, -1);
nmx = getmxrr(name, mxhosts, NULL, 0, statp, NULL, -1, NULL);
_res.options = saveopts;
if (nmx <= 0)
return NULL;

View File

@ -114,10 +114,6 @@ fatal_error(exc)
char MsgBuf[BUFSIZ*2]; /* text of most recent message */
static char HeldMessageBuf[sizeof(MsgBuf)]; /* for held messages */
#if NAMED_BIND && !defined(NO_DATA)
# define NO_DATA NO_ADDRESS
#endif
void
/*VARARGS1*/
#ifdef __STDC__

View File

@ -331,6 +331,12 @@ dochompheader(line, pflag, hdrp, e)
case '\015': /* cr */
qval[l++] = ' ';
break;
case '\\':
qval[l++] = fvalue[k];
++k;
XLEN(fvalue[k]);
qval[l++] = fvalue[k];
break;
case '"':
XLEN('\\');
qval[l++] = '\\';
@ -344,14 +350,22 @@ dochompheader(line, pflag, hdrp, e)
XLEN('"');
qval[l++] = '"';
qval[l] = '\0';
k += strlen(fvalue + k);
if (k >= sizeof(qval))
l = strlen(fvalue + k);
/*
** If there is something left in fvalue
** then it has been truncated.
** Note: the log entry might not be correct
** in the EAI case: to get the "real" length
** ilenx() would have to be applied to fvalue.
*/
if (l > 0)
{
if (LogLevel > 9)
sm_syslog(LOG_WARNING, e->e_id,
"Warning: truncated header '%s' before check with '%s' len=%d max=%d",
fname, rs, k,
(int) (sizeof(qval) - 1));
fname, rs, xlen + l, MAXNAME);
}
macdefine(&e->e_macro, A_TEMP,
macid("{currHeader}"), qval);
@ -498,7 +512,6 @@ dochompheader(line, pflag, hdrp, e)
** Contents of 'line' are destroyed.
*/
unsigned long
chompheader(line, pflag, hdrp, e)
char *line;
@ -1122,7 +1135,6 @@ eatheader(e, full, log)
** none
*/
#define XBUFLEN MAXNAME
#if (SYSLOG_BUFSIZE) >= 256
# ifndef MSGIDLOGLEN
@ -1130,11 +1142,11 @@ eatheader(e, full, log)
# define FIRSTLOGLEN 850
# else
# if MSGIDLOGLEN < 100
# ERROR "MSGIDLOGLEN too short"
# error "MSGIDLOGLEN too short"
# endif
/* XREF: this is "sizeof(sbuf)", see above */
# if MSGIDLOGLEN >= MAXLINE / 2
# ERROR "MSGIDLOGLEN too long"
# error "MSGIDLOGLEN too long"
# endif
/* 850 - 100 for original MSGIDLOGLEN */
@ -1142,7 +1154,7 @@ eatheader(e, full, log)
/* check that total length is ok */
# if FIRSTLOGLEN + 200 >= MAXLINE
# ERROR "MSGIDLOGLEN too long"
# error "MSGIDLOGLEN too long"
# endif
# if MSGIDLOGLEN > MAXNAME
# undef XBUFLEN
@ -1371,7 +1383,7 @@ priencode(p)
} while (0)
#if MAXNAME < 10
# ERROR "MAXNAME must be at least 10"
# error "MAXNAME must be at least 10"
#endif
char *

View File

@ -11,8 +11,6 @@ cpyr By using this file, you agree to the terms and conditions set
cpyr forth in the LICENSE file which can be found at the top level of
cpyr the sendmail distribution.
cpyr
cpyr $$Id: helpfile,v 8.49 2013-11-22 20:51:55 ca Exp $$
cpyr
smtp This is sendmail version $v
smtp Topics:
smtp HELO EHLO MAIL RCPT DATA
@ -39,7 +37,6 @@ ehlo TURN Turn the operation around [RFC821]
ehlo 8BITMIME Use 8-bit data [RFC1652]
ehlo SIZE Message size declaration [RFC1870]
ehlo VERB Verbose [Allman]
ehlo CHUNKING Chunking [RFC1830]
ehlo BINARYMIME Binary MIME [RFC1830]
ehlo PIPELINING Command Pipelining [RFC1854]
ehlo DSN Delivery Status Notification [RFC1891]
@ -48,6 +45,7 @@ ehlo STARTTLS Secure SMTP [RFC2487]
ehlo AUTH Authentication [RFC2554]
ehlo ENHANCEDSTATUSCODES Enhanced status codes [RFC2034]
ehlo DELIVERBY Deliver By [RFC2852]
ehlo SMTPUTF8 Internationalized Email [RFC6530]
mail MAIL From:<sender> [ <parameters> ]
mail Specifies the sender. Parameters are ESMTP extensions.
mail See "HELP DSN" for details.
@ -56,7 +54,7 @@ rcpt Specifies the recipient. Can be used any number of times.
rcpt Parameters are ESMTP extensions. See "HELP DSN" for details.
data DATA
data Following text is collected as the message.
data End with a single dot.
data End with a single dot on a line by itself.
rset RSET
rset Resets the system.
quit QUIT

View File

@ -83,7 +83,6 @@ int NextMacroId = 0240; /* codes for long named macros */
#define NEXTMACROID(mid) ((mid) + 1)
#endif /* _FFR_MORE_MACROS */
/*
** INITMACROS -- initialize the macro system
**
@ -411,6 +410,9 @@ mactabclear(mac)
** id -- Macro id. This is a single character macro name
** such as 'g', or a value returned by macid().
** value -- Macro value: either NULL, or a string.
**
** Returns:
** none.
*/
void
@ -442,8 +444,8 @@ macdefine(mac, vclass, id, value)
sm_dprintf(")\n");
}
#if USE_EAI && 0
if (('j' == id || 'm' == id) && !addr_is_ascii(value))
return an error/warning to caller and let them handle it.
// if (('j' == id || 'm' == id) && !addr_is_ascii(value))
// return an error/warning to caller and let them handle it.
#endif
if (mac->mac_rpool == NULL)
@ -504,6 +506,9 @@ macdefine(mac, vclass, id, value)
** mac -- Macro table.
** i -- Macro name, specified as an integer offset.
** value -- Macro value: either NULL, or a string.
**
** Returns:
** none.
*/
void
@ -758,7 +763,51 @@ wordinclass(str, cl)
int cl;
{
STAB *s;
#if _FFR_DYN_CLASS
MAP *map;
int status;
char *p;
char key[MAXLINE];
s = stab(str, ST_CLASS, ST_FIND);
return s != NULL && bitnset(bitidx(cl), s->s_class);
p = macname(cl);
s = stab(p, ST_DYNMAP, ST_FIND);
if (NULL == s)
{
#endif
s = stab(str, ST_CLASS, ST_FIND);
return s != NULL && bitnset(bitidx(cl), s->s_class);
#if _FFR_DYN_CLASS
}
map = &s->s_dynclass;
SM_REQUIRE(NULL != map);
SM_REQUIRE(!SM_IS_EMPTY(str));
if (bitset(MF_OPENBOGUS, map->map_mflags))
{
/* need to set some error! */
return false;
}
key[0] = '\0';
if (!SM_IS_EMPTY(map->map_tag))
{
sm_strlcpy(key, map->map_tag, sizeof(key));
sm_strlcat(key, ":", sizeof(key));
}
sm_strlcat(key, str, sizeof(key));
status = EX_OK;
p = (map->map_class->map_lookup)(map, key, NULL, &status);
if (NULL != p)
return true;
if ((EX_OK == status && NULL == p) || EX_NOTFOUND == status)
return false;
sm_syslog(LOG_WARNING, CurEnv->e_id,
"dynamic class: A{%s}: map lookup failed: key=%s, status=%d",
map->map_mname, key, status);
/* Note: this error is shown to the client, so do not "leak" info */
usrerr("451 4.3.1 temporary error");
return false;
#endif
}

View File

@ -326,9 +326,7 @@ main(argc, argv, envp)
V6LoopbackAddrFound = false;
# endif
#endif
#if XDEBUG
checkfd012("after openlog");
#endif
tTsetup(tTdvect, sizeof(tTdvect), "0-99.1,*_trace_*.1");
@ -672,6 +670,11 @@ main(argc, argv, envp)
sm_dprintf(" OpenSSL: linked 0x%08x\n",
(uint) TLS_version_num());
}
# if defined(LIBRESSL_VERSION_NUMBER)
if (tTd(0, 15))
sm_dprintf(" LibreSSL: compiled 0x%08x\n",
(uint) LIBRESSL_VERSION_NUMBER);
# endif
#endif /* STARTTLS */
/* clear sendmail's environment */
@ -1276,9 +1279,7 @@ main(argc, argv, envp)
** Extract special fields for local use.
*/
#if XDEBUG
checkfd012("before readcf");
#endif
vendor_pre_defaults(&BlankEnvelope);
readcf(getcfname(OpMode, SubmitMode, cftype, conffile),
@ -1377,7 +1378,7 @@ main(argc, argv, envp)
makeworkgroups();
#if USE_EAI
if (!SMTPUTF8 && MainEnvelope.e_smtputf8)
if (!SMTP_UTF8 && MainEnvelope.e_smtputf8)
{
usrerr("-U requires SMTPUTF8");
finis(false, true, EX_USAGE);
@ -1507,8 +1508,8 @@ main(argc, argv, envp)
usrerr("Illegal body type %s", BlankEnvelope.e_bodytype);
BlankEnvelope.e_bodytype = NULL;
}
else if (i != BODYTYPE_NONE)
SevenBitInput = (i == BODYTYPE_7BIT);
else if (BODYTYPE_7BIT == i)
BlankEnvelope.e_flags |= EF_7BITBODY;
/* tweak default DSN notifications */
if (DefaultNotify == 0)
@ -2014,9 +2015,7 @@ main(argc, argv, envp)
sm_sasl_init();
#endif
#if XDEBUG
checkfd012("before main() initmaps");
#endif
/*
** Do operation-mode-dependent initialization.
@ -2625,7 +2624,6 @@ main(argc, argv, envp)
/* init TLS for server, ignore result for now */
(void) initsrvtls(tls_ok);
#endif
nextreq:
p_flags = getrequests(&MainEnvelope);
@ -2663,8 +2661,8 @@ main(argc, argv, envp)
authinfo = buf;
if (tTd(75, 9))
sm_syslog(LOG_INFO, NOQID,
"main: where=not_calling_getauthinfo, RealHostAddr=%s",
anynet_ntoa(&RealHostAddr));
"main: where=not_calling_getauthinfo, RealHostAddr=%s, RealHostName=%s",
anynet_ntoa(&RealHostAddr), RealHostName);
}
else
/* WARNING: "non-braced" else */
@ -2818,7 +2816,7 @@ main(argc, argv, envp)
(MainEnvelope.e_smtputf8 = !asciistr(fromaddr))))
{
/* not very efficient: asciistr() may be called above already */
if (!SMTPUTF8 && !asciistr(fromaddr))
if (!SMTP_UTF8 && !asciistr(fromaddr))
{
usrerr("non-ASCII sender address %s requires SMTPUTF8",
fromaddr);
@ -2879,7 +2877,8 @@ main(argc, argv, envp)
/* collect body for UUCP return */
if (OpMode != MD_VERIFY)
collect(InChannel, false, NULL, &MainEnvelope, true);
collect(InChannel, SMTPMODE_NO, NULL, &MainEnvelope,
true);
finis(true, true, EX_USAGE);
/* NOTREACHED */
}
@ -2922,24 +2921,13 @@ main(argc, argv, envp)
int savederrors;
unsigned long savedflags;
/*
** workaround for compiler warning on Irix:
** do not initialize variable in the definition, but
** later on:
** warning(1548): transfer of control bypasses
** initialization of:
** variable "savederrors" (declared at line 2570)
** variable "savedflags" (declared at line 2571)
** goto giveup;
*/
savederrors = Errors;
savedflags = MainEnvelope.e_flags & EF_FATALERRS;
MainEnvelope.e_flags |= EF_GLOBALERRS;
MainEnvelope.e_flags &= ~EF_FATALERRS;
Errors = 0;
buffer_errors();
collect(InChannel, false, NULL, &MainEnvelope, true);
collect(InChannel, SMTPMODE_NO, NULL, &MainEnvelope, true);
/* header checks failed */
if (Errors > 0)
@ -3285,6 +3273,10 @@ sigterm(sig)
FIX_SYSV_SIGNAL(sig, sigterm);
ShutdownRequest = "signal";
errno = save_errno;
#if _FFR_DMTRIGGER
/* temporary? */
proc_list_signal(PROC_QM, sig);
#endif
return SIGFUNC_RETURN;
}
/*
@ -3427,7 +3419,7 @@ intsig(sig)
** none
**
** Side Effects:
** Trys to insure that we are immune to vagaries of
** Try to insure that we are immune to vagaries of
** the controlling tty.
*/
@ -3530,9 +3522,7 @@ disconnect(droplev, e)
errno = 0;
}
#if XDEBUG
checkfd012("disconnect");
#endif
if (LogLevel > 71)
sm_syslog(LOG_DEBUG, LOGID(e), "in background, pid=%d",
@ -4219,6 +4209,10 @@ testmodeline(line, e)
#if _FFR_8BITENVADDR
int len = sizeof(exbuf);
#endif
#if _FFR_TESTS
extern void t_hostsig __P((ADDRESS *, char *, MAILER *));
extern void t_parsehostsig __P((char *, MAILER *));
#endif
/* skip leading spaces */
while (*line == ' ')
@ -4226,6 +4220,7 @@ testmodeline(line, e)
lbp = NULL;
eightbit = false;
maps_reset_chged("testmodeline");
switch (line[0])
{
case '#':
@ -4376,7 +4371,36 @@ testmodeline(line, e)
case '$':
if (line[1] == '=')
{
#if _FFR_DYN_CLASS
MAP *dynmap;
STAB *st;
#endif
mid = macid(&line[2]);
#if _FFR_DYN_CLASS
if (mid != 0 &&
(st = stab(macname(mid), ST_DYNMAP, ST_FIND)) != NULL)
{
dynmap = &st->s_dynclass;
q = dynmap->map_class->map_cname;
if (SM_IS_EMPTY(q))
q = "implicit";
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"$=%s not possible for a dynamic class, use\n",
line + 2);
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"makemap -u %s %s",
q, dynmap->map_file);
if (!SM_IS_EMPTY(dynmap->map_tag))
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
" | grep -i '^%s:'",
dynmap->map_tag);
}
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, "\n");
return;
}
#endif
if (mid != 0)
stabapply(dump_class, mid);
return;
@ -4435,7 +4459,7 @@ testmodeline(line, e)
return;
}
nmx = getmxrr(p, mxhosts, NULL, TRYFALLBACK, &rcode,
NULL, -1);
NULL, -1, NULL);
if (nmx == NULLMX)
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"getmxrr(%s) returns null MX (See RFC7505)\n",
@ -4626,7 +4650,11 @@ testmodeline(line, e)
macdefine(&e->e_macro, A_TEMP,
macid("{addr_type}"), exbuf);
}
else if (SM_STRCASEEQ(&line[1], "parse"))
else if (SM_STRCASEEQ(&line[1], "parse")
#if _FFR_TESTS
|| SM_STRCASEEQ(&line[1], "hostsig")
#endif
)
{
if (*p == '\0')
{
@ -4653,11 +4681,20 @@ testmodeline(line, e)
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"Cannot parse\n");
else if (a.q_host != NULL && a.q_host[0] != '\0')
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
{
#if _FFR_TESTS
if (SM_STRCASEEQ(&line[1], "hostsig"))
t_hostsig(&a, NULL, NULL);
else
#endif /* _FFR_TESTS */
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"mailer %s, host %s, user %s\n",
a.q_mailer->m_name,
a.q_host,
a.q_user);
}
}
else
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"mailer %s, user %s\n",
@ -4743,6 +4780,31 @@ testmodeline(line, e)
r = NULL;
}
}
# if _FFR_TESTS
else if (SM_STRCASEEQ(&line[1], "hostsignature"))
{
STAB *st;
MAILER *m;
st = stab("esmtp", ST_MAILER, ST_FIND);
if (NULL == st)
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"Unknown mailer esmtp\n");
return;
}
m = st->s_mailer;
if (NULL == m)
{
(void) sm_io_fprintf(smioout, SM_TIME_DEFAULT,
"Unknown mailer esmtp\n");
return;
}
t_hostsig(NULL, p, m);
}
else if (SM_STRCASEEQ(&line[1], "parsesig"))
t_parsehostsig(p, NULL);
# endif /* _FFR_TESTS */
#endif /* DANE */
else
{

View File

@ -60,7 +60,7 @@ static bool extract_canonname __P((char *, char *, char *, char[], int));
static void map_close __P((STAB *, int));
static void map_init __P((STAB *, int));
#ifdef LDAPMAP
static STAB * ldapmap_findconn __P((SM_LDAP_STRUCT *));
static STAB *ldapmap_findconn __P((SM_LDAP_STRUCT *));
#endif
#if NISPLUS
static bool nisplus_getcanonname __P((char *, int, int *));
@ -90,6 +90,176 @@ static STAB *socket_map_findconn __P((const char*));
# endif
#endif /* ENOSYS */
/*
** MAP_HAS_CHGED -- check whether fd was updated or fn refers to a different file
**
** Parameters:
** map -- map being checked
** fn -- (full) file name of map.
** fd -- fd of map.
**
** Returns:
** true iff file referenced by fd was updated
** or fn refers to a different file.
*/
static bool map_has_chged __P((MAP *, const char *, int));
static bool
map_has_chged(map, fn, fd)
MAP *map;
const char *fn;
int fd;
{
struct stat stbuf;
#if _FFR_MAP_CHK_FILE
struct stat nstbuf;
#endif
#if _FFR_MAP_CHK_FILE > 1
if (tTd(38, 8))
sm_dprintf("map_has_chged: fn=%s, fd=%d, checked=%d\n",
fn, fd, bitset(MF_CHKED_CHGD, map->map_mflags));
if (fd < 0)
return true;
/* XXX check can be disabled via -d38.101 for testing */
if (bitset(MF_CHKED_CHGD, map->map_mflags) && !tTd(38, 101))
return false;
map->map_mflags |= MF_CHKED_CHGD;
#endif
if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
{
if (tTd(38, 4))
sm_dprintf("reopen map: name=%s, fd=%d\n", map->map_mname, fd);
return true;
}
#if _FFR_MAP_CHK_FILE
if (stat(fn, &nstbuf) == 0 &&
(nstbuf.st_dev != stbuf.st_dev || nstbuf.st_ino != stbuf.st_ino))
{
if (tTd(38, 4) && stat(fn, &nstbuf) == 0)
sm_dprintf("reopen map: fn=%s, ndev=%d, dev=%d, nino=%d, ino=%d\n",
fn, (int) nstbuf.st_dev, (int) stbuf.st_dev,
(int) nstbuf.st_ino, (int) stbuf.st_ino);
return true;
}
#endif
return false;
}
#if _FFR_MAP_CHK_FILE > 1
/*
** MAP_RESET_CHGD -- reset MF_CHKED_CHGD in a map
**
** Parameters:
** s -- STAB entry: if map: reset MF_CHKED_CHGD
** unused -- unused variable
**
** Returns:
** none.
*/
static void map_reset_chged __P((STAB *, int));
/* ARGSUSED1 */
static void
map_reset_chged(s, unused)
STAB *s;
int unused;
{
MAP *map;
/* has to be a map */
if (ST_MAP != s->s_symtype
#if _FFR_DYN_CLASS
&& ST_DYNMAP != s->s_symtype
#endif
)
return;
map = &s->s_map;
if (!bitset(MF_VALID, map->map_mflags))
return;
if (tTd(38, 8))
sm_dprintf("map_reset_chged: name=%s, checked=%d\n",
map->map_mname, bitset(MF_CHKED_CHGD, map->map_mflags));
map->map_mflags &= ~MF_CHKED_CHGD;
}
/*
** MAPS_RESET_CHGD -- reset MF_CHKED_CHGD in all maps
**
** Parameters:
** msg - caller (for debugging)
**
** Returns:
** none.
*/
void
maps_reset_chged(msg)
const char *msg;
{
if (tTd(38, 16))
sm_dprintf("maps_reset_chged: msg=%s\n", msg);
stabapply(map_reset_chged, 0);
}
#endif /* _FFR_MAP_CHK_FILE > 1 */
#if NEWDB || CDB || (NDBM && _FFR_MAP_CHK_FILE)
static bool smdb_add_extension __P((char *, int, char *, char *));
/*
** SMDB_ADD_EXTENSION -- Adds an extension to a file name.
**
** Just adds a . followed by a string to a db_name if there
** is room and the db_name does not already have that extension.
**
** Parameters:
** full_name -- The final file name.
** max_full_name_len -- The max length for full_name.
** db_name -- The name of the db.
** extension -- The extension to add.
**
** Returns:
** SMDBE_OK -- Success.
** Anything else is an error. Look up more info about the
** error in the comments for the specific open() used.
*/
static bool
smdb_add_extension(full_name, max_full_name_len, db_name, extension)
char *full_name;
int max_full_name_len;
char *db_name;
char *extension;
{
int extension_len;
int db_name_len;
if (full_name == NULL || db_name == NULL || extension == NULL)
return false; /* SMDBE_INVALID_PARAMETER; */
extension_len = strlen(extension);
db_name_len = strlen(db_name);
if (extension_len + db_name_len + 2 > max_full_name_len)
return false; /* SMDBE_DB_NAME_TOO_LONG; */
if (db_name_len < extension_len + 1 ||
db_name[db_name_len - extension_len - 1] != '.' ||
strcmp(&db_name[db_name_len - extension_len], extension) != 0)
(void) sm_snprintf(full_name, max_full_name_len, "%s.%s",
db_name, extension);
else
(void) sm_strlcpy(full_name, db_name, max_full_name_len);
return true;
}
#endif /* NEWDB || CDB || (NDBM && _FFR_MAP_CHK_FILE) */
/*
** MAP.C -- implementations for various map classes.
**
@ -130,6 +300,7 @@ static STAB *socket_map_findconn __P((const char*));
** to be more properly integrated into the map structure.
*/
/* XREF: conf.c must use the same expression */
#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL
# define LOCK_ON_OPEN 1 /* we can open/create a locked file */
#else
@ -459,6 +630,52 @@ map_rewrite(map, s, slen, av)
sm_dprintf("map_rewrite => %s\n", buf);
return buf;
}
/*
** MAPCHOWN -- if available fchown() the fds to TrustedUid
**
** Parameters:
** mapname - name of map (for error reporting)
** fd0 - first fd (must be valid)
** fd1 - second fd (<0: do not use)
** filename - name of file (for error reporting)
**
** Returns:
** none.
*/
static void mapchown __P((const char *, int, int, const char *));
static void
mapchown(mapname, fd0, fd1, filename)
const char *mapname;
int fd0;
int fd1;
const char *filename;
{
if (!(geteuid() == 0 && TrustedUid != 0))
return;
#if HASFCHOWN
if (fchown(fd0, TrustedUid, -1) < 0 ||
(fd1 >= 0 && fchown(fd1, TrustedUid, -1) < 0))
{
int err = errno;
sm_syslog(LOG_ALERT, NOQID,
"ownership change on %s failed: %s",
filename, sm_errstring(err));
message("050 ownership change on %s failed: %s",
filename, sm_errstring(err));
}
#else /* HASFCHOWN */
sm_syslog(LOG_ALERT, NOQID,
"no fchown(): cannot change ownership on %s",
mapname);
message("050 no fchown(): cannot change ownership on %s",
mapname);
#endif /* HASFCHOWN */
}
/*
** INITMAPS -- rebuild alias maps
**
@ -472,14 +689,11 @@ map_rewrite(map, s, slen, av)
void
initmaps()
{
#if XDEBUG
checkfd012("entering initmaps");
#endif
stabapply(map_init, 0);
#if XDEBUG
checkfd012("exiting initmaps");
#endif
}
/*
** MAP_INIT -- rebuild a map
**
@ -533,7 +747,7 @@ map_init(s, unused)
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
}
(void) rebuildaliases(map, false);
(void) rebuildaliases(map);
return;
}
/*
@ -692,7 +906,7 @@ map_close(s, bogus)
map->map_mflags |= MF_CLOSING;
map->map_class->map_close(map);
}
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_OPENBOGUS|MF_CLOSING);
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_OPENBOGUS|MF_CLOSING|MF_CHKED_CHGD);
}
#if defined(SUN_EXTENSIONS) && defined(SUN_INIT_DOMAIN)
@ -1072,14 +1286,14 @@ dns_map_parseargs(map,args)
break;
switch (*++p)
{
# if DNSSEC_TEST
# if DNSSEC_TEST || _FFR_NAMESERVER
case '@':
++p;
if (nsportip(p) < 0)
syserr("dns map %s: nsportip(%s)=failed",
map->map_mname, p);
break;
# endif /* DNSSEC_TEST */
# endif /* DNSSEC_TEST || _FFR_NAMESERVER */
case 'A':
map->map_mflags |= MF_APPEND;
@ -1243,7 +1457,7 @@ dns_map_parseargs(map,args)
**
** Parameters:
** map -- pointer to MAP
** name -- name to lookup
** name -- name to look up
** av -- arguments to interpolate into buf.
** statp -- pointer to status (EX_)
**
@ -1694,28 +1908,7 @@ ndbm_map_open(map, mode)
else
{
map->map_mflags |= MF_LOCKED;
if (geteuid() == 0 && TrustedUid != 0)
{
# if HASFCHOWN
if (fchown(dfd, TrustedUid, -1) < 0 ||
fchown(pfd, TrustedUid, -1) < 0)
{
int err = errno;
sm_syslog(LOG_ALERT, NOQID,
"ownership change on %s failed: %s",
map->map_file, sm_errstring(err));
message("050 ownership change on %s failed: %s",
map->map_file, sm_errstring(err));
}
# else /* HASFCHOWN */
sm_syslog(LOG_ALERT, NOQID,
"no fchown(): cannot change ownership on %s",
map->map_file);
message("050 no fchown(): cannot change ownership on %s",
map->map_file);
# endif /* HASFCHOWN */
}
mapchown(map->map_file, dfd, pfd, map->map_file);
}
return true;
}
@ -1735,7 +1928,10 @@ ndbm_map_lookup(map, name, av, statp)
datum key, val;
int dfd, pfd;
char keybuf[MAXNAME + 1]; /* EAI:ok */
struct stat stbuf;
# if _FFR_MAP_CHK_FILE
char buf[MAXPATHLEN];
# endif
const char *fn = NULL;
if (tTd(38, 20))
sm_dprintf("ndbm_map_lookup(%s, %s)\n",
@ -1752,13 +1948,24 @@ ndbm_map_lookup(map, name, av, statp)
makelower_buf(keybuf, keybuf, sizeof(keybuf));
key.dptr = keybuf;
}
# if _FFR_MAP_CHK_FILE
if (!smdb_add_extension(buf, sizeof(buf), map->map_file, "pag"))
{
errno = 0;
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("ndbm map \"%s\": map file %s name too long",
map->map_mname, map->map_file);
return NULL;
}
fn = buf;
# endif
lockdbm:
dfd = dbm_dirfno((DBM *) map->map_db1);
if (dfd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(dfd, map->map_file, ".dir", LOCK_SH);
pfd = dbm_pagfno((DBM *) map->map_db1);
if (pfd < 0 || fstat(pfd, &stbuf) < 0 ||
stbuf.st_mtime > map->map_mtime)
if (map_has_chged(map, fn, pfd))
{
/* Reopen the database to sync the cache */
int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
@ -2070,26 +2277,14 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
char buf[MAXPATHLEN];
/* do initial file and directory checks */
if (sm_strlcpy(buf, map->map_file, sizeof(buf)) >= sizeof(buf))
if (!smdb_add_extension(buf, sizeof(buf), map->map_file, "db"))
{
errno = 0;
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("map \"%s\": map file %s name too long",
syserr("db map \"%s\": map file %s name too long",
map->map_mname, map->map_file);
return false;
}
i = strlen(buf);
if (i < 3 || strcmp(&buf[i - 3], ".db") != 0)
{
if (sm_strlcat(buf, ".db", sizeof(buf)) >= sizeof(buf))
{
errno = 0;
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("map \"%s\": map file %s name too long",
map->map_mname, map->map_file);
return false;
}
}
mode &= O_ACCMODE;
omode = mode;
@ -2121,7 +2316,7 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
if (i == ENOENT)
prob = "missing";
if (tTd(38, 2))
sm_dprintf("\t%s map file: %s\n", prob, sm_errstring(i));
sm_dprintf("\t%s map file %s: %s\n", prob, buf, sm_errstring(i));
errno = i;
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("%s map \"%s\": %s map file %s",
@ -2299,36 +2494,14 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
map->map_mflags |= MF_LOCKED;
# if LOCK_ON_OPEN
if (fd >= 0 && mode == O_RDONLY)
{
(void) lockfile(fd, buf, NULL, LOCK_UN);
}
# endif /* LOCK_ON_OPEN */
# endif
/* try to make sure that at least the database header is on disk */
if (mode == O_RDWR)
{
(void) db->sync(db, 0);
if (geteuid() == 0 && TrustedUid != 0)
{
# if HASFCHOWN
if (fchown(fd, TrustedUid, -1) < 0)
{
int err = errno;
sm_syslog(LOG_ALERT, NOQID,
"ownership change on %s failed: %s",
buf, sm_errstring(err));
message("050 ownership change on %s failed: %s",
buf, sm_errstring(err));
}
# else /* HASFCHOWN */
sm_syslog(LOG_ALERT, NOQID,
"no fchown(): cannot change ownership on %s",
map->map_file);
message("050 no fchown(): cannot change ownership on %s",
map->map_file);
# endif /* HASFCHOWN */
}
mapchown(map->map_file, fd, -1, buf);
}
map->map_db2 = (ARBPTR_T) db;
@ -2342,6 +2515,18 @@ db_map_open(map, mode, mapclassname, dbtype, openinfo)
if (fd >= 0 && fstat(fd, &st) >= 0)
map->map_mtime = st.st_mtime;
# if _FFR_TESTS
if (tTd(68, 101) && fd >= 0 && mode == O_RDONLY)
{
int sl;
sl = tTdlevel(68) - 100;
/* XXX test checks for map type!!! */
sm_dprintf("hash_map_open: sleep=%d\n", sl);
sleep(sl);
}
# endif
if (mode == O_RDONLY && bitset(MF_ALIAS, map->map_mflags) &&
!aliaswait(map, ".db", true))
return false;
@ -2362,11 +2547,9 @@ db_map_lookup(map, name, av, statp)
{
DBT key, val;
register DB *db = (DB *) map->map_db2;
int i;
int st;
int save_errno;
int fd;
struct stat stbuf;
char keybuf[MAXNAME + 1]; /* EAI:ok */
char buf[MAXPATHLEN];
@ -2376,18 +2559,14 @@ db_map_lookup(map, name, av, statp)
if (tTd(38, 20))
sm_dprintf("db_map_lookup(%s, %s)\n",
map->map_mname, name);
if (sm_strlcpy(buf, map->map_file, sizeof(buf)) >= sizeof(buf))
if (!smdb_add_extension(buf, sizeof(buf), map->map_file, "db"))
{
errno = 0;
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("map \"%s\": map file %s name too long",
syserr("db map \"%s\": map file %s name too long",
map->map_mname, map->map_file);
return NULL;
}
i = strlen(buf);
if (i > 3 && strcmp(&buf[i - 3], ".db") == 0)
buf[i - 3] = '\0';
key.size = strlen(name);
if (key.size > sizeof(keybuf) - 1)
@ -2405,15 +2584,15 @@ db_map_lookup(map, name, av, statp)
errno = db->fd(db, &fd);
# endif /* DB_VERSION_MAJOR < 2 */
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, buf, ".db", LOCK_SH);
if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
(void) lockfile(fd, buf, NULL, LOCK_SH);
if (map_has_chged(map, buf, fd))
{
/* Reopen the database to sync the cache */
int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
: O_RDONLY;
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, buf, ".db", LOCK_UN);
(void) lockfile(fd, buf, NULL, LOCK_UN);
map->map_mflags |= MF_CLOSING;
map->map_class->map_close(map);
map->map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
@ -2498,7 +2677,7 @@ db_map_lookup(map, name, av, statp)
}
save_errno = errno;
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, buf, ".db", LOCK_UN);
(void) lockfile(fd, buf, NULL, LOCK_UN);
if (st != 0)
{
errno = save_errno;
@ -2686,56 +2865,6 @@ db_map_close(map)
** CDB Modules
*/
static bool smdb_add_extension __P((char *, int, char *, char *));
/*
** SMDB_ADD_EXTENSION -- Adds an extension to a file name.
**
** Just adds a . followed by a string to a db_name if there
** is room and the db_name does not already have that extension.
**
** Parameters:
** full_name -- The final file name.
** max_full_name_len -- The max length for full_name.
** db_name -- The name of the db.
** extension -- The extension to add.
**
** Returns:
** SMDBE_OK -- Success.
** Anything else is an error. Look up more info about the
** error in the comments for the specific open() used.
*/
static bool
smdb_add_extension(full_name, max_full_name_len, db_name, extension)
char *full_name;
int max_full_name_len;
char *db_name;
char *extension;
{
int extension_len;
int db_name_len;
if (full_name == NULL || db_name == NULL || extension == NULL)
return false; /* SMDBE_INVALID_PARAMETER; */
extension_len = strlen(extension);
db_name_len = strlen(db_name);
if (extension_len + db_name_len + 2 > max_full_name_len)
return false; /* SMDBE_DB_NAME_TOO_LONG; */
if (db_name_len < extension_len + 1 ||
db_name[db_name_len - extension_len - 1] != '.' ||
strcmp(&db_name[db_name_len - extension_len], extension) != 0)
(void) sm_snprintf(full_name, max_full_name_len, "%s.%s",
db_name, extension);
else
(void) sm_strlcpy(full_name, db_name, max_full_name_len);
return true;
}
bool
cdb_map_open(map, mode)
MAP *map;
@ -2748,8 +2877,9 @@ cdb_map_open(map, mode)
char buf[MAXPATHLEN];
if (tTd(38, 2))
sm_dprintf("cdb_map_open(%s, %s, %d)\n",
map->map_mname, map->map_file, mode);
sm_dprintf("cdb_map_open(%s, %s, %s)\n",
map->map_mname, map->map_file,
O_RDWR == (mode & O_ACCMODE) ? "rdwr" : "rdonly");
map->map_db1 = (ARBPTR_T)NULL;
map->map_db2 = (ARBPTR_T)NULL;
@ -2844,6 +2974,10 @@ cdb_map_open(map, mode)
/* actually lock the opened file */
if (!lockfile(fd, buf, NULL, mode == O_RDONLY ? LOCK_SH : LOCK_EX))
syserr("cdb_map_open: cannot lock %s", buf);
# else /* !LOCK_ON_OPEN */
if (tTd(55, 60))
sm_dprintf("lockopen(%s, fd=%d, action=nb, type=%s): SUCCESS\n",
buf, fd, mode == O_RDONLY ? "rd" : "wr");
# endif /* !LOCK_ON_OPEN */
map->map_lockfd = fd;
@ -2867,8 +3001,20 @@ cdb_map_open(map, mode)
}
map->map_db2 = (ARBPTR_T)cdbmp;
mapchown(map->map_file, fd, -1, buf);
return true;
}
(void) lockfile(fd, buf, NULL, LOCK_UN);
# if _FFR_TESTS
if (tTd(68, 101))
{
int sl;
sl = tTdlevel(68) - 100;
sm_dprintf("cdb_map_open: sleep=%d\n", sl);
sleep(sl);
}
# endif
cdbp = (struct cdb *) xalloc(sizeof(*cdbp));
status = cdb_init(cdbp, fd);
@ -2879,7 +3025,13 @@ cdb_map_open(map, mode)
syserr("initialization of cdb map failed");
return false;
}
map->map_db1 = (ARBPTR_T)cdbp;
if (bitset(MF_ALIAS, map->map_mflags) && !aliaswait(map, CDBEXT, true))
{
close(fd); /* XXX more error handling needed? */
return false;
}
return true;
}
@ -2896,7 +3048,6 @@ cdb_map_lookup(map, name, av, statp)
int st, fd;
char key[MAXNAME + 1]; /* EAI:ok */
char buf[MAXPATHLEN];
struct stat stbuf;
data = NULL;
cdbmap = map->map_db1;
@ -2909,7 +3060,7 @@ cdb_map_lookup(map, name, av, statp)
if (!bitset(MF_OPTIONAL, map->map_mflags))
syserr("cdb map \"%s\": map file %s name too long",
map->map_mname, map->map_file);
return false;
return NULL;
}
klen = strlen(name);
@ -2925,8 +3076,7 @@ cdb_map_lookup(map, name, av, statp)
fd = map->map_lockfd;
if (fd >= 0 && !bitset(MF_LOCKED, map->map_mflags))
(void) lockfile(fd, buf, NULL, LOCK_SH);
if (fd < 0 || fstat(fd, &stbuf) < 0 || stbuf.st_mtime > map->map_mtime)
if (map_has_chged(map, buf, fd))
{
/* Reopen the database to sync the cache */
int omode = bitset(map->map_mflags, MF_WRITABLE) ? O_RDWR
@ -3097,7 +3247,7 @@ cdb_map_close(map)
# endif
/*
** NIS_MAP_OPEN -- open DBM map
** NIS_MAP_OPEN -- open NIS map
*/
bool
@ -4037,7 +4187,7 @@ ldapmap_lookup(map, name, av, statp)
char *argv[SM_LDAP_ARGS];
char keybuf[MAXKEY];
# if SM_LDAP_ARGS != MAX_MAP_ARGS
# ERROR "SM_LDAP_ARGS must be the same as MAX_MAP_ARGS"
# error "SM_LDAP_ARGS must be the same as MAX_MAP_ARGS"
# endif
# define AV_FREE(av) \

View File

@ -54,6 +54,10 @@ extern char *macro_map_lookup __P((MAP *, char *, char **, int *));
extern bool map_parseargs __P((MAP *, char *));
#if LDAPMAP
extern bool ldapmap_parseargs __P((MAP *, char *));
#endif
#if NDBM
extern char *ndbm_map_lookup __P((MAP *, char *, char **, int *));
extern void ndbm_map_store __P((MAP *, char *, char *));
@ -68,6 +72,10 @@ extern void null_map_close __P((MAP *));
extern char *null_map_lookup __P((MAP *, char *, char **, int *));
extern void null_map_store __P((MAP *, char *, char *));
#if PH_MAP
extern bool ph_map_parseargs __P((MAP *, char *));
#endif
extern char *prog_map_lookup __P((MAP *, char *, char **, int *));
extern bool regex_map_init __P((MAP *, char *));

View File

@ -351,7 +351,6 @@ mci_clear(mci)
mactabclear(&mci->mci_macro);
}
/*
** MCI_GET -- get information about a particular host
**
@ -617,6 +616,7 @@ struct mcifbits
};
static struct mcifbits MciFlags[] =
{
{ MCIF_OCC_INCR, "OCC_INCR" },
{ MCIF_CACHED, "CACHED" },
{ MCIF_ESMTP, "ESMTP" },
{ MCIF_EXPN, "EXPN" },
@ -630,7 +630,6 @@ static struct mcifbits MciFlags[] =
{ MCIF_CVT7TO8, "CVT7TO8" },
{ MCIF_INMIME, "INMIME" },
{ MCIF_AUTH, "AUTH" },
{ MCIF_AUTH2, "AUTH2" },
{ MCIF_AUTHACT, "AUTHACT" },
{ MCIF_ENHSTAT, "ENHSTAT" },
{ MCIF_PIPELINED, "PIPELINED" },
@ -640,8 +639,16 @@ static struct mcifbits MciFlags[] =
{ MCIF_TLSACT, "TLSACT" },
#endif
{ MCIF_DLVR_BY, "DLVR_BY" },
#if _FFR_IGNORE_EXT_ON_HELO
{ MCIF_HELO, "HELO" },
#endif
{ MCIF_INLONGLINE, "INLONGLINE" },
{ MCIF_AUTH2, "AUTH2" },
{ MCIF_ONLY_EHLO, "ONLY_EHLO" },
{ MCIF_NOTSTICKY, "NOTSTICKY" },
#if USE_EAI
{ MCIF_EAI, "EAI" },
#endif
{ 0, NULL }
};
@ -1200,7 +1207,7 @@ mci_traverse_persistent(action, pathname)
struct dirent *e;
char newpath[MAXPATHLEN];
#if MAXPATHLEN <= MAXNAMLEN - 3
# ERROR "MAXPATHLEN <= MAXNAMLEN - 3"
# error "MAXPATHLEN <= MAXNAMLEN - 3"
#endif
if ((d = opendir(pathname)) == NULL)

View File

@ -71,7 +71,6 @@ static void milter_delrcpt __P((char *, ssize_t, ENVELOPE *, const char *));
static int milter_replbody __P((char *, ssize_t, bool, ENVELOPE *, const char *));
static int milter_set_macros __P((char *, char **, char *, int));
/* milter states */
# define SMFS_CLOSED 'C' /* closed for all further actions */
# define SMFS_OPEN 'O' /* connected to remote milter filter */
@ -1877,6 +1876,24 @@ milter_abort_filter(m, e)
** none
*/
#if _FFR_TESTS
# define TST_EO \
do \
{ \
if (tTd(86, 100) && \
(SMFIC_EOH == cmd || SMFIC_BODYEOB == cmd) && \
strncmp(macros[i], "{EO", 3) == 0) \
{ \
if (SMFIC_EOH == cmd) \
v = "at_EOH"; \
else if (SMFIC_BODYEOB == cmd) \
v = "at_EOM"; \
} \
} while (0)
#else
# define TST_EO ((void) 0)
#endif
static void
milter_send_macros(m, macros, cmd, e)
struct milter *m;
@ -1904,6 +1921,7 @@ milter_send_macros(m, macros, cmd, e)
if (mid == 0)
continue;
v = macvalue(mid, e);
TST_EO;
if (v == NULL)
continue;
expand(v, exp, sizeof(exp), e);
@ -1928,6 +1946,7 @@ milter_send_macros(m, macros, cmd, e)
if (mid == 0)
continue;
v = macvalue(mid, e);
TST_EO;
if (v == NULL)
continue;
expand(v, exp, sizeof(exp), e);
@ -2289,7 +2308,7 @@ milter_command(cmd, data, sz, stage, e, state, where, cmd_error)
/* log the time it took for the command per filter */
sm_syslog(LOG_INFO, e->e_id,
"Milter (%s): time command (%c), %d",
m->mf_name, command, (int) (tn - curtime()));
m->mf_name, command, (int) (curtime() - tn));
}
if (*state != SMFIR_CONTINUE)
@ -3329,9 +3348,9 @@ milter_changeheader(m, response, rlen, e)
** MILTER_SPLIT_RESPONSE -- Split response into fields.
**
** Parameters:
** response -- encoded repsonse.
** response -- encoded response.
** rlen -- length of response.
** pargc -- number of arguments (ouput)
** pargc -- number of arguments (output)
**
** Returns:
** array of pointers to the individual strings

View File

@ -347,7 +347,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
goto writeerr;
if (tTd(43, 35))
sm_dprintf(" ...%s\n", buf);
collect(e->e_dfp, false, &hdr, e, false);
collect(e->e_dfp, SMTPMODE_NO, &hdr, e, false);
if (tTd(43, 101))
putline("+++after collect", mci);
if (!putheader(mci, hdr, e, flags))
@ -409,7 +409,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
goto writeerr;
mci->mci_flags |= MCIF_INMIME;
collect(e->e_dfp, false, &hdr, e, false);
collect(e->e_dfp, SMTPMODE_NO, &hdr, e, false);
if (tTd(43, 101))
putline("+++after collect", mci);
if (!putheader(mci, hdr, e, flags))
@ -483,7 +483,7 @@ mime8to7(mci, header, e, boundaries, flags, level)
** If more than 1/8 of the total characters have the
** eighth bit set, use base64; else use quoted-printable.
** However, only encode binary encoded data as base64,
** since otherwise the NL=>CRLF mapping will be a problem.
** since otherwise the LF=>CRLF mapping will be a problem.
*/
if (tTd(43, 8))
@ -837,7 +837,7 @@ mime_getchar(fp, boundaries, btp)
return *bp++;
}
/*
** MIME_GETCHAR_CRLF -- do mime_getchar, but translate NL => CRLF
** MIME_GETCHAR_CRLF -- do mime_getchar, but translate LF => CRLF
**
** Parameters:
** fp -- the input file.

View File

@ -89,7 +89,7 @@ parseaddr(addr, a, flags, delim, delimptr, e, isrcpt)
#if _FFR_8BITENVADDR
if (bitset(RF_IS_EXT, flags) && addr != NULL)
{
int len = 0;
int len;
addr = quote_internal_chars(addr, NULL, &len, NULL);
}
@ -155,8 +155,9 @@ parseaddr(addr, a, flags, delim, delimptr, e, isrcpt)
a = buildaddr(pvp, a, flags, e);
#if _FFR_8BITENVADDR
if (NULL != a->q_user)
{
int len = 0;
int len;
a->q_user = quote_internal_chars(a->q_user, NULL, &len, e->e_rpool); /* EAI: ok */
}
@ -267,7 +268,7 @@ parseaddr(addr, a, flags, delim, delimptr, e, isrcpt)
** isrcpt -- true iff the address is for a recipient.
**
** Returns:
** true -- if the address has characters that are reservered
** true -- if the address has characters that are reserved
** for macros or is too long.
** false -- otherwise.
*/
@ -398,7 +399,7 @@ hasctrlchar(addr, isrcpt, complain)
break;
}
}
if (!SMTPUTF8 && !EightBitAddrOK && (*addr & 0340) == 0200)
if (!SMTP_UTF8 && !EightBitAddrOK && (*addr & 0340) == 0200)
{
setstat(EX_USAGE);
result = "8-bit character";
@ -447,7 +448,7 @@ allocaddr(a, flags, paddr, e)
ENVELOPE *e;
{
if (tTd(24, 4))
sm_dprintf("allocaddr(flags=%x, paddr=%s, ad=%d)\n", flags, paddr, bitset(EF_SECURE, e->e_flags));
sm_dprintf("allocaddr: flags=%x, paddr=%s, ad=%d\n", flags, paddr, bitset(EF_SECURE, e->e_flags));
a->q_paddr = paddr;
@ -688,7 +689,6 @@ unsigned char TokTypeNoC[256] =
ATM,ATM,ATM,ATM,ATM,ATM,ATM,ATM, ATM,ATM,ATM,ATM,ATM,ATM,ATM,ONE
};
#define NOCHAR (-1) /* signal nothing in lookahead token */
char **
@ -2015,6 +2015,9 @@ buildaddr(tv, a, flags, e)
char **hostp;
char hbuf[MAXNAME + 1]; /* EAI:ok */
static char ubuf[MAXNAME_I + 2];
#if _FFR_8BITENVADDR
int len;
#endif
if (tTd(24, 5))
{
@ -2211,7 +2214,12 @@ buildaddr(tv, a, flags, e)
}
/* rewrite according recipient mailer rewriting rules */
macdefine(&e->e_macro, A_PERM, 'h', a->q_host);
#if _FFR_8BITENVADDR
p = quote_internal_chars(a->q_host, NULL, &len, NULL);
#else
p = a->q_host;
#endif
macdefine(&e->e_macro, A_PERM, 'h', p);
if (ConfigLevel >= 10 ||
!bitset(RF_SENDERADDR|RF_HEADERADDR, flags))
@ -2477,7 +2485,6 @@ static struct qflags AddressFlags[] =
{ "QEXPANDED", QEXPANDED },
{ "QDELIVERED", QDELIVERED },
{ "QDELAYED", QDELAYED },
{ "QTHISPASS", QTHISPASS },
{ "QALIAS", QALIAS },
{ "QBYTRACE", QBYTRACE },
{ "QBYNDELAY", QBYNDELAY },
@ -2485,9 +2492,11 @@ static struct qflags AddressFlags[] =
{ "QINTBCC", QINTBCC },
{ "QDYNMAILER", QDYNMAILER },
{ "QSECURE", QSECURE },
{ "QQUEUED", QQUEUED },
{ "QINTREPLY", QINTREPLY },
{ "QMXSECURE", QMXSECURE },
{ "QTHISPASS", QTHISPASS },
{ "QRCPTOK", QRCPTOK },
{ "QQUEUED", QQUEUED },
{ NULL, 0 }
};
@ -2880,7 +2889,11 @@ maplocaluser(a, sendq, aliaslevel, e)
{
register char **pvp;
register ADDRESS *SM_NONVOLATILE a1 = NULL;
char *p;
char pvpbuf[PSBUFSIZE];
#if _FFR_8BITENVADDR
int len;
#endif
if (tTd(29, 1))
{
@ -2897,7 +2910,12 @@ maplocaluser(a, sendq, aliaslevel, e)
return;
}
macdefine(&e->e_macro, A_PERM, 'h', a->q_host);
#if _FFR_8BITENVADDR
p = quote_internal_chars(a->q_host, NULL, &len, NULL);
#else
p = a->q_host;
#endif
macdefine(&e->e_macro, A_PERM, 'h', p);
macdefine(&e->e_macro, A_PERM, 'u', a->q_user);
macdefine(&e->e_macro, A_PERM, 'z', a->q_home);
@ -3321,8 +3339,10 @@ rscheck(rwset, p1, p2, e, flags, logl, host, logid, addr, addrstr)
rwset, p1, lbuf, ubuf);
else
sm_syslog(LOG_NOTICE, logid,
"ruleset=%s, arg1=%s%s, reject=%s",
rwset, p1, lbuf, MsgBuf);
"ruleset=%s, arg1=%s%s, %s=%s",
rwset, p1, lbuf,
bitset(RSF_STATUS, flags) ? "status" : "reject",
MsgBuf);
}
finis: ;

View File

@ -21,6 +21,9 @@ SM_RCSID("@(#)$Id: queue.c,v 8.1000 2013-11-22 20:51:56 ca Exp $")
#if _FFR_DMTRIGGER
# include <sm/notify.h>
#endif
#if USE_EAI
# include <sm/ixlen.h>
#endif
#define RELEASE_QUEUE (void) 0
#define ST_INODE(st) (st).st_ino
@ -295,7 +298,6 @@ hash_q(p, h)
#define FILE_SYS_BLKSIZE(i) FILE_SYS(i).fs_blksize
#define FILE_SYS_DEV(i) FILE_SYS(i).fs_dev
/*
** Current qf file field assignments:
**
@ -744,6 +746,8 @@ queueup(e, flags)
(void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'D');
if (bitset(QINTBCC, q->q_flags))
(void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'B');
if (bitset(QMXSECURE, q->q_flags))
(void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'X');
if (q->q_alias != NULL &&
bitset(QALIAS, q->q_alias->q_flags))
(void) sm_io_putc(tfp, SM_TIME_DEFAULT, 'A');
@ -1637,7 +1641,6 @@ runqueue(forkflag, verbose, persistent, runall)
}
}
#if SM_HEAP_CHECK
if (sm_debug_active(&DebugLeakQ, 1))
sm_heap_setgroup(oldgroup);
@ -1698,7 +1701,7 @@ skip_domains(skip)
/*
** RUNNER_WORK -- have a queue runner do its work
**
** Have a queue runner do its work a list of entries.
** Have a queue runner do its work on a list of entries (WorkQ).
** When work isn't directly being done then this process can take a signal
** and terminate immediately (in a clean fashion of course).
** When work is directly being done, it's not to be interrupted
@ -2525,7 +2528,7 @@ runqueueevent(ignore)
** full -- (optional) to be set 'true' if WorkList is full
** more -- (optional) to be set 'true' if there are still more
** messages in this queue not added to WorkList
** pnentries -- (optional) total nuber of entries in queue
** pnentries -- (optional) total number of entries in queue
**
** Returns:
** The number of request in the queue (not necessarily
@ -3708,6 +3711,7 @@ dowork(qgrp, qdir, id, forkflag, requeueflag, e)
else
{
pid = 0;
maps_reset_chged("dowork");
}
if (pid == 0)
@ -3947,6 +3951,7 @@ doworklist(el, forkflag, requeueflag)
ei->e_quarmsg != NULL)
continue;
maps_reset_chged("doworklist");
rpool = sm_rpool_new_x(NULL);
clearenvelope(&e, true, rpool);
e.e_flags |= EF_QUEUERUN|EF_GLOBALERRS;
@ -4509,6 +4514,10 @@ readqf(e, openonly)
qflags |= QINTBCC;
break;
case 'X':
qflags |= QMXSECURE;
break;
case QDYNMAILFLG:
qflags |= QDYNMAILER;
break;
@ -4887,6 +4896,28 @@ printqueue()
** Prints a listing of the mail queue on the standard output.
*/
#if USE_EAI
# define PRINTADDR(addr, len) \
do \
{ \
if (smtputf8) \
{ \
char xbuf[MAXNAME]; \
(void) dequote_internal_chars(addr, xbuf, sizeof(xbuf));\
if (utf8_valid(xbuf, strlen(xbuf))) \
{ \
(void) sm_io_fprintf(smioout, \
SM_TIME_DEFAULT, \
"%.*s ", len, xbuf); \
break; \
} \
} \
prtstr(addr, len); \
} while (0)
#else
# define PRINTADDR(addr, len) prtstr(addr, len)
#endif /* USE_EAI */
int
print_single_queue(qgrp, qdir)
int qgrp;
@ -4998,6 +5029,9 @@ print_single_queue(qgrp, qdir)
char statmsg[MAXLINE];
char bodytype[MAXNAME + 1]; /* EAI:ok */
char qf[MAXPATHLEN];
#if USE_EAI
bool smtputf8 = false;
#endif
if (StopRequest)
stop_sendmail();
@ -5114,7 +5148,7 @@ print_single_queue(qgrp, qdir)
bitset(EF_WARNING, flags)
? '+' : ' ',
ctime(&submittime) + 4);
prtstr(&buf[1], 78);
PRINTADDR(buf+1, 78);
}
else
{
@ -5123,7 +5157,7 @@ print_single_queue(qgrp, qdir)
"%8ld %.16s ",
dfsize,
ctime(&submittime));
prtstr(&buf[1], 39);
PRINTADDR(buf+1, 39);
}
if (quarmsg[0] != '\0')
@ -5174,14 +5208,14 @@ print_single_queue(qgrp, qdir)
(void) sm_io_fprintf(smioout,
SM_TIME_DEFAULT,
"\n\t\t\t\t\t\t");
prtstr(p, 71);
PRINTADDR(p, 71);
}
else
{
(void) sm_io_fprintf(smioout,
SM_TIME_DEFAULT,
"\n\t\t\t\t\t ");
prtstr(p, 38);
PRINTADDR(p, 38);
}
if (Verbose && statmsg[0] != '\0')
{
@ -5202,6 +5236,11 @@ print_single_queue(qgrp, qdir)
{
switch (*p)
{
#if USE_EAI
case 'e':
smtputf8 = true;
break;
#endif /* USE_EAI */
case 'w':
flags |= EF_WARNING;
break;
@ -5593,7 +5632,6 @@ unlockqueue(e)
sm_dprintf("unlockqueue(%s)\n",
e->e_id == NULL ? "NOQUEUE" : e->e_id);
/* if there is a lock file in the envelope, close it */
SM_CLOSE_FP(e->e_lockfp);
@ -5840,7 +5878,7 @@ qid_printqueue(qgrp, qdir)
** fsize -- file size in bytes
** e -- envelope, or NULL
**
** Result:
** Returns:
** NOQDIR if no queue directory in qg has enough free space to
** hold a file of size 'fsize', otherwise the index of
** a randomly selected queue directory which resides on a
@ -6351,7 +6389,6 @@ multiqueue_cache(basedir, blen, qg, qn, phash)
qg->qg_qpaths[qg->qg_numqueues].qp_subdirs |= flag; \
else
CHKRSUBDIR("qf", QP_SUBQF);
CHKRSUBDIR("df", QP_SUBDF);
CHKRSUBDIR("xf", QP_SUBXF);
@ -7233,7 +7270,6 @@ init_shm(qn, owner, hash)
}
#endif /* SM_CONF_SHM */
/*
** SETUP_QUEUES -- set up all queue groups
**
@ -7333,7 +7369,6 @@ setup_queues(owner)
for (i = 0; i < NumQueue && Queue[i] != NULL; i++)
Queue[i]->qg_nextrun = now;
if (UseMSP && OpMode != MD_TEST)
{
long sff = SFF_CREAT;
@ -8017,7 +8052,7 @@ makeworkgroups()
** old -- old envelope.
** new -- new envelope.
**
** Results:
** Returns:
** Returns true on success, false on failure.
**
** Side Effects:
@ -8119,7 +8154,7 @@ dup_df(old, new)
** qgrp -- index of queue group.
** qdir -- queue directory.
**
** Results:
** Returns:
** new envelope.
**
*/
@ -8190,7 +8225,7 @@ split_env(e, sendqueue, qgrp, qdir)
** Parameters:
** e -- envelope.
**
** Results:
** Returns:
** SM_SPLIT_FAIL on failure
** SM_SPLIT_NONE if no splitting occurred,
** or 1 + the number of additional envelopes created.
@ -8413,7 +8448,7 @@ split_across_queue_groups(e)
** Parameters:
** e -- envelope.
**
** Results:
** Returns:
** SM_SPLIT_FAIL on failure
** SM_SPLIT_NONE if no splitting occurred,
** or 1 + the number of additional envelopes created.
@ -8605,7 +8640,7 @@ split_within_queue(e)
** Parameters:
** e -- envelope.
**
** Results:
** Returns:
** Returns true on success, false on failure.
**
** Side Effects:
@ -8703,7 +8738,7 @@ split_by_recipient(e)
** e -- envelope information for the item
** reason -- quarantine reason, NULL means unquarantine.
**
** Results:
** Returns:
** true if item changed, false otherwise
**
** Side Effects:
@ -8936,7 +8971,6 @@ quarantine_queue_item(qgrp, qdir, e, reason)
failing = true;
}
/* Figure out the new filename */
newtype = (reason == NULL ? NORMQF_LETTER : QUARQF_LETTER);
if (oldtype == newtype)
@ -9062,7 +9096,7 @@ quarantine_queue_item(qgrp, qdir, e, reason)
** reason -- quarantine reason, "." means unquarantine.
** qgrplimit -- limit to single queue group unless NOQGRP
**
** Results:
** Returns:
** none.
**
** Side Effects:
@ -9169,141 +9203,3 @@ quarantine_queue(reason, qgrplimit)
changed == 1 ? "" : "s");
}
}
#if _FFR_DMTRIGGER
/*
** QM -- queue "manager"
**
** Parameters:
** none.
**
** Results:
** false on error
**
** Side Effects:
** fork()s and runs as process to deliver queue entries
*/
bool
qm()
{
int r;
pid_t pid;
long tmo;
sm_syslog(LOG_DEBUG, NOQID, "queue manager: start");
(void) sm_blocksignal(SIGCHLD);
(void) sm_signal(SIGCHLD, reapchild);
pid = dofork();
if (pid == -1)
{
const char *msg = "queue manager -- fork() failed";
const char *err = sm_errstring(errno);
if (LogLevel > 8)
sm_syslog(LOG_INFO, NOQID, "%s: %s",
msg, err);
(void) sm_releasesignal(SIGCHLD);
return false;
}
if (pid != 0)
{
/* parent -- pick up intermediate zombie */
(void) sm_releasesignal(SIGCHLD);
return true;
}
/* XXX put this into a macro/function because it is used several times? */
/* child -- clean up signals */
/* Reset global flags */
RestartRequest = NULL;
RestartWorkGroup = false;
ShutdownRequest = NULL;
PendingSignal = 0;
CurrentPid = getpid();
close_sendmail_pid();
/*
** Initialize exception stack and default exception
** handler for child process.
*/
sm_exc_newthread(fatal_error);
clrcontrol();
proc_list_clear();
/* Add parent process as first child item */
proc_list_add(CurrentPid, "Queue manager", PROC_QM, 0, -1, NULL);
(void) sm_releasesignal(SIGCHLD);
(void) sm_signal(SIGCHLD, SIG_DFL);
(void) sm_signal(SIGHUP, SIG_DFL);
(void) sm_signal(SIGTERM, intsig);
/* drop privileges */
if (geteuid() == (uid_t) 0)
(void) drop_privileges(false);
disconnect(1, NULL);
QuickAbort = false;
r = sm_notify_start(true, 0);
if (r != 0)
syserr("sm_notify_start() failed=%d", r);
/*
** Initially wait indefinitely, then only wait
** until something needs to get done (not yet implemented).
*/
tmo = -1;
while (true)
{
char buf[64];
ENVELOPE *e;
SM_RPOOL_T *rpool;
/*
** TODO: This should try to receive multiple ids:
** after it got one, check for more with a very short timeout
** and collect them in a list.
** but them some other code should be used to run all of them.
*/
sm_syslog(LOG_DEBUG, NOQID, "queue manager: rcv=start");
r = sm_notify_rcv(buf, sizeof(buf), tmo);
if (-ETIMEDOUT == r)
{
sm_syslog(LOG_DEBUG, NOQID, "queue manager: rcv=timed_out");
continue;
}
if (r < 0)
{
sm_syslog(LOG_DEBUG, NOQID, "queue manager: rcv=%d", r);
goto end;
}
if (r > 0 && r < sizeof(buf))
buf[r] = '\0';
buf[sizeof(buf) - 1] = '\0';
sm_syslog(LOG_DEBUG, NOQID, "queue manager: got=%s", buf);
CurEnv = &QueueEnvelope;
rpool = sm_rpool_new_x(NULL);
e = newenvelope(&QueueEnvelope, CurEnv, rpool);
e->e_flags = BlankEnvelope.e_flags;
e->e_parent = NULL;
r = sm_io_sscanf(buf, "N:%d:%d:%s", &e->e_qgrp, &e->e_qdir, e->e_id);
if (r != 3)
{
sm_syslog(LOG_DEBUG, NOQID, "queue manager: buf=%s, scan=%d", buf, r);
goto end;
}
dowork(e->e_qgrp, e->e_qdir, e->e_id, true, false, e);
}
end:
sm_syslog(LOG_DEBUG, NOQID, "queue manager: stop");
finis(false, false, EX_OK);
return false;
}
#endif /* _FFR_DMTRIGGER */

View File

@ -228,7 +228,7 @@ gen_hash(saddr)
}
}
#else /* HASH_ALG == 1 */
# ERROR "unsupported HASH_ALG"
# error "unsupported HASH_ALG"
hv = ((hv << 1) ^ (*p & 0377)) % cctx->cc_size; ???
#endif /* HASH_ALG == 1 */
@ -419,7 +419,6 @@ conn_limits(e, now, saddr, clflags, hashary, ratelimit, conclimit)
}
#endif
#if RATECTL_DEBUG
logit = true;
#endif

View File

@ -16,8 +16,8 @@
#if STARTTLS
# include <tls.h>
#endif
#if DNSSEC_TEST
# include <sm_resolve.h>
#if DNSSEC_TEST || _FFR_NAMESERVER
# include "sm_resolve.h"
#endif
SM_RCSID("@(#)$Id: readcf.c,v 8.692 2013-11-22 20:51:56 ca Exp $")
@ -33,12 +33,18 @@ SM_RCSID("@(#)$Id: readcf.c,v 8.692 2013-11-22 20:51:56 ca Exp $")
#define HOURS HOUR
static void fileclass __P((int, char *, char *, bool, bool, bool));
#if _FFR_DYN_CLASS
static void dynclass __P((int, char *));
#endif
static char **makeargv __P((char *));
static void settimeout __P((char *, char *, bool));
static void toomany __P((int, int));
static char *extrquotstr __P((char *, char **, char *, bool *));
static void parse_class_words __P((int, char *));
#if _FFR_CLASS_RM_ENTRY
static void classrmentry __P((int, char *));
#endif
#if _FFR_BOUNCE_QUEUE
static char *bouncequeue = NULL;
@ -161,6 +167,11 @@ readcf(cfname, safe, e)
char pvpbuf[MAXLINE + MAXATOM];
static char *null_list[1] = { NULL };
extern unsigned char TokTypeNoC[];
#if _FFR_CLASS_RM_ENTRY
int off;
#else
# define off 1
#endif
FileName = cfname;
LineNumber = 0;
@ -463,7 +474,6 @@ readcf(cfname, safe, e)
endtoken = 0;
break;
#if 0
/*
** This doesn't work yet as there are maps defined *after* the cf
@ -534,12 +544,12 @@ readcf(cfname, safe, e)
if (mid == 0)
break;
#if USE_EAI && 0
if ('j' == mid && !addr_is_ascii(ep))
{
usrerr("hostname %s must be ASCII", ep);
finis(false, true, EX_CONFIG);
/* NOTREACHED */
}
// if ('j' == mid && !addr_is_ascii(ep))
// {
// usrerr("hostname %s must be ASCII", ep);
// finis(false, true, EX_CONFIG);
// /* NOTREACHED */
// }
#endif
p = munchstring(ep, NULL, '\0');
macdefine(&e->e_macro, A_TEMP, mid, p);
@ -551,9 +561,15 @@ readcf(cfname, safe, e)
case 'C': /* word class */
case 'T': /* trusted user (set class `t') */
#if _FFR_CLASS_RM_ENTRY
if (bp[0] != '\0' && bp[1] == '-')
off = 2;
else
off = 1;
#endif
if (bp[0] == 'C')
{
mid = macid_parse(&bp[1], &ep);
mid = macid_parse(&bp[off], &ep);
if (mid == 0)
break;
expand(ep, exbuf, sizeof(exbuf), e);
@ -565,7 +581,7 @@ readcf(cfname, safe, e)
else
{
mid = 't';
p = &bp[1];
p = &bp[off];
}
while (*p != '\0')
{
@ -580,11 +596,29 @@ readcf(cfname, safe, e)
delim = *p;
*p = '\0';
if (wd[0] != '\0')
setclass(mid, wd);
{
if (off < 2)
setclass(mid, wd);
#if _FFR_CLASS_RM_ENTRY
else
classrmentry(mid, wd);
#endif /* _FFR_CLASS_RM_ENTRY */
}
*p = delim;
}
break;
#if _FFR_DYN_CLASS
case 'A': /* dynamic class */
mid = macid_parse(&bp[1], &ep);
if (mid == 0)
break;
for (p = ep; SM_ISSPACE(*p); )
p++;
dynclass(mid, p);
break;
#endif
case 'F': /* word class from file */
mid = macid_parse(&bp[1], &ep);
if (mid == 0)
@ -940,11 +974,11 @@ toomany(id, maxcnt)
syserr("too many %c lines, %d max", id, maxcnt);
}
/*
** FILECLASS -- read members of a class from a file
** FILECLASS -- read members of a class from a file, program, or map
**
** Parameters:
** class -- class to define.
** filename -- name of file to read.
** filename -- name of file to read/specification of map and key.
** fmt -- scanf string to use for match.
** ismap -- if set, this is a map lookup.
** safe -- if set, this is a safe read.
@ -955,8 +989,10 @@ toomany(id, maxcnt)
** none
**
** Side Effects:
** puts all lines in filename that match a scanf into
** the named class.
** puts all entries retrieved from a file, program, or map
** into the named class:
** - file or |prg: all words in lines that match a scanf fmt
** - map: all words in value (rhs) of a map lookup of a key
*/
/*
@ -1109,7 +1145,6 @@ fileclass(class, filename, fmt, ismap, safe, optional)
sm_dprintf("fileclass: F{%s}: map class %s, key %s, spec %s\n",
mn, cl, key, spec);
/* parse map spec */
if (!map.map_class->map_parse(&map, spec))
{
@ -1229,6 +1264,124 @@ fileclass(class, filename, fmt, ismap, safe, optional)
(void) waitfor(pid);
}
#if _FFR_DYN_CLASS
/*
** DYNCLASS -- open a dynamic class
**
** Parameters:
** class -- class to define.
** arg -- rest of class definition from cf.
**
** Returns:
** none
*/
static void
dynclass(class, arg)
int class;
char *arg;
{
char *p;
char *tag;
char *mn;
char *maptype, *spec;
STAB *mapclass, *dynmap;
mn = newstr(macname(class));
if (*arg == '\0')
{
syserr("dynamic class: A{%s}: missing class definition", mn);
return;
}
tag = arg;
dynmap = stab(mn, ST_DYNMAP, ST_FIND);
if (NULL != dynmap)
{
syserr("dynamic class: A{%s}: already defined", mn);
goto error;
}
/* skip past tag */
if ((p = strchr(arg, '@')) == NULL)
{
/* should not happen */
syserr("dynamic class: A{%s}: bogus map specification", mn);
goto error;
}
/* skip past '@' */
*p++ = '\0';
maptype = p;
if ((spec = strchr(maptype, ':')) == NULL)
{
syserr("dynamic class: A{%s}: missing map class", mn);
goto error;
}
*spec++ ='\0';
/* set up map structure */
mapclass = stab(maptype, ST_MAPCLASS, ST_FIND);
if (NULL == mapclass)
{
syserr("dynamic class: A{%s}: map type %s not available",
mn, maptype);
goto error;
}
if (tTd(37, 5))
sm_dprintf("dynamic class: A{%s}: type='%s', tag='%s', spec='%s'\n",
mn, maptype, tag, spec);
/* enter map in stab */
dynmap = stab(mn, ST_DYNMAP, ST_ENTER);
if (NULL == dynmap)
{
syserr("dynamic class: A{%s}: cannot enter", mn);
goto error2;
}
dynmap->s_dynclass.map_class = &mapclass->s_mapclass;
dynmap->s_dynclass.map_mname = newstr(mn);
/* parse map spec */
if (!dynmap->s_dynclass.map_class->map_parse(&dynmap->s_dynclass, spec))
{
/* map_parse() showed the error already */
goto error;
}
/* open map */
if (dynmap->s_dynclass.map_class->map_open(&dynmap->s_dynclass, O_RDONLY))
{
dynmap->s_dynclass.map_mflags |= MF_OPEN;
dynmap->s_dynclass.map_pid = getpid();
}
else
{
syserr("dynamic class: A{%s}: map open failed", mn);
goto error;
}
dynmap->s_dynclass.map_mflags |= MF_VALID;
dynmap->s_dynclass.map_tag = newstr(tag);
#if 0
/* close map: where to do this? */
dynmap->s_dynclass.map_mflags |= MF_CLOSING;
dynmap->s_dynclass.map_class->map_close(&map);
dynmap->s_dynclass.map_mflags &= ~(MF_OPEN|MF_WRITABLE|MF_CLOSING);
#endif
sm_free(mn);
return;
error:
dynmap->s_dynclass.map_mflags |= MF_OPENBOGUS;
error2:
sm_free(mn);
return;
}
#endif
#if _FFR_RCPTFLAGS
/* first character for dynamically created mailers */
static char dynmailerp = ' ';
@ -1380,7 +1533,6 @@ newmodmailer(rcpt, fl)
** enters the mailer into the mailer table.
*/
void
makemailer(line)
char *line;
@ -2958,7 +3110,7 @@ static struct optioninfo
#endif
#if _FFR_EIGHT_BIT_ADDR_OK
# if !ALLOW_255
# ERROR "_FFR_EIGHT_BIT_ADDR_OK requires ALLOW_255"
# error "_FFR_EIGHT_BIT_ADDR_OK requires ALLOW_255"
# endif
# define O_EIGHT_BIT_ADDR_OK 0xdf
{ "EightBitAddrOK", O_EIGHT_BIT_ADDR_OK, OI_NONE },
@ -3013,7 +3165,7 @@ static struct optioninfo
# define O_TLSFB2CLEAR 0xef
{ "TLSFallbacktoClear", O_TLSFB2CLEAR, OI_NONE },
#endif
#if DNSSEC_TEST
#if DNSSEC_TEST || _FFR_NAMESERVER
# define O_NSPORTIP 0xf0
{ "NameServer", O_NSPORTIP, OI_NONE },
#endif
@ -3021,7 +3173,7 @@ static struct optioninfo
# define O_DANE 0xf1
{ "DANE", O_DANE, OI_NONE },
#endif
#if DNSSEC_TEST
#if DNSSEC_TEST || _FFR_NAMESERVER
# define O_NSSRCHLIST 0xf2
{ "NameSearchList", O_NSSRCHLIST, OI_NONE },
#endif
@ -3744,7 +3896,6 @@ setoption(opt, val, safe, sticky, e)
WkTimeFact = atoi(val);
break;
#if _FFR_QUEUE_GROUP_SORTORDER
/* coordinate this with makequeue() */
#endif
@ -4737,7 +4888,7 @@ setoption(opt, val, safe, sticky, e)
UseCompressedIPv6Addresses = atobool(val);
break;
#if DNSSEC_TEST
#if DNSSEC_TEST || _FFR_NAMESERVER
case O_NSPORTIP:
nsportip(val);
break;
@ -4776,9 +4927,9 @@ setoption(opt, val, safe, sticky, e)
#if USE_EAI
/* hack for testing */
if (isascii(*val) && isdigit(*val))
SMTPUTF8 = (int) strtol(val, NULL, 0);
SMTP_UTF8 = (int) strtol(val, NULL, 0);
else
SMTPUTF8 = atobool(val);
SMTP_UTF8 = atobool(val);
#else
if (atobool(val))
syserr("readcf: option: %s set but no USE_EAI support",
@ -4861,6 +5012,42 @@ setclass(class, str)
setbitn(bitidx(class), s->s_class);
}
}
#if _FFR_CLASS_RM_ENTRY
/*
** CLASSRMENTRY -- remove a string from a class
**
** Parameters:
** class -- the class from which to remove the string.
** str -- the string to remove
**
** Returns:
** none.
**
** Side Effects:
** removes the string from the class (if it was in there).
*/
static void
classrmentry(class, str)
int class;
char *str;
{
STAB *s;
s = stab(str, ST_CLASS, ST_FIND);
if (NULL == s /* || ST_CLASS != s->s_symtype */)
{
if (tTd(37, 8))
sm_dprintf("classrmentry: entry=%s not in class %s\n", str, macname(class));
return;
}
clrbitn(bitidx(class), s->s_class);
if (tTd(37, 8))
sm_dprintf("classrmentry(%s, %s)=%d\n", macname(class), str, bitnset(bitidx(class), s->s_class));
}
#endif /* _FFR_CLASS_RM_ENTRY */
/*
** MAKEMAPENTRY -- create a map entry
**
@ -5169,7 +5356,6 @@ static struct timeoutinfo
{ NULL, 0 },
};
static void
settimeout(name, val, sticky)
char *name;

View File

@ -117,9 +117,11 @@ sortbysignature(xx, yy)
/* Let's avoid redoing the signature over and over again */
if (xx->q_signature == NULL)
xx->q_signature = hostsignature(xx->q_mailer, xx->q_host, xx->q_flags & QSECURE);
xx->q_signature = hostsignature(xx->q_mailer, xx->q_host,
QISSECURE(xx), NULL);
if (yy->q_signature == NULL)
yy->q_signature = hostsignature(yy->q_mailer, yy->q_host, yy->q_flags & QSECURE);
yy->q_signature = hostsignature(yy->q_mailer, yy->q_host,
QISSECURE(yy), NULL);
ret = strcmp(xx->q_signature, yy->q_signature);
/*
@ -748,7 +750,7 @@ recipient(new, sendq, aliaslevel, e)
if (i == 0) /* equal */
{
/*
** Sortbysignature() has said that the two have
** sortbysignature() has said that the two have
** equal MX RR's and the same user. Calling sameaddr()
** now checks if the two hosts are as identical as the
** MX RR's are (which might not be the case)
@ -1600,7 +1602,6 @@ include(fname, forwarding, ctladdr, sendq, aliaslevel, e)
else
ev = NULL;
/* check for writable parent directory */
p = strrchr(fname, '/');
if (p != NULL)
@ -1977,7 +1978,7 @@ sendtoargv(argv, e)
{
int len = 0;
if (!SMTPUTF8 && !asciistr(p))
if (!SMTP_UTF8 && !asciistr(p))
{
usrerr("non-ASCII recipient address %s requires SMTPUTF8",
p);

View File

@ -1887,8 +1887,8 @@ pruneroute(addr)
while (start != NULL)
{
if (getmxrr(hostbuf, mxhosts, NULL, TRYFALLBACK, &rcode, NULL, -1)
> 0)
if (getmxrr(hostbuf, mxhosts, NULL, TRYFALLBACK, &rcode, NULL,
-1, NULL) > 0)
{
(void) sm_strlcpy(addr + 1, start + 1,
strlen(addr) - 1);

View File

@ -0,0 +1,172 @@
/*
* Copyright (c) 2021 Proofpoint, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
#include <sendmail.h>
#if _FFR_DMTRIGGER
#include <sm/sendmail.h>
#include <sm/notify.h>
static ENVELOPE QmEnvelope;
/*
** Macro for fork():
** FORK_P1(): parent
** FORK_C1(): child
** Note: these are not "universal", e.g.,
** proc_list_add() might be used in parent or child.
** maybe check pname != NULL to invoke proc_list_add()?
*/
#define FORK_P1(emsg, pname, ptype) \
do { \
(void) sm_blocksignal(SIGCHLD); \
(void) sm_signal(SIGCHLD, reapchild); \
\
pid = dofork(); \
if (pid == -1) \
{ \
const char *msg = emsg; \
const char *err = sm_errstring(errno); \
\
if (LogLevel > 8) \
sm_syslog(LOG_INFO, NOQID, "%s: %s", \
msg, err); \
(void) sm_releasesignal(SIGCHLD); \
return false; \
} \
if (pid != 0) \
{ \
proc_list_add(pid, pname, ptype, 0, -1, NULL); \
/* parent -- pick up intermediate zombie */ \
(void) sm_releasesignal(SIGCHLD); \
return true; \
} \
} while (0)
#define FORK_C1() \
do { \
/* child -- clean up signals */ \
\
/* Reset global flags */ \
RestartRequest = NULL; \
RestartWorkGroup = false; \
ShutdownRequest = NULL; \
PendingSignal = 0; \
CurrentPid = getpid(); \
close_sendmail_pid(); \
\
/* \
** Initialize exception stack and default exception \
** handler for child process. \
*/ \
\
sm_exc_newthread(fatal_error); \
clrcontrol(); \
proc_list_clear(); \
\
(void) sm_releasesignal(SIGCHLD); \
(void) sm_signal(SIGCHLD, SIG_DFL); \
(void) sm_signal(SIGHUP, SIG_DFL); \
(void) sm_signal(SIGTERM, intsig); \
\
/* drop privileges */ \
if (geteuid() == (uid_t) 0) \
(void) drop_privileges(false); \
disconnect(1, NULL); \
QuickAbort = false; \
\
} while (0)
/*
** QM -- queue "manager"
**
** Parameters:
** none.
**
** Returns:
** false on error
**
** Side Effects:
** fork()s and runs as process to deliver queue entries
*/
bool
qm()
{
int r;
pid_t pid;
long tmo;
sm_syslog(LOG_DEBUG, NOQID, "queue manager: start");
FORK_P1("Queue manager -- fork() failed", "QM", PROC_QM);
FORK_C1();
r = sm_notify_start(true, 0);
if (r != 0)
syserr("sm_notify_start() failed=%d", r);
/*
** Initially wait indefinitely, then only wait
** until something needs to get done (not yet implemented).
*/
tmo = -1;
while (true)
{
char buf[64];
ENVELOPE *e;
SM_RPOOL_T *rpool;
/*
** TODO: This should try to receive multiple ids:
** after it got one, check for more with a very short timeout
** and collect them in a list.
** but them some other code should be used to run all of them.
*/
sm_syslog(LOG_DEBUG, NOQID, "queue manager: rcv=start");
r = sm_notify_rcv(buf, sizeof(buf), tmo);
if (-ETIMEDOUT == r)
{
sm_syslog(LOG_DEBUG, NOQID, "queue manager: rcv=timed_out");
continue;
}
if (r < 0)
{
sm_syslog(LOG_DEBUG, NOQID, "queue manager: rcv=%d", r);
goto end;
}
if (r > 0 && r < sizeof(buf))
buf[r] = '\0';
buf[sizeof(buf) - 1] = '\0';
sm_syslog(LOG_DEBUG, NOQID, "queue manager: got=%s", buf);
CurEnv = &QmEnvelope;
rpool = sm_rpool_new_x(NULL);
e = newenvelope(&QmEnvelope, CurEnv, rpool);
e->e_flags = BlankEnvelope.e_flags;
e->e_parent = NULL;
r = sm_io_sscanf(buf, "N:%d:%d:%s", &e->e_qgrp, &e->e_qdir, e->e_id);
if (r != 3)
{
sm_syslog(LOG_DEBUG, NOQID, "queue manager: buf=%s, scan=%d", buf, r);
goto end;
}
dowork(e->e_qgrp, e->e_qdir, e->e_id, true, false, e);
}
end:
sm_syslog(LOG_DEBUG, NOQID, "queue manager: stop");
finis(false, false, EX_OK);
/* NOTREACHED */
return false;
}
#endif /* _FFR_DMTRIGGER */

View File

@ -87,8 +87,8 @@ or
Go into
ARPANET
mode.
All input lines must end with a CR-LF,
and all messages will be generated with a CR-LF at the end.
All input lines must end with a CRLF,
and all messages will be generated with a CRLF at the end.
Also,
the ``From:'' and ``Sender:''
fields are examined for the name of the sender.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2013 Proofpoint, Inc. and its suppliers.
* Copyright (c) 1998-2013, 2023,2024 Proofpoint, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
* Copyright (c) 1988, 1993
@ -46,16 +46,16 @@
# endif
#else /* STARTTLS */
# if DANE
# ERROR "DANE set but STARTTLS not defined"
# error "DANE set but STARTTLS not defined"
# endif
# if _FFR_TLS_ALTNAMES
# ERROR "_FFR_TLS_ALTNAMES set but STARTTLS not defined"
# error "_FFR_TLS_ALTNAMES set but STARTTLS not defined"
# endif
# if _FFR_TLSFB2CLEAR
# ERROR "_FFR_TLSFB2CLEAR set but STARTTLS not defined"
# error "_FFR_TLSFB2CLEAR set but STARTTLS not defined"
# endif
# if _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE
# ERROR "_FFR_TLS_USE_CERTIFICATE_CHAIN_FILE set but STARTTLS not defined"
# error "_FFR_TLS_USE_CERTIFICATE_CHAIN_FILE set but STARTTLS not defined"
# endif
#endif /* STARTTLS */
@ -124,9 +124,12 @@ SM_UNUSED(static char SmailId[]) = "@(#)$Id: sendmail.h,v 8.1104 2013-11-22 20:5
# undef NOERROR /* avoid <sys/streams.h> conflict */
# endif
# include <resolv.h>
# if !defined(NO_DATA)
# define NO_DATA NO_ADDRESS
# endif
#else /* NAMED_BIND */
# undef SM_SET_H_ERRNO
# define SM_SET_H_ERRNO(err)
# undef SM_SET_H_ERRNO
# define SM_SET_H_ERRNO(err)
#endif /* NAMED_BIND */
#if HESIOD
@ -140,29 +143,39 @@ SM_UNUSED(static char SmailId[]) = "@(#)$Id: sendmail.h,v 8.1104 2013-11-22 20:5
# define ALLOW_255 1
#endif
#if _FFR_EAI && _FFR_EIGHT_BIT_ADDR_OK
# ERROR "Cannot enable both of these FFRs: _FFR_EAI _FFR_EIGHT_BIT_ADDR_OK"
# error "Cannot enable both of these FFRs: _FFR_EAI _FFR_EIGHT_BIT_ADDR_OK"
#endif
#if _FFR_OCC && !SM_CONF_SHM
# ERROR "_FFR_OCC requires SM_CONF_SHM"
# error "_FFR_OCC requires SM_CONF_SHM"
#endif
#if _FFR_SM_LDAP_DBG && !(LDAPMAP && defined(LBER_OPT_LOG_PRINT_FN))
# ERROR "_FFR_SM_LDAP_DBG requires LDAPMAP and LBER_OPT_LOG_PRINT_FN"
#if !NOT_SENDMAIL
# if _FFR_SM_LDAP_DBG && !(LDAPMAP && defined(LBER_OPT_LOG_PRINT_FN))
# error "_FFR_SM_LDAP_DBG requires LDAPMAP and LBER_OPT_LOG_PRINT_FN"
# endif
#endif
#if _FFR_LOG_MORE1 > 1 || _FFR_LOG_MORE2 > 1
# if _FFR_LOG_MORE1 != _FFR_LOG_MORE2
# ERROR "_FFR_LOG_MORE1 != _FFR_LOG_MORE2"
# error "_FFR_LOG_MORE1 != _FFR_LOG_MORE2"
# endif
#endif
#if LDAP_NETWORK_TIMEOUT && !(LDAPMAP && defined(LDAP_OPT_NETWORK_TIMEOUT))
# ERROR "LDAP_NETWORK_TIMEOUT requires LDAPMAP"
#if !NOT_SENDMAIL
# if LDAP_NETWORK_TIMEOUT && !(LDAPMAP && defined(LDAP_OPT_NETWORK_TIMEOUT))
# error "LDAP_NETWORK_TIMEOUT requires LDAPMAP"
# endif
#endif
#if !NOT_SENDMAIL
# if LDAP_REFERRALS && !LDAPMAP
# error "LDAP_REFERRALS requires LDAPMAP"
# endif
#endif
#if _FFR_VRFY_TRUSTED_FIRST && !defined(X509_V_FLAG_TRUSTED_FIRST)
# ERROR "_FFR_VRFY_TRUSTED_FIRST set but X509_V_FLAG_TRUSTED_FIRST not defined"
# error "_FFR_VRFY_TRUSTED_FIRST set but X509_V_FLAG_TRUSTED_FIRST not defined"
#endif
#if _FFR_8BITENVADDR
@ -171,26 +184,37 @@ SM_UNUSED(static char SmailId[]) = "@(#)$Id: sendmail.h,v 8.1104 2013-11-22 20:5
# define MAXNAME_I MAXNAME
#endif
#if !defined(_FFR_M_ONLY_IPV4)
# define _FFR_M_ONLY_IPV4 1
#endif
#define SM_IS_EMPTY(s) (NULL == (s) || '\0' == *(s))
#if STARTTLS
# if DANE
# define DANE_FP_LOG_LEN 256
# define DANE_FP_DBG_LEN 4096
struct dane_vrfy_ctx_S
{
/* see tls.h: values for DANE option and dane_vrfy_chk */
int dane_vrfy_chk;
int dane_vrfy_res;
int dane_vrfy_port;
/* use OpenSSL functions for DANE checks? */
bool dane_vrfy_dane_enabled;
/* look up TLSA RRs, SNI unless dane_tlsa_sni is set. */
char *dane_vrfy_host;
char *dane_vrfy_sni; /* if not NULL: use for SNI */
/* full fingerprint in printable format */
char dane_vrfy_fp[1024];
/* fingerprint in printable format - just for logging */
char dane_vrfy_fp[DANE_FP_LOG_LEN];
};
typedef struct dane_tlsa_S dane_tlsa_T, *dane_tlsa_P;
typedef struct dane_vrfy_ctx_S dane_vrfy_ctx_T, *dane_vrfy_ctx_P;
# endif /* DANE */
/* TLS information context */
@ -208,8 +232,8 @@ typedef struct tlsi_ctx_S tlsi_ctx_T, *tlsi_ctx_P;
#define TLSI_FL_CRLREQ 'R' /* CRL required */
#define TLSI_FL_FB2CLR 'C' /* fall back to clear text is ok */
#define TLSI_FL_NOFB2CLR 'c' /* do not fall back to clear text */
#define TLSI_FL_NODANE 'd' /* do not use/lookup DANE */
#define TLSI_FL_NOSTS 'M' /* do not use/lookup STS */
#define TLSI_FL_NODANE 'd' /* do not use/look up DANE */
#define TLSI_FL_NOSTS 'M' /* do not use/look up STS */
/* internal */
#define TLSI_FL_STS_NOFB2CLR 0x01 /* no clear text: STS is used */
#define SM_TLSI_IS(tlsi_ctx, flag) \
@ -265,14 +289,14 @@ typedef int (*sasl_callback_ft)(void);
# define SASL SASL_VERSION
# else /* SASL == 1 || SASL == 2 */
# if SASL != SASL_VERSION
# ERROR "README: -DSASL (SASL) does not agree with the version of the CYRUS_SASL library (SASL_VERSION)"
# ERROR "README: see README!"
# error "README: -DSASL (SASL) does not agree with the version of the CYRUS_SASL library (SASL_VERSION)"
# error "README: see README!"
# endif /* SASL != SASL_VERSION */
# endif /* SASL == 1 || SASL == 2 */
# else /* defined(SASL_VERSION_MAJOR) && defined(SASL_VERSION_MINOR) && defined(SASL_VERSION_STEP) */
# if SASL == 1
# ERROR "README: please set -DSASL to the version of the CYRUS_SASL library"
# ERROR "README: see README!"
# error "README: please set -DSASL to the version of the CYRUS_SASL library"
# error "README: see README!"
# endif /* SASL == 1 */
# endif /* defined(SASL_VERSION_MAJOR) && defined(SASL_VERSION_MINOR) && defined(SASL_VERSION_STEP) */
#endif /* SASL */
@ -351,7 +375,7 @@ struct address
char *q_paddr; /* the printname for the address */
char *q_user; /* user name */
char *q_ruser; /* real user name, or NULL if q_user */
char *q_host; /* host name */
char *q_host; /* host name [x] */
#if DANE
char *q_qname; /* original query (host) name */
#endif
@ -382,6 +406,18 @@ struct address
typedef struct address ADDRESS;
/*
** Note: only some of the flags are saved in the queue;
** the code in queue.c does not use the actual value but maps each flag
** to/from an associated character.
** If the values would not change then those could be stored/retrieved
** directly (applying a mask to select those flags which should be kep) --
** the mapping to/from characters provides a "defined" external interface
** provided those mappings are kept (and if an old mapping is removed then
** it should be kept as comment so it is not reused "too soon").
*/
/* bit values for q_flags */
#define QGOODUID 0x00000001 /* the q_uid q_gid fields are good */
#define QPRIMARY 0x00000002 /* set from RCPT or argv */
@ -403,9 +439,10 @@ typedef struct address ADDRESS;
#define QBYNRELAY 0x00020000 /* DeliverBy: notify, relayed */
#define QINTBCC 0x00040000 /* internal Bcc */
#define QDYNMAILER 0x00080000 /* "dynamic mailer" */
#define QSECURE 0x00100000 /* DNSSEC ok */
#define QSECURE 0x00100000 /* DNSSEC ok for host lookup */
#define QQUEUED 0x00200000 /* queued */
#define QINTREPLY 0x00400000 /* internally rejected (delivery) */
#define QMXSECURE 0x00800000 /* DNSSEC ok for MX lookup */
#define QTHISPASS 0x40000000 /* temp: address set this pass */
#define QRCPTOK 0x80000000 /* recipient() processed address */
@ -413,6 +450,8 @@ typedef struct address ADDRESS;
#define Q_PINGFLAGS (QPINGONSUCCESS|QPINGONFAILURE|QPINGONDELAY)
#define QISSECURE(r) (0 != ((r)->q_flags & QSECURE))
#if _FFR_RCPTFLAGS
# define QMATCHFLAGS (QINTBCC|QDYNMAILER)
# define QMATCH_FLAG(a) ((a)->q_flags & QMATCHFLAGS)
@ -617,8 +656,8 @@ struct mailer
#define M_NOMX '0' /* turn off MX lookups */
#define M_NONULLS '1' /* don't send null bytes */
#define M_FSMTP '2' /* force SMTP (no ESMTP even if offered) */
/* '4' free? */
#define M_EBCDIC '3' /* extend Q-P encoding for EBCDIC */
#define M_ONLY_IPV4 '4' /* Use only IPv4 */
#define M_TRYRULESET5 '5' /* use ruleset 5 after local aliasing */
#define M_7BITHDRS '6' /* strip headers to 7 bits even in 8 bit path */
#define M_7BITS '7' /* use 7-bit path */
@ -633,6 +672,9 @@ struct mailer
#define M_PLUS '+' /* Reserved: Used in mc for adding new flags */
#define M_MINUS '-' /* Reserved: Used in mc for removing flags */
#define M_NOMHHACK '!' /* Don't perform HM hack dropping explicit from */
#if _FFR_SMTPS_CLIENT
# define M_SMTPS_CLIENT '_' /* use SMTP over TLS (465/TCP) */
#endif
/* functions */
extern void initerrmailers __P((void));
@ -767,12 +809,12 @@ extern bool filesys_free __P((long));
(SASL_SEC_FORWARD_SECRECY & SASL_SEC_MASK) == 0 || \
(SASL_SEC_NOANONYMOUS & SASL_SEC_MASK) == 0 || \
(SASL_SEC_PASS_CREDENTIALS & SASL_SEC_MASK) == 0
# ERROR "change SASL_SEC_MASK notify sendmail.org!"
# error "change SASL_SEC_MASK notify sendmail.org!"
# endif /* SASL_SEC_NOPLAINTEXT & SASL_SEC_MASK) == 0 ... */
# endif /* SASL >= 20101 */
# define MAXOUTLEN 8192 /* length of output buffer, should be 2^n */
# if (SASL_AUTH_AUTH & SASL_SEC_MASK) != 0
# ERROR "change SASL_AUTH_AUTH notify sendmail.org!"
# error "change SASL_AUTH_AUTH notify sendmail.org!"
# endif
/* functions */
@ -875,7 +917,7 @@ MCI
#define MCIF_8BITMIME 0x00000040 /* BODY=8BITMIME supported */
#define MCIF_7BIT 0x00000080 /* strip this message to 7 bits */
/* 0x00000100 unused, was MCIF_MULTSTAT: MAIL11V3: handles MULT status */
#define MCIF_INHEADER 0x00000200 /* currently outputing header */
#define MCIF_INHEADER 0x00000200 /* currently outputting header */
#define MCIF_CVT8TO7 0x00000400 /* convert from 8 to 7 bits */
#define MCIF_DSN 0x00000800 /* DSN extension supported */
#define MCIF_8BITOK 0x00001000 /* OK to send 8 bit characters */
@ -915,6 +957,7 @@ MCI
#define MCIF_EXTENS (MCIF_EXPN|MCIF_SIZE|MCIF_8BITMIME|MCIF_DSN|MCIF_8BITOK|MCIF_AUTH|MCIF_ENHSTAT|MCIF_PIPELINED|MCIF_VERB|MCIF_TLS|MCIF_DLVR_BY|MCIF_AUTH2|MCIF_EAI)
/* states */
/* XREF: deliver.c: mcis[] -- any changes here must be reflected there! */
#define MCIS_CLOSED 0 /* no traffic on this connection */
#define MCIS_OPENING 1 /* sending initial protocol */
#define MCIS_OPEN 2 /* open, initial protocol sent */
@ -1032,7 +1075,6 @@ TIMERS
TIMER ti_overall; /* the whole process */
};
#define PUSHTIMER(l, t) { if (tTd(98, l)) pushtimer(&t); }
#define POPTIMER(l, t) { if (tTd(98, l)) poptimer(&t); }
@ -1115,11 +1157,13 @@ struct envelope
MCI *e_mci; /* connection info */
char *e_auth_param; /* readonly; NULL or static storage or
* allocated from e_rpool */
#if _FFR_TIMERS
TIMERS e_timers; /* per job timers */
#endif
long e_deliver_by; /* deliver by */
int e_dlvr_flag; /* deliver by flag */
SM_RPOOL_T *e_rpool; /* resource pool for this envelope */
unsigned int e_features; /* server features */
unsigned long e_features; /* server features */
#define ENHSC_LEN 11
#if _FFR_MILTER_ENHSC
char e_enhsc[ENHSC_LEN]; /* enhanced status code */
@ -1128,6 +1172,9 @@ struct envelope
int e_rcode; /* reply code */
char e_renhsc[ENHSC_LEN]; /* enhanced status code */
char *e_text; /* reply text */
#if _FFR_LOG_STAGE
int e_estate; /* protocol state when error happened */
#endif
};
#define PRT_NONNEGL(v) ((v) < 0 ? LONG_MAX : (v))
@ -1151,8 +1198,8 @@ struct envelope
#define EF_LOGSENDER 0x00008000L /* need to log the sender */
#define EF_NORECEIPT 0x00010000L /* suppress all return-receipts */
#define EF_HAS8BIT 0x00020000L /* at least one 8-bit char in body */
/* was: EF_NL_NOT_EOL 0x00040000L * don't accept raw NL as EOLine */
/* was: EF_CRLF_NOT_EOL 0x00080000L * don't accept CR-LF as EOLine */
/* was: EF_NL_NOT_EOL 0x00040000L * don't accept raw LF as EOLine */
/* was: EF_CRLF_NOT_EOL 0x00080000L * don't accept CRLF as EOLine */
#define EF_RET_PARAM 0x00100000L /* RCPT command had RET argument */
#define EF_HAS_DF 0x00200000L /* set when data file is instantiated */
#define EF_IS_MIME 0x00400000L /* really is a MIME message */
@ -1163,6 +1210,7 @@ struct envelope
#define EF_UNSAFE 0x08000000L /* unsafe: read from untrusted source */
#define EF_TOODEEP 0x10000000L /* message is nested too deep */
#define EF_SECURE 0x20000000L /* DNSSEC for currently parsed addr */
#define EF_7BITBODY 0x40000000L /* strip body to 7bit on input */
#define DLVR_NOTIFY 0x01
#define DLVR_RETURN 0x02
@ -1414,8 +1462,8 @@ typedef union
/* functions */
extern int getcanonname __P((char *, int, bool, int *));
extern int getmxrr __P((char *, char **, unsigned short *, unsigned int, int *, int *, int));
extern char *hostsignature __P((MAILER *, char *, bool));
extern int getmxrr __P((char *, char **, unsigned short *, unsigned int, int *, int *, int, int *));
extern char *hostsignature __P((MAILER *, char *, bool, unsigned long *));
extern int getfallbackmxrr __P((char *));
/*
@ -1462,6 +1510,9 @@ MAP
short map_return[MAXMAPACTIONS]; /* return bitmaps for stacked maps */
};
#if _FFR_DYN_CLASS
# define map_tag map_domain /* overload map field */
#endif
/* bit values for map_mflags */
#define MF_VALID 0x00000001 /* this entry is valid */
@ -1474,7 +1525,8 @@ MAP
#define MF_ALIAS 0x00000080 /* this is an alias file */
#define MF_TRY0NULL 0x00000100 /* try with no null byte */
#define MF_TRY1NULL 0x00000200 /* try with the null byte */
#define MF_LOCKED 0x00000400 /* this map is currently locked */
#define MF_LOCKED 0x00000400 /* map is locked (RDWR) */
/* that means: no extra lockfile() calls must be made (in *map_lookup()) */
#define MF_ALIASWAIT 0x00000800 /* alias map in aliaswait state */
#define MF_IMPL_HASH 0x00001000 /* implicit: underlying hash database */
#define MF_IMPL_NDBM 0x00002000 /* implicit: underlying NDBM database */
@ -1491,6 +1543,7 @@ MAP
#define MF_CLOSING 0x01000000 /* map is being closed */
#define MF_SECURE 0x02000000 /* DNSSEC result is "secure" */
#define MF_KEEPXFMT 0x04000000 /* keep [x] format */
#define MF_CHKED_CHGD 0x08000000 /* checked whether underlying map changed */
#define DYNOPENMAP(map) \
do \
@ -1552,6 +1605,11 @@ extern int udbexpand __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern void _udbx_close __P((void));
extern char *udbsender __P((char *, SM_RPOOL_T *));
#endif
#if _FFR_MAP_CHK_FILE > 1
extern void maps_reset_chged __P((const char *));
#else
# define maps_reset_chged(msg)
#endif
/*
** LDAP related items
@ -1579,7 +1637,6 @@ struct lssvalues
};
/* functions */
extern bool ldapmap_parseargs __P((MAP *, char *));
extern void ldapmap_set_defaults __P((char *));
#endif /* LDAPMAP */
@ -1711,6 +1768,9 @@ struct symtab
QUEUEGRP *sv_queue; /* pointer to queue */
#if DANE
dane_tlsa_P sv_tlsa; /* pointer to TLSA RRs */
#endif
#if _FFR_DYN_CLASS
MAP sv_dynclass; /* map for dynamic class */
#endif
} s_value;
};
@ -1746,9 +1806,12 @@ typedef struct symtab STAB;
#if DANE
# define ST_TLSA_RR 17 /* cached TLSA RRs */
#endif
#if _FFR_DYN_CLASS
# define ST_DYNMAP 18 /* dynamic map */
#endif
/* This entry must be last */
#define ST_MCI 18 /* mailer connection info (offset) */
#define ST_MCI 19 /* mailer connection info (offset) */
#define s_class s_value.sv_class
#define s_mailer s_value.sv_mailer
@ -1775,6 +1838,9 @@ typedef struct symtab STAB;
#if DANE
# define s_tlsa s_value.sv_tlsa
#endif
#if _FFR_DYN_CLASS
# define s_dynclass s_value.sv_dynclass
#endif
/* opcodes to stab */
#define ST_FIND 0 /* find entry */
@ -1960,6 +2026,7 @@ EXTERN unsigned long PrivacyFlags; /* privacy flags */
#define RSF_COUNT 0x0004 /* count rejections (statistics)? */
#define RSF_ADDR 0x0008 /* reassemble address */
#define RSF_STRING 0x0010 /* reassemble address as string */
#define RSF_STATUS 0x0020 /* log "status" instead of "reject" */
/*
** Flags passed to mime8to7 and putheader.
@ -2246,6 +2313,7 @@ extern void sync_dir __P((char *, bool));
#endif
#if _FFR_DMTRIGGER
extern bool qm __P((void));
extern int deliver __P((ENVELOPE *, ADDRESS *));
#endif
/*
@ -2320,6 +2388,11 @@ extern void inittimeouts __P((char *, bool));
# define tTd(flag, level) (tTdvect[flag] >= (unsigned char)level)
#else
# define tTd(flag, level) (tTdvect[flag] >= (unsigned char)level && !IntSig)
# if _FFR_TESTS
# define TTD(flag, level) (tTdvect[flag] >= (unsigned char)level && !IntSig)
# else
# define TTD(flag, level) false
# endif
#endif
#define tTdlevel(flag) (tTdvect[flag])
@ -2402,6 +2475,7 @@ extern unsigned char tTdvect[100]; /* trace vector */
} while (0)
/* reply types (text in SmtpMsgBuffer) */
/* XREF: deliver.c: xs_states[] -- any changes here must be reflected there! */
#define XS_DEFAULT 0 /* other commands, e.g., RSET */
#define XS_STARTTLS 1
#define XS_AUTH 2
@ -2509,6 +2583,8 @@ EXTERN int volatile CurChildren; /* current number of daemonic children */
EXTERN int CurrentLA; /* current load average */
#if DANE
EXTERN int Dane; /* DANE */
#else
# define Dane 0 /* XREF: see tls.h: #define DANE_NEVER */
#endif
EXTERN int DefaultNotify; /* default DSN notification flags */
EXTERN int DelayLA; /* load average to delay connections */
@ -2560,9 +2636,9 @@ EXTERN char *MemoryResource;/* memory resource to look up */
#endif /* _FFR_MEMSTAT */
EXTERN int SuperSafe; /* be extra careful, even if expensive */
#if USE_EAI
EXTERN int SMTPUTF8; /* enable SMTPUTF8 support */
EXTERN int SMTP_UTF8; /* enable SMTPUTF8 support */
#else
# define SMTPUTF8 false
# define SMTP_UTF8 false
#endif
EXTERN int VendorCode; /* vendor-specific operation enhancements */
EXTERN int Verbose; /* set if blow-by-blow desired */
@ -2691,10 +2767,10 @@ extern int skipaddrhost __P((const char *, bool));
/* alias file */
extern void alias __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern bool aliaswait __P((MAP *, char *, bool));
extern bool aliaswait __P((MAP *, const char *, bool));
extern void forward __P((ADDRESS *, ADDRESS **, int, ENVELOPE *));
extern void readaliases __P((MAP *, SM_FILE_T *, bool, bool));
extern bool rebuildaliases __P((MAP *, bool));
extern bool rebuildaliases __P((MAP *));
extern void setalias __P((char *));
/* logging */
@ -2704,7 +2780,7 @@ extern void PRINTFLIKE(3, 4) sm_syslog __P((int, const char *, const char *, ...
/* SMTP */
extern void giveresponse __P((int, char *, MAILER *, MCI *, ADDRESS *, time_t, ENVELOPE *, ADDRESS *));
extern int reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)__P((char *, bool, MAILER *, MCI *, ENVELOPE *)), char **, int));
extern int reply __P((MAILER *, MCI *, ENVELOPE *, time_t, void (*)__P((char *, bool, MAILER *, MCI *, ENVELOPE *)), char **, int, char **));
extern void smtp __P((char *volatile, BITMAP256, ENVELOPE *volatile));
#if SASL
extern int smtpauth __P((MAILER *, MCI *, ENVELOPE *));
@ -2784,9 +2860,12 @@ extern void buildfname __P((char *, char *, char *, int));
extern bool chkclientmodifiers __P((int));
extern bool chkdaemonmodifiers __P((int));
extern int checkcompat __P((ADDRESS *, ENVELOPE *));
#ifdef XDEBUG
#if XDEBUG
extern void checkfd012 __P((char *));
extern void checkfdopen __P((int, char *));
#else
# define checkfd012(str) ((void) 0)
# define checkfdopen(n, str) ((void) 0)
#endif
extern void checkfds __P((char *));
extern bool chownsafe __P((int, bool));
@ -2796,7 +2875,7 @@ extern void cleanup_shm __P((bool));
#endif
extern void close_sendmail_pid __P((void));
extern void clrdaemon __P((void));
extern void collect __P((SM_FILE_T *, bool, HDR **, ENVELOPE *, bool));
extern void collect __P((SM_FILE_T *, int, HDR **, ENVELOPE *, bool));
extern time_t convtime __P((char *, int));
extern char **copyplist __P((char **, bool, SM_RPOOL_T *));
extern void copy_class __P((int, int));
@ -2979,6 +3058,15 @@ extern bool xtextok __P((char *));
extern int xunlink __P((char *));
extern char *xuntextify __P((char *));
/* flags for collect() */
#define SMTPMODE_NO 0
#define SMTPMODE_LAX 0x01
#define SMTPMODE_CRLF 0x02 /* CRLF.CRLF required for EOM */
#define SMTPMODE_LF_421 0x04 /* bare LF: drop connection */
#define SMTPMODE_CR_421 0x08 /* bare CR: drop connection */
#define SMTPMODE_LF_SP 0x10 /* bare LF: replace with space */
#define SMTPMODE_CR_SP 0x20 /* bare CR: replace with space */
#define ASSIGN_IFDIFF(old, new) \
do \
{ \
@ -2992,6 +3080,7 @@ extern char *xuntextify __P((char *));
#if USE_EAI
extern bool addr_is_ascii __P((const char *));
extern bool str_is_print __P((const char *));
extern const char *hn2alabel __P((const char *));
#endif

Some files were not shown because too many files have changed in this diff Show More