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 
smtp_unalias_name(const char * name)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 
smtp_unalias_addr(VSTRING * result,const char * addr)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 
main(int unused_argc,char ** unused_argv)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