#!/usr/bin/perl
#
# OGIHARA Hirotaka	2012.02.25
#
# Thanks for Morikawa and Kyoma's imappwdbg.
#
# NAKAMOTO Jumpei 2013.12.27 
# TADA Naohiro    2014.05.09 修正
# dovecotpw の代わりに doveadm を使うように変更

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

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

# パスワードファイルと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"`;
      $crampass = `$doveadm pw -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";
system "$chownbin dovecot:dovecot $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 . "\\";
  }
}
