Home | History | Annotate | Line # | Download | only in smtp
      1 /*	$NetBSD: smtp_unalias.c,v 1.2 2025/02/25 19:15:49 christos 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