Initial functioning version, pre-docker.

This commit is contained in:
Brian Lycett 2018-06-01 17:10:45 +01:00
commit 797ba68bc1
24 changed files with 9164 additions and 0 deletions

1
README.md Normal file
View File

@ -0,0 +1 @@
A PHP GUI admin interface for LDAP account management, designed to be run in a container.

View File

@ -0,0 +1 @@
Password strength progress taken from https://github.com/martinwnet/zxcvbn-bootstrap-strength-meter

117
change_password/index.php Normal file
View File

@ -0,0 +1,117 @@
<?php
include_once("web_functions.inc.php");
include_once("ldap_functions.inc.php");
set_page_access("user");
if (isset($_POST['change_password'])) {
if (!is_numeric($_POST['pass_score']) or $_POST['pass_score'] < 3) { $not_strong_enough = 1; }
if (preg_match("/\"|'/",$_POST['password'])) { $invalid_chars = 1; }
if ($_POST['password'] != $_POST['password_match']) { $mismatched = 1; }
if (!isset($mismatched) and !isset($not_strong_enough) and !isset($invalid_chars) ) {
$ldap_connection = open_ldap_connection();
ldap_change_password($ldap_connection,$USER_ID,$_POST['password']) or die("change_ldap_password() failed.");
render_header("Password changed");
?>
<div class="alert alert-success">
<p class="text-center">Your password has been changed.</p>
</div>
<?php
render_footer();
exit(0);
}
}
render_header('Change your LDAP password');
if (isset($not_strong_enough)) { ?>
<div class="alert alert-warning">
<p class="text-center">The password wasn't strong enough.</p>
</div>
<?php }
if (isset($invalid_chars)) { ?>
<div class="alert alert-warning">
<p class="text-center">The password contained invalid characters.</p>
</div>
<?php }
if (isset($mismatched)) { ?>
<div class="alert alert-warning">
<p class="text-center">The passwords didn't match.</p>
</div>
<?php }
?>
<script src="//cdnjs.cloudflare.com/ajax/libs/zxcvbn/1.0/zxcvbn.min.js"></script>
<script type="text/javascript" src="/js/zxcvbn-bootstrap-strength-meter.js"></script>
<script type="text/javascript">$(document).ready(function(){ $("#StrengthProgressBar").zxcvbnProgressBar({ passwordInput: "#password" });});</script>
<div class="container">
<div class="col-sm-8">
<div class="panel panel-default">
<div class="panel-heading text-center">Change password</div>
<div class="panel-body text-center">
<form class="form-horizontal" action='' method='post'>
<input type='hidden' id="change_password" name="change_password">
<input type='hidden' id="pass_score" value="0" name="pass_score">
<div class="form-group" id="password_div">
<label for="password" class="col-sm-4 control-label">Password</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="password" name="password">
</div>
</div>
<script>
function check_passwords_match() {
if (document.getElementById('password').value != document.getElementById('confirm').value ) {
document.getElementById('password_div').classList.add("has-error");
document.getElementById('confirm_div').classList.add("has-error");
}
else {
document.getElementById('password_div').classList.remove("has-error");
document.getElementById('confirm_div').classList.remove("has-error");
}
}
</script>
<div class="form-group" id="confirm_div">
<label for="password" class="col-sm-4 control-label">Confirm</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="confirm" name="password_match" onkeyup="check_passwords_match()">
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-default">Change password</button>
</div>
</form>
<div class="progress">
<div id="StrengthProgressBar" class="progress progress-bar"></div>
</div>
</div>
</div>
</div>
</div>
<?php
render_footer();
?>

72
includes/config.inc.php Normal file
View File

@ -0,0 +1,72 @@
<?php
#Mandatory
$LDAP['uri'] = getenv('LDAP_URI');
$LDAP['base_dn'] = getenv('LDAP_BASE_DN');
$LDAP['admins_group'] = getenv('LDAP_ADMINS_GROUP');
$LDAP['admin_bind_dn'] = getenv('LDAP_ADMIN_BIND_DN');
$LDAP['admin_bind_pwd'] = getenv('LDAP_ADMIN_BIND_PWD');
#Optional
$LDAP['group_ou'] = (getenv('LDAP_GROUP_OU') ? getenv('LDAP_GROUP_OU') : 'groups');
$LDAP['user_ou'] = (getenv('LDAP_USER_OU') ? getenv('LDAP_USER_OU') : 'people');
$LDAP['group_membership_attribute'] = (getenv('LDAP_GROUP_MEMBERSHIP_ATTRIBUTE') ? getenv('LDAP_GROUP_MEMBERSHIP_ATTRIBUTE') : 'uniquemember');
$LDAP['group_membership_uses_uid'] = (getenv('LDAP_GROUP_MEMBERSHIP_USES_UID') ? TRUE : FALSE);
$LDAP['account_attribute'] = (getenv('LDAP_ACCOUNT_ATTRIBUTE') ? getenv('LDAP_ACCOUNT_ATTRIBUTE') : 'uid');
$LDAP['starttls'] = (getenv('LDAP_STARTTLS') ? TRUE : FALSE);
$DEFAULT_USER_GROUP = (getenv('DEFAULT_USER_GROUP') ? getenv('DEFAULT_USER_GROUP') : 'everybody');
$DEFAULT_USER_SHELL = (getenv('DEFAULT_USER_SHELL') ? getenv('DEFAULT_SHELL') : '/bin/bash');
$EMAIL_DOMAIN = (getenv('EMAIL_DOMAIN') ? getenv('EMAIL_DOMAIN') : Null);
$LOGIN_TIMEOUT_MINS = (getenv('SESSION_TIMEOUT') ? getenv('SESSION_TIMEOUT') : 10);
$WEBSITE_NAME = (getenv('SITE_NAME') ? getenv('SITE_NAME') : 'LDAP user manager');
$USERNAME_FORMAT = (getenv('USERNAME_SEPARATOR') ? getenv('USERNAME_SEPARATOR') : '{first_name}.{last_name}');
$USERNAME_REGEX = '^[a-z][a-zA-Z0-9\._-]{3,32}$';
#We'll use the username regex for groups too.
###
$LDAP['group_dn'] = "ou=${LDAP['group_ou']},${LDAP['base_dn']}";
$LDAP['user_dn'] = "ou=${LDAP['user_ou']},${LDAP['base_dn']}";
###
$errors = "";
if (empty($LDAP['uri'])) {
$errors .= "<div class='alert alert-warning'><p class='text-center'>LDAP_URI isn't set</p></div>\n";
}
if (empty($LDAP['base_dn'])) {
$errors .= "<div class='alert alert-warning'><p class='text-center'>LDAP_BASE_DN isn't set</p></div>\n";
}
if (empty($LDAP['admin_bind_dn'])) {
$errors .= "<div class='alert alert-warning'><p class='text-center'>LDAP_ADMIN_BIND_DN isn't set</p></div>\n";
}
if (empty($LDAP['admin_bind_pwd'])) {
$errors .= "<div class='alert alert-warning'><p class='text-center'>LDAP_ADMIN_BIND_PWD isn't set</p></div>\n";
}
if (empty($LDAP['admins_group'])) {
$errors .= "<div class='alert alert-warning'><p class='text-center'>LDAP_ADMINS_GROUP isn't set</p></div>\n";
}
if ($errors != "") {
render_header();
print $errors;
render_footer();
exit(1);
}
#POSIX accounts
$min_uid = 2000;
$min_gid = 2000;
?>

View File

