Code

Added support for master-key encrypted passwords in gosa.conf
authorcajus <cajus@594d385d-05f5-0310-b6e9-bd551577e9d8>
Mon, 5 May 2008 15:19:46 +0000 (15:19 +0000)
committercajus <cajus@594d385d-05f5-0310-b6e9-bd551577e9d8>
Mon, 5 May 2008 15:19:46 +0000 (15:19 +0000)
git-svn-id: https://oss.gonicus.de/repositories/gosa/branches/2.5@10767 594d385d-05f5-0310-b6e9-bd551577e9d8

bin/gosa-encrypt-passwords [new file with mode: 0755]
debian/README.debian
debian/changelog
include/class_config.inc
include/functions.inc

diff --git a/bin/gosa-encrypt-passwords b/bin/gosa-encrypt-passwords
new file mode 100755 (executable)
index 0000000..0f8c5ad
--- /dev/null
@@ -0,0 +1,114 @@
+#!/usr/bin/php
+<?php
+
+function cred_encrypt($input, $password) {
+
+  $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
+  $iv = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
+
+  return bin2hex(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $password, $input, MCRYPT_MODE_ECB, $iv));
+}
+
+
+function get_random_char() {
+  $randno = rand (0, 63);
+  if ($randno < 12) {
+    return (chr ($randno + 46)); // Digits, '/' and '.'
+  } else if ($randno < 38) {
+    return (chr ($randno + 53)); // Uppercase
+  } else {
+    return (chr ($randno + 59)); // Lowercase
+  }
+}
+
+
+function get_random_string($size= 32){
+  $str= "";
+  for ($i = 0; $i < $size; $i++) {
+    $str .= get_random_char();
+  }
+  return $str;
+}
+
+
+# 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\n";
+echo "* generating random master key\n";
+$master_key= get_random_string();
+
+# Do we have a valid gosa.secrets, already? 
+if (file_exists("/etc/gosa/gosa.secrets")){
+  die ("There's already a /etc/gosa/gosa.secrets. Cannot convert your existing gosa.conf - aborted\n");
+} else {
+  echo "* creating /etc/gosa/gosa.secrets\n";
+  $fp = fopen("/etc/gosa/gosa.secrets", 'w') or die("Cannot open /etc/gosa/gosa.secrets for writing - aborted");
+  fwrite($fp, "RequestHeader set GOSA_KEY $master_key\n");
+  fclose($fp);
+  chmod ("/etc/gosa/gosa.secrets", 0600);
+  chown ("/etc/gosa/gosa.secrets", "root");
+  chgrp ("/etc/gosa/gosa.secrets", "root");
+}
+
+# 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");
+echo "* encrypting existent passwords with master key\n";
+foreach($referrals as $referral){
+  $pw= $referral->attributes->getNamedItem("password");
+  $pw->nodeValue= cred_encrypt($pw->nodeValue, $master_key);
+}
+
+# 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";
+
+# Print reminder
+echo<<<EOF
+Please adapt your http gosa location declaration to include the newly
+created "/etc/gosa/gosa.secrets".
+
+Example:
+
+Alias /gosa /usr/share/gosa/html
+
+<Location /gosa-loc>
+  php_admin_flag engine on
+  php_admin_value open_basedir "/etc/gosa/:/usr/share/gosa/:/var/cache/gosa/:/var/spool/gosa/"
+  php_admin_flag register_globals off
+  php_admin_flag allow_call_time_pass_reference off
+  php_admin_flag expose_php off
+  php_admin_flag zend.ze1_compatibility_mode off
+  php_admin_flag register_long_arrays off
+  php_admin_flag magic_quotes_gpc on
+  include /etc/gosa/gosa.secrets
+</Location>
+
+
+Please reload your httpd configuration after you've modified anything.
+
+
+EOF;
+?>
index 9f57efc873a79f03d296557c50bd6e3aff62372c..99dd917a2f7392f78cd5934899edec54b3533651 100644 (file)
@@ -70,6 +70,11 @@ an important LDAP password as the www-data user. If you allow other
 people to have i.e. public html directories, they will be able to read
 this configuration as well - if you don't take steps against it.
 
+As a simple solution, you can pass a master password via request headers.
+This can be achieved by running:
+
+# a2enmod headers
+# gosa-encrypt-passwords
 
 ----
 Cajus Pollmeier <cajus@debian.org>  Fri 02 Jun 2006 16:23:50 +0200
index 1c2f0e74ac4920b91302fafc2f32bebef6016c11..8de28da29f64982065a8c749b72b3c2077b539f4 100644 (file)
@@ -4,6 +4,7 @@ gosa (2.5.16-1) unstable; urgency=low
   * Fixed problem with broken characters in the password fields (Closes #470303)
   * Added apache configuration advisory to the README.debian
   * Removed additional bashisms from the rules file (Closes #478388)
+  * Add a root-readable master key for passwords in gosa.conf (Closes #402010)
 
  -- Cajus Pollmeier <cajus@debian.org>  Fri, 04 Apr 2008 09:03:52 +0200
 
index 887288feb759716fec8c0aec3419d6a40082866f..270f1e2565c7f5484e10308ce47d45a1a1805a40 100644 (file)
@@ -179,16 +179,21 @@ class config  {
     $this->level--;
   }
 
+
+  function get_credentials($creds)
+  {
+    if (isset($_SERVER['HTTP_GOSA_KEY'])){
+      return (cred_decrypt($creds, $_SERVER['HTTP_GOSA_KEY']));
+    }
+    return ($creds);
+  }
+
+
   function get_ldap_link($sizelimit= FALSE)
   {
-# Reuse same handle ldap handle.
-# Disabled due to unpredictable results
-#
-#    if($this->ldap === NULL || !is_resource($this->ldap->cid)){
-#
       /* Build new connection */
       $this->ldap= ldap_init ($this->current['SERVER'], $this->current['BASE'],
-          $this->current['ADMIN'], $this->current['PASSWORD']);
+          $this->current['ADMIN'], $this->get_credentials($this->current['PASSWORD']));
 
       /* Check for connection */
       if (is_null($this->ldap) || (is_int($this->ldap) && $this->ldap == 0)){
index 70ab363acedfc872f34830b1a1dd11b2ae7d51fc..cebbb4a3f9c3e82321775d45d97a90c015869d42 100644 (file)
@@ -2643,6 +2643,23 @@ function remove_objectClass($classes, &$attrs)
 }
 
 
+function cred_encrypt($input, $password) {
+
+  $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
+  $iv = mcrypt_create_iv($size, MCRYPT_DEV_RANDOM);
+
+  return bin2hex(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $password, $input, MCRYPT_MODE_ECB, $iv));
+}
+
+
+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 mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $password, pack("H*", $input), MCRYPT_MODE_ECB, $iv);
+}
+
+
 /* Returns contents of the given POST variable and check magic quotes settings */
 function get_post($name)
 {