2 # Functions for reading and writing a .htpasswd format file
3 # XXX md5 and old password
5 BEGIN { push(@INC, ".."); };
9 %access = &get_module_acl();
12 $htdigest_command = &has_command("htdigest") || &has_command("htdigest2");
15 # Returns an array of user and password details from the given file
18 local $file = $_[0] || $config{'file'};
19 if (!defined($list_authusers_cache{$file})) {
20 $list_authusers_cache{$file} = [ ];
24 open(HTPASSWD, $file);
26 if (/^(#?)\s*([^:]+):(\S*)/) {
27 push(@{$list_authusers_cache{$file}},
33 'index' => $count++ });
39 return $list_authusers_cache{$file};
42 # list_digest_users([file])
43 # Returns an array of user, domain and password details from the given file
46 local $file = $_[0] || $config{'file'};
47 if (!defined($list_authusers_cache{$file})) {
48 $list_authusers_cache{$file} = [ ];
52 open(HTPASSWD, $file);
54 if (/^(#?)\s*(\S+):(\S+):(\S*)/) {
55 push(@{$list_authusers_cache{$file}},
63 'index' => $count++ });
69 return $list_authusers_cache{$file};
75 local $lref = &read_file_lines($_[0]->{'file'});
76 if ($_[0]->{'digest'}) {
77 $lref->[$_[0]->{'line'}] = ($_[0]->{'enabled'} ? "" : "#").
78 "$_[0]->{'user'}:$_[0]->{'dom'}:$_[0]->{'pass'}";
81 $lref->[$_[0]->{'line'}] = ($_[0]->{'enabled'} ? "" : "#").
82 "$_[0]->{'user'}:$_[0]->{'pass'}";
84 &flush_file_lines($_[0]->{'file'});
87 # create_user(&user, [file])
90 $_[0]->{'file'} = $_[1] || $config{'file'};
91 local $lref = &read_file_lines($_[0]->{'file'});
92 $_[0]->{'line'} = @$lref;
93 if ($_[0]->{'digest'}) {
94 push(@$lref, ($_[0]->{'enabled'} ? "" : "#").
95 "$_[0]->{'user'}:$_[0]->{'dom'}:$_[0]->{'pass'}");
98 push(@$lref, ($_[0]->{'enabled'} ? "" : "#").
99 "$_[0]->{'user'}:$_[0]->{'pass'}");
101 &flush_file_lines($_[0]->{'file'});
102 $_[0]->{'index'} = @{$list_authusers_cache{$_[0]->{'file'}}};
103 push(@{$list_authusers_cache{$_[0]->{'file'}}}, $_[0]);
109 local $lref = &read_file_lines($_[0]->{'file'});
110 splice(@$lref, $_[0]->{'line'}, 1);
111 &flush_file_lines($_[0]->{'file'});
112 splice(@{$list_authusers_cache{$_[0]->{'file'}}}, $_[0]->{'index'}, 1);
113 map { $_->{'line'}-- if ($_->{'line'} > $_[0]->{'line'}) }
114 @{$list_authusers_cache{$_[0]->{'file'}}};
117 # encrypt_password(string, [old], md5mode)
123 return &encrypt_md5($_[0], $_[1]);
127 return &encrypt_sha1($_[0]);
131 return &digest_password(undef, undef, $_[0]);
135 if ($gconfig{'os_type'} eq 'windows' && &has_command("htpasswd")) {
136 # Call htpasswd program
137 local $qp = quotemeta($_[0]);
138 local $out = `htpasswd -n -b foo $qp 2>&1 <$null_file`;
139 if ($out =~ /^foo:(\S+)/) {
143 &error("htpasswd failed : $out");
147 # Use built-in encryption code
148 local $salt = $_[1] ||
149 chr(int(rand(26))+65).chr(int(rand(26))+65);
150 return &unix_crypt($_[0], $salt);
155 # digest_password(user, realm, pass)
156 # Encrypts a password in the format used by htdigest
159 local ($user, $dom, $pass) = @_;
160 local $temp = &tempname();
161 eval "use Digest::MD5";
163 # Use the digest::MD5 module to do the encryption directly
164 return Digest::MD5::md5_hex("$user:$dom:$pass");
167 # Shell out to htdigest command
168 &foreign_require("proc", "proc-lib.pl");
169 local ($fh, $fpid) = &proc::pty_process_exec("$htdigest_command -c $temp ".quotemeta($dom)." ".quotemeta($user));
170 &wait_for($fh, "password:");
171 &sysprint($fh, "$pass\n");
172 &wait_for($fh, "password:");
173 &sysprint($fh, "$pass\n");
176 local $tempusers = &list_digest_users($temp);
178 return $tempusers->[0]->{'pass'};
183 # Returns an array of group details from the given file
187 if (!defined($list_authgroups_cache{$file})) {
188 $list_authgroups_cache{$file} = [ ];
192 open(HTPASSWD, $file);
194 if (/^(#?)\s*(\S+):\s*(.*)/) {
195 push(@{$list_authgroups_cache{$file}},
198 'members' => [ split(/\s+/, $3) ],
201 'index' => $count++ });
207 return $list_authgroups_cache{$file};
210 # modify_group(&group)
213 local $lref = &read_file_lines($_[0]->{'file'});
214 $lref->[$_[0]->{'line'}] = ($_[0]->{'enabled'} ? "" : "#").
215 "$_[0]->{'group'}: ".
216 join(" ", @{$_[0]->{'members'}});
220 # create_group(&group, [file])
223 $_[0]->{'file'} = $_[1] || $config{'file'};
224 local $lref = &read_file_lines($_[0]->{'file'});
225 $_[0]->{'line'} = @$lref;
226 push(@$lref, ($_[0]->{'enabled'} ? "" : "#").
227 "$_[0]->{'group'}: ".
228 join(" ", @{$_[0]->{'members'}}));
230 $_[0]->{'index'} = @{$list_authgroups_cache{$_[0]->{'file'}}};
231 push(@{$list_authgroups_cache{$_[0]->{'file'}}}, $_[0]);
234 # delete_group(&group)
237 local $lref = &read_file_lines($_[0]->{'file'});
238 splice(@$lref, $_[0]->{'line'}, 1);
240 splice(@{$list_authgroups_cache{$_[0]->{'file'}}}, $_[0]->{'index'}, 1);
241 map { $_->{'line'}-- if ($_->{'line'} > $_[0]->{'line'}) }
242 @{$list_authgroups_cache{$_[0]->{'file'}}};