From ef9a212ece3e5c54837f06ff5a6f77f990d5d84d Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Thu, 22 Nov 2007 07:41:30 +0000 Subject: [PATCH] fixed user management addresses #1 --- admin/common.inc.php | 17 ++- admin/getgroups.php | 29 ++--- admin/users.php | 250 +++++++++++++++++++++++++------------------ 3 files changed, 173 insertions(+), 123 deletions(-) diff --git a/admin/common.inc.php b/admin/common.inc.php index 53b41f0..ee0b24a 100644 --- a/admin/common.inc.php +++ b/admin/common.inc.php @@ -79,39 +79,46 @@ function getFullPath($dirname) { // check configuration $errmsgs = array(); if (!isset($davconfig['digest.file'])) { - array_push($errmsgs, 'digest.file not defined'); + array_push($errmsgs, 'digest.file is not defined.'); } elseif (!is_readable($davconfig['digest.file']) || !is_writable($davconfig['digest.file'])) { array_push($errmsgs, 'The specified digest file is not readable and writable.'); } if (!isset($davconfig['group.file'])) { - array_push($errmsgs, 'group.file not defined'); + array_push($errmsgs, 'group.file is not defined.'); } elseif (!is_readable($davconfig['group.file']) || !is_writable($davconfig['group.file'])) { array_push($errmsgs, 'The specified group file is not readable and writable.'); } if (!isset($davconfig['namemap.file'])) { - array_push($errmsgs, 'namemap.file not defined'); + array_push($errmsgs, 'namemap.file is not defined.'); } elseif (!is_readable($davconfig['namemap.file']) || !is_writable($davconfig['namemap.file'])) { array_push($errmsgs, 'The specified name mapping file is not readable and writable.'); } if (!isset($davconfig['dav.dir'])) { - array_push($errmsgs, 'dav.dir not defined'); + array_push($errmsgs, 'dav.dir is not defined.'); } elseif (!is_dir($davconfig['dav.dir']) || !is_readable($davconfig['dav.dir']) || !is_writable($davconfig['dav.dir'])) { array_push($errmsgs, 'The specified DAV directory is no directory or not accessable.'); } +if (empty($davconfig['dav.realm'])) { + array_push($errmsgs, 'dav.realm is not defined.'); +} +if (empty($davconfig['dav.uri'])) { + array_push($errmsgs, 'dav.uri is not defined.'); +} if (!empty($errmsgs)) { errorAsHtml(implode("
", $errmsgs)); } -$namemap = json_decode(readfile($davconfig['namemap.file']), true); +$namemapdata = file_get_contents($davconfig['namemap.file']); +$namemap = json_decode($namemapdata, true); if ($namemap === NULL) { $namemap = array(); } diff --git a/admin/getgroups.php b/admin/getgroups.php index 6f64980..f32cbfd 100644 --- a/admin/getgroups.php +++ b/admin/getgroups.php @@ -27,8 +27,17 @@ * 02110-1301 USA. */ +if (!isset($_SERVER['DavAdminConfDir'])) { + header('HTTP/1.0 500 Internal Server Error'); + header('Status: 500 Internal Server Error'); + header('Content-Type: text/plain;charset=utf8'); + print("The Server is not configured correctly. " . + "Please tell your Administrator to set the " . + "DavAdminConfDir environment variable."); + exit(); +} /** Include configuration information. */ -require_once('config.inc.php'); +require_once($_SERVER['DavAdminConfDir'] . '/config.inc.php'); // output is plain text (JSON or an error message) header("Content-Type: text/plain; charset=UTF-8"); @@ -45,19 +54,15 @@ function getGroups($part) { preg_match_all($regexp, $part, $matches); $array = $matches[1]; $last_string = trim(array_pop($array)); + $retval = array(); if ($last_string != '') { - try { - $dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']); - $sth = $dbh->prepare("SELECT DISTINCT groupname FROM dav_group WHERE LOWER(groupname) LIKE LOWER(?) ORDER BY groupname"); - $sth->execute(array("%" . $last_string . "%")); - $prefix = count($array) ? implode(",", $array) . ", " : ''; - $retval = array(); - foreach ($sth->fetchAll(PDO::FETCH_ASSOC) as $row) { - $retval[$prefix . $row['groupname']] = $row['groupname']; + $groups = file($GLOBALS['davconfig']['group.file']); + foreach ($groups as $line) { + list($group, $users) = explode(":", $line); + $group = trim($group); + if (stripos($group, $last_string) === 0) { + array_push($retval, $group); } - $dbh = null; - } catch (PDOException $e) { - return $e->getMessage(); } } return json_encode($retval); diff --git a/admin/users.php b/admin/users.php index 1530f23..217e1a2 100644 --- a/admin/users.php +++ b/admin/users.php @@ -34,14 +34,12 @@ function getGroups($username) { $groupdata = file($GLOBALS['davconfig']['group.file']); $retval = array(); foreach ($groupdata as $line) { - $colonpos = strpos($line, ":"); - if ($colonpos > 0) { - $groupname = trim(substr($line, 0, $colonpos - 1)); - $users = explode(" ", substr($line, $colonpos + 1)); - foreach ($users as $user) { - if (trim($user) == $username) { - array_push($retval, $groupname); - } + list($group, $users) = explode(":", $line); + $group = trim($group); + $users = explode(" ", $users); + foreach ($users as $user) { + if (trim($user) == $username) { + array_push($retval, $group); } } } @@ -122,11 +120,85 @@ function validateUserData(&$userdata, $forinsert) { return $errormsgs; } +/** + * Creates an entry for a digest authentication file. + * + * @param string $username user name + * @param string $realm realm name + * @param string $password password + * @return string digest entry + */ function createDigest($username, $realm, $password) { return sprintf("%s:%s:%s", $username, $realm, md5(sprintf("%s:%s:%s", $username, $realm, $password))); } +function updateNameMap() { + $fh = fopen($GLOBALS['davconfig']['namemap.file'], 'w'); + fwrite($fh, json_encode($GLOBALS['namemap'])); + fclose($fh); +} + +function updateDigest(&$userdata) { + if ($userdata['password']) { + $digests = file($GLOBALS['davconfig']['digest.file']); + $written = false; + $fh = fopen($GLOBALS['davconfig']['digest.file'], 'w'); + foreach ($digests as $digest) { + list($username, $realm, $data) = explode(":", $digest); + if ($username == $userdata['username'] + && $realm == $GLOBALS['davconfig']['dav.realm']) { + fwrite($fh, createDigest($userdata['username'], + $GLOBALS['davconfig']['dav.realm'], + $userdata['password']) . "\n"); + $written = true; + } else { + fwrite($fh, $digest); + } + } + if (!$written) { + fwrite($fh, createDigest($userdata['username'], + $GLOBALS['davconfig']['dav.realm'], + $userdata['password']) . "\n"); + } + fclose($fh); + } +} + +function updateGroups(&$userdata) { + if ($userdata['groups']) { + $written = array(); + foreach (explode(",", $userdata['groups']) as $group) { + $written[trim($group)] = false; + } + $groupdata = file($GLOBALS['davconfig']['group.file']); + $fh = fopen($GLOBALS['davconfig']['group.file'], 'w'); + foreach ($groupdata as $groupline) { + list ($group, $users) = explode(":", $groupline); + $group = trim($group); + $users = explode(" ", trim($users)); + foreach ($users as $key => $user) { + $users[$key] = trim($user); + } + if (array_key_exists($group, $written)) { + if (!in_array($userdata['username'], $users)) { + array_push($users, $userdata['username']); + } + fprintf($fh, "%s: %s\n", $group, implode(" ", $users)); + $written[$group] = true; + } else { + fwrite($fh, $groupline); + } + } + foreach ($written as $group => $done) { + if (!$done) { + fprintf($fh, "%s: %s\n", $group, $userdata['username']); + } + } + fclose($fh); + } +} + /** * Updates the data of a user in the database. * @@ -137,53 +209,17 @@ function updateUser(&$userdata) { if (!empty($validation)) { errorAsXml(implode("\n", $validation)); } - try { - $dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']); - $dbh->beginTransaction(); - if ($userdata['password']) { - $sth = $dbh->prepare("UPDATE dav_password SET firstname=:firstname, lastname=:lastname, password=md5(:password) WHERE uid=:uid"); - if (!$sth->execute(array(':firstname' => $userdata['firstname'], - ':lastname' => $userdata['lastname'], - ':password' => $userdata['password'], - ':uid' => $userdata['uid']))) { - $dbh->rollback(); - statementErrorAsXml($sth); - } - } else { - $sth = $dbh->prepare("UPDATE dav_password SET firstname=:firstname, lastname=:lastname WHERE uid=:uid"); - if (!$sth->execute(array(':firstname' => $userdata['firstname'], - ':lastname' => $userdata['lastname'], - ':uid' => $userdata['uid']))) { - $dbh->rollback(); - statementErrorAsXml($sth); - } - } - if ($userdata['groups']) { - $groups = array(); - $sth = $dbh->prepare("DELETE FROM dav_group WHERE username=:username"); - if (!$sth->execute(array(':username' => $userdata['username']))) { - $dbh->rollback(); - statementErrorAsXml($sth); - } - $sth = $dbh->prepare("INSERT INTO dav_group (username, groupname) VALUES (:username, :groupname)"); - foreach (explode(",", $userdata['groups']) as $group) { - $group = trim($group); - if (!in_array($group, $groups)) { - array_push($groups, $group); - if (!$sth->execute(array(':username' => $userdata['username'], - ':groupname' => $group))) { - $dbh->rollback(); - statementErrorAsXml($sth); - } - $sth->closeCursor(); - } - } - } - $dbh->commit(); - $dbh = null; - } catch (PDOException $e) { - errorAsXml($e->getMessage()); - } + $GLOBALS['namemap'][$userdata['uid']] = + array('uid' => $userdata['uid'], + 'username' => $userdata['username'], + 'firstname' => $userdata['firstname'], + 'lastname' => $userdata['lastname']); + // write name mapping data + updateNameMap(); + // write digest data + updateDigest($userdata); + // update group file + updateGroups($userdata); } /** @@ -196,40 +232,58 @@ function insertUser(&$userdata) { if (!empty($validation)) { errorAsXml(implode("\n", $validation)); } - try { - $dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']); - $dbh->beginTransaction(); - $sth = $dbh->prepare("INSERT INTO dav_password (username, firstname, lastname, password) VALUES (:username, :firstname, :lastname, md5(:password))"); - if (!$sth->execute(array(':username' => $userdata['username'], - ':firstname' => $userdata['firstname'], - ':lastname' => $userdata['lastname'], - ':password' => $userdata['password']))) { - $dbh->rollback(); - statementErrorAsXml($sth); - } - $uid = $dbh->lastInsertId('dav_password_uid_seq'); - $groups = array(); - $sth = $dbh->prepare("INSERT INTO dav_group (username, groupname) VALUES (:username, :groupname)"); - foreach (split(",", $userdata['groups']) as $group) { - $group = trim($group); - if (!in_array($group, $groups)) { - array_push($groups, $group); - if (!$sth->execute(array(':username' => $userdata['username'], - ':groupname' => $group))) { - $dbh->rollback(); - statementErrorAsXml($sth); - } - $sth->closeCursor(); - } - } - $dbh->commit(); - $dbh = null; - } catch (PDOException $e) { - errorAsXml($e->getMessage); + $uids = array_keys($GLOBALS['namemap']); + if (empty($uids)) { + $uid = 1; + } else { + arsort($uids); + $uid = $uids[0] + 1; } + $GLOBALS['namemap'][$uid] = + array('uid' => $uid, + 'username' => $userdata['username'], + 'firstname' => $userdata['firstname'], + 'lastname' => $userdata['lastname']); + // write name mapping data + updateNameMap(); + // write digest data + updateDigest($userdata); + // update group file + updateGroups($userdata); return $uid; } +function removeDigest($username) { + $digests = file($GLOBALS['davconfig']['digest.file']); + $fh = fopen($GLOBALS['davconfig']['digest.file'], 'w'); + foreach ($digests as $digest) { + list($username, $realm, $data) = explode(":", $digest); + if (!($username == $userdata['username'] + && $realm == $GLOBALS['davconfig']['dav.realm'])) { + fwrite($fh, $digest); + } + } + fclose($fh); +} + +function removeFromGroups($username) { + $groupdata = file($GLOBALS['davconfig']['group.file']); + $fh = fopen($GLOBALS['davconfig']['group.file'], 'w'); + foreach ($groupdata as $groupline) { + list ($group, $users) = explode(":", $groupline); + $group = trim($group); + $users = explode(" ", trim($users)); + foreach ($users as $key => $user) { + $users[$key] = trim($user); + } + if (in_array($username, $users)) { + $users = array_splice($users, array_search($username, $users)); + } + fprintf($fh, "%s: %s\n", $group, implode(" ", $users)); + } + fclose($fh); +} + /** * Delete the user with the given user id and its group assignments * from the database. @@ -237,27 +291,13 @@ function insertUser(&$userdata) { * @param int $uid user id */ function deleteUser($uid) { - if (!is_numeric($uid)) { + if (!(is_numeric($uid) && array_key_exists($uid, $GLOBALS['namemap']))) { errorAsXml(sprintf(_("Invalid user id %s"), $uid)); } - try { - $dbh = new PDO($GLOBALS['dsn'], $GLOBALS['dbuser'], $GLOBALS['dbpass']); - $dbh->beginTransaction(); - $query = $dbh->prepare("DELETE FROM dav_group WHERE username IN (SELECT username FROM dav_password WHERE uid=:uid)"); - if (!$query->execute(array(':uid' => $uid))) { - $dbh->rollback(); - statementErrorAsXml($query); - } - $query = $dbh->prepare("DELETE FROM dav_password WHERE uid=:uid"); - if (!$query->execute(array(':uid' => $uid))) { - $dbh->rollback(); - statementErrorAsXml($query); - } - $dbh->commit(); - $dbh = null; - } catch (PDOException $e) { - errorAsXml($e->getMessage()); - } + removeDigest($GLOBALS['namemap'][$uid]['username']); + removeFromGroups($GLOBALS['namemap'][$uid]['username']); + unset($GLOBALS['namemap'][$uid]); + updateNameMap(); } if ($_GET) { @@ -300,8 +340,6 @@ if ($_GET) { invalidCall(); } } else { - $currentuser = $_SERVER['PHP_AUTH_USER']; - header("Content-Type: text/html; charset=UTF-8"); $smarty->assign("users", $namemap); $smarty->display("users.html");