<?php
error_reporting(E_ALL | E_STRICT);
ini_set('track_errors', 'On');
$rg_cache_debug = TRUE;
$rg_util_debug = TRUE;
$rg_sql_debug = 100;
$test_normal = TRUE;
$INC = dirname(__FILE__) . '/../inc';
require_once(dirname(__FILE__) . '/config.php');
require_once($INC . '/init.inc.php');
require_once($INC . '/util.inc.php');
require_once($INC . '/ldap.inc.php');
require_once($INC . '/ldap_sync.inc.php');
require_once('helpers.inc.php');
require_once('http.inc.php');
rg_log_set_file('ldap.log');
require_once('common.php');
$_testns = 'admin_ldap';
function rg_ldap_start_server(&$l)
{
$prep = 'ldap/chroot-' . $l['rg_ldap_ns'] . '/prep.done';
$r = @unlink($prep);
rg_log('unlinking prep.done returned ' . ($r === FALSE ? 'false' : 'true'));
$log = __DIR__ . '/ldap-' . $l['rg_ldap_port'];
$pid = pcntl_fork();
if ($pid == 0) { // child
foreach ($l as $k => $v) {
rg_log($k . '=' . $v);
putenv($k . '=' . $v);
}
rg_exec('cd ldap && bash -x start.sh &> ' . $log . '.log', '', FALSE, FALSE, FALSE);
rg_exec('cd ldap && bash -x prepare.sh &> ' . $log . '.prep.log', '', FALSE, FALSE, FALSE);
exit(0);
}
rg_log('Child started with pid ' . $pid);
rg_log('Waiting for preparation to finish...');
$tries = 200;
while ($tries-- > 0) {
$x = @file_get_contents($prep);
if ($x !== FALSE)
break;
rg_log('prep file [' . $prep . '] is not present, wait.');
usleep(100000);
}
if ($tries == 0) {
rg_log('Could not prepare! Exit!');
posix_kill($pid, SIGKILL);
exit(1);
}
$l['log'] = $log;
}
function clean($log)
{
rg_log_set_file('ldap-clean.log');
rg_log('Cleaning processes attached to file ' . $log . '.log...');
$r = rg_exec('fuser -k -v -9 ' . escapeshellarg($log . '.log'), '', FALSE, FALSE, FALSE);
rg_log_ml('fuser returned: ' . print_r($r, TRUE));
}
$rg_ui = array('is_admin' => 1);
rg_test_create_user($db, $rg_ui);
$info = array('id' => $rg_ui['username']);
prepare_http($info);
$r = test_login($test_url, $rg_ui);
if ($r === FALSE) {
rg_log('Cannot login!');
exit(1);
}
rg_log('');
rg_log('Generating certificates...');
$r = rg_exec('./ca.sh ldap', '', FALSE, FALSE, FALSE);
if (!strstr($r['data'], 'CA_SH_OK')) {
rg_log_ml('data: ' . $r['data']);
rg_log('Cannot generate certificates!');
exit(1);
}
$bind_addr = '127.' . rand(1, 255) . '.' . rand(1,255) . '.' . rand(2,255);
$bind_port = 65100; $bind_ports = 65101;
$pass = rg_id(16);
$user_pass = rg_id(16);
$user_key = rg_id(16);
rg_log('bind_addr=' . $bind_addr . ' bind_port=' . $bind_port
. ' bind_ports=' . $bind_ports . ' pass=' . $pass
. ' user_pass=' . $user_pass . ' user_key=' . $user_key);
rg_log('');
rg_log_enter('Deleting all LDAP servers');
$sql = 'TRUNCATE ldap_servers';
$res = rg_sql_query($db, $sql);
if ($res === FALSE) {
rg_log('Cannot delete all LDAP servers');
exit(1);
}
rg_sql_free_result($res);
rg_cache_unset('ldap', RG_SOCKET_NO_WAIT);
rg_log_exit();
rg_log('');
rg_log_enter('Deleting LDAP cache');
$sql = 'TRUNCATE ldap_cache';
$res = rg_sql_query($db, $sql);
if ($res === FALSE) {
rg_log('Cannot delete LDAP cache');
exit(1);
}
rg_sql_free_result($res);
//TODO rg_cache_unset('ldap_cache', RG_SOCKET_NO_WAIT);
rg_log_exit();
rg_log('');
rg_log_enter('Loading Admin -> LDAP -> Add...');
$data = array();
$headers = array();
$r = do_req($info, $test_url . '/op/admin/ldap/add', $data, $headers);
if ($r === FALSE) {
rg_log('Cannot load add page!');
exit(1);
}
if (!isset($r['tokens']['ldap_add'])) {
rg_log_ml('r:' . print_r($r, TRUE));
rg_log('No ldap_add token?!');
exit(1);
}
$token = $r['tokens']['ldap_add'];
$id = rg_id(8);
$name = 'server-' . $id . ' <xss>';
rg_log('Posting the form...');
$data = array(
'doit' => 1,
'token' => $token,
'ldap::id' => 0,
'ldap::plan_id' => 0,
'ldap::prio' => 10,
'ldap::session_time' => 600,
'ldap::name' => $name,
'ldap::url' => 'ldap://' . $bind_addr . ':' . $bind_port,
'ldap::bind_dn' => '',
'ldap::bind_pass' => '',
'ldap::user_base' => 'dc=my-domain,dc=com',
'ldap::uid_attr' => 'uid',
'ldap::filter' => 'memberOf=cn=group1,ou=Group,dc=my-domain,dc=com',
'ldap::group_base' => 'dc=my-domain,dc=com',
'ldap::group_attr' => 'memberOf',
'ldap::group_filter' => '',
'ldap::admin_group' => 'cn=(Admins|Admins2),ou=Group,dc=my-domain,dc=com',
'ldap::ca_cert' => ''
);
$r = do_req($info, $test_url . '/op/admin/ldap/add', $data, $headers);
if (!strstr($r['body'], 'LDAP server has been successfully added/edited.')) {
rg_log_ml('body: ' . $r['body']);
rg_log('Success message not found!');
exit(1);
}
rg_log_exit();
rg_log('');
rg_log_enter('Loading Admin -> LDAP -> List...');
$data = array();
$headers = array();
$r = do_req($info, $test_url . '/op/admin/ldap/list', $data, $headers);
if ($r === FALSE) {
rg_log('Cannot load list page!');
exit(1);
}
// TODO, here test that everything is present in the list
$token = $r['tokens']['ldap_list'];
rg_log_exit();
rg_log('');
rg_log_enter('Setting up two LDAP servers in mirror mode...');
// We are forced to close the connection, else will get a nasty error,
// Even if the child is not doing anything with the connection.
rg_sql_close($db);
$l1 = array(
'rg_ldap_ns' => 's1',
'rg_ldap_addr' => $bind_addr,
'rg_ldap_port' => $bind_port,
'rg_ldap_ports' => $bind_ports,
'rg_ldap_server_id' => '001',
'rg_ldap_producer_url' => 'ldap://' . $bind_addr . ':' . ($bind_port + 2),
'rg_ldap_producer_rid' => '002',
'rg_ldap_add_data' => 1,
'rg_ldap_pass' => $pass,
'rg_ldap_user_pass' => $user_pass,
'rg_ldap_user_key' => $user_key
);
rg_ldap_start_server($l1);
$l2 = array(
'rg_ldap_ns' => 's2',
'rg_ldap_addr' => $bind_addr,
'rg_ldap_port' => $bind_port + 2,
'rg_ldap_ports' => $bind_ports + 2,
'rg_ldap_server_id' => '002',
'rg_ldap_producer_url' => 'ldap://' . $bind_addr . ':' . $bind_port,
'rg_ldap_producer_rid' => '001',
'rg_ldap_add_data' => 0,
'rg_ldap_pass' => $pass,
'rg_ldap_user_pass' => $user_pass,
'rg_ldap_user_key' => $user_key
);
rg_ldap_start_server($l2);
register_shutdown_function('clean', $l1['log']);
register_shutdown_function('clean', $l2['log']);
$data = array(
'addr' => $bind_addr,
'port' => $bind_port,
'bind_user' => 'cn=Manager,dc=my-domain,dc=com',
'bind_pass' => $pass,
'base' => 'dc=my-domain,dc=com'
);
rg_log_exit();
rg_log('');
rg_log_enter('Find out the id of the server...');
$r = rg_ldap_list($db);
if ($r['ok'] !== 1) {
rg_log('Cannot get the ldap servers list: ' . $r['errmsg']);
exit(1);
}
$found = FALSE;
foreach ($r['list'] as $id => $i) {
if (strcmp($i['url'], 'ldap://' . $bind_addr . ':' . $bind_port) != 0)
continue;
$found = TRUE;
break;
}
if (!$found) {
rg_log('Could not find the server in database!');
exit(1);
}
$data['server_id'] = $id;
rg_log_exit();
/* TODO: this has to be made available after I deal with the sync
rg_log('');
rg_log_enter('sync_ro...');
$r = rg_ldap_sync_ro($db, $data);
if ($r['ok'] != 1) {
rg_log('Cannot sync: ' . $r['errmsg'] . '!');
exit(1);
}
rg_log_exit();
rg_log('');
rg_log_enter('Deleting user user4...');
$r = rg_ldap_core_connect('ldap://' . $l1['rg_ldap_addr']
. ':' . $l1['rg_ldap_port'], 3);
if ($r['ok'] !== 1) {
rg_log('Cannot connect to second server: ' . $r['errmsg'] . '!');
exit(1);
}
$con = $r['con'];
$r = rg_ldap_core_bind($con, 'cn=Manager,dc=my-domain,dc=com', $pass);
if ($r['ok'] !== 1) {
rg_log('cannot bind: ' . $r['errmsg']);
exit(1);
}
$r = rg_ldap_core_del($con, 'uid=user4,ou=People,dc=my-domain,dc=com');
if ($r['ok'] !== 1) {
rg_log('Cannot delete: ' . $r['errmsg'] . '!');
exit(1);
}
rg_log_exit();
// TODO: needed?!
sleep(3);
rg_log('');
rg_log_enter('get server CSN field...');
$res = rg_sql_query($db, 'SELECT csn FROM ldap_servers'
. ' WHERE id = ' . $data['server_id']);
if ($res === FALSE) {
rg_log('Cannot select csn from db: ' . rg_sql_error() . '!');
exit(1);
}
$row = rg_sql_fetch_array($res);
rg_sql_free_result($res);
$csn = $row['csn'];
rg_log('csn: ' . $csn);
rg_log_exit();
rg_log('');
rg_log_enter('sync_ro (after a delete)...');
$data['rid'] = '001'; $data['csn'] = $csn; // not sure if rid is correct TODO
$r = rg_ldap_sync_ro($db, $data);
if ($r['ok'] != 1) {
rg_log('Cannot sync: ' . $r['errmsg'] . '!');
exit(1);
}
rg_log_exit();
*/
rg_log('');
rg_log_enter('Login using a LDAP user using ldap uid (first login)');
$_ui = array(
'username' => 'user1-' . $user_key,
'pass' => $user_pass,
't' => 'first login by uid'
);
$r = test_login($test_url, $_ui);
if ($r === FALSE)
exit(1);
rg_log_exit();
rg_log('');
rg_log_enter('Setting ldap_cache.uid to 0 to trigger a conflict in inserting'
. ' in \'users\' table');
$params = array('user' => 'user1-' . $user_key);
$sql = 'UPDATE ldap_cache SET uid = 0 WHERE ldap_uid = @@user@@';
$res = rg_sql_query_params($db, $sql, $params);
if ($res === FALSE) {
rg_log('Cannot update ldap_cache.uid!');
exit(1);
}
rg_sql_free_result($res);
rg_log_exit();
rg_log('');
// User will not be found in 'users' table because we search by e-mail
rg_log_enter('Login using a LDAP user: mail');
$_ui = array(
'username' => 'user1-' . $user_key . '@my-domain.com',
'pass' => $user_pass,
't' => 'login by e-mail expecting conflict inserting into users table'
);
$r = test_login($test_url, $_ui);
if ($r === FALSE)
exit(1);
rg_log_exit();
rg_log('');
rg_log_enter('Login using a LDAP user: uid (second time, expect user present)');
$_ui = array(
'username' => 'user1-' . $user_key,
'pass' => $user_pass,
't' => 'second login by uid, expecting user present in users table'
);
$r = test_login($test_url, $_ui);
if ($r === FALSE) {
rg_log('Cannot login!');
exit(1);
}
rg_log_exit();
rg_log('');
rg_log_enter('Login using a LDAP user: uid (third time, but delete from'
. ' \'users\' table first)');
$params = array(
'new' => 'user1-fake-' . $user_key,
'old' => 'user1-' . $user_key
);
// First, find out the uid
$sql = 'SELECT uid FROM users WHERE username = @@old@@';
$res = rg_sql_query_params($db, $sql, $params);
if ($res === FALSE) {
rg_log('Cannot get info user1 username!');
exit(1);
}
$row = rg_sql_fetch_array($res);
rg_sql_free_result($res);
$params['uid'] = $row['uid'];
$sql = 'UPDATE users SET username = @@new@@ WHERE uid = @@uid@@';
$res = rg_sql_query_params($db, $sql, $params);
if ($res === FALSE) {
rg_log('Cannot update user1 username!');
exit(1);
}
$k = 'username_to_uid::user1-' . $user_key;
rg_cache_unset($k, RG_SOCKET_NO_WAIT);
$k = 'user::' . $params['uid'];
rg_cache_unset($k, RG_SOCKET_NO_WAIT);
$_ui = array(
'username' => 'user1-' . $user_key,
'pass' => $user_pass,
't' => 'login by uid, but delete from users before'
);
$r = test_login($test_url, $_ui);
if ($r === FALSE) {
rg_log('Cannot login!');
exit(1);
}
rg_log_exit();
rg_log('');
rg_log_enter('We try to login with user2, which have the description as the uid');
rg_log('Updating LDAP server...');
rg_cache_set('ldap::list::' . $data['server_id'] . '::uid_attr',
'DescriptioN', RG_SOCKET_NO_WAIT);
$_ui = array(
'username' => 'user2-' . $user_key,
'pass' => $user_pass,
't' => 'now, the uid attr field is description'
);
$r = test_login($test_url, $_ui);
if ($r === FALSE) {
rg_log('Cannot login!');
exit(1);
}
rg_log_exit();
rg_log('');
rg_log_enter('Loading Admin -> LDAP -> List -> [Edit]...');
$data = array();
$headers = array();
$r = do_req($info, $test_url . '/op/admin/ldap/edit/' . $id, $data, $headers);
if ($r === FALSE) {
rg_log('Cannot load edit page!');
exit(1);
}
if (!isset($r['tokens']['ldap_add'])) {
rg_log('Cannot find ldap_add token!');
exit(1);
}
$token = $r['tokens']['ldap_add'];
rg_log_exit();
rg_log('');
rg_log_enter('Posting new data...');
$data = array(
'doit' => 1,
'token' => $token,
'ldap::id' => $id,
'ldap::plan_id' => 9,
'ldap::prio' => 11,
'ldap::session_time' => 700,
'ldap::name' => $name . '<xss>',
'ldap::url' => 'ldaps://' . $bind_addr . ':' . $bind_port,
'ldap::bind_dn' => 'binddn',
'ldap::bind_pass' => 'bind_pass',
'ldap::user_base' => 'o=a,dc=my-domain,dc=com',
'ldap::uid_attr' => 'uid2',
'ldap::filter' => 'memberOf=cn=groupX,ou=Group,dc=my-domain,dc=com',
'ldap::group_base' => 'o=b,dc=my-domain,dc=com',
'ldap::group_attr' => 'memberOfNot',
'ldap::group_filter' => 'group_filter',
'ldap::admin_group' => 'cn=(Admins4|Admins5),ou=Group,dc=my-domain,dc=com',
'ldap::timeout' => 13,
'ldap::ca_cert' => 'ca_cert'
);
$headers = array();
$r = do_req($info, $test_url . '/op/admin/ldap/add', $data, $headers);
if ($r === FALSE) {
rg_log('Cannot load edit page!');
exit(1);
}
if (!strstr($r['body'], 'LDAP server has been successfully added/edited.')) {
rg_log_ml('body: ' . $r['body']);
rg_log('Success message not found!');
exit(1);
}
$sql = 'SELECT * FROM ldap_servers WHERE id = ' . $id;
$res = rg_sql_query($db, $sql);
$row = rg_sql_fetch_array($res);
rg_sql_free_result($res);
$key = 'ldap::list::' . $id;
$c = test_wait_cache($key, 50);
foreach ($data as $k => $v) {
// ignore some fields
if (strncmp($k, 'ldap::', 6) != 0)
continue;
$k = substr($k, 6);
if (!isset($row[$k])) {
rg_log('Field [' . $k . '] was not found in db!');
exit(1);
}
if (strcmp($row[$k], $v) != 0) {
rg_log('Field [' . $k . '] seems was missed in edit (db)!');
rg_log('db=' . $row[$k] . ' sent=' . $v);
exit(1);
}
if (!isset($c[$k])) {
rg_log('Field [' . $k . '] was not found in cache!');
exit(1);
}
if (strcmp($c[$k], $v) != 0) {
rg_log('Field [' . $k . '] seems was missed in edit (cache)!');
rg_log('cache=' . $c[$k] . ' sent=' . $v);
exit(1);
}
}
// Testing if all fields in the database were updated
unset($row['itime']);
unset($row['who']);
unset($row['csn']);
foreach ($row as $k => $v) {
if (isset($data['ldap::' . $k]))
continue;
rg_log('Field [' . $k . '] was missing from the http update!');
exit(1);
}
rg_log_exit();
rg_log('');
rg_log_enter('Loading Admin -> LDAP -> List (for delete)...');
$data = array();
$headers = array();
$r = do_req($info, $test_url . '/op/admin/ldap/list', $data, $headers);
if ($r === FALSE) {
rg_log('Cannot load list page!');
exit(1);
}
$token = $r['tokens']['ldap_list'];
rg_log_exit();
rg_log('');
rg_log_enter('Deleting a LDAP server...');
$data = array(
'delete' => 1,
'token' => $token,
'delete_list[' . $id . ']' => 'on'
);
$headers = array();
$r = do_req($info, $test_url . '/op/admin/ldap/list', $data, $headers);
if ($r === FALSE) {
rg_log('Cannot load list page!');
exit(1);
}
if (!strstr($r['body'], 'The selected LDAP servers have been successfully deleted.')) {
rg_log_ml('r: ' . print_r($r, TRUE));
rg_log('Cannot delete LDAP server(s)!');
exit(1);
}
rg_log_exit();
rg_log('OK!');