| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package HTTPD::RealmDef; |
|
2
|
4
|
|
|
4
|
|
3595
|
use Carp; |
|
|
4
|
|
|
|
|
9
|
|
|
|
4
|
|
|
|
|
406
|
|
|
3
|
|
|
|
|
|
|
|
|
4
|
4
|
|
|
4
|
|
23
|
use strict; |
|
|
4
|
|
|
|
|
8
|
|
|
|
4
|
|
|
|
|
152
|
|
|
5
|
4
|
|
|
4
|
|
789
|
use HTTPD::RealmManager; |
|
|
4
|
|
|
|
|
8
|
|
|
|
4
|
|
|
|
|
247
|
|
|
6
|
4
|
|
|
4
|
|
21
|
use vars qw($VERSION); |
|
|
4
|
|
|
|
|
9
|
|
|
|
4
|
|
|
|
|
342
|
|
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
$VERSION = $HTTPD::Realm::VERSION = 1.52; |
|
9
|
|
|
|
|
|
|
|
|
10
|
4
|
|
|
4
|
|
7584
|
use overload '""'=>\&name; |
|
|
4
|
|
|
|
|
5384
|
|
|
|
4
|
|
|
|
|
40
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub new { |
|
13
|
12
|
|
|
12
|
|
21
|
my ($class,$name) = @_; |
|
14
|
12
|
|
|
|
|
57
|
return bless { 'name' => $name },$class; |
|
15
|
|
|
|
|
|
|
} |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
sub userdb { |
|
18
|
18
|
|
|
18
|
|
21
|
my $self = shift; |
|
19
|
18
|
|
33
|
|
|
150
|
return $self->{users} || $self->{userfile}; |
|
20
|
|
|
|
|
|
|
} |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub groupdb { |
|
23
|
10
|
|
|
10
|
|
15
|
my $self = shift; |
|
24
|
10
|
|
33
|
|
|
55
|
return $self->{groups} || $self->{groupfile}; |
|
25
|
|
|
|
|
|
|
} |
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# backwards compatability only |
|
28
|
0
|
|
|
0
|
|
0
|
sub userfile { return &userdb; } |
|
29
|
0
|
|
|
0
|
|
0
|
sub groupfile { return &groupdb; } |
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
sub mode { |
|
32
|
3
|
|
50
|
3
|
|
35
|
return shift->{mode} || 0644; |
|
33
|
|
|
|
|
|
|
} |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
sub database { |
|
36
|
1
|
|
50
|
1
|
|
20
|
return shift->{database} || "www\@localhost"; |
|
37
|
|
|
|
|
|
|
} |
|
38
|
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# |
|
40
|
|
|
|
|
|
|
# added by John Porter: |
|
41
|
|
|
|
|
|
|
# |
|
42
|
|
|
|
|
|
|
sub dblogin { |
|
43
|
1
|
|
|
1
|
|
3
|
return shift->{dblogin}; |
|
44
|
|
|
|
|
|
|
} |
|
45
|
|
|
|
|
|
|
sub dbpassword { |
|
46
|
1
|
|
|
1
|
|
4
|
return shift->{dbpassword}; |
|
47
|
|
|
|
|
|
|
} |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub fields { |
|
50
|
1
|
|
|
1
|
|
6
|
return shift->{fields}; |
|
51
|
|
|
|
|
|
|
} |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
sub usertype { |
|
54
|
18
|
|
|
18
|
|
23
|
my $self = shift; |
|
55
|
18
|
|
33
|
|
|
124
|
return $self->{usertype} || $self->{type}; |
|
56
|
|
|
|
|
|
|
} |
|
57
|
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
sub grouptype { |
|
59
|
5
|
|
|
5
|
|
10
|
my $self = shift; |
|
60
|
5
|
|
33
|
|
|
35
|
return $self->{grouptype} || $self->{type}; |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
sub authentication { |
|
64
|
10
|
|
100
|
10
|
|
84
|
return shift->{'authentication'} || 'Basic'; |
|
65
|
|
|
|
|
|
|
} |
|
66
|
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
sub driver { |
|
68
|
0
|
|
0
|
0
|
|
0
|
return shift->{'driver'} || 'mSQL'; |
|
69
|
|
|
|
|
|
|
} |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub server { |
|
72
|
4
|
|
50
|
4
|
|
43
|
return shift->{'server'} || 'apache'; |
|
73
|
|
|
|
|
|
|
} |
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
sub crypt { |
|
76
|
9
|
|
|
9
|
|
11
|
my $self = shift; |
|
77
|
9
|
50
|
|
|
|
647
|
return $self->{'crypt'} if $self->{'crypt'}; |
|
78
|
9
|
50
|
|
|
|
22
|
return 'crypt' if lc($self->authentication) eq 'basic'; |
|
79
|
0
|
0
|
|
|
|
0
|
return 'MD5' if lc($self->authentication) eq 'digest'; |
|
80
|
0
|
|
|
|
|
0
|
return 'crypt'; # default currently |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub name { |
|
84
|
185
|
|
|
185
|
|
699
|
return shift->{'name'}; |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# return a pointer to an associative array with mSQL info. |
|
88
|
|
|
|
|
|
|
# it will contain the keys: |
|
89
|
|
|
|
|
|
|
# host name of the database host |
|
90
|
|
|
|
|
|
|
# database name of the database |
|
91
|
|
|
|
|
|
|
# dblogin |
|
92
|
|
|
|
|
|
|
# dbpassword |
|
93
|
|
|
|
|
|
|
# usertable name of the table that user/passwd/other info is in |
|
94
|
|
|
|
|
|
|
# grouptable name of the table containing user/group pairs |
|
95
|
|
|
|
|
|
|
# userfield name of the user field (both tables) |
|
96
|
|
|
|
|
|
|
# groupuserfield |
|
97
|
|
|
|
|
|
|
# groupfield name of the group field (group table only) |
|
98
|
|
|
|
|
|
|
# passwdfield name of the password field (user table only) |
|
99
|
|
|
|
|
|
|
# userfield_len length of the user field |
|
100
|
|
|
|
|
|
|
# groupfield_len length of the group field |
|
101
|
|
|
|
|
|
|
# passwdfield_len length of the password field |
|
102
|
|
|
|
|
|
|
sub SQLdata { |
|
103
|
1
|
|
|
1
|
|
3
|
my $self = shift; |
|
104
|
1
|
50
|
|
|
|
5
|
return undef unless $self->usertype=~/sql/i; |
|
105
|
1
|
|
|
|
|
89
|
my ($u,$g) = ($self->split_parms($self->userdb),$self->split_parms($self->groupdb)); |
|
106
|
1
|
|
|
|
|
2
|
my %result; |
|
107
|
1
|
|
|
|
|
4
|
@result{qw(database host)} = split('@',$self->database); |
|
108
|
1
|
|
50
|
|
|
5
|
$result{host} ||= 'localhost'; |
|
109
|
|
|
|
|
|
|
# |
|
110
|
|
|
|
|
|
|
# Do what Lincoln didn't: |
|
111
|
1
|
|
|
|
|
5
|
$result{dblogin} = $self->dblogin; |
|
112
|
1
|
|
|
|
|
5
|
$result{dbpassword} = $self->dbpassword; |
|
113
|
|
|
|
|
|
|
# |
|
114
|
1
|
|
50
|
|
|
6
|
$result{usertable} = $u->{table} || 'users'; |
|
115
|
1
|
|
|
|
|
3
|
$result{grouptable} = $g->{table}; # no default |
|
116
|
1
|
|
50
|
|
|
7
|
$result{userfield} = $u->{uid} || $g->{uid} || 'users'; |
|
117
|
1
|
|
50
|
|
|
8
|
$result{groupuserfield} = $g->{uid} || $u->{uid} || 'users'; |
|
118
|
1
|
|
|
|
|
3
|
$result{groupfield} = $g->{group}; |
|
119
|
1
|
|
50
|
|
|
8
|
$result{passwdfield} = $u->{password} || 'password'; |
|
120
|
1
|
|
50
|
|
|
7
|
$result{userfield_len} = $u->{uid_len} || $u->{user_len} || 12; |
|
121
|
1
|
|
50
|
|
|
5
|
$result{groupfield_len} = $g->{group_len} || 20; |
|
122
|
1
|
|
33
|
|
|
11
|
$result{passwdfield_len}= $u->{password_len} || |
|
123
|
|
|
|
|
|
|
(lc($self->authentication) eq 'digest' ? 32 + 3 + length($self->name) + $result{userfield_len} : 13); |
|
124
|
1
|
|
|
|
|
9
|
return \%result; |
|
125
|
|
|
|
|
|
|
} |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
sub connect { |
|
128
|
3
|
|
|
3
|
|
6
|
my $self = shift; |
|
129
|
3
|
|
|
|
|
22
|
my ($writable,$mode,$server) = rearrange([[qw(WRITABLE WRITE MODIFY)],qw(MODE SERVER)],@_); |
|
130
|
3
|
|
33
|
|
|
27
|
return new HTTPD::RealmManager(-realm => $self, |
|
|
|
|
50
|
|
|
|
|
|
131
|
|
|
|
|
|
|
-writable => $writable, |
|
132
|
|
|
|
|
|
|
'-mode' => $mode || $self->mode, |
|
133
|
|
|
|
|
|
|
'-server' => $server || $self->server || 'apache'); |
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
# A utility routine |
|
137
|
|
|
|
|
|
|
sub split_parms { |
|
138
|
2
|
|
|
2
|
|
4
|
my($self,$j) = @_; |
|
139
|
2
|
|
|
|
|
33
|
my($junk,%p) = split(/\s*(\w+)=/,$j); |
|
140
|
2
|
|
|
|
|
9
|
foreach (keys %p) { |
|
141
|
6
|
|
|
|
|
20
|
$p{$_}=~s/^"//; |
|
142
|
6
|
|
|
|
|
17
|
$p{$_}=~s/"$//; |
|
143
|
6
|
100
|
|
|
|
26
|
if ($p{$_}=~/:[a-zA-Z]?(\d+)$/) { |
|
144
|
4
|
|
|
|
|
10
|
$p{$_}=$`; |
|
145
|
4
|
|
|
|
|
14
|
$p{"${_}_len"}=$1; |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
} |
|
148
|
2
|
|
|
|
|
9
|
\%p; |
|
149
|
|
|
|
|
|
|
} |
|
150
|
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
# ---------------------------------------------------------------------------------------- |
|
152
|
|
|
|
|
|
|
package HTTPD::Realm; |
|
153
|
|
|
|
|
|
|
|
|
154
|
4
|
|
|
4
|
|
4628
|
use strict; |
|
|
4
|
|
|
|
|
8
|
|
|
|
4
|
|
|
|
|
192
|
|
|
155
|
4
|
|
|
4
|
|
22
|
use HTTPD::RealmManager; |
|
|
4
|
|
|
|
|
8
|
|
|
|
4
|
|
|
|
|
274
|
|
|
156
|
4
|
|
|
4
|
|
24
|
use Carp; |
|
|
4
|
|
|
|
|
8
|
|
|
|
4
|
|
|
|
|
4775
|
|
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
*dbm = \&connect; |
|
159
|
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
my %CACHE; |
|
161
|
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
my %VALID_DIRECTIVES = ( |
|
163
|
|
|
|
|
|
|
'dblogin' =>1, |
|
164
|
|
|
|
|
|
|
'dbpassword' =>1, |
|
165
|
|
|
|
|
|
|
'users' =>1, # file or table of user/passwd info |
|
166
|
|
|
|
|
|
|
'groups' =>1, # file or table of user/group info |
|
167
|
|
|
|
|
|
|
'database' =>1, # database name (SQL only) |
|
168
|
|
|
|
|
|
|
'fields' =>1, # other fields (SQL only) |
|
169
|
|
|
|
|
|
|
'type' =>1, # db type (text|NDBM|DB|mSQL|SQL) |
|
170
|
|
|
|
|
|
|
'driver' =>1, # SQL db driver type [mSQL] |
|
171
|
|
|
|
|
|
|
'usertype' =>1, # override db type for users only |
|
172
|
|
|
|
|
|
|
'grouptype' =>1, # override db type for groups only |
|
173
|
|
|
|
|
|
|
'default' =>1, # set default realm |
|
174
|
|
|
|
|
|
|
'authentication' =>1, # authentication scheme (Basic|Digest) |
|
175
|
|
|
|
|
|
|
'server' =>1, # server type (Apache|NCSA|Netscape) |
|
176
|
|
|
|
|
|
|
'mode' =>1, # mode for newly-created text & DBM files |
|
177
|
|
|
|
|
|
|
'crypt' =>1, # override encryption, backward compatability only |
|
178
|
|
|
|
|
|
|
'userfile' =>1, # synonyms for backward compatability only |
|
179
|
|
|
|
|
|
|
'groupfile' =>1, # synonyms for backward compatability only |
|
180
|
|
|
|
|
|
|
); |
|
181
|
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
# Security realm parsing utility -- high level interface to Doug MacEachern's |
|
183
|
|
|
|
|
|
|
# HTTPD utilities. |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# Pass the location of the configuration file. |
|
186
|
|
|
|
|
|
|
sub new { |
|
187
|
3
|
|
|
3
|
1
|
29
|
my $class = shift; |
|
188
|
3
|
|
|
|
|
24
|
my ($config_file) = rearrange([[qw(CONFIG CONFIG_FILE)]],@_); |
|
189
|
|
|
|
|
|
|
|
|
190
|
3
|
100
|
66
|
|
|
40
|
if ($CACHE{$config_file} && -C $config_file == $CACHE{$config_file}{ctime}) { |
|
191
|
1
|
|
|
|
|
5
|
return $CACHE{$config_file}{obj}; |
|
192
|
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
2
|
|
|
|
|
32
|
my $self = { config_file => $config_file, }; |
|
195
|
|
|
|
|
|
|
|
|
196
|
2
|
|
|
|
|
6
|
my($realm,$realm_name,$directive,$value,$default_realm,$first_realm); |
|
197
|
2
|
50
|
|
|
|
112
|
open(CONF,$config_file) || croak "Couldn't open $config_file: $!"; |
|
198
|
2
|
|
|
|
|
81
|
while () { |
|
199
|
94
|
|
|
|
|
111
|
chomp; |
|
200
|
94
|
|
|
|
|
120
|
s/\#.*$//; # get rid of all comments |
|
201
|
|
|
|
|
|
|
|
|
202
|
94
|
100
|
|
|
|
1687
|
if (//i) { |
|
203
|
12
|
50
|
|
|
|
29
|
croak "Syntax error in $config_file, line $.: Missing directive.\n" |
|
204
|
|
|
|
|
|
|
if $realm; |
|
205
|
12
|
50
|
|
|
|
34
|
croak "Syntax error in $config_file, line $.: directive without realm name.\n" |
|
206
|
|
|
|
|
|
|
unless $1; |
|
207
|
12
|
|
|
|
|
51
|
$realm = new HTTPD::RealmDef($realm_name = $1); |
|
208
|
12
|
100
|
|
|
|
30
|
$first_realm = $realm unless $first_realm; |
|
209
|
12
|
|
|
|
|
42
|
next; |
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
|
|
212
|
82
|
100
|
|
|
|
666
|
if (/<\/Realm\s*>/i) { |
|
213
|
12
|
50
|
|
|
|
23
|
croak "Syntax error in $config_file, line $.: seen without preceding directive.\n" |
|
214
|
|
|
|
|
|
|
unless $realm; |
|
215
|
12
|
50
|
33
|
|
|
32
|
croak "Incomplete definition for realm $realm. Need Users and Type directives at line $.\n" |
|
216
|
|
|
|
|
|
|
unless $realm->userdb && $realm->usertype; |
|
217
|
12
|
|
|
|
|
38
|
$self->{realms}->{$realm_name}=$realm; |
|
218
|
12
|
|
|
|
|
18
|
undef $realm; |
|
219
|
12
|
|
|
|
|
16
|
undef $realm_name; |
|
220
|
12
|
|
|
|
|
61
|
next; |
|
221
|
|
|
|
|
|
|
} |
|
222
|
|
|
|
|
|
|
|
|
223
|
70
|
100
|
|
|
|
525
|
next unless ($directive,$value) = /(\w+)\s*(.*)/; |
|
224
|
60
|
50
|
|
|
|
2922
|
croak "Syntax error in $config_file, line $.: $directive directive without preceding tag.\n" |
|
225
|
|
|
|
|
|
|
unless $realm; |
|
226
|
|
|
|
|
|
|
|
|
227
|
60
|
|
|
|
|
587
|
$directive=~tr/A-Z/a-z/; |
|
228
|
60
|
50
|
|
|
|
291
|
croak "Unknown directive \"$directive\" at line $.\n" |
|
229
|
|
|
|
|
|
|
unless $VALID_DIRECTIVES{$directive}; |
|
230
|
|
|
|
|
|
|
|
|
231
|
60
|
50
|
|
|
|
373
|
$realm->{$directive} = $directive =~ /file/ ? untaint($value) : $value; |
|
232
|
60
|
100
|
|
|
|
2006
|
if ($directive eq 'default') { |
|
233
|
2
|
50
|
|
|
|
7
|
croak "More than one Default directive defined at $config_file, line $.\n" |
|
234
|
|
|
|
|
|
|
if $default_realm; |
|
235
|
2
|
|
|
|
|
13
|
$default_realm = $realm_name; |
|
236
|
|
|
|
|
|
|
} |
|
237
|
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
} |
|
239
|
2
|
|
|
|
|
670
|
close CONF; |
|
240
|
|
|
|
|
|
|
|
|
241
|
2
|
|
33
|
|
|
11
|
$self->{default_realm}=$default_realm || $first_realm; |
|
242
|
2
|
|
|
|
|
8
|
bless $self,$class; |
|
243
|
2
|
|
|
|
|
48
|
$CACHE{$config_file}{ctime} = -C $config_file; |
|
244
|
2
|
|
|
|
|
12
|
return $CACHE{$config_file}{obj} = $self; |
|
245
|
|
|
|
|
|
|
} |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
sub connect { |
|
248
|
2
|
|
|
2
|
1
|
4
|
my $self = shift; |
|
249
|
2
|
|
|
|
|
12
|
my ($writable,$realm,$mode) = rearrange([[qw(WRITABLE WRITE MODIFY)],qw(REALM MODE)],@_); |
|
250
|
2
|
|
|
|
|
14
|
my $r = $self->realm($realm); |
|
251
|
2
|
50
|
|
|
|
7
|
die "Unknown realm $realm" unless ref($r); |
|
252
|
2
|
|
|
|
|
4
|
my(@p); |
|
253
|
2
|
100
|
|
|
|
8
|
push(@p,'-writable'=>$writable) if $writable; |
|
254
|
2
|
50
|
|
|
|
6
|
push(@p,'-mode'=>$mode) if $mode; |
|
255
|
2
|
|
|
|
|
9
|
return $r->connect(@p); |
|
256
|
|
|
|
|
|
|
} |
|
257
|
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
sub exists { |
|
259
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
260
|
0
|
|
|
|
|
0
|
my ($realm) = rearrange(['REALM'],@_); |
|
261
|
0
|
|
|
|
|
0
|
return defined($self->{realms}->{$realm}); |
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub list { |
|
265
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
|
266
|
0
|
|
|
|
|
0
|
return sort keys %{$self->{realms}}; |
|
|
0
|
|
|
|
|
0
|
|
|
267
|
|
|
|
|
|
|
} |
|
268
|
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
sub realm { |
|
270
|
6
|
|
|
6
|
1
|
23
|
my $self = shift; |
|
271
|
6
|
|
|
|
|
28
|
my ($realm) = rearrange(['REALM'],@_); |
|
272
|
6
|
|
33
|
|
|
21
|
$realm ||= $self->{default_realm}; |
|
273
|
6
|
|
|
|
|
26
|
return $self->{realms}->{$realm}; |
|
274
|
|
|
|
|
|
|
} |
|
275
|
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
sub untaint { |
|
277
|
0
|
|
|
0
|
0
|
|
my $taint = shift; |
|
278
|
0
|
0
|
0
|
|
|
|
croak('Relative paths are not allowed in password and/or group file definitions') |
|
279
|
|
|
|
|
|
|
if $taint =~ /\.\./ or $taint !~ m|^/|; |
|
280
|
0
|
|
|
|
|
|
$taint =~ m!(/[a-zA-Z/0-9._-]+)!; |
|
281
|
0
|
|
|
|
|
|
return $1; |
|
282
|
|
|
|
|
|
|
} |
|
283
|
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
sub DESTROY { |
|
285
|
0
|
|
|
0
|
|
|
my $self = shift; |
|
286
|
|
|
|
|
|
|
} |
|
287
|
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
1; |
|
290
|
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
__END__ |