| <?php |
| /* |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| require_once(".ht-inc/secrets.php"); |
| require_once(".ht-inc/authentication.php"); |
| require_once(".ht-inc/spyc-0.5.1/Spyc.php"); |
| if(file_exists(".ht-inc/vcldocs.php")) |
| require_once(".ht-inc/vcldocs.php"); |
| |
| /** |
| * \file |
| */ |
| |
| /// used for processInputVar, means the input variable should be numeric |
| define("ARG_NUMERIC", 1); |
| /// used for processInputVar, means the input variable should be a string |
| define("ARG_STRING", 1 << 1); |
| /// used for processInputVar, means the input variable should be an array of numbers |
| define("ARG_MULTINUMERIC", 1 << 2); |
| /// used for processInputVar, means the input variable should be an array of strings |
| define("ARG_MULTISTRING", 1 << 3); |
| |
| /// global array used to hold request information between calling isAvailable |
| /// and addRequest |
| $requestInfo = array(); |
| |
| /// global array to cache arrays of node parents for getNodeParents |
| $nodeparents = array(); |
| /// global array to cache various data |
| $cache = array(); |
| /// global variable to store what needs to be printed in printHTMLHeader |
| $HTMLheader = ""; |
| /// global variable to store if header has been printed |
| $printedHTMLheader = 0; |
| |
| spl_autoload_register('vclAutoLoader'); |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn initGlobals() |
| /// |
| /// \brief this is where globals get initialized |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function initGlobals() { |
| global $mode, $user, $remoteIP, $authed, $oldmode; |
| global $days, $phpVer, $keys, $pemkey, $submitErr, $submitErrMsg; |
| global $passwdArray, $skin, $contdata, $lastmode, $inContinuation; |
| global $ERRORS, $actions; |
| global $affilValFunc, $addUserFunc, $updateUserFunc, $addUserFuncArgs; |
| global $uniqid, $cryptkey, $ivsize; |
| |
| define("SECINDAY", 86400); |
| define("SECINWEEK", 604800); |
| define("SECINMONTH", 2678400); |
| define("SECINYEAR", 31536000); |
| |
| define("SYMALGO", "AES"); |
| define("SYMOPT", "CBC"); |
| define("SYMLEN", 256); |
| |
| define("ASYMALGO", "RSA"); |
| define("ASYMOPT", "OAEP"); |
| define("ASYMLEN", 4096); |
| |
| if(! defined('QUERYLOGGING')) |
| define('QUERYLOGGING', 1); |
| # TODO validate security of this |
| if(array_key_exists("PATH_INFO", $_SERVER)) { |
| $pathdata = explode("/", $_SERVER["PATH_INFO"]); |
| $tmp = explode('.', $pathdata[1]); |
| $_GET["mode"] = $tmp[0]; |
| } |
| |
| if(function_exists('openssl_encrypt')) { |
| define('USE_PHPSECLIB', 0); |
| $cryptkey = base64_decode($cryptkey); |
| } |
| else { |
| define('USE_PHPSECLIB', 1); |
| require_once(".ht-inc/phpseclib/Crypt/Base.php"); |
| require_once(".ht-inc/phpseclib/Crypt/Rijndael.php"); |
| require_once(".ht-inc/phpseclib/Crypt/AES.php"); |
| require_once(".ht-inc/phpseclib/Crypt/Random.php"); |
| } |
| $ivsize = 16; |
| |
| $mode = processInputVar("mode", ARG_STRING, 'main'); |
| $inContinuation = 0; |
| $contdata = array(); |
| $contuserid = ''; |
| $continuation = processInputVar('continuation', ARG_STRING); |
| if(! empty($continuation)) { |
| $tmp = getContinuationsData($continuation); |
| if(empty($tmp)) |
| abort(11); |
| elseif(array_key_exists('error', $tmp)) { |
| $mode = "continuationsError"; |
| $contdata = $tmp; |
| } |
| else { |
| $inContinuation = 1; |
| $contuserid = $tmp['userid']; |
| $lastmode = $tmp['frommode']; |
| $mode = $tmp['nextmode']; |
| $contdata = $tmp['data']; |
| } |
| } |
| $submitErr = 0; |
| $submitErrMsg = array(); |
| $remoteIP = $_SERVER["REMOTE_ADDR"]; |
| $days = array(i('Sunday'), i('Monday'), i('Tuesday'), i('Wednesday'), i('Thursday'), i('Friday'), i('Saturday')); |
| $phpVerArr = explode('.', phpversion()); |
| $phpVer = $phpVerArr[0]; |
| |
| $host = $_SERVER['HTTP_HOST']; |
| if(strpos($host, ':')) { |
| $host = substr($host, 0, strpos($host, ':')); |
| } |
| $uniqid = uniqid($host . "-" . getmypid() . "-"); |
| |
| $passwdArray = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', |
| 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', |
| 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', |
| 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', |
| 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', |
| '4', '5', '6', '7', '8', '9', '0'); |
| |
| if(isset($_COOKIE['VCLAUTH']) || |
| $mode == 'submitLogin' || |
| $mode == 'selectauth' || |
| $mode == 'xmlrpccall' || |
| $mode == 'main') { |
| // open keys |
| $fp = fopen(".ht-inc/keys.pem", "r"); |
| $key = fread($fp, 8192); |
| fclose($fp); |
| $keys["private"] = openssl_pkey_get_private($key, $pemkey); |
| if(! $keys['private']) |
| abort(6); |
| $fp = fopen(".ht-inc/pubkey.pem", "r"); |
| $key = fread($fp, 8192); |
| fclose($fp); |
| $keys["public"] = openssl_pkey_get_public($key); |
| if(! $keys['public']) |
| abort(7); |
| } |
| |
| # USING A SINGLE USER WITHOUT LOGGING IN: |
| # to automatically log in to vcl with the same user |
| # every time, comment out from this comment block to |
| # the 'end auth check' comment, then, right after |
| # that, set $authed = 1 and $userid to the id from |
| # the user table corresponding to the user you want |
| # logged in |
| |
| # start auth check |
| $authed = 0; |
| if(array_key_exists("VCLAUTH", $_COOKIE)) { |
| $userid = readAuthCookie(); |
| if(! is_null($userid)) |
| $authed = 1; |
| } |
| else { |
| global $authFuncs; |
| foreach($authFuncs as $type) { |
| if($type['test']()) { |
| $userid = $type['auth'](); |
| if(! is_null($userid)) { |
| $authed = 1; |
| break; |
| } |
| } |
| } |
| } |
| # end auth check |
| |
| if($authed && $mode == 'selectauth') |
| $mode = 'main'; |
| |
| # check that mode is valid |
| if(! array_key_exists($mode, $actions['pages'])) |
| $mode = 'main'; |
| |
| if(! $authed) { |
| # set $skin based on cookie (so it gets set before user logs in |
| # later, we set it by affiliation (helps with 'view as user') |
| if(array_key_exists('VCLSKIN', $_COOKIE)) { |
| switch($_COOKIE['VCLSKIN']) { |
| case 'EXAMPLE2': |
| $skin = 'example2'; |
| break; |
| default: |
| $skin = getAffiliationTheme(0); |
| break; |
| } |
| } |
| # set skin based on IP address, useful to ensure anyone coming |
| # from a certain organization automatically gets a different skin |
| /*elseif(preg_match('/^152\.9\./', $_SERVER['REMOTE_ADDR']) || |
| (array_key_exists('VCLSKIN', $_COOKIE) && $_COOKIE['VCLSKIN'] == 'EXAMPLE1')) { |
| $skin = 'example1'; |
| }*/ |
| else |
| $skin = getAffiliationTheme(0); |
| if($mode != 'selectauth' && $mode != 'submitLogin') |
| require_once("themes/$skin/page.php"); |
| |
| require_once(".ht-inc/requests.php"); |
| if($mode != "logout" && |
| $mode != "shiblogout" && |
| $mode != "xmlrpccall" && |
| $mode != "xmlrpcaffiliations" && |
| $mode != "selectauth" && |
| $mode != "submitLogin" && |
| $mode != "changeLocale") { |
| $oldmode = $mode; |
| $mode = "auth"; |
| } |
| if($mode == 'xmlrpccall' || $mode == 'xmlrpcaffiliations') { |
| require_once(".ht-inc/xmlrpcWrappers.php"); |
| require_once(".ht-inc/requests.php"); |
| #require_once(".ht-inc/serverprofiles.php"); |
| require_once(".ht-inc/groups.php"); |
| setupSession(); |
| } |
| return; |
| } |
| setupSession(); |
| if(array_key_exists('user', $_SESSION)) { |
| $user = $_SESSION['user']; |
| if(! empty($contuserid) && |
| $user['id'] != $contuserid) |
| abort(51); |
| } |
| else { |
| # get info about user |
| if(! $user = getUserInfo($userid)) { |
| // if first call to getUserInfo fails, try calling with $noupdate set |
| if(! $user = getUserInfo($userid, 1)) { |
| $ERRORS[1] = i("Failed to get user info from database. userid was ") . "$userid"; |
| abort(1); |
| } |
| } |
| if(! empty($contuserid) && |
| $user['id'] != $contuserid) |
| abort(51); |
| $_SESSION['user'] = $user; |
| } |
| |
| # setskin |
| $skin = getAffiliationTheme($user['affiliationid']); |
| require_once("themes/$skin/page.php"); |
| |
| $_SESSION['mode'] = $mode; |
| |
| // check for and possibly clear dirty permission cache |
| $dontClearModes = array('AJchangeUserPrivs', 'AJchangeUserGroupPrivs', 'AJchangeResourcePrivs'); |
| if(! in_array($mode, $dontClearModes) && |
| array_key_exists('dirtyprivs', $_SESSION) && |
| $_SESSION['dirtyprivs']) { |
| clearPrivCache(); |
| $_SESSION['dirtyprivs'] = 0; |
| } |
| |
| # set up $affilValFunc, $addUserFunc, $updateUserFunc for any shibonly affiliations |
| $query = "SELECT id FROM affiliation WHERE shibonly = 1"; |
| $qh = doQuery($query); |
| while($row = mysqli_fetch_assoc($qh)) { |
| $id = $row['id']; |
| if(! array_key_exists($id, $affilValFunc)) { |
| if(ALLOWADDSHIBUSERS) |
| $affilValFunc[$id] = function() {return 1;}; |
| else |
| $affilValFunc[$id] = function() {return 0;}; |
| } |
| if(! array_key_exists($id, $addUserFunc)) { |
| if(ALLOWADDSHIBUSERS) { |
| $addUserFunc[$id] = 'addShibUserStub'; |
| $addUserFuncArgs[$id] = $id; |
| } |
| else |
| $addUserFunc[$id] = function() {return 0;}; |
| } |
| if(! array_key_exists($id, $updateUserFunc)) |
| $updateUserFunc[$id] = function() {return NULL;}; |
| } |
| |
| # include appropriate files |
| switch($actions['pages'][$mode]) { |
| case 'blockAllocations': |
| require_once(".ht-inc/blockallocations.php"); |
| break; |
| case 'help': |
| require_once(".ht-inc/help.php"); |
| break; |
| case 'userPreferences': |
| require_once(".ht-inc/userpreferences.php"); |
| break; |
| case 'statistics': |
| require_once(".ht-inc/statistics.php"); |
| break; |
| case 'manageGroups': |
| require_once(".ht-inc/groups.php"); |
| break; |
| case 'privileges': |
| case 'userLookup': |
| require_once(".ht-inc/privileges.php"); |
| break; |
| case 'sitemaintenance': |
| require_once(".ht-inc/sitemaintenance.php"); |
| break; |
| case 'vm': |
| require_once(".ht-inc/vm.php"); |
| break; |
| case 'dashboard': |
| require_once(".ht-inc/dashboard.php"); |
| break; |
| case 'siteconfig': |
| require_once(".ht-inc/siteconfig.php"); |
| break; |
| case 'resource': |
| case 'config': |
| case 'image': |
| case 'computer': |
| case 'managementnode': |
| case 'schedule': |
| case 'addomain': |
| require_once(".ht-inc/resource.php"); |
| break; |
| case 'storebackend': |
| require_once(".ht-inc/storebackend.php"); |
| break; |
| /*case 'serverProfiles': |
| require_once(".ht-inc/serverprofiles.php"); |
| require_once(".ht-inc/requests.php"); |
| break;*/ |
| case 'oneClicks': |
| require_once(".ht-inc/oneclick.php"); |
| break; |
| default: |
| require_once(".ht-inc/requests.php"); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn vclAutoLoader($class) |
| /// |
| /// \param $class - name of a class |
| /// |
| /// \brief handles loading class implementation file for a specified class |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function vclAutoLoader($class) { |
| global $actions; |
| $class = strtolower($class); |
| require_once(".ht-inc/resource.php"); |
| if(array_key_exists($class, $actions['classmapping'])) { |
| require_once(".ht-inc/{$actions['classmapping'][$class]}.php"); |
| return; |
| } |
| require_once(".ht-inc/$class.php"); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn checkAccess() |
| /// |
| /// \brief gets the user's access level to the locker from the ptsowner_admin |
| /// table |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function checkAccess() { |
| global $mode, $user, $actionFunction, $authMechs; |
| global $itecsauthkey, $ENABLE_ITECSAUTH, $actions; |
| global $inContinuation, $apiValidateFunc; |
| if($mode == 'xmlrpccall') { |
| // double check for SSL |
| if(! isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") { |
| printXMLRPCerror(4); # must have SSL enabled |
| dbDisconnect(); |
| exit; |
| } |
| if(! isset($_SERVER['HTTP_X_USER'])) { |
| printXMLRPCerror(3); # access denied |
| dbDisconnect(); |
| exit; |
| } |
| $xmluser = processInputData($_SERVER['HTTP_X_USER'], ARG_STRING, 1); |
| if(! $user = getUserInfo($xmluser)) { |
| // if first call to getUserInfo fails, try calling with $noupdate set |
| if(! $user = getUserInfo($xmluser, 1)) { |
| $testid = $xmluser; |
| $affilid = DEFAULT_AFFILID; |
| getAffilidAndLogin($testid, $affilid); |
| addLoginLog($testid, 'unknown', $affilid, 0); |
| printXMLRPCerror(3); # access denied |
| dbDisconnect(); |
| exit; |
| } |
| } |
| if(! array_key_exists('HTTP_X_PASS', $_SERVER) || strlen($_SERVER['HTTP_X_PASS']) == 0) { |
| addLoginLog($xmluser, 'unknown', $user['affilid'], 0); |
| printXMLRPCerror(3); # access denied |
| dbDisconnect(); |
| exit; |
| } |
| $xmlpass = $_SERVER['HTTP_X_PASS']; |
| $apiver = processInputData($_SERVER['HTTP_X_APIVERSION'], ARG_NUMERIC, 1); |
| if($apiver == 1) { |
| addLoginLog($xmluser, 'unknown', $user['affilid'], 0); |
| printXMLRPCerror(8); # unsupported API version |
| dbDisconnect(); |
| exit; |
| } |
| elseif($apiver == 2) { |
| $authtype = ""; |
| foreach($authMechs as $key => $authmech) { |
| if($authmech['affiliationid'] == $user['affiliationid']) { |
| $authtype = $key; |
| break; |
| } |
| } |
| if(empty($authtype)) { |
| print "No authentication mechanism found for passed in X-User"; |
| addLoginLog($xmluser, 'unknown', $user['affilid'], 0); |
| dbDisconnect(); |
| exit; |
| } |
| if($authMechs[$authtype]['type'] == 'ldap') { |
| $auth = $authMechs[$authtype]; |
| $ds = ldap_connect("ldaps://{$auth['server']}/"); |
| if(! $ds) { |
| addLoginLog($xmluser, $authtype, $user['affilid'], 0); |
| printXMLRPCerror(5); # failed to connect to auth server |
| dbDisconnect(); |
| exit; |
| } |
| ldap_set_option($ds, LDAP_OPT_PROTOCOL_VERSION, 3); |
| ldap_set_option($ds, LDAP_OPT_REFERRALS, 0); |
| if($auth['lookupuserbeforeauth']) { |
| # in this case, we have to look up what part of the tree the user is in |
| # before we can actually look up the user |
| if(array_key_exists('masterlogin', $auth) && strlen($auth['masterlogin'])) |
| $res = ldap_bind($ds, $auth['masterlogin'], $auth['masterpwd']); |
| else |
| $res = ldap_bind($ds); |
| if(! $res) { |
| addLoginLog($user['unityid'], $authtype, $user['affiliationid'], 0); |
| printXMLRPCerror(5); # failed to connect to auth server |
| dbDisconnect(); |
| exit; |
| } |
| $search = ldap_search($ds, |
| $auth['binddn'], |
| "{$auth['lookupuserfield']}={$user['unityid']}", |
| array('dn'), 0, 3, 15); |
| if($search) { |
| $tmpdata = ldap_get_entries($ds, $search); |
| if(! $tmpdata['count'] || ! array_key_exists('dn', $tmpdata[0])) { |
| addLoginLog($user['unityid'], $authtype, $user['affiliationid'], 0); |
| printXMLRPCerror(3); # access denied |
| dbDisconnect(); |
| exit; |
| } |
| $ldapuser = $tmpdata[0]['dn']; |
| } |
| else { |
| addLoginLog($user['unityid'], $authtype, $user['affiliationid'], 0); |
| printXMLRPCerror(3); # access denied |
| dbDisconnect(); |
| exit; |
| } |
| } |
| else |
| $ldapuser = sprintf($auth['userid'], $user['unityid']); |
| $res = ldap_bind($ds, $ldapuser, $xmlpass); |
| if(! $res) { |
| addLoginLog($user['unityid'], $authtype, $user['affiliationid'], 0); |
| printXMLRPCerror(3); # access denied |
| dbDisconnect(); |
| exit; |
| } |
| addLoginLog($user['unityid'], $authtype, $user['affiliationid'], 1); |
| } |
| elseif($ENABLE_ITECSAUTH && |
| $authMechs[$authtype]['affiliationid'] == getAffiliationID('ITECS')) { |
| $rc = ITECSAUTH_validateUser($itecsauthkey, $user['unityid'], $xmlpass); |
| if(empty($rc) || $rc['passfail'] == 'fail') { |
| printXMLRPCerror(3); # access denied |
| dbDisconnect(); |
| exit; |
| } |
| } |
| elseif($authMechs[$authtype]['type'] == 'local') { |
| if(! validateLocalAccount($user['unityid'], $xmlpass)) { |
| printXMLRPCerror(3); # access denied |
| dbDisconnect(); |
| exit; |
| } |
| } |
| elseif($authMechs[$authtype]['type'] == 'redirect') { |
| $affilid = $authMechs[$authtype]['affiliationid']; |
| if(!(isset($apiValidateFunc) && is_array($apiValidateFunc) && |
| array_key_exists($affilid, $apiValidateFunc) && |
| $apiValidateFunc[$affilid]($xmluser, $xmlpass))) { |
| printXMLRPCerror(3); # access denied |
| dbDisconnect(); |
| exit; |
| } |
| } |
| else { |
| printXMLRPCerror(6); # unable to auth passed in X-User |
| dbDisconnect(); |
| exit; |
| } |
| } |
| else { |
| printXMLRPCerror(7); # unknown API version |
| dbDisconnect(); |
| exit; |
| } |
| } |
| elseif($mode == 'xmlrpcaffiliations') { |
| // double check for SSL, not really required for this mode, but it keeps things consistant |
| if(! isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != "on") { |
| printXMLRPCerror(4); # must have SSL enabled |
| dbDisconnect(); |
| exit; |
| } |
| $apiver = processInputData($_SERVER['HTTP_X_APIVERSION'], ARG_NUMERIC, 1); |
| if($apiver == 1) { |
| printXMLRPCerror(8); # unsupported API version |
| dbDisconnect(); |
| exit; |
| } |
| elseif($apiver != 2) { |
| printXMLRPCerror(7); # unknown API version |
| dbDisconnect(); |
| exit; |
| } |
| } |
| elseif(! empty($mode)) { |
| if(! in_array($mode, $actions['entry']) && |
| ! $inContinuation) { |
| $mode = "main"; |
| $actionFunction = "main"; |
| return; |
| } |
| else { |
| if(! $inContinuation) { |
| # check that user has access to this area |
| switch($mode) { |
| case 'viewGroups': |
| if(! in_array("groupAdmin", $user["privileges"])) { |
| $mode = ""; |
| $actionFunction = "main"; |
| return; |
| } |
| break; |
| /*case 'serverProfiles': |
| if(! in_array("serverProfileAdmin", $user["privileges"]) && |
| ! in_array("serverCheckOut", $user["privileges"])) { |
| $mode = ""; |
| $actionFunction = "main"; |
| return; |
| } |
| break;*/ |
| case 'pickTimeTable': |
| $computermetadata = getUserComputerMetaData(); |
| if(! count($computermetadata["platforms"]) || |
| ! count($computermetadata["schedules"])) { |
| $mode = ""; |
| $actionFunction = "main"; |
| return; |
| } |
| break; |
| case 'viewNodes': |
| if(! in_array("userGrant", $user["privileges"]) && |
| ! in_array("resourceGrant", $user["privileges"]) && |
| ! in_array("nodeAdmin", $user["privileges"])) { |
| $mode = ""; |
| $actionFunction = "main"; |
| return; |
| } |
| break; |
| case 'userLookup': |
| if(! checkUserHasPerm('User Lookup (global)') && |
| ! checkUserHasPerm('User Lookup (affiliation only)')) { |
| $mode = ""; |
| $actionFunction = "main"; |
| return; |
| } |
| break; |
| case 'editVMInfo': |
| if(! in_array("computerAdmin", $user["privileges"])) { |
| $mode = ""; |
| $actionFunction = "main"; |
| return; |
| } |
| break; |
| case 'siteMaintenance': |
| if(! checkUserHasPerm('Schedule Site Maintenance')) { |
| $mode = ""; |
| $actionFunction = "main"; |
| return; |
| } |
| break; |
| case 'dashboard': |
| if(! checkUserHasPerm('View Dashboard (global)') && |
| ! checkUserHasPerm('View Dashboard (affiliation only)')) { |
| $mode = ""; |
| $actionFunction = "main"; |
| return; |
| } |
| break; |
| } |
| } |
| } |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn checkCryptkey() |
| /// |
| /// \brief checks for an entry in cryptkey; if missing, generates keys |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function checkCryptkey() { |
| global $pemkey; |
| |
| $reg = "|" . SCRIPT . "$|"; |
| $filebase = preg_replace($reg, '', $_SERVER['SCRIPT_FILENAME']); |
| $filebase .= "/.ht-inc/cryptkey"; |
| $idfile = "$filebase/cryptkeyid"; |
| |
| if(is_file($idfile)) { |
| $fh = fopen($idfile, 'r'); |
| $id = fread($fh, 50); |
| fclose($fh); |
| $_id = vcl_mysql_escape_string($id); |
| |
| $query = "SELECT id " |
| . "FROM cryptkey " |
| . "WHERE id = '$_id'"; |
| $qh = doQuery($query); |
| if($row = mysqli_fetch_assoc($qh)) |
| return; |
| } |
| |
| // if no id file and cannot write to cryptkey directory, return |
| if(! is_writable($filebase)) |
| return; |
| |
| # no id file or no matching entry in cryptkey, create new key |
| $keyfile = "$filebase/private.pem"; |
| |
| $_algorithm = constant("OPENSSL_KEYTYPE_" . ASYMALGO); |
| |
| $args = array('private_key_bits' => ASYMLEN, |
| 'private_key_type' => $_algorithm); |
| # open and lock id file before generating key |
| $fh = fopen($idfile, 'w'); |
| if(! flock($fh, LOCK_EX | LOCK_NB)) { |
| # assume collision with another web server generating a key |
| # return because when the key is needed, it should exist from |
| # the other server |
| fclose($fh); |
| return; |
| } |
| # generate key pair |
| $prikeyobj = openssl_pkey_new($args); |
| # create and secure private key file |
| touch($keyfile); |
| chmod($keyfile, 0600); |
| # save private key to file |
| $rc = openssl_pkey_export_to_file($prikeyobj, $keyfile, $pemkey); |
| if(! $rc) { |
| # release lock, close and delete file, return |
| flock($fh, LOCK_UN); |
| fclose($fh); |
| unlink($keyfile); |
| return; |
| } |
| # save public key to database |
| $tmp = openssl_pkey_get_details($prikeyobj); |
| $pubkey = $tmp['key']; |
| $query = "INSERT INTO cryptkey " |
| . "(hostid, " |
| . "hosttype, " |
| . "pubkey, " |
| . "algorithm, " |
| . "algorithmoption, " |
| . "keylength) " |
| . "SELECT COALESCE(MAX(hostid), 0) + 1, " |
| . "'web', " |
| . "'$pubkey', " |
| . "'" . ASYMALGO . "', " |
| . "'" . ASYMOPT . "', " |
| . ASYMLEN . " " |
| . "FROM cryptkey " |
| . "WHERE hosttype = 'web'"; |
| doQuery($query); |
| $cryptkeyid = dbLastInsertID(); |
| # save cryptkey id to file |
| fwrite($fh, $cryptkeyid); |
| # unlock file |
| flock($fh, LOCK_UN); |
| fclose($fh); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn maintenanceCheck() |
| /// |
| /// \brief checks for site being in maintenance; if so, read user message from |
| /// current maintenance file; print site header, maintenance message, and site |
| /// foother; then exit; also removes any old maintenance files |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function maintenanceCheck() { |
| global $authed, $mode, $user; |
| $now = time(); |
| $reg = "|" . SCRIPT . "$|"; |
| $search = preg_replace($reg, '', $_SERVER['SCRIPT_FILENAME']); |
| $search .= "/.ht-inc/maintenance/"; |
| $files = glob("{$search}[0-9]*"); |
| if(! is_array($files)) |
| return; |
| if(empty($files)) { |
| dbConnect(); |
| $query = "SELECT id " |
| . "FROM sitemaintenance " |
| . "WHERE start <= NOW() AND " |
| . "end > NOW()"; |
| $qh = doQuery($query); |
| $ids = array(); |
| while($row = mysqli_fetch_assoc($qh)) |
| $ids[] = $row['id']; |
| if(empty($ids)) { |
| dbDisconnect(); |
| return; |
| } |
| $allids = implode(',', $ids); |
| $query = "UPDATE sitemaintenance " |
| . "SET end = NOW() " |
| . "WHERE id IN ($allids)"; |
| doQuery($query, 101, 'vcl', 1); |
| dbDisconnect(); |
| return; |
| } |
| $inmaintenance = 0; |
| $skin = ''; |
| foreach($files as $file) { |
| if(! preg_match("|^$search([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})$|", $file, $matches)) |
| continue; |
| #YYYYMMDDHHMM |
| $tmp = "{$matches[1]}-{$matches[2]}-{$matches[3]} {$matches[4]}:{$matches[5]}:00"; |
| $start = datetimeToUnix($tmp); |
| if($start < $now) { |
| # check to see if end time has been reached |
| $fh = fopen($file, 'r'); |
| $msg = ''; |
| while($line = fgets($fh)) { |
| $line = strip_tags($line); |
| if(preg_match("/^END=([0-9]{4})([0-9]{2})([0-9]{2})([0-9]{2})([0-9]{2})$/", $line, $matches)) { |
| $tmp = "{$matches[1]}-{$matches[2]}-{$matches[3]} {$matches[4]}:{$matches[5]}:00"; |
| $end = datetimeToUnix($tmp); |
| if($end < $now) { |
| fclose($fh); |
| unlink($file); |
| $_SESSION['usersessiondata'] = array(); |
| return; |
| } |
| else |
| $inmaintenance = 1; |
| } |
| elseif(preg_match("/^THEME=([-A-Za-z0-9@#_:;,\.])+$/", $line, $matches)) { |
| $skin = $matches[1]; |
| } |
| else |
| $msg .= $line; |
| } |
| fclose($fh); |
| if($inmaintenance) |
| break; |
| } |
| } |
| if($inmaintenance) { |
| $authed = 0; |
| $mode = 'inmaintenance'; |
| $user = array(); |
| if(array_key_exists('VCLSKIN', $_COOKIE)) |
| $skin = strtolower($_COOKIE['VCLSKIN']); |
| if($skin != '') { |
| $allskins = array(); |
| foreach(glob('themes/*') as $item) { |
| if(! is_dir($item)) |
| continue; |
| $tmp = explode('/', $item); |
| $item = array_pop($tmp); |
| $allskins[$item] = 1; |
| } |
| if(! array_key_exists($skin, $allskins)) |
| $skin = DEFAULTTHEME; |
| } |
| else |
| $skin = DEFAULTTHEME; |
| setVCLLocale(); |
| require_once("themes/$skin/page.php"); |
| printHTMLHeader(); |
| print "<h2>" . i("Site Currently Under Maintenance") . "</h2>\n"; |
| if(! empty($msg)) { |
| $msg = htmlentities($msg); |
| $msg = preg_replace("/\n/", "<br>\n", $msg); |
| print "$msg<br>\n"; |
| } |
| else |
| print i("This site is currently in maintenance.") . "<br>\n"; |
| $niceend = prettyDatetime($end, 1, 0, 1); |
| printf(i("The maintenance is scheduled to end <strong>%s</strong>.") . "<br><br><br>\n", $niceend); |
| printHTMLFooter(); |
| exit; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn maintenanceNotice() |
| /// |
| /// \brief checks informhoursahead for upcoming maintenance items and prints |
| /// message about upcoming maintenance if currently within warning window |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function maintenanceNotice() { |
| $items = getMaintItems(); |
| foreach($items as $item) { |
| $start = datetimeToUnix($item['start']); |
| $file = date('YmdHi', $start); |
| $secahead = $item['informhoursahead'] * 3600; |
| if($start - $secahead < time()) { |
| $reg = "|" . SCRIPT . "$|"; |
| $search = preg_replace($reg, '', $_SERVER['SCRIPT_FILENAME']); |
| $search .= "/.ht-inc/maintenance/$file"; |
| $files = glob("$search"); |
| if(empty($files)) { |
| $_SESSION['usersessiondata'] = array(); |
| return; |
| } |
| $nicestart = prettyDatetime($start, 1, 0, 1); |
| $niceend = prettyDatetime($item['end'], 1, 0, 1); |
| print "<div id=\"maintenancenotice\">\n"; |
| print "<strong>" . i("NOTICE:") . "</strong> "; |
| print i("This site will be down for maintenance during the following times:") . "<br><br>\n"; |
| print i("Start:") . " $nicestart<br>\n"; |
| print i("End:") . " $niceend.<br><br>\n"; |
| if($item['allowreservations']) { |
| print i("You will be able to access your reserved machines during this maintenance. However, you will not be able to access information on how to connect to them.") . "<br>\n"; |
| } |
| else { |
| print i("You will not be able to access any of your reservations during this maintenance.") . "<br>\n"; |
| } |
| print "</div>\n"; |
| return; |
| } |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn clearPrivCache() |
| /// |
| /// \brief sets userresources, nodeprivileges, cascadenodeprivileges, and |
| /// userhaspriv keys of $_SESSION array to empty arrays |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function clearPrivCache() { |
| $_SESSION['userresources'] = array(); |
| $_SESSION['nodeprivileges'] = array(); |
| $_SESSION['cascadenodeprivileges'] = array(); |
| $_SESSION['userhaspriv'] = array(); |
| $_SESSION['compstateflow'] = array(); |
| $_SESSION['usersessiondata'] = array(); |
| $_SESSION['variables'] = array(); |
| unset($_SESSION['user']); |
| unset($_SESSION['locales']); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn AJclearPermCache() |
| /// |
| /// \brief ajax wrapper for clearPrivCache |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function AJclearPermCache() { |
| clearPrivCache(); |
| print "alert('Permission cache cleared');"; |
| dbDisconnect(); |
| exit; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn setupSession() |
| /// |
| /// \brief starts php session and initializes useful variables |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function setupSession() { |
| global $mode; |
| if($mode == 'xmlrpccall') |
| $_SESSION = array(); |
| else |
| session_start(); |
| if(! array_key_exists('cachetimestamp', $_SESSION)) |
| $_SESSION['cachetimestamp'] = time(); |
| else { |
| if(($_SESSION['cachetimestamp'] + (PRIV_CACHE_TIMEOUT * 60)) < time()) { |
| clearPrivCache(); |
| $_SESSION['cachetimestamp'] = time(); |
| return; |
| } |
| } |
| if(! array_key_exists('userresources', $_SESSION)) |
| $_SESSION['userresources'] = array(); |
| if(! array_key_exists('nodeprivileges', $_SESSION)) |
| $_SESSION['nodeprivileges'] = array(); |
| if(! array_key_exists('cascadenodeprivileges', $_SESSION)) |
| $_SESSION['cascadenodeprivileges'] = array(); |
| if(! array_key_exists('userhaspriv', $_SESSION)) |
| $_SESSION['userhaspriv'] = array(); |
| if(! array_key_exists('compstateflow', $_SESSION)) |
| $_SESSION['compstateflow'] = array(); |
| if(! array_key_exists('usersessiondata', $_SESSION)) |
| $_SESSION['usersessiondata'] = array(); |
| if(! array_key_exists('variables', $_SESSION)) |
| $_SESSION['variables'] = array(); |
| if(! array_key_exists('persistdata', $_SESSION)) |
| $_SESSION['persistdata'] = array(); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn stopSession() |
| /// |
| /// \brief ends the user's session and prints info to notify the user |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function stopSession() { |
| $_SESSION = array(); |
| if(isset($_COOKIE[session_name()])) |
| setcookie(session_name(), "", time()-42000, '/'); |
| session_destroy(); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn main() |
| /// |
| /// \brief prints a welcome screen |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function main() { |
| global $user, $authed; |
| print "<H2>" . i("Welcome to the Virtual Computing Lab") . "</H2>\n"; |
| if($authed) { |
| if(! empty($user['lastname']) && ! empty($user['preferredname'])) |
| print i("Hello") . " {$user["preferredname"]} {$user['lastname']}<br><br>\n"; |
| elseif(! empty($user['lastname']) && ! empty($user['firstname'])) |
| print i("Hello") . " {$user["firstname"]} {$user['lastname']}<br><br>\n"; |
| $tmp = array_values($user['groups']); |
| if(count($tmp) == 1 && $tmp[0] == 'nodemo') { |
| print "Your account is a demo account that has expired. "; |
| print "You cannot make any more reservations. Please contact <a href=\""; |
| print "mailto:" . HELPEMAIL . "\">" . HELPEMAIL . "</a> if you need "; |
| print "further access to VCL.<br>\n"; |
| return; |
| } |
| $requests = getUserRequests("all", $user["id"]); |
| if($num = count($requests)) { |
| if($num == 1) |
| print i("You currently have 1 reservation.") . "<br>\n"; |
| else |
| printf(i("You currently have %d reservations.") . "<br>\n", $num); |
| } |
| else { |
| print i("You do not have any current reservations.") . "<br>\n"; |
| } |
| print i("Please make a selection from the menu to continue.") . "<br>\n"; |
| } |
| else { |
| print i("Please log in to start using the VCL system.") . "<br>\n"; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn abort($errcode, $query) |
| /// |
| /// \param $errcode - error code |
| /// \param $query - a myql query |
| /// |
| /// \brief prints out error message(s), closes db connection, prints footer |
| /// and exits |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function abort($errcode, $query="") { |
| global $mysqli_link_vcl, $mysqli_link_acct, $ERRORS, $user, $mode; |
| global $ENABLE_ITECSAUTH, $requestInfo, $aborting; |
| if(! isset($aborting)) |
| $aborting = 1; |
| elseif($aborting == 1) |
| return; |
| if($mode == 'xmlrpccall') |
| xmlRPCabort($errcode, $query); |
| if(ONLINEDEBUG && checkUserHasPerm('View Debug Information')) { |
| if($errcode >= 100 && $errcode < 400) { |
| print "<span class=\"rederrormsg\">" . mysqli_error($mysqli_link_vcl) . "</span><br>\n"; |
| error_log(mysqli_error($mysqli_link_vcl)); |
| if($ENABLE_ITECSAUTH) { |
| print "<span class=\"rederrormsg\">" . mysqli_error($mysqli_link_acct) . "</span><br>\n"; |
| error_log(mysqli_error($mysqli_link_acct)); |
| } |
| print "$query<br>\n"; |
| error_log($query); |
| } |
| print "ERROR($errcode): " . $ERRORS["$errcode"] . "<BR>\n"; |
| error_log("==========================================================================="); |
| error_log("ERROR($errcode): " . $ERRORS["$errcode"]); |
| $backtrace = getBacktraceString(FALSE); |
| print "<pre>\n"; |
| print $backtrace; |
| print "</pre>\n"; |
| error_log($backtrace); |
| } |
| else { |
| $message = ""; |
| if($errcode >= 100 && $errcode < 400) { |
| $message .= mysqli_error($mysqli_link_vcl) . "\n"; |
| if($ENABLE_ITECSAUTH) |
| $message .= mysqli_error($mysqli_link_acct) . "\n"; |
| $message .= $query . "\n"; |
| } |
| $message .= "ERROR($errcode): " . $ERRORS["$errcode"] . "\n"; |
| if(is_array($user) && array_key_exists('unityid', $user)) |
| $message .= "Logged in user was " . $user["unityid"] . "\n"; |
| $message .= "Mode was $mode\n\n"; |
| if($errcode == 20) { |
| $urlArray = explode('?', $_SERVER["HTTP_REFERER"]); |
| $message .= "HTTP_REFERER URL - " . $urlArray[0] . "\n"; |
| $message .= "correct URL - " . BASEURL . SCRIPT . "\n"; |
| } |
| if($errcode == 40) { |
| $message .= "One of the following computers didn't get a mgmt node:\n"; |
| foreach($requestInfo["images"] as $key => $imageid) { |
| $message .= "imageid: $imageid\n"; |
| $message .= "compid: {$requestInfo['computers'][$key]}\n"; |
| } |
| } |
| $message .= getBacktraceString(FALSE); |
| if($errcode == 8) |
| $message = preg_replace("/Argument#: 3 => .*\n/", "Argument#: 3 => *********\n", $message); |
| $mailParams = "-f" . ENVELOPESENDER; |
| error_log($message); |
| mail(ERROREMAIL, "Error with VCL pages ($errcode)", $message, '', $mailParams); |
| $subj = rawurlencode(i("Problem With VCL")); |
| $href = "<a href=\"mailto:" . HELPEMAIL . "?Subject=$subj\">" . HELPEMAIL . "</a>"; |
| printf(i("An error has occurred. If this problem persists, please email %s for further assistance. Please include the steps you took that led up to this problem in your email message."), $href); |
| } |
| |
| // call clearPrivCache in case that helps clear up what caused the error |
| clearPrivCache(); |
| |
| // release semaphore lock |
| cleanSemaphore(); |
| dbDisconnect(); |
| printHTMLFooter(); |
| exit; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn errorrpt() |
| /// |
| /// \brief takes input from ajax call and emails error to ERROREMAIL |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function errorrpt() { |
| $mailParams = "-f" . ENVELOPESENDER; |
| mail(ERROREMAIL, "Error with VCL pages (ajax sent html wrappers)", $_POST['data'], '', $mailParams); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn validateUserid($loginid) |
| /// |
| /// \param $loginid - a submitted loginid |
| /// |
| /// \return 0 if the loginid is not found in one of the authentications |
| /// systems, 1 if it is |
| /// |
| /// \brief checks to see if $loginid is found in one of the authentication |
| /// systems |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function validateUserid($loginid) { |
| global $affilValFuncArgs, $affilValFunc; |
| if(empty($loginid)) |
| return 0; |
| |
| $rc = getAffilidAndLogin($loginid, $affilid); |
| if($rc == -1) |
| return 0; |
| |
| if(empty($affilid)) |
| return 0; |
| |
| $escloginid = vcl_mysql_escape_string($loginid); |
| $query = "SELECT id " |
| . "FROM user " |
| . "WHERE unityid = '$escloginid' AND " |
| . "affiliationid = $affilid"; |
| $qh = doQuery($query, 101); |
| if(mysqli_num_rows($qh)) |
| return 1; |
| |
| if($rc == 0 && |
| ALLOWADDSHIBUSERS == 1 && |
| strpos($loginid, '@')) { |
| $query = "SELECT shibonly " |
| . "FROM affiliation " |
| . "WHERE id = " . DEFAULT_AFFILID; |
| $qh = doQuery($query); |
| $row = mysqli_fetch_assoc($qh); |
| if($row['shibonly'] == 1) |
| return 0; |
| } |
| |
| $valfunc = $affilValFunc[$affilid]; |
| if(array_key_exists($affilid, $affilValFuncArgs)) |
| return $valfunc($affilValFuncArgs[$affilid], $loginid); |
| else |
| return $valfunc($loginid); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn AJvalidateUserid() |
| /// |
| /// \brief checks to see if submitted userid is valid |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function AJvalidateUserid() { |
| $user = processInputVar('user', ARG_STRING); |
| if(validateUserid($user)) |
| sendJSON(array('status' => 'valid')); |
| else |
| sendJSON(array('status' => 'invalid')); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getAffilidAndLogin(&$login, &$affilid) |
| /// |
| /// \param $login - login for user, may include \@affiliation |
| /// \param $affilid - variable in which to stick the affiliation id |
| /// |
| /// \return 1 if $affilid set by a registered function, 0 if set to default, |
| /// -1 if @affiliation was part of $login but did not contain a known |
| /// affiliation |
| /// |
| /// \brief tries registered affiliation lookup functions to determine the |
| /// affiliation id of the user; if it finds it, sticks the affiliationid in |
| /// $affilid and sets $login to not include \@affiliation if it did |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getAffilidAndLogin(&$login, &$affilid) { |
| global $findAffilFuncs; |
| foreach($findAffilFuncs as $func) { |
| $rc = $func($login, $affilid); |
| if($rc) |
| return $rc; |
| } |
| $affilid = DEFAULT_AFFILID; |
| return 0; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn mysql_connect_plus($host, $user, $pwd, $db) |
| /// |
| /// \param $host - mysql host |
| /// \param $user - userid to use for connection |
| /// \param $pwd - password to use for connection |
| /// \param $db - database to use after connecting |
| /// |
| /// \return mysql resource identifier, 0 if failure to connect |
| /// |
| /// \brief opens a socket connection to $host, if it is not established in 5 |
| /// seconds, returns an error, otherwise, opens a connection to the database |
| /// and returns the identifier |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function mysql_connect_plus($host, $user, $pwd, $db) { |
| $timeout = 5; /* timeout in seconds */ |
| |
| if($fp = @fsockopen($host, 3306, $errno, $errstr, $timeout)) { |
| fclose($fp); |
| return $link = mysqli_connect($host, $user, $pwd, $db); |
| } else { |
| #print "ERROR: socket timeout<BR>\n"; |
| return 0; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn dbConnect() |
| /// |
| /// \brief opens connections to database, the resource identifiers are\n |
| /// \b $mysqli_link_vcl - for vcl database\n |
| /// \b $mysqli_link_acct - for accounts database\n |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function dbConnect() { |
| global $vclhost, $vcldb, $vclusername, $vclpassword, $mysqli_link_vcl; |
| global $accthost, $acctusername, $acctpassword, $mysqli_link_acct; |
| global $ENABLE_ITECSAUTH; |
| |
| if($ENABLE_ITECSAUTH) { |
| // open a connection to mysql server for accounts |
| if(! ($mysqli_link_acct = mysql_connect_plus($accthost, $acctusername, $acctpassword, 'accounts'))) |
| $ENABLE_ITECSAUTH = 0; |
| } |
| |
| // open a connection to mysql server for vcl |
| if(! $mysqli_link_vcl = mysql_connect_plus($vclhost, $vclusername, $vclpassword, $vcldb)) { |
| die("Error connecting to $vclhost.<br>\n"); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn dbDisconnect() |
| /// |
| /// \brief closes connections to the database |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function dbDisconnect() { |
| global $mysqli_link_vcl, $mysqli_link_acct, $ENABLE_ITECSAUTH; |
| mysqli_close($mysqli_link_vcl); |
| if($ENABLE_ITECSAUTH) |
| mysqli_close($mysqli_link_acct); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn doQuery($query, $errcode, $db, $nolog) |
| /// |
| /// \param $query - SQL statement |
| /// \param $errcode - error code |
| /// \param $db - (optional, defaul=vcl), database to query against |
| /// \param $nolog - (optional, defaul=0), don't log to queryLog table |
| /// |
| /// \return $qh - query handle |
| /// |
| /// \brief performs the query and returns $qh or aborts on error |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function doQuery($query, $errcode=101, $db="vcl", $nolog=0) { |
| global $mysqli_link_vcl, $mysqli_link_acct, $user, $mode, $ENABLE_ITECSAUTH; |
| if($db == "vcl") { |
| if(QUERYLOGGING != 0 && (! $nolog) && |
| preg_match('/^(UPDATE|INSERT|DELETE)/', $query) && |
| strpos($query, 'UPDATE continuations SET expiretime = ') === FALSE) { |
| if(isset($user['id'])) |
| $id = $user['id']; |
| else |
| $id = 0; |
| $q = "INSERT INTO querylog " |
| . "(userid, " |
| . "timestamp, " |
| . "mode, " |
| . "query) " |
| . "VALUES " |
| . "(?, " # $id |
| . "NOW(), " |
| . "?, " # $mode |
| . "?)"; # $logquery |
| $s = mysqli_prepare($mysqli_link_vcl, $q); |
| mysqli_stmt_bind_param($s, 'iss', $id, $mode, $query); |
| mysqli_stmt_execute($s); |
| } |
| for($i = 0; ! ($qh = mysqli_query($mysqli_link_vcl, $query)) && $i < 3; $i++) { |
| if(mysqli_errno($mysqli_link_vcl) == '1213') # DEADLOCK, sleep and retry |
| usleep(50); |
| else |
| abort($errcode, $query); |
| } |
| } |
| elseif($db == "accounts") { |
| if($ENABLE_ITECSAUTH) |
| $qh = mysqli_query($mysqli_link_acct, $query) or abort($errcode, $query); |
| else |
| $qh = NULL; |
| } |
| return $qh; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn doPSQuery($query, $paramtypes, $params, $errcode, $db, $nolog) |
| /// |
| /// \param $query - SQL statement |
| /// \param $paramtypes - string containing the types of parameters to fill in |
| /// for the ?s in the query, ex: 'ssi' for string string integer |
| /// \param $params - array of parameters to fill in for the ?s in the query |
| /// \param $errcode - error code |
| /// \param $db - (optional, defaul=vcl), database to query against |
| /// \param $nolog - (optional, defaul=0), don't log to queryLog table |
| /// |
| /// \return $qh - query handle or NULL if problem encountered |
| /// |
| /// \brief performs the query and returns $qh or aborts on error |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function doPSQuery($query, $paramtypes, $params, $errcode=101, $db="vcl", |
| $nolog=0) { |
| global $mysqli_link_vcl, $mysqli_link_acct, $user, $mode, $ENABLE_ITECSAUTH; |
| global $totalQueries, $queryTimes, $totalQueryTime; |
| $totalQueries++; |
| if(strlen($paramtypes) != count($params)) |
| return NULL; |
| if($db == "vcl") { |
| if(QUERYLOGGING != 0 && (! $nolog) && |
| preg_match('/^(UPDATE|INSERT|DELETE)/', $query) && |
| strpos($query, 'UPDATE continuations SET expiretime = ') === FALSE) { |
| if(isset($user['id'])) |
| $id = $user['id']; |
| else |
| $id = 0; |
| $q = "INSERT INTO querylog " |
| . "(userid, " |
| . "timestamp, " |
| . "mode, " |
| . "query) " |
| . "VALUES " |
| . "(?, " # $id |
| . "NOW(), " |
| . "?, " # $mode |
| . "?)"; # $logquery |
| $s = mysqli_prepare($mysqli_link_vcl, $q); |
| mysqli_stmt_bind_param($s, 'iss', $id, $mode, $query); |
| mysqli_stmt_execute($s); |
| } |
| $stmt = mysqli_prepare($mysqli_link_vcl, $query); |
| if(strlen($paramtypes)) |
| mysqli_stmt_bind_param($stmt, $paramtypes, ...$params); |
| for($i = 0; ! mysqli_stmt_execute($stmt) && $i < 3; $i++) { |
| if(mysqli_errno($mysqli_link_vcl) == '1213') # DEADLOCK, sleep and retry |
| usleep(50); |
| else |
| abort($errcode, $query); |
| } |
| $qh = mysqli_stmt_get_result($stmt); |
| } |
| elseif($db == "accounts") { |
| if($ENABLE_ITECSAUTH) { |
| $stmt = mysqli_prepare($mysqli_link_acct, $query); |
| mysqli_stmt_bind_param($stmt, $paramtypes, ...$params); |
| mysqli_stmt_execute($stmt); |
| $qh = mysqli_stmt_get_result($stmt) or abort($errcode, $query); |
| } |
| else |
| $qh = NULL; |
| } |
| return $qh; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn dbLastInsertID() |
| /// |
| /// \return last insert id for $mysqli_link_vcl |
| /// |
| /// \brief calls mysqli_insert_id for $mysqli_link_vcl |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function dbLastInsertID() { |
| global $mysqli_link_vcl; |
| return mysqli_insert_id($mysqli_link_vcl); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn vcl_mysql_escape_string($string) { |
| /// |
| /// \param $string - string to be escaped |
| /// |
| /// \return escaped string |
| /// |
| /// \brief wrapper for mysqli_real_escape_string so that $mysqli_link_vcl global |
| /// variable doesn't have to be included in every function needing to call it |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function vcl_mysql_escape_string($string) { |
| global $mysqli_link_vcl; |
| if(is_null($string)) |
| $string = ''; |
| return mysqli_real_escape_string($mysqli_link_vcl, $string); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getOSList() |
| /// |
| /// \return $oslist - array of OSs |
| /// |
| /// \brief builds an array of OSs |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getOSList() { |
| $query = "SELECT id, name, prettyname, type, installtype FROM OS ORDER BY prettyname"; |
| $qh = doQuery($query, "115"); |
| $oslist = array(); |
| while($row = mysqli_fetch_assoc($qh)) |
| $oslist[$row['id']] = $row; |
| return $oslist; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getImages($includedeleted=0, $imageid=0) |
| /// |
| /// \param $includedeleted = (optional) 1 to show deleted images, 0 not to |
| /// \param $imageid = (optional) only get data for this image, defaults |
| /// to getting data for all images |
| /// |
| /// \return $imagelist - array of images with the following elements:\n |
| /// \b name - name of image\n |
| /// \b prettyname - pretty name of image\n |
| /// \b ownerid - userid of owner\n |
| /// \b owner - unity id of owner\n |
| /// \b platformid - platformid for the platform the image if for\n |
| /// \b platform - platform the image is for\n |
| /// \b osid - osid for the os on the image\n |
| /// \b os - os the image contains\n |
| /// \b installtype - method used to install image\n |
| /// \b ostypeid - id of the OS type in the image\n |
| /// \b ostype - name of the OS type in the image\n |
| /// \b minram - minimum amount of RAM needed for image\n |
| /// \b minprocnumber - minimum number of processors needed for image\n |
| /// \b minprocspeed - minimum speed of processor(s) needed for image\n |
| /// \b minnetwork - minimum speed of network needed for image\n |
| /// \b maxconcurrent - maximum concurrent usage of this iamge\n |
| /// \b reloadtime - time in minutes for image to be loaded\n |
| /// \b deleted - 'yes' or 'no'; whether or not this image has been deleted\n |
| /// \b test - 0 or 1; whether or not there is a test version of this image\n |
| /// \b resourceid - image's resource id from the resource table\n |
| /// \b lastupdate - datetime image was last updated\n |
| /// \b forcheckout - 0 or 1; whether or not the image is allowed to be directly |
| /// checked out\n |
| /// \b maxinitialtime - maximum time (in minutes) to be shown when requesting |
| /// a reservation that the image can reserved for\n |
| /// \b imagemetaid - NULL or corresponding id from imagemeta table and the |
| /// following additional information:\n |
| /// \b checkuser - whether or not vcld should check for a logged in user\n |
| /// \b sysprep - whether or not to use sysprep on creation of the image\n |
| /// \b connectmethods - array of enabled connect methods\n |
| /// \b subimages - an array of subimages to be loaded along with selected |
| /// image\n |
| /// \b imagerevision - an array of revision info about the image, it has these |
| /// keys: id, revision, userid, user, datecreated, prettydate, production, |
| /// imagename |
| /// |
| /// \brief generates an array of images |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getImages($includedeleted=0, $imageid=0) { |
| # key in $imagelist is for $includedeleted |
| static $imagelist = array(0 => array(), 1 => array()); |
| if(! empty($imagelist[$includedeleted])) { |
| if($imageid == 0) |
| return $imagelist[$includedeleted]; |
| else |
| return array($imageid => $imagelist[$includedeleted][$imageid]); |
| } |
| # get all image meta data |
| $allmetadata = array(); |
| $query = "SELECT checkuser, " |
| . "rootaccess, " |
| . "subimages, " |
| . "sysprep, " |
| . "sethostname, " |
| . "id " |
| . "FROM imagemeta"; |
| $qh = doQuery($query); |
| while($row = mysqli_fetch_assoc($qh)) |
| $allmetadata[$row['id']] = $row; |
| |
| # get all image revision data |
| $allrevisiondata = array(); |
| $query = "SELECT i.id, " |
| . "i.imageid, " |
| . "i.revision, " |
| . "i.userid, " |
| . "CONCAT(u.unityid, '@', a.name) AS user, " |
| . "i.datecreated, " |
| . "DATE_FORMAT(i.datecreated, '%c/%d/%y %l:%i %p') AS prettydate, " |
| . "i.deleted, " |
| . "i.datedeleted, " |
| . "i.production, " |
| . "i.imagename " |
| . "FROM imagerevision i, " |
| . "affiliation a, " |
| . "user u " |
| . "WHERE i.userid = u.id AND "; |
| if(! $includedeleted) |
| $query .= "i.deleted = 0 AND "; |
| $query .= "u.affiliationid = a.id " |
| . "ORDER BY i.imageid, i.revision"; |
| $qh = doQuery($query, 101); |
| while($row = mysqli_fetch_assoc($qh)) { |
| $id = $row['imageid']; |
| unset($row['imageid']); |
| $allrevisiondata[$id][$row['id']] = $row; |
| } |
| $query = "SELECT i.id AS id," |
| . "i.name AS name, " |
| . "i.prettyname AS prettyname, " |
| . "i.ownerid AS ownerid, " |
| . "CONCAT(u.unityid, '@', a.name) AS owner, " |
| . "i.platformid AS platformid, " |
| . "p.name AS platform, " |
| . "i.OSid AS osid, " |
| . "o.name AS os, " |
| . "o.installtype, " |
| . "ot.id AS ostypeid, " |
| . "ot.name AS ostype, " |
| . "i.minram AS minram, " |
| . "i.minprocnumber AS minprocnumber, " |
| . "i.minprocspeed AS minprocspeed, " |
| . "i.minnetwork AS minnetwork, " |
| . "i.maxconcurrent AS maxconcurrent, " |
| . "i.reloadtime AS reloadtime, " |
| . "i.deleted AS deleted, " |
| . "i.test AS test, " |
| . "r.id AS resourceid, " |
| . "i.lastupdate, " |
| . "i.forcheckout, " |
| . "i.maxinitialtime, " |
| . "i.imagemetaid, " |
| . "ad.id AS addomainid, " |
| . "ad.name AS addomain, " |
| . "iadd.baseOU " |
| . "FROM platform p, " |
| . "OS o, " |
| . "OStype ot, " |
| . "resource r, " |
| . "resourcetype t, " |
| . "user u, " |
| . "affiliation a, " |
| . "image i " |
| . "LEFT JOIN imageaddomain iadd ON (i.id = iadd.imageid) " |
| . "LEFT JOIN addomain ad ON (iadd.addomainid = ad.id) " |
| . "WHERE i.platformid = p.id AND " |
| . "r.resourcetypeid = t.id AND " |
| . "t.name = 'image' AND " |
| . "r.subid = i.id AND " |
| . "i.OSid = o.id AND " |
| . "o.type = ot.name AND " |
| . "i.ownerid = u.id AND " |
| . "u.affiliationid = a.id "; |
| if(! $includedeleted) |
| $query .= "AND i.deleted = 0 "; |
| $query .= "ORDER BY i.prettyname"; |
| $qh = doQuery($query, 120); |
| while($row = mysqli_fetch_assoc($qh)) { |
| if(is_null($row['maxconcurrent'])) |
| $row['maxconcurrent'] = 0; |
| $imagelist[$includedeleted][$row["id"]] = $row; |
| $imagelist[$includedeleted][$row["id"]]['checkuser'] = 1; |
| $imagelist[$includedeleted][$row["id"]]['rootaccess'] = 1; |
| if($row['ostype'] == 'windows' || $row['ostype'] == 'osx') |
| $imagelist[$includedeleted][$row['id']]['sethostname'] = 0; |
| else |
| $imagelist[$includedeleted][$row['id']]['sethostname'] = 1; |
| $imagelist[$includedeleted][$row['id']]['adauthenabled'] = 0; |
| if($row['addomainid'] != NULL) |
| $imagelist[$includedeleted][$row['id']]['adauthenabled'] = 1; |
| if($row["imagemetaid"] != NULL) { |
| if(isset($allmetadata[$row['imagemetaid']])) { |
| $metaid = $row['imagemetaid']; |
| $imagelist[$includedeleted][$row['id']]['checkuser'] = $allmetadata[$metaid]['checkuser']; |
| $imagelist[$includedeleted][$row['id']]['rootaccess'] = $allmetadata[$metaid]['rootaccess']; |
| $imagelist[$includedeleted][$row['id']]['sysprep'] = $allmetadata[$metaid]['sysprep']; |
| if($allmetadata[$metaid]['sethostname'] != NULL) |
| $imagelist[$includedeleted][$row['id']]['sethostname'] = $allmetadata[$metaid]['sethostname']; |
| $imagelist[$includedeleted][$row["id"]]["subimages"] = array(); |
| if($allmetadata[$metaid]["subimages"]) { |
| $query2 = "SELECT imageid " |
| . "FROM subimages " |
| . "WHERE imagemetaid = $metaid"; |
| $qh2 = doQuery($query2, 101); |
| while($row2 = mysqli_fetch_assoc($qh2)) |
| $imagelist[$includedeleted][$row["id"]]["subimages"][] = $row2["imageid"]; |
| } |
| } |
| else |
| $imagelist[$includedeleted][$row["id"]]["imagemetaid"] = NULL; |
| } |
| if(isset($allrevisiondata[$row['id']])) |
| $imagelist[$includedeleted][$row['id']]['imagerevision'] = $allrevisiondata[$row['id']]; |
| $imagelist[$includedeleted][$row['id']]['connectmethods'] = getImageConnectMethods($row['id']); |
| } |
| if($imageid != 0) |
| return array($imageid => $imagelist[$includedeleted][$imageid]); |
| return $imagelist[$includedeleted]; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getServerProfiles($id) |
| /// |
| /// \param $id - (optional) if specified, only return data for specified profile |
| /// |
| /// \return an array where each key is a profile id whose value is an array with |
| /// these values:\n |
| /// \b name - profile name\n |
| /// \b description - profile description\n |
| /// \b imageid - id of image associated with profile\n |
| /// \b image - pretty name of image associated with profile\n |
| /// \b ownerid - user id of owner of profile\n |
| /// \b owner - unityid of owner of profile\n |
| /// \b fixedIP - IP address to be used with deployed profile\n |
| /// \b fixedMAC - MAC address to be used with deployed profile\n |
| /// \b admingroupid - id of admin user group associated with profile\n |
| /// \b admingroup - name of admin user group associated with profile\n |
| /// \b logingroupid - id of login user group associated with profile\n |
| /// \b logingroup - name of login user group associated with profile\n |
| /// \b monitored - whether or not deployed profile should be monitored\n |
| /// \b resourceid - resource id of profile |
| /// |
| /// \brief gets information about server profiles |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| /*function getServerProfiles($id=0) { |
| $key = getKey(array('getServerProfiles', $id)); |
| if(isset($_SESSION['usersessiondata'][$key])) |
| return $_SESSION['usersessiondata'][$key]; |
| |
| $fixeddata = array(); |
| $query = "SELECT name, value FROM variable WHERE name LIKE 'fixedIPsp%'"; |
| $qh = doQuery($query); |
| while($row = mysqli_fetch_assoc($qh)) { |
| $spid = str_replace('fixedIPsp', '', $row['name']); |
| $fixeddata[$spid] = Spyc::YAMLLoad($row['value']); |
| } |
| |
| $query = "SELECT s.id, " |
| . "s.name, " |
| . "s.description, " |
| . "s.imageid, " |
| . "i.prettyname AS image, " |
| . "s.ownerid, " |
| . "CONCAT(u.unityid, '@', a.name) AS owner, " |
| . "s.fixedIP, " |
| . "s.fixedMAC, " |
| . "s.admingroupid, " |
| . "CONCAT(ga.name, '@', aa.name) AS admingroup, " |
| . "s.logingroupid, " |
| . "CONCAT(gl.name, '@', al.name) AS logingroup, " |
| . "s.monitored, " |
| . "r.id AS resourceid " |
| . "FROM serverprofile s " |
| . "LEFT JOIN image i ON (i.id = s.imageid) " |
| . "LEFT JOIN user u ON (u.id = s.ownerid) " |
| . "LEFT JOIN affiliation a ON (a.id = u.affiliationid) " |
| . "LEFT JOIN usergroup ga ON (ga.id = s.admingroupid) " |
| . "LEFT JOIN affiliation aa ON (aa.id = ga.affiliationid) " |
| . "LEFT JOIN usergroup gl ON (gl.id = s.logingroupid) " |
| . "LEFT JOIN affiliation al ON (al.id = gl.affiliationid) " |
| . "LEFT JOIN resource r ON (r.subid = s.id) " |
| . "WHERE r.resourcetypeid = 17 "; |
| if($id != 0) |
| $query .= "AND s.id = $id"; |
| else |
| $query .= "ORDER BY name"; |
| $qh = doQuery($query, 101); |
| $profiles = array(); |
| while($row = mysqli_fetch_assoc($qh)) { |
| $profiles[$row['id']] = $row; |
| if(isset($fixeddata[$row['id']])) { |
| $profiles[$row['id']]['netmask'] = $fixeddata[$row['id']]['netmask']; |
| $profiles[$row['id']]['router'] = $fixeddata[$row['id']]['router']; |
| $profiles[$row['id']]['dns'] = implode(',', $fixeddata[$row['id']]['dns']); |
| } |
| else { |
| $profiles[$row['id']]['netmask'] = ''; |
| $profiles[$row['id']]['router'] = ''; |
| $profiles[$row['id']]['dns'] = ''; |
| } |
| } |
| $_SESSION['usersessiondata'][$key] = $profiles; |
| return $profiles; |
| }*/ |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getServerProfileImages($userid) |
| /// |
| /// \param $userid - id from user table |
| /// |
| /// \return array where the key is the id of the image and the value is the |
| /// prettyname of the image |
| /// |
| /// \brief builds an array of images that user has access to via server profiles |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| /*function getServerProfileImages($userid) { |
| $key = getKey(array('getServerProfileImages', $userid)); |
| if(isset($_SESSION['usersessiondata'][$key])) |
| return $_SESSION['usersessiondata'][$key]; |
| $resources = getUserResources(array('serverCheckOut', 'serverProfileAdmin'), |
| array('available', 'administer')); |
| $ids = array_keys($resources['serverprofile']); |
| $inids = implode(',', $ids); |
| if(empty($inids)) { |
| $_SESSION['usersessiondata'][$key] = array(); |
| return array(); |
| } |
| $query = "SELECT i.id, " |
| . "i.prettyname AS image " |
| . "FROM serverprofile s, " |
| . "image i " |
| . "WHERE s.imageid = i.id AND " |
| . "s.id IN ($inids)"; |
| $qh = doQuery($query, 101); |
| $profiles = array(); |
| while($row = mysqli_fetch_assoc($qh)) |
| $profiles[$row['id']] = $row['image']; |
| $_SESSION['usersessiondata'][$key] = $profiles; |
| return $profiles; |
| }*/ |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getImageRevisions($imageid, $incdeleted) |
| /// |
| /// \param $imageid - id of an image |
| /// \param $incdeleted - (optional, defaults to 0) 1 to include deleted images |
| /// |
| /// \return an array where each key is the id of the image revision and each |
| /// element has these values:\n |
| /// \b id - id of revision\n |
| /// \b revision - revision number\n |
| /// \b creatorid - user id of person that created the revision\n |
| /// \b creator - user@affiliation\n |
| /// \b datecreated - datetime of when revision was created\n |
| /// \b deleted - 1 if deleted, 0 if not\n |
| /// \b production - 1 if production revision, 0 if not\n |
| /// \b comments - comments about the revision\n |
| /// \b imagename - name for files related to revision |
| /// |
| /// \brief gets image revision data related to $imageid |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getImageRevisions($imageid, $incdeleted=0) { |
| $query = "SELECT i.id, " |
| . "i.revision, " |
| . "i.userid AS creatorid, " |
| . "CONCAT(u.unityid, '@', a.name) AS creator, " |
| . "i.datecreated, " |
| . "i.deleted, " |
| . "i.production, " |
| . "i.comments, " |
| . "i.imagename " |
| . "FROM imagerevision i, " |
| . "user u, " |
| . "affiliation a " |
| . "WHERE i.userid = u.id " |
| . "AND u.affiliationid = a.id " |
| . "AND i.imageid = $imageid"; |
| if(! $incdeleted) |
| $query .= " AND i.deleted = 0"; |
| $query .= " ORDER BY revision"; |
| $qh = doQuery($query, 101); |
| $return = array(); |
| while($row = mysqli_fetch_assoc($qh)) |
| $return[$row['id']] = $row; |
| return $return; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getImageNotes($imageid) |
| /// |
| /// \param $imageid - id of an image |
| /// \param $revisionid - image revision id |
| /// |
| /// \return an array with these keys:\n |
| /// \b description - description of image\n |
| /// \b usage - notes on using the image |
| /// |
| /// \brief gets data from the imageinfo table for $imageid and $revisionid |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getImageNotes($imageid) { |
| if(empty($imageid)) |
| $imageid = 0; |
| $query = "SELECT COALESCE(description, '') as description, " |
| . "COALESCE(`usage`, '') as `usage` " |
| . "FROM image " |
| . "WHERE id = $imageid"; |
| $qh = doQuery($query, 101); |
| if($row = mysqli_fetch_assoc($qh)) |
| return $row; |
| else |
| return array('description' => '', 'usage' => ''); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getImageConnectMethods($imageid, $revisionid, $nostatic=0) |
| /// |
| /// \param $imageid - id of an image |
| /// \param $revisionid - (optional, default=0) revision id of image |
| /// \param $nostatic - (optional, default=0) pass 1 to keep from using the |
| /// static variable defined in the function |
| /// |
| /// \return an array of connect methods enabled for specified image where the |
| /// key is the id of the connect method and the value is the description |
| /// |
| /// \brief builds an array of connect methods enabled for the image |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getImageConnectMethods($imageid, $revisionid=0, $nostatic=0) { |
| $key = getKey(array('getImageConnectMethods', (int)$imageid, (int)$revisionid)); |
| if(isset($_SESSION['usersessiondata'][$key])) |
| return $_SESSION['usersessiondata'][$key]; |
| if($revisionid == 0) |
| $revisionid = getProductionRevisionid($imageid, $nostatic); |
| if($revisionid == '') { |
| $_SESSION['usersessiondata'][$key] = array(); |
| return array(); |
| } |
| |
| static $allmethods = array(); |
| if($nostatic) |
| $allmethods = array(); |
| |
| if(empty($allmethods)) { |
| $query = "DROP TEMPORARY TABLE IF EXISTS imageconnectmethods"; |
| doQuery($query); |
| $query = "CREATE TEMPORARY TABLE imageconnectmethods ( " |
| . "imageid smallint(5) unsigned NOT NULL, " |
| . "imagerevisionid mediumint(8) unsigned NOT NULL, " |
| . "connectmethodid tinyint unsigned NOT NULL, " |
| . "description varchar(255) NOT NULL, " |
| . "disabled tinyint(1) unsigned NOT NULL, " |
| . "UNIQUE KEY (imagerevisionid, connectmethodid, disabled) " |
| . ") ENGINE=MEMORY"; |
| doQuery($query, 101); |
| |
| $qbase = "INSERT IGNORE INTO imageconnectmethods " |
| . "SELECT DISTINCT i.id, " |
| . "ir.id, " |
| . "c.id, " |
| . "c.description, " |
| . "cm.disabled " |
| . "FROM image i " |
| . "LEFT JOIN OS o ON (o.id = i.OSid) " |
| . "LEFT JOIN OStype ot ON (ot.name = o.type) " |
| . "LEFT JOIN imagerevision ir ON (ir.imageid = i.id) " |
| . "LEFT JOIN connectmethodmap cm ON (%s) " |
| . "LEFT JOIN connectmethod c ON (cm.connectmethodid = c.id) " |
| . "WHERE cm.autoprovisioned IS NULL " |
| . "HAVING c.id IS NOT NULL " |
| . "ORDER BY i.id, " |
| . "cm.disabled, " |
| . "c.description"; |
| $query = sprintf($qbase, "cm.OStypeid = ot.id"); |
| doQuery($query); |
| $query = sprintf($qbase, "cm.OSid = o.id"); |
| doQuery($query); |
| $query = sprintf($qbase, "cm.imagerevisionid = ir.id"); |
| doQuery($query); |
| |
| $query = "SELECT imageid, " |
| . "imagerevisionid, " |
| . "connectmethodid, " |
| . "description, " |
| . "disabled " |
| . "FROM imageconnectmethods " |
| . "ORDER BY imagerevisionid, " |
| . "connectmethodid, " |
| . "disabled"; |
| |
| $qh = doQuery($query); |
| while($row = mysqli_fetch_assoc($qh)) { |
| if($row['disabled'] && |
| isset($allmethods[$row['imageid']][$row['imagerevisionid']][$row['connectmethodid']])) |
| unset($allmethods[$row['imageid']][$row['imagerevisionid']][$row['connectmethodid']]); |
| else |
| $allmethods[$row['imageid']][$row['imagerevisionid']][$row['connectmethodid']] = $row['description']; |
| } |
| } |
| if(! isset($allmethods[$imageid][$revisionid])) { |
| $_SESSION['usersessiondata'][$key] = array(); |
| return array(); |
| } |
| $methods = $allmethods[$imageid][$revisionid]; |
| $_SESSION['usersessiondata'][$key] = $methods; |
| return $methods; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getImageConnectMethodTexts($imageid, $revisionid) |
| /// |
| /// \param $imageid - id of an image |
| /// \param $revisionid - (optional, default=0) revision id of image |
| /// |
| /// \return an array of connect method texts enabled for specified image where |
| /// the key is the id of the connect method and the value is the connecttext |
| /// |
| /// \brief builds an array of connect methods enabled for the image |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getImageConnectMethodTexts($imageid, $revisionid=0) { |
| global $locale; |
| $descfield = 'description'; |
| $textfield = 'connecttext'; |
| if(! preg_match('/^en/', $locale)) { |
| $query = "DESC connectmethod"; |
| $qh = doQuery($query, 101); |
| while($row = mysqli_fetch_assoc($qh)) { |
| if($row['Field'] == "description_$locale") |
| $descfield = "description_$locale"; |
| if($row['Field'] == "connecttext_$locale") |
| $textfield = "connecttext_$locale"; |
| } |
| } |
| $cmports = array(); |
| $query = "SELECT id, " |
| . "connectmethodid, " |
| . "port, " |
| . "protocol " |
| . "FROM connectmethodport"; |
| $qh = doQuery($query); |
| while($row = mysqli_fetch_assoc($qh)) { |
| $row['key'] = "#Port-{$row['protocol']}-{$row['port']}#"; |
| $cmports[$row['connectmethodid']][] = $row; |
| } |
| if($revisionid == 0) |
| $revisionid = getProductionRevisionid($imageid); |
| $query = "SELECT c.id, " |
| . "c.`$descfield` AS description, " |
| . "c.`$textfield` AS connecttext, " |
| . "cm.disabled " |
| . "FROM connectmethod c, " |
| . "connectmethodmap cm, " |
| . "image i " |
| . "LEFT JOIN OS o ON (o.id = i.OSid) " |
| . "LEFT JOIN OStype ot ON (ot.name = o.type) " |
| . "WHERE i.id = $imageid AND " |
| . "cm.connectmethodid = c.id AND " |
| . "cm.autoprovisioned IS NULL AND " |
| . "(cm.OStypeid = ot.id OR " |
| . "cm.OSid = o.id OR " |
| . "cm.imagerevisionid = $revisionid) " |
| . "ORDER BY cm.disabled, " |
| . "c.`$descfield`"; |
| $methods = array(); |
| $qh = doQuery($query, 101); |
| while($row = mysqli_fetch_assoc($qh)) { |
| if($row['disabled']) { |
| if(isset($methods[$row['id']])) |
| unset($methods[$row['id']]); |
| } |
| else |
| $methods[$row['id']] = array('description' => $row['description'], |
| 'connecttext' => $row['connecttext'], |
| 'ports' => $cmports[$row['id']]); |
| } |
| return $methods; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getImageTypes() |
| /// |
| /// \return array of image types where each key is the id and each value is the |
| /// name |
| /// |
| /// \brief builds an array of image types from the imagetype table |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getImageTypes() { |
| $query = "SELECT id, name FROM imagetype ORDER BY name"; |
| $qh = doQuery($query); |
| $data = array(); |
| while($row = mysqli_fetch_assoc($qh)) |
| $data[$row['id']] = $row['name']; |
| return $data; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn checkClearImageMeta($imagemetaid, $imageid, $ignorefield) |
| /// |
| /// \param $imagemetaid - id from imagemeta table |
| /// \param $imageid - id from image table |
| /// \param $ignorefield - (optional, default='') field to ignore being different |
| /// from default |
| /// |
| /// \return 0 if imagemeta entry was not deleted, 1 if it was |
| /// |
| /// \brief checks to see if all values of the imagemeta table are defaults, and |
| /// if so, deletes the entry and sets imagemetaid to NULL in image table |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function checkClearImageMeta($imagemetaid, $imageid, $ignorefield='') { |
| # get defaults for imagemeta table |
| $query = "DESC imagemeta"; |
| $qh = doQuery($query, 101); |
| $defaults = array(); |
| while($row = mysqli_fetch_assoc($qh)) |
| $defaults[$row['Field']] = $row['Default']; |
| # get imagemeta data |
| $query = "SELECT * FROM imagemeta WHERE id = $imagemetaid"; |
| $qh = doQuery($query, 101); |
| $row = mysqli_fetch_assoc($qh); |
| $alldefaults = 1; |
| if(mysqli_num_rows($qh) == 0) |
| # it is possible that the imagemeta record could have been deleted before |
| # this was submitted |
| return 1; |
| foreach($row as $field => $val) { |
| if($field == 'id' || $field == $ignorefield) |
| continue; |
| if($defaults[$field] != $val) { |
| $alldefaults = 0; |
| break; |
| } |
| } |
| // if all default values, delete imagemeta entry |
| if($alldefaults) { |
| $query = "DELETE FROM imagemeta WHERE id = $imagemetaid"; |
| doQuery($query, 101); |
| $query = "UPDATE image SET imagemetaid = NULL WHERE id = $imageid"; |
| doQuery($query, 101); |
| return 1; |
| } |
| return 0; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getProductionRevisionid($imageid, $nostatic=0) |
| /// |
| /// \param $imageid |
| /// \param $nostatic - (optional, default=0) pass 1 to keep from using the |
| /// static variable defined in the function |
| /// |
| /// \return the production revision id for $imageid |
| /// |
| /// \brief gets the production revision id for $imageid from the imagerevision |
| /// table |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getProductionRevisionid($imageid, $nostatic=0) { |
| static $alldata = array(); |
| if($nostatic) |
| $alldata = array(); |
| if(! empty($alldata)) |
| if(isset($alldata[$imageid])) |
| return $alldata[$imageid]; |
| else |
| return ''; |
| $query = "SELECT id, " |
| . "imageid " |
| . "FROM imagerevision " |
| . "WHERE production = 1"; |
| $qh = doQuery($query, 101); |
| while($row = mysqli_fetch_assoc($qh)) |
| $alldata[$row['imageid']] = $row['id']; |
| return $alldata[$imageid]; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn removeNoCheckout($images) |
| /// |
| /// \param $images - an array of images |
| /// |
| /// \return an array of images with the images that have forcheckout == 0 |
| /// removed |
| /// |
| /// \brief removes any images in $images that have forcheckout == 0 |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function removeNoCheckout($images) { |
| $allimages = getImages(); |
| foreach(array_keys($images) as $id) { |
| if(isset($allimages[$id]) && ! $allimages[$id]["forcheckout"]) |
| unset($images[$id]); |
| } |
| return $images; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getUserResources($userprivs, $resourceprivs, $onlygroups, |
| /// $includedeleted, $userid, $groupid) |
| /// |
| /// \param $userprivs - array of privileges to look for (such as |
| /// imageAdmin, imageCheckOut, etc) - this is an OR list; don't include 'block' |
| /// or 'cascade' |
| /// \param $resourceprivs - array of privileges to look for (such as |
| /// available, administer, manageGroup) - this is an OR list; don't include |
| /// 'block' or 'cascade' |
| /// \param $onlygroups - (optional) if 1, return the resource groups instead |
| /// of the resources |
| /// \param $includedeleted - (optional) included deleted resources if 1, |
| /// don't if 0 |
| /// \param $userid - (optional) id from the user table, if not given, use the |
| /// id of the currently logged in user |
| /// \param $groupid - (optional) id from the usergroup table, if not given, look |
| /// up by $userid; $userid must be 0 to look up by $groupid |
| /// |
| /// \return an array of 2 arrays where the first indexes are resource types |
| /// and each one's arrays are a list of resources available to the user where |
| /// the index of each item is the id and the value is the name of the |
| /// resource\n |
| /// if $onlygroups == 1:\n |
| /// {[computer] => {[groupid] => "groupname",\n |
| /// [groupid] => "groupname"},\n |
| /// [image] => {[groupid] => "groupname",\n |
| /// [groupid] => "groupname"},\n |
| /// ...}\n |
| /// if $onlygroups == 0:\n |
| /// {[computer] => {[compid] => "hostname",\n |
| /// [compid] => "hosename"},\n |
| /// [image] => {[imageid] => "prettyname",\n |
| /// [imageid] => "prettyname"},\n |
| /// ...} |
| /// |
| /// \brief builds a list of resources a user has access to and returns it |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getUserResources($userprivs, $resourceprivs=array("available"), |
| $onlygroups=0, $includedeleted=0, $userid=0, |
| $groupid=0) { |
| global $user; |
| if(isset($userprivs['managementnodeAdmin'])) |
| $userprivs[] = 'mgmtNodeAdmin'; |
| $key = getKey(array($userprivs, $resourceprivs, $onlygroups, $includedeleted, $userid, $groupid)); |
| if(isset($_SESSION['userresources'][$key])) |
| return $_SESSION['userresources'][$key]; |
| #FIXME this whole function could be much more efficient |
| $bygroup = 0; |
| if($userid == 0 && $groupid != 0) |
| $bygroup = 1; |
| if(! $userid) |
| $userid = $user["id"]; |
| |
| $nodeprivs = array(); |
| $startnodes = array(); |
| # build a list of nodes where user is granted $userprivs |
| $inlist = "'" . implode("','", $userprivs) . "'"; |
| $query = "SELECT u.privnodeid " |
| . "FROM userpriv u, " |
| . "userprivtype t " |
| . "WHERE u.userprivtypeid = t.id AND " |
| . "t.name IN ($inlist) AND "; |
| if(! $bygroup) { |
| $query .= "(u.userid = $userid OR " |
| . "u.usergroupid IN (SELECT usergroupid " |
| . "FROM usergroupmembers " |
| . "WHERE userid = $userid))"; |
| } |
| else |
| $query .= "u.usergroupid = $groupid"; |
| $qh = doQuery($query, 101); |
| while($row = mysqli_fetch_assoc($qh)) { |
| array_push($startnodes, $row["privnodeid"]); |
| } |
| # build data array from userprivtype and userpriv tables to reduce queries |
| # in addNodeUserResourcePrivs |
| $privdataset = array('user' => array(), 'usergroup' => array()); |
| $query = "SELECT t.name, " |
| . "u.privnodeid " |
| . "FROM userprivtype t, " |
| . "userpriv u " |
| . "WHERE u.userprivtypeid = t.id AND " |
| . "u.userid IS NOT NULL AND " |
| . "u.userid = $userid AND " |
| . "t.name IN ('block','cascade',$inlist)"; |
| $qh = doQuery($query); |
| while($row = mysqli_fetch_assoc($qh)) |
| $privdataset['user'][$row['privnodeid']][] = $row['name']; |
| $query = "SELECT t.name, " |
| . "u.usergroupid, " |
| . "u.privnodeid " |
| . "FROM userprivtype t, " |
| . "userpriv u " |
| . "WHERE u.userprivtypeid = t.id AND " |
| . "u.usergroupid IS NOT NULL AND "; |
| if($bygroup) |
| $query .= "u.usergroupid = $groupid AND "; |
| else |
| $query .= "u.usergroupid IN (SELECT usergroupid " |
| . "FROM usergroupmembers " |
| . "WHERE userid = $userid) AND "; |
| $query .= "t.name IN ('block','cascade',$inlist) " |
| . "ORDER BY u.privnodeid, " |
| . "u.usergroupid"; |
| $qh = doQuery($query, 101); |
| while($row = mysqli_fetch_assoc($qh)) |
| $privdataset['usergroup'][$row['privnodeid']][] = array('name' => $row['name'], 'groupid' => $row['usergroupid']); |
| |
| # travel up tree looking at privileges granted at parent nodes |
| foreach($startnodes as $nodeid) { |
| getUserResourcesUp($nodeprivs, $nodeid, $userid, $userprivs, $privdataset); |
| } |
| # travel down tree looking at privileges granted at child nodes if cascade privs at this node |
| foreach($startnodes as $nodeid) { |
| getUserResourcesDown($nodeprivs, $nodeid, $userid, $userprivs, $privdataset); |
| } |
| $nodeprivs = simplifyNodePrivs($nodeprivs, $userprivs); // call this before calling addUserResources |
| addUserResources($nodeprivs, $userid); |
| |
| # build a list of resource groups user has access to |
| $resourcegroups = array(); |
| $types = getTypes("resources"); |
| foreach($types["resources"] as $type) { |
| $resourcegroups[$type] = array(); |
| } |
| foreach(array_keys($nodeprivs) as $nodeid) { |
| // if user doesn't have privs at this node, no need to look |
| // at any resource groups here |
| $haspriv = 0; |
| foreach($userprivs as $priv) { |
| if($nodeprivs[$nodeid][$priv]) |
| $haspriv = 1; |
| } |
| if(! $haspriv) |
| continue; |
| # check to see if resource groups has any of $resourceprivs at this node |
| foreach(array_keys($nodeprivs[$nodeid]["resources"]) as $resourceid) { |
| foreach($resourceprivs as $priv) { |
| if(isset($nodeprivs[$nodeid]["resources"][$resourceid][$priv])) { |
| list($type, $name, $id) = explode('/', $resourceid); |
| $resourcegroups[$type][$id] = $name; |
| } |
| } |
| } |
| # check to see if resource groups has any of $resourceprivs cascaded to this node |
| foreach(array_keys($nodeprivs[$nodeid]["cascaderesources"]) as $resourceid) { |
| foreach($resourceprivs as $priv) { |
| if(isset($nodeprivs[$nodeid]["cascaderesources"][$resourceid][$priv]) && |
| ! (isset($nodeprivs[$nodeid]["resources"][$resourceid]["block"]))) { |
| list($type, $name, $id) = explode('/', $resourceid); |
| $resourcegroups[$type][$id] = $name; |
| } |
| } |
| } |
| } |
| |
| if(! $bygroup) |
| addOwnedResourceGroups($resourcegroups, $userid); |
| if($onlygroups) { |
| foreach(array_keys($resourcegroups) as $type) |
| uasort($resourcegroups[$type], "sortKeepIndex"); |
| $_SESSION['userresources'][$key] = $resourcegroups; |
| return $resourcegroups; |
| } |
| |
| $resources = array(); |
| foreach(array_keys($resourcegroups) as $type) { |
| $resources[$type] = |
| getResourcesFromGroups($resourcegroups[$type], $type, $includedeleted); |
| } |
| if(! $bygroup) |
| addOwnedResources($resources, $includedeleted, $userid); |
| $noimageid = getImageId('noimage'); |
| if(isset($resources['image'][$noimageid])) |
| unset($resources['image'][$noimageid]); |
| $_SESSION['userresources'][$key] = $resources; |
| return $resources; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getUserResourcesUp(&$nodeprivs, $nodeid, $userid, |
| /// $resourceprivs, $privdataset) |
| /// |
| /// \param $nodeprivs - node privilege array used in getUserResources |
| /// \param $nodeid - an id from the nodepriv table |
| /// \param $userid - an id from the user table |
| /// \param $resourceprivs - array of privileges to look for (such as |
| /// imageAdmin, imageCheckOut, etc); don't include 'block' or 'cascade' |
| /// \param $privdataset - array of data from userpriv table built in |
| /// getUserResources function |
| /// |
| /// \return modifies $nodeprivs, but doesn't return anything |
| /// |
| /// \brief adds resource privileges to $nodeprivs for the parents of $nodeid |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getUserResourcesUp(&$nodeprivs, $nodeid, $userid, |
| $resourceprivs, $privdataset) { |
| # build list of parent nodes |
| # starting at top, get images available at that node and user privs there and |
| # walk down to $nodeid |
| $nodelist = getParentNodes($nodeid); |
| array_unshift($nodelist, $nodeid); |
| $lastid = 0; |
| while(count($nodelist)) { |
| $id = array_pop($nodelist); |
| if(isset($nodeprivs[$id])) |
| continue; |
| |
| addNodeUserResourcePrivs($nodeprivs, $id, $lastid, $userid, $resourceprivs, $privdataset); |
| $lastid = $id; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getUserResourcesDown(&$nodeprivs, $nodeid, $userid, |
| /// $resourceprivs, $privdataset) |
| /// |
| /// \param $nodeprivs - node privilege array used in getUserResources |
| /// \param $nodeid - an id from the nodepriv table |
| /// \param $userid - an id from the user table |
| /// \param $resourceprivs - array of privileges to look for (such as |
| /// imageAdmin, imageCheckOut, etc); don't include 'block' or 'cascade' |
| /// \param $privdataset - array of data from userpriv table built in |
| /// getUserResources function |
| /// |
| /// \return modifies $nodeprivs, but doesn't return anything |
| /// |
| /// \brief recursively adds resource privileges to $nodeprivs for any children |
| /// of $nodeid |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getUserResourcesDown(&$nodeprivs, $nodeid, $userid, |
| $resourceprivs, $privdataset) { |
| # FIXME can we check for cascading and if not there, don't descend? |
| $children = getChildNodes($nodeid); |
| foreach($children as $id => $tmp) { |
| addNodeUserResourcePrivs($nodeprivs, $id, $nodeid, $userid, $resourceprivs, $privdataset); |
| getUserResourcesDown($nodeprivs, $id, $userid, $resourceprivs, $privdataset); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn addNodeUserResourcePrivs(&$nodeprivs, $id, $lastid, $userid, |
| /// $resourceprivs, $privdataset) |
| /// |
| /// \param $nodeprivs - node privilege array used in getUserResources |
| /// \param $id - an id from the nodepriv table |
| /// \param $lastid - $id's parent, 0 if at the root |
| /// \param $userid - an id from the user table |
| /// \param $resourceprivs - array of privileges to look for (such as |
| /// imageAdmin, imageCheckOut, etc); don't include 'block' or 'cascade' |
| /// \param $privdataset - array of data from userpriv table built in |
| /// getUserResources function |
| /// |
| /// \return modifies $nodeprivs, but doesn't return anything |
| /// |
| /// \brief for $id, gets privileges and cascaded privileges the user and any |
| /// groups the user is and adds them to $nodeprivs |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function addNodeUserResourcePrivs(&$nodeprivs, $id, $lastid, $userid, |
| $resourceprivs, $privdataset) { |
| $nodeprivs[$id]["user"] = array("cascade" => 0); |
| foreach($resourceprivs as $priv) { |
| $nodeprivs[$id]["user"][$priv] = 0; |
| } |
| |
| # add permissions for user |
| $block = 0; |
| if(isset($privdataset['user'][$id])) { |
| foreach($privdataset['user'][$id] as $name) { |
| if($name != 'block') |
| $nodeprivs[$id]['user'][$name] = 1; |
| else |
| $block = 1; |
| } |
| } |
| // if don't have anything in $resourceprivs, set cascade = 0 |
| if($nodeprivs[$id]["user"]["cascade"]) { |
| $noprivs = 1; |
| foreach($resourceprivs as $priv) { |
| if($nodeprivs[$id]["user"][$priv]) |
| $noprivs = 0; |
| } |
| if($noprivs) |
| $nodeprivs[$id]["user"]["cascade"] = 0; |
| } |
| // if not blocking at this node, and previous node had cascade |
| if($lastid && ! $block && $nodeprivs[$lastid]["user"]["cascade"]) { |
| # set cascade = 1 |
| $nodeprivs[$id]["user"]["cascade"] = 1; |
| # set each priv in $resourceprivs = 1 |
| foreach($resourceprivs as $priv) { |
| if($nodeprivs[$lastid]["user"][$priv]) |
| $nodeprivs[$id]["user"][$priv] = 1; |
| } |
| } |
| |
| # add permissions for user's groups |
| $basearray = array("cascade" => 0, |
| "block" => 0); |
| foreach($resourceprivs as $priv) |
| $basearray[$priv] = 0; |
| if(isset($privdataset['usergroup'][$id])) { |
| foreach($privdataset['usergroup'][$id] as $data) { |
| if(! isset($nodeprivs[$id][$data["groupid"]])) |
| $nodeprivs[$id][$data["groupid"]] = $basearray; |
| $nodeprivs[$id][$data["groupid"]][$data["name"]] = 1; |
| } |
| } |
| # add groups from $lastid if it is not 0 |
| if($lastid) { |
| foreach($nodeprivs[$lastid] as $groupid => $tmp) { |
| if(isset($nodeprivs[$id][$groupid])) |
| continue; |
| $nodeprivs[$id][$groupid] = $basearray; |
| } |
| } |
| foreach($nodeprivs[$id] as $groupid => $tmp) { |
| if(! is_numeric($groupid)) |
| continue; |
| // if don't have anything in $resourceprivs, set cascade = 0 |
| if($nodeprivs[$id][$groupid]["cascade"]) { |
| $noprivs = 1; |
| foreach($resourceprivs as $priv) { |
| if($nodeprivs[$id][$groupid][$priv]) |
| $noprivs = 0; |
| } |
| if($noprivs) |
| $nodeprivs[$id][$groupid]["cascade"] = 0; |
| } |
| // if group not blocking at this node, and group had cascade at previous |
| # node |
| if($lastid && ! $nodeprivs[$id][$groupid]["block"] && |
| isset($nodeprivs[$lastid][$groupid]) && |
| $nodeprivs[$lastid][$groupid]["cascade"]) { |
| # set cascade = 1 |
| $nodeprivs[$id][$groupid]["cascade"] = 1; |
| # set each priv in $resourceprivs = 1 |
| foreach($resourceprivs as $priv) { |
| if($nodeprivs[$lastid][$groupid][$priv]) |
| $nodeprivs[$id][$groupid][$priv] = 1; |
| } |
| } |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn simplifyNodePrivs($nodeprivs, $resourceprivs) |
| /// |
| /// \param $nodeprivs - node privilege array used in getUserResources |
| /// \param $resourceprivs - array of privileges to look for (such as |
| /// imageAdmin, imageCheckOut, etc); don't include 'block' or 'cascade' |
| /// |
| /// \return a simplified version of $nodeprivs |
| /// |
| /// \brief checks the user and group privileges for each node in $nodeprivs and |
| /// creates a new privilege array that just shows if the user has that |
| /// permission (either directly or from a group) |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function simplifyNodePrivs($nodeprivs, $resourceprivs) { |
| $return = array(); |
| $basearray = array(); |
| foreach($resourceprivs as $priv) { |
| $basearray[$priv] = 0; |
| } |
| foreach(array_keys($nodeprivs) as $nodeid) { |
| $return[$nodeid] = $basearray; |
| foreach(array_keys($nodeprivs[$nodeid]) as $key) { |
| foreach($resourceprivs as $priv) { |
| if($nodeprivs[$nodeid][$key][$priv]) |
| $return[$nodeid][$priv] = 1; |
| } |
| } |
| } |
| return $return; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn addUserResources(&$nodeprivs, $userid) |
| /// |
| /// \param $nodeprivs - node privilege array used in getUserResources |
| /// \param $userid - an id from the user table |
| /// |
| /// \return modifies $nodeprivs, but doesn't return anything |
| /// |
| /// \brief for each node in $nodeprivs, adds any resources that are available |
| /// to $nodeprivs |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function addUserResources(&$nodeprivs, $userid) { |
| require_once(".ht-inc/privileges.php"); |
| foreach(array_keys($nodeprivs) as $nodeid) { |
| $privs = getNodePrivileges($nodeid, "resources"); |
| $nodeprivs[$nodeid]["resources"] = $privs["resources"]; |
| $privs = getNodeCascadePrivileges($nodeid, "resources"); |
| $nodeprivs[$nodeid]["cascaderesources"] = $privs["resources"]; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn addOwnedResources(&$resources, $includedeleted, $userid) |
| /// |
| /// \param $resources - array of resources from getUserResources |
| /// \param $includedeleted - 1 to include deleted resources, 0 not to |
| /// \param $userid - id from user table |
| /// |
| /// \return modifies $resources, but doesn't return anything |
| /// |
| /// \brief adds resources that the user owns |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function addOwnedResources(&$resources, $includedeleted, $userid) { |
| foreach(array_keys($resources) as $type) { |
| # TODO make this get name field from classes |
| switch($type) { |
| case "image": |
| $field = 'prettyname'; |
| break; |
| case "computer": |
| case "managementnode": |
| $field = 'hostname'; |
| break; |
| default: |
| $field = 'name'; |
| break; |
| } |
| $query = "SELECT id, " |
| . "$field " |
| . "FROM $type " |
| . "WHERE ownerid = $userid"; |
| if(! $includedeleted && |
| ($type == "image" || $type == "computer" || $type == 'config')) |
| $query .= " AND deleted = 0"; |
| if(! $includedeleted && $type == 'managementnode') |
| $query .= " AND stateid != (SELECT id FROM state WHERE name = 'deleted') "; |
| $qh = doQuery($query, 101); |
| while($row = mysqli_fetch_assoc($qh)) { |
| if(! isset($resources[$type][$row["id"]])) |
| $resources[$type][$row["id"]] = $row[$field]; |
| } |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn addOwnedResourceGroups(&$resourcegroups, $userid) |
| /// |
| /// \param $resourcegroups - array of resources from getUserResources |
| /// \param $userid - id from user table |
| /// |
| /// \return modifies $resources, but doesn't return anything |
| /// |
| /// \brief adds resources that the user owns |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function addOwnedResourceGroups(&$resourcegroups, $userid) { |
| if(! $user = getUserInfo($userid, 1, 1)) |
| return; |
| $userid = $user["id"]; |
| $groupids = implode(',', array_keys($user["groups"])); |
| if(empty($groupids)) |
| $groupids = "''"; |
| $query = "SELECT g.id AS id, " |
| . "g.name AS name, " |
| . "t.name AS type " |
| . "FROM resourcegroup g, " |
| . "resourcetype t " |
| . "WHERE g.resourcetypeid = t.id AND " |
| . "g.ownerusergroupid IN ($groupids)"; |
| $qh = doQuery($query, 101); |
| while($row = mysqli_fetch_assoc($qh)) { |
| if(! isset($resourcegroups[$row["type"]][$row["id"]])) |
| $resourcegroups[$row["type"]][$row["id"]] = $row["name"]; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getResourcesFromGroups($groups, $type, $includedeleted) |
| /// |
| /// \param $groups - an array of group names |
| /// \param $type - the type of the groups (from resourcetype table) |
| /// \param $includedeleted - 1 to include deleted resources, 0 not to |
| /// |
| /// \return an array of resources where the index is the id of the resource and |
| /// the value is the name of the resource |
| /// |
| /// \brief builds an array of resources from $groups |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getResourcesFromGroups($groups, $type, $includedeleted) { |
| $return = array(); |
| switch($type) { |
| case "image": |
| $field = 'prettyname'; |
| break; |
| case "computer": |
| case "managementnode": |
| $field = 'hostname'; |
| break; |
| default: |
| $field = 'name'; |
| break; |
| } |
| |
| $groups = implode("','", $groups); |
| $inlist = "'$groups'"; |
| |
| $query = "SELECT DISTINCT(r.subid) AS id, " |
| . "t.$field AS name " |
| . "FROM $type t, " |
| . "resource r, " |
| . "resourcegroupmembers m, " |
| . "resourcegroup g, " |
| . "resourcetype rt " |
| . "WHERE r.subid = t.id AND " |
| . "r.id = m.resourceid AND " |
| . "m.resourcegroupid = g.id AND " |
| . "g.name IN ($inlist) AND " |
| . "g.resourcetypeid = rt.id AND " |
| . "rt.name = '$type' "; |
| if(! $includedeleted && |
| ($type == "image" || $type == "computer" || $type == 'config')) { |
| $query .= "AND deleted = 0 "; |
| } |
| if(! $includedeleted && $type == 'managementnode') |
| $query .= "AND t.stateid != (SELECT id FROM state WHERE name = 'deleted') "; |
| /*if($type == "image") |
| $query .= "AND test = 0 ";*/ |
| $query .= "ORDER BY t.$field"; |
| $qh = doQuery($query, 101); |
| while($row = mysqli_fetch_assoc($qh)) { |
| $return[$row["id"]] = $row["name"]; |
| } |
| return $return; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn updateUserOrGroupPrivs($name, $node, $adds, $removes, $mode) |
| /// |
| /// \param $name - loginid, user id, or user group id |
| /// \param $node - id of the node |
| /// \param $adds - array of privs (the name, not the id) to add |
| /// \param $removes - array of privs (the name, not the id) to remove |
| /// \param $mode - "user" or "group" |
| /// |
| /// \brief adds/removes $adds/$removes privs for $unityid to/from $node |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function updateUserOrGroupPrivs($name, $node, $adds, $removes, $mode) { |
| if(! (count($adds) || count($removes))) { |
| return; |
| } |
| if($mode == "user") { |
| $field = "userid"; |
| if(is_numeric($name)) |
| $id = $name; |
| else { |
| $id = getUserlistID($name); |
| if(! $id) |
| $id = addUser($name); |
| } |
| } |
| else { |
| $field = "usergroupid"; |
| $id = $name; |
| } |
| foreach($adds as $type) { |
| $typeid = getUserPrivTypeID($type); |
| $query = "INSERT IGNORE INTO userpriv (" |
| . "$field, " |
| . "privnodeid, " |
| . "userprivtypeid) " |
| . "VALUES (" |
| . "$id, " |
| . "$node, " |
| . "$typeid)"; |
| doQuery($query, 375); |
| } |
| foreach($removes as $type) { |
| $typeid = getUserPrivTypeID($type); |
| $query = "DELETE FROM userpriv " |
| . "WHERE $field = $id AND " |
| . "privnodeid = $node AND " |
| . "userprivtypeid = $typeid"; |
| doQuery($query, 376); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn updateResourcePrivs($group, $node, $adds, $removes) |
| /// |
| /// \param $group - id from resourcegroup table, or group name of the form |
| /// type/name |
| /// \param $node - id of the node |
| /// \param $adds - array of privs (the name, not the id) to add |
| /// \param $removes - array of privs (the name, not the id) to remove |
| /// |
| /// \brief adds/removes $adds/$removes privs for $name to/from $node |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function updateResourcePrivs($group, $node, $adds, $removes) { |
| if(! (count($adds) || count($removes))) { |
| return; |
| } |
| if(is_numeric($group)) |
| $groupid = $group; |
| else |
| $groupid = getResourceGroupID($group); |
| foreach($adds as $type) { |
| $type = vcl_mysql_escape_string($type); |
| $query = "INSERT IGNORE INTO resourcepriv (" |
| . "resourcegroupid, " |
| . "privnodeid, " |
| . "type) " |
| . "VALUES (" |
| . "$groupid, " |
| . "$node, " |
| . "'$type')"; |
| doQuery($query, 377); |
| } |
| foreach($removes as $type) { |
| $type = vcl_mysql_escape_string($type); |
| $query = "DELETE FROM resourcepriv " |
| . "WHERE resourcegroupid = $groupid AND " |
| . "privnodeid = $node AND " |
| . "type = '$type'"; |
| doQuery($query, 378); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getKey($data) |
| /// |
| /// \param $data - an array |
| /// |
| /// \return an md5 string that is unique for $data |
| /// |
| /// \brief generates an md5sum for $data |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getKey($data) { |
| return md5(serialize($data)); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn encryptData($data, $cryptkey, $algo, $option, $keylength) |
| /// |
| /// \param $data - a string |
| /// \param $cryptkey - key for encryption |
| /// \param $algo - algorithm to use for decryption |
| /// \param $option - an algorithm option (such as CBC) |
| /// \param $keylength - length of key being used |
| /// |
| /// \return an encrypted form of $data that has been base64 encoded or NULL if |
| /// encryption failed |
| /// |
| /// \brief encrypts $data with $algo and $option and base64 encodes it; IV is |
| /// generated and prepended to encrypted data before base64 encoding |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function encryptData($data, $cryptkey, $algo, $option, $keylength) { |
| global $ivsize; |
| if(! $data) |
| return false; |
| if(USE_PHPSECLIB) { |
| # only AES is currently supported |
| if($algo == 'AES') { |
| $mode = constant("CRYPT_AES_MODE_$option"); |
| $aes = new Crypt_AES($mode); |
| } |
| else |
| return false; |
| $aes->setKeyLength($keylength); |
| $aes->setKey($cryptkey); |
| $iv = crypt_random_string($ivsize); |
| $aes->setIV($iv); |
| $cryptdata = $aes->encrypt($data); |
| } |
| else { |
| $iv = openssl_random_pseudo_bytes($ivsize); |
| $mode = "{$algo}-{$keylength}-{$option}"; |
| $cryptdata = openssl_encrypt($data, $mode, $cryptkey, 1, $iv); |
| if($cryptdata === FALSE) |
| return NULL; |
| } |
| $cryptdata = $iv . $cryptdata; |
| return trim(base64_encode($cryptdata)); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn decryptData($data, $cryptkey, $algo, $option, $keylength) |
| /// |
| /// \param $data - a string |
| /// \param $cryptkey - key for decryption |
| /// \param $algo - algorithm to use for decryption |
| /// \param $option - an algorithm option (such as CBC) |
| /// \param $keylength - length of key being used |
| /// |
| /// \return decrypted form of $data or false on error |
| /// |
| /// \brief base64 decodes $data and decrypts it; $data is split into IV and |
| /// encrypted data after base64 decoding |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function decryptData($data, $cryptkey, $algo, $option, $keylength) { |
| global $ivsize; |
| if(! $data) |
| return false; |
| $cryptdata = base64_decode($data); |
| $iv = substr($cryptdata, 0, $ivsize); |
| if(strlen($iv) < $ivsize) |
| return false; |
| $cryptdata = substr($cryptdata, $ivsize); |
| if(strlen($cryptdata) == 0) |
| return false; |
| if(USE_PHPSECLIB) { |
| if($algo == 'AES') { |
| $mode = constant("CRYPT_AES_MODE_$option"); |
| $aes = new Crypt_AES($mode); |
| } |
| else |
| return false; |
| $aes->setKeyLength($keylength); |
| $aes->setKey($cryptkey); |
| $aes->setIV($iv); |
| $decryptdata = $aes->decrypt($cryptdata); |
| } |
| else { |
| $mode = "{$algo}-{$keylength}-{$option}"; |
| $decryptdata = openssl_decrypt($cryptdata, $mode, $cryptkey, 1, $iv); |
| if($decryptdata === FALSE) |
| return false; |
| } |
| return trim($decryptdata); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn encryptDBdata($data, $secretid) |
| /// |
| /// \param $data - a string |
| /// \param $secretid - secretid from cryptsecret table |
| /// |
| /// \return base64-encoded, encrypted form of $data or NULL on error |
| /// |
| /// \brief encrypts $data with secret key from cryptsecret table |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function encryptDBdata($data, $secretid) { |
| # fetch cryptsecret from db |
| $cryptkeyid = getCryptKeyID(); |
| if($cryptkeyid == NULL) |
| return NULL; |
| $query = "SELECT cryptsecret, " |
| . "algorithm, " |
| . "algorithmoption, " |
| . "keylength " |
| . "FROM cryptsecret " |
| . "WHERE cryptkeyid = $cryptkeyid AND " |
| . "secretid = $secretid"; |
| $qh = doQuery($query); |
| if(! ($row = mysqli_fetch_assoc($qh))) |
| return NULL; |
| $secret = decryptSecretKey($row['cryptsecret']); |
| if($secret === NULL) |
| return NULL; |
| $edata = encryptData($data, $secret, $row['algorithm'], $row['algorithmoption'], $row['keylength']); |
| return $edata; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn encryptSecretKey($secret, $cryptkey) |
| /// |
| /// \param $secret - secret key to encrypt |
| /// \param $cryptkey - id from cryptkey table for public key to use or public |
| /// key itself |
| /// |
| /// \return encrypted data; returns NULL on error |
| /// |
| /// \brief encrypts $secret with key for $cryptkeyid |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function encryptSecretKey($secret, $cryptkey) { |
| if(is_numeric($cryptkey)) { |
| $query = "SELECT pubkey, " |
| . "algorithmoption " |
| . "FROM cryptkey " |
| . "WHERE id = $cryptkey"; |
| $qh = doQuery($query); |
| if(! ($row = mysqli_fetch_assoc($qh))) |
| return NULL; |
| $cryptkey = $row['pubkey']; |
| if($row['algorithmoption'] == 'OAEP' || 1) # OAEP only currently supported option |
| $padding = constant('OPENSSL_PKCS1_OAEP_PADDING'); |
| } |
| else |
| $padding = constant('OPENSSL_PKCS1_OAEP_PADDING'); |
| $savehdlr = set_error_handler(function() {}); |
| if(@openssl_public_encrypt($secret, $encdata, $cryptkey, $padding)) { |
| set_error_handler($savehdlr); |
| $b64data = base64_encode($encdata); |
| return $b64data; |
| } |
| set_error_handler($savehdlr); |
| return NULL; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn decryptSecretKey($encsecret) |
| /// |
| /// \param $encsecret - encrypted secret |
| /// |
| /// \return string that is decrypted form of $encsecret or NULL on error |
| /// |
| /// \brief decrypts $encsecret using web server's secret key |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function decryptSecretKey($encsecret) { |
| global $pemkey; |
| $cryptsecret = base64_decode($encsecret); |
| # read private key from file |
| $reg = "|" . SCRIPT . "$|"; |
| $file = preg_replace($reg, '', $_SERVER['SCRIPT_FILENAME']); |
| $file .= "/.ht-inc/cryptkey/private.pem"; |
| $prikey = openssl_pkey_get_private("file://$file", $pemkey); |
| # decrypt secret using private key |
| $savehdlr = set_error_handler(function() {}); |
| if(ASYMOPT == 'OAEP') |
| $padding = constant('OPENSSL_PKCS1_OAEP_PADDING'); |
| # OAEP currently only supported padding option |
| if(! openssl_private_decrypt($cryptsecret, $secret, $prikey, $padding)) { |
| set_error_handler($savehdlr); |
| return NULL; |
| } |
| return $secret; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getSecretKeyID($table, $field, $recordid) |
| /// |
| /// \param $table - name of a database table having a secret |
| /// \param $field - name of field in table referencing secretid |
| /// \param $recordid - id for record in table |
| /// |
| /// \return id corresponding to a cryptsecret.secretid value; if value not found |
| /// and function failed to generate a new secret ID, NULL is returned |
| /// |
| /// \brief gets the id for a cryptsecret.secretid entry from a table containing |
| /// an encrypted value; if no entry is found, a new secret is generated and |
| /// saved in cryptsecret |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getSecretKeyID($table, $field, $recordid) { |
| $query = "SELECT $field FROM $table WHERE id = $recordid"; |
| $qh = doQuery($query); |
| if(($row = mysqli_fetch_row($qh)) && $row[0] != 0) |
| return $row[0]; |
| |
| # generate secret key |
| if(USE_PHPSECLIB) |
| $key = crypt_random_string(32); |
| else { |
| $key = openssl_random_pseudo_bytes(32); |
| if($key === FALSE) |
| return NULL; |
| } |
| # encrypt with my public key |
| $cryptkeyid = getCryptKeyID(); |
| if($cryptkeyid === NULL) |
| return NULL; |
| $encdata = encryptSecretKey($key, $cryptkeyid); |
| if($encdata === NULL) |
| return NULL; |
| # write to cryptsecret |
| $query = "INSERT INTO cryptsecret " |
| . "(cryptkeyid, " |
| . "secretid, " |
| . "cryptsecret, " |
| . "algorithm, " |
| . "algorithmoption, " |
| . "keylength) " |
| . "SELECT $cryptkeyid, " |
| . "COALESCE(MAX(secretid), 0) + 1, " |
| . "'$encdata', " |
| . "'" . SYMALGO . "', " |
| . "'" . SYMOPT . "', " |
| . SYMLEN . " " |
| . "FROM cryptsecret"; |
| doQuery($query); |
| $id = dbLastInsertID(); |
| if($id < 1) |
| return NULL; |
| $query = "SELECT secretid FROM cryptsecret WHERE id = $id"; |
| $qh = doQuery($query); |
| if(! ($row = mysqli_fetch_assoc($qh))) |
| return NULL; |
| # encrypt with all other public keys and write to cryptsecret |
| encryptWebSecretKeys($key, $row['secretid'], $cryptkeyid); |
| return $row['secretid']; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn deleteSecretKeys($secretid) |
| /// |
| /// \param $secretid - secretid value corresponding to cryptsecret.secretid |
| /// |
| /// \brief deletes all entries in cryptsecret for $secretid |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function deleteSecretKeys($secretid) { |
| $query = "DELETE FROM cryptsecret WHERE secretid = $secretid"; |
| doQuery($query); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| /// |
| /// \fn getCryptKeyID() |
| /// |
| /// \return id from cryptkey table corresponding to this web server's file |
| /// space; returns NULL on error |
| /// |
| /// \brief reads id from cryptkeyid file in web server's file space; if not |
| /// found, calls checkCryptkey to generate a key and then returns it |
| /// |
| //////////////////////////////////////////////////////////////////////////////// |
| function getCryptKeyID() { |
| $reg = "|" . SCRIPT . "$|"; |
| $filebase = preg_replace($reg, '', $_SERVER['SCRIPT_FILENAME']); |
| $filebase = preg_replace('|/shibauth|', '', $filebase); |
| $filebase .= "/.ht-inc/cryptkey"; |
| $idfile = "$filebase/cryptkeyid"; |
| |
| static $create = 1; # set flag so that recursion only goes one level deep |
| |
| if(! is_file($idfile)) { |
| if($create) { |
| $create = 0; # set to 0, subsequent calls to function should never need to create a key |
| checkCryptkey(); |
| return getCryptKeyID(); |
| |