File Coverage

blib/lib/LWP/Auth_UA.pm
Criterion Covered Total %
statement 36 36 100.0
branch 11 14 78.5
condition 2 3 66.6
subroutine 6 6 100.0
pod 1 3 33.3
total 56 62 90.3


line stmt bran cond sub pod time code
1             package LWP::Auth_UA;
2             $REVISION=q$Revision: 1.5 $ ; $VERSION = sprintf ( "%d.%02d", $REVISION =~ /(\d+).(\d+)/ );
3 2     2   174541 use LWP::UserAgent;
  2         151861  
  2         86  
4             @ISA=qw(LWP::UserAgent);
5              
6 2     2   21 use strict;
  2         3  
  2         59  
7 2     2   10 use warnings;
  2         6  
  2         571  
8              
9             =head1 NAME
10              
11             LWP::Auth_UA.pm - a user agent which knows some authorisation tokens
12              
13             =head1 SYNOPSIS
14              
15             use LWP::Auth_UA.pm
16             credentials ( {
17             my_realm => { uri_re => "https://myhost.example.com",
18             credential => "my_secret" }
19             } );
20              
21             $ua = LWP::Auth_UA->new;
22             $request = HTTP::Request->new('GET', 'file://localhost/etc/motd');
23             $response = $ua->request($request);
24             etc...
25              
26             =head1 DESCRIPTION
27              
28             This is a LWP user agent which is almost identical to the normal user
29             agent (LWP::UserAgent) except that if it reaches a situation where it
30             needs an authentication token then it will send a token which it has
31             stored.
32              
33             Storing authentication tokens in a file is inherently a security
34             issue. This risk may, however, not be much higher than the one that
35             you are currently carrying, so this can be useful.
36              
37             This page describes how this works and how to ensure that the security
38             risks you are taking on are not greater than are acceptable to you.
39              
40             As with the rest of LinkController, there is no warantee. If you have
41             an environment in which this might be a problem, you should definitely
42             find someone to look over your installation and ensure that everything
43             is done correctly. Of course, this is true of every piece of software
44             you install.
45              
46             =head1 SECURITY RISKS
47              
48             The fundamental security problem with this system is that the
49             authentication token must be stored somewhere where the program can
50             access it. This is because link-controller has to send the actual
51             authentication token over the link to authenticate. Since it's very
52             easy to monitor the inputs and outputs of a program, it's very easy to
53             monitor this password.
54              
55             This applies even if we keep the password in some encrypted form,
56             since we then have to store the decryption key in the program which
57             can then be found and used to decrypt the key.
58              
59             So there are only two possible defenses:
60              
61             =over 4
62              
63             =item *
64              
65             make sure that the program data remains secret
66              
67             =item *
68              
69             make sure that the passwords the program has can't do any real damage
70              
71             =back
72              
73             We demand permissions on our files which protect against accidental
74             disclosure by encouraging the user to be more secure.
75              
76             Making sure that the program can't do any damage is normally achieved
77             by giving it a dedicated account which has only read only privilages
78             and, preferably, can only use it's privilages from a specified system
79             which will be the host on which the link checking is run.
80              
81             =head2 Accidental Sending of Tokens
82              
83             Another authentication risk is that the system will send it to a
84             server which is trying to trick it. This is again difficult to
85             protect against. The only solution in this case is to ensure that the
86             regular expression used for limiting the URI matches only host names
87             which are under the control of the body responsible for handing out
88             the authentication token.
89              
90             The security of this system is not of course perfect. If we can
91             pretend to be the host that we are meant to send the authentication
92             token to then we will can trick the user agent into sending the token.
93             Remember that the hostname being used is the one in the URL we are
94             trying to examine, so the protection against this is having a secure
95             and correct DNS system and ensuring that we have a secure IP
96             connection to the end host.
97              
98             =head2 Sending of Tokens over Insecure protocols
99              
100             If an insecure protocol like HTTP is used for sending an
101             authentication token, then it is possible for someone to listen to the
102             transaction and record the token for later use.
103              
104             The protection against this is to switch over to only using secure
105             protocols and hard wire the protocol name into the URI regular expression.
106              
107             =cut
108              
109             sub get_basic_credentials {
110 4     4 1 353889 my $self=shift;
111 4         8 my $realm=shift;
112 4         6 my $uri=shift;
113 4         6 my $proxy=shift;
114 4         8 my $credentials=$self->{"Auth_UA-credentials"};
115 4 100       15 return undef unless defined $credentials;
116 3         5 my $rec=$credentials->{$realm};
117 3 100       9 return undef unless defined $rec;
118 2         4 my $re=$rec->{uri_re};
119 2 100       24 return undef unless $uri =~ m/$re/;
120 1         5 return $rec->{credential}
121             }
122              
123             sub auth_ua_credentials {
124 1     1 0 4595 my $self=shift;
125 1 50       7 return $self->{"Auth_UA-credentials"} unless @_;
126 1         3 my $cred=shift;
127 1         3 $self->{"Auth_UA-credentials"} = $cred;
128 1         3 return $cred;
129             }
130              
131             sub delete_brain_dead_credentials {
132 1     1 0 20 my $self=shift;
133 1         2 my $cred=shift;
134 1 50       5 $cred=$self->{"Auth_UA-credentials"} unless defined $cred;
135 1 50       4 return undef unless defined $cred;
136 1         6 foreach my $key ( keys %$cred ) {
137 2         5 my $rec=$cred->{$key};
138 2         4 my $re=$rec->{uri_re};
139             ( "http://3133t3hax0rs.rhere.com" =~ m/$re/
140             or "http://3133t3hax0rs.rhere.com/secretstuff/www.goodplace.com/" =~ m/$re/ )
141 2 100 66     56 and do {
142 1         16 warn "Deleting credential with dangerous URI RE $re in Auth_UE for real $key";
143 1         9 delete $cred->{$key};
144             };
145             }
146 1         4 return $cred;
147             }
148              
149              
150             # sub aua_load_credentials {
151             # my $self=shift;
152             # my $file=$self->{Auth_UA-authfile};
153             # open my $cred, $file;
154             # while ( <$cred> ) {
155             # my ($realm, $auth, $uri_re) = m/
156             # };
157             # }
158              
159             # sub aua_authfile {
160             # my $self=shift;
161             # return $self->{Auth_UA-authfile} unless @_;
162             # $self->{Auth_UA-authfile} = shift;
163             # }