1CGI::Application::PlugiUns:e:rLiCnoknItnrtiebgurtieCtdGyI(P:3e:)rAlppDloiccuamteinotna:t:iPolnugin::LinkIntegrity(3)
2
3
4

NAME

6       CGI::Application::Plugin::LinkIntegrity - Make tamper-resisistent links
7       in CGI::Application
8

VERSION

10       Version 0.06
11

SYNOPSIS

13       In your application:
14
15           use base 'CGI::Application';
16           use CGI::Application::Plugin::LinkIntegrity;
17
18           sub setup {
19               my $self = shift;
20               $self->link_integrity_config(
21                   secret => 'some secret string known only to you and me',
22               );
23           }
24
25           sub account_info {
26               my $self = shift;
27
28               my $account_id = get_user_account_id();
29
30               my $template = $self->load_tmpl('account.html');
31
32               $template->param(
33                   'balance'    => $self->link("/account.cgi?rm=balance&acct_id=$account_id");
34                   'transfer'   => $self->link("/account.cgi?rm=transfer&acct_id=$account_id");
35                   'withdrawal' => $self->link("/account.cgi?rm=withdrawl&acct_id=$account_id");
36               );
37           }
38
39       In your template:
40
41           <h1>Welcome to The Faceless Banking Corp.</h1>
42           <h3>Actions:</h3>
43           <br /><a href="<TMPL_VAR NAME="balance">">Show Balance</a>
44           <br /><a href="<TMPL_VAR NAME="transfer">">Make a Transfer</a>
45           <br /><a href="<TMPL_VAR NAME="withdrawal">">Get Cash</a>
46
47       This will send the following HTML to the browser:
48
49           <h1>Welcome to The Faceless Banking Corp.</h1>
50           <h3>Actions:</h3>
51           <br /><a href="/account.cgi?rm=balance&acct_id=73&_checksum=1d7c4b82d075785de04fa6b98b572691">Show Balance</a>
52           <br /><a href="/account.cgi?rm=transfer&acct_id=73&_checksum=d41d8cd98f00b204e9800998ecf8427e">Make a Transfer</a>
53           <br /><a href="/account.cgi?rm=withdrawl&acct_id=73&_checksum=3c5ad17bdeef3c4281abd39c6386cfd6">Get Cash</a>
54
55       The URLs created are now tamper-resistent.  If the user changes
56       "acct_id" from 73 to 74, the "_checksum" will not match, and the system
57       will treat it as an intrusion attempt.
58
59   Calling link and self_link directly from the template
60       If you use "Template::Toolkit|Template" or
61       "HTML::Template::Plugin::Dot", you can pass the "CGI::Application"
62       $self object into the template and call "link" and "self_link" directly
63       from the template.  In your app:
64
65           $template->param(
66               'app'     => $self,
67               'name'    => 'gordon',
68               'email'   => 'gordon@example.com',
69           );
70
71       And in your template you can use
72
73           # Template::Toolkit syntax
74           <a href="[% app.self_link('name', name, 'email', email %]">...</a>
75
76           # HTML::Template::Plugin::Dot syntax
77           <a href="<TMPL_VAR NAME="app.self_link('name', name, 'email', email">">...</a>
78
79           # Petal syntax
80           <a href="http://www.example.com"
81              tal:attributes="href app/self_link('name', name, 'email', email)">...</a>
82
83       Note that in the parameters of the call to << link >>, items enclosed
84       in quotes are treated as literal parameters and barewords are treated
85       as template params.  So 'email' is the literal string, and "email" is
86       the template paramter named email (in this case 'gordon@example.com').
87

DESCRIPTION

89       "CGI::Application::Plugin::LinkIntegrity" lets you create tamper-
90       resistent links within your CGI::Application project.  When you create
91       an URL with "link", a "_checksum" is added to the URL:
92
93           my $link = $self->link("/account.cgi?rm=balance&acct_id=73");
94           print $link; # /account.cgi?rm=balance&acct_id=73&_checksum=1d7c4b82d075785de04fa6b98b572691
95
96       The checksum is a (cryptographic) hash of the URL, plus a secret string
97       known only to the server.
98
99       If the user attempts to change part of the URL (e.g. a query string
100       parameter, or the PATH_INFO), then the checksum will not match.  The
101       run mode will be changed to "link_tampered", and the "invalid_checksum"
102       hook will be called.
103
104       You can define the "link_tampered" run mode yourself, or you can use
105       the default "link_tampered" run mode built into
106       CGI::Application::Plugin::LinkIntegrity.
107
108       You can disable link checking during development by passing a true
109       value to the "disable" parameter of "$self->link_integrity_config".
110

METHODS

112   link_integrity_config
113       Configure the CGI::Application::Plugin::LinkIntegrity.  Usually, it
114       makes sense to configure this in the "setup" method of your
115       application's base class:
116
117           use CGI::Application::Plugin::LinkIntegrity;
118           use base 'CGI::Application';
119           package My::Project;
120
121           sub setup {
122               my $self = shift;
123
124               $self->run_modes(['bad_user_no_biscuit']);
125               $self->link_integrity_config(
126                   secret                 => 'some secret string known only to you and me',
127                   link_tampered_run_mode => 'bad_user_no_biscuit',
128                   digest_module          => 'Digest::MD5',
129                   disable                => 1,
130               );
131           }
132
133       Or you can pull in this configuration info from a config file.  For
134       instance, with using CGI::Application::Config::Context:
135
136           use CGI::Application::Plugin::LinkIntegrity;
137           use CGI::Application::Plugin::Config::Context;
138
139           use base 'CGI::Application';
140           package My::Project;
141
142           sub setup {
143               my $self = shift;
144
145               $self->conf->init(
146                   file   => 'app.conf',
147                   driver => 'ConfigGeneral',
148               );
149
150               my $config = $self->conf->context;
151
152               $self->link_integrity_config(
153                   $config->{'LinkIntegrity'},
154                   additional_data => sub {
155                       my $self = shift;
156                       return $self->session->id;
157                   },
158               );
159
160               my $link_tampered_rm = $config->{'LinkIntegrity'}{'link_tampered_run_mode'} || 'link_tampered';
161
162               $self->run_modes([$link_tampered_rm]);
163           }
164
165       Then in your configuration file:
166
167           <LinkIntegrity>
168               secret                 = some REALLY secret string
169               link_tampered_run_mode = bad_user_no_biscuit
170               hash_algorithm         = SHA1
171               disable                = 1
172           </LinkIntegrity>
173
174       This strategy allows you to enable and disable link checking on the fly
175       by changing the value of "disable" in the config file.
176
177       The following configuration parameters are available:
178
179       secret
180           A string known only to your application.  At a commandline, you can
181           generate a secret string with md5:
182
183            $ perl -MDigest::MD5 -le"print Digest::MD5::md5_hex($$, time, rand(42));"
184
185           Or you can use Data::UUID:
186
187            $ perl -MData::UUID -le"$ug = new Data::UUID; $uuid = $ug->create; print $ug->to_string($uuid)"
188
189           If someone knows your secret string, then they can generate their
190           own checksums on arbitrary data that will always pass the integrity
191           check in your application.  That's a Bad Thing, so don't let other
192           people know your secret string, and don't use the default secret
193           string if you can help it.
194
195       additional_data
196           You can pass constant additional data to the checksum generator for
197           every link.
198
199               $self->link_integrity_config(
200                   secret          => 'really secret',
201                   additional_data => 'some other secret data',
202               }
203
204           For instance, to stop one user from following a second user's link,
205           you can add a user-specific component to the session, such as the
206           user's session id:
207
208               $self->link_integrity_config(
209                   secret          => 'really secret',
210                   additional_data => sub {
211                       my $self = shift;
212                       return $self->session->id;
213                   }
214               }
215
216           You can pass a string instead of a subroutine.  But in the case of
217           the user's session, a subroutine is useful so that you get the
218           value of the user's session at the time when the checksum is
219           generated, not at the time when the link integrity system is
220           configured.
221
222       checksum_param
223           The name of the checksum parameter, which is added to the query
224           string and contains the cryptographic checksum of link. By default,
225           this parameter is named "_checksum".
226
227       link_tampered_run_mode
228           The run mode to go to when it has been detected that the user has
229           tampered with the link.  The default is "link_tampered".
230
231           See "The link_tampered Run Mode", below.
232
233       digest_module
234           Which digest module to use to create the checksum.  Typically, this
235           will be either "Digest::MD5" or "Digest::SHA1".  However any module
236           supported by "Digest::HMAC" will work.
237
238           The default "digest_module" is "Digest::MD5".
239
240       checksum_generator
241           If you want to provide a custom subroutine to make your own
242           checksums, you can define your own subroutine do it via the
243           "make_checksum" param.  Here's an example of one that uses
244           Digest::SHA2:
245
246                   $self->link_integrity_config(
247                       checksum_generator => sub {
248                           my ($url, $secret) = @_;
249                           require Digest::SHA2;
250
251                           my $ctx = Digest::SHA2->new();
252                           $ctx->add($url . $secret);
253
254                           return $ctx->hexdigest;
255                       },
256                   );
257
258       disable
259           You can disable link checking entirely by setting "disable" to a
260           true value.  This can be useful when you are developing or
261           debugging the application and you want the ability to tweak URL
262           params without getting busted.
263
264   link
265       Create a link, and add a checksum to it.
266
267       You can add parameters to the link directly in the URL:
268
269           my $link = $self->link('/cgi-bin/app.cgi?var=value&var2=value2');
270
271       Or you can add them as a hash of parameters after the URL:
272
273           my $link = $self->link(
274               '/cgi-bin/app.cgi',
275               'param1'  => 'value',
276               'param2' => 'value2',
277           );
278
279   self_link
280       Make a link to the current application, with optional parameters, and
281       add a checksum to the URL.
282
283           my $link = $self->self_link(
284               'param1' => 'value1',
285               'param2' => 'value2',
286           );
287
288       "self_link" preserves the value of the current application's
289       "PATH_INFO".  For instance if the current URL is:
290
291           /cgi-bin/app.cgi/some/path?foo=bar # PATH_INFO is 'some/path'
292
293       Calling:
294
295           $self->self_link('bar' => 'baz');
296
297       Will produce the URL:
298
299           /cgi-bin/app.cgi/some/path?bar=baz
300
301       If you want to remove the "PATH_INFO" value or replace it with a new
302       value, use path_link.
303
304   path_link
305       Calling "path_link" is the same as calling "self_link", except the
306       current value of "PATH_INFO" can be replaced.
307
308           my $link = $self->path_link(
309               '/new/path',
310               'param1' => 'value1',
311               'param2' => 'value2',
312           );
313
314       For instance if the current URL is:
315
316           /cgi-bin/app.cgi/some/path?foo=bar # PATH_INFO is 'some/path'
317
318       Calling:
319
320           $self->path_link('/new/path');
321
322       Will produce the URL:
323
324           /cgi-bin/app.cgi/new/path?foo=bar
325
326       If you want to remove "PATH_INFO" entirely, call one of the following:
327
328           $self->path_link;
329           $self->path_link(undef, 'param1' => 'val1', 'param2 => 'val2' ...);
330           $self->path_link('', 'param1' => 'val1', 'param2 => 'val2' ...);
331
332       If you want to keep the existing "PATH_INFO" that was passed to the
333       current application, use self_link instead.
334

RUN MODES

336   The link_tampered Run Mode
337       Your application is redirected to this run mode when it has been
338       detected that the user has tampered with the link.  You can change the
339       name of this run mode by changing the value of the
340       "link_tampered_runmode" param to "link_integrity_config".
341
342       CGI::Application::Plugin::LinkIntegrity provides a default
343       "link_tampered" run mode, which just displays a page with some stern
344       warning text.
345
346       You can define your own as follows:
347
348           sub link_tampered {
349               my $self = shift;
350               my $template = $self->load_template('stern_talking_to');
351               return $template->output;
352           }
353

HOOKS

355       When a link is followed that doesn't match the checksum, the
356       "invalid_checksum" hook is called.  You can add a callback to this hook
357       to do some cleanup such as deleting the user's session.  For instance:
358
359           sub setup {
360               my $self = shift;
361               $self->add_callback('invalid_checksum' => \&bad_user);
362           }
363
364           sub bad_user {
365               my $self = shift;
366
367               # The user has been messing with the URLs, possibly trying to
368               # break into the system.  We don't tolerate this behaviour.
369               # So we delete the user's session:
370
371               $self->session->delete;
372           }
373

AUTHOR

375       Michael Graham, "<mag-perl@occamstoothbrush.com>"
376

ACKNOWLEDGEMENTS

378       This module was based on the checksum feature originally built into
379       Richard Dice's CGI::Application::Framework.
380

BUGS

382       Please report any bugs or feature requests to
383       "bug-cgi-application-plugin-linkintegrity@rt.cpan.org", or through the
384       web interface at <http://rt.cpan.org>.  I will be notified, and then
385       you'll automatically be notified of progress on your bug as I make
386       changes.
387
389       Copyright 2005 Michael Graham, All Rights Reserved.
390
391       This program is free software; you can redistribute it and/or modify it
392       under the same terms as Perl itself.
393
394
395
396perl v5.28.1                      201C9G-I0:2:-A0p2plication::Plugin::LinkIntegrity(3)
Impressum