Forum Discussion

mtobkes_108891's avatar
mtobkes_108891
Icon for Nimbostratus rankNimbostratus
Apr 13, 2011

Error with or operator

Hi,

 

 

I'm having issues with this iRule when trying to match multiple strings using the or operator. Oddly enough I don't get the error in line 2 but I do in line 4. Can you please tell me how I can accomplish this?

 

 

 

when HTTP_REQUEST {

 

if { ([string tolower [HTTP::uri]] contains "font") && ([string tolower [HTTP::uri]] ends_with ".eot" || ".ttf") } {

 

log local0. "uri matches font and allowed extensions"

 

if { [string tolower [HTTP::header "Referer"]] contains ".abc.com" || ".xyz.com" || ""} {

 

set referer { [HTTP::header "Referer"] }

 

log local0. "referer variable set to $referer"

 

}

 

else { HTTP::respond 403 content "403 - Forbidden"

 

log local0. "403 sent to client" }

 

}

 

}

 

 

 

 

Log messages:

 

 

Wed Apr 13 15:08:13 EDT 2011 tmm2 tmm2[4964] 01220001 TCL error: font_resource_restriction_403 HTTP_REQUEST - cant use non-numeric string as operand of || while executing if { [string tolower [HTTP::header Referer]] contains .abc.com or .xyz.com } { set referer { [HTTP::header Referer] } log loc...

 

 

Wed Apr 13 15:08:13 EDT 2011 tmm2 tmm2[4964] Rule font_resource_restriction_403 HTTP_REQUEST: uri matches font and allowed extensions

 

 

 

Thanks,

 

-Myles
  • It's because of the empty string at the end of the "if" expression. You can try to use some other function for checking empty string.
  • Hi Myles,

     

     

    You need to perform the full check against the URI as string tolower doesn't accept multiple strings.

     

     

    if { ([string tolower [HTTP::uri]] contains "font") && ([string tolower [HTTP::uri]] ends_with ".eot" || ".ttf") } {

     

     

    ->

     

     

    if { ([string tolower [HTTP::uri]] contains "font") && ([string tolower [HTTP::uri]] ends_with ".eot" || [string tolower [HTTP::uri]] ends_with ".ttf") } {

     

     

    If you're doing this many checks on the URI, you should save the lowercase value in a variable:

     

     

    set uri [string tolower [HTTP::uri]]

     

    if { ( $uri contains "font") && ($uri ends_with ".eot" || $uri ends_with ".ttf") } {

     

     

    Aaron
  • Also note that the Referer header (and any other HTTP header) can easily be spoofed. So I wouldn't recommend allowing access to sensitive resources based on that.

     

     

    http://en.wikipedia.org/wiki/Referrer_spoofing

     

     

    Aaron
  • Thanks all!

     

     

    Here is my updated iRule:

     

     

    when HTTP_REQUEST {

     

    set uri [string tolower [HTTP::uri]]

     

    if { ($uri contains "font") && ($uri ends_with ".eot" || $uri ends_with ".ttf" || $uri ends_with ".svg" || $uri ends_with ".woff") } {

     

    log local0. "uri matches font and allowed extensions"

     

    set headerstr [string tolower [HTTP::header "Referer"]]

     

    if { $headerstr contains ".abc.com" || $headerstr contains ".xyz.com" || $headerstr contains ""} {

     

    set referer { [HTTP::header "Referer"] }

     

    log local0. "referer variable set to $referer"

     

    set origin { [HTTP::header "Origin"] }

     

    log local0. "origin variable set to $origin"

     

    } else { HTTP::respond 403 content "403 - Forbidden"

     

    log local0. "403 sent to client"

     

    }

     

    }

     

    }

     

    when HTTP_RESPONSE {

     

    if { [$origin exists] } {

     

    HTTP::header insert Access-Control-Allow-Origin [$origin]

     

    }

     

    }

     

     

     

    If not the referer, what other option is there since referer is easily spoofed? I am using the origin header in my responses but it is not always present in requests.

     

     

     

    Thanks again for all your help!

     

     

     

    Myles

     

  • Hi Myles,

     

     

    Does a legitimate client need to authenticate with the application in order to access these URIs? If so, you could look for a successful authentication and use the applications session cookie (or generate your own in the iRule) as a way to restrict access. If the application doesn't require a login, then what's the logic for who you want to allow and who you want to block?

     

     

    Also, your HTTP_RESPONSE code doesn't look valid. $origin exists isn't a valid iRule command. So I expect that would generate a runtime TCL error. And inserting an HTTP header in a response won't change the client's behavior. ie, it would trigger the client to include that header in a subsequent request. If you want to do something like that you could set a cookie in the response using HTTP::cookie insert.

     

     

    Aaron