Hey James - 

Phil committed this for me, so I'll try to answer (and I take responsibility 
for all the dirty hacks in it). I've been sitting on this plugin for probably 
over a year now, telling myself I'll get time to clean it up and make it better 
before I submit it, but just never got around to it, and learned last week 
there was interest in it, so I decided to "let it go" as is... 

> Can you move this to the docs? It would be docs/reference/plugins/url_sig.rst

I'll try to get some better docs in there. Not sure if just moving that README 
is up to the standards... 

> If I'm reading the code right, the error_url key is
>       error_url = STATUS URL
> 
> Is that right?

For error_url in the config file, there's 2 options:

1) you want to send a 403 when the check fails. Just put "error_url=403" here
2) you want to redirect to another url when the check fails. Just put 
"error_url=302 <the other url>" here


> This should be TSConfigDirGet().

You're probably right. I'll change that.

> What's wrong with TSHttpTxnClientAddrGet()?

Nothing. It's my ignorance. I'll change that too.

> You can't sign URLs with query parameters?

Nope. Like I said, it's not perfect, but certainly usable given the known 
restrictions. 

Cheers,
JvD


On Apr 18, 2014, at 2:22 PM, James Peach <jpe...@apache.org> wrote:

> On Apr 18, 2014, at 12:56 PM, sor...@apache.org wrote:
> 
>> Repository: trafficserver
>> Updated Branches:
>> refs/heads/master bcfd36abf -> 88f18501d
>> 
>> 
>> TS-2732: Add url_sig plugin
>> 
>> 
>> Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
>> Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/88f18501
>> Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/88f18501
>> Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/88f18501
>> 
>> Branch: refs/heads/master
>> Commit: 88f18501d110bdff6a7347f307d94eb3629dad79
>> Parents: bcfd36a
>> Author: Phil Sorber <sor...@apache.org>
>> Authored: Fri Apr 18 13:49:12 2014 -0600
>> Committer: Phil Sorber <sor...@apache.org>
>> Committed: Fri Apr 18 13:55:42 2014 -0600
>> 
>> ----------------------------------------------------------------------
>> CHANGES                                    |   2 +
>> NOTICE                                     |   4 +-
>> configure.ac                               |   1 +
>> plugins/experimental/Makefile.am           |   1 +
>> plugins/experimental/url_sig/Makefile.am   |  21 ++
>> plugins/experimental/url_sig/Makefile.tsxs |  26 ++
>> plugins/experimental/url_sig/README        | 183 ++++++++++
>> plugins/experimental/url_sig/genkeys.pl    |  29 ++
>> plugins/experimental/url_sig/sign.pl       | 101 ++++++
>> plugins/experimental/url_sig/url_sig.c     | 456 ++++++++++++++++++++++++
>> plugins/experimental/url_sig/url_sig.h     |  52 +++
>> 11 files changed, 874 insertions(+), 2 deletions(-)
>> ----------------------------------------------------------------------
>> 
>> 
>> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/88f18501/CHANGES
>> ----------------------------------------------------------------------
>> diff --git a/CHANGES b/CHANGES
>> index 49c2227..d30d399 100644
>> --- a/CHANGES
>> +++ b/CHANGES
>> @@ -1,6 +1,8 @@
>>                                                        -*- coding: utf-8 -*-
>> Changes with Apache Traffic Server 5.0.0
>> 
>> +  *) [TS-2732] Add url_sign (Signed URL's) plugin.
>> +
>> *) [TS-2650] Redirect handling enhancements in ATS
>> 
>> *) [TS-1125] POST's with Expect: 100-continue are slowed by delayed 100 
>> response
>> 
>> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/88f18501/NOTICE
>> ----------------------------------------------------------------------
>> diff --git a/NOTICE b/NOTICE
>> index 00196cb..dacd4a7 100644
>> --- a/NOTICE
>> +++ b/NOTICE
>> @@ -54,8 +54,8 @@ Copyright (c) 2013 LinkedIn
>> 
>> ~~~
>> 
>> -remap_stats plugin developed by Comcast.
>> -Copyright (C) 2013 Comcast
>> +remap_stats and url_sig plugins developed by Comcast.
>> +Copyright (C) 2014 Comcast
>> 
>> ~~~
>> 
>> 
>> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/88f18501/configure.ac
>> ----------------------------------------------------------------------
>> diff --git a/configure.ac b/configure.ac
>> index bd3ddcf..7467a2d 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -1946,6 +1946,7 @@ AC_CONFIG_FILES([
>> plugins/experimental/s3_auth/Makefile
>> plugins/experimental/spdy/Makefile
>> plugins/experimental/ts_lua/Makefile
>> +  plugins/experimental/url_sig/Makefile
>> plugins/experimental/xdebug/Makefile
>> proxy/Makefile
>> proxy/api/ts/Makefile
>> 
>> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/88f18501/plugins/experimental/Makefile.am
>> ----------------------------------------------------------------------
>> diff --git a/plugins/experimental/Makefile.am 
>> b/plugins/experimental/Makefile.am
>> index 4b811c1..b8bddce 100644
>> --- a/plugins/experimental/Makefile.am
>> +++ b/plugins/experimental/Makefile.am
>> @@ -34,6 +34,7 @@ SUBDIRS = \
>> s3_auth \
>> spdy \
>> ts_lua \
>> + url_sig \
>> xdebug
>> 
>> endif
>> 
>> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/88f18501/plugins/experimental/url_sig/Makefile.am
>> ----------------------------------------------------------------------
>> diff --git a/plugins/experimental/url_sig/Makefile.am 
>> b/plugins/experimental/url_sig/Makefile.am
>> new file mode 100644
>> index 0000000..a9011ff
>> --- /dev/null
>> +++ b/plugins/experimental/url_sig/Makefile.am
>> @@ -0,0 +1,21 @@
>> +#  Licensed to the Apache Software Foundation (ASF) under one
>> +#  or more contributor license agreements.  See the NOTICE file
>> +#  distributed with this work for additional information
>> +#  regarding copyright ownership.  The ASF licenses this file
>> +#  to you under the Apache License, Version 2.0 (the
>> +#  "License"); you may not use this file except in compliance
>> +#  with the License.  You may obtain a copy of the License at
>> +#
>> +#      http://www.apache.org/licenses/LICENSE-2.0
>> +#
>> +#  Unless required by applicable law or agreed to in writing, software
>> +#  distributed under the License is distributed on an "AS IS" BASIS,
>> +#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> +#  See the License for the specific language governing permissions and
>> +#  limitations under the License.
>> +
>> +include $(top_srcdir)/build/plugins.mk
>> +
>> +pkglib_LTLIBRARIES = url_sig.la
>> +url_sig_la_SOURCES = url_sig.c
>> +url_sig_la_LDFLAGS = $(TS_PLUGIN_LDFLAGS)
>> 
>> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/88f18501/plugins/experimental/url_sig/Makefile.tsxs
>> ----------------------------------------------------------------------
>> diff --git a/plugins/experimental/url_sig/Makefile.tsxs 
>> b/plugins/experimental/url_sig/Makefile.tsxs
>> new file mode 100644
>> index 0000000..e3ee96e
>> --- /dev/null
>> +++ b/plugins/experimental/url_sig/Makefile.tsxs
>> @@ -0,0 +1,26 @@
>> +#  Licensed to the Apache Software Foundation (ASF) under one
>> +#  or more contributor license agreements.  See the NOTICE file
>> +#  distributed with this work for additional information
>> +#  regarding copyright ownership.  The ASF licenses this file
>> +#  to you under the Apache License, Version 2.0 (the
>> +#  "License"); you may not use this file except in compliance
>> +#  with the License.  You may obtain a copy of the License at
>> +#
>> +#      http://www.apache.org/licenses/LICENSE-2.0
>> +#
>> +#  Unless required by applicable law or agreed to in writing, software
>> +#  distributed under the License is distributed on an "AS IS" BASIS,
>> +#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> +#  See the License for the specific language governing permissions and
>> +#  limitations under the License.
>> +
>> +TSXS?=tsxs
>> +
>> +all:        url_sig.c
>> +    $(TSXS) -v -o url_sig.so $?
>> +
>> +install:
>> +    $(TSXS) -i -o url_sig.so
>> +
>> +clean:
>> +    rm -f *.lo *.so
>> 
>> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/88f18501/plugins/experimental/url_sig/README
>> ----------------------------------------------------------------------
>> diff --git a/plugins/experimental/url_sig/README 
>> b/plugins/experimental/url_sig/README
>> new file mode 100644
>> index 0000000..d2a4ce0
>> --- /dev/null
>> +++ b/plugins/experimental/url_sig/README
> 
> Can you move this to the docs? It would be docs/reference/plugins/url_sig.rst
> 
>> @@ -0,0 +1,183 @@
>> +Signed URL plugin
>> +
>> +This ATS plugin checks a signature query string on the URL, and rejects 
>> (HTTP
>> +403), or redirects (HTTP 302) when this check fails. The signature is based 
>> on
>> +a secret (key) that a signing portal and the Traffic Server cache share. The
>> +algorithm for the signature can be MD5 or SHA1. When the check passes, the
>> +query string is stripped, and the request is handled as if there was no 
>> query
>> +string in the first place.
>> +
>> +This plugin comes with 2 example perl scripts. The sign.pl script shows how 
>> to
>> +sign a URL using the different options, this script is just an example, in 
>> any
>> +real usage scenario, the content owner will incorporate this functionality 
>> in
>> +their portal. The genkeys.pl script is a quick hack to generate a config 
>> file
>> +with random keys. Keep your keys to yourself (secret) if you are using this
>> +plugin, and only share them with the content owner.
>> +
>> +Signed URLs do not replace DRM.
>> +
>> +Quick install:
>> +    You can build with ./configure --enable-experimental-plugins or
>> +    with tsxs:
>> +
>> +            Make sure devel packages for traffic-server are installed.
>> +            Make sure that 'tsxs' is in your path.
>> +            Make sure versions of this plugin and ATS are compatible.
>> +
>> +                    make -f Makefile.tsxs
>> +                    make -f Makefile.tsxs install
>> +
>> +    add @plugin=url_sig.so @pparam=<config file> to the remap rule you want
>> +    to be signed
>> +
>> +
>> +Edge cache debugging
>> +    To enable the TSDebug verbose logging, change records.config to have:
>> +
>> +            CONFIG proxy.config.diags.debug.enabled INT 1
>> +            CONFIG proxy.config.diags.debug.tags STRING url_sig
>> +
>> +    and do a traffic_line -x; Debug output will go to traffic.out.
>> +    Failed transactions (signature check fails that is) will be logged
>> +    in to error.log.
>> +
>> +Signing a URL
>> +    At the signing portal take the full URL, without any query string, and
>> +    add on a query string with the following parameters:
>> +
>> +    Client IP address
>> +            The client IP address that this signature is valid for.
>> +            C=<client IP address>
>> +    Expiration
>> +            The Expiration time (seconds since epoch) of this signature.
>> +            E=<expiration time in secs since unix epoch>
>> +    Algorithm
>> +            The Algorithm used to create the signature. Only 1 (HMAC_SHA1)
>> +            and 2 (HMAC_MD5) are supported at this time
>> +            A=<algorithm number>
>> +    Key index
>> +            Index of the key used. This is the index of the key in the
>> +            configuration file on the cache. The set of keys is a shared
>> +            secret between the signing portal and the edge caches. There
>> +            is one set of keys per reverse proxy domain (fqdn).
>> +            K=<key index used>
>> +    Parts
>> +            Parts to use for the signature, always excluding the scheme
>> +            (http://).  parts0 = fqdn, parts1..x is the directory parts
>> +            of the path, if there are more parts to the path than letters
>> +            in the parts param, the last one is repeated for those.
>> +            Examples:
>> +                    1: use fqdn and all of URl path
>> +                    0110: use part1 and part 2 of path only
>> +                    01: use everything except the fqdn
>> +            P=<parts string (0's and 1's>
>> +    Signature
>> +            The signature over the parts + the query string up to and
>> +            including "S=".
>> +            S=<signature>
>> +
>> +
>> +Example
>> +    Build, install
>> +
>> +            make -f Makefile.tsxs
>> +            make -f Makefile.tsxs install
>> +
>> +    Create the config file, using the genkeys script, or otherwise.
>> +
>> +            $ ./genkeys.pl  > 
>> /usr/local/trafficserver-master/etc/trafficserver/sign_test.config
>> +            $ cat 
>> /usr/local/trafficserver-master/etc/trafficserver/sign_test.config
>> +            key0 = YwG7iAxDo6Gaa38KJOceV4nsxiAJZ3DS
>> +            key1 = nLE3SZKRgaNM9hLz_HnIvrCw_GtTUJT1
>> +            key2 = YicZbmr6KlxfxPTJ3p9vYhARdPQ9WJYZ
>> +            key3 = DTV4Tcn046eM9BzJMeYrYpm3kbqOtBs7
>> +            key4 = C1r6R6MINoQd5YSH25fU66tuRhhz3fs_
>> +            key5 = l4dxe6YEpYbJtyiOmX5mafhwKImC5kej
>> +            key6 = ekKNHXu9_oOC5eqIGJVxV0vI9FYvKVya
>> +            key7 = BrjibTmpTTuhMHqphkQAuCWA0Zg97WQB
>> +            key8 = rEtWLb1jcYoq9VG8Z8TKgX4GxBuro20J
>> +            key9 = mrP_6ibDBG4iYpfDB6W8yn3ZyGmdwc6M
>> +            key10 = tbzoTTGZXPLcvpswCQCYz1DAIZcAOGyX
>> +            key11 = lWsn6gUeSEW79Fk2kwKVfzhVG87EXLna
>> +            key12 = Riox0SmGtBWsrieLUHVWtpj18STM4MP1
>> +            key13 = kBsn332B7yG3HdcV7Tw51pkvHod7_84l
>> +            key14 = hYI4GUoIlZRf0AyuXkT3QLvBMEoFxkma
>> +            key15 = EIgJKwIR0LU9CUeTUdVtjMgGmxeCIbdg
>> +            error_url = 403
> 
> If I'm reading the code right, the error_url key is
>       error_url = STATUS URL
> 
> Is that right?
> 
>> +            $
>> +
>> +    Add the remap rule like
>> +
>> +            map http://test-remap.domain.com http://google.com 
>> @plugin=url_sig.so @pparam=sign_test.config
>> +
>> +    Restart traffic server or traffic_line -x - verify there are no errors 
>> in diags.log
>> +
>> +    Try the path unsigned:
>> +
>> +            $ curl -vs -H'Host: test-remap.domain.com' 
>> http://localhost:8080/
>> +            * Adding handle: conn: 0x200f8a0
>> +            * Adding handle: send: 0
>> +            * Adding handle: recv: 0
>> +            * Curl_addHandleToPipeline: length: 1
>> +            * - Conn 0 (0x200f8a0) send_pipe: 1, recv_pipe: 0
>> +            * About to connect() to localhost port 8080 (#0)
>> +            *   Trying 127.0.0.1...
>> +            * Connected to localhost (127.0.0.1) port 8080 (#0)
>> +            > GET / HTTP/1.1
>> +            > User-Agent: curl/7.32.0
>> +            > Accept: */*
>> +            > Host: test-remap.domain.com
>> +            >
>> +            < HTTP/1.1 403 Forbidden
>> +            < Date: Tue, 15 Apr 2014 22:57:32 GMT
>> +            < Connection: close
>> +            * Server ATS/5.0.0 is not blacklisted
>> +            < Server: ATS/5.0.0
>> +            < Cache-Control: no-store
>> +            < Content-Type: text/plain
>> +            < Content-Language: en
>> +            < Content-Length: 21
>> +            <
>> +            * Closing connection 0
>> +            Authorization Denied$
>> +            $
>> +
>> +    Sign the URL and try it again. Run the script with appropriate params, 
>> and it will output the curl line to run:
>> +
>> +            $ ./sign.pl --url http://test-remap.domain.com/ --useparts 1 
>> --algorithm 1 --duration 60 --keyindex 3 --key 
>> DTV4Tcn046eM9BzJMeYrYpm3kbqOtBs7
>> +            curl -s -o /dev/null -v --max-redirs 0 
>> 'http://test-remap.domain.com/?E=1397603088&A=1&K=3&P=1&S=28d822f68ac7265db61a8441e0877a98fe1007cc'
>> +
>> +    Since test-remap.domain.com doesn't actually exist, we have to change 
>> that line slightly:
>> +
>> +            $ curl -s -o /dev/null -v --max-redirs 0 -H 'Host: 
>> test-remap.domain.com' 
>> 'http://localhost:8080/?E=1397603088&A=1&K=3&P=1&S=28d822f68ac7265db61a8441e0877a98fe1007cc'
>> +            * Adding handle: conn: 0xef0a90
>> +            * Adding handle: send: 0
>> +            * Adding handle: recv: 0
>> +            * Curl_addHandleToPipeline: length: 1
>> +            * - Conn 0 (0xef0a90) send_pipe: 1, recv_pipe: 0
>> +            * About to connect() to localhost port 8080 (#0)
>> +            *   Trying 127.0.0.1...
>> +            * Connected to localhost (127.0.0.1) port 8080 (#0)
>> +            > GET 
>> /?E=1397603088&A=1&K=3&P=1&S=28d822f68ac7265db61a8441e0877a98fe1007cc 
>> HTTP/1.1
>> +            > User-Agent: curl/7.32.0
>> +            > Accept: */*
>> +            > Host: test-remap.domain.com
>> +            >
>> +            < HTTP/1.1 200 OK
>> +            < Location: http://www.google.com/
>> +            < Content-Type: text/html; charset=UTF-8
>> +            < Date: Tue, 15 Apr 2014 23:04:36 GMT
>> +            < Expires: Thu, 15 May 2014 23:04:36 GMT
>> +            < Cache-Control: public, max-age=2592000
>> +            * Server ATS/5.0.0 is not blacklisted
>> +            < Server: ATS/5.0.0
>> +            < Content-Length: 219
>> +            < X-XSS-Protection: 1; mode=block
>> +            < X-Frame-Options: SAMEORIGIN
>> +            < Alternate-Protocol: 80:quic
>> +            < Age: 0
>> +            < Connection: keep-alive
>> +            <
>> +            { [data not shown]
>> +            * Connection #0 to host localhost left intact
>> +            $
>> 
>> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/88f18501/plugins/experimental/url_sig/genkeys.pl
>> ----------------------------------------------------------------------
>> diff --git a/plugins/experimental/url_sig/genkeys.pl 
>> b/plugins/experimental/url_sig/genkeys.pl
>> new file mode 100755
>> index 0000000..ae5bc07
>> --- /dev/null
>> +++ b/plugins/experimental/url_sig/genkeys.pl
>> @@ -0,0 +1,29 @@
>> +#!/usr/bin/perl
>> +
>> +#  Licensed to the Apache Software Foundation (ASF) under one
>> +#  or more contributor license agreements.  See the NOTICE file
>> +#  distributed with this work for additional information
>> +#  regarding copyright ownership.  The ASF licenses this file
>> +#  to you under the Apache License, Version 2.0 (the
>> +#  "License"); you may not use this file except in compliance
>> +#  with the License.  You may obtain a copy of the License at
>> +#
>> +#      http://www.apache.org/licenses/LICENSE-2.0
>> +#
>> +#  Unless required by applicable law or agreed to in writing, software
>> +#  distributed under the License is distributed on an "AS IS" BASIS,
>> +#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> +#  See the License for the specific language governing permissions and
>> +#  limitations under the License.
>> +
>> +my $len = 32;
>> +my @chars = ( 'a' .. 'z', 'A' .. 'Z', '0' .. '9', '_' );
>> +foreach my $i ( 0 .. 15 ) {
>> +    my $string = "";
>> +    foreach ( 1 .. $len ) {
>> +        $string .= $chars[ rand @chars ];
>> +    }
>> +    print "key" . $i . " = " . $string . "\n";
>> +}
>> +#print "error_url=302 http://www.domain.com/this/is/the/path/error.html\n";;
>> +print "error_url = 403\n";
>> 
>> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/88f18501/plugins/experimental/url_sig/sign.pl
>> ----------------------------------------------------------------------
>> diff --git a/plugins/experimental/url_sig/sign.pl 
>> b/plugins/experimental/url_sig/sign.pl
>> new file mode 100755
>> index 0000000..d3fbdeb
>> --- /dev/null
>> +++ b/plugins/experimental/url_sig/sign.pl
>> @@ -0,0 +1,101 @@
>> +#!/usr/bin/perl
>> +
>> +#  Licensed to the Apache Software Foundation (ASF) under one
>> +#  or more contributor license agreements.  See the NOTICE file
>> +#  distributed with this work for additional information
>> +#  regarding copyright ownership.  The ASF licenses this file
>> +#  to you under the Apache License, Version 2.0 (the
>> +#  "License"); you may not use this file except in compliance
>> +#  with the License.  You may obtain a copy of the License at
>> +#
>> +#      http://www.apache.org/licenses/LICENSE-2.0
>> +#
>> +#  Unless required by applicable law or agreed to in writing, software
>> +#  distributed under the License is distributed on an "AS IS" BASIS,
>> +#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> +#  See the License for the specific language governing permissions and
>> +#  limitations under the License.
>> +
>> +use Digest::SHA qw(hmac_sha1 hmac_sha1_hex);
>> +use Digest::HMAC_MD5 qw(hmac_md5 hmac_md5_hex);
>> +use Getopt::Long;
>> +use strict;
>> +use warnings;
>> +my $key       = undef;
>> +my $string    = undef;
>> +my $useparts  = undef;
>> +my $result    = undef;
>> +my $duration  = undef;
>> +my $keyindex  = undef;
>> +my $verbose   = 0;
>> +my $url       = undef;
>> +my $client    = undef;
>> +my $algorithm = 1;
>> +
>> +$result = GetOptions(
>> +    "url=s"       => \$url,
>> +    "useparts=s"  => \$useparts,
>> +    "duration=i"  => \$duration,
>> +    "key=s"       => \$key,
>> +    "client=s"    => \$client,
>> +    "algorithm=i" => \$algorithm,
>> +    "keyindex=i"  => \$keyindex,
>> +    "verbose"     => \$verbose
>> +);
>> +
>> +if ( !defined($key) || !defined($url) || !defined($duration) || 
>> !defined($keyindex) ) {
>> +    &help();
>> +    exit(1);
>> +}
>> +
>> +$url =~ s/^http:\/\///;
>> +my $i              = 0;
>> +my $part_active    = 0;
>> +my $j              = 0;
>> +my @inactive_parts = ();
>> +foreach my $part ( split( /\//, $url ) ) {
>> +    if ( length($useparts) > $i ) {
>> +            $part_active = substr( $useparts, $i++, 1 );
>> +    }
>> +    if ($part_active) {
>> +            $string .= $part . "/";
>> +    }
>> +    else {
>> +            $inactive_parts[$j] = $part;
>> +    }
>> +    $j++;
>> +}
>> +chop($string);
>> +if ( defined($client) ) {
>> +    $string .= "?C=" . $client . "&E=" . ( time() + $duration ) . "&A=" . 
>> $algorithm . "&K=" . $keyindex . "&P=" . $useparts . "&S=";
>> +}
>> +else {
>> +    $string .= "?E=" . ( time() + $duration ) . "&A=" . $algorithm . "&K=" 
>> . $keyindex . "&P=" . $useparts . "&S=";
>> +}
>> +
>> +$verbose && print "signed string = " . $string . "\n";
>> +
>> +my $digest;
>> +if ( $algorithm == 1 ) {
>> +    $digest = hmac_sha1_hex( $string, $key );
>> +}
>> +else {
>> +    $digest = hmac_md5_hex( $string, $key );
>> +}
>> +my $qstring = ( split( /\?/, $string ) )[1];
>> +
>> +print "curl -s -o /dev/null -v --max-redirs 0 'http://"; . $url . "?" . 
>> $qstring . $digest . "'\n";
>> +
>> +sub help {
>> +    print "sign.pl - Example signing utility in perl for signed URLs\n";
>> +    print "Usage: \n";
>> +    print "  ./sign.pl  --url <value> \\ \n";
>> +    print "             --useparts <value> \\ \n";
>> +    print "             --algorithm <value> \\ \n";
>> +    print "             --duration <value> \\ \n";
>> +    print "             --keyindex <value> \\ \n";
>> +    print "             [--client <value>] \\ \n";
>> +    print "             --key <value>  \\ \n";
>> +    print "             [--verbose] \n";
>> +    print "\n";
>> +}
>> 
>> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/88f18501/plugins/experimental/url_sig/url_sig.c
>> ----------------------------------------------------------------------
>> diff --git a/plugins/experimental/url_sig/url_sig.c 
>> b/plugins/experimental/url_sig/url_sig.c
>> new file mode 100644
>> index 0000000..0cde9d3
>> --- /dev/null
>> +++ b/plugins/experimental/url_sig/url_sig.c
>> @@ -0,0 +1,456 @@
>> +/** @file
>> +  Licensed to the Apache Software Foundation (ASF) under one
>> +  or more contributor license agreements.  See the NOTICE file
>> +  distributed with this work for additional information
>> +  regarding copyright ownership.  The ASF licenses this file
>> +  to you under the Apache License, Version 2.0 (the
>> +  "License"); you may not use this file except in compliance
>> +  with the License.  You may obtain a copy of the License at
>> +
>> +      http://www.apache.org/licenses/LICENSE-2.0
>> +
>> +  Unless required by applicable law or agreed to in writing, software
>> +  distributed under the License is distributed on an "AS IS" BASIS,
>> +  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> +  See the License for the specific language governing permissions and
>> +  limitations under the License.
>> + */
>> +
>> +#include "url_sig.h"
>> +
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +#include <sys/types.h>
>> +#include <time.h>
>> +#include <openssl/hmac.h>
>> +#include <openssl/evp.h>
>> +#include <sys/socket.h>
>> +#include <netinet/in.h>
>> +#include <arpa/inet.h>
>> +#include <limits.h>
>> +#include <ctype.h>
>> +
>> +#include <ts/ts.h>
>> +#include <ts/remap.h>
>> +
>> +static const char* PLUGIN_NAME = "url_sig";
>> +
>> +struct config {
>> +    char *map_from;
>> +    char *map_to;
>> +    TSHttpStatus err_status;
>> +    char *err_url;
>> +    char keys[MAX_KEY_NUM][MAX_KEY_LEN];
>> +};
>> +
>> +TSReturnCode TSRemapInit(TSRemapInterface* api_info, char *errbuf, int 
>> errbuf_size) {
>> +    if (!api_info) {
>> +            strncpy(errbuf, "[tsremap_init] - Invalid TSRemapInterface 
>> argument", (size_t) (errbuf_size - 1));
>> +            return TS_ERROR;
>> +    }
>> +
>> +    if (api_info->tsremap_version < TSREMAP_VERSION) {
>> +            snprintf(errbuf, errbuf_size - 1, "[TSRemapInit] - Incorrect 
>> API version %ld.%ld", api_info->tsremap_version >> 16,
>> +                            (api_info->tsremap_version & 0xffff));
>> +            return TS_ERROR;
>> +    }
>> +
>> +    TSDebug(PLUGIN_NAME, "plugin is succesfully initialized");
>> +    return TS_SUCCESS;
>> +}
>> +
>> +// To force a config file reload touch remap.config and do a "traffic_line 
>> -x"
>> +TSReturnCode TSRemapNewInstance(int argc, char* argv[], void** ih, char* 
>> errbuf, int errbuf_size) {
>> +    char config_file[PATH_MAX];
>> +    struct config *cfg;
>> +
>> +    cfg = TSmalloc(sizeof(struct config));
>> +    *ih = (void *) cfg;
>> +
>> +    int i = 0;
>> +    for (i = 0; i < MAX_KEY_NUM; i++) {
>> +            cfg->keys[i][0] = '\0';
>> +    }
>> +
>> +    if (argc != 3) {
>> +            snprintf(errbuf, errbuf_size - 1, "[TSRemapNewKeyInstance] - 
>> Argument count wrong (%d)... Need exactly two pparam= (config file name).",
>> +                            argc);
>> +            return TS_ERROR;
>> +    }
>> +    TSDebug(PLUGIN_NAME, "Initializing remap function of %s -> %s with 
>> config from %s", argv[0], argv[1], argv[2]);
>> +    cfg->map_from = TSstrndup( argv[0], strlen(argv[0]));
>> +    cfg->map_to = TSstrndup( argv[0], strlen(argv[1]));
>> +
>> +    const char* install_dir = TSInstallDirGet();
>> +    snprintf(config_file, sizeof(config_file), "%s/%s/%s", install_dir, 
>> "etc/trafficserver", argv[2]);
> 
> This should be TSConfigDirGet().
> 
>> +    TSDebug(PLUGIN_NAME, "config file name: %s", config_file);
>> +    FILE *file = fopen(config_file, "r");
>> +    if (file == NULL ) {
>> +            snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - Error 
>> opening file %s.", config_file);
>> +            return TS_ERROR;
>> +    }
>> +
>> +    char line[260];
>> +    int line_no = 0;
>> +    int keynum;
>> +    while (fgets(line, sizeof(line), file) != NULL ) {
>> +            TSDebug(PLUGIN_NAME, "LINE: %s (%d)", line, (int) strlen(line));
>> +            line_no++;
>> +            if (line[0] == '#' || strlen(line) <= 1)
>> +                    continue;
>> +            char *pos = strchr(line, '=');
>> +            if (pos == NULL ) {
>> +                    TSError("Error parsing line %d of file %s (%s).", 
>> line_no, config_file, line);
>> +            }
>> +            *pos = '\0';
>> +            char *value = pos + 1;
>> +        while (isspace(*value))         // remove whitespace
>> +                            value++;
>> +            pos = strchr(value, '\n');              // remove the new line, 
>> terminate the string
>> +            if (pos != NULL ) {
>> +                    *pos = '\0';
>> +            } else {
>> +                    snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] 
>> - Maximum line (%d) exceeded on line %d.", MAX_KEY_LEN, line_no);
>> +                    return TS_ERROR;
>> +            }
>> +            if (strncmp(line, "key", 3) == 0) {
>> +                    if (value != NULL ) {
>> +                            if (strncmp((char *) (line + 3), "0", 1) == 0) {
>> +                                    keynum = 0;
>> +                            } else {
>> +                    TSDebug(PLUGIN_NAME, ">>> %s <<<", line +3);
>> +                                    keynum = atoi((char *) (line + 3));
>> +                                    if (keynum == 0) {
>> +                                            keynum = -1; // Not a Number
>> +                                    }
>> +                            }
>> +                            TSDebug(PLUGIN_NAME, "key number %d == %s", 
>> keynum, value);
>> +                            if (keynum > MAX_KEY_NUM || keynum == -1) {
>> +                                    snprintf(errbuf, errbuf_size - 1, 
>> "[TSRemapNewInstance] - Key number (%d) > MAX_KEY_NUM (%d) or NaN.", keynum, 
>> MAX_KEY_NUM);
>> +                                    return TS_ERROR;
>> +                            }
>> +                            strcpy(&cfg->keys[keynum][0], value);
>> +                    }
>> +            } else if (strncmp(line, "error_url", 9) == 0) {
>> +                    if (atoi(value)) {
>> +                            cfg->err_status = atoi(value);
>> +                    }
>> +                    value += 3;
>> +                    while (isspace(*value))
>> +                            value++;
>> +//                  if (strncmp(value, "http://";, strlen("http://";)) != 0) {
>> +//                          snprintf(errbuf, errbuf_size - 1,
>> +//                                          "[TSRemapNewInstance] - Invalid 
>> config, err_status == 302, but err_url does not start with \"http://\"";);
>> +//                          return TS_ERROR;
>> +//                  }
>> +                    if (cfg->err_status == TS_HTTP_STATUS_MOVED_TEMPORARILY)
>> +                            cfg->err_url = TSstrndup(value, strlen(value));
>> +                    else cfg->err_url = NULL;
>> +            } else {
>> +                    TSError("Error parsing line %d of file %s (%s).", 
>> line_no, config_file, line);
>> +            }
>> +    }
>> +
>> +    switch (cfg->err_status) {
>> +    case TS_HTTP_STATUS_MOVED_TEMPORARILY:
>> +            if (cfg->err_url == NULL ) {
>> +                    snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] 
>> - Invalid config, err_status == 302, but err_url == NULL");
>> +                    return TS_ERROR;
>> +            }
>> +            printf("[url_sig] mapping {%s -> %s} with status %d and err url 
>> %s\n", argv[0], argv[1], cfg->err_status, cfg->err_url);
>> +            break;
>> +    case TS_HTTP_STATUS_FORBIDDEN:
>> +            if (cfg->err_url != NULL ) {
>> +                    snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] 
>> - Invalid config, err_status == 403, but err_url != NULL");
>> +                    return TS_ERROR;
>> +            }
>> +            printf("[url_sig] mapping {%s -> %s} with status %d\n", 
>> argv[0], argv[1], cfg->err_status);
>> +            break;
>> +    default:
>> +            snprintf(errbuf, errbuf_size - 1, "[TSRemapNewInstance] - 
>> Return code %d not supported.", cfg->err_status);
>> +            return TS_ERROR;
>> +
>> +    }
>> +
>> +    i = 0;
>> +    for (i = 0; i < MAX_KEY_NUM; i++) {
>> +            if (cfg->keys[i] != NULL && strlen(cfg->keys[i]) > 0)
>> +                    printf("[url_sig] shared secret key[%d] = %s\n", i, 
>> cfg->keys[i]);
>> +    }
>> +    fclose(file);
>> +    printf("%s version %s initialized.\n", PLUGIN_NAME, VERSION);
>> +    return TS_SUCCESS;
>> +}
>> +
>> +void TSRemapDeleteInstance(void* ih) {
>> +    struct config *cfg;
>> +    cfg = (struct config *) ih;
>> +
>> +    TSError("Cleaning up...");
>> +    TSfree(cfg->map_from);
>> +    TSfree(cfg->map_to);
>> +    TSfree(cfg->err_url);
>> +    TSfree(cfg);
>> +}
>> +
>> +void err_log(char *url, char *msg) {
>> +    if (msg && url) {
>> +            TSDebug(PLUGIN_NAME, "[URL=%s]: %s", url, msg);
>> +            TSError("[URL=%s]: %s", url, msg); // This goes to error.log
>> +    } else {
>> +            TSError("Invalid err_log request");
>> +    }
>> +}
>> +
>> +TSRemapStatus TSRemapDoRemap(void* ih, TSHttpTxn txnp, TSRemapRequestInfo 
>> *rri) {
>> +    struct config *cfg;
>> +    cfg = (struct config *) ih;
>> +
>> +    int url_len = 0;
>> +    time_t expiration = 0;
>> +    int algorithm = -1;
>> +    int keyindex = -1;
>> +    int cmp_res;
>> +    int rval;
>> +    int i = 0;
>> +    int j = 0;
>> +    unsigned int sig_len = 0;
>> +
>> +    /* all strings are locally allocated except url... about 25k per 
>> instance*/
>> +    char *url;
>> +    char signed_part[8192] = { '\0' }; // this initializes the whole array 
>> and is needed
>> +    char urltokstr[8192] = { '\0' };
>> +    char client_ip[CIP_STRLEN] = { '\0' };
>> +    char ipstr[CIP_STRLEN] = { '\0' };
>> +    unsigned char sig[MAX_SIG_SIZE + 1];
>> +    char sig_string[2 * MAX_SIG_SIZE + 1];
>> +
>> +    /* these are just pointers into other allocations */
>> +    char *signature = NULL;
>> +    char *parts = NULL;
>> +    char *part = NULL;
>> +    char *p = NULL, *pp = NULL;
>> +    char *query = NULL;
>> +
>> +    int retval, sockfd;
>> +    socklen_t peer_len;
>> +    struct sockaddr_in peer;
>> +
>> +    url = TSUrlStringGet(rri->requestBufp, rri->requestUrl, &url_len);
>> +
>> +    if (url_len >= MAX_REQ_LEN - 1) {
>> +            err_log(url, "URL string too long.");
>> +            goto deny;
>> +    }
>> +
>> +    TSDebug(PLUGIN_NAME, "%s", url);
>> +
>> +    query = strstr(url, "?");
>> +    if (query == NULL ) {
>> +            err_log(url, "Has no query string.");
>> +            goto deny;
>> +    }
>> +
>> +    if (strncmp(url, "http://";, strlen("http://";)) != 0) {
>> +            err_log(url, "Invalid URL scheme - only http supported.");
>> +            goto deny;
>> +    }
>> +
>> +    /* first, parse the query string */
>> +    query++; /* get rid of the ? */
>> +    TSDebug(PLUGIN_NAME, "Query string is:%s", query);
>> +
>> +    // Client IP - this one is optional
>> +    p = strstr(query, CIP_QSTRING"=");
>> +    if (p != NULL ) {
>> +
>> +            p += strlen(CIP_QSTRING + 1);
>> +            pp = strstr(p, "&");
>> +            if ((pp - p) > CIP_STRLEN - 1 || (pp - p) < 4) {
>> +                    err_log(url, "IP address string too long or short.");
>> +                    goto deny;
>> +            }
>> +            strncpy(client_ip, p + strlen(CIP_QSTRING) + 1, (pp - p - 
>> (strlen(CIP_QSTRING) + 1)));
>> +            client_ip[pp - p - (strlen(CIP_QSTRING) + 1)] = '\0';
>> +            TSDebug(PLUGIN_NAME, "CIP: -%s-", client_ip);
>> +            retval = TSHttpTxnClientFdGet(txnp, &sockfd);
>> +            if (retval != TS_SUCCESS) {
>> +                    err_log(url, "Error getting sockfd.");
>> +                    goto deny;
>> +            }
>> +            peer_len = sizeof(peer);
>> +            if (getpeername(sockfd, (struct sockaddr*) &peer, &peer_len) != 
>> 0) {
>> +                    perror("Can't get peer address:");
>> +            }
> 
> What's wrong with TSHttpTxnClientAddrGet()?
> 
>> +            struct sockaddr_in *s = (struct sockaddr_in *) &peer;
>> +            inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
>> +            TSDebug(PLUGIN_NAME, "Peer address: -%s-", ipstr);
>> +            if (strcmp(ipstr, client_ip) != 0) {
>> +                    err_log(url, "Client IP doesn't match signature.");
>> +                    goto deny;
>> +            }
>> +    }
>> +    // Expiration
>> +    p = strstr(query, EXP_QSTRING"=");
>> +    if (p != NULL ) {
>> +            p += strlen(EXP_QSTRING) + 1;
>> +            expiration = atoi(p);
>> +            if (expiration == 0 || expiration < time(NULL )) {
>> +                    err_log(url, "Invalid expiration, or expired.");
>> +                    goto deny;
>> +            }
>> +            TSDebug(PLUGIN_NAME, "Exp: %d", (int) expiration);
>> +    } else {
>> +            err_log(url, "Expiration query string not found.");
>> +            goto deny;
>> +    }
>> +    // Algorithm
>> +    p = strstr(query, ALG_QSTRING"=");
>> +    if (p != NULL ) {
>> +            p += strlen(ALG_QSTRING) + 1;
>> +            algorithm = atoi(p);
>> +            // The check for a valid algorithm is later.
>> +            TSDebug(PLUGIN_NAME, "Algorithm: %d", algorithm);
>> +    } else {
>> +            err_log(url, "Algorithm query string not found.");
>> +            goto deny;
>> +    }
>> +    // Key index
>> +    p = strstr(query, KIN_QSTRING"=");
>> +    if (p != NULL ) {
>> +            p += strlen(KIN_QSTRING) + 1;
>> +            keyindex = atoi(p);
>> +            if (keyindex == -1) {
>> +                    err_log(url, "Invalid key index.");
>> +                    goto deny;
>> +            }
>> +            TSDebug(PLUGIN_NAME, "Key Index: %d", keyindex);
>> +    } else {
>> +            err_log(url, "KeyIndex query string not found.");
>> +            goto deny;
>> +    }
>> +    // Parts
>> +    p = strstr(query, PAR_QSTRING"=");
>> +    if (p != NULL ) {
>> +            p += strlen(PAR_QSTRING) + 1;
>> +            parts = p; // NOTE parts is not NULL terminated it is 
>> terminated by "&" of next param
>> +            p = strstr(parts, "&");
>> +            TSDebug(PLUGIN_NAME, "Parts: %.*s", (int) (p - parts), parts);
>> +    } else {
>> +            err_log(url, "PartsSigned query string not found.");
>> +            goto deny;
>> +    }
>> +    // And finally, the sig (has to be last)
>> +    p = strstr(query, SIG_QSTRING"=");
>> +    if (p != NULL ) {
>> +            p += strlen(SIG_QSTRING) + 1;
>> +            signature = p; // NOTE sig is not NULL terminated, it has to be 
>> 20 chars
>> +            if ((algorithm == USIG_HMAC_SHA1 && strlen(signature) < 
>> SHA1_SIG_SIZE) || (algorithm == USIG_HMAC_MD5 && strlen(signature) < 
>> MD5_SIG_SIZE)) {
>> +                    err_log(url, "Signature query string too short (< 
>> 20).");
>> +                    goto deny;
>> +            }
>> +    } else {
>> +            err_log(url, "Signature query string not found.");
>> +            goto deny;
>> +    }
>> +
>> +    /* have the query string, and parameters passed initial checks */
>> +    TSDebug(PLUGIN_NAME, "Found all needed parameters: C=%s E=%d A=%d K=%d 
>> P=%s S=%s", client_ip, (int) expiration, algorithm, keyindex, parts,
>> +                    signature);
>> +
>> +    /* find the string that was signed - cycle through the parts letters, 
>> adding the part of the fqdn/path if it is 1 */
>> +    p = strstr(url, "?");
>> +    memcpy(urltokstr, &url[strlen("http://";)], p - url - strlen("http://";));
>> +    part = strtok_r(urltokstr, "/", &p);
>> +    while (part != NULL ) {
>> +            if (parts[j] == '1') {
>> +                    strcpy(signed_part + strlen(signed_part), part);
>> +                    strcpy(signed_part + strlen(signed_part), "/");
>> +            }
>> +            if (parts[j + 1] == '0' || parts[j + 1] == '1') // This 
>> remembers the last part, meaning, if there are no more valid letters in parts
>> +                    j++;                                        // will 
>> keep repeating the value of the last one
>> +            part = strtok_r(NULL, "/", &p);
>> +    }
>> +
>> +    signed_part[strlen(signed_part) - 1] = '?'; // chop off the last /, 
>> replace with '?'
>> +    p = strstr(query, SIG_QSTRING"=");
>> +    strncat(signed_part, query, (p - query) + strlen(SIG_QSTRING) + 1);
>> +
>> +    TSDebug(PLUGIN_NAME, "Signed string=\"%s\"", signed_part);
>> +
>> +    /* calculate the expected the signature with the right algorithm */
>> +    switch (algorithm) {
>> +    case USIG_HMAC_SHA1:
>> +            HMAC(EVP_sha1(), (const unsigned char *) cfg->keys[keyindex], 
>> strlen(cfg->keys[keyindex]), (const unsigned char *) signed_part,
>> +                            strlen(signed_part), sig, &sig_len);
>> +            if (sig_len != SHA1_SIG_SIZE) {
>> +                    TSDebug(PLUGIN_NAME, "sig_len: %d", sig_len);
>> +                    err_log(url, "Calculated sig len !=  SHA1_SIG_SIZE !");
>> +                    goto deny;
>> +            }
>> +
>> +            break;
>> +    case USIG_HMAC_MD5:
>> +            HMAC(EVP_md5(), (const unsigned char *) cfg->keys[keyindex], 
>> strlen(cfg->keys[keyindex]), (const unsigned char *) signed_part,
>> +                            strlen(signed_part), sig, &sig_len);
>> +            if (sig_len != MD5_SIG_SIZE) {
>> +                    TSDebug(PLUGIN_NAME, "sig_len: %d", sig_len);
>> +                    err_log(url, "Calculated sig len !=  MD5_SIG_SIZE !");
>> +                    goto deny;
>> +            }
>> +            break;
>> +    default:
>> +            err_log(url, "Algorithm not supported.");
>> +            goto deny;
>> +    }
>> +
>> +    for (i = 0; i < sig_len; i++) {
>> +            sprintf(&(sig_string[i * 2]), "%02x", sig[i]);
>> +    }
>> +
>> +    TSDebug(PLUGIN_NAME, "Expected signature: %s", sig_string);
>> +
>> +    /* and compare to signature that was sent */
>> +    cmp_res = strncmp(sig_string, signature, sig_len * 2);
>> +    if (cmp_res != 0) {
>> +            err_log(url, "Signature check failed.");
>> +            goto deny;
>> +    } else {
>> +            TSDebug(PLUGIN_NAME, "Signature check passed.");
>> +            goto allow;
>> +    }
>> +
>> +    /* ********* Deny ********* */
>> +    deny: if (url)
>> +            TSfree(url);
>> +    switch (cfg->err_status) {
>> +    case TS_HTTP_STATUS_MOVED_TEMPORARILY:
>> +            TSDebug(PLUGIN_NAME, "Redirecting to %s", cfg->err_url);
>> +            char *start, *end;
>> +            start = cfg->err_url;
>> +            end = start + strlen(cfg->err_url);
>> +            if (TSUrlParse(rri->requestBufp, rri->requestUrl, (const char 
>> **) &start, end) != TS_PARSE_DONE) {
>> +                    err_log("url", "Error inn TSUrlParse!");
>> +            }
>> +            rri->redirect = 1;
>> +            break;
>> +    case TS_HTTP_STATUS_FORBIDDEN:
>> +    default:
>> +            /* set status and body to be 403 */
>> +            TSHttpTxnSetHttpRetStatus(txnp, TS_HTTP_STATUS_FORBIDDEN);
>> +            TSHttpTxnErrorBodySet(txnp, TSstrdup("Authorization Denied"), 
>> strlen("Authorization Denied") - 1, TSstrdup("text/plain"));
>> +            break;
>> +    }
>> +    return TSREMAP_DID_REMAP;
>> +
>> +    /* ********* Allow ********* */
>> +    allow: if (url)
>> +            TSfree(url);
>> +    /* drop the query string so we can cache-hit */
>> +    rval = TSUrlHttpQuerySet(rri->requestBufp, rri->requestUrl, NULL, 0);
> 
> You can't sign URLs with query parameters?
> 
>> +    if (rval != TS_SUCCESS) {
>> +            TSError("Error stripping query string: %d.", rval);
>> +    }
>> +    return TSREMAP_NO_REMAP;
>> +}
>> 
>> http://git-wip-us.apache.org/repos/asf/trafficserver/blob/88f18501/plugins/experimental/url_sig/url_sig.h
>> ----------------------------------------------------------------------
>> diff --git a/plugins/experimental/url_sig/url_sig.h 
>> b/plugins/experimental/url_sig/url_sig.h
>> new file mode 100644
>> index 0000000..c495b4b
>> --- /dev/null
>> +++ b/plugins/experimental/url_sig/url_sig.h
>> @@ -0,0 +1,52 @@
>> +/** @file
>> +  Licensed to the Apache Software Foundation (ASF) under one
>> +  or more contributor license agreements.  See the NOTICE file
>> +  distributed with this work for additional information
>> +  regarding copyright ownership.  The ASF licenses this file
>> +  to you under the Apache License, Version 2.0 (the
>> +  "License"); you may not use this file except in compliance
>> +  with the License.  You may obtain a copy of the License at
>> +
>> +      http://www.apache.org/licenses/LICENSE-2.0
>> +
>> +  Unless required by applicable law or agreed to in writing, software
>> +  distributed under the License is distributed on an "AS IS" BASIS,
>> +  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>> +  See the License for the specific language governing permissions and
>> +  limitations under the License.
>> + */
>> +
>> +#ifndef URL_SIG_H_
>> +#define URL_SIG_H_
>> +
>> +#define VERSION     "1.0"
>> +/* in the query string that we add to sign the url: */
>> +#define CIP_QSTRING "C"  /* C=24.0.33.12 designates the client IP address */
>> +#define EXP_QSTRING "E"  /* E=1356128799 means expires at (seconds since 
>> Unix epoch) */
>> +#define ALG_QSTRING "A"  /* A=1 means hashing algorithm 1 */
>> +#define KIN_QSTRING "K"  /* K=3 means use key number 3 */
>> +#define PAR_QSTRING "P"  /* P=1110 means use parts 0, 1 and 2 (and no more) 
>> for the hashing of the url after removing the 'http://' */
>> +                         /* and making the parts by doing a split("/") */
>> +#define SIG_QSTRING "S"  /* S=9e2828d570a4bee3c964f698b0985ee58b9f6b64 
>> means 9e2828d570a4bee3c964f698b0985ee58b9f6b64 is the sig
>> +                            This one has to be the last one of the string */
>> +
>> +#define CIP_STRLEN 20
>> +#define EXP_STRLEN 16
>> +#define PAR_STRLEN 16
>> +#define MAX_PARTS 32
>> +
>> +#define MAX_HTTP_REQUEST_SIZE 8192 //
>> +
>> +#define MAX_SIG_SIZE 20
>> +#define SHA1_SIG_SIZE 20
>> +#define MD5_SIG_SIZE 16
>> +
>> +#define MAX_REQ_LEN 8192
>> +#define MAX_KEY_LEN 256
>> +#define MAX_KEY_NUM 16
>> +
>> +#define USIG_HMAC_SHA1  1
>> +#define USIG_HMAC_MD5  2
>> +
>> +
>> +#endif /* URL_SIG_H_ */
>> 
> 

Reply via email to