#!/usr/bin/perl
#
# OGIHARA Hirotaka	2012.02.25
#
# Thanks for Morikawa and Kyoma's imappwdbg.

#
# dovecotpwdbg -  dovecot(imap)'s password making script
#
# このスクリプトは~Maildir/.passwd からパスワードを取り出して
# /etc/dovecot.cram-md5 に書き込むスクリプト.
#  user 情報はpasswd ファイルから持ってくる. 
# それがuserかどうかはgate-user-showで確かめる. よって, 書きこまれるのは
# gate に登録している人だけ.

    # 必要な外部コマンドの取得
$chmodbin = '/bin/chmod';
$usershow = '/usr/local/bin/gate-user-show';
$dovecotpw = '/usr/sbin/dovecotpw';

    # パスワードファイルとuserのパスワードファイルの取得
$dovecotpwd = '/etc/dovecot.cram-md5';
$userpwfile = 'Maildir/.password';


    # dovecot.cram-md5 に書き込む権限を与える.
system "$chmodbin 600 $dovecotpwd";

    # dovecot.cram-md5 に書き込む準備
open (DBFILE,"> $dovecotpwd");

    # dovecot.cram-md5 のコメント文.
print DBFILE '# CRAM-MD5 authentication database',"\n";
print DBFILE '# Entries are in form <user>:{plain}<password>:<uid>:<gid>::<Home dir>',"\n";
print DBFILE '# or <user>:{CRAM-MD5}<cram_md5 password>:<uid>:<gid>::<Home dir>',"\n";
print DBFILE '# Lines starting with "#" are comments',"\n";
print DBFILE "\n";

while (($user,$passwd,$uid,$gid,$quota,$comm,$gcos,$dir,$shell) = getpwent) {
    #
    # getpwent で user の情報をそれぞれの変数に格納していく
    # uid が1000より大きく29999以下のときに書き込む
    if ( $uid >= 1000 && $uid <= 29999 ) {
	open(PWFILE,"< $dir/$userpwfile");
	$pass = '';
	$pass = $_ while(<PWFILE>);
	chop($pass);
	close(PWFILE);
	if($pass ne '') {
	$passescape = $pass;
	#パスワードの末尾の\のエスケープ
	&escape;
	  # パスワードをCRAM-MD5の形式に変更する(plainでも良いがよりセキュリティを上げるため)
#        $crampass = system "$dovecotpw -s CRAM-MD5 -p $pass";
        $crampass =`$dovecotpw -s CRAM-MD5 -p "$passescape"`;
        # 改行が入るので改行を消す
        chomp ($crampass);
	    #
	    # gate-user-show で user かを確認する
	    #
	    #
	    unless (-x $usershow) {
		die "dovecot.cram-md5 require $usershow\.\n"
		    ."Please install gate-toroku-system\.\n";
	    }
              # gate-user-showのコマンドの入力を取得
	    open (GATEUS,"$usershow $user |");
              # typeだけ取り出し
	    while (<GATEUS>) { 
		if (/type/) { ($typeq) = /type: (.*)/; } 
	    }
	    close (GATEUS);
	    #
	    # type: person のときにdovecot.cram-md5 に書き込む
	    #
	    if ( $typeq eq 'person' ) {
		print DBFILE $user;
#		print DBFILE ":{plain}";
		print DBFILE ":";
		print DBFILE $crampass;
#		print DBFILE $pass;
                print DBFILE ":";
                print DBFILE $uid;
                print DBFILE ":";
                print DBFILE $gid;
                print DBFILE "::";
                print DBFILE $dir;
		print DBFILE "\n";
	    }
	}
    }
}

close (DBFILE);

    # dovecot.cram-md5 のパーミッションを戻す
system "$chmodbin 400 $dovecotpwd";
#パスワードに\が入っている場合\を足してエスケープするサブルーチン
sub escape{
       my $var = 1;
       my $passchar = substr($passescape,-1,$var);
	#末尾の文字を検索して\なら$varを１足す
       while ($passchar eq "\\"){
       	$var = $var + 1;
       	$passchar = substr($passescape, -$var,1);
       }
	#$varの数になるまで\\を追加していく
       for ($i=1;$i<$var;$i++){
       	$passescape = $passescape . "\\";
       }
}
