SetEnvIf - set variable based on another variable - apache

So I'm trying to emulate AND with SetEnvIf to block/allow httpd access based on country and city. This is my block in my httpd conf:
SetEnvIf RemoteHost "^" AllowEntry=0
SetEnvIf GEOIP_COUNTRY_CODE US AllowEntry=1
SetEnvIf GEOIP_REGION MA AllowEntry=AllowEntry+1
SetEnvIf AllowEntry 2 AllowEntry2
Order deny,allow
Deny from all
Allow from env=AllowEntry2
But it doesn't work, line 3 will assign the value "AllowEntry+1" to the variable AllowEntry instead of 2.
It doesn't need to be 2 as in the math operation, the string "1+1" would work as well.
Any ideas? Is it possible?
PS: would still like to know if it's possible but for now I solve my requirement with:
SetEnvIfExpr "%{ENV:GEOIP_COUNTRY_CODE} == 'US' && %{ENV:GEOIP_REGION} == 'MA'" AllowEntry

Related

How do I get if directives to read variables from ldap?

I am trying to set an SSO request based on specific variables, in a way that multiple users will have the same account.
For example If their first name is Robert then it would try to login as user robert. etc..
I have apache working in every way except the if statement seems to be seeing the variables as null.
here is what i am trying to do, but the if statement fails.
<Location "/">
AuthType Basic
...other auth ldap stuff
Require ldap-user %{variable-redacted}
RequestHeader set Name %{env:AUTHORIZE_FirstName}s
</Location>
<If "%{env:AUTHORIZE_FirstName} in { 'Robert', 'John', 'Steve' }">
RequestHeader set User "Admin"
</If>
<Else>
RequestHeader set User "User"
</Else>
So far everything works. Except the if statement evaluates false. I tried several methods here and i'm pretty sure it sees the variable as (null)
What really confuses me is if i use this:
<If "%{variableName} != 'John'">
RequestHeader set user %{variableName}s
</If>
it will actually set the request header to the variable information.
So what is happening? Why does the if statement fail, but the variable works in the failed if statement?!?!
UPDATE: I will leave this question open if some one figures it out. But in the mean time, I have found a way. Since RewriteCond and RewriteRule are handled in order, as expected, I created a solution for them.
First it sets a variable to the "least precise" username, and then if there is more details i can keep adding rules. and my final rewritecond will check if they are an admin, and correct the user. Then finally sets the requestheader based on the user variable. Once a requestheader is set, it needs to be removed to replace it. but variables can be changed over and over. - I have to say, after this, apache will not be my choice if i can avoid it.

Multiple words in apache LocationMatch

I need to block URLs that containt specific words which can be everywhere in the URL.
For example: www.mytest.de/main/:aaa or www.mytest.de/:aaa/main
So I need to block all URLs which contain :aaa. The same will be for :bbb and :ccc.
Not all URLs containing ":" should be blocked, only specific ones.
So I added
<LocationMatch ":aaa">
Require env VAR
</LocationMatch>
<LocationMatch ":bbb">
Require env VAR
</LocationMatch>
How is it possible to put this all in one line like:
<LocationMatch ":aaa" ":bbb">
Require env VAR
</LocationMatch>
Thank you

Using two environment variables to block access in Apache .htaccess

I'm using SetEnvIf and Deny to block access to certain countries in my .htaccess.
But I need to exclude certain URLs from this blocking, and thus I'm setting another environment variable for those URLs.
How do I Deny based on a combination of variable 1 and variable 2 ?
SetEnvIf GEOIP_COUNTRY_CODE xx BlockedCountry
SetEnvIf Request_URI "^/important" NeverBlock
In pseudo code I want to do this now:
Deny from env=BlockedCountry && !NeverBlock
From Apache documentation :
Syntax: Deny from all|host|env=[!]env-variable
[host|env=[!]env-variable] ...
Which means you can combine conditions one after the other (there is no "boolean" operators in between).
So in your case, it should look like this
Deny from env=BlockedCountry env=!NeverBlock
Update
From what you said, it looks like this implies an OR condition instead of an AND (what you want). To do so, you can use this workaround
SetEnvIf GEOIP_COUNTRY_CODE xx MustBeBlocked
SetEnvIf Request_URI "^/important" !MustBeBlocked
Deny from env=MustBeBlocked
With this technique, you set/unset the environment variable depending on the case, which simulates an AND condition.

