1/* $NetBSD$ */ 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 81const 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 92int 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 137int 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