#!/usr/local/bin/perl
# PASSWORDを再発行します
# 詳細 → http://ahox.jp/doc/basic_auth.html
use strict;
use warnings;
use utf8;
use CGI;
use Fcntl ':flock';
use String::Random;
use Carp;
print "Content-Type: text/html\n\n";
binmode(STDOUT, ":utf8");
# htpasswdの機能とおなじの。
sub htpasswd {
my ($pass)=@_;
my $s = new String::Random;
$s->{'A'} = ['A'..'Z', 'a'..'z', '0'..'9', '.', '/'];
my $salt = $s->randpattern('AA');
return crypt($pass,$salt);
}
# 設定項目
my $sendmail = '/usr/sbin/sendmail'; # Sendmailのパス
my $mail_from = 'sample@hogehoge.net'; # 管理者のメールアドレス
my $site_domain = 'hogehoge.net'; # サイトのドメイン
my $site_address = 'http://hogehoge.net/basic_auth/'; # サイトのURL
my $file = "data/user_list.txt"; # ユーザーリストの設定ファイル(改行コードLF,文字コードUTF8のTAB区切りファイル。設定項目は[MAIL,ID,PASSWORD]。(PASSWORDは更新したら上書きされる))
my $filelist = "data/access_list.txt"; # 設定を書き込むhtpasswdファイルのリスト(改行コードLF,文字コードUTF8)
# 変数初期化
my $msg = "";
my $mail_rx =q{(?:[-!#-'*+/-9=?A-Z^-~]+(?:\.[-!#-'*+/-9=?A-Z^-~]+)*|"(?:[!} .
q{#-\[\]-~]|\\\\[\x09 -~])*")@[-!#-'*+/-9=?A-Z^-~]+(?:\.[-!#-'*+/-9=?A-Z^-~]+)*};
my $string_random = new String::Random;
$string_random->{'A'} = ['A'..'Z', 'a'..'z', '0'..'9'];
my $q = new CGI;
my $mail = $q->param('mail');
# メアド判定
if($mail){
if($mail =~ /$mail_rx/){
# メールアドレスが登録されているか検索する。
my $flag = 0; # 登録されていれば1になる
my $id; # ID
my $pass; # PASSWORD
my $htpass; # PASSWORDのハッシュ
# ユーザーリストと照合
open my $fh, "+<", $file or die "$!:$file";
flock $fh, LOCK_EX;
my @dat = <$fh>; # 読み込みデータ
my @dat2 = (); # 新規データ
foreach (@dat){
chomp;
my ($m,$i,$p) = split(/\t/,$_);
if($m eq $mail){
# 一致
$flag = 1;
$mail = $m;
$id = $i;
$pass = $string_random->randpattern('AAAAAAAA'); # 新しいパスワードをランダムに生成
$htpass = htpasswd($pass);
push(@dat2,join("\t",$mail,$id,$htpass));
}else{
# 不一致
push(@dat2,$_);
}
}
# 一致するものがあった場合はファイルを更新
if($flag){
seek $fh, 0, 0;
print $fh join("\n",@dat2);
}
close $fh;
# 一致するものがあった場合はhtpasswdファイルをすべて更新し、メールを送信。
if($flag){
# htpasswdファイルの内容を生成
my $htstr = "";
foreach(@dat2){
chomp;
my ($m,$i,$p) = split(/\t/,$_);
$htstr .= "$i:$p\n";
}
# すべてのhtpasswdファイルを更新
open my $fh, "<", $filelist or die "$!:$filelist"; # htpasswdのファイルリストを読込
while(<$fh>){
chomp;
open my $htpass_fh, ">", $_ or die "$!:$_";
flock $htpass_fh, LOCK_EX;
print $htpass_fh $htstr;
close $htpass_fh;
}
close $fh;
# メール送信
open(SDML,"| $sendmail -t -i") || die 'sendmail error';
print SDML "From: ${mail_from}\nTo: ${mail}\nSubject: Change Your Password at ${site_domain}\nContent-Transfer-Encoding: 7bit\nContent-Type: text/plain;\n\nID: ${id}\nPASS: ${pass}\n\nURL:${site_address}\n\n";
close(SDML);
$msg = "新しいID・パスワードをメールで送信しました。";
}else{
$msg = "メールアドレスが登録されていません。";
}
}else{
$msg = "メールアドレスの形式がへんです。";
}
}else{
$msg = "メールアドレスが入力されてないですよ。";
}
print <<"EOF";
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>PASSWORD再発行</title>
</head>
<body>
$msg
</body>
</html>
EOF