/* * Copyright (c) 2005 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. */ #include "sm/generic.h" SM_RCSID("@(#)$Id: validdomain.c,v 1.5 2006/12/25 20:37:01 ca Exp $") #include "sm/assert.h" #include "sm/error.h" #include "sm/ctype.h" #include "sm/net.h" #include "sm/rfc2821.h" #include "sm/str.h" #include "sm/misc.h" /* ** VALIDDOMAIN -- check whether a domain is syntactically valid ** ** Parameters: ** str -- string that stores domain ** flags -- flags to influence checks ** ** Returns: ** true iff domain is syntactically valid */ bool validdomain(sm_str_P str, uint flags) { uint i, len, beginsub; uchar ch, lastch; if (NULL == str) return false; len = sm_str_getlen(str); if (0 == len) return false; ch = sm_str_rd_elem(str, 0); if (ch == '[') { sm_ret_T ret; char *begin, *end; ipv4_T ipv4; begin = (char *) sm_str_getdata(str); if (NULL == begin) return true; ret = sm_inet_a2ipv4(begin, &end, &ipv4); return sm_is_success(ret); } beginsub = 0; do { /* ** Domain = (sub-domain 1*("." sub-domain)) / address-literal ** sub-domain = Let-dig [Ldh-str] ** Let-dig = ALPHA / DIGIT ** Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig */ ch = sm_str_rd_elem(str, beginsub); if (!ISALNUM(ch)) return false; for (i = beginsub; i < len; ++i) { lastch = ch; ch = sm_str_rd_elem(str, i); if ('.' == ch) { if (!ISALNUM(lastch)) return false; beginsub = i + 1; break; } if (!(ISALNUM(ch) || ch == '-' || (HAS_R2821(flags, R2821__) && ch == '_'))) return false; } SM_ASSERT(i >= len || '.' == ch); if ('.' == ch && beginsub >= len) return !HAS_R2821(flags, R2821_NO_TRLDOT); } while (i < len); if (!ISALNUM(ch)) { if ('.' == ch) return !HAS_R2821(flags, R2821_NO_TRLDOT); return false; } return true; }