/** * sync LDAP against the DB */ function sync_LDAP() { global $c; $ldapDriver = getStaticLdap(); if (!$ldapDriver->valid) { return; } $mapping = $c->authenticate_hook['config']['mapping_field']; $attributes = array_values_mapping($mapping); $ldap_users_tmp = $ldapDriver->getAllUsers($attributes); if (sizeof($ldap_users_tmp) == 0) { return; } foreach ($ldap_users_tmp as $key => $ldap_user) { $ldap_users_info[$ldap_user[$mapping['username']]] = $ldap_user; unset($ldap_users_tmp[$key]); } $qry = new AwlQuery("SELECT username, user_no, modified as updated FROM dav_principal where type_id=1"); $qry->Exec('sync_LDAP', __LINE__, __FILE__); while ($db_user = $qry->Fetch()) { $db_users[] = $db_user->username; $db_users_info[$db_user->username] = array('user_no' => $db_user->user_no, 'updated' => $db_user->updated); } // all users from ldap $ldap_users = array_keys($ldap_users_info); // users only in ldap $users_to_create = array_diff($ldap_users, $db_users); // users only in db $users_to_deactivate = array_diff($db_users, $ldap_users); // users present in ldap and in the db $users_to_update = array_intersect($db_users, $ldap_users); // creation of all users; if (sizeof($users_to_create)) { $c->messages[] = sprintf(i18n('- creating record for users : %s'), join(', ', $users_to_create)); foreach ($users_to_create as $username) { $principal = new Principal('username', $username); $valid = $ldap_users_info[$username]; $ldap_timestamp = $valid[$mapping['modified']]; if (!empty($c->authenticate_hook['config']['format_updated'])) { /** * This splits the LDAP timestamp apart and assigns values to $Y $m $d $H $M and $S */ foreach ($c->authenticate_hook['config']['format_updated'] as $k => $v) { ${$k} = substr($ldap_timestamp, $v[0], $v[1]); } $ldap_timestamp = $Y . $m . $d . $H . $M . $S; } else { if (preg_match('{^(\\d{8})(\\d{6})(Z)?$', $ldap_timestamp, $matches)) { $ldap_timestamp = $matches[1] . 'T' . $matches[2] . $matches[3]; } else { if (empty($ldap_timestamp)) { $ldap_timestamp = date('c'); } } } $valid[$mapping['modified']] = $ldap_timestamp; sync_user_from_LDAP($principal, $mapping, $valid); } } // deactivating all users $params = array(); $i = 0; $paramstring = ''; foreach ($users_to_deactivate as $v) { if (isset($c->do_not_sync_from_ldap) && isset($c->do_not_sync_from_ldap[$v])) { continue; } if ($i > 0) { $paramstring .= ','; } $paramstring .= ':u' . $i . '::text'; $params[':u' . $i++] = strtolower($v); } if (count($params) > 0) { $c->messages[] = sprintf(i18n('- deactivating users : %s'), join(', ', $users_to_deactivate)); $qry = new AwlQuery('UPDATE usr SET active = FALSE WHERE lower(username) IN (' . $paramstring . ')', $params); $qry->Exec('sync_LDAP', __LINE__, __FILE__); Principal::cacheFlush('lower(username) IN (' . $paramstring . ')', $params); } // updating all users if (sizeof($users_to_update)) { foreach ($users_to_update as $key => $username) { $principal = new Principal('username', $username); $valid = $ldap_users_info[$username]; $ldap_timestamp = $valid[$mapping['modified']]; $valid['user_no'] = $db_users_info[$username]['user_no']; $mapping['user_no'] = 'user_no'; /** * This splits the LDAP timestamp apart and assigns values to $Y $m $d $H $M and $S */ foreach ($c->authenticate_hook['config']['format_updated'] as $k => $v) { ${$k} = substr($ldap_timestamp, $v[0], $v[1]); } $ldap_timestamp = $Y . $m . $d . $H . $M . $S; $valid[$mapping['modified']] = "{$Y}-{$m}-{$d} {$H}:{$M}:{$S}"; $db_timestamp = substr(strtr($db_users_info[$username]['updated'], array(':' => '', ' ' => '', '-' => '')), 0, 14); if ($ldap_timestamp > $db_timestamp) { sync_user_from_LDAP($principal, $mapping, $valid); } else { unset($users_to_update[$key]); $users_nothing_done[] = $username; } } if (sizeof($users_to_update)) { $c->messages[] = sprintf(i18n('- updating user records : %s'), join(', ', $users_to_update)); } if (sizeof($users_nothing_done)) { $c->messages[] = sprintf(i18n('- nothing done on : %s'), join(', ', $users_nothing_done)); } } $admins = 0; $qry = new AwlQuery("SELECT count(*) AS admins FROM usr JOIN role_member USING ( user_no ) JOIN roles USING (role_no) WHERE usr.active=TRUE AND role_name='Admin'"); $qry->Exec('sync_LDAP', __LINE__, __FILE__); while ($db_user = $qry->Fetch()) { $admins = $db_user->admins; } if ($admins == 0) { $c->messages[] = sprintf(i18n('Warning: there are no active admin users! You should fix this before logging out. Consider using the $c->do_not_sync_from_ldap configuration setting.')); } }
function process_ace($grantor, $by_principal, $by_collection, $ace) { global $cache_delete_list, $request; $elements = $ace->GetContent(); $principal_node = $elements[0]; $grant = $elements[1]; if ($principal_node->GetNSTag() != 'DAV::principal') { $request->MalformedRequest('ACL request must contain a principal, not ' . $principal->GetNSTag()); } $grant_tag = $grant->GetNSTag(); if ($grant_tag == 'DAV::deny') { $request->PreconditionFailed(403, 'grant-only'); } if ($grant_tag == 'DAV::invert') { $request->PreconditionFailed(403, 'no-invert'); } if ($grant->GetNSTag() != 'DAV::grant') { $request->MalformedRequest('ACL request must contain a principal for each ACE'); } $privilege_names = array(); $xml_privs = $grant->GetPath("/DAV::grant/DAV::privilege/*"); foreach ($xml_privs as $k => $priv) { $privilege_names[] = $priv->GetNSTag(); } $privileges = privilege_to_bits($privilege_names); $principal_content = $principal_node->GetContent(); if (count($principal_content) != 1) { $request->MalformedRequest('ACL request must contain exactly one principal per ACE'); } $principal_content = $principal_content[0]; switch ($principal_content->GetNSTag()) { case 'DAV::property': $principal_property = $principal_content->GetContent(); if ($principal_property[0]->GetNSTag() != 'DAV::owner') { $request->PreconditionFailed(403, 'recognized-principal'); } if (privilege_to_bits('all') != $privileges) { $request->PreconditionFailed(403, 'no-protected-ace-conflict', 'Owner must always have all permissions'); } continue; // and then we ignore it, since it's protected break; case 'DAV::unauthenticated': $request->PreconditionFailed(403, 'allowed-principal', 'May not set privileges for unauthenticated users'); break; case 'DAV::href': $principal_type = 'href'; $grantee = new DAVResource(DeconstructURL($principal_content->GetContent())); $grantee_id = $grantee->getProperty('principal_id'); if (!$grantee->Exists() || !$grantee->IsPrincipal()) { $request->PreconditionFailed(403, 'recognized-principal', 'Principal "' + $principal_content->GetContent() + '" not found.'); } $sqlparms = array(':to_principal' => $grantee_id); $where = 'WHERE to_principal=:to_principal AND '; if (isset($by_principal)) { $sqlparms[':by_principal'] = $by_principal; $where .= 'by_principal = :by_principal'; } else { $sqlparms[':by_collection'] = $by_collection; $where .= 'by_collection = :by_collection'; } $qry = new AwlQuery('SELECT privileges FROM grants ' . $where, $sqlparms); if ($qry->Exec('ACL', __LINE__, __FILE__) && $qry->rows() == 1 && ($current = $qry->Fetch())) { $sql = 'UPDATE grants SET privileges=:privileges::INT::BIT(24) ' . $where; } else { $sqlparms[':by_principal'] = $by_principal; $sqlparms[':by_collection'] = $by_collection; $sql = 'INSERT INTO grants (by_principal, by_collection, to_principal, privileges) VALUES(:by_principal, :by_collection, :to_principal, :privileges::INT::BIT(24))'; } $sqlparms[':privileges'] = $privileges; $qry = new AwlQuery($sql, $sqlparms); if ($qry->Exec('ACL', __LINE__, __FILE__)) { Principal::cacheDelete('dav_name', $grantee->dav_name()); Principal::cacheFlush('principal_id IN (SELECT member_id FROM group_member WHERE group_id = ?)', array($grantee_id)); } break; case 'DAV::authenticated': $principal_type = 'authenticated'; if (bindec($grantor->GetProperty('default_privileges')) == $privileges) { continue; } // There is no change, so skip it $sqlparms = array(':privileges' => $privileges); if (isset($by_collection)) { $sql = 'UPDATE collection SET default_privileges=:privileges::INT::BIT(24) WHERE collection_id=:by_collection'; $sqlparms[':by_collection'] = $by_collection; } else { $sql = 'UPDATE principal SET default_privileges=:privileges::INT::BIT(24) WHERE principal_id=:by_principal'; $sqlparms[':by_principal'] = $by_principal; } $qry = new AwlQuery($sql, $sqlparms); if ($qry->Exec('ACL', __LINE__, __FILE__)) { /** * Basically this has changed everyone's permissions now, so... */ Principal::cacheFlush('TRUE'); } break; case 'DAV::all': // $principal_type = 'all'; $request->PreconditionFailed(403, 'allowed-principal', 'May not set privileges for unauthenticated users'); break; default: $request->PreconditionFailed(403, 'recognized-principal'); break; } }