xref: /netbsd-src/external/ibm-public/postfix/dist/src/global/valid_mailhost_addr.c (revision 41fbaed053f8fbfdf9d2a4ee0a7386a3c83f8505)
1 /*	$NetBSD: valid_mailhost_addr.c,v 1.1.1.1 2009/06/23 10:08:47 tron Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	valid_mailhost_addr 3
6 /* SUMMARY
7 /*	mailhost address syntax validation
8 /* SYNOPSIS
9 /*	#include <valid_mailhost_addr.h>
10 /*
11 /*	const char *valid_mailhost_addr(name, gripe)
12 /*	const char *name;
13 /*	int	gripe;
14 /*
15 /*	int	valid_mailhost_literal(addr, gripe)
16 /*	const char *addr;
17 /*	int	gripe;
18 /* DESCRIPTION
19 /*	valid_mailhost_addr() requires that the input is a valid
20 /*	RFC 2821 string representation of an IPv4 or IPv6 network
21 /*	address.  A valid IPv4 address is in dotted quad decimal
22 /*	form.  A valid IPv6 address includes the "IPV6:" prefix as
23 /*	required by RFC 2821, and is in valid hexadecimal form or
24 /*	in valid IPv4-in-IPv6 form.  The result value is the bare
25 /*	address in the input argument (i.e. text after "IPV6:"
26 /*	prefix, if any) in case of success, a null pointer in case
27 /*	of failure.
28 /*
29 /*	valid_mailhost_literal() requires an address enclosed in
30 /*	[].  The result is non-zero in case of success, zero in
31 /*	case of failure.
32 /*
33 /*	These routines operate silently unless the gripe parameter
34 /*	specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE
35 /*	provide suitable constants.
36 /*
37 /*	The IPV6_COL macro defines the "IPv6:" prefix.
38 /* DIAGNOSTICS
39 /*	Warnings are logged with msg_warn().
40 /* SEE ALSO
41 /*	valid_hostname(3)
42 /*	RFC 952, RFC 1123, RFC 1035, RFC 2821
43 /* LICENSE
44 /* .ad
45 /* .fi
46 /*	The Secure Mailer license must be distributed with this software.
47 /* AUTHOR(S)
48 /*	Wietse Venema
49 /*	IBM T.J. Watson Research
50 /*	P.O. Box 704
51 /*	Yorktown Heights, NY 10598, USA
52 /*--*/
53 
54 
55 /* System library. */
56 
57 #include <sys_defs.h>
58 #include <string.h>
59 
60 #ifdef STRCASECMP_IN_STRINGS_H
61 #include <strings.h>
62 #endif
63 
64 /* Utility library. */
65 
66 #include <msg.h>
67 #include <myaddrinfo.h>
68 
69 /* Global library. */
70 
71 #include <valid_mailhost_addr.h>
72 
73 /* Application-specific. */
74 
75 #define IPV6_COL_LEN       (sizeof(IPV6_COL) - 1)
76 #define HAS_IPV6_COL(str)  (strncasecmp((str), IPV6_COL, IPV6_COL_LEN) == 0)
77 #define SKIP_IPV6_COL(str) (HAS_IPV6_COL(str) ? (str) + IPV6_COL_LEN : (str))
78 
79 /* valid_mailhost_addr - validate RFC 2821 numerical address form */
80 
valid_mailhost_addr(const char * addr,int gripe)81 const char *valid_mailhost_addr(const char *addr, int gripe)
82 {
83     const char *bare_addr;
84 
85     bare_addr = SKIP_IPV6_COL(addr);
86     return ((bare_addr != addr ? valid_ipv6_hostaddr : valid_ipv4_hostaddr)
87 	    (bare_addr, gripe) ? bare_addr : 0);
88 }
89 
90 /* valid_mailhost_literal - validate [RFC 2821 numerical address] form */
91 
valid_mailhost_literal(const char * addr,int gripe)92 int     valid_mailhost_literal(const char *addr, int gripe)
93 {
94     const char *myname = "valid_mailhost_literal";
95     MAI_HOSTADDR_STR hostaddr;
96     const char *last;
97     size_t address_bytes;
98 
99     if (*addr != '[') {
100 	if (gripe)
101 	    msg_warn("%s: '[' expected at start: %.100s", myname, addr);
102 	return (0);
103     }
104     if ((last = strchr(addr, ']')) == 0) {
105 	if (gripe)
106 	    msg_warn("%s: ']' expected at end: %.100s", myname, addr);
107 	return (0);
108     }
109     if (last[1]) {
110 	if (gripe)
111 	    msg_warn("%s: unexpected text after ']': %.100s", myname, addr);
112 	return (0);
113     }
114     if ((address_bytes = last - addr - 1) >= sizeof(hostaddr.buf)) {
115 	if (gripe)
116 	    msg_warn("%s: too much text: %.100s", myname, addr);
117 	return (0);
118     }
119     strncpy(hostaddr.buf, addr + 1, address_bytes);
120     hostaddr.buf[address_bytes] = 0;
121     return (valid_mailhost_addr(hostaddr.buf, gripe) != 0);
122 }
123 
124 #ifdef TEST
125 
126  /*
127   * Test program - reads hostnames from stdin, reports invalid hostnames to
128   * stderr.
129   */
130 #include <stdlib.h>
131 
132 #include <vstring.h>
133 #include <vstream.h>
134 #include <vstring_vstream.h>
135 #include <msg_vstream.h>
136 
main(int unused_argc,char ** argv)137 int     main(int unused_argc, char **argv)
138 {
139     VSTRING *buffer = vstring_alloc(1);
140 
141     msg_vstream_init(argv[0], VSTREAM_ERR);
142     msg_verbose = 1;
143 
144     while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
145 	msg_info("testing: \"%s\"", vstring_str(buffer));
146 	if (vstring_str(buffer)[0] == '[')
147 	    valid_mailhost_literal(vstring_str(buffer), DO_GRIPE);
148 	else
149 	    valid_mailhost_addr(vstring_str(buffer), DO_GRIPE);
150     }
151     exit(0);
152 }
153 
154 #endif
155