Issues

ZF-6676: Zend_Validate_Hostname attempts to validate non ip addresses as ip addresses

Description

Zend_Validate_Hostname ALWAYS checks to see if the value is a valid ip address - even if it's a hostname like "localhost". I think there should be a regex check to see if the value matches an ip address format. I'm sure I'm not considering all possibilities like IPv6 and my regex coule be more specific, but here's what I did to get it to work.

/* original code

class Zend_Validate_Hostname extends Zend_Validate_Abstract { // ... public function isValid() { // ...

    // Check input against IP address schema
    if ($this->_ipValidator->setTranslator($this->getTranslator())->isValid($valueString)) {
        if (!($this->_allow & self::ALLOW_IP)) {
            $this->_error(self::IP_ADDRESS_NOT_ALLOWED);
            return false;
        } else{
            return true;
        }
    }

    //...
  }
  //...

} */

// new code

class Zend_Validate_Hostname extends Zend_Validate_Abstract { // ... public function isValid() { // ...

    // Added this check to avoid validating hostnames as ip addresses. Otherwise, the inet_pton() call times out
    if (preg_match('%^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$%', $valueString)) {

        // Moved this check before checking if ip is valid. Why would you care if the ip was valid if you weren't allowing ips anyways?
        if (!($this->_allow & self::ALLOW_IP)) {
            $this->_error(self::IP_ADDRESS_NOT_ALLOWED);
            return false;
        }

        // Check input against IP address schema
        if ($this->_ipValidator->setTranslator($this->getTranslator())->isValid($valueString)) {
            return true;
        }
    }

    //...
  }
//...

}

This was causing form submission on any page that validated an email address to timeout. This is using the default email address validator. It was also causing another issue - attempting to send any email would give the message "inet_pton() [function.inet-pton]: Unrecognized address "localhost". inet_pton() should not be called on a string like "localhost". Nor should that string be validated as an ip address

Comments

Generic: Why should we erase the support for IPV6 ? And why should we duplicate IP validation when there is already a IP validator available ?

Reason: Actually IP checks are done by the IP validator. As the validation for hostnames also involves the validation for IP adresses we must do it. Otherwise, when you give a IP adress as hostname, which is allowed but does not conform RFC, the validation would return false .

Actually inet_pton does not thrown an error by itself. I expect that you are using a own error-handler, disabling php's error supression, and connecting this to Zend_Mail to get an email for each thrown error.

Note that this does not have to do anything with "localhost", but with using a own error-handler which does not take into account php's settings.

Actually there is no way to get rid of the error-supression as this would eigther mean to disable IP checking, disable IPV6 support or adding a userland slow IPV6 converter.

I didn't state anything about getting rid of IPv6 support. I just didn't implement it in my regex cause I didn't need it and I didn't want to spend the time on it. The eventual implementation would check for either IPv4 or IPv6.

I understand the reasoning for needing to validate ips in Zend_Validate_Hostname. However, if it's not in an ip address format, why would we continue to validate it? Especially if it's something we need to use error suppression for or that can cause timeouts (I was getting consistent timeouts from the validation of the ip address)

I'm not really concerned with the fact the inet_pton() throws an error and the fact that I'm using my own error handler. In my opinion, it shouldn't get to the point where it's even attempting to validate it since it's not an ip address at all.

But to know if it's an IP-adress format we have to call Zend_Validate_Ip, which you said should not be done.

What do you mean with "continue to validate it" ? We first check for IP adress by calling Zend_Validate_IP... If it's not valid we continue to check according to RFC. When we don't continue to validate we could not check for hostname.

I can also not reproduce your timeout problem by ip validation. IP validation calls ip2long and reverse for IPv4 check, and inet_pton and reverse for IPv6 check. All 4 used methods do not call any system calls and have no delay in time as they are simple string changing methods.

Where you will have timeouts is by enabling MX check for email checks. This is a online check, which is per default disabled. But this has nothing to do with hostname or ip adresses.

I think this is just confusion caused by a slightly misleading use of Zend_Validate_Ip. In this case, it's not being used to validate an ip address, but to test if a string IS an ip address in the first place.

By the same logic, you wouldn't use Zend_Validate_EmailAddress to test whether or not a string was an email address. The name implies, this is an email address, is it a valid one?

Anyways, not sure what could be done about that. I'll just run some more tests and see if I can figure out more specifically where the timeout was coming from.

Changed from bug to improvement, as IP adresses have been checked since this class was released (about 1,5 years) and this change introduces a change in behaviour.

Fixed with r15596