@ -0,0 +1,601 @@
<?php
$log_prefix = date('Y-m-d H:i:s') . " - LDAP manager - $USER_ID - ";
###################################
function open_ldap_connection() {
global $log_prefix, $LDAP, $ENCRYPTED;
$ldap_connection = ldap_connect($LDAP['uri']);
if (!$ldap_connection) {
print "Problem: Can't connect to the LDAP server at ${LDAP['uri']}";
die("Can't connect to the LDAP server at ${LDAP['uri']}");
exit(1);
}
ldap_set_option($ldap_connection, LDAP_OPT_PROTOCOL_VERSION, 3);
$bind_result = ldap_bind( $ldap_connection, $LDAP['admin_bind_dn'], $LDAP['admin_bind_pwd']);
if ($bind_result != TRUE) {
print "Problem: Failed to bind as ${LDAP['admin_bind_dn']}";
error_log("$log_prefix Failed to bind as ${LDAP['admin_bind_dn']}",0);
exit(1);
}
if ($LDAP["starttls"]) {
$tls_result = ldap_start_tls($ldap_connection);
if ($tls_result != TRUE) {
error_log("$log_prefix Failed to start STARTTLS connection to ${LDAP['uri']}",0);
}
else {
$ENCRYPTED=TRUE;
}
}
return $ldap_connection;
}
###################################
function ldap_auth_username($ldap_connection,$username, $password) {
# Search for the DN for the given username. If found, try binding with the DN and user's password.
# If the binding succeeds, return the DN.
global $log_prefix, $LDAP;
$ldap_search = ldap_search( $ldap_connection, $LDAP['base_dn'], "${LDAP['account_attribute']}=${username}");
if (!$ldap_search) {
error_log("$log_prefix Couldn't search for $username",0);
return FALSE;
}
$result = ldap_get_entries($ldap_connection, $ldap_search);
if ($result["count"] == 1) {
$auth_ldap_connection = open_ldap_connection();
$can_bind = @ldap_bind( $auth_ldap_connection, $result[0]['dn'], $password);
ldap_close($auth_ldap_connection);
if ($can_bind) {
preg_match("/{$LDAP['account_attribute']}=(.*?),/",$result[0]['dn'],$dn_match);
return $dn_match[1];
ldap_unbind($auth_ldap_connection);
}
else {
return FALSE;
}
}
}
###################################
function ldap_setup_auth($ldap_connection, $password) {
#For the initial setup we need to make sure that whoever's running it has the default admin user
#credentials as passed in ADMIN_BIND_*
global $log_prefix, $LDAP;
$auth_ldap_connection = open_ldap_connection();
$can_bind = @ldap_bind($auth_ldap_connection, $LDAP['admin_bind_dn'], $password);
ldap_close($auth_ldap_connection);
if ($can_bind) { return TRUE; } else { return FALSE; }
}
###################################
function ldap_check_is_admin($username, $ldap_connection) {
#Checks to see if $username is in the group defined by $LDAP['admins_group']
global $log_prefix, $LDAP;
##Check via memberOf.
##TODO: check via parsing group membership otherwise.
$this_filter="(&(${LDAP['account_attribute']}=${username})(memberOf=cn=${LDAP['admins_group']},${LDAP['group_dn']}))";
$ldap_search = ldap_search( $ldap_connection, $LDAP['base_dn'], $this_filter);
$no_results = ldap_count_entries($ldap_connection,$ldap_search);
if ($no_results == 1) {
return TRUE;
}
else {
return FALSE;
}
}
##################################
function ldap_hashed_password($password) {
$hashed_pwd = '{MD5}' . base64_encode(md5($password,TRUE));
return $hashed_pwd;
}
##################################
function ldap_get_user_list($ldap_connection,$start=0,$entries=NULL,$sort="asc",$sort_key=NULL,$filters=NULL,$fields=NULL) {
global $log_prefix, $LDAP;
if (!isset($fields)) { $fields = array("uid", "givenname", "sn"); }
if (!isset($sort_key)) { $sort_key = $LDAP['account_attribute']; }
$ldap_search = ldap_search($ldap_connection, "${LDAP['user_dn']}", "(&(${LDAP['account_attribute']}=*)$filters)", $fields);
$result = ldap_get_entries($ldap_connection, $ldap_search);
$records = array();
foreach ($result as $record) {
if (isset($record[$sort_key][0])) {
$add_these = array();
foreach($fields as $this_attr) {
if ($this_attr != $sort_key) { $add_these[$this_attr] = $record[$this_attr][0]; }
}
$records[$record[$sort_key][0]] = $add_these;
}
}
if ($sort == "asc") { ksort($records); } else { krsort($records); }
return(array_slice($records,$start,$entries));
}
##################################
function ldap_get_highest_id($ldap_connection,$type="uid") {
global $log_prefix, $LDAP, $min_uid, $min_gid;
if ($type == "uid") {
$this_id = $min_uid;
$record_base_dn = $LDAP['user_dn'];
$record_filter = "(${LDAP['account_attribute']}=*)";
$record_attribute = array("uidNumber");
}
else {
$type = "gid";
$this_id = $min_gid;
$record_base_dn = $LDAP['group_dn'];
$record_filter = "(objectClass=posixGroup)";
$record_attribute = array("gidNumber");
}
$filter = "(&(objectclass=device)(cn=last${type}))";
$ldap_search = ldap_search($ldap_connection, "${LDAP['base_dn']}", $filter, array('serialNumber'));
$result = ldap_get_entries($ldap_connection, $ldap_search);
$fetched_id = $result[0]['serialnumber'][0];
if (isset($fetched_id) and is_numeric($fetched_id)){
$this_id = $fetched_id;
}
else {
$ldap_search = ldap_search($ldap_connection, $record_base_dn, $record_filter, $record_attribute);
$result = ldap_get_entries($ldap_connection, $ldap_search);
foreach ($result as $record) {
if (isset($record[$record_attribute][0])) {
if ($record[$record_attribute][0] > $this_id) { $this_id = $record[$record_attribute][0]; }
}
}
}
return($this_id);
}
##################################
function ldap_get_group_list($ldap_connection,$start=0,$entries=NULL,$sort="asc",$filters=NULL) {
global $log_prefix, $LDAP;
$ldap_search = ldap_search($ldap_connection, "${LDAP['group_dn']}", "(&(objectclass=*)$filters)");
$result = ldap_get_entries($ldap_connection, $ldap_search);
$records = array();
foreach ($result as $record) {
if (isset($record['cn'][0])) {
array_push($records, $record['cn'][0]);
}
}
if ($sort == "asc") { sort($records); } else { rsort($records); }
return(array_slice($records,$start,$entries));
}
##################################
function ldap_get_group_members($ldap_connection,$group_name,$start=0,$entries=NULL,$sort="asc") {
global $log_prefix, $LDAP;
$ldap_search = ldap_search($ldap_connection, "${LDAP['group_dn']}", "(cn=$group_name)", array($LDAP['group_membership_attribute']));
$result = ldap_get_entries($ldap_connection, $ldap_search);
$records = array();
foreach ($result[0][$LDAP['group_membership_attribute']] as $record => $value) {
if ($record != 'count' and isset($value)) {
array_push($records, $value);
}
}
if ($sort == "asc") { sort($records); } else { rsort($records); }
return(array_slice($records,$start,$entries));
}
##################################
function ldap_is_group_member($ldap_connection,$group_name,$username) {
global $log_prefix, $LDAP;
$ldap_search = ldap_search($ldap_connection, "${LDAP['group_dn']}", "(cn=$group_name)");
$result = ldap_get_entries($ldap_connection, $ldap_search);
if ($LDAP['group_membership_uses_uid'] == FALSE) {
$username = "${LDAP['account_attribute']}=$username,${LDAP['user_dn']}";
}
if (preg_grep ("/^${username}$/i", $result[0][$LDAP['group_membership_attribute']])) {
return TRUE;
}
else {
return FALSE;
}
}
##################################
function ldap_new_group($ldap_connection,$group_name) {
global $log_prefix, $LDAP;
if (isset($group_name)) {
$ldap_search = ldap_search($ldap_connection, "${LDAP['group_dn']}", "(cn=$group_name,${LDAP['group_dn']})");
$result = ldap_get_entries($ldap_connection, $ldap_search);
if ($result['count'] == 0) {
$highest_gid = ldap_get_highest_id($ldap_connection,'gid');
$new_gid = $highest_gid + 1;
$add_group = ldap_add($ldap_connection,
"cn=$group_name,${LDAP['group_dn']}",
array( 'objectClass' => array( 'top', 'groupOfUniqueNames', 'posixGroup' ),
'cn' => $group_name,
'gidNumber' => $new_gid,
$LDAP['group_membership_attribute'] => ''
)
);
if ($add_group) {
error_log("$log_prefix Added new group $group_name",0);
$update_gid = ldap_mod_replace($ldap_connection, "cn=lastGID,${LDAP['base_dn']}", array( 'serialNumber' => $new_gid ));
if ($update_gid) {
error_log("$log_prefix Updated cn=lastGID with $new_gid",0);
return TRUE;
}
else {
error_log("$log_prefix Failed to update cn=lastGID",0);
}
}
}
else {
error_log("$log_prefix Create group; group $group_name already exists.",0);
}
}
else {
error_log("$log_prefix Create group; group name wasn't set.",0);
}
return FALSE;
}
##################################
function ldap_delete_group($ldap_connection,$group_name) {
global $log_prefix, $LDAP;
if (isset($group_name)) {
$delete = ldap_delete($ldap_connection, "cn=$group_name,${LDAP['group_dn']}");
if ($delete) {
error_log("$log_prefix Deleted group $group_name",0);
return TRUE;
}
else {
error_log("$log_prefix Couldn't delete group $group_name",0);
return FALSE;
}
}
}
##################################
function ldap_get_gid_of_group($ldap_connection,$group_name) {
global $log_prefix, $LDAP;
if (isset($group_name)) {
$ldap_search = ldap_search($ldap_connection, "${LDAP['group_dn']}", "(cn=$group_name)", array("gidNumber"));
$result = ldap_get_entries($ldap_connection, $ldap_search);
if (isset($result[0]['gidnumber'][0]) and is_numeric($result[0]['gidnumber'][0])) {
return $result[0]['gidnumber'][0];
}
}
return FALSE;
}
##################################
function ldap_new_account($ldap_connection,$first_name,$last_name,$username,$password) {
global $log_prefix, $LDAP, $DEFAULT_USER_SHELL, $DEFAULT_USER_GROUP, $EMAIL_DOMAIN;
if (isset($first_name) and isset($last_name) and isset($username) and isset($password)) {
$ldap_search = ldap_search($ldap_connection, "${LDAP['user_dn']}", "(${LDAP['account_attribute']}=$username,${LDAP['user_dn']})");
$result = ldap_get_entries($ldap_connection, $ldap_search);
if ($result['count'] == 0) {
$highest_uid = ldap_get_highest_id($ldap_connection,'uid');
$new_uid = $highest_uid + 1;
$default_gid = ldap_get_gid_of_group($ldap_connection,$DEFAULT_USER_GROUP);
if (!is_numeric($default_gid)) {
$group_add = ldap_new_group($ldap_connection,$username);
$gid = ldap_get_gid_of_group($ldap_connection,$username);
$add_to_group = $username;
}
else {
$gid = $default_gid;
$add_to_group = $DEFAULT_USER_GROUP;
}
$hashed_pass = ldap_hashed_password($password);
$user_info = array( 'objectClass' => array( 'person', 'inetOrgPerson', 'posixAccount' ),
'uid' => $username,
'givenName' => $first_name,
'sn' => $last_name,
'cn' => "$first_name $last_name",
'displayName' => "$first_name $last_name",
'uidNumber' => $new_uid,
'gidNumber' => $gid,
'loginShell' => $DEFAULT_USER_SHELL,
'homeDirectory' => "/home/$username",
'userPassword' => $hashed_pass
);
if (isset($EMAIL_DOMAIN)) {
array_push($user_info, ['mail' => "$username@$EMAIL_DOMAIN"]);
}
$add_account = ldap_add($ldap_connection,
"${LDAP['account_attribute']}=$username,${LDAP['user_dn']}",
$user_info
);
if ($add_account) {
error_log("$log_prefix Created new account: $username",0);
ldap_add_member_to_group($ldap_connection,$add_to_group,$username);
$update_uid = ldap_mod_replace($ldap_connection, "cn=lastUID,${LDAP['base_dn']}", array( 'serialNumber' => $new_uid ));
if ($update_uid) {
error_log("$log_prefix Create account; Updated cn=lastUID with $new_uid",0);
return TRUE;
}
else {
error_log("$log_prefix Create account; Failed to update cn=lastUID",0);
}
}
else {
error_log("$log_prefix Create account; couldn't create the account for $username",0);
}
}
else {
error_log("$log_prefix Create account; Account for $username already exists",0);
}
}
else {
error_log("$log_prefix Create account; missing parameters",0);
}
return FALSE;
}
##################################
function ldap_delete_account($ldap_connection,$username) {
global $log_prefix, $LDAP;
if (isset($username)) {
$delete = ldap_delete($ldap_connection, "${LDAP['account_attribute']}=$username,${LDAP['user_dn']}");
if ($delete) {
error_log("$log_prefix Deleted account for $username",0);
return TRUE;
}
else {
error_log("$log_prefix Couldn't delete account for $username",0);
return FALSE;
}
}
}
##################################
function ldap_add_member_to_group($ldap_connection,$group_name,$username) {
global $log_prefix, $LDAP;
$group_dn = "cn=${group_name},${LDAP['group_dn']}";
if ($LDAP['group_membership_uses_uid'] == FALSE) {
$username = "${LDAP['account_attribute']}=$username,${LDAP['user_dn']}";
}
$group_update = array($LDAP['group_membership_attribute'] => $username);
$update = ldap_mod_add($ldap_connection,$group_dn,$group_update);
if ($update) {
error_log("$log_prefix Added $username to $group_name",0);
return TRUE;
}
else {
error_log("$log_prefix Couldn't add $username to $group_name",0);
return FALSE;
}
}
##################################
function ldap_delete_member_from_group($ldap_connection,$group_name,$username) {
global $log_prefix, $LDAP;
$group_dn = "cn=${group_name},${LDAP['group_dn']}";
if ($LDAP['group_membership_uses_uid'] == FALSE) {
$username = "${LDAP['account_attribute']}=$username,${LDAP['user_dn']}";
}
$group_update = array($LDAP['group_membership_attribute'] => $username);
$update = ldap_mod_del($ldap_connection,$group_dn,$group_update);
if ($update) {
error_log("$log_prefix Removed $username from $group_name",0);
return TRUE;
}
else {
error_log("$log_prefix Couldn't remove $username from $group_name",0);
return FALSE;
}
}
##################################
function ldap_change_password($ldap_connection,$username,$new_password) {
global $log_prefix, $LDAP;
#Find DN of user
$ldap_search = ldap_search( $ldap_connection, $LDAP['base_dn'], "${LDAP['account_attribute']}=${username}");
if ($ldap_search) {
$result = ldap_get_entries($ldap_connection, $ldap_search);
if ($result["count"] == 1) {
$this_dn=$result[0]['dn'];
}
else {
error_log("$log_prefix Couldn't find the DN for user $username");
return FALSE;
}
}
else {
error_log("$log_prefix Couldn't perform an LDAP search for ${LDAP['account_attribute']}=${username}",0);
return FALSE;
}
#Hash password
$hashed_pass = ldap_hashed_password($new_password);
$entries["userPassword"] = $new_password;
$update = ldap_mod_replace($ldap_connection, $this_dn, $entries);
if ($update) {
error_log("$log_prefix Updated the password for $username");
return TRUE;
}
else {
error_log("$log_prefix Couldn't update the password for $username");
return TRUE;
}
}
?>

