example is to capture output from "postmulti -p status" to
figure out which instances are or are not running. Files:
postfix/postfix.c, postlog/postlog.c.
+
+20230209
+
+ Cleanup: in smtp_service_addr() refined the loop detection
+ code for SRV lookup. File: smtp/smtp_addr.c.
+
+ Cleanup: renamed macros with invisible side effects and
+ implicit inputs to upper case. Verified that the compiled
+ code did not change. File: tls_fprint.c.
+
+20230310
+
+ Cleanup: the milter header/body checks logged less text (up
+ to 60 bytes) than the 'original' header/body checks (up to
+ 200 bytes). Problem reported by Aleksandr Stankevic. Fixed
+ the same inconsistency in the Postfix SMTP client. Files:
+ cleanup/cleanup_milter.c, smtp/smtp_proto.c.
+
+20230311
+
+ Hardening: the Postfix SMTP server can now aggregate
+ smtpd_client_*_rate and smtpd_client_*_count statistics by
+ network block, as specified with smtpd_client_ipv4_prefix_length
+ (default 32, no aggregation) and smtpd_client_ipv6_prefix_length
+ (default 72, aggregation by /72 network blocks). The latter
+ raises the bar for a memory exhaustion attack. Files:
+ util/net_mask_top.[hc], smtpd/smtpd.c, smtpd/smtpd_peer.c,
+ mantools/postlink, proto/postconf.proto.
Multi-recipient support in sender/recipient_bcc_maps and
always_bcc.
+ mail_conf_xxx supprt for non-negative numbers (i.e.
+ numbers with a lower bound of zero).
+
+ Log anvil transgressions with their address range (in
+ addition to the offending IP address. We should not disclose
+ to random clients how we aggregate anvil event counters.
+
Should "postconf -f" pretty-print text inside {}?
Is there any code that calls attr_scan*() and that works
</p>
+</DD>
+
+<DT><b><a name="smtpd_client_ipv4_prefix_length">smtpd_client_ipv4_prefix_length</a>
+(default: 32)</b></DT><DD>
+
+<p> Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
+by IPv4 network blocks with the specified network prefix. Aggregation
+reduces the <a href="anvil.8.html">anvil(8)</a> resources needed to maintain counters. By
+default, aggregation is disabled for IPv4. </p>
+
+<p> This feature is available in Postfix 3.8 and later. </p>
+
+
+</DD>
+
+<DT><b><a name="smtpd_client_ipv6_prefix_length">smtpd_client_ipv6_prefix_length</a>
+(default: 72)</b></DT><DD>
+
+<p> Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
+by IPv6 network blocks with the specified network prefix. Aggregation
+reduces the <a href="anvil.8.html">anvil(8)</a> resources needed to maintain counters. By
+default, aggregation is enabled for IPv6.
+</p>
+
+<p> This feature is available in Postfix 3.8 and later. </p>
+
+
</DD>
<DT><b><a name="smtpd_client_message_rate_limit">smtpd_client_message_rate_limit</a>
<b><a href="postconf.5.html#header_from_format">header_from_format</a> (standard)</b>
The format of the Postfix-generated <b>From:</b> header.
+ Available in Postfix version 3.8 and later:
+
+ <b><a href="postconf.5.html#smtpd_client_ipv4_prefix_length">smtpd_client_ipv4_prefix_length</a> (32)</b>
+ Aggregate smtpd_client_*_count and smtpd_client_*_rate statis-
+ tics by IPv4 network blocks with the specified network prefix.
+
+ <b><a href="postconf.5.html#smtpd_client_ipv6_prefix_length">smtpd_client_ipv6_prefix_length</a> (72)</b>
+ Aggregate smtpd_client_*_count and smtpd_client_*_rate statis-
+ tics by IPv6 network blocks with the specified network prefix.
+
<b>TARPIT CONTROLS</b>
When a remote SMTP client makes errors, the Postfix SMTP server can
insert delays before responding. This can help to slow down run-away
later).
.PP
This feature is available in Postfix 2.2 and later.
+.SH smtpd_client_ipv4_prefix_length (default: 32)
+Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
+by IPv4 network blocks with the specified network prefix. Aggregation
+reduces the \fBanvil\fR(8) resources needed to maintain counters. By
+default, aggregation is disabled for IPv4.
+.PP
+This feature is available in Postfix 3.8 and later.
+.SH smtpd_client_ipv6_prefix_length (default: 72)
+Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
+by IPv6 network blocks with the specified network prefix. Aggregation
+reduces the \fBanvil\fR(8) resources needed to maintain counters. By
+default, aggregation is enabled for IPv6.
+.PP
+This feature is available in Postfix 3.8 and later.
.SH smtpd_client_message_rate_limit (default: 0)
The maximal number of message delivery requests that any client is
allowed to make to this service per time unit, regardless of whether
smtpd_per_request_deadline.
.IP "\fBheader_from_format (standard)\fR"
The format of the Postfix\-generated \fBFrom:\fR header.
+.PP
+Available in Postfix version 3.8 and later:
+.IP "\fBsmtpd_client_ipv4_prefix_length (32)\fR"
+Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
+by IPv4 network blocks with the specified network prefix.
+.IP "\fBsmtpd_client_ipv6_prefix_length (72)\fR"
+Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
+by IPv6 network blocks with the specified network prefix.
.SH "TARPIT CONTROLS"
.na
.nf
s;\bsmtpd_client_port_logging\b;<a href="postconf.5.html#smtpd_client_port_logging">$&</a>;g;
s;\bsmtpd_client_recipient_rate_limit\b;<a href="postconf.5.html#smtpd_client_recipient_rate_limit">$&</a>;g;
s;\bsmtpd_client_new_tls_session_rate_limit\b;<a href="postconf.5.html#smtpd_client_new_tls_session_rate_limit">$&</a>;g;
+ s;\bsmtpd_client_ipv4_prefix_length\b;<a href="postconf.5.html#smtpd_client_ipv4_prefix_length">$&</a>;g;
+ s;\bsmtpd_client_ipv6_prefix_length\b;<a href="postconf.5.html#smtpd_client_ipv6_prefix_length">$&</a>;g;
s;\bsmtpd_client_restrictions\b;<a href="postconf.5.html#smtpd_client_restrictions">$&</a>;g;
s;\bsmtpd_command_filter\b;<a href="postconf.5.html#smtpd_command_filter">$&</a>;g;
s;\bsmtpd_data_restrictions\b;<a href="postconf.5.html#smtpd_data_restrictions">$&</a>;g;
to MX or IP address lookup as if SRV record lookup was not enabled. <p>
<p> This feature is available in Postfix 3.8 and later. </p>
+
+%PARAM smtpd_client_ipv4_prefix_length 32
+
+<p> Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
+by IPv4 network blocks with the specified network prefix. Aggregation
+reduces the anvil(8) resources needed to maintain counters. By
+default, aggregation is disabled for IPv4. </p>
+
+<p> This feature is available in Postfix 3.8 and later. </p>
+
+%PARAM smtpd_client_ipv6_prefix_length 72
+
+<p> Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
+by IPv6 network blocks with the specified network prefix. Aggregation
+reduces the anvil(8) resources needed to maintain counters. By
+default, aggregation is enabled for IPv6.
+</p>
+
+<p> This feature is available in Postfix 3.8 and later. </p>
void void cleanup_milter_receive state count
struct DICT open const char int int dict_xx_open
Available in in Postfix version 2 3 3 7
+length length of 0 31 0 127
tls tls_proxy h tlsproxy tlsproxy c
postfix postfix c postlog postlog c
postfix postfix c postlog postlog c
+ util net_mask_top hc smtpd smtpd c smtpd smtpd_peer c
ign
noport
nopref
+ADDRP
+iffalse
+iftrue
Bordo
css
makemanidx
+soho
+soho
const CLEANUP_STATE *state = (CLEANUP_STATE *) context;
const char *attr;
- vstring_sprintf(state->temp1, "%s: milter-%s-%s: %s %.60s from %s[%s];",
+ vstring_sprintf(state->temp1, "%s: milter-%s-%s: %s %.200s from %s[%s];",
state->queue_id, where, action, where, line,
state->client_name, state->client_addr);
if (state->sender)
#define DEF_SMTPD_CAUTH_LIMIT 0
extern int var_smtpd_cauth_limit;
+#define VAR_SMTPD_CIPV4_PREFIX "smtpd_client_ipv4_prefix_length"
+#define DEF_SMTPD_CIPV4_PREFIX 32
+#define MAX_SMTPD_CIPV4_PREFIX 32
+extern int var_smtpd_cipv4_prefix;
+
+#define VAR_SMTPD_CIPV6_PREFIX "smtpd_client_ipv6_prefix_length"
+#define DEF_SMTPD_CIPV6_PREFIX 72
+#define MAX_SMTPD_CIPV6_PREFIX 128
+extern int var_smtpd_cipv6_prefix;
+
#define VAR_SMTPD_HOGGERS "smtpd_client_event_limit_exceptions"
#define DEF_SMTPD_HOGGERS "${smtpd_client_connection_limit_exceptions:$" VAR_MYNETWORKS "}"
extern char *var_smtpd_hoggers;
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20230308"
+#define MAIL_RELEASE_DATE "20230312"
#define MAIL_VERSION_NUMBER "3.8"
#ifdef SNAPSHOT
dsb_status(why, "5.4.4");
break;
}
- *found_myself |= (self != 0);
/*
* If permitted, fall back to non-SRV record lookups.
else
addr_list = smtp_host_addr(name, misc_flags, why);
}
+
+ /*
+ * Only if we're not falling back.
+ */
+ else {
+ *found_myself |= (self != 0);
+ }
return (addr_list);
}
const SMTP_STATE *state = (SMTP_STATE *) context;
if (*text) {
- msg_info("%s: %s: %s %.60s: %s",
+ msg_info("%s: %s: %s %.200s: %s",
state->request->queue_id, action, where, content, text);
} else {
- msg_info("%s: %s: %s %.60s",
+ msg_info("%s: %s: %s %.200s",
state->request->queue_id, action, where, content);
}
}
smtpd_peer.o: ../../include/mymalloc.h
smtpd_peer.o: ../../include/name_code.h
smtpd_peer.o: ../../include/name_mask.h
+smtpd_peer.o: ../../include/net_mask_top.h
smtpd_peer.o: ../../include/nvtable.h
smtpd_peer.o: ../../include/sock_addr.h
smtpd_peer.o: ../../include/split_at.h
/* smtpd_per_request_deadline.
/* .IP "\fBheader_from_format (standard)\fR"
/* The format of the Postfix-generated \fBFrom:\fR header.
+/* .PP
+/* Available in Postfix version 3.8 and later:
+/* .IP "\fBsmtpd_client_ipv4_prefix_length (32)\fR"
+/* Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
+/* by IPv4 network blocks with the specified network prefix.
+/* .IP "\fBsmtpd_client_ipv6_prefix_length (72)\fR"
+/* Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
+/* by IPv6 network blocks with the specified network prefix.
/* TARPIT CONTROLS
/* .ad
/* .fi
int var_smtpd_crcpt_limit;
int var_smtpd_cntls_limit;
int var_smtpd_cauth_limit;
+int var_smtpd_cipv4_prefix;
+int var_smtpd_cipv6_prefix;
char *var_smtpd_hoggers;
char *var_local_rwr_clients;
char *var_smtpd_ehlo_dis_words;
&& anvil_clnt
&& var_smtpd_cauth_limit > 0
&& !namadr_list_match(hogger_list, state->name, state->addr)
- && anvil_clnt_auth(anvil_clnt, state->service, state->addr,
+ && anvil_clnt_auth(anvil_clnt, state->service, state->anvil_range,
&rate) == ANVIL_STAT_OK
&& rate > var_smtpd_cauth_limit) {
state->error_mask |= MAIL_ERROR_POLICY;
&& anvil_clnt
&& var_smtpd_cmail_limit > 0
&& !namadr_list_match(hogger_list, state->name, state->addr)
- && anvil_clnt_mail(anvil_clnt, state->service, state->addr,
+ && anvil_clnt_mail(anvil_clnt, state->service, state->anvil_range,
&rate) == ANVIL_STAT_OK
&& rate > var_smtpd_cmail_limit) {
state->error_mask |= MAIL_ERROR_POLICY;
&& anvil_clnt
&& var_smtpd_crcpt_limit > 0
&& !namadr_list_match(hogger_list, state->name, state->addr)
- && anvil_clnt_rcpt(anvil_clnt, state->service, state->addr,
+ && anvil_clnt_rcpt(anvil_clnt, state->service, state->anvil_range,
&rate) == ANVIL_STAT_OK
&& rate > var_smtpd_crcpt_limit) {
state->error_mask |= MAIL_ERROR_POLICY;
&& anvil_clnt
&& var_smtpd_crcpt_limit > 0
&& !namadr_list_match(hogger_list, state->name, state->addr)
- && anvil_clnt_rcpt(anvil_clnt, state->service, state->addr,
+ && anvil_clnt_rcpt(anvil_clnt, state->service, state->anvil_range,
&rate) == ANVIL_STAT_OK
&& rate > var_smtpd_crcpt_limit) {
state->error_mask |= MAIL_ERROR_POLICY;
&& !xclient_allowed
&& anvil_clnt
&& !namadr_list_match(hogger_list, state->name, state->addr)
- && anvil_clnt_newtls(anvil_clnt, state->service, state->addr,
+ && anvil_clnt_newtls(anvil_clnt, state->service, state->anvil_range,
&rate) == ANVIL_STAT_OK
&& rate > var_smtpd_cntls_limit) {
state->error_mask |= MAIL_ERROR_POLICY;
&& !xclient_allowed
&& anvil_clnt
&& !namadr_list_match(hogger_list, state->name, state->addr)
- && anvil_clnt_newtls_stat(anvil_clnt, state->service, state->addr,
- &rate) == ANVIL_STAT_OK
+ && anvil_clnt_newtls_stat(anvil_clnt, state->service,
+ state->anvil_range, &rate) == ANVIL_STAT_OK
&& rate > var_smtpd_cntls_limit) {
state->error_mask |= MAIL_ERROR_POLICY;
msg_warn("Refusing STARTTLS request from %s for service %s",
&& anvil_clnt
&& !namadr_list_match(hogger_list, state->name, state->addr)
&& anvil_clnt_newtls_stat(anvil_clnt, state->service,
- state->addr, &tls_rate) == ANVIL_STAT_OK
+ state->anvil_range, &tls_rate) == ANVIL_STAT_OK
&& tls_rate > var_smtpd_cntls_limit) {
state->error_mask |= MAIL_ERROR_POLICY;
msg_warn("Refusing TLS service request from %s for service %s",
&& !xclient_allowed
&& anvil_clnt
&& !namadr_list_match(hogger_list, state->name, state->addr)
- && anvil_clnt_connect(anvil_clnt, state->service, state->addr,
- &state->conn_count, &state->conn_rate)
+ && anvil_clnt_connect(anvil_clnt, state->service,
+ state->anvil_range, &state->conn_count,
+ &state->conn_rate)
== ANVIL_STAT_OK) {
if (var_smtpd_cconn_limit > 0
&& state->conn_count > var_smtpd_cconn_limit) {
&& !xclient_allowed
&& anvil_clnt
&& !namadr_list_match(hogger_list, state->name, state->addr))
- anvil_clnt_disconnect(anvil_clnt, state->service, state->addr);
+ anvil_clnt_disconnect(anvil_clnt, state->service, state->anvil_range);
/*
* Log abnormal session termination, in case postmaster notification has
VAR_SMTPD_CRCPT_LIMIT, DEF_SMTPD_CRCPT_LIMIT, &var_smtpd_crcpt_limit, 0, 0,
VAR_SMTPD_CNTLS_LIMIT, DEF_SMTPD_CNTLS_LIMIT, &var_smtpd_cntls_limit, 0, 0,
VAR_SMTPD_CAUTH_LIMIT, DEF_SMTPD_CAUTH_LIMIT, &var_smtpd_cauth_limit, 0, 0,
+ VAR_SMTPD_CIPV4_PREFIX, DEF_SMTPD_CIPV4_PREFIX, &var_smtpd_cipv4_prefix, 0, MAX_SMTPD_CIPV4_PREFIX,
+ VAR_SMTPD_CIPV6_PREFIX, DEF_SMTPD_CIPV6_PREFIX, &var_smtpd_cipv6_prefix, 0, MAX_SMTPD_CIPV6_PREFIX,
#ifdef USE_TLS
VAR_SMTPD_TLS_CCERT_VD, DEF_SMTPD_TLS_CCERT_VD, &var_smtpd_tls_ccert_vd, 0, 0,
#endif
char *addr; /* client host address string */
char *port; /* port for logging */
char *namaddr; /* name[address]:port */
+ char *anvil_range; /* client address or network/length */
char *rfc_addr; /* address for RFC 2821 */
int addr_family; /* address family */
char *dest_addr; /* Dovecot AUTH, Milter {daemon_addr} */
#include <sock_addr.h>
#include <inet_proto.h>
#include <split_at.h>
+#include <net_mask_top.h>
/* Global library. */
state->addr = mystrdup(colonp + 1);
state->rfc_addr = mystrdup(colonp + 1);
state->addr_family = AF_INET;
- aierr = hostaddr_to_sockaddr(state->addr, (char *) 0, 0, &res0);
+ aierr =
+ hostaddr_to_sockaddr(state->addr, state->port, 0, &res0);
if (aierr)
- msg_fatal("%s: cannot convert %s from string to binary: %s",
- myname, state->addr, MAI_STRERROR(aierr));
+ msg_fatal("%s: cannot convert [%s]:%s to binary: %s",
+ myname, state->addr, state->port,
+ MAI_STRERROR(aierr));
sa_length = res0->ai_addrlen;
if (sa_length > sizeof(state->sockaddr))
sa_length = sizeof(state->sockaddr);
/*
* Following RFC 2821 section 4.1.3, an IPv6 address literal gets
* a prefix of 'IPv6:'. We do this consistently for all IPv6
- * addresses that appear in headers or envelopes. The fact
- * that valid_mailhost_addr() enforces the form helps of course.
- * We use the form without IPV6: prefix when doing access
- * control, or when accessing the connection cache.
+ * addresses that appear in headers or envelopes. The fact that
+ * valid_mailhost_addr() enforces the form helps of course. We
+ * use the form without IPV6: prefix when doing access control,
+ * or when accessing the connection cache.
*/
else {
state->addr = mystrdup(client_addr.buf);
void smtpd_peer_init(SMTPD_STATE *state)
{
+ int af;
/*
* Initialize.
state->namaddr = 0;
state->rfc_addr = 0;
state->port = 0;
+ state->anvil_range = 0;
state->dest_addr = 0;
state->dest_port = 0;
*/
state->namaddr = SMTPD_BUILD_NAMADDRPORT(state->name, state->addr,
state->port);
+
+ /*
+ * Generate 'address' or 'net/mask' index for anvil event aggregation.
+ */
+ af = SOCK_ADDR_FAMILY(&(state->sockaddr));
+ state->anvil_range = net_mask_top(af,
+ SOCK_ADDR_ADDRP(&(state->sockaddr)),
+ af == AF_INET ?
+ var_smtpd_cipv4_prefix :
+ var_smtpd_cipv6_prefix);
}
/* smtpd_peer_reset - destroy peer information */
myfree(state->dest_addr);
if (state->dest_port)
myfree(state->dest_port);
+ if (state->anvil_range)
+ myfree(state->anvil_range);
}
static const char hexcodes[] = "0123456789ABCDEF";
-#define checkok(stillok) (ok = ok && (stillok))
-#define digest_object(p) digest_data((unsigned char *)(p), sizeof(*(p)))
-#define digest_data(p, l) checkok(digest_bytes(mdctx, (p), (l)))
-#define digest_string(s) checkok(digest_chars(mdctx, (s)))
-#define digest_dane(tlsa) checkok(tls_digest_tlsa(mdctx, tlsa))
+#define CHECK_OK_AND(stillok) (ok = ok && (stillok))
+#define CHECK_OK_AND_DIGEST_OBJECT(m, p) \
+ CHECK_OK_AND_DIGEST_DATA((m), (unsigned char *)(p), sizeof(*(p)))
+#define CHECK_OK_AND_DIGEST_DATA(m, p, l) CHECK_OK_AND(digest_bytes((m), (p), (l)))
+#define CHECK_OK_AND_DIGEST_CHARS(m, s) CHECK_OK_AND(digest_chars((m), (s)))
/* digest_bytes - hash octet string of given length */
arr[i++] = (void *) p;
qsort(arr, n, sizeof(arr[0]), tlsa_cmp);
- digest_object(&n);
+ CHECK_OK_AND_DIGEST_OBJECT(mdctx, &n);
for (i = 0; i < n; ++i) {
- digest_object(&arr[i]->usage);
- digest_object(&arr[i]->selector);
- digest_object(&arr[i]->mtype);
- digest_object(&arr[i]->length);
- digest_data(arr[i]->data, arr[i]->length);
+ CHECK_OK_AND_DIGEST_OBJECT(mdctx, &arr[i]->usage);
+ CHECK_OK_AND_DIGEST_OBJECT(mdctx, &arr[i]->selector);
+ CHECK_OK_AND_DIGEST_OBJECT(mdctx, &arr[i]->mtype);
+ CHECK_OK_AND_DIGEST_OBJECT(mdctx, &arr[i]->length);
+ CHECK_OK_AND_DIGEST_DATA(mdctx, arr[i]->data, arr[i]->length);
}
myfree((void *) arr);
return (ok);
* Note that EVP_MD_CTX_{create,destroy} were renamed to, respectively,
* EVP_MD_CTX_{new,free} in OpenSSL 1.1.0.
*/
- checkok(md = EVP_get_digestbyname(mdalg));
+ CHECK_OK_AND(md = EVP_get_digestbyname(mdalg));
/*
* Sanity check: Newer shared libraries could (hypothetical ABI break)
* allow larger digests, we avoid such poison algorithms.
*/
- checkok(EVP_MD_size(md) <= EVP_MAX_MD_SIZE);
- checkok(mdctx = EVP_MD_CTX_new());
- checkok(EVP_DigestInit_ex(mdctx, md, NULL));
+ CHECK_OK_AND(EVP_MD_size(md) <= EVP_MAX_MD_SIZE);
+ CHECK_OK_AND(mdctx = EVP_MD_CTX_new());
+ CHECK_OK_AND(EVP_DigestInit_ex(mdctx, md, NULL));
if (ok && mdctxPtr != 0)
/* Salt the session lookup key with the OpenSSL runtime version. */
sslversion = OpenSSL_version_num();
- digest_string(props->helo ? props->helo : "");
- digest_object(&sslversion);
- digest_string(props->protocols);
- digest_string(ciphers);
+ CHECK_OK_AND_DIGEST_CHARS(mdctx, props->helo ? props->helo : "");
+ CHECK_OK_AND_DIGEST_OBJECT(mdctx, &sslversion);
+ CHECK_OK_AND_DIGEST_CHARS(mdctx, props->protocols);
+ CHECK_OK_AND_DIGEST_CHARS(mdctx, ciphers);
/*
* Ensure separation of caches for sessions where DANE trust
* should always see a certificate validation failure, both on initial
* handshake and on resumption.
*/
- digest_object(&TLScontext->must_fail);
+ CHECK_OK_AND_DIGEST_OBJECT(mdctx, &TLScontext->must_fail);
/*
* DNS-based or synthetic DANE trust settings are potentially used at all
*/
if (TLScontext->level > TLS_LEV_ENCRYPT
&& props->dane && props->dane->tlsa) {
- digest_dane(props->dane->tlsa);
+ CHECK_OK_AND(tls_digest_tlsa(mdctx, props->dane->tlsa));
} else {
int none = 0; /* Record a TLSA RR count of zero */
- digest_object(&none);
+ CHECK_OK_AND_DIGEST_OBJECT(mdctx, &none);
}
/*
* selection.
*/
if (TLScontext->level > TLS_LEV_ENCRYPT && TLScontext->peer_sni)
- digest_string(TLScontext->peer_sni);
+ CHECK_OK_AND_DIGEST_CHARS(mdctx, TLScontext->peer_sni);
else
- digest_string("");
+ CHECK_OK_AND_DIGEST_CHARS(mdctx, "");
- checkok(EVP_DigestFinal_ex(mdctx, md_buf, &md_len));
+ CHECK_OK_AND(EVP_DigestFinal_ex(mdctx, md_buf, &md_len));
EVP_MD_CTX_destroy(mdctx);
if (!ok)
msg_fatal("error computing %s message digest", mdalg);
if (tls_digest_byname(mdalg, &mdctx) == 0)
msg_panic("digest algorithm \"%s\" not found", mdalg);
- digest_data(buf, len);
- checkok(EVP_DigestFinal_ex(mdctx, md_buf, &md_len));
+ CHECK_OK_AND_DIGEST_DATA(mdctx, buf, len);
+ CHECK_OK_AND(EVP_DigestFinal_ex(mdctx, md_buf, &md_len));
EVP_MD_CTX_destroy(mdctx);
if (!ok)
msg_fatal("error computing %s message digest", mdalg);
msg_logger.c logwriter.c unix_dgram_connect.c unix_dgram_listen.c \
byte_mask.c known_tcp_ports.c argv_split_at.c dict_stream.c \
sane_strtol.c hash_fnv.c ldseed.c mkmap_cdb.c mkmap_db.c mkmap_dbm.c \
- mkmap_fail.c mkmap_lmdb.c mkmap_open.c mkmap_sdbm.c
+ mkmap_fail.c mkmap_lmdb.c mkmap_open.c mkmap_sdbm.c net_mask_top.c
OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
msg_logger.o logwriter.o unix_dgram_connect.o unix_dgram_listen.o \
byte_mask.o known_tcp_ports.o argv_split_at.o dict_stream.o \
sane_strtol.o hash_fnv.o ldseed.o mkmap_db.o mkmap_dbm.o \
- mkmap_fail.o mkmap_open.o
+ mkmap_fail.o mkmap_open.o net_mask_top.o
# MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
# When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
# otherwise it sets the PLUGIN_* macros.
slmdb.h compat_va_copy.h dict_pipe.h dict_random.h \
valid_utf8_hostname.h midna_domain.h dict_union.h dict_inline.h \
check_arg.h argv_attr.h msg_logger.h logwriter.h byte_mask.h \
- known_tcp_ports.h sane_strtol.h hash_fnv.h ldseed.h mkmap.h
+ known_tcp_ports.h sane_strtol.h hash_fnv.h ldseed.h mkmap.h \
+ net_mask_top.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
DEFS = -I. -D$(SYSTYPE)
nbbio.o: nbbio.c
nbbio.o: nbbio.h
nbbio.o: sys_defs.h
+net_mask_top.o: check_arg.h
+net_mask_top.o: mask_addr.h
+net_mask_top.o: msg.h
+net_mask_top.o: myaddrinfo.h
+net_mask_top.o: net_mask_top.c
+net_mask_top.o: net_mask_top.h
+net_mask_top.o: sys_defs.h
+net_mask_top.o: vbuf.h
+net_mask_top.o: vstring.h
netstring.o: check_arg.h
netstring.o: compat_va_copy.h
netstring.o: msg.h
--- /dev/null
+/*++
+/* NAME
+/* net_mask_top 3
+/* SUMMARY
+/* convert net/mask to printable string
+/* SYNOPSIS
+/* #include <mask_addr.h>
+/*
+/* char *net_mask_top(
+/* int family,
+/* const void *src,
+/* int prefix_len)
+/* DESCRIPTION
+/* net_mask_top() prints the network portion of the specified
+/* IPv4 or IPv6 address, null bits for the host portion, and
+/* the prefix length if it is shorter than the address.
+/* The result should be passed to myfree(). The code can
+/* handle addresses of any length, and bytes of any width.
+/*
+/* Arguments:
+/* .IP af
+/* The address family, as with inet_ntop().
+/* .IP src
+/* Pointer to storage for an IPv4 or IPv6 address, as with
+/* inet_ntop().
+/* .IP prefix_len
+/* The number of most-significant bits in \fBsrc\fR that should
+/* not be cleared.
+/* DIAGNOSTICS
+/* Panic: unexpected protocol family, bad prefix length. Fatal
+/* errors: address conversion error.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/*--*/
+
+ /*
+ * System library.
+ */
+#include <sys_defs.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+ /*
+ * Utility library.
+ */
+#include <mask_addr.h>
+#include <msg.h>
+#include <myaddrinfo.h>
+#include <net_mask_top.h>
+#include <vstring.h>
+
+/*
+ * XXX Factor out if we also need this in other places.
+ */
+struct addr_size {
+ int af; /* address family (binary) */
+ char ipproto_str[5]; /* IP protocol version (string) */
+ int addr_bitcount; /* bits per address */
+ int addr_bytecount; /* bytes per address */
+ int addr_strlen; /* string representation length */
+ int slashdigs_strlen; /* length of /0-31, /0-127 */
+};
+static struct addr_size addr_sizes[] = {
+ AF_INET, "IPv4", MAI_V4ADDR_BITS, MAI_V4ADDR_BYTES, INET_ADDRSTRLEN, 3,
+#ifdef HAS_IPV6
+ AF_INET6, "IPv6", MAI_V6ADDR_BITS, MAI_V6ADDR_BYTES, INET6_ADDRSTRLEN, 4,
+#endif
+};
+
+/* get_addr_size - get bit-banging numbers for address family */
+
+static struct addr_size *get_addr_size(int af)
+{
+ struct addr_size *ap;
+
+ for (ap = addr_sizes; /* see below */ ; ap++) {
+ if (ap >= addr_sizes + sizeof(addr_sizes) / sizeof(struct addr_size))
+ return (0);
+ if (ap->af == af)
+ return (ap);
+ }
+}
+
+/* net_mask_top - printable net/mask pattern */
+
+char *net_mask_top(int af, const void *src, int prefix_len)
+{
+ const char myname[] = "net_mask_top";
+ union {
+ struct in_addr in_addr;
+ struct in6_addr in6_addr;
+ } u;
+ VSTRING *buf;
+ struct addr_size *ap;
+
+ if ((ap = get_addr_size(af)) == 0)
+ msg_panic("%s: unexpected address family: %d", myname, af);
+ if (prefix_len > ap->addr_bitcount || prefix_len < 0)
+ msg_fatal("%s: bad %s address prefix length: %d",
+ myname, ap->ipproto_str, prefix_len);
+ memcpy((void *) &u, src, ap->addr_bytecount);
+ if (prefix_len < ap->addr_bitcount) {
+ mask_addr((unsigned char *) &u, ap->addr_bytecount, prefix_len);
+ buf = vstring_alloc(ap->addr_strlen + ap->slashdigs_strlen);
+ } else {
+ buf = vstring_alloc(ap->addr_strlen);
+ }
+ if (inet_ntop(af, &u, vstring_str(buf), vstring_avail(buf)) == 0)
+ msg_fatal("%s: inet_ntop: %m", myname);
+ vstring_set_payload_size(buf, strlen(vstring_str(buf)));
+ if (prefix_len < ap->addr_bitcount)
+ vstring_sprintf_append(buf, "/%d", prefix_len);
+ return (vstring_export(buf));
+}
--- /dev/null
+#ifndef _NET_MASK_TOP_H_INCLUDED_
+#define _NET_MASK_TOP_H_INCLUDED_
+
+/*++
+/* NAME
+/* net_mask_top 3h
+/* SUMMARY
+/* convert net/mask to printable string
+/* SYNOPSIS
+/* #include <net_mask_top.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * External interface.
+ */
+extern char *net_mask_top(int, const void *, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/*--*/
+
+#endif
/* struct sockaddr *SOCK_ADDR_PTR(ptr)
/* unsigned char SOCK_ADDR_FAMILY(ptr)
/* unsigned char SOCK_ADDR_LEN(ptr)
+/* void *SOCK_ADDR_ADDRP(ptr)
/* unsigned short SOCK_ADDR_PORT(ptr)
/* unsigned short *SOCK_ADDR_PORTP(ptr)
/*
/* address family and length of the real structure that hides
/* inside a generic sockaddr structure. On systems where struct
/* sockaddr has no sa_len member, SOCK_ADDR_LEN() cannot be
-/* used as lvalue. SOCK_ADDR_PORT() returns the IPv4 or IPv6
+/* used as lvalue. SOCKADDR_ADDRP() returns a pointer to the
+/* IPv4 or IPv6 address. SOCK_ADDR_PORT() returns the IPv4 or IPv6
/* port number, in network byte order; it must not be used as
/* lvalue. SOCK_ADDR_PORTP() returns a pointer to the same.
/*
sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
#endif
+#define SOCK_ADDR_ADDRP(sa) \
+ (SOCK_ADDR_FAMILY(sa) == AF_INET ? \
+ (void *) &SOCK_ADDR_IN_ADDR(sa) : (void *) &SOCK_ADDR_IN6_ADDR(sa))
#define SOCK_ADDR_PORT(sa) \
(SOCK_ADDR_PTR(sa)->sa_family == AF_INET6 ? \
SOCK_ADDR_IN6_PORT(sa) : SOCK_ADDR_IN_PORT(sa))
#define SOCK_ADDR_LEN(sa) sizeof(struct sockaddr_in)
#endif
-#define SOCK_ADDR_PORT(sa) SOCK_ADDR_IN_PORT(sa))
-#define SOCK_ADDR_PORTP(sa) &SOCK_ADDR_IN_PORT(sa))
+#define SOCK_ADDR_ADDRP(sa) (&SOCK_ADDR_IN_ADDR(sa))
+#define SOCK_ADDR_PORT(sa) SOCK_ADDR_IN_PORT(sa)
+#define SOCK_ADDR_PORTP(sa) (&SOCK_ADDR_IN_PORT(sa))
#define SOCK_ADDR_EQ_ADDR(sa, sb) \
(SOCK_ADDR_FAMILY(sa) == AF_INET && SOCK_ADDR_FAMILY(sb) == AF_INET \