diff options
Diffstat (limited to '')
-rw-r--r-- | src/smtp/smtp_unalias.c | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/src/smtp/smtp_unalias.c b/src/smtp/smtp_unalias.c new file mode 100644 index 0000000..1c4d34d --- /dev/null +++ b/src/smtp/smtp_unalias.c @@ -0,0 +1,142 @@ +/*++ +/* NAME +/* smtp_unalias 3 +/* SUMMARY +/* replace host/domain alias by official name +/* SYNOPSIS +/* #include "smtp.h" +/* +/* const char *smtp_unalias_name(name) +/* const char *name; +/* +/* VSTRING *smtp_unalias_addr(result, addr) +/* VSTRING *result; +/* const char *addr; +/* DESCRIPTION +/* smtp_unalias_name() looks up A or MX records for the specified +/* name and returns the official name provided in the reply. When +/* no A or MX record is found, the result is a copy of the input. +/* In order to improve performance, smtp_unalias_name() remembers +/* results in a private cache, so a name is looked up only once. +/* +/* smtp_unalias_addr() returns the input address, which is in +/* RFC 821 quoted form, after replacing the domain part by the +/* official name as found by smtp_unalias_name(). When the input +/* contains no domain part, the result is a copy of the input. +/* 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 <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdlib.h> +#include <netdb.h> +#include <string.h> + +/* Utility library. */ + +#include <htable.h> +#include <vstring.h> +#include <msg.h> + +/* DNS library. */ + +#include <dns.h> + +/* Application-specific. */ + +#include "smtp.h" + +static int smtp_unalias_flags; + +/* smtp_unalias_name - look up the official host or domain name. */ + +const char *smtp_unalias_name(const char *name) +{ + static HTABLE *cache; + VSTRING *fqdn; + char *result; + + if (*name == '[') + return (name); + + /* + * Initialize the cache on the fly. The smtp client is designed to exit + * after servicing a limited number of requests, so there is no need to + * prevent the cache from growing too large, or to expire old entries. + */ + if (cache == 0) + cache = htable_create(10); + + /* + * Look up the fqdn. If none is found use the query name instead, so that + * we won't lose time looking up the same bad name again. + */ + if ((result = htable_find(cache, name)) == 0) { + fqdn = vstring_alloc(10); + if (dns_lookup_l(name, smtp_unalias_flags, (DNS_RR **) 0, fqdn, + (VSTRING *) 0, DNS_REQ_FLAG_NONE, T_MX, T_A, +#ifdef HAS_IPV6 + T_AAAA, +#endif + 0) != DNS_OK) + vstring_strcpy(fqdn, name); + htable_enter(cache, name, result = vstring_export(fqdn)); + } + return (result); +} + +/* smtp_unalias_addr - rewrite aliases in domain part of address */ + +VSTRING *smtp_unalias_addr(VSTRING *result, const char *addr) +{ + char *at; + const char *fqdn; + + if ((at = strrchr(addr, '@')) == 0 || at[1] == 0) { + vstring_strcpy(result, addr); + } else { + fqdn = smtp_unalias_name(at + 1); + vstring_strncpy(result, addr, at - addr + 1); + vstring_strcat(result, fqdn); + } + return (result); +} + +#ifdef TEST + + /* + * Test program - read address from stdin, print result on stdout. + */ + +#include <vstring_vstream.h> + +int main(int unused_argc, char **unused_argv) +{ + VSTRING *addr = vstring_alloc(10); + VSTRING *result = vstring_alloc(10); + + smtp_unalias_flags |= RES_DEBUG; + + while (vstring_fgets_nonl(addr, VSTREAM_IN)) { + smtp_unalias_addr(result, vstring_str(addr)); + vstream_printf("%s -> %s\n", vstring_str(addr), vstring_str(result)); + vstream_fflush(VSTREAM_OUT); + } + vstring_free(addr); + vstring_free(result); + return (0); +} + +#endif |