17
includes/modules.inc.php Normal file
View File

@ -0,0 +1,17 @@
<?php
#Modules and how they can be accessed.
#access:
#user = need to be logged-in to see it
#hidden_on_login = only visible when not logged in
#admin = need to be logged in as an admin to see it
$MODULES = array(
'log_in' => 'hidden_on_login',
'change_password' => 'auth',
'ldap_manager' => 'admin',
'log_out' => 'auth'
);
?>

View File

@ -0,0 +1,362 @@
<?php
#Security level vars
$VALIDATED = False;
$IS_ADMIN = False;
$IS_SETUP_ADMIN = False;
$ENCRYPTED = False;
$ACCESS_LEVEL_NAME = array('account','admin');
unset($USER_ID);
$CURRENT_PAGE=htmlentities($_SERVER['PHP_SELF']);
$paths=explode('/',getcwd());
$THIS_MODULE_PATH=end($paths);
$GOOD_ICON = "&#9745;";
$WARN_ICON = "&#9888;";
$FAIL_ICON = "&#9940;";
include ("modules.inc.php"); # module definitions
include ("config.inc.php"); # get local settings
validate_passkey_cookie();
######################################################
function generate_passkey() {
$rnd1 = rand(10000000,100000000000);
$rnd2 = rand(10000000,100000000000);
$rnd3 = rand(10000000,100000000000);
return sprintf("%0x",$rnd1) . sprintf("%0x",$rnd2) . sprintf("%0x",$rnd3);
}
######################################################
function set_passkey_cookie($user_id,$is_admin) {
# Create a random value, store it locally and set it in a cookie.
global $LOGIN_TIMEOUT_MINS, $VALIDATED, $USER_ID, $IS_ADMIN;
$passkey = generate_passkey();
$this_time=time();
$admin_val = 0;
if ($is_admin == True ) {
$admin_val = 1;
$IS_ADMIN = True;
}
$filename = preg_replace('/[^a-zA-Z0-9]/','_', $user_id);
file_put_contents("/tmp/$filename","$passkey:$admin_val:$this_time");
setcookie('orf_cookie', "$user_id:$passkey", $this_time+(60 * $LOGIN_TIMEOUT_MINS), '/', $_SERVER["HTTP_HOST"]);
$VALIDATED = True;
}
######################################################
function validate_passkey_cookie() {
global $LOGIN_TIMEOUT_MINS, $IS_ADMIN, $USER_ID, $VALIDATED;
if (isset($_COOKIE['orf_cookie'])) {
list($user_id,$c_passkey) = explode(":",$_COOKIE['orf_cookie']);
$filename = preg_replace('/[^a-zA-Z0-9]/','_', $user_id);
$session_file = file_get_contents("/tmp/$filename");
list($f_passkey,$f_is_admin,$f_time) = explode(":",$session_file);
$this_time=time();
if (!empty($c_passkey) and $f_passkey == $c_passkey and $this_time < $f_time+(60 * $LOGIN_TIMEOUT_MINS)) {
if ($f_is_admin == 1) { $IS_ADMIN = True; }
$VALIDATED = True;
$USER_ID=$user_id;
set_passkey_cookie($USER_ID,$IS_ADMIN);
}
}
}
######################################################
function set_setup_cookie() {
# Create a random value, store it locally and set it in a cookie.
global $LOGIN_TIMEOUT_MINS, $IS_SETUP_ADMIN;
$passkey = generate_passkey();
$this_time=time();
$IS_SETUP_ADMIN = True;
file_put_contents("/tmp/ldap_setup","$passkey:$this_time");
setcookie('setup_cookie', "$passkey", $this_time+(60 * $LOGIN_TIMEOUT_MINS), '/', $_SERVER["HTTP_HOST"]);
}
######################################################
function validate_setup_cookie() {
global $LOGIN_TIMEOUT_MINS, $IS_SETUP_ADMIN;
if (isset($_COOKIE['setup_cookie'])) {
$c_passkey = $_COOKIE['setup_cookie'];
$session_file = file_get_contents("/tmp/ldap_setup");
list($f_passkey,$f_time) = explode(":",$session_file);
$this_time=time();
if (!empty($c_passkey) and $f_passkey == $c_passkey and $this_time < $f_time+(60 * $LOGIN_TIMEOUT_MINS)) {
$IS_SETUP_ADMIN = True;
set_setup_cookie();
}
}
}
######################################################
function log_out($method='normal') {
# Delete the passkey from the database and the passkey cookie
global $USER_ID;
setcookie('orf_cookie', "", time()-20000 , "/", $_SERVER["HTTP_HOST"], 0);
$filename = preg_replace('/[^a-zA-Z0-9]/','_', $USER_ID);
unlink("/tmp/$filename");
if ($method == 'auto') { $options = "?logged_out"; } else { $options = ""; }
header("Location: //${_SERVER["HTTP_HOST"]}/index.php$options\n\n");
}
######################################################
function render_header($title="",$menu=TRUE) {
global $WEBSITE_NAME, $IS_ADMIN;
if (empty($title)) { $title = $WEBSITE_NAME; }
#Initialise the HTML output for the page.
?>
<HTML>
<HEAD>
<TITLE><?php print "$title"; ?></TITLE>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</HEAD>
<BODY>
<?php
if ($menu == True) {
render_menu();
}
}
######################################################
function render_menu() {
#Render the navigation menu.
#The menu is dynamically rendered the $MODULES hash
global $WEBSITE_NAME, $MODULES, $THIS_MODULE_PATH, $VALIDATED, $IS_ADMIN;
?>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" href="#"><?php print $WEBSITE_NAME ?></a>
</div>
<ul class="nav navbar-nav">
<?php
foreach ($MODULES as $module => $access) {
$this_module_name=stripslashes(ucwords(preg_replace('/_/',' ',$module)));
$show_this_module = True;
if ($VALIDATED == True) {
if ($access == 'hidden_on_login') { $show_this_module = False; }
if ($IS_ADMIN == False and $access == 'admin' ){ $show_this_module = False; }
}
else {
if ($access != 'hidden_on_login') { $show_this_module = False; }
}
#print "<p>$module - access is $access & show is $show_this_module</p>";
if ($show_this_module == True ) {
if ($module == $THIS_MODULE_PATH) {
print "<li class='active'>";
}
else {
print '<li>';
}
print "<a href='/{$module}'>$this_module_name</a></li>\n";
}
}
?>
</ul>
</div>
</nav>
<?php
}
######################################################
function render_footer() {
#Finish rendering an HTML page.
?>
</BODY>
</HTML>
<?php
}
######################################################
function set_page_access($level) {
global $IS_ADMIN, $IS_SETUP_ADMIN, $VALIDATED;
#Set the security level needed to view a page.
#This should be one of the first pieces of code
#you call on a page.
#Either 'setup', 'admin' or 'user'.
if ($level == "setup") {
if ($IS_SETUP_ADMIN == True) {
return;
}
else {
header("Location: //" . $_SERVER["HTTP_HOST"] . "/setup/index.php?unauthorised\n\n");
exit(0);
}
}
if ($level == "admin") {
if ($IS_ADMIN == True and $VALIDATED == True) {
return;
}
else {
header("Location: //" . $_SERVER["HTTP_HOST"] . "/index.php?unauthorised\n\n");
exit(0);
}
}
if ($level == "user") {
if ($VALIDATED == True){
return;
}
else {
header("Location: //" . $_SERVER["HTTP_HOST"] . "/index.php?unauthorised\n\n");
exit(0);
}
}
}
######################################################
function is_valid_email($email) {
if (ereg('^[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+'.'@'.'[-!#$%&\'*+\\/0-9=?A-Z^_`a-z{|}~]+\.'.'[-!#$%&\'*+\\./0-9=?A-Z^_`a-z{|}~]+$', $email)) {
return true;
}
else {
return false;
}
}
function render_js_username_check(){
global $USERNAME_REGEX;
print <<<EoCheckJS
<script>
function check_entity_name_validity(name,div_id) {
var check_regex = /$USERNAME_REGEX/;
if (! check_regex.test(name) ) {
document.getElementById(div_id).classList.add("has-error");
}
else {
document.getElementById(div_id).classList.remove("has-error");
}
}
</script>
EoCheckJS;
}
######################################################
function render_js_username_generator($firstname_field_id,$lastname_field_id,$username_field_id,$username_div_id) {
#Parameters are the IDs of the input fields and username name div in the account creation form.
#The div will be set to warning if the username is invalid.
global $USERNAME_FORMAT, $USERNAME_REGEX;
render_js_username_check();
print <<<EoRenderJS
<script>
function update_username() {
var first_name = document.getElementById('$firstname_field_id').value;
var last_name = document.getElementById('$lastname_field_id').value;
var template = '$USERNAME_FORMAT';
var actual_username = template;
actual_username = actual_username.replace('{first_name}', first_name.toLowerCase() );
actual_username = actual_username.replace('{first_initial}', first_name.charAt(0).toLowerCase() );
actual_username = actual_username.replace('{last_name}', last_name.toLowerCase() );
actual_username = actual_username.replace('{last_initial}', last_name.charAt(0).toLowerCase() );
check_entity_name_validity(actual_username,'$username_div_id');
document.getElementById('$username_field_id').value = actual_username;
}
</script>
EoRenderJS;
}
?>

32
index.php Normal file
View File

@ -0,0 +1,32 @@
<?php
include_once("web_functions.inc.php");
render_header($WEBSITE_NAME);
if (isset($_GET['logged_out'])) {
?>
<div class="alert alert-warning">
<p class="text-center">You've been automatically logged out because you've been inactive for over
<?php print $LOGIN_TIMEOUT_MINS; ?> minutes. Click on the 'Log in' link to get back into the system.</p>
</div>
<?php
}
if (isset($_GET['logged_in'])) {
?>
<div class="alert alert-success">
<p class="text-center">You're logged in. Select from the menu above.</p>
</div>
<?php
}
if (isset($_GET['unauthorised'])) {
?>
<div class="alert alert-danger">
<p class="text-center">You don't have the necessary permissions needed to use this module.</p>
</div>
<?php
}
render_footer();
?>

71
js/generate_passphrase.js Normal file
View File

