/*++
/* NAME
/* rewrite 3
/* SUMMARY
/* mail address rewriter
/* SYNOPSIS
/* #include "trivial-rewrite.h"
/*
/* void rewrite_init(void)
/*
/* void rewrite_proto(stream)
/* VSTREAM *stream;
/*
/* void rewrite_addr(context, addr, result)
/* RWR_CONTEXT *context;
/* char *addr;
/* VSTRING *result;
/*
/* void rewrite_tree(context, tree)
/* RWR_CONTEXT *context;
/* TOK822 *tree;
/*
/* RWR_CONTEXT local_context;
/* RWR_CONTEXT remote_context;
/* DESCRIPTION
/* This module implements the trivial address rewriting engine.
/*
/* rewrite_init() initializes data structures that are private
/* to this module. It should be called once before using the
/* actual rewriting routines.
/*
/* rewrite_proto() implements the client-server protocol: read
/* one rule set name and one address in external (quoted) form,
/* reply with the rewritten address in external form.
/*
/* rewrite_addr() rewrites an address string to another string.
/* Both input and output are in external (quoted) form.
/*
/* rewrite_tree() rewrites a parse tree with a single address to
/* another tree. A tree is a dummy node on top of a token list.
/*
/* local_context and remote_context provide domain names for
/* completing incomplete address forms.
/* STANDARDS
/* DIAGNOSTICS
/* Problems and transactions are logged to \fBsyslogd\fR(8)
/* or \fBpostlogd\fR(8).
/* BUGS
/* SEE ALSO
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System library. */
#include <sys_defs.h>
#include <stdlib.h>
#include <string.h>
#ifdef STRCASECMP_IN_STRINGS_H
#include <strings.h>
#endif
/* Utility library. */
#include <msg.h>
#include <vstring.h>
#include <vstream.h>
#include <vstring_vstream.h>
#include <split_at.h>
/* Global library. */
#include <mail_params.h>
#include <mail_proto.h>
#include <resolve_local.h>
#include <tok822.h>
#include <mail_conf.h>
/* Application-specific. */
#include "trivial-rewrite.h"
RWR_CONTEXT local_context = {
VAR_MYORIGIN, &var_myorigin,
VAR_MYDOMAIN, &var_mydomain,
};
RWR_CONTEXT remote_context = {
VAR_REM_RWR_DOMAIN, &var_remote_rwr_domain,
VAR_REM_RWR_DOMAIN, &var_remote_rwr_domain,
};
static VSTRING *ruleset;
static VSTRING *address;
static VSTRING *result;
/* rewrite_tree - rewrite address according to rule set */
void rewrite_tree(RWR_CONTEXT *context, TOK822 *tree)
{
TOK822 *colon;
TOK822 *domain;
TOK822 *bang;
TOK822 *local;
VSTRING *vstringval;
/*
* XXX If you change this module , quote_822_local . c , or tok822_parse . c ,
* be sure to re - run the tests under " make rewrite_clnt_test " and " make
* resolve_clnt_test " in the global directory .
*/
/*
* Sanity check .
*/
if (tree->head == 0 )
msg_panic("rewrite_tree: empty tree" );
/*
* An empty address is a special case .
*/
if (tree->head == tree->tail
&& tree->tail->type == TOK822_QSTRING
&& VSTRING_LEN(tree->tail->vstr) == 0 )
return ;
/*
* Treat a lone @ as if it were an empty address .
*/
if (tree->head == tree->tail
&& tree->tail->type == '@' ) {
tok822_free_tree(tok822_sub_keep_before(tree, tree->tail));
tok822_sub_append(tree, tok822_alloc(TOK822_QSTRING, "" ));
return ;
}
/*
* Strip source route .
*/
if (tree->head->type == '@'
&& (colon = tok822_find_type(tree->head, ':' )) != 0
&& colon != tree->tail)
tok822_free_tree(tok822_sub_keep_after(tree, colon));
/*
* Optionally , transform address forms without @ .
*/
if ((domain = tok822_rfind_type(tree->tail, '@' )) == 0 ) {
/*
* Swap domain ! user to user @ domain .
*/
if (var_swap_bangpath != 0
&& (bang = tok822_find_type(tree->head, '!' )) != 0 ) {
tok822_sub_keep_before(tree, bang);
local = tok822_cut_after(bang);
tok822_free(bang);
tok822_sub_prepend(tree, tok822_alloc('@' , (char *) 0 ));
if (local)
tok822_sub_prepend(tree, local);
}
/*
* Promote user % domain to user @ domain .
*/
else if (var_percent_hack != 0
&& (domain = tok822_rfind_type(tree->tail, '%' )) != 0 ) {
domain->type = '@' ;
}
/*
* Append missing @ origin
*/
else if (var_append_at_myorigin != 0
&& REW_PARAM_VALUE(context->origin) != 0
&& REW_PARAM_VALUE(context->origin)[0 ] != 0 ) {
domain = tok822_sub_append(tree, tok822_alloc('@' , (char *) 0 ));
tok822_sub_append(tree, tok822_scan(REW_PARAM_VALUE(context->origin),
(TOK822 **) 0 ));
}
}
/*
* Append missing . domain , but leave broken forms ending in @ alone . This
* merely makes diagnostics more accurate by leaving bogus addresses
* alone .
*
* Backwards - compatibility warning : warn for " user @ localhost " when there is
* no " localhost " in mydestination or in any other address class with an
* explicit domain list .
*/
if (var_append_dot_mydomain != 0
&& REW_PARAM_VALUE(context->domain) != 0
&& REW_PARAM_VALUE(context->domain)[0 ] != 0
&& (domain = tok822_rfind_type(tree->tail, '@' )) != 0
&& domain != tree->tail
&& tok822_find_type(domain, TOK822_DOMLIT) == 0
&& tok822_find_type(domain, '.' ) == 0 ) {
if (warn_compat_break_app_dot_mydomain
&& (vstringval = domain->next->vstr) != 0 ) {
if (strcasecmp(vstring_str(vstringval), "localhost" ) != 0 ) {
msg_info("using backwards-compatible default setting "
VAR_APP_DOT_MYDOMAIN "=yes to rewrite \" %s\" to "
"\" %s.%s\"" , vstring_str(vstringval),
vstring_str(vstringval), var_mydomain);
} else if (resolve_class("localhost" ) == RESOLVE_CLASS_DEFAULT) {
msg_info("using backwards-compatible default setting "
VAR_APP_DOT_MYDOMAIN "=yes to rewrite \" %s\" to "
"\" %s.%s\"; please add \" localhost\" to "
"mydestination or other address class" ,
vstring_str(vstringval), vstring_str(vstringval),
var_mydomain);
}
}
tok822_sub_append(tree, tok822_alloc('.' , (char *) 0 ));
tok822_sub_append(tree, tok822_scan(REW_PARAM_VALUE(context->domain),
(TOK822 **) 0 ));
}
/*
* Strip trailing dot at end of domain , but not dot - dot or @ - dot . This
* merely makes diagnostics more accurate by leaving bogus addresses
* alone .
*/
if (tree->tail->type == '.'
&& tree->tail->prev
&& tree->tail->prev->type != '.'
&& tree->tail->prev->type != '@' )
tok822_free_tree(tok822_sub_keep_before(tree, tree->tail));
}
/* rewrite_proto - read request and send reply */
int rewrite_proto(VSTREAM *stream)
{
RWR_CONTEXT *context;
TOK822 *tree;
if (attr_scan(stream, ATTR_FLAG_STRICT,
RECV_ATTR_STR(MAIL_ATTR_RULE, ruleset),
RECV_ATTR_STR(MAIL_ATTR_ADDR, address),
ATTR_TYPE_END) != 2 )
return (-1 );
if (strcmp(vstring_str(ruleset), MAIL_ATTR_RWR_LOCAL) == 0 )
context = &local_context;
else if (strcmp(vstring_str(ruleset), MAIL_ATTR_RWR_REMOTE) == 0 )
context = &remote_context;
else {
msg_warn("unknown context: %s" , vstring_str(ruleset));
return (-1 );
}
/*
* Sanity check . An address is supposed to be in externalized form .
*/
if (*vstring_str(address) == 0 ) {
msg_warn("rewrite_addr: null address" );
vstring_strcpy(result, vstring_str(address));
}
/*
* Convert the address from externalized ( quoted ) form to token list ,
* rewrite it , and convert back .
*/
else {
tree = tok822_scan_addr(vstring_str(address));
rewrite_tree(context, tree);
tok822_externalize(result, tree, TOK822_STR_DEFL);
tok822_free_tree(tree);
}
if (msg_verbose)
msg_info("`%s' `%s' -> `%s'" , vstring_str(ruleset),
vstring_str(address), vstring_str(result));
attr_print(stream, ATTR_FLAG_NONE,
SEND_ATTR_INT(MAIL_ATTR_FLAGS, server_flags),
SEND_ATTR_STR(MAIL_ATTR_ADDR, vstring_str(result)),
ATTR_TYPE_END);
if (vstream_fflush(stream) != 0 ) {
msg_warn("write rewrite reply: %m" );
return (-1 );
}
return (0 );
}
/* rewrite_init - module initializations */
void rewrite_init(void )
{
ruleset = vstring_alloc(100 );
address = vstring_alloc(100 );
result = vstring_alloc(100 );
}
Messung V0.5 in Prozent C=82 H=94 G=88
¤ Dauer der Verarbeitung: 0.1 Sekunden
(vorverarbeitet am 2026-08-08)
¤
*© Formatika GbR, Deutschland