1/*++ 2/* NAME 3/* smtp_unalias 3 4/* SUMMARY 5/* replace host/domain alias by official name 6/* SYNOPSIS 7/* #include "smtp.h" 8/* 9/* const char *smtp_unalias_name(name) 10/* const char *name; 11/* 12/* VSTRING *smtp_unalias_addr(result, addr) 13/* VSTRING *result; 14/* const char *addr; 15/* DESCRIPTION 16/* smtp_unalias_name() looks up A or MX records for the specified 17/* name and returns the official name provided in the reply. When 18/* no A or MX record is found, the result is a copy of the input. 19/* In order to improve performance, smtp_unalias_name() remembers 20/* results in a private cache, so a name is looked up only once. 21/* 22/* smtp_unalias_addr() returns the input address, which is in 23/* RFC 821 quoted form, after replacing the domain part by the 24/* official name as found by smtp_unalias_name(). When the input 25/* contains no domain part, the result is a copy of the input. 26/* LICENSE 27/* .ad 28/* .fi 29/* The Secure Mailer license must be distributed with this software. 30/* AUTHOR(S) 31/* Wietse Venema 32/* IBM T.J. Watson Research 33/* P.O. Box 704 34/* Yorktown Heights, NY 10598, USA 35/*--*/ 36 37/* System library. */ 38 39#include <sys_defs.h> 40#include <sys/socket.h> 41#include <netinet/in.h> 42#include <arpa/inet.h> 43#include <stdlib.h> 44#include <netdb.h> 45#include <string.h> 46 47/* Utility library. */ 48 49#include <htable.h> 50#include <vstring.h> 51#include <msg.h> 52 53/* DNS library. */ 54 55#include <dns.h> 56 57/* Application-specific. */ 58 59#include "smtp.h" 60 61static int smtp_unalias_flags; 62 63/* smtp_unalias_name - look up the official host or domain name. */ 64 65const char *smtp_unalias_name(const char *name) 66{ 67 static HTABLE *cache; 68 VSTRING *fqdn; 69 char *result; 70 71 if (*name == '[') 72 return (name); 73 74 /* 75 * Initialize the cache on the fly. The smtp client is designed to exit 76 * after servicing a limited number of requests, so there is no need to 77 * prevent the cache from growing too large, or to expire old entries. 78 */ 79 if (cache == 0) 80 cache = htable_create(10); 81 82 /* 83 * Look up the fqdn. If none is found use the query name instead, so that 84 * we won't lose time looking up the same bad name again. 85 */ 86 if ((result = htable_find(cache, name)) == 0) { 87 fqdn = vstring_alloc(10); 88 if (dns_lookup_l(name, smtp_unalias_flags, (DNS_RR **) 0, fqdn, 89 (VSTRING *) 0, DNS_REQ_FLAG_NONE, T_MX, T_A, 90#ifdef HAS_IPV6 91 T_AAAA, 92#endif 93 0) != DNS_OK) 94 vstring_strcpy(fqdn, name); 95 htable_enter(cache, name, result = vstring_export(fqdn)); 96 } 97 return (result); 98} 99 100/* smtp_unalias_addr - rewrite aliases in domain part of address */ 101 102VSTRING *smtp_unalias_addr(VSTRING *result, const char *addr) 103{ 104 char *at; 105 const char *fqdn; 106 107 if ((at = strrchr(addr, '@')) == 0 || at[1] == 0) { 108 vstring_strcpy(result, addr); 109 } else { 110 fqdn = smtp_unalias_name(at + 1); 111 vstring_strncpy(result, addr, at - addr + 1); 112 vstring_strcat(result, fqdn); 113 } 114 return (result); 115} 116 117#ifdef TEST 118 119 /* 120 * Test program - read address from stdin, print result on stdout. 121 */ 122 123#include <vstring_vstream.h> 124 125int main(int unused_argc, char **unused_argv) 126{ 127 VSTRING *addr = vstring_alloc(10); 128 VSTRING *result = vstring_alloc(10); 129 130 smtp_unalias_flags |= RES_DEBUG; 131 132 while (vstring_fgets_nonl(addr, VSTREAM_IN)) { 133 smtp_unalias_addr(result, vstring_str(addr)); 134 vstream_printf("%s -> %s\n", vstring_str(addr), vstring_str(result)); 135 vstream_fflush(VSTREAM_OUT); 136 } 137 vstring_free(addr); 138 vstring_free(result); 139 return (0); 140} 141 142#endif 143