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 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 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 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