summaryrefslogtreecommitdiffstats
path: root/src/smtp/smtp_unalias.c
blob: 1c4d34d9492883a4293a510711d34c919840cba9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/*++
/* 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 <sys_defs.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <netdb.h>
#include <string.h>

/* Utility library. */

#include <htable.h>
#include <vstring.h>
#include <msg.h>

/* DNS library. */

#include <dns.h>

/* 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 <vstring_vstream.h>

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