@ -0,0 +1,71 @@
'use strict';
//Adapted from https://github.com/mike-hearn/useapassphrase
function generatePassword(numberOfWords,seperator,passwordField,confirmField) {
// IDs of password field and confirm field
var passwordField = document.getElementById(passwordField);
var confirmField = document.getElementById(confirmField);
// Cryptographically generated random numbers
numberOfWords = parseInt(numberOfWords);
var array = new Uint32Array(numberOfWords);
var crypto = window.crypto || window.msCrypto;
crypto.getRandomValues(array);
// Empty array to be filled with wordlist
var generatedPasswordArray = [];
var integerIndex = getRandomInt(4);
var integerValue = getRandomInt(99);
var uppercaseIndex = getRandomInt(4);
while (uppercaseIndex == integerIndex) {
uppercaseIndex = getRandomInt(4);
}
// Grab a random word, push it to the password array
for (var i = 0; i < array.length; i++) {
var this_word = "";
if (i == integerIndex ) {
this_word = integerValue;
}
else {
var index = (array[i] % 5852);
this_word = wordlist[index];
if (i == uppercaseIndex) {
this_word = this_word[0].toUpperCase() + this_word.slice(1);
}
}
generatedPasswordArray.push(this_word);
}
var this_password = generatedPasswordArray.join(seperator);
passwordField.type = 'text';
passwordField.value = this_password;
confirmField.type = 'text';
confirmField.value = this_password;
//Copy to the clipboard
passwordField.focus();
passwordField.select();
document.execCommand("copy");
}
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}

5839
js/wordlist.js Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,77 @@
//Requires zxcvbn.js and Bootstrap
(function ($) {
$.fn.zxcvbnProgressBar = function (options) {
//init settings
var settings = $.extend({
passwordInput: '#Password',
userInputs: [],
ratings: ["Very poor", "Poor", "Lukewarm", "Good", "Great"],
//all progress bar classes removed before adding score specific css class
allProgressBarClasses: "progress-bar-danger progress-bar-warning progress-bar-success progress-bar-striped active",
//bootstrap css classes (0-4 corresponds with zxcvbn score)
progressBarClass0: "progress-bar-danger progress-bar-striped active",
progressBarClass1: "progress-bar-danger progress-bar-striped active",
progressBarClass2: "progress-bar-warning progress-bar-striped active",
progressBarClass3: "progress-bar-success",
progressBarClass4: "progress-bar-success"
}, options);
return this.each(function () {
settings.progressBar = this;
//init progress bar display
UpdateProgressBar();
//Update progress bar on each keypress of password input
$(settings.passwordInput).keyup(function (event) {
UpdateProgressBar();
});
});
function UpdateProgressBar() {
var progressBar = settings.progressBar;
var password = $(settings.passwordInput).val();
if (password) {
var result = zxcvbn(password, settings.userInputs);
//result.score: 0, 1, 2, 3 or 4 - if crack time is less than 10**2, 10**4, 10**6, 10**8, Infinity.
var scorePercentage = (result.score + 1) * 20;
$(progressBar).css('width', scorePercentage + '%');
$( "input#pass_score" ).val(result.score);
if (result.score == 0) {
//weak
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass0);
$(progressBar).html(settings.ratings[0]);
}
else if (result.score == 1) {
//normal
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass1);
$(progressBar).html(settings.ratings[1]);
}
else if (result.score == 2) {
//medium
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass2);
$(progressBar).html(settings.ratings[2]);
}
else if (result.score == 3) {
//strong
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass3);
$(progressBar).html(settings.ratings[3]);
}
else if (result.score == 4) {
//very strong
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass4);
$(progressBar).html(settings.ratings[4]);
}
}
else {
$(progressBar).css('width', '0%');
$(progressBar).removeClass(settings.allProgressBarClasses).addClass(settings.progressBarClass0);
$(progressBar).html('');
}
}
update_password_bar = UpdateProgressBar;
};
})(jQuery);

97
ldap_manager/groups.php Normal file
View File

@ -0,0 +1,97 @@
<?php
include_once("web_functions.inc.php");
set_page_access("admin");
include_once("ldap_functions.inc.php");
include_once("module_functions.inc.php");
render_header("LDAP manager");
render_submenu();
$ldap_connection = open_ldap_connection();
if (isset($_POST['delete_group'])) {
?>
<script>
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<?php
$this_group = $_POST['delete_group'];
if (preg_match("/$USERNAME_REGEX/",$this_group)) {
$del_group = ldap_delete_group($ldap_connection,$this_group);
if ($del_group) {
?>
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<strong>Success!</strong> Group <strong><?php print $this_group; ?> was deleted.
</div>
<?php
}
else {
?>
<div class="alert alert-danger" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<strong>Problem!</strong> Group <strong><?php print $this_group; ?></strong> wasn't deleted.
</div>
<?php
}
}
}
$groups = ldap_get_group_list($ldap_connection);
ldap_close($ldap_connection);
render_js_username_check();
?>
<script type="text/javascript">
function show_new_group_form() {
group_form = document.getElementById('group_name');
group_submit = document.getElementById('add_group');
group_form.classList.replace('invisible','visible');
group_submit.classList.replace('invisible','visible');
}
</script>
<div class="container">
<div class="form-inline" id="new_group_div">
<form action="/<?php print $THIS_MODULE_PATH; ?>/show_group.php" method="post">
<input type="hidden" name="new_group">
<button id="show_new_group" class="form-control btn btn-default" type="button" onclick="show_new_group_form();">New group</button>
<input type="text" class="form-control invisible" name="group_name" id="group_name" placeholder="Group name" onkeyup="check_entity_name_validity(document.getElementById('group_name').value,'new_group_div');"><button id="add_group" class="form-control btn btn-primary btn-sm invisible" type="submit">Add</button>
</form>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>Group name</th>
</tr>
</thead>
<tbody>
<?php
foreach ($groups as $group){
print " <tr>\n <td><a href='/$THIS_MODULE_PATH/show_group.php?group_name=$group'>$group</a></td>\n </tr>\n";
}
?>
</tbody>
</table>
</div>
<?php
render_footer();
?>

80
ldap_manager/index.php Normal file
View File

@ -0,0 +1,80 @@
<?php
include_once("web_functions.inc.php");
include_once("ldap_functions.inc.php");
include_once("module_functions.inc.php");
set_page_access("admin");
render_header("LDAP manager");
render_submenu();
$ldap_connection = open_ldap_connection();
if (isset($_POST['delete_user'])) {
?>
<script>
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<?php
$this_user = $_POST['delete_user'];
if (preg_match("/$USERNAME_REGEX/",$this_user)) {
$del_user = ldap_delete_account($ldap_connection,$this_user);
if ($del_user) {
?>
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<strong>Success!</strong> User <strong><?php print $this_user; ?> was deleted.
</div>
<?php
}
else {
?>
<div class="alert alert-danger" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<strong>Problem!</strong> User <strong><?php print $this_user; ?></strong> wasn't deleted.
</div>
<?php
}
}
}
$people = ldap_get_user_list($ldap_connection);
ldap_close($ldap_connection);
?>
<div class="container">
<form action="/<?php print $THIS_MODULE_PATH; ?>/new_user.php" method="post">
<button id="add_group" class="btn btn-default" type="submit">New user</button>
</form>
<table class="table table-striped">
<thead>
<tr>
<th>Username</th>
<th>First name</th>
<th>Last name</th>
</tr>
</thead>
<tbody>
<?php
foreach ($people as $username => $attribs){
print " <tr>\n <td><a href='/$THIS_MODULE_PATH/show_user.php?username=$username'>$username</a></td>\n";
print " <td>" . $people[$username]['givenname'] . "</td>\n";
print " <td>" . $people[$username]['sn'] . "</td>\n";
print " </tr>\n";
}
?>
</tbody>
</table>
</div>
<?php
render_footer();
?>

View File

@ -0,0 +1,37 @@
<?php
##################################
function render_submenu() {
global $THIS_MODULE_PATH;
$submodules = array( 'users' => 'index.php',
'groups' => 'groups.php'
);
?>
<nav class="navbar navbar-default">
<div class="container-fluid">
<ul class="nav navbar-nav">
<?php
foreach ($submodules as $submodule => $path) {
if (basename($_SERVER['SCRIPT_FILENAME']) == $path) {
print "<li class='active'>";
}
else {
print '<li>';
}
print "<a href='/${THIS_MODULE_PATH}/{$path}'>" . ucwords($submodule) . "</a></li>\n";
}
?>
</ul>
</div>
</nav>
<?php
}
?>

212
ldap_manager/new_user.php Normal file
View File

@ -0,0 +1,212 @@
<?php
include_once("web_functions.inc.php");
include_once("ldap_functions.inc.php");
include_once("module_functions.inc.php");
set_page_access("admin");
render_header($WEBSITE_NAME);
$invalid_password = False;
$mismatched_passwords = False;
$invalid_username = False;
$weak_password = False;
if (isset($_POST['create_account'])) {
$ldap_connection = open_ldap_connection();
$first_name = stripslashes($_POST['first_name']);
$last_name = stripslashes($_POST['last_name']);
$username = stripslashes($_POST['username']);
$password = $_POST['password'];
if (!is_numeric($_POST['pass_score']) or $_POST['pass_score'] < 3) { $weak_password = True; }
if (preg_match("/\"|'/",$password)) { $invalid_password = True; }
if ($_POST['password'] != $_POST['password_match']) { $mismatched_passwords = True; }
if (!preg_match("/$USERNAME_REGEX/",$username)) { $invalid_username = True; }
if ( isset($first_name)
and isset($last_name)
and isset($username)
and isset($password)
and !$mismatched_passwords
and !$weak_password
and !$invalid_password
and !$invalid_username ) {
$ldap_connection = open_ldap_connection();
$new_account = ldap_new_account($ldap_connection, $first_name, $last_name, $username, $password);
if ($new_account) {
?>
<div class="alert alert-success">
<p class="text-center">Account created.</p>
</div>
<form action='/<?php print $THIS_MODULE_PATH; ?>/'>
<p align="center">
<input type='submit' class="btn btn-success" value='Finished'>
</p>
</form>
<?php
render_footer();
exit(0);
}
else {
if (!$new_account) { ?>
<div class="alert alert-warning">
<p class="text-center">Couldn't create the account.</p>
</div>
<?php
}
render_footer();
exit(0);
}
}
}
if ($weak_password) { ?>
<div class="alert alert-warning">
<p class="text-center">The password wasn't strong enough.</p>
</div>
<?php }
if ($invalid_password) { ?>
<div class="alert alert-warning">
<p class="text-center">The password contained invalid characters.</p>
</div>
<?php }
if ($mismatched_passwords) { ?>
<div class="alert alert-warning">
<p class="text-center">The passwords didn't match.</p>
</div>
<?php }
if ($invalid_username) { ?>
<div class="alert alert-warning">
<p class="text-center">The username is invalid.</p>
</div>
<?php }
render_js_username_generator('first_name','last_name','username','username_div');
?>
<script src="//cdnjs.cloudflare.com/ajax/libs/zxcvbn/1.0/zxcvbn.min.js"></script>
<script type="text/javascript" src="/js/zxcvbn-bootstrap-strength-meter.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#StrengthProgressBar").zxcvbnProgressBar({ passwordInput: "#password" });
});
</script>
<script type="text/javascript" src="/js/generate_passphrase.js"></script>
<script type="text/javascript" src="/js/wordlist.js"></script>
<script>
function check_passwords_match() {
if (document.getElementById('password').value != document.getElementById('confirm').value ) {
document.getElementById('password_div').classList.add("has-error");
document.getElementById('confirm_div').classList.add("has-error");
}
else {
document.getElementById('password_div').classList.remove("has-error");
document.getElementById('confirm_div').classList.remove("has-error");
}
}
function random_password() {
generatePassword(4,'-','password','confirm');
$("#StrengthProgressBar").zxcvbnProgressBar({ passwordInput: "#password" });
}
function back_to_hidden(passwordField,confirmField) {
var passwordField = document.getElementById(passwordField).type = 'password';
var confirmField = document.getElementById(confirmField).type = 'password';
}
</script>
<div class="container">
<div class="col-sm-7">
<div class="panel panel-default">
<div class="panel-heading text-center">New account</div>
<div class="panel-body text-center">
<form class="form-horizontal" action="" method="post">
<input type="hidden" name="create_account">
<input type="hidden" id="pass_score" value="0" name="pass_score">
<div class="form-group">
<label for="first_name" class="col-sm-2 control-label">First name</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="first_name" name="first_name" <?php if (isset($first_name)){ print " value='$first_name'"; } ?> onkeyup="update_username()">
</div>
</div>
<div class="form-group">
<label for="last_name" class="col-sm-2 control-label">Last name</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="last_name" name="last_name" <?php if (isset($last_name)){ print " value='$last_name'"; } ?> onkeyup="update_username()">
</div>
</div>
<div class="form-group" id="username_div">
<label for="username" class="col-sm-2 control-label">Username</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="username" name="username" <?php if (isset($username)){ print " value='$username'"; } ?> onkeyup="check_username_validity(document.getElementById('username').value)">
</div>
</div>
<div class="form-group" id="password_div">
<label for="password" class="col-sm-2 control-label">Password</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="password" name="password" onkeyup="back_to_hidden('password','confirm');">
</div>
<div class="col-sm-1">
<input type="button" class="btn btn-sm" id="password_generator" onclick="random_password();" value="Generate password">
</div>
</div>
<div class="form-group" id="confirm_div">
<label for="confirm" class="col-sm-2 control-label">Confirm</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="confirm" name="password_match" onkeyup="check_passwords_match()">
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-warning">Create account</button>
</div>
</form>
<div class="progress">
<div id="StrengthProgressBar" class="progress-bar"></div>
</div>
</div>
</div>
</div>
</div>
<?php
render_footer();
?>

