RFC2616 states the Location value should be a fully qualified URL. Some apps use a local reference (just the URI). I've seen absolute URIs and relative URIs. Here are a few examples of the different forms and how the browser typically handles it:
http://example.com/new_location - browser doesn't do any normalisation of this
/new_location - most browsers assume the same protocol and host, and then append the new URI to form the new request
new_location - most browsers assume the same protocol and host, and then append the new URI portion to the previously requested protocol, host and path to form the new request
If your app uses the fully qualified URL, you would need to parse the URI. You would then need to encrypt it, base64 encode it, URI encode it and finally prepend a forward slash to the new path. Similarly, for an absolute URI, you would need to encrypt it, base64 encode it, URI encode it and then prepend a leading forward slash. For a local URI, you would need to save the requested path, append the new location token, encrypt it, base64 encode it, URI encode it and then prepend a forward slash.
URI encoding is necessary as the base64 encoded value can contain characters outside the normal ASCII set allowed in HTTP headers.
To differentiate between a URI which was encrypted and one that wasn't, I'd suggest inserting some arbitrary characters like enc_. The command would look something like this:
set encrypted_location_path "/enc_[URI::encode [b64encode [AES::encrypt $::my_aes_key $string_to_encrypt]]]"
To decyrpt this on the request, you'd want to first check if the requested path started with /_enc. If not, it wasn't encrypted. You would want to use catch (
Click here) to handle any errors in decoding/decrypting the request.
You would want to strip off the prepended forward slash, URI decode, base64 decode and the decrypt the string.
Before trying to decrypt the path, check if the session cookie has a length and that the path starts with the encrypted string prefix
if {[string length $session_cookie_value] and $path starts_with "/$::encrypted_string_prefix"}{
URI decode the path. Need to take off the leading forward slash and string "enc_" we added in the response.
Use 'catch' to catch any errors that occur when trying to decode the path value.
Save the output to path_uri_decoded.
if {not ([catch {URI::decode [string range [HTTP::path] [expr {$::encrypted_string_prefix_length + 1}] end]} path_uri_decoded]) \
and [string length $path_uri_decoded]}{
Log that the path was URI decoded
if {$::path_encrypt_debug > 2}{log local0. "[IP::client_addr]:[TCP::client_port]: \$path_uri_decoded was set successfully: $path_uri_decoded"}
If you see failures in the decoding and/or decrypting, try logging the values you're setting in the response and comparing them to the value the client sends in the request.
When I did this last, I ended up encrypting the paths (not the full query string) and just parameters that the application set. If you try to encrypt all parameters, you can potentially run into a problem handling the client-set parameters.
Aaron
Aaron