In uc_clickandbuy.module there is the following check:

if (substr($_SERVER["REMOTE_ADDR"], 0, 11) != "217.22.128.") {
    $error = t('Invalid EMS PUSH remote IP @ip.', array('@ip' => $_SERVER["REMOTE_ADDR"]));
}
else ...

My reversed proxy (running apache2.2 that needs slowloris protection) receives the soap request from clickandbuy and sends it to apache which errors because the REMOTE_ADDR header == 127.0.0.1.

The check should also be on the headers: HTTP_CLIENT_IP and HTTP_X_FORWARDED_FOR. Read all about it!

So im suggesting this code:

function getClassCIp($ip) {
    return substr($ip, 0, 11)
}

function checkIp($clickAndBuyIp) {
    if (!empty($_SERVER['HTTP_CLIENT_IP']) && 
            getClassCIp($_SERVER['HTTP_CLIENT_IP']) == $clickAndBuyIp)   //check ip from share internet
    {
      return true;
    }
    elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR']) &&
            getClassCIp($_SERVER['HTTP_X_FORWARDED_FOR'])  == $clickAndBuyIp)   //to check if  is passed from proxy
    {
        return true;
    }
    else
    {
      return getClassCIp($_SERVER['REMOTE_ADDR']) == $clickAndBuyIp;
    }
}
else ...

ps. first issue post here, so excuse me for booboos

Comments

slickrik’s picture

Actually, use this... nice and generic... php 4 && 5 proof, nothing deprecated. No magic numbers like substr($ip,0,11)

        //args: ip-address, start class, class length.
        //start class=0 and class length=3 means Class C ip-address check
        //start class=0 and class length=4 means Class D ip-address check (no start && length defaults to class D ip check)
        //echo "82.136.251.333 = ".(checkIpsFor("82.136.251.333", 0, 3) ? "true" : "false");
        //echo "82.136.251.333 = ".(checkIpsFor("82.136.251.333") ? "true" : "false");

        function getClassCIp($ip, $ipClassStart, $ipClassLength) {
                $ipArray = explode(".", $ip);
                $ip = implode(".", array_slice($ipArray, $ipClassStart, $ipClassLength));
                //echo $ip."<br/>";
                return $ip;
        }

        function checkIpFor($ip, $remoteIp, $ipClassStart, $ipClassLength) {
                $isIpEqual = getClassCIp($ip, $ipClassStart, $ipClassLength) == 
                                getClassCIp($remoteIp, $ipClassStart, $ipClassLength);
                //echo "Ips are ". ($isIpEqual ? "equal" : "not equal") . "<br/>";
                return $isIpEqual;
        }

        function checkIpsFor($remoteIp, $ipClassStart=0, $ipClassLength=4) {
                $headers = array("HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR", "REMOTE_ADDR");
                foreach($headers as $header) {
                        //echo "Checking $header<br/>";
                        if(!empty($_SERVER[$header]) && 
                                        checkIpFor($_SERVER[$header], $remoteIp, $ipClassStart, $ipClassLength))
                                return true;
                }
                return false;
        }

greets Rik

longwave’s picture

Status: Needs review » Needs work

The problem with simply checking HTTP_X_FORWARDED_FOR is that it can easily be spoofed; any client can send this header and pretend to be forwarding for someone else.

Drupal 6 works around this in the ip_address() function, which this module uses in the 6.x releases. Drupal 5 does not appear to support reverse proxies and apparently has other similar issues, see #142773: Drupal does not fully work when using a reverse proxy for details. I'm tempted to mark this as "won't fix" unless someone can find evidence that Drupal 5 was actually designed to support reverse proxies without patching.

longwave’s picture

Status: Needs work » Closed (won't fix)