postfix/postfix-srs.patch

Mon, 28 Jan 2013 17:37:18 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 28 Jan 2013 17:37:18 +0100
changeset 758
a2c6460cfb16
permissions
-rw-r--r--

Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.

     1 diff -urN README_FILES/SRS_README.orig README_FILES/SRS_README
     2 --- README_FILES/SRS_README.orig	1970-01-01 01:00:00.000000000 +0100
     3 +++ README_FILES/SRS_README	2012-02-21 14:22:05.000000000 +0100
     4 @@ -0,0 +1,56 @@
     5 +
     6 +CREDITS:
     7 +
     8 +- originally written by Shevek <srs@anarres.org>
     9 +- fixes and porting to postfix 2.1 by Branko F. Gracnar <bfg@frost.ath.cx>
    10 +- redesigned and ported to debian postfix 2.7.0 by Chris <chris@codefrickler.de>
    11 +
    12 +SYNOPSIS:
    13 +Works with all address classes (not limited to local domain).
    14 +Doesn't depend on .forward-files or alias_maps.
    15 +SMTPD accepts valid srs addresses without further configuration.
    16 +Sender gets rewritten only when necessary:
    17 +- rewrite after queuing (after separation to on- and off-site destinations)
    18 +- rewrite only if sender and recipient are off-site and host is not a relay for recipient
    19 +Alias domain can be chosen automatically from original on-site-recipient.
    20 +
    21 +
    22 +USAGE:
    23 +
    24 +1) Apply the patch.
    25 +
    26 +2) Create makefiles with
    27 +
    28 +make makefiles CCARGS="-DHAS_SRS -I<directory-containing--srs2.h>" AUXLIBS="-L<directory-containing--libsrs2.so> -lsrs2"
    29 +
    30 +
    31 +3) Build.
    32 +
    33 +4) Add the following global configuration variables to main.cf:
    34 +All variables are optional, except where stated:
    35 +
    36 +	srs_domain               (string)
    37 +		A domain to use in rewritten addresses. This must point only
    38 +		to machines which know the encoding secret used by this
    39 +		system. It defaults to $myorigin. If set to the emtpy
    40 +		string, use domain from original recipient if host is final
    41 +		destination, otherwise use $myorigin.
    42 +	srs_hashlength           (int)
    43 +		The hash length to generate in a rewritten address.
    44 +	srs_hashmin              (int)
    45 +		The hash length to require when checking an address.
    46 +	srs_maxage               (int)
    47 +		The maximum permitted age of a rewritten address.
    48 +	srs_secrets              (string)
    49 +		[required] A list of secrets with which to generate
    50 +		and check addresses.
    51 +	srs_separator            (string)
    52 +		The separator to appear immediately after SRS[01] in
    53 +		rewritten addresses.
    54 +
    55 +
    56 +See http://www.libsrs2.org/ for more information about the meaning
    57 +of these variables. They are standard across MTAs.
    58 +
    59 +5) Fire up and enjoy.
    60 +
    61 diff -urN src/cleanup/cleanup_addr.c.orig src/cleanup/cleanup_addr.c
    62 --- src/cleanup/cleanup_addr.c.orig	2012-02-21 14:21:34.000000000 +0100
    63 +++ src/cleanup/cleanup_addr.c	2012-02-21 14:22:05.000000000 +0100
    64 @@ -163,6 +163,10 @@
    65  {
    66      VSTRING *clean_addr = vstring_alloc(100);
    67      const char *bcc;
    68 +#ifdef HAS_SRS
    69 +    int srs_state;
    70 +    VSTRING *srs_rcpt;
    71 +#endif
    73      /*
    74       * Note: an unqualified envelope address is for all practical purposes
    75 @@ -174,6 +178,14 @@
    76      cleanup_rewrite_internal(MAIL_ATTR_RWR_LOCAL,
    77  			     clean_addr, *buf ? buf : var_empty_addr);
    78      if (state->flags & CLEANUP_FLAG_MAP_OK) {
    79 +#ifdef HAS_SRS	
    80 +	if ((srs_state = postfix_srs_reverse(STR(clean_addr), &srs_rcpt)) < 0) {
    81 +            /* XXX errors */
    82 +        } else if (srs_state == 1) {
    83 +            vstring_free(clean_addr);
    84 +            clean_addr = srs_rcpt;
    85 +        }
    86 +#endif
    87  	if (cleanup_rcpt_canon_maps
    88  	    && (cleanup_rcpt_canon_flags & CLEANUP_CANON_FLAG_ENV_RCPT))
    89  	    cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
    90 diff -urN src/global/mail_params.c.orig src/global/mail_params.c
    91 --- src/global/mail_params.c.orig	2012-02-21 14:21:34.000000000 +0100
    92 +++ src/global/mail_params.c	2012-02-21 14:22:05.000000000 +0100
    93 @@ -308,6 +308,15 @@
    94  bool    var_long_queue_ids;
    95  bool    var_daemon_open_fatal;
    97 +#ifdef HAS_SRS
    98 +int     var_srs_hashlength;
    99 +int     var_srs_hashmin;
   100 +int     var_srs_maxage;
   101 +char    *var_srs_secrets;
   102 +char    *var_srs_separator;
   103 +char    *var_srs_domain;
   104 +#endif
   105 +
   106  const char null_format_string[1] = "";
   108  /* check_myhostname - lookup hostname and validate */
   109 @@ -579,6 +588,11 @@
   110  	VAR_INT_FILT_CLASSES, DEF_INT_FILT_CLASSES, &var_int_filt_classes, 0, 0,
   111  	/* multi_instance_wrapper may have dependencies but not dependents. */
   112  	VAR_MULTI_WRAPPER, DEF_MULTI_WRAPPER, &var_multi_wrapper, 0, 0,
   113 +#ifdef HAS_SRS
   114 +	VAR_SRS_SECRETS, DEF_SRS_SECRETS, &var_srs_secrets, 0, 0,
   115 +	VAR_SRS_SEPARATOR, DEF_SRS_SEPARATOR, &var_srs_separator, 1, 1,
   116 +	VAR_SRS_DOMAIN, DEF_SRS_DOMAIN, &var_srs_domain, 0, 0,
   117 +#endif
   118  	0,
   119      };
   120      static const CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
   121 @@ -602,6 +616,11 @@
   122  	VAR_MIME_BOUND_LEN, DEF_MIME_BOUND_LEN, &var_mime_bound_len, 1, 0,
   123  	VAR_DELAY_MAX_RES, DEF_DELAY_MAX_RES, &var_delay_max_res, MIN_DELAY_MAX_RES, MAX_DELAY_MAX_RES,
   124  	VAR_INET_WINDOW, DEF_INET_WINDOW, &var_inet_windowsize, 0, 0,
   125 +#ifdef HAS_SRS
   126 +	VAR_SRS_HASHLENGTH, DEF_SRS_HASHLENGTH, &var_srs_hashlength, 1, 20,
   127 +	VAR_SRS_HASHMIN, DEF_SRS_HASHMIN, &var_srs_hashmin, 1, 20,
   128 +	VAR_SRS_MAXAGE, DEF_SRS_MAXAGE, &var_srs_maxage, 1, 0,
   129 +#endif
   130  	0,
   131      };
   132      static const CONFIG_LONG_TABLE long_defaults[] = {
   133 diff -urN src/global/mail_params.h.orig src/global/mail_params.h
   134 --- src/global/mail_params.h.orig	2012-02-21 14:21:34.000000000 +0100
   135 +++ src/global/mail_params.h	2012-02-21 14:22:41.000000000 +0100
   136 @@ -1981,6 +1981,35 @@
   137  #define DEF_ALLOW_UNTRUST_ROUTE	0
   138  extern bool var_allow_untrust_route;
   140 +/**
   141 + * SRS. Shevek <srs@anarres.org>, updated by Chris <chris@codefrickler.de>
   142 + */
   143 +#ifdef HAS_SRS
   144 +#define VAR_SRS_HASHLENGTH		"srs_hashlength"
   145 +#define DEF_SRS_HASHLENGTH		4
   146 +extern int var_srs_hashlength;
   147 +
   148 +#define VAR_SRS_HASHMIN			"srs_hashmin"
   149 +#define DEF_SRS_HASHMIN			4
   150 +extern int var_srs_hashmin;
   151 +
   152 +#define VAR_SRS_MAXAGE			"srs_maxage"
   153 +#define DEF_SRS_MAXAGE			21
   154 +extern int var_srs_maxage;
   155 +
   156 +#define VAR_SRS_SECRETS			"srs_secrets"
   157 +#define DEF_SRS_SECRETS			""
   158 +extern char *var_srs_secrets;
   159 +
   160 +#define VAR_SRS_DOMAIN			"srs_domain"
   161 +#define DEF_SRS_DOMAIN			"$myorigin"
   162 +extern char *var_srs_domain;
   163 +
   164 +#define VAR_SRS_SEPARATOR		"srs_separator"
   165 +#define DEF_SRS_SEPARATOR		"="
   166 +extern char *var_srs_separator;
   167 +#endif
   168 +
   169   /*
   170    * Names of specific restrictions, and the corresponding configuration
   171    * parameters that control the status codes sent in response to rejected
   172 diff -urN src/global/Makefile.in.orig src/global/Makefile.in
   173 --- src/global/Makefile.in.orig	2012-02-21 14:21:34.000000000 +0100
   174 +++ src/global/Makefile.in	2012-02-21 14:22:05.000000000 +0100
   175 @@ -29,7 +29,7 @@
   176  	user_acl.c valid_mailhost_addr.c verify.c verify_clnt.c \
   177  	verp_sender.c wildcard_inet_addr.c xtext.c delivered_hdr.c \
   178  	fold_addr.c header_body_checks.c mkmap_proxy.c data_redirect.c \
   179 -	match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \
   180 +	match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c srs.c \
   181  	smtp_reply_footer.c safe_ultostr.c verify_sender_addr.c \
   182  	dict_memcache.c mail_version.c memcache_proto.c server_acl.c \
   183  	mkmap_fail.c
   184 @@ -63,7 +63,7 @@
   185  	user_acl.o valid_mailhost_addr.o verify.o verify_clnt.o \
   186  	verp_sender.o wildcard_inet_addr.o xtext.o delivered_hdr.o \
   187  	fold_addr.o header_body_checks.o mkmap_proxy.o data_redirect.o \
   188 -	match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \
   189 +	match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o srs.o \
   190  	smtp_reply_footer.o safe_ultostr.o verify_sender_addr.o \
   191  	dict_memcache.o mail_version.o memcache_proto.o server_acl.o \
   192  	mkmap_fail.o
   193 diff -urN src/global/srs.c.orig src/global/srs.c
   194 --- src/global/srs.c.orig	1970-01-01 01:00:00.000000000 +0100
   195 +++ src/global/srs.c	2012-02-21 14:22:27.000000000 +0100
   196 @@ -0,0 +1,144 @@
   197 +/*++
   198 +/* NAME
   199 +/*	srs 3
   200 +/* SUMMARY
   201 +/*	Sender Rewriting Scheme
   202 +/* SYNOPSIS
   203 +/*	void	postfix_srs_reverse(rcpt, decoded)
   204 +/*	const char *rcpt
   205 +/*	VSTRING **decoded
   206 +/*
   207 +/*	int postfix_srs_forward(sender, alias, encoded)
   208 +/*	const char *sender
   209 +/*	const char *alias
   210 +/*	VSTRING **decoded
   211 +/* DESCRIPTION
   212 +/*	This module rewrites addresses according to the Sender Rewriting
   213 +/*  Scheme, documented at http://www.libsrs2.org/.
   214 +/*
   215 +/*	srs_reverse() reverse-rewrites the rewritten form of an address
   216 +/*
   217 +/*	srs_forward() rewrites the envelope sender using alias domain
   218 +/*
   219 +/* DIAGNOSTICS
   220 +/* LICENSE
   221 +/* .ad
   222 +/* .fi
   223 +/*	The Secure Mailer license must be distributed with this software.
   224 +/* AUTHOR(S)
   225 +/*	Shevek <srs@anarres.org>
   226 +/*	Chris <chris@codefrickler.de>
   227 +/*--*/
   228 +
   229 +#ifdef HAS_SRS
   230 +
   231 +/* System library. */
   232 +
   233 +#include <stdlib.h>
   234 +#include <sys_defs.h>
   235 +#include <string.h>
   236 +
   237 +#include <srs2.h>
   238 +
   239 +/* Utility library. */
   240 +
   241 +#include <msg.h>
   242 +#include <vstring.h>
   243 +#include <mymalloc.h>
   244 +#include <stringops.h>
   245 +
   246 +/* Global library. */
   247 +
   248 +#include <mail_params.h>
   249 +
   250 +#define SRS_FAIL_UNLESS(x) do {	int __ret = (x); if (__ret != SRS_SUCCESS) msg_fatal("SRS configuration error: %s", srs_strerror(__ret)); } while(0)
   251 +
   252 +/* my function declarations */
   253 +int postfix_srs_forward (const char *sender, const char *alias, VSTRING **encoded);
   254 +int postfix_srs_reverse (const char *rcpt, VSTRING **decoded);
   255 +
   256 +static srs_t *srs;
   257 +
   258 +static void postfix_srs_init (void) {
   259 +	char *saved_secrets;
   260 +	char *secret;
   261 +	char *ptr;
   262 +
   263 +	if (srs == NULL) {
   264 +		/* XXX Can't use memory functions from postfix because of inconsistensies in libsrs2
   265 +		srs_set_malloc((srs_malloc_t)mymalloc, (srs_realloc_t)myrealloc, (srs_free_t)myfree);
   266 +		*/
   267 +
   268 +		srs = srs_new();
   269 +		/* avoid sender-domain-check, since we have already done this ourselves */
   270 +		SRS_FAIL_UNLESS(srs_set_alwaysrewrite(srs, 1));
   271 +		SRS_FAIL_UNLESS(srs_set_hashlength(srs, var_srs_hashlength));
   272 +		SRS_FAIL_UNLESS(srs_set_hashmin(srs, var_srs_hashmin));
   273 +		SRS_FAIL_UNLESS(srs_set_maxage(srs, var_srs_maxage));
   274 +		SRS_FAIL_UNLESS(srs_set_separator(srs, var_srs_separator[0]));
   275 +		
   276 +		ptr = saved_secrets = mystrdup(var_srs_secrets);
   277 +		while ((secret = mystrtok(&ptr, ", \t\r\n")) != 0) {
   278 +			SRS_FAIL_UNLESS(srs_add_secret(srs, secret));
   279 +		}
   280 +		myfree(saved_secrets);
   281 +	}
   282 +}
   283 +
   284 +int postfix_srs_reverse(const char *rcpt, VSTRING **decoded) {
   285 +	char *out;
   286 +	int ret;
   287 +
   288 +	if (!SRS_IS_SRS_ADDRESS(rcpt))
   289 +		return (0);
   290 +
   291 +	postfix_srs_init();
   292 +
   293 +	ret = srs_reverse_alloc(srs, &out, rcpt);
   294 +
   295 +	if (ret != SRS_SUCCESS) {
   296 +		switch (SRS_ERROR_TYPE(ret)) {
   297 +			case SRS_ERRTYPE_CONFIG:
   298 +				msg_fatal("SRS configuration error: %s", srs_strerror(ret));
   299 +				return (-1);
   300 +			case SRS_ERRTYPE_INPUT:
   301 +				msg_fatal("SRS reverse failed for <%s>: %s", rcpt, srs_strerror(ret));
   302 +				return (-1);
   303 +			case SRS_ERRTYPE_SYNTAX:
   304 +			case SRS_ERRTYPE_SRS:
   305 +				msg_warn("SRS reverse failed for <%s>: %s", rcpt, srs_strerror(ret));
   306 +				break;
   307 +		}
   308 +		return (0);
   309 +	}
   310 +
   311 +	if (decoded) {
   312 +		*decoded = vstring_alloc(100);
   313 +		vstring_strcpy(*decoded, out);
   314 +	}
   315 +	free(out);
   316 +
   317 +	return (1);
   318 +}
   319 +
   320 +int postfix_srs_forward(const char *sender, const char *alias, VSTRING **encoded) {
   321 +	char *out;
   322 +	int  ret;
   323 +
   324 +	postfix_srs_init();
   325 +
   326 +	ret = srs_forward_alloc(srs, &out, sender, alias);
   327 +	
   328 +	if (ret != SRS_SUCCESS) {
   329 +		msg_warn("SRS forward failed for <%s>: %s", sender, srs_strerror(ret));
   330 +		return (0);
   331 +	}
   332 +	
   333 +	*encoded = vstring_alloc(100);
   334 +	vstring_strcpy(*encoded, out);
   335 +	free(out);
   336 +
   337 +	return (1);
   338 +}
   339 +
   340 +#endif
   341 diff -urN src/qmgr/qmgr_deliver.c.orig src/qmgr/qmgr_deliver.c
   342 --- src/qmgr/qmgr_deliver.c.orig	2012-02-21 14:21:34.000000000 +0100
   343 +++ src/qmgr/qmgr_deliver.c	2012-02-21 14:22:05.000000000 +0100
   344 @@ -76,6 +76,7 @@
   345  #include <dsn_buf.h>
   346  #include <dsb_scan.h>
   347  #include <rcpt_print.h>
   348 +#include <resolve_clnt.h>
   350  /* Application-specific. */
   352 @@ -129,6 +130,73 @@
   353      }
   354  }
   356 +#ifdef HAS_SRS
   357 +/* qmgr_deliver_check_srs - check whether sender should be rewritten */
   358 +
   359 +static int qmgr_deliver_check_srs(QMGR_MESSAGE *message, RECIPIENT_LIST list, char **alias, RESOLVE_REPLY *reply)
   360 +{
   361 +    char *pos;
   362 +
   363 +    /* 
   364 +     * Rewrite if we are not final destination nor relay host for recipient and sender address
   365 +     * it should be enough to look at the first recipient, since transport/nexthop are the same for all recipients
   366 +     */
   367 +    resolve_clnt_query(list.info->address, reply);
   368 +    if (reply->flags & RESOLVE_FLAG_FAIL)
   369 +        return (-1);
   370 +    else if (!(reply->flags & RESOLVE_CLASS_DEFAULT))
   371 +        return (0);
   372 +
   373 +    resolve_clnt_query(message->sender, reply);
   374 +    if (reply->flags & RESOLVE_FLAG_FAIL)
   375 +        return (-1);
   376 +    else if (!(reply->flags & RESOLVE_CLASS_DEFAULT))
   377 +        return (0);
   378 +
   379 +    if (var_srs_domain[0]) {
   380 +        *alias = var_srs_domain;
   381 +    } else {
   382 +        /* retrieve alias domain from original recipient if we are final destination ... */
   383 +        resolve_clnt_query(list.info->orig_addr, reply);
   384 +        if (reply->flags & RESOLVE_FLAG_FAIL)
   385 +            return (-1);
   386 +        if ((reply->flags & RESOLVE_CLASS_FINAL) && (pos = strrchr(list.info->orig_addr, '@'))) {
   387 +            *alias = pos + 1;
   388 +        } else {
   389 +            /* ... or use myorigin as fallback */
   390 +            *alias = var_myorigin;
   391 +        }
   392 +    }
   393 +
   394 +    return (1);
   395 +}
   396 +
   397 +/* qmgr_deliver_do_srs - compute srs address if necessary */
   398 +
   399 +static int qmgr_deliver_do_srs(QMGR_MESSAGE *message, RECIPIENT_LIST list, VSTRING **encoded)
   400 +{
   401 +    RESOLVE_REPLY reply;
   402 +    char *alias;
   403 +    int state;
   404 +
   405 +    resolve_clnt_init(&reply);
   406 +    state = qmgr_deliver_check_srs(message, list, &alias, &reply);
   407 +    resolve_clnt_free(&reply);
   408 +    if (state < 0) {
   409 +        msg_warn("srs lookup problem");
   410 +        return (-1);
   411 +    } else if (state == 0) {
   412 +        return (0);
   413 +    }
   414 +
   415 +    state = postfix_srs_forward(message->sender, alias, encoded);
   416 +    if (state < 0)
   417 +        return (-1);
   418 +
   419 +    return (1);
   420 +}
   421 +#endif
   422 +
   423  /* qmgr_deliver_send_request - send delivery request to delivery process */
   425  static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
   426 @@ -140,6 +208,9 @@
   427      MSG_STATS stats;
   428      char   *sender;
   429      int     flags;
   430 +#ifdef HAS_SRS
   431 +    int srs_state;
   432 +#endif
   434      /*
   435       * If variable envelope return path is requested, change prefix+@origin
   436 @@ -147,7 +218,19 @@
   437       * recipient per delivery.
   438       */
   439      if (message->verp_delims == 0) {
   440 -	sender = message->sender;
   441 +#ifdef HAS_SRS
   442 +        srs_state = qmgr_deliver_do_srs(message, list, &sender_buf);
   443 +        if (srs_state < 0) {
   444 +            return (-1);
   445 +        } else if (srs_state == 1) {
   446 +            sender = vstring_str(sender_buf);
   447 +            msg_info("%s: srs_from=<%s>", message->queue_id, sender);
   448 +        } else {
   449 +            sender = message->sender;
   450 +        }
   451 +#else
   452 +        sender = message->sender;
   453 +#endif
   454      } else {
   455  	sender_buf = vstring_alloc(100);
   456  	verp_sender(sender_buf, message->verp_delims,
   457 diff -urN src/smtpd/smtpd_check.c.orig src/smtpd/smtpd_check.c
   458 --- src/smtpd/smtpd_check.c.orig	2012-02-21 14:21:34.000000000 +0100
   459 +++ src/smtpd/smtpd_check.c	2012-02-21 14:22:05.000000000 +0100
   460 @@ -929,6 +929,19 @@
   461  	reject_server_error(state);
   462  }
   464 +#ifdef HAS_SRS
   465 +/* check_mail_addr_srs - check if address is a valid srs address */
   466 +
   467 +static int check_mail_addr_srs(SMTPD_STATE *state, const char *reply_name, const char *addr)
   468 +{
   469 +    int result;
   470 +
   471 +    if ((result = postfix_srs_reverse(addr, 0)) < 0)
   472 +        reject_dict_retry(state, reply_name);
   473 +    return (result);
   474 +}
   475 +#endif
   476 +
   477  /* reject_unknown_reverse_name - fail if reverse client hostname is unknown */
   479  static int reject_unknown_reverse_name(SMTPD_STATE *state)
   480 @@ -4552,6 +4565,13 @@
   481  	|| MATCH(canonical_maps, CONST_STR(reply->recipient))
   482  	|| MATCH(virt_alias_maps, CONST_STR(reply->recipient)))
   483  	return (0);
   484 +	
   485 +#ifdef HAS_SRS
   486 +    /* allow valid srs address */
   487 +    if ((reply->flags & RESOLVE_CLASS_FINAL)
   488 +        && check_mail_addr_srs(state, recipient, CONST_STR(reply->recipient)) == 1)
   489 +        return (0);
   490 +#endif
   492      /*
   493       * At this point, anything that resolves to the error mailer is known to

mercurial