File Coverage

blib/lib/SF/SF_form_secure.pm
Criterion Covered Total %
statement 47 114 41.2
branch 18 64 28.1
condition 13 64 20.3
subroutine 9 10 90.0
pod 0 6 0.0
total 87 258 33.7


line stmt bran cond sub pod time code
1             package SF_form_secure;
2            
3             delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
4 1     1   1013 use strict;
  1         3  
  1         52  
5 1     1   6 use warnings;
  1         2  
  1         43  
6 1     1   974 use Digest::SHA1 qw(sha1_hex);
  1         2906  
  1         99  
7 1     1   86 use vars qw($VERSION %x_error $exp2);
  1         3  
  1         2481  
8            
9             $VERSION = '4.0';
10            
11             # Error List
12             %x_error = (
13             a => 'Referer and Query String match.',
14             b => 'Referer is to long.',
15             c => 'Referer is not from HTTP Host.',
16             e => 'Referers do not Match.',
17             f => 'Bad code format.',
18             h => 'Code Has expired.',
19             i => 'Encoding is bad.'
20             );
21            
22             our $code = '';
23             our $exp = '';
24             our $ip_ct = '';
25            
26             # Main Function
27             sub x_secure {
28 2     2 0 114 my ($act, $link, $ref) = @_;
29 2         10 my $ip;
30            
31 2 50       9 if (!$link) {
32 0         0 $link = '';
33             }
34             # bound code to remote ip
35 2 50       10 $ip_ct eq 'ip'
36             ? $ip = $ENV{REMOTE_ADDR}
37             : $ip = '';
38            
39             # ------------------------------------------------------------------------------
40             # return secure link (makes secure link)
41             # ------------------------------------------------------------------------------
42 2 50 33     40 if ($act eq 1 && $link && $code) {
    50 33        
    50 33        
    100 33        
    50 66        
      33        
      33        
43             # Allow experation times 1 up to 99 minutes
44 0         0 $exp2 = x_time_cal($exp);
45 0         0 my $security_key = x_code_maker($code, $exp2, $link, $ip);
46 0         0 $security_key = $link . ';Flex=' . $security_key . '|' . $exp2;
47 0         0 return $security_key;
48             }
49             elsif ($act eq 2 && $code) {
50             # ------------------------------------------------------------------------------
51             # return 1 for good link or error text if bad.
52             # ------------------------------------------------------------------------------
53            
54             # Get Referer and link Query String
55 0   0     0 my $REF = $ENV{'HTTP_REFERER'} || '';
56 0   0     0 my $QRY = $ENV{'QUERY_STRING'} || '';
57 0         0 my $ref2 = x_regex($REF);
58            
59 0 0 0     0 if ($link =~ m!^(1|3)$!i || $ref) {
60 0   0     0 my $host_name = $ENV{'HTTP_HOST'} || '';
61             # Security issue 1
62 0 0       0 if ($ref2 eq $QRY) {
63 0         0 return $x_error{a};
64             }
65             # Security issue 2
66 0 0       0 if (length($REF) > 1024) {
67 0         0 return $x_error{b};
68             }
69             # Security issue 3
70 0 0       0 if ($REF !~ m!^(http|https)\:\/\/$host_name((.*?)+)$!i) {
71 0         0 return $x_error{c};
72             }
73             }
74            
75             # get referer codes
76 0         0 $REF =~ s/\;Flex\=(.+?)\|(.+?)$//;
77 0         0 my $ref_code = $1;
78 0         0 my $ref_date = $2;
79            
80             # Mach Referer with one given.
81 0 0 0     0 if ($ref && $ref ne $REF) {
82 0         0 return $x_error{e};
83             }
84            
85             # check the Referer code and/or date.
86 0 0 0     0 if ($link == 1 || $link == 3) {
87            
88             # Check input integrity
89 0         0 my $ref_input = x_bad_input($ref_code, $ref_date);
90 0 0       0 if($ref_input) {
91 0         0 return $ref_input;
92             }
93             # page expires
94 0         0 my $expir = x_code_expires($exp, $ref_date);
95 0 0       0 if ($expir) {
96 0         0 return $expir;
97             }
98            
99 0         0 $REF = x_regex($REF);
100 0         0 my $security_key = x_code_maker($code, $ref_date, $REF, $ip);
101 0 0       0 if ($security_key ne $ref_code) {
102 0         0 return $x_error{i};
103             }
104             }
105            
106             # check the query code and/or date.
107 0 0 0     0 if ($link == 2 || $link == 3) {
108            
109             # get query codes
110 0         0 $QRY =~ s/\;Flex\=(.*?)\|(.*?)$//;
111 0   0     0 my $qry_code = $1 || '';
112 0   0     0 my $qry_date = $2 || '';
113            
114             # Check input integrity
115 0         0 my $qry_input = x_bad_input($qry_code, $qry_date);
116 0 0       0 if($qry_input) {
117 0         0 return $qry_input;
118             }
119             # page expires
120 0         0 my $expir = x_code_expires($exp, $qry_date);
121 0 0       0 if ($expir) {
122 0         0 return $expir;
123             }
124             # check the QUERY_STRING code.
125 0         0 my $security_key = x_code_maker($code, $qry_date, $QRY, $ip);
126 0 0       0 if ($security_key ne $qry_code) {
127 0         0 return $x_error{i};
128             }
129             }
130             # looks good to x_secure
131 0         0 return 1;
132             }
133             elsif ($act eq 3 && $code){
134             # ------------------------------------------------------------------------------
135             # Settup starting page
136             # ------------------------------------------------------------------------------
137             # Returns The Query String with Encoding to be used in a redirect.
138 0         0 my $QRY = $ENV{'QUERY_STRING'};
139 0 0 0     0 if ($QRY !~ m!;Flex=(.+?)$!i && $QRY eq $link) {
140 0         0 $exp2 = x_time_cal($exp);
141 0         0 my $security_key = x_code_maker($code, $exp2, $QRY, $ip);
142 0         0 $security_key = $QRY . ';Flex=' . $security_key . '|' . $exp2;
143 0         0 return $security_key;
144             }
145             }
146             elsif ($act eq 4 && $code) {
147             # ------------------------------------------------------------------------------
148             # Action 4 Returns an encoding for action 5 to check
149             # ------------------------------------------------------------------------------
150             # x_secure(4, extra_code, '');
151            
152 1         7 $exp2 = x_time_cal($exp);
153 1 50       6 if (!$link) {
154 0         0 $link = $exp2;
155             }
156 1         4 my $security_key = x_code_maker($code, $exp2, $link, $ip);
157 1         3 $security_key = $security_key . '|' . $exp2;
158 1         5 return $security_key;
159             }
160             elsif ($act eq 5 && $code && $ref) {
161             # ------------------------------------------------------------------------------
162             # Action 5 Checks an encoding action 4 makes
163             # ------------------------------------------------------------------------------
164             # x_secure(5, extra_code, match_code);
165            
166             # split the data
167 1         15 $ref =~ s/^(.*?)\|(.*?)$/$1/;
168 1         3 my $the_date = $2;
169             # Check input integrity
170 1         3 my $the_input = x_bad_input($ref, $the_date);
171 1 50       4 if($the_input) {
172 0         0 return $the_input;
173             }
174             # code expires
175 1         3 my $expir = x_code_expires($exp, $the_date);
176 1 50       4 if ($expir) {
177 0         0 return $expir;
178             }
179 1 50       2 if (!$link) {
180 0         0 $link = $the_date;
181             }
182            
183 1         3 my $security_key = x_code_maker($code, $the_date, $link, $ip);
184 1 50       7 $security_key ne $ref
185             ? return $x_error{i}
186             : return 1; # looks good to x_secure
187             }
188             else {
189 0         0 return $VERSION;
190             }
191             }
192            
193             sub x_code_expires {
194 1     1 0 2 my ($expdate,$datein) = @_;
195 1         2 my $date = time;
196 1 0 33     5 if ($expdate && $expdate =~ m!^([0-9]+)$!i && length($expdate) <= 2 && $datein < $date) {
      33        
      0        
197 0         0 return $x_error{h};
198             }
199             }
200            
201             sub x_regex {
202 0     0 0 0 my $regex = shift;
203 0         0 $regex =~ s/^(.*?)\?(.*?)$/$2/;
204 0         0 return $regex;
205             }
206            
207             sub x_bad_input {
208 1     1 0 1 my ($codein, $datein) = @_;
209 1 50       6 if($codein !~ m/^([0-9a-z]+)$/i) {
210 0         0 return $x_error{f};
211             }
212 1 50 33     6 if (length($codein) < 40 || length($codein) > 40) {
213 0         0 return $x_error{f};
214             }
215 1 50       5 if($datein !~ m!^([0-9]+)$!i) {
216 0         0 return $x_error{f};
217             }
218 1 50 33     7 if (length($datein) < 10 || length($datein) > 10) {
219 0         0 return $x_error{f};
220             }
221             }
222            
223             sub x_code_maker {
224 2     2 0 5 my ($codea, $datea, $QRYa, $ip_cta) = @_;
225 2         4 $codea = $codea . $datea . $ip_cta;
226 2         20 my $security_keya = sha1_hex($QRYa, $codea);
227 2         5 return $security_keya;
228             }
229            
230             sub x_time_cal {
231 1     1 0 3 my $limit = shift;
232             # Allow experation times 1 up to 99 minutes
233 1 50 33     8 if ($limit =~ m!^([0-9]+)$!i && length($limit) <= 2) {
234 0         0 $limit = 60 * $limit;
235 0         0 $limit = time + $limit;
236             }
237             else {
238             # No experation
239 1         9 $limit = time;
240             }
241 1         4 return $limit;
242             }
243            
244             1;
245             __END__