WASD Hypertext Services - Technical Overview
11 - Conditional Configuration
11.1 - Conditional Keywords
11.2 - Examples
[next] [previous] [contents] [full-page]
Mapping (HTTPD$MAP) and authorization (HTTPD$AUTH) rules may be
conditionally applied depending on request, server or other charactersistics.
These include
- server host name, port
- client IP address and host name
- browser-accepted content-types, character sets, languages, encodings
- browser identification string
- scheme ("http:" or "https:", i.e. is it a secure request?)
- HTTP method (GET, POST, etc.)
- request path, query string, cookie data, refering page
- virtual host:port specified in request header
- system information (hardware, Alpha/VAX, node name, VMS version, etc.)
- system time
- random number generation
Conditionals may be nested up to a maximum depth of eight, are not case
sensitive and generally match via string comparison (with asterisk and
percentage wildcards), although IP addresses will accept a network mask.
Conditional and rule text may be indented for clarifying structure. They may
be used in the following formats.
if (condition) then apply rest of line
if (condition)
then apply one
or more rules
up until the corresponding ...
endif
if (condition)
then apply one
or more rules
else
apply one or more other rules
up until the corresponding ...
endif
if (condition)
then apply one
or more rules
elif (condition)
apply one or more other rules
in a sort or case statement
else
a possible default rule or rules
up until the delimiting
endif
Logical operators are also supported, in conjunction with precedence
ordering parentheses, allowing moderately complex compound expressions to be
applied in conditionals.
- ! logical negation
- && logical AND
- || logical OR
There are two more conditional structures that allow previous decisions to
be reused. These are unif and the ifif. The first
unconditionally includes rules regardless of the current state of execution.
The second resumes execution only if the previous if or
elif expression was true. The else statement may also
be used after an unif to continue only if the previous expression
was false. The purpose of these constructs are to allow a single decision
statement to include both conditional and unconditional rules.
if (condition)
then apply one
or more rules
unif
apply this block of rules
unconditionally
ifif
applied only if the original
if expression was evaulated as true
unif
apply another block of rules
unconditionally
else
and this block of rules
only if the original if was false
endif
Conditional syntax is checked a rule load time (either server startup or
reload). Basic errors such as unknown keywords and unbalanced parantheses or
structure statements will be detected and reported to the corresponding Admin
Menu report and to the server process log.
CAUTION
Unless these reports are checked after modifying rule sets syntax errors may
result in unexpected mappings or access.
11.1 - Conditional Keywords
The following keywords provide a match between the corresponding request or
other value and a string immediately following the delimiting colon. White
space or other reserved characters may not be included unless preceded by a
backslash. The actual value being used in the conditional matching may be
observed using the mapping item of the WATCH facility
(18 - WATCH Facility).
- accept:
Browser-accepted content types as listed in the "Accept:" request
header field. Same string as provided in CGI variable HTTP_ACCEPT.
- accept-charset:
Browser-accepted character sets as listed in the "Accept-Charset:"
request header field. CGI variable HTTP_ACCEPT_CHARSET.
- accept-encoding:
Browser-accepted content encoding as listed in the
"Accept-Encoding:" request header field. CGI variable
HTTP_ACCEPT_ENCODING.
- accept-language:
Browser language preferences as listed in the
"Accept-Language:" request header field. CGI variable
HTTP_ACCEPT_LANGUAGE.
- authorization:
The raw authorization string from the request header, if any supplied.
This could be simply used to test whether it has been supplied or not.
- cluster_member:
If the supplied node name is (perhaps currently) a member of the cluster (if
any) the server may be executing on.
- command_line:
The command line qualifiers and parameters used when the server image was
activated.
- cookie:
Raw cookie data as the text string provided in "Cookie:" request
header field. CGI variable HTTP_COOKIE.
- decnet:
Whether DECnet is active on the system and which version is available.
This value will be 0 if not active, 4 if PhaseIV or 5 is PhaseV.
- forwarded:
Proxy/gateway host(s) request forwarded by, as specified in request header
field "Forwarded:". CGI variable HTTP_FORWARDED.
- host:
The host (and optionally port) specified in request header "Host:"
field. This is used by all modern browsers to provide virtual host information
to the server. CGI variable HTTP_HOST.
- jpi_username:
The account username the server is executing as.
- mapped_path:
The path resulting from mapping (phase 2 if script path involved) from which
the path-translated is derived.
- ods:
Specified as 2 or 5 (Extended File System), or as SRI file name encoding
(MultiNet NFS and others) PWK encoding (PATHWORKS 4/5), ADS encoding
(Advanced Server / PATHWORKS 6), SMB encoding (Samba - same as ADS).
- path-info:
Path specified in the request line. CGI variable PATH_INFO.
- path-translated:
VMS translation of path-info. Available after rule mapping (i.e. during
authorization rule processing).
- query-string:
Query string specified in request line. Same information as provided in
CGI variable QUERY_STRING.
- rand:
Value from a random number generator. See
Rand: Keyword.
- redirected:
If a request has been internally redirected (i.e. not back to the browser) this
conditional will be non-zero. Can be used as a boolean or with a digit
specified.
- referer:
URL of refering page as provided in "Referer:" request header field.
CGI variable HTTP_REFERER.
- remote-addr:
Client IP address. Same as provided as CGI variable REMOTE_ADDR. As
with all IP addresses used for conditional testing this may be wildcard string
match or network mask expressed as address/mask-length
(see Host Addresses).
- remote-host:
Client host name if name resolution enabled, otherwise the IP address (same
as remote-addr).
CGI variable REMOTE_HOST.
- request-method:
HTTP method ("GET", "POST", etc.) specified in the request
line. CGI variable REQUEST_METHOD.
- request-scheme:
Request protocol as "http:" or "https:". CGI variable
REQUEST_SCHEME.
- script-name:
After the first pass of rule mapping (script component resolution), or during
authorization processing, any script component of the request URI.
- server-addr:
The service IP address. CGI variable SERVER_ADDR.
This may be wildcard string match or network mask expressed as
address/mask-length.
- server-name:
The (possibly virtual) server name. This may or may not exactly match any
string provided via the host keyword. CGI variable SERVER_NAME.
- server-port:
The (possibly virtual) server port number. CGI variable SERVER_PORT.
- server-software:
The server identification string, including the version. For example
"HTTPd-WASD/8.0.0 OpenVMS/AXP SSL". CGI variable SERVER_SOFTWARE.
- service:
This is the composite server name plus port as
server-name:port.
- ssl:
Simple boolean value. If request is via Secure Sockets Layer then this
will be true.
- syi_arch_name:
System information; CPU architecture of the server system, "Alpha"
or "VAX".
- syi_hw_name:
System information; hardware identification string, for example
"AlphaStation 400 4/233".
- syi_nodename:
System information; the node name, for example "KLAATU".
- syi_version:
System information; VMS version string, for example "V7.3".
- tcpip:
A string derived from the UCX$IPC_SHR shareable image.
It looks something like this "Compaq TCPIP$IPC_SHR V5.1-15
(11-JAN-2001 02:28:33.95)" and comprises the agent (Compaq, MultiNet, TCPware,
unknown), the name of the image, the version and finally the link date.
- time:
Compare to current system time. See Time: Keyword.
- trnlnm:
Translate a logical name. See Trnlnm: Keyword.
- user-agent:
Browser identification string as provided in "User-Agent:" request
header field. CGI variable HTTP_USER_AGENT.
- x-forwarded-for:
Proxied client name or address as provided in "X-Forwarded-For:" request
header field. CGI variable HTTP_X_FORWARDED_FOR.
Rand: Keyword
At the commencement of each pass a new pseudo-random number is generated
(and therefore remains constant during that pass). The rand:
conditional is intended to allow some sort of distribution to be built into a
set of rules, where each pass (request) generates a different one. The random
conditional accepts two parameters, a modulas number, which is used
to modulas the base number, and a comparison number, which is
compared to the modulas result.
Hence the following conditional rules
if (rand:3:0)
do this
elif (rand:3:1)
do this
else
do this
endif
would pseudo-randomly generate base numbers of 0, 1, 2 and perform the
appropriate conditional block. Over a sufficient number of usages this should
produce a relatively even distribution of numbers. If the modulas is specified
as less than two (i.e. no distribution factor at all) it defaults to 2 (i.e. a
distribution of 50%). Hence the following example should be the equivalent of
a coin toss.
if (rand:)
heads
else
tails
endif
Time: Keyword
The time: conditional allows server behaviour to change
according to the time of day, week, or even year. It compares the supplied
parameter to the current system time in one of three ways.
- The supplied parameter is in the form "1200-1759", which should
be read as "twelve noon to five fifty-nine PM" (i.e. as a time range in
minutes, generalized as hhmm-hhmm), where the first is the start
time and the second the end time. If the current time is within that range
(inclusive) the conditional returns true, otherwise false. If the range
doesn't look correct false is always returned.
if (time:0000-0000)
it's midnight
elif (time:0001-1159)
it's AM
elif (time:1200-1200)
it's noon
else
it's PM
endif
- If the supplied parameter is a single digit it is compared to the VMS day
of the week (1-Monday, 2-Tuesday ... 7-Sunday).
if (time:6 || time:7)
it's the weekend
else
it's the working week
endif
- If the supplied string is not in either of the formats described above it
is treated as a string match with a VMS comparision time (i.e.
yyyy-mm-dd hh-mm-ss.hh).
if (time:%%%%-05-*)
it's the month of May
endif
Trnlnm: Keyword
The trnlnm: conditional dynamically translates a logical name
and uses the value. One mandatory and up to two optional parameters may be
supplied.
trnlnm:logical-name[;name-table][:string-to-match]
The logical-name must be supplied; without it false is always
returned. If just the logical-name is supplied the conditional
returns true if the name exists or false if it does not. The default
name-table is LNM$FILE_DEV. When the optional
name-table is supplied the lookup is confined to that table. If
the optional string-to-match is supplied it is matched against the
value of the logical and the result returned.
Host Addresses
Host names or addresses can be an alpha-numeric string (if DNS lookup is
enabled) or dotted-decimal network address, a slash, then a dotted-decimal
mask. For example "131.185.250.0/255.255.255.192". This has a 6 bit
subnet. It operates by bitwise-ANDing the client host address with the mask,
bitwise-ANDing the network address supplied with the mask, then comparing the
two results for equality. Using the above example the host 131.185.250.250
would be accepted, but 131.185.250.50 would be rejected. Equivalent notation
for this rule would be "131.185.250.0/26".
11.2 - Examples
The following provides a collection of examples of conditional mapping and
authorization rules illustrating the use of wildcard matching, network mask
matching and the various formats in which the rules may be blocked.
- This first example shows an EXEC mapping rule being applied to a path if
the request query string contains the string "example".
if (query-string:*example*) exec /* /cgi-bin/example/*
- In this example a block of mapping statements is processed if the virtual
service of the request matches that in the conditional, otherwise the block is
skipped. Note the indentation to help clarify the structure.
if (service:the.host.name:80)
pass /web/* /dka0/the_host_name_web/*
pass /graphics/* /dka100/graphics/*
pass * "404 Resource not found."
endif
- This example a series of tests allow a form of case processing where the
first to match will be processed and terminate the matching process. In this
case if a match does not occur rule processing continues after the
endif.
if (service:the.host.name:80)
pass /web/* /dka0/the_host_name_web/*
elif (service:next.host.name:80)
pass /web/* /dka0/next_host_name_web/*
elif (service:another.host.name:80)
pass /web/* /dka0/another_host_name_web/*
endif
pass /graphics/* /dka100/graphics/*
pass * "404 Resource not found."
- In this (somewhat contrived) example a nested test is used to check
(virtual) server name and that the request is being handled via Secure Sockets
Layer (SSL) for security. If it is not an informative message is supplied.
The else and the quotes are not really required but included here
for illustration.
if (server-name:the.host.name)
if (scheme:"https")
pass /secure/* /dka0/the_host_name_web/secure/*
else
pass * /dka0/the_host_name_web/secure/only-via-SSL.html
endif
endif
- This would be another way to accomplish a similar objective to example 4.
This uses a negation operator to exclude access to successive
mappings if not requesting via SSL.
if (server-name:the.host.name)
if (!SSL:)
pass * /web/secure/only-via-SSL.html
endif
pass /secure/* /web/secure/*
pass /other/* /web/other/*
pass /web/* /web/web/*
pass * "404 Resource not found."
endif
- This example shows the use of a compound conditional using the AND and OR
operators. It also illustrates the use of a network mask. It will exclude all
access to the specified path unless the request is originating from
within a specified network (perhaps an intranet) or via SSL.
if (path:/sensitive/* && !(remote-addr:131.185.250.0/24 || SSL:))
pass * 404 "Access denied (SSL only)."
endif
- This example illustrates restricting authentication to SSL.
[[*]]
["Your VMS password"=VMS]
if (!request-scheme:https)
* r+w,#0
endif
- Logical name translation may be used to dynamically alter the flow of rule
interpretation.
if (trnlnm:HTTPD_EXAMPLE)
pass /* /example/*
else
pass /* /*
endif
[next] [previous] [contents] [full-page]