#!/usr/bin/php
<?php
###################################################################
# Migration script to migrate your gosa.conf
# from mcrypt to openssl.
#
# If you already updated to openssl don't execute
# this script again!
# Your GOsa² installation will become unusable and you need
# to revert the passwords manually.
# 
# On new installations you don't need to execute this script.
# Password encryption is done by gosa-encrypt-passwords
###################################################################


function cred_encrypt($input, $password, $cipher = "aes-256-ecb") {
  if (in_array($cipher, openssl_get_cipher_methods())) {
    $ivlen = openssl_cipher_iv_length($cipher);
    $iv = openssl_random_pseudo_bytes($ivlen);
    return bin2hex(openssl_encrypt($input, $cipher, $password, OPENSSL_RAW_DATA, $iv));
  }

  return null;
}

function cred_decrypt($input, $password) {
  $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
  $iv = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
  return rtrim(@openssl_decrypt( pack("H*", $input), "aes-256-ecb" , $password, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv ), "\0\3\4\n");
}


# We need to have access to gosa.secrets
if (posix_getuid() != 0){
  die ("This program needs to be called by root!\n");
}

# Do we have a valid gosa.conf?
if (!file_exists("/etc/gosa/gosa.conf")){
  die ("Cannot find a valid /etc/gosa/gosa.conf!\n");
}

echo "Starting password encryption update\n";
echo "* read master key from gosa.secrets\n";
$master_key="";

# Do we have a valid gosa.secrets, already? 
if (!file_exists("/etc/gosa/gosa.secrets")){
  die ("There's no /etc/gosa/gosa.secrets. No need to update passwords\n");
} else {
  echo "* open /etc/gosa/gosa.secrets\n";
  $content = file_get_contents("/etc/gosa/gosa.secrets");
  $pos = strpos($content, "GOSAKEY");

  if($pos !== NULL) {
    $master_key = trim(substr($content, $pos + strlen("GOSAKEY")));
  } else {
    die ("/etc/gosa/gosa.secrets maulformed\n");
  }
}

# Locate all passwords inside the gosa.conf
echo "* loading /etc/gosa/gosa.conf\n";
$conf = new DOMDocument();
$conf->load("/etc/gosa/gosa.conf") or die ("Cannot read /etc/gosa/gosa.conf - aborted\n");
$conf->encoding = 'UTF-8';
$referrals= $conf->getElementsByTagName("referral");
foreach($referrals as $referral){
  $user = $referral->attributes->getNamedItem("adminDn");
  echo "* encrypting GOsa password for: ".$user->nodeValue."\n";
  $pw= $referral->attributes->getNamedItem("adminPassword");
  $encryptedSecret = cred_encrypt(cred_decrypt($pw->nodeValue, $master_key), $master_key);

  if($encryptedSecret !== NULL) {
    $pw->nodeValue = $encryptedSecret;
  }
}

# Encrypt the snapshot passwords 
$locations= $conf->getElementsByTagName("location");
foreach($locations as $location){
  $name = $location->attributes->getNamedItem("name"); 
  $node = $location->attributes->getNamedItem("snapshotAdminPassword"); 
  if($node->nodeValue){
    echo "* encrypting snapshot pasword for location: ".$name->nodeValue."\n";
    $encryptedSecret = cred_encrypt(cred_decrypt($node->nodeValue, $master_key), $master_key);
    if($encryptedSecret !== NULL) {
      $node->nodeValue = $encryptedSecret;
    }
  }
}

# Move original gosa.conf out of the way and make it unreadable for the web user
echo "* creating backup in /etc/gosa/gosa.conf.orig\n";
rename("/etc/gosa/gosa.conf", "/etc/gosa/gosa.conf.orig");
chmod("/etc/gosa/gosa.conf.orig", 0600);
chown ("/etc/gosa/gosa.conf.orig", "root");
chgrp ("/etc/gosa/gosa.conf.orig", "root");

# Save new passwords
echo "* saving modified /etc/gosa/gosa.conf\n";
$conf->save("/etc/gosa/gosa.conf") or die("Cannot write modified /etc/gosa/gosa.conf - aborted\n");
chmod("/etc/gosa/gosa.conf", 0640);
chown ("/etc/gosa/gosa.conf", "root");
chgrp ("/etc/gosa/gosa.conf", "www-data");
echo "OK\n\n";

?>