302
ldap_manager/show_group.php Normal file
View File

@ -0,0 +1,302 @@
<?php
include_once("web_functions.inc.php");
set_page_access("admin");
include_once("ldap_functions.inc.php");
include_once("module_functions.inc.php");
render_header("LDAP manager");
render_submenu();
$ldap_connection = open_ldap_connection();
if (!isset($_POST['group_name']) and !isset($_GET['group_name'])) {
?>
<div class="alert alert-danger">
<p class="text-center">The group name is missing.</p>
</div>
<?php
render_footer();
exit(0);
}
else {
$group_cn = (isset($_POST['group_name']) ? $_POST['group_name'] : $_GET['group_name']);
}
if (!preg_match("/$USERNAME_REGEX/",$group_cn)) {
?>
<div class="alert alert-danger">
<p class="text-center">The group name is invalid.</p>
</div>
<?php
render_footer();
exit(0);
}
if (isset($_POST['new_group'])) {
$group_add = ldap_new_group($ldap_connection,$group_cn);
}
######################################################################################
$ldap_search = ldap_search($ldap_connection, "${LDAP['group_dn']}", "cn=$group_cn");
$result = ldap_get_entries($ldap_connection, $ldap_search);
$current_members = array();
if ($result["count"] == 1) {
foreach ($result[0][$LDAP['group_membership_attribute']] as $key => $value) {
if ($key != 'count') {
$this_member = preg_replace("/^.*?=(.*?),.*/", "$1", $value);
array_push($current_members, $this_member);
}
}
}
$all_accounts = ldap_get_user_list($ldap_connection);
$all_people = array();
foreach ($all_accounts as $this_person => $attrs) {
array_push($all_people, $this_person);
}
$non_members = array_diff($all_people,$current_members);
if (isset($_POST["update_members"])) {
$updated_membership = array();
foreach ($_POST as $index => $member) {
if (is_numeric($index) and preg_match("/$USERNAME_REGEX/",$member)) {
array_push($updated_membership,$member);
}
}
$members_to_del = array_diff($current_members,$updated_membership);
$members_to_add = array_diff($updated_membership,$current_members);
foreach ($members_to_del as $this_member) {
ldap_delete_member_from_group($ldap_connection,$group_cn,$this_member);
}
foreach ($members_to_add as $this_member) {
ldap_add_member_to_group($ldap_connection,$group_cn,$this_member);
}
$non_members = array_diff($all_people,$updated_membership);
$group_members = $updated_membership;
?>
<script>
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<strong>Success!</strong> The group has been updated.
</div>
<?php
}
else {
$group_members = $current_members;
}
ldap_close($ldap_connection);
?>
<script type="text/javascript">
function show_delete_group_button() {
var group_del_submit = document.getElementById('delete_group');
group_del_submit.classList.replace('invisible','visible');
}
function update_form_with_users() {
var members_form = document.getElementById('group_members');
var member_list_ul = document.getElementById('membership_list');
var member_list = member_list_ul.getElementsByTagName("li");
for (var i = 0; i < member_list.length; ++i) {
var hidden = document.createElement("input");
hidden.type = "hidden";
hidden.name = i;
hidden.value = member_list[i]['textContent'];
members_form.appendChild(hidden);
}
members_form.submit();
}
$(function () {
$('body').on('click', '.list-group .list-group-item', function () {
$(this).toggleClass('active');
});
$('.list-arrows button').click(function () {
var $button = $(this), actives = '';
if ($button.hasClass('move-left')) {
actives = $('.list-right ul li.active');
actives.clone().appendTo('.list-left ul');
$('.list-left ul li.active').removeClass('active');
actives.remove();
} else if ($button.hasClass('move-right')) {
actives = $('.list-left ul li.active');
actives.clone().appendTo('.list-right ul');
$('.list-right ul li.active').removeClass('active');
actives.remove();
}
$("#submit_members").prop("disabled", false);
});
$('.dual-list .selector').click(function () {
var $checkBox = $(this);
if (!$checkBox.hasClass('selected')) {
$checkBox.addClass('selected').closest('.well').find('ul li:not(.active)').addClass('active');
$checkBox.children('i').removeClass('glyphicon-unchecked').addClass('glyphicon-check');
} else {
$checkBox.removeClass('selected').closest('.well').find('ul li.active').removeClass('active');
$checkBox.children('i').removeClass('glyphicon-check').addClass('glyphicon-unchecked');
}
});
$('[name="SearchDualList"]').keyup(function (e) {
var code = e.keyCode || e.which;
if (code == '9') return;
if (code == '27') $(this).val(null);
var $rows = $(this).closest('.dual-list').find('.list-group li');
var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();
$rows.show().filter(function () {
var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
return !~text.indexOf(val);
}).hide();
});
});
</script>
<style type='text/css'>
.dual-list .list-group {
margin-top: 8px;
}
.list-left li, .list-right li {
cursor: pointer;
}
.list-arrows {
padding-top: 100px;
}
.list-arrows button {
margin-bottom: 20px;
}
.right_button {
width: 200px;
float: right;
}
</style>
<div class="container">
<div class="panel panel-default">
<div class="panel-heading clearfix">
<h3 class="panel-title pull-left" style="padding-top: 7.5px;"><?php print $group_cn; ?></h3>
<button class="btn btn-warning pull-right" onclick="show_delete_group_button();">Delete group</button>
<form action="/<?php print $THIS_MODULE_PATH; ?>/groups.php" method="post"><input type="hidden" name="delete_group" value="<?php print $group_cn; ?>"><button class="btn btn-danger pull-right invisible" id="delete_group">Confirm deletion</button></form>
</div>
<div class="panel-body">
<div class="row">
<div class="dual-list list-left col-md-5">
<strong>Members</strong>
<div class="well">
<div class="row">
<div class="col-md-10">
<div class="input-group">
<span class="input-group-addon glyphicon glyphicon-search"></span>
<input type="text" name="SearchDualList" class="form-control" placeholder="search" />
</div>
</div>
<div class="col-md-2">
<div class="btn-group">
<a class="btn btn-default selector" title="select all"><i class="glyphicon glyphicon-unchecked"></i></a>
</div>
</div>
</div>
<ul class="list-group" id="membership_list">
<?php
foreach ($group_members as $member) {
print "<li class='list-group-item'>$member</li>\n";
}
?>
</ul>
</div>
</div>
<div class="list-arrows col-md-1 text-center">
<button class="btn btn-default btn-sm move-left">
<span class="glyphicon glyphicon-chevron-left"></span>
</button>
<button class="btn btn-default btn-sm move-right">
<span class="glyphicon glyphicon-chevron-right"></span>
</button>
<form id="group_members" action="<?php print $CURRENT_PAGE; ?>" method="post">
<input type="hidden" name="update_members">
<input type="hidden" name="group_name" value="<?php print $group_cn; ?>">
</form>
<button id="submit_members" class="btn btn-info" disabled type="submit" onclick="update_form_with_users()">Save</button>
</div>
<div class="dual-list list-right col-md-5">
<strong>Available accounts</strong>
<div class="well">
<div class="row">
<div class="col-md-2">
<div class="btn-group">
<a class="btn btn-default selector" title="select all"><i class="glyphicon glyphicon-unchecked"></i></a>
</div>
</div>
<div class="col-md-10">
<div class="input-group">
<input type="text" name="SearchDualList" class="form-control" placeholder="search" />
<span class="input-group-addon glyphicon glyphicon-search"></span>
</div>
</div>
</div>
<ul class="list-group">
<?php
foreach ($non_members as $nonmember) {
print "<li class='list-group-item'>$nonmember</li>\n";
}
?>
</ul>
</div>
</div>
</div>
</div>
<?php
render_footer();
?>

472
ldap_manager/show_user.php Normal file
View File

