<?php /* * Object passwords tab by Gjermund Jensvoll (gjerjens@xxxxxxxxx) * Version 0.8 * * * REQUIREMENTS: * PHP 5 * mcrypt module for PHP: * yum install php-mcrypt (RedHat/CentOS) * apt-get install php5-mcrypt (Debian/Ubuntu) * * * INSTALL: * * 1. create ObjectPWs Table in your RackTables database * CREATE TABLE IF NOT EXISTS `ObjectPWs` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `object_id` int(10) unsigned NOT NULL, `user_name` char(64) DEFAULT NULL, `password_hash` char(255) DEFAULT NULL, `comment` text, PRIMARY KEY (`id`), KEY `object_id` (`object_id`), CONSTRAINT `ObjectPWs-FK-object_id` FOREIGN KEY (`object_id`) REFERENCES `Object` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8; * 2. copy passwords.php to plugins directory * 3. change $key variable to something random (important!) * 4. make sure passwords.php is only readable by webserver and root (also important!) * * * UPGRADE: * Upgrading from 0.7 means that you need to re-encrypt the password database. I've made an upgrade script which does it for you. * You can get the script by emailing me at gjerjens@xxxxxxxxx, and I'll send you the script along with upgrade instructions. * * * CHANGELOG: * * Version 0.8 - 03.06.2013 * - Addon now makes use of Initialization Vector (IV) for better security (See http://stackoverflow.com/questions/11821195/use-of-initialization-vector-in-openssl-encrypt * for details) - Thanks Aaron Dummer and "sudopeople" on stackoverflow.com * - maxlength added to form items "Username" and "Password". * - !!!!! This update brakes backward compatability with older password databases, see details under "UPDATE" !!!!! * Version 0.7 - 14.05.2013 * - Initial public release * * * TESTED on RHEL6.4, Apache/2.2.15, PHP 5.3.3, MySQL 5.0.77 * RackTables <= 0.20.4 * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ $tab['object']['passwords'] = 'Passwords'; $tabhandler['object']['passwords'] = 'passwordsTabHandler'; //$ophandler['object']['passwords']['addPW'] = 'addPW'; //registerOpHandler (object, passwords, addPW, addPW, after); $key = "kl3XCqtC67sOjsWjxxxxxxxxCHANGExxTHISxxVARIABLExxxxxxxx4K4lsd02BsjfMppd"; $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); // Function for adding new passwords function commitNewPassword($object_id, $user_name, $password, $comment) { global $key, $iv_size; /* TODO check permissions */ $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $encrypted = openssl_encrypt($password, "AES-256-CBC", $key, 0, $iv); $data = $iv.$encrypted; $data_base64 = base64_encode($data); return usePreparedExecuteBlade ( "INSERT INTO ObjectPWs (object_id, user_name, password_hash, comment) VALUES (?, ?, ?, ?)", array ($object_id, $user_name, $data_base64, $comment) ); } /* commitNewPassword */ // Function for updating existing passwords function commitUpdatePassword($pw_id, $user_name, $password, $comment) { global $key, $iv_size; /* TODO check permissions */ $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); $encrypted = openssl_encrypt($password, "AES-256-CBC", $key, 0, $iv); $data = $iv.$encrypted; $data_base64 = base64_encode($data); return usePreparedExecuteBlade ( "UPDATE ObjectPWs SET user_name=?, password_hash = ?, comment = ? WHERE id = ?", array ($user_name, $data_base64, $comment, $pw_id) ); } /* commitUpdatePassword */ // Function for deleting passwords function commitDeletePassword($pw_id) { /* TODO check permissions */ return usePreparedExecuteBlade ( "DELETE FROM ObjectPWs WHERE id = ?", array ($pw_id) ); } /* commitDeletePassword */ // Main function function passwordsTabHandler () { global $key, $iv_size; // Show warning for IE users echo "<SCRIPT language=\"JavaScript\"> <!-- var browserName = navigator.appName; var bN = navigator.appCodeName; if (browserName == \"Microsoft Internet Explorer\") { document.write(\"<center><br><br><font color=red>This page requires a html5 capable browser. Turn off compatability mode in Internet Explorer.</font></center>\"); } //--> </SCRIPT>"; /* IE warning */ // Show password function echo "<SCRIPT language='JavaScript'> function ShowHide(pwfieldId,buttonId) { if(document.getElementById(pwfieldId).type != 'password') { document.getElementById(pwfieldId).type = 'password'; document.getElementById(buttonId).value = 'show'; } else { document.getElementById(pwfieldId).type = 'text'; document.getElementById(buttonId).value = 'hide'; } } </SCRIPT> "; /* Show password function */ $display ="<center><br><br><br>\n"; if (isset($_POST['op'])) { if ($_POST['op'] == "addPW") { commitNewPassword($_POST['object_id'], $_POST['user_name'], $_POST['password'], $_POST['comment']); } if ($_POST['op'] == "editPW") { commitUpdatePassword($_POST['pw_id'], $_POST['user_name'], $_POST['password'], $_POST['comment']); } } if (isset($_GET['op'])) { if ($_GET['op'] == "delPW") { commitDeletePassword($_GET['pw_id']); } } // Table header -> display $display .= "<table cellspacing=0 cellpadding='5' align='center' class='widetable'>"; $display .= "<tr><th> </th>"; $display .= "<th class=tdleft>Username</th>"; $display .= "<th class=tdleft>Password</th>"; $display .= "<th class=tdleft>Comment</th>"; $display .= "<th> </th></tr>"; assertUIntArg ('object_id', __FUNCTION__); $object = spotEntity ('object', $_REQUEST['object_id']); // Existing passwords -> display $query = "SELECT * FROM ObjectPWs WHERE object_id = '$object[id]'"; $result = NULL; $result = usePreparedSelectBlade ($query); while ($row = $result->fetch (PDO::FETCH_ASSOC)) { $pw_id = $row['id']; $object_id = $row['object_id']; $user_name = $row['user_name']; $data = base64_decode($row['password_hash']); $iv = substr($data, 0, $iv_size); $decrypted = openssl_decrypt(substr($data, $iv_size), "AES-256-CBC", $key, 0, $iv); $comment = $row['comment']; $display .= "<form method=post id=editPW name=editPW autocomplete=off action=\"\">"; $display .= "<input type=hidden name=\"pw_id\" value=\"".$pw_id."\">"; $display .= "<input type=hidden name=\"op\" value=\"editPW\">"; $display .= "<input type=hidden name=\"object_id\" value=\"".$object_id."\">"; $display .= "<tr><td><a href='?page=object&tab=passwords&object_id=".$object_id."&op=delPW&pw_id=".$pw_id."' onclick=\"javascript:return confirm('Are you sure you want to delete this password?')\">"; $display .= "<img src='?module=chrome&uri=pix/tango-list-remove.png' width=16 height=16 border=0 title='Delete this password'></a></td>"; $display .= "<td class='tdleft' NOWRAP><input type=text name=user_name value='".$user_name."' size=20 maxlength=64></td>"; $display .= "<td class='tdleft' NOWRAP><input type='password' id='password".$pw_id."' name='password' value='".$decrypted."' size=30 maxlength=110 required>"; $display .= "<input type='button' id='button".$pw_id."' value='show' onclick=\"javascript:ShowHide('password".$pw_id."','button".$pw_id."')\"></td>\n"; $display .= "<td class='tdleft' NOWRAP><input type=text name=comment value='".$comment."' size=30></td>"; $display .= "<td><input type=image name=submit class=icon src='?module=chrome&uri=pix/tango-document-save-16x16.png' border=0 title='Save changes' onclick=\"javascript:return confirm('Are you sure you want to edit this password?')\"></td></form></tr>"; } // Form to add new password -> display $display .= "<form action=\"\" method=post autocomplete=off id=\"addPW\" name=\"addPW\">"; $display .= "<input type=hidden name=\"object_id\" value=\"".$object['id']."\">"; $display .= "<input type=hidden name=\"op\" value=\"addPW\">"; $display .= "<tr><td><input type=image name=submit class=icon src='?module=chrome&uri=pix/tango-list-add.png' border=0 title='add a new password'></td>"; $display .= "<td class='tdleft'><input type=text size=20 name=user_name maxlength=64 tabindex=100></td>"; $display .= "<td class='tdleft'><input type=text name='password' id=newpassword tabindex=101 size=30 maxlength=110 required>"; $display .= "<input type='button' id='newbutton' value='hide' onclick=\"javascript:ShowHide('newpassword','newbutton')\"></td>\n"; $display .= "<td class='tdleft'><input type=text size=30 name=comment tabindex=102></td>"; $display .= "<td><input type=image name=submit class=icon src='?module=chrome&uri=pix/tango-list-add.png' border=0 tabindex=103 title='add a new password'></td></tr>"; $display .= "</form>"; $display .= "</table><br></center>"; // Output all display echo $display; } /* passwordsTabHandler */ ?>