Use mod_macro with environment variable

Is it possible to use a macro with the value of a environment variable?
E.g.
<Macro setLog $name>
CustomLog "|cronolog -l /var/www/logs/$name/access.log /var/www/logs/$name/%Y-%m-%d_access.log" logging
ErrorLog "|cronolog -l /var/www/logs/$name/error.log /var/www/logs/$name/%Y-%m-%d_error.log"
</Macro>
SetEnvIf Host soup* path=soup
use setLog path
Which would 'print' the macro with path. Can I use the value for path? (in this case soup)
No, the internal variables modified by SetEnv and SetEnvIf are during request processing. Your macros are expanded when the configuration is parsed -- the logs are also opened up front and can't depend on parameters of the request.

Exclude one folder in htaccess protected directory

I have a directory protected by htaccess. Here is the code I use now:
AuthName "Test Area"
Require valid-user
AuthUserFile "/***/.htpasswd"
AuthType basic
This is working fine. However, I now have a directory inside of this folder that I would like to allow anyone to access, but am not sure how to do it.
I know that it is possible to just move the files outside of the protected directory, but to make a long story short the folder needs to stay inside the protected folder, but be accessible to all.
How can I restrict access to the folder, but allow access to the subfolder?
Just create an .htaccess file in the subdirectory with the content:
Satisfy any
According to this article you can accomplish this by using SetEnvIf. You match each of the folders and files you want to grand access to and define an environment variable 'allow' for them. Then you add a condition that allows access if this environment variable is present.
You need to add the following directives to your .htaccess.
SetEnvIf Request_URI "(path/to/directory/)$" allow
SetEnvIf Request_URI "(path/to/file\.php)$" allow
Order allow,deny
Allow from env=allow
Satisfy any
The accepted answer does not seem to run well with new Apache Versions, since it stopped working as soon as Apache Updates were rolled out on some of my customers servers.
I recommend the following approach:
AuthType Basic
AuthName "NO PUBLIC ACCESS"
AuthUserFile /xxx/.htpasswd
SetEnvIf REQUEST_URI "(path/to/directory/)$" ALLOW
<RequireAny>
Require env ALLOW
Require valid-user
</RequireAny>
I don't have enough reputation to add a comment, but two of these answers use the pattern:
SetEnvIf Request_URI "(path/to/directory/)$" allow
to set an environment variable and then check to see if it exists. The part in the quotes is a regular expression. This statement is saying that any path that ENDS with "path/to/directory/" matches and should set the variable, such as "administrationpath/to/directory/", but not "path/to/directory/index.html". The "$" matches the end of the string.
A better match would be:
SetEnvIf Request_URI "^/path/to/directory/" allow
This means the URI path must begin with "/path/to/directory/" (the caret matches the start of the string) but can have additional content after the trailing slash. Note that this requires the trailing slash. To make it optional you could add two rules:
SetEnvIf Request_URI "^/path/to/directory$" allow
SetEnvIf Request_URI "^/path/to/directory/" allow
or, with more pattern matching:
SetEnvIf Request_URI "^/path/to/directory(/.*)?$" allow
The parenthesis and question mark make an optional group and ".*" means zero or more characters.
Personally, I'd either use require all granted 1 in the subfolder's .htaccess or:
require expr "%{REQUEST_URI} =~ m|^/path/to/directory(/.*)?$|" 2 in the parent's.
For Apache 2.4, create a .htaccess file with the following content:
Require all granted
Place it in the subdirectory you want to allow access to.
There is no need to create a .htaccess in the subdirectory.
Just create as many variables as you need with SetEnvIf directive, and be sure the file or path name you want to allw/deny is part of the URI regex you pass to SetEnvIf, exactly like #Sumurai8 said, but set the regex to fit your needs, for the URI should start/end/contain a set of characters............