@ -0,0 +1,472 @@
<?php
include_once("web_functions.inc.php");
include_once("ldap_functions.inc.php");
include_once("module_functions.inc.php");
set_page_access("admin");
render_header($WEBSITE_NAME);
$invalid_password = False;
$mismatched_passwords = False;
$invalid_username = False;
$weak_password = False;
$attribute_map = array( "givenname" => "First name",
"sn" => "Last name",
"uidnumber" => "UID",
"gidnumber" => "GID",
"loginshell" => "Login shell",
"homedirectory" => "Home directory"
);
$ldap_connection = open_ldap_connection();
if (!isset($_POST['username']) and !isset($_GET['username'])) {
?>
<div class="alert alert-danger">
<p class="text-center">The username is missing.</p>
</div>
<?php
render_footer();
exit(0);
}
else {
$username = (isset($_POST['username']) ? $_POST['username'] : $_GET['username']);
}
if (!preg_match("/$USERNAME_REGEX/",$username)) {
?>
<div class="alert alert-danger">
<p class="text-center">The username is invalid.</p>
</div>
<?php
render_footer();
exit(0);
}
$ldap_search = ldap_search( $ldap_connection, $LDAP['base_dn'], "(${LDAP['account_attribute']}=$username)" );
if ($ldap_search) {
$user = ldap_get_entries($ldap_connection, $ldap_search);
################################################
### Check for updates
if (isset($_POST['update_account'])) {
$to_update = array();
foreach ($attribute_map as $key => $value) {
if ($user[0][$key][0] != $_POST[$key]) {
$to_update[$key] = $_POST[$key];
$user[0][$key][0] = $_POST[$key];
}
}
if (isset($_POST['password']) and $_POST['password'] != "") {
$password = $_POST['password'];
if (!is_numeric($_POST['pass_score']) or $_POST['pass_score'] < 3) { $weak_password = True; }
if (preg_match("/\"|'/",$password)) { $invalid_password = True; }
if ($_POST['password'] != $_POST['password_match']) { $mismatched_passwords = True; }
if (!preg_match("/$USERNAME_REGEX/",$username)) { $invalid_username = True; }
if ( !$mismatched_passwords
and !$weak_password
and !$invalid_password
) {
$to_update['userpassword'] = ldap_hashed_password($password);
}
}
$updated_account = ldap_mod_replace($ldap_connection, $user[0]['dn'] , $to_update);
if ($updated_account) {
?>
<script>
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<strong>Success!</strong> The group has been updated.
</div>
<?php
}
else {
?>
<script>
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<strong>Success!</strong> The group has been updated.
</div>
<?php
}
}
if ($weak_password) { ?>
<div class="alert alert-warning">
<p class="text-center">The password wasn't strong enough.</p>
</div>
<?php }
if ($invalid_password) { ?>
<div class="alert alert-warning">
<p class="text-center">The password contained invalid characters.</p>
</div>
<?php }
if ($mismatched_passwords) { ?>
<div class="alert alert-warning">
<p class="text-center">The passwords didn't match.</p>
</div>
<?php }
################################################
$all_groups = ldap_get_group_list($ldap_connection);
$currently_member_of = array();
foreach ($all_groups as $this_group) {
if (ldap_is_group_member($ldap_connection,$this_group,$username)) {
array_push($currently_member_of,$this_group);
}
}
$not_member_of = array_diff($all_groups,$currently_member_of);
######### Add/remove from groups
if (isset($_POST["update_member_of"])) {
$updated_group_membership = array();
foreach ($_POST as $index => $group) {
if (is_numeric($index) and preg_match("/$USERNAME_REGEX/",$group)) {
array_push($updated_group_membership,$group);
}
}
$groups_to_add = array_diff($updated_group_membership,$currently_member_of);
$groups_to_del = array_diff($currently_member_of,$updated_group_membership);
foreach ($groups_to_del as $this_group) {
ldap_delete_member_from_group($ldap_connection,$this_group,$username);
}
foreach ($groups_to_add as $this_group) {
ldap_add_member_to_group($ldap_connection,$this_group,$username);
}
$not_member_of = array_diff($all_groups,$updated_group_membership);
$member_of = $updated_group_membership;
?>
<script>
window.setTimeout(function() {
$(".alert").fadeTo(500, 0).slideUp(500, function(){ $(this).remove(); });
}, 4000);
</script>
<div class="alert alert-success" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<strong>Success!</strong> The group has been updated.
</div>
<?php
}
else {
$member_of = $currently_member_of;
}
################
?>
<script src="//cdnjs.cloudflare.com/ajax/libs/zxcvbn/1.0/zxcvbn.min.js"></script>
<script type="text/javascript" src="/js/zxcvbn-bootstrap-strength-meter.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$("#StrengthProgressBar").zxcvbnProgressBar({ passwordInput: "#password" });
});
</script>
<script type="text/javascript" src="/js/generate_passphrase.js"></script>
<script type="text/javascript" src="/js/wordlist.js"></script>
<script>
function show_delete_user_button() {
group_del_submit = document.getElementById('delete_user');
group_del_submit.classList.replace('invisible','visible');
}
function check_passwords_match() {
if (document.getElementById('password').value != document.getElementById('confirm').value ) {
document.getElementById('password_div').classList.add("has-error");
document.getElementById('confirm_div').classList.add("has-error");
}
else {
document.getElementById('password_div').classList.remove("has-error");
document.getElementById('confirm_div').classList.remove("has-error");
}
}
function random_password() {
generatePassword(4,'-','password','confirm');
$("#StrengthProgressBar").zxcvbnProgressBar({ passwordInput: "#password" });
}
function back_to_hidden(passwordField,confirmField) {
var passwordField = document.getElementById(passwordField).type = 'password';
var confirmField = document.getElementById(confirmField).type = 'password';
}
function update_form_with_groups() {
var group_form = document.getElementById('update_with_groups');
var group_list_ul = document.getElementById('member_of_list');
var group_list = group_list_ul.getElementsByTagName("li");
for (var i = 0; i < group_list.length; ++i) {
var hidden = document.createElement("input");
hidden.type = "hidden";
hidden.name = i;
hidden.value = group_list[i]['textContent'];
group_form.appendChild(hidden);
}
group_form.submit();
}
$(function () {
$('body').on('click', '.list-group .list-group-item', function () {
$(this).toggleClass('active');
});
$('.list-arrows button').click(function () {
var $button = $(this), actives = '';
if ($button.hasClass('move-left')) {
actives = $('.list-right ul li.active');
actives.clone().appendTo('.list-left ul');
$('.list-left ul li.active').removeClass('active');
actives.remove();
} else if ($button.hasClass('move-right')) {
actives = $('.list-left ul li.active');
actives.clone().appendTo('.list-right ul');
$('.list-right ul li.active').removeClass('active');
actives.remove();
}
$("#submit_members").prop("disabled", false);
});
$('.dual-list .selector').click(function () {
var $checkBox = $(this);
if (!$checkBox.hasClass('selected')) {
$checkBox.addClass('selected').closest('.well').find('ul li:not(.active)').addClass('active');
$checkBox.children('i').removeClass('glyphicon-unchecked').addClass('glyphicon-check');
} else {
$checkBox.removeClass('selected').closest('.well').find('ul li.active').removeClass('active');
$checkBox.children('i').removeClass('glyphicon-check').addClass('glyphicon-unchecked');
}
});
$('[name="SearchDualList"]').keyup(function (e) {
var code = e.keyCode || e.which;
if (code == '9') return;
if (code == '27') $(this).val(null);
var $rows = $(this).closest('.dual-list').find('.list-group li');
var val = $.trim($(this).val()).replace(/ +/g, ' ').toLowerCase();
$rows.show().filter(function () {
var text = $(this).text().replace(/\s+/g, ' ').toLowerCase();
return !~text.indexOf(val);
}).hide();
});
});
</script>
<div class="container">
<div class="col-sm-7">
<div class="panel panel-default">
<div class="panel-heading clearfix">
<h3 class="panel-title pull-left" style="padding-top: 7.5px;"><?php print $user[0]['uid'][0]; ?></h3>
<button class="btn btn-warning pull-right" onclick="show_delete_user_button();">Delete account</button>
<form action="/<?php print $THIS_MODULE_PATH; ?>/index.php" method="post"><input type="hidden" name="delete_user" value="<?php print $username; ?>"><button class="btn btn-danger pull-right invisible" id="delete_user">Confirm deletion</button></form>
</div>
<div class="panel-body">
<form class="form-horizontal" action="" method="post">
<input type="hidden" name="update_account">
<input type="hidden" id="pass_score" value="0" name="pass_score">
<input type="hidden" name="username" value="<?php print $username; ?>">
<?php
foreach ($attribute_map as $key => $value) {
?>
<div class="form-group">
<label for="<?php print $key; ?>" class="col-sm-3 control-label"><?php print $value; ?></label>
<div class="col-sm-6">
<input type="text" class="form-control" id="<?php print $key; ?>" name="<?php print $key; ?>" value="<?php print $user[0][$key][0]; ?>">
</div>
</div>
<?php
}
?>
<div class="form-group" id="password_div">
<label for="password" class="col-sm-3 control-label">Password</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="password" name="password" onkeyup="back_to_hidden('password','confirm');">
</div>
<div class="col-sm-1">
<input type="button" class="btn btn-sm" id="password_generator" onclick="random_password();" value="Generate password">
</div>
</div>
<div class="form-group" id="confirm_div">
<label for="confirm" class="col-sm-3 control-label">Confirm</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="confirm" name="password_match" onkeyup="check_passwords_match()">
</div>
</div>
<div class="form-group">
<p align='center'><button type="submit" class="btn btn-default">Update account details</button></p>
</div>
</form>
<div class="progress">
<div id="StrengthProgressBar" class="progress-bar"></div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="col-sm-12">
<div class="panel panel-default">
<div class="panel-heading clearfix">
<h3 class="panel-title pull-left" style="padding-top: 7.5px;">Group membership</h3>
</div>
<div class="panel-body">
<div class="row">
<div class="dual-list list-left col-md-5">
<strong>Member of</strong>
<div class="well">
<div class="row">
<div class="col-md-10">
<div class="input-group">
<span class="input-group-addon glyphicon glyphicon-search"></span>
<input type="text" name="SearchDualList" class="form-control" placeholder="search" />
</div>
</div>
<div class="col-md-2">
<div class="btn-group">
<a class="btn btn-default selector" title="select all"><i class="glyphicon glyphicon-unchecked"></i></a>
</div>
</div>
</div>
<ul class="list-group" id="member_of_list">
<?php
foreach ($member_of as $group) {
print "<li class='list-group-item'>$group</li>\n";
}
?>
</ul>
</div>
</div>
<div class="list-arrows col-md-1 text-center">
<button class="btn btn-default btn-sm move-left">
<span class="glyphicon glyphicon-chevron-left"></span>
</button>
<button class="btn btn-default btn-sm move-right">
<span class="glyphicon glyphicon-chevron-right"></span>
</button>
<form id="update_with_groups" action="<?php print $CURRENT_PAGE; ?>" method="post">
<input type="hidden" name="update_member_of">
<input type="hidden" name="username" value="<?php print $username; ?>">
</form>
<button id="submit_members" class="btn btn-info" disabled type="submit" onclick="update_form_with_groups()">Save</button>
</div>
<div class="dual-list list-right col-md-5">
<strong>Available groups</strong>
<div class="well">
<div class="row">
<div class="col-md-2">
<div class="btn-group">
<a class="btn btn-default selector" title="select all"><i class="glyphicon glyphicon-unchecked"></i></a>
</div>
</div>
<div class="col-md-10">
<div class="input-group">
<input type="text" name="SearchDualList" class="form-control" placeholder="search" />
<span class="input-group-addon glyphicon glyphicon-search"></span>
</div>
</div>
</div>
<ul class="list-group">
<?php
foreach ($not_member_of as $group) {
print "<li class='list-group-item'>$group</li>\n";
}
?>
</ul>
</div>
</div>
</div>
</div>
</div>
<?php
}
render_footer();
?>

76
log_in/index.php Normal file
View File

@ -0,0 +1,76 @@
<?php
include("web_functions.inc.php");
include("ldap_functions.inc.php");
if (isset($_POST["user_id"]) and isset($_POST["password"])) {
$ldap_connection = open_ldap_connection();
$user_auth = ldap_auth_username($ldap_connection,$_POST["user_id"],$_POST["password"]);
$is_admin = ldap_check_is_admin($_POST["user_id"],$ldap_connection);
ldap_close($ldap_connection);
if ($user_auth != False) {
set_passkey_cookie($user_auth,$is_admin);
if (isset($_POST["sendto"])) {
header("Location: //${_SERVER["HTTP_HOST"]}${_POST["sendto"]}\n\n");
}
else {
header("Location: //${_SERVER["HTTP_HOST"]}/index.php?logged_in\n\n");
}
}
else {
header("Location: //${_SERVER["HTTP_HOST"]}/${THIS_MODULE_PATH}/index.php?invalid\n\n");
}
}
else {
render_header("Log in");
?>
<div class="container">
<div class="col-sm-8">
<div class="panel panel-default">
<div class="panel-heading text-center">Log in</div>
<div class="panel-body text-center">
<?php if (isset($_GET["invalid"])) { ?>
<div class="alert alert-warning">
The username and/or password are unrecognised.
</div>
<?php } ?>
<form class="form-horizontal" action='' method='post'>
<?php if (isset($sendto) and ($sendto != "")) { ?><input type="hidden" name="sendto" value="<?php print $sendto; ?>"><?php } ?>
<div class="form-group">
<label for="username" class="col-sm-4 control-label">Username</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="user_id" name="user_id">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-4 control-label">Password</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="confirm" name="password">
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-default">Log in</button>
</div>
</form>
</div>
</div>
</div>
<?php
}
render_footer();
?>

4
log_out/index.php Normal file
View File

@ -0,0 +1,4 @@
<?php
include("web_functions.inc.php");
log_out();
?>

52
setup/index.php Normal file
View File

@ -0,0 +1,52 @@
<?php
include("web_functions.inc.php");
include("ldap_functions.inc.php");
if (isset($_POST["admin_password"])) {
$ldap_connection = open_ldap_connection();
$user_auth = ldap_setup_auth($ldap_connection,$_POST["admin_password"]);
ldap_close($ldap_connection);
if ($user_auth != False) {
set_setup_cookie($user_auth);
header("Location: //${_SERVER["HTTP_HOST"]}/${THIS_MODULE_PATH}/run_checks.php\n\n");
}
else {
header("Location: //${_SERVER["HTTP_HOST"]}/${THIS_MODULE_PATH}/index.php?invalid\n\n");
}
}
else {
render_header("Setup log in");
if (isset($_GET["invalid"])) {
?>
<div class="alert alert-warning">
<p class="text-center">The password was incorrect.</p>
</div>
<?php
}
?>
<div class="container">
<div class="panel panel-default">
<div class="panel-heading text-center">Password for <?php print $LDAP['admin_bind_dn']; ?></div>
<div class="panel-body text-center">
<form class="form-inline" action='' method='post'>
<div class="form-group">
<input type='password' class="form-control" name='admin_password'>
</div>
<div class="form-group">
<input type='submit' class="btn btn-default" value='Log in'>
</div>
</form>
</div>
</div>
</div>
</div>
<?php
}
render_footer();
?>

View File

@ -0,0 +1,7 @@
<?php
$li_good="<li class='list-group-item list-group-item-success'>$GOOD_ICON";
$li_warn="<li class='list-group-item list-group-item-warning'>$WARN_ICON";
$li_fail="<li class='list-group-item list-group-item-danger'>$FAIL_ICON";
?>

235
setup/run_checks.php Normal file
View File

@ -0,0 +1,235 @@
<?php
include_once("web_functions.inc.php");
include_once("ldap_functions.inc.php");
include_once("module_functions.inc.php");
validate_setup_cookie();
set_page_access("setup");
render_header($WEBSITE_NAME);
$show_finish_button = True;
$ldap_connection = open_ldap_connection();
?>
<script>
$(document).ready(function(){
$('[data-toggle="popover"]').popover();
});
</script>
<div class="form-group">
<form action="<?php print "/$THIS_MODULE_PATH/setup_ldap.php"; ?>" method="post">
<input type="hidden" name="fix_problems">
<div class='container'>
<div class="panel panel-default">
<div class="panel-heading">LDAP connection tests</div>
<div class="panel-body">
<ul class="list-group">
<?php
#Can we connect? The open_ldap_connection() function will call die() if we can't.
print "$li_good Connected to ${LDAP['uri']}</li>\n";
#TLS?
if ($LDAP['starttls'] && $ENCRYPTED == True) {
print "$li_good Encrypted connection to ${LDAP['uri']} via STARTTLS</li>\n";
}
else {
print "$li_warn Unable to connect to ${LDAP['uri']} via STARTTLS. ";
print "<a href='#' data-toggle='popover' title='STARTTLS' data-content='";
print "The connection to the LDAP server works, but encrypted communication can&#39;t be enabled.";
print "'>What's this?</a></li>\n";
}
?>
</ul>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">LDAP OU checks</div>
<div class="panel-body">
<ul class="list-group">
<?php
$group_filter = "(&(objectclass=organizationalUnit)(ou=${LDAP['group_ou']}))";
$ldap_group_search = ldap_search($ldap_connection, "${LDAP['base_dn']}", $group_filter);
$group_result = ldap_get_entries($ldap_connection, $ldap_group_search);
if ($group_result['count'] != 1) {
print "$li_fail The group OU (<strong>${LDAP['group_dn']}</strong>) doesn't exist. ";
print "<a href='#' data-toggle='popover' title='${LDAP['group_dn']}' data-content='";
print "This is the Organizational Unit (OU) that the groups are stored under.";
print "'>What's this?</a>";
print "<label class='pull-right'><input type='checkbox' name='setup_group_ou' class='pull-right' checked>Create?&nbsp;</label>";
print "</li>\n";
$show_finish_button = False;
}
else {
print "$li_good The group OU (<strong>${LDAP['group_dn']}</strong>) is present.</li>";
}
$user_filter = "(&(objectclass=organizationalUnit)(ou=${LDAP['user_ou']}))";
$ldap_user_search = ldap_search($ldap_connection, "${LDAP['base_dn']}", $user_filter);
$user_result = ldap_get_entries($ldap_connection, $ldap_user_search);
if ($user_result['count'] != 1) {
print "$li_fail The user OU (<strong>${LDAP['user_dn']}</strong>) doesn't exist. ";
print "<a href='#' data-toggle='popover' title='${LDAP['user_dn']}' data-content='";
print "This is the Organisational Unit (OU) that the user accounts are stored under.";
print "'>What's this?</a>";
print "<label class='pull-right'><input type='checkbox' name='setup_user_ou' class='pull-right' checked>Create?&nbsp;</label>";
print "</li>\n";
$show_finish_button = False;
}
else {
print "$li_good The user OU (<strong>${LDAP['user_dn']}</strong>) is present.</li>";
}
?>
</ul>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">LDAP group and settings</div>
<div class="panel-body">
<ul class="list-group">
<?php
$gid_filter = "(&(objectclass=device)(cn=lastGID))";
$ldap_gid_search = ldap_search($ldap_connection, "${LDAP['base_dn']}", $gid_filter);
$gid_result = ldap_get_entries($ldap_connection, $ldap_gid_search);
if ($gid_result['count'] != 1) {
print "$li_warn The <strong>lastGID</strong> entry doesn't exist. ";
print "<a href='#' data-toggle='popover' title='cn=lastGID,${LDAP['base_dn']}' data-content='";
print "This is used to store the last group ID used when creating a POSIX group. Without this the highest current group ID is found and incremented, but this might re-use the GID from a deleted group.";
print "'>What's this?</a>";
print "<label class='pull-right'><input type='checkbox' name='setup_last_gid' class='pull-right' checked>Create?&nbsp;</label>";
print "</li>\n";
$show_finish_button = False;
}
else {
print "$li_good The <strong>lastGID</strong> entry is present.</li>";
}
$uid_filter = "(&(objectclass=device)(cn=lastUID))";
$ldap_uid_search = ldap_search($ldap_connection, "${LDAP['base_dn']}", $uid_filter);
$uid_result = ldap_get_entries($ldap_connection, $ldap_uid_search);
if ($uid_result['count'] != 1) {
print "$li_warn The <strong>lastUID</strong> entry doesn't exist. ";
print "<a href='#' data-toggle='popover' title='cn=lastUID,${LDAP['base_dn']}' data-content='";
print "This is used to store the last user ID used when creating a POSIX account. Without this the highest current user ID is found and incremented, but this might re-use the UID from a deleted account.";
print "'>What's this?</a>";
print "<label class='pull-right'><input type='checkbox' name='setup_last_uid' class='pull-right' checked>Create?&nbsp;</label>";
print "</li>\n";
$show_finish_button = False;
}
else {
print "$li_good The <strong>lastUID</strong> entry is present.</li>";
}
$defgroup_filter = "(&(objectclass=posixGroup)(cn=${DEFAULT_USER_GROUP}))";
$ldap_defgroup_search = ldap_search($ldap_connection, "${LDAP['base_dn']}", $defgroup_filter);
$defgroup_result = ldap_get_entries($ldap_connection, $ldap_defgroup_search);
if ($defgroup_result['count'] != 1) {
print "$li_warn The default group (<strong>$DEFAULT_USER_GROUP</strong>) doesn't exist. ";
print "<a href='#' data-toggle='popover' title='Default user group' data-content='";
print "When we add users we need to assign them a default group ($DEFAULT_USER_GROUP). If this doesn&#39;t exist then a new group will be created to match each user account, which may not be desirable.";
print "'>What's this?</a>";
print "<label class='pull-right'><input type='checkbox' name='setup_default_group' class='pull-right' checked>Create?&nbsp;</label>";
print "</li>\n";
$show_finish_button = False;
}
else {
print "$li_good The default user group (<strong>$DEFAULT_USER_GROUP</strong>) is present.</li>";
}
$adminsgroup_filter = "(&(objectclass=posixGroup)(cn=${LDAP['admins_group']}))";
$ldap_adminsgroup_search = ldap_search($ldap_connection, "${LDAP['base_dn']}", $adminsgroup_filter);
$adminsgroup_result = ldap_get_entries($ldap_connection, $ldap_adminsgroup_search);
if ($adminsgroup_result['count'] != 1) {
print "$li_fail The group defining LDAP account administrators (<strong>${LDAP['admins_group']}</strong>) doesn't exist. ";
print "<a href='#' data-toggle='popover' title='LDAP account administrators group' data-content='";
print "Only members of this group (${LDAP['admins_group']}) will be able to access the account managment section, so it&#39;s definitely something you&#39;ll want to create.";
print "'>What's this?</a>";
print "<label class='pull-right'><input type='checkbox' name='setup_admins_group' class='pull-right' checked>Create?&nbsp;</label>";
print "</li>\n";
$show_finish_button = False;
}
else {
print "$li_good The LDAP account administrators group (<strong>${LDAP['admins_group']}</strong>) is present.</li>";
$admins = ldap_get_group_members($ldap_connection,$LDAP['admins_group']);
if (count($admins) < 1) {
print "$li_fail The LDAP administration group is empty. You can add an admin account in the next section.</li>";
$show_finish_button = False;
}
}
?>
</ul>
</div>
</div>
<?php
##############
if ($show_finish_button == True) {
?>
</form>
<div class='well'>
<form action="/log_in">
<input type='submit' class="btn btn-success center-block" value='Done'>
</form>
</div>
<?php
}
else {
?>
<div class='well'>
<input type='submit' class="btn btn-primary center-block" value='Next >'>
</div>
</form>
<?php
}
?>
</div>
</div>
<?php
render_footer();
?>

View File

@ -0,0 +1,204 @@
<?php
include_once("web_functions.inc.php");
include_once("ldap_functions.inc.php");
include_once("module_functions.inc.php");
validate_setup_cookie();
set_page_access("setup");
render_header($WEBSITE_NAME);
$invalid_password = False;
$mismatched_passwords = False;
$invalid_username = False;
$weak_password = False;
if (isset($_POST['create_account'])) {
$ldap_connection = open_ldap_connection();
$first_name = stripslashes($_POST['first_name']);
$last_name = stripslashes($_POST['last_name']);
$username = stripslashes($_POST['username']);
$password = $_POST['password'];
if (!is_numeric($_POST['pass_score']) or $_POST['pass_score'] < 3) { $weak_password = True; }
if (preg_match("/\"|'/",$password)) { $invalid_password = True; }
if ($_POST['password'] != $_POST['password_match']) { $mismatched_passwords = True; }
if (!preg_match("/$USERNAME_REGEX/",$username)) { $invalid_username = True; }
if ( isset($first_name)
and isset($last_name)
and isset($username)
and isset($password)
and !$mismatched_passwords
and !$weak_password
and !$invalid_password
and !$invalid_username ) {
$ldap_connection = open_ldap_connection();
$new_account = ldap_new_account($ldap_connection, $first_name, $last_name, $username, $password);
$member_add = ldap_add_member_to_group($ldap_connection, $LDAP['admins_group'], $username);
if ($new_account and $member_add) {
?>
<div class="alert alert-success">
<p class="text-center">Account created.</p>
</div>
<form action='/log_in'>
<p align="center">
<input type='submit' class="btn btn-success" value='Finished'>
</p>
</form>
<?php
render_footer();
exit(0);
}
else {
if (!$new_account) { ?>
<div class="alert alert-warning">
<p class="text-center">Couldn't create the account.</p>
</div>
<?php
}
if (!$member_add) { ?>
<div class="alert alert-warning">
<p class="text-center">Couldn't add the account to the admin group.</p>
</div>
<?php
}
?>
<form action='/setup/run_checks.php'>
<p align="center">
<input type='submit' class="btn btn-danger" value='Start again'>
</p>
</form>
<?php
render_footer();
exit(0);
}
}
}
if ($weak_password) { ?>
<div class="alert alert-warning">
<p class="text-center">The password wasn't strong enough.</p>
</div>
<?php }
if ($invalid_password) { ?>
<div class="alert alert-warning">
<p class="text-center">The password contained invalid characters.</p>
</div>
<?php }
if ($mismatched_passwords) { ?>
<div class="alert alert-warning">
<p class="text-center">The passwords didn't match.</p>
</div>
<?php }
if ($invalid_username) { ?>
<div class="alert alert-warning">
<p class="text-center">The username is invalid.</p>
</div>
<?php }
render_js_username_generator('first_name','last_name','username','username_div');
?>
<script src="//cdnjs.cloudflare.com/ajax/libs/zxcvbn/1.0/zxcvbn.min.js"></script>
<script type="text/javascript" src="/js/zxcvbn-bootstrap-strength-meter.js"></script>
<script type="text/javascript">$(document).ready(function(){ $("#StrengthProgressBar").zxcvbnProgressBar({ passwordInput: "#password" });});</script>
<script>
function check_passwords_match() {
if (document.getElementById('password').value != document.getElementById('confirm').value ) {
document.getElementById('password_div').classList.add("has-error");
document.getElementById('confirm_div').classList.add("has-error");
}
else {
document.getElementById('password_div').classList.remove("has-error");
document.getElementById('confirm_div').classList.remove("has-error");
}
}
</script>
<div class="container">
<div class="col-sm-8">
<div class="panel panel-default">
<div class="panel-heading text-center">New administrator account</div>
<div class="panel-body text-center">
<form class="form-horizontal" action="" method="post">
<input type="hidden" name="create_account">
<input type="hidden" id="pass_score" value="0" name="pass_score">
<div class="form-group">
<label for="first_name" class="col-sm-4 control-label">First name</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="first_name" name="first_name" <?php if (isset($first_name)){ print " value='$first_name'"; } ?> onkeyup="update_username()">
</div>
</div>
<div class="form-group">
<label for="last_name" class="col-sm-4 control-label">Last name</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="last_name" name="last_name" <?php if (isset($last_name)){ print " value='$last_name'"; } ?> onkeyup="update_username()">
</div>
</div>
<div class="form-group" id="username_div">
<label for="username" class="col-sm-4 control-label">Username</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="username" name="username" <?php if (isset($username)){ print " value='$username'"; } ?> onkeyup="check_username_validity(document.getElementById('username').value)">
</div>
</div>
<div class="form-group" id="password_div">
<label for="password" class="col-sm-4 control-label">Password</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="password" name="password">
</div>
</div>
<div class="col-sm-4 "></div>
<div class="col-sm-6 progress">
<div id="StrengthProgressBar" class="progress-bar"></div>
</div>
<div class="form-group" id="confirm_div">
<label for="password" class="col-sm-4 control-label">Confirm</label>
<div class="col-sm-6">
<input type="password" class="form-control" id="confirm" name="password_match" onkeyup="check_passwords_match()">
</div>
</div>
<div class="form-group">
<button type="submit" class="btn btn-warning">Create account</button>
</div>
</form>
</div>
</div>
</div>
</div>
<?php
render_footer();
?>

196
setup/setup_ldap.php Normal file
View File

@ -0,0 +1,196 @@
<?php
include_once("web_functions.inc.php");
include_once("ldap_functions.inc.php");
include_once("module_functions.inc.php");
validate_setup_cookie();
set_page_access("setup");
render_header($WEBSITE_NAME);
$ldap_connection = open_ldap_connection();
$no_errors = True;
$show_create_admin_button = False;
# Set up missing stuff
if (isset($_POST['fix_problems'])) {
?>
<script>
$(document).ready(function(){
$('[data-toggle="popover"]').popover();
});
</script>
<div class='container'>
<div class="panel panel-default">
<div class="panel-heading">Updating LDAP...</div>
<div class="panel-body">
<ul class="list-group">
<?php
if (isset($_POST['setup_group_ou'])) {
$ou_add = ldap_add($ldap_connection, $LDAP['group_dn'], array( 'objectClass' => 'organizationalUnit', 'ou' => $LDAP['group_ou'] ));
if ($ou_add == True) {
print "$li_good Created OU <strong>${LDAP['group_dn']}</strong></li>\n";
}
else {
$error = ldap_error($ldap_connection);
print "$li_fail Couldn't create ${LDAP['group_dn']}: <pre>$error</pre></li>\n";
$no_errors = False;
}
}
if (isset($_POST['setup_user_ou'])) {
$ou_add = ldap_add($ldap_connection, $LDAP['user_dn'], array( 'objectClass' => 'organizationalUnit', 'ou' => $LDAP['user_ou'] ));
if ($ou_add == True) {
print "$li_good Created OU <strong>${LDAP['user_dn']}</strong></li>\n";
}
else {
$error = ldap_error($ldap_connection);
print "$li_fail Couldn't create ${LDAP['user_dn']}: <pre>$error</pre></li>\n";
$no_errors = False;
}
}
if (isset($_POST['setup_last_gid'])) {
$highest_gid = ldap_get_highest_id($ldap_connection,'gid');
$description = "Records the last GID used to create a Posix group. This prevents the re-use of a GID from a deleted group.";
$gid_add = ldap_add($ldap_connection, "cn=lastGID,${LDAP['base_dn']}", array( 'objectClass' => array('device','top'),
'serialnumber' => $highest_gid,
'description' => $description )
);
if ($gid_add == True) {
print "$li_good Created <strong>cn=lastGID,${LDAP['base_dn']}</strong></li>\n";
}
else {
$error = ldap_error($ldap_connection);
print "$li_fail Couldn't create cn=lastGID,${LDAP['base_dn']}: <pre>$error</pre></li>\n";
$no_errors = False;
}
}
if (isset($_POST['setup_last_uid'])) {
$highest_uid = ldap_get_highest_id($ldap_connection,'uid');
$description = "Records the last UID used to create a Posix account. This prevents the re-use of a UID from a deleted account.";
$uid_add = ldap_add($ldap_connection, "cn=lastUID,${LDAP['base_dn']}", array( 'objectClass' => array('device','top'),
'serialnumber' => $highest_uid,
'description' => $description )
);
if ($uid_add == True) {
print "$li_good Created <strong>cn=lastUID,${LDAP['base_dn']}</strong></li>\n";
}
else {
$error = ldap_error($ldap_connection);
print "$li_fail Couldn't create cn=lastUID,${LDAP['base_dn']}: <pre>$error</pre></li>\n";
$no_errors = False;
}
}
if (isset($_POST['setup_default_group'])) {
$group_add = ldap_new_group($ldap_connection,$DEFAULT_USER_GROUP);
if ($group_add == True) {
print "$li_good Created default group: <strong>$DEFAULT_USER_GROUP</strong></li>\n";
}
else {
$error = ldap_error($ldap_connection);
print "$li_fail Couldn't create default group: <pre>$error</pre></li>\n";
$no_errors = False;
}
}
if (isset($_POST['setup_admins_group'])) {
$group_add = ldap_new_group($ldap_connection,$LDAP['admins_group']);
if ($group_add == True) {
print "$li_good Created LDAP administrators group: <strong>${LDAP['admins_group']}</strong></li>\n";
}
else {
$error = ldap_error($ldap_connection);
print "$li_fail Couldn't create LDAP administrators group: <pre>$error</pre></li>\n";
$no_errors = False;
}
}
$admins = ldap_get_group_members($ldap_connection,$LDAP['admins_group']);
if (count($admins) < 1) {
?>
<div class="form-group">
<form action="<?php print "/$THIS_MODULE_PATH/setup_admin_account.php"; ?>" method="post">
<input type="hidden" name="setup_account">
<?php
print "$li_fail The LDAP administration group is empty. ";
print "<a href='#' data-toggle='popover' title='LDAP account administrators' data-content='";
print "Only members of this group (${LDAP['admins_group']}) will be able to access the account managment section, so we need to add people to it.";
print "'>What's this?</a>";
print "<label class='pull-right'><input type='checkbox' name='setup_admin_account' class='pull-right' checked>Create a new account and add it to the admin group?&nbsp;</label>";
print "</li>\n";
$show_create_admin_button = True;
}
else {
print "$li_good The LDAP account administrators group (<strong>${LDAP['admins_group']}</strong>) isn't empty.</li>";
}
?>
</ul>
</div>
</div>
<?php
##############
if ($no_errors == True) {
if ($show_create_admin_button == False) {
?>
<div class='well'>
<form action="/">
<input type='submit' class="btn btn-success center-block" value='Finished' class='center-block'>
</form>
</div>
<?php
}
else {
?>
<div class='well'>
<input type='submit' class="btn btn-warning center-block" value='Create new account >' class='center-block'>
</form>
</div>
<?php
}
}
else {
?>
<div class='well'>
<form action="/setup/run_checks.php">
<input type='submit' class="btn btn-danger center-block" value='< Re-run setup' class='center-block'>
</form>
</div>
<?php
}
}
render_footer();
?>