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