# HG changeset patch # User Michael Schloh von Bennewitz # Date 1347559549 -7200 # Node ID 7a7cc794483bf5325ccb01d2930bd5e2c0514375 # Parent 43d6421543301027cceb472e3f02b6f6ffc1b66e Integrate useful recipient and helo access maps, and introduce SRS logic. diff -r 43d642154330 -r 7a7cc794483b postfix/postfix-srs.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/postfix/postfix-srs.patch Thu Sep 13 20:05:49 2012 +0200 @@ -0,0 +1,493 @@ +diff -urN README_FILES/SRS_README.orig README_FILES/SRS_README +--- README_FILES/SRS_README.orig 1970-01-01 01:00:00.000000000 +0100 ++++ README_FILES/SRS_README 2012-02-21 14:22:05.000000000 +0100 +@@ -0,0 +1,56 @@ ++ ++CREDITS: ++ ++- originally written by Shevek ++- fixes and porting to postfix 2.1 by Branko F. Gracnar ++- redesigned and ported to debian postfix 2.7.0 by Chris ++ ++SYNOPSIS: ++Works with all address classes (not limited to local domain). ++Doesn't depend on .forward-files or alias_maps. ++SMTPD accepts valid srs addresses without further configuration. ++Sender gets rewritten only when necessary: ++- rewrite after queuing (after separation to on- and off-site destinations) ++- rewrite only if sender and recipient are off-site and host is not a relay for recipient ++Alias domain can be chosen automatically from original on-site-recipient. ++ ++ ++USAGE: ++ ++1) Apply the patch. ++ ++2) Create makefiles with ++ ++make makefiles CCARGS="-DHAS_SRS -I" AUXLIBS="-L -lsrs2" ++ ++ ++3) Build. ++ ++4) Add the following global configuration variables to main.cf: ++All variables are optional, except where stated: ++ ++ srs_domain (string) ++ A domain to use in rewritten addresses. This must point only ++ to machines which know the encoding secret used by this ++ system. It defaults to $myorigin. If set to the emtpy ++ string, use domain from original recipient if host is final ++ destination, otherwise use $myorigin. ++ srs_hashlength (int) ++ The hash length to generate in a rewritten address. ++ srs_hashmin (int) ++ The hash length to require when checking an address. ++ srs_maxage (int) ++ The maximum permitted age of a rewritten address. ++ srs_secrets (string) ++ [required] A list of secrets with which to generate ++ and check addresses. ++ srs_separator (string) ++ The separator to appear immediately after SRS[01] in ++ rewritten addresses. ++ ++ ++See http://www.libsrs2.org/ for more information about the meaning ++of these variables. They are standard across MTAs. ++ ++5) Fire up and enjoy. ++ +diff -urN src/cleanup/cleanup_addr.c.orig src/cleanup/cleanup_addr.c +--- src/cleanup/cleanup_addr.c.orig 2012-02-21 14:21:34.000000000 +0100 ++++ src/cleanup/cleanup_addr.c 2012-02-21 14:22:05.000000000 +0100 +@@ -163,6 +163,10 @@ + { + VSTRING *clean_addr = vstring_alloc(100); + const char *bcc; ++#ifdef HAS_SRS ++ int srs_state; ++ VSTRING *srs_rcpt; ++#endif + + /* + * Note: an unqualified envelope address is for all practical purposes +@@ -174,6 +178,14 @@ + cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL, + clean_addr, *buf ? buf : var_empty_addr); + if (state->flags & CLEANUP_FLAG_MAP_OK) { ++#ifdef HAS_SRS ++ if ((srs_state = postfix_srs_reverse(STR(clean_addr), &srs_rcpt)) < 0) { ++ /* XXX errors */ ++ } else if (srs_state == 1) { ++ vstring_free(clean_addr); ++ clean_addr = srs_rcpt; ++ } ++#endif + if (cleanup_rcpt_canon_maps + && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT)) + cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, +diff -urN src/global/mail_params.c.orig src/global/mail_params.c +--- src/global/mail_params.c.orig 2012-02-21 14:21:34.000000000 +0100 ++++ src/global/mail_params.c 2012-02-21 14:22:05.000000000 +0100 +@@ -308,6 +308,15 @@ + bool var_long_queue_ids; + bool var_daemon_open_fatal; + ++#ifdef HAS_SRS ++int var_srs_hashlength; ++int var_srs_hashmin; ++int var_srs_maxage; ++char *var_srs_secrets; ++char *var_srs_separator; ++char *var_srs_domain; ++#endif ++ + const char null_format_string[1] = ""; + + /* check_myhostname - lookup hostname and validate */ +@@ -579,6 +588,11 @@ + VAR_INT_FILT_CLASSES, DEF_INT_FILT_CLASSES, &var_int_filt_classes, 0, 0, + /* multi_instance_wrapper may have dependencies but not dependents. */ + VAR_MULTI_WRAPPER, DEF_MULTI_WRAPPER, &var_multi_wrapper, 0, 0, ++#ifdef HAS_SRS ++ VAR_SRS_SECRETS, DEF_SRS_SECRETS, &var_srs_secrets, 0, 0, ++ VAR_SRS_SEPARATOR, DEF_SRS_SEPARATOR, &var_srs_separator, 1, 1, ++ VAR_SRS_DOMAIN, DEF_SRS_DOMAIN, &var_srs_domain, 0, 0, ++#endif + 0, + }; + static const CONFIG_STR_FN_TABLE function_str_defaults_2[] = { +@@ -602,6 +616,11 @@ + VAR_MIME_BOUND_LEN, DEF_MIME_BOUND_LEN, &var_mime_bound_len, 1, 0, + VAR_DELAY_MAX_RES, DEF_DELAY_MAX_RES, &var_delay_max_res, MIN_DELAY_MAX_RES, MAX_DELAY_MAX_RES, + VAR_INET_WINDOW, DEF_INET_WINDOW, &var_inet_windowsize, 0, 0, ++#ifdef HAS_SRS ++ VAR_SRS_HASHLENGTH, DEF_SRS_HASHLENGTH, &var_srs_hashlength, 1, 20, ++ VAR_SRS_HASHMIN, DEF_SRS_HASHMIN, &var_srs_hashmin, 1, 20, ++ VAR_SRS_MAXAGE, DEF_SRS_MAXAGE, &var_srs_maxage, 1, 0, ++#endif + 0, + }; + static const CONFIG_LONG_TABLE long_defaults[] = { +diff -urN src/global/mail_params.h.orig src/global/mail_params.h +--- src/global/mail_params.h.orig 2012-02-21 14:21:34.000000000 +0100 ++++ src/global/mail_params.h 2012-02-21 14:22:41.000000000 +0100 +@@ -1981,6 +1981,35 @@ + #define DEF_ALLOW_UNTRUST_ROUTE 0 + extern bool var_allow_untrust_route; + ++/** ++ * SRS. Shevek , updated by Chris ++ */ ++#ifdef HAS_SRS ++#define VAR_SRS_HASHLENGTH "srs_hashlength" ++#define DEF_SRS_HASHLENGTH 4 ++extern int var_srs_hashlength; ++ ++#define VAR_SRS_HASHMIN "srs_hashmin" ++#define DEF_SRS_HASHMIN 4 ++extern int var_srs_hashmin; ++ ++#define VAR_SRS_MAXAGE "srs_maxage" ++#define DEF_SRS_MAXAGE 21 ++extern int var_srs_maxage; ++ ++#define VAR_SRS_SECRETS "srs_secrets" ++#define DEF_SRS_SECRETS "" ++extern char *var_srs_secrets; ++ ++#define VAR_SRS_DOMAIN "srs_domain" ++#define DEF_SRS_DOMAIN "$myorigin" ++extern char *var_srs_domain; ++ ++#define VAR_SRS_SEPARATOR "srs_separator" ++#define DEF_SRS_SEPARATOR "=" ++extern char *var_srs_separator; ++#endif ++ + /* + * Names of specific restrictions, and the corresponding configuration + * parameters that control the status codes sent in response to rejected +diff -urN src/global/Makefile.in.orig src/global/Makefile.in +--- src/global/Makefile.in.orig 2012-02-21 14:21:34.000000000 +0100 ++++ src/global/Makefile.in 2012-02-21 14:22:05.000000000 +0100 +@@ -29,7 +29,7 @@ + user_acl.c valid_mailhost_addr.c verify.c verify_clnt.c \ + verp_sender.c wildcard_inet_addr.c xtext.c delivered_hdr.c \ + fold_addr.c header_body_checks.c mkmap_proxy.c data_redirect.c \ +- match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \ ++ match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c srs.c \ + smtp_reply_footer.c safe_ultostr.c verify_sender_addr.c \ + dict_memcache.c mail_version.c memcache_proto.c server_acl.c \ + mkmap_fail.c +@@ -63,7 +63,7 @@ + user_acl.o valid_mailhost_addr.o verify.o verify_clnt.o \ + verp_sender.o wildcard_inet_addr.o xtext.o delivered_hdr.o \ + fold_addr.o header_body_checks.o mkmap_proxy.o data_redirect.o \ +- match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \ ++ match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o srs.o \ + smtp_reply_footer.o safe_ultostr.o verify_sender_addr.o \ + dict_memcache.o mail_version.o memcache_proto.o server_acl.o \ + mkmap_fail.o +diff -urN src/global/srs.c.orig src/global/srs.c +--- src/global/srs.c.orig 1970-01-01 01:00:00.000000000 +0100 ++++ src/global/srs.c 2012-02-21 14:22:27.000000000 +0100 +@@ -0,0 +1,144 @@ ++/*++ ++/* NAME ++/* srs 3 ++/* SUMMARY ++/* Sender Rewriting Scheme ++/* SYNOPSIS ++/* void postfix_srs_reverse(rcpt, decoded) ++/* const char *rcpt ++/* VSTRING **decoded ++/* ++/* int postfix_srs_forward(sender, alias, encoded) ++/* const char *sender ++/* const char *alias ++/* VSTRING **decoded ++/* DESCRIPTION ++/* This module rewrites addresses according to the Sender Rewriting ++/* Scheme, documented at http://www.libsrs2.org/. ++/* ++/* srs_reverse() reverse-rewrites the rewritten form of an address ++/* ++/* srs_forward() rewrites the envelope sender using alias domain ++/* ++/* DIAGNOSTICS ++/* LICENSE ++/* .ad ++/* .fi ++/* The Secure Mailer license must be distributed with this software. ++/* AUTHOR(S) ++/* Shevek ++/* Chris ++/*--*/ ++ ++#ifdef HAS_SRS ++ ++/* System library. */ ++ ++#include ++#include ++#include ++ ++#include ++ ++/* Utility library. */ ++ ++#include ++#include ++#include ++#include ++ ++/* Global library. */ ++ ++#include ++ ++#define SRS_FAIL_UNLESS(x) do { int __ret = (x); if (__ret != SRS_SUCCESS) msg_fatal("SRS configuration error: %s", srs_strerror(__ret)); } while(0) ++ ++/* my function declarations */ ++int postfix_srs_forward (const char *sender, const char *alias, VSTRING **encoded); ++int postfix_srs_reverse (const char *rcpt, VSTRING **decoded); ++ ++static srs_t *srs; ++ ++static void postfix_srs_init (void) { ++ char *saved_secrets; ++ char *secret; ++ char *ptr; ++ ++ if (srs == NULL) { ++ /* XXX Can't use memory functions from postfix because of inconsistensies in libsrs2 ++ srs_set_malloc((srs_malloc_t)mymalloc, (srs_realloc_t)myrealloc, (srs_free_t)myfree); ++ */ ++ ++ srs = srs_new(); ++ /* avoid sender-domain-check, since we have already done this ourselves */ ++ SRS_FAIL_UNLESS(srs_set_alwaysrewrite(srs, 1)); ++ SRS_FAIL_UNLESS(srs_set_hashlength(srs, var_srs_hashlength)); ++ SRS_FAIL_UNLESS(srs_set_hashmin(srs, var_srs_hashmin)); ++ SRS_FAIL_UNLESS(srs_set_maxage(srs, var_srs_maxage)); ++ SRS_FAIL_UNLESS(srs_set_separator(srs, var_srs_separator[0])); ++ ++ ptr = saved_secrets = mystrdup(var_srs_secrets); ++ while ((secret = mystrtok(&ptr, ", \t\r\n")) != 0) { ++ SRS_FAIL_UNLESS(srs_add_secret(srs, secret)); ++ } ++ myfree(saved_secrets); ++ } ++} ++ ++int postfix_srs_reverse(const char *rcpt, VSTRING **decoded) { ++ char *out; ++ int ret; ++ ++ if (!SRS_IS_SRS_ADDRESS(rcpt)) ++ return (0); ++ ++ postfix_srs_init(); ++ ++ ret = srs_reverse_alloc(srs, &out, rcpt); ++ ++ if (ret != SRS_SUCCESS) { ++ switch (SRS_ERROR_TYPE(ret)) { ++ case SRS_ERRTYPE_CONFIG: ++ msg_fatal("SRS configuration error: %s", srs_strerror(ret)); ++ return (-1); ++ case SRS_ERRTYPE_INPUT: ++ msg_fatal("SRS reverse failed for <%s>: %s", rcpt, srs_strerror(ret)); ++ return (-1); ++ case SRS_ERRTYPE_SYNTAX: ++ case SRS_ERRTYPE_SRS: ++ msg_warn("SRS reverse failed for <%s>: %s", rcpt, srs_strerror(ret)); ++ break; ++ } ++ return (0); ++ } ++ ++ if (decoded) { ++ *decoded = vstring_alloc(100); ++ vstring_strcpy(*decoded, out); ++ } ++ free(out); ++ ++ return (1); ++} ++ ++int postfix_srs_forward(const char *sender, const char *alias, VSTRING **encoded) { ++ char *out; ++ int ret; ++ ++ postfix_srs_init(); ++ ++ ret = srs_forward_alloc(srs, &out, sender, alias); ++ ++ if (ret != SRS_SUCCESS) { ++ msg_warn("SRS forward failed for <%s>: %s", sender, srs_strerror(ret)); ++ return (0); ++ } ++ ++ *encoded = vstring_alloc(100); ++ vstring_strcpy(*encoded, out); ++ free(out); ++ ++ return (1); ++} ++ ++#endif +diff -urN src/qmgr/qmgr_deliver.c.orig src/qmgr/qmgr_deliver.c +--- src/qmgr/qmgr_deliver.c.orig 2012-02-21 14:21:34.000000000 +0100 ++++ src/qmgr/qmgr_deliver.c 2012-02-21 14:22:05.000000000 +0100 +@@ -76,6 +76,7 @@ + #include + #include + #include ++#include + + /* Application-specific. */ + +@@ -129,6 +130,73 @@ + } + } + ++#ifdef HAS_SRS ++/* qmgr_deliver_check_srs - check whether sender should be rewritten */ ++ ++static int qmgr_deliver_check_srs(QMGR_MESSAGE *message, RECIPIENT_LIST list, char **alias, RESOLVE_REPLY *reply) ++{ ++ char *pos; ++ ++ /* ++ * Rewrite if we are not final destination nor relay host for recipient and sender address ++ * it should be enough to look at the first recipient, since transport/nexthop are the same for all recipients ++ */ ++ resolve_clnt_query(list.info->address, reply); ++ if (reply->flags & RESOLVE_FLAG_FAIL) ++ return (-1); ++ else if (!(reply->flags & RESOLVE_CLASS_DEFAULT)) ++ return (0); ++ ++ resolve_clnt_query(message->sender, reply); ++ if (reply->flags & RESOLVE_FLAG_FAIL) ++ return (-1); ++ else if (!(reply->flags & RESOLVE_CLASS_DEFAULT)) ++ return (0); ++ ++ if (var_srs_domain[0]) { ++ *alias = var_srs_domain; ++ } else { ++ /* retrieve alias domain from original recipient if we are final destination ... */ ++ resolve_clnt_query(list.info->orig_addr, reply); ++ if (reply->flags & RESOLVE_FLAG_FAIL) ++ return (-1); ++ if ((reply->flags & RESOLVE_CLASS_FINAL) && (pos = strrchr(list.info->orig_addr, '@'))) { ++ *alias = pos + 1; ++ } else { ++ /* ... or use myorigin as fallback */ ++ *alias = var_myorigin; ++ } ++ } ++ ++ return (1); ++} ++ ++/* qmgr_deliver_do_srs - compute srs address if necessary */ ++ ++static int qmgr_deliver_do_srs(QMGR_MESSAGE *message, RECIPIENT_LIST list, VSTRING **encoded) ++{ ++ RESOLVE_REPLY reply; ++ char *alias; ++ int state; ++ ++ resolve_clnt_init(&reply); ++ state = qmgr_deliver_check_srs(message, list, &alias, &reply); ++ resolve_clnt_free(&reply); ++ if (state < 0) { ++ msg_warn("srs lookup problem"); ++ return (-1); ++ } else if (state == 0) { ++ return (0); ++ } ++ ++ state = postfix_srs_forward(message->sender, alias, encoded); ++ if (state < 0) ++ return (-1); ++ ++ return (1); ++} ++#endif ++ + /* qmgr_deliver_send_request - send delivery request to delivery process */ + + static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) +@@ -140,6 +208,9 @@ + MSG_STATS stats; + char *sender; + int flags; ++#ifdef HAS_SRS ++ int srs_state; ++#endif + + /* + * If variable envelope return path is requested, change prefix+@origin +@@ -147,7 +218,19 @@ + * recipient per delivery. + */ + if (message->verp_delims == 0) { +- sender = message->sender; ++#ifdef HAS_SRS ++ srs_state = qmgr_deliver_do_srs(message, list, &sender_buf); ++ if (srs_state < 0) { ++ return (-1); ++ } else if (srs_state == 1) { ++ sender = vstring_str(sender_buf); ++ msg_info("%s: srs_from=<%s>", message->queue_id, sender); ++ } else { ++ sender = message->sender; ++ } ++#else ++ sender = message->sender; ++#endif + } else { + sender_buf = vstring_alloc(100); + verp_sender(sender_buf, message->verp_delims, +diff -urN src/smtpd/smtpd_check.c.orig src/smtpd/smtpd_check.c +--- src/smtpd/smtpd_check.c.orig 2012-02-21 14:21:34.000000000 +0100 ++++ src/smtpd/smtpd_check.c 2012-02-21 14:22:05.000000000 +0100 +@@ -929,6 +929,19 @@ + reject_server_error(state); + } + ++#ifdef HAS_SRS ++/* check_mail_addr_srs - check if address is a valid srs address */ ++ ++static int check_mail_addr_srs(SMTPD_STATE *state, const char *reply_name, const char *addr) ++{ ++ int result; ++ ++ if ((result = postfix_srs_reverse(addr, 0)) < 0) ++ reject_dict_retry(state, reply_name); ++ return (result); ++} ++#endif ++ + /* reject_unknown_reverse_name - fail if reverse client hostname is unknown */ + + static int reject_unknown_reverse_name(SMTPD_STATE *state) +@@ -4552,6 +4565,13 @@ + || MATCH(canonical_maps, CONST_STR(reply->recipient)) + || MATCH(virt_alias_maps, CONST_STR(reply->recipient))) + return (0); ++ ++#ifdef HAS_SRS ++ /* allow valid srs address */ ++ if ((reply->flags & RESOLVE_CLASS_FINAL) ++ && check_mail_addr_srs(state, recipient, CONST_STR(reply->recipient)) == 1) ++ return (0); ++#endif + + /* + * At this point, anything that resolves to the error mailer is known to diff -r 43d642154330 -r 7a7cc794483b postfix/postfix.spec --- a/postfix/postfix.spec Wed Sep 12 19:10:15 2012 +0200 +++ b/postfix/postfix.spec Thu Sep 13 20:05:49 2012 +0200 @@ -48,6 +48,7 @@ %option with_pgsql no %option with_ldap no %option with_whoson no +%option with_spfsrs no %option with_fdsetsize no # list of sources @@ -59,6 +60,7 @@ Patch0: postfix.patch Patch1: postfix.patch.pfls Patch2: http://download.openpkg.org/components/versioned/postfix/postfix-%{V_whoson}-whoson.patch +Patch3: postfix-srs.patch # build information BuildPreReq: OpenPKG, openpkg >= 20100101, perl, gcc @@ -97,6 +99,10 @@ BuildPreReq: whoson PreReq: whoson %endif +%if "%{with_spfsrs}" == "yes" +BuildPreReq: libsrs2 +PreReq: libsrs2 +%endif Provides: MTA Conflicts: exim, sendmail, ssmtp @@ -117,6 +123,7 @@ o Optional PostgreSQL dictionary support (see package options) o Optional OpenLDAP dictionary support (see package options) o Optional WHOSON dictionary support (see package options) + o Optional SPF SRS protection support (see package options) %track prog postfix = { @@ -134,6 +141,11 @@ url = http://download.openpkg.org/components/versioned/postfix/ regex = postfix-(__VER__)-whoson.patch } + prog postfix:spfsrs = { + version = %{V_spfsrs} + url = http://www.codefrickler.de/srs/ + regex = postfix-srs-(__VER__).patch + } %prep # unpack distribution files @@ -149,6 +161,11 @@ %patch -p0 -P 2 %endif + # apply vendor SPF SRS patch +%if "%{with_spfsrs}" == "yes" + %patch -p0 -P 3 +%endif + # remove OpenPKG privelege model incompatible exit conditions %{l_shtool} subst \ -e 's;msg_fatal\(.*attribute specifies mail system\);msg_info\1;g' \ @@ -229,6 +246,10 @@ AUXLIBS="$AUXLIBS %{l_fsl_ldflags} %{l_fsl_libs}" CCARGS="$CCARGS -DUSE_SOFTLIMITONLY" %endif +%if "%{with_spfsrs}" == "yes" + CCARGS="$CCARGS -DHAS_SRS" + AUXLIBS="$AUXLIBS -lsrs2" +%endif %if "%{with_fdsetsize}" != "no" %if "%{with_fdsetsize}" == "yes" CCARGS="$CCARGS -DFD_SETSIZE=1024" diff -r 43d642154330 -r 7a7cc794483b postfix/postfix.txt --- a/postfix/postfix.txt Wed Sep 12 19:10:15 2012 +0200 +++ b/postfix/postfix.txt Thu Sep 13 20:05:49 2012 +0200 @@ -25,6 +25,8 @@ T_CLIENTS = clients T_SENDERS = senders T_CLICRT = clicrt +T_RECIPIENT = recipient +T_HELO = helo # dependency tracking TIMESTAMP = .up-to-date @@ -43,7 +45,9 @@ $(T_ALIASES).db \ $(T_CLIENTS).db \ $(T_SENDERS).db \ - $(T_CLICRT).db + $(T_CLICRT).db \ + $(T_RECIPIENT).db \ + $(T_HELO).db # default target all: $(TABLES) $(TIMESTAMP) @@ -79,6 +83,10 @@ $(POSTMAP) hash:$(T_SENDERS) $(T_CLICRT).db: $(T_CLICRT) $(MAKEFILE) $(POSTMAP) hash:$(T_CLICRT) +$(T_RECIPIENT).db: $(T_RECIPIENT) $(MAKEFILE) + $(POSTMAP) hash:$(T_RECIPIENT) +$(T_HELO).db: $(T_HELO) $(MAKEFILE) + $(POSTMAP) hash:$(T_HELO) # cleanup target clean: @@ -440,3 +448,59 @@ # | 18:81:F5:22:18:BA:EB:15:FF:40:30:00:EA:C0:B4:2E:EC:AE:86:8E user2 + +## +## @l_prefix@/etc/postfix/recipient -- control for relaying recipients +## +## Searched for RCPT TO address, domain, parent domains, or localpart@ +## and rejects the request if the result is REJECT or "[45]XX text" or +## permits the request if the result is OK or RELAY or all-numerical. +## + +# Syntax (see access(5)): +# | user@domain action +# | domain action +# | user@ action +# | net.work.addr.ess action +# | net.work.addr action +# | net.work action +# | net action +# where "action" is one of: +# "[45]NN text", "REJECT", "OK", "restriction..." +# +# Examples: +# | mail.example.com OK +# | example.com REJECT +# | 192.168.0.1 OK +# | 192.168 REJECT +# | postmaster@ OK + + + +## +## @l_prefix@/etc/postfix/helo -- control for relaying helo transmissions +## +## Searched for HELO or EHLO hostname or parent domains and rejects the +## request if the result is REJECT or "[45]XX text" or permits the request +## if the result is OK or RELAY or all-numerical. +## + +# Syntax (see access(5)): +# | user@domain action +# | domain action +# | user@ action +# | net.work.addr.ess action +# | net.work.addr action +# | net.work action +# | net action +# where "action" is one of: +# "[45]NN text", "REJECT", "OK", "restriction..." +# +# Examples: +# | mail.example.com OK +# | example.com REJECT +# | 192.168.0.1 OK +# | 192.168 REJECT +# | postmaster@ OK + +