/*++ /* 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 #include #include #include #include #include #include /* Utility library. */ #include #include #include /* DNS library. */ #include /* 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 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