function checkCmd($httpReq, $cmd) { $cmd = getCmd($httpReq); if ($cmd !== $cmd) { WrongRequestException::throwException(8030, "Only the command >{$cmd}< is accepted", 'got: ' . $reqdecoded['cmd']); } }
function handleTallyReq($voterReq) { switch ($voterReq['cmd']) { // TODO throw an error if cmd is not set case 'getWinners': $winners = array(); foreach ($this->elConfig['questions'] as $question) { $completeElectionId = makeCompleteElectionId($this->elConfig['electionId'], $question['questionID']); $pseudoVoterReq = array('electionId' => $completeElectionId); $allvotesTmp = parent::getAllVotesEvent($pseudoVoterReq); $allVotes = $allvotesTmp['data']['allVotes']; $winners[$question['questionID']] = $this->GetResultMain($allVotes, $question['tallyData'], $question['options']); } $result = array('cmd' => 'showWinners', 'data' => $winners); return $result; break; case 'getStatistic': // get the array of questions from the requested questionId or return all questions if (isset($voterReq['questionID'])) { // return the result statistics for the requested question only if (is_array($voterReq['questionID'])) { $questionIds = $voterReq['questionID']; } else { $questionIds[] = $voterReq['questionID']; } // just a single question requested foreach ($questionIds as $questionId) { if (!(is_int($questionId) || is_string($questionId))) { WrongRequestException::throwException(85657, 'The questionID must be an int, a string or an array of integers resp. strings', print_r($voterReq, true)); } $key = find_in_subarray($this->elConfig['questions'], 'questionID', $questionId); if ($key === false) { WrongRequestException::throwException(85658, 'The questionID you requested does not exist', print_r($questionId, true)); } $questions[] = $this->elConfig['questions'][$key]; } } else { $questions = $this->elConfig['questions']; } // return the result statistics for all questions // generate statistics $resultStat = array(); foreach ($questions as $question) { $completeElectionId = makeCompleteElectionId($this->elConfig['electionId'], $question['questionID']); $pseudoVoterReq = array('electionId' => $completeElectionId); $allvotesTmp = parent::getAllVotesEvent($pseudoVoterReq); $allVotes = $allvotesTmp['data']['allVotes']; $allOptionIDs = $this->getAllOptionIDs($question['options']); $resultStat[$question['questionID']] = $this->GetResultStat($allVotes, $allOptionIDs, $question['tallyData']['scheme']); } $result = array('cmd' => 'showStatistic', 'data' => $resultStat); return $result; break; default: return parent::handleTallyReq($voterReq); break; } }
function newElection($electionId, $checkTokenUrl) { $exists = $this->load(array('electionId' => $electionId), 'xt_config', 'electionId'); if (isset($exists[0])) { WrongRequestException::throwException(3000, 'election ID already used', $electionId); } $saved = $this->save(array('electionId' => $electionId, 'checkTokenUrl' => $checkTokenUrl), 'xt_config'); if (!$saved) { InternalServerError::throwException(3001, 'internal server error; election not saved', $electionId); } return $saved; }
function newElection($electionId, $secret) { $exists = $this->load(array('electionId' => $electionId), 'sp_credentials', 'electionId'); if (isset($exists[0])) { WrongRequestException::throwException(3000, 'election ID already used', $electionId); } $saved = $this->save(array('electionId' => $electionId, 'sp_credentials' => $secret), 'sp_credentials'); if (!$saved) { InternalServerError::throwException(3001, 'internal server error; election not saved', $electionId); } return $saved; }
/** * * @param unknown $electionId * @param unknown $req : $$req['sharedPassw'] */ function handleNewElectionReq($electionId, $req) { $authConfig = parent::handleNewElectionReq($electionId, $req); if (isset($electionId) && isset($req['sharedPassw']) && gettype($electionId) == 'string' && gettype($req['sharedPassw']) == 'string') { $ok = $this->newElection($electionId, $req['sharedPassw']); if (!$ok) { InternalServerError::throwException(2710, 'Internal server error: error saving election auth information', "request received: \n" . print_r($req, true)); } return $authConfig; } else { WrongRequestException::throwException(2000, 'ElectionId or shared password not set or of wrong type', "request received: \n" . print_r($req, true)); } }
/** * * @param unknown $electionId * @param unknown $req : $req['externalToken'] */ function handleNewElectionReq($electionId, $req) { $ret = parent::handleNewElectionReq($electionId, $req); if (!isset($electionId)) { WrongRequestException::throwException(2340, 'ElectionId not set', "request received: \n" . print_r($req, true)); } if (gettype($electionId) != 'string') { WrongRequestException::throwException(2345, 'ElectionId is not of type /string/', "request received: \n" . print_r($req, true)); } if (isset($req['configId']) && gettype($req['configId']) == 'string') { $ret['configId'] = $req['configId']; return $ret; } else { if (isset($req['checkTokenUrl']) && gettype($req['checkTokenUrl']) == 'string') { $ok = $this->newElection($electionId, $req['checkTokenUrl']); if (!$ok) { InternalServerError::throwException(2710, 'Internal server error: error saving election auth information', "request received: \n" . print_r($req, true)); } return $ret; } else { WrongRequestException::throwException(2350, 'neither chekTokenUrl nor configId is set', "request received: \n" . print_r($req, true)); } } }
/** * This class handles the XmlHttp-messages between the counting server and the voter * getAllVotes * ErrorNo start at 7200 */ require_once 'connectioncheck.php'; // answers if &connectioncheck is part of the URL and exists require_once 'exception.php'; require_once 'loadmodules.php'; require_once 'getcmd.php'; header('Access-Control-Allow-Origin: *', false); // this allows any cross-site scripting header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept"); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); if (isset($HTTP_RAW_POST_DATA)) { $electionIdPlace = function ($a) { if (!isset($a['electionId'])) { WrongRequestException::throwException(7200, 'Election id missing in client request', $httpRawPostData); } return $a['electionId']; }; try { $data = getData($HTTP_RAW_POST_DATA); // throws an error if this command is not there $el = loadElectionModules($HTTP_RAW_POST_DATA, $electionIdPlace); $result = $el->tally->handleTallyReq($data); } catch (ElectionServerException $e) { $result = $e->makeServerAnswer(); } print json_encode($result); }
function handlePermissionReq($req) { try { $voterReq = json_decode($req, true); //, $options=JSON_BIGINT_AS_STRING); // decode $req if ($voterReq == null) { // json could not be decoded WrongRequestException::throwException(100, 'Error while decoding JSON request', $req); } $result = array(); // print "voterReq\n"; // print_r($voterReq); // $this.verifysyntax($result); // $this.verifyuser($voterReq['voterid'], $voterReq['secret']); // get state the user is in for the selected election switch ($voterReq['cmd']) { case 'pickBallots': $result = $this->pickBallotsEvent($voterReq); break; case 'signBallots': $result = $this->signBallotsEvent($voterReq); break; case 'getAllPermissedBallots': $result = $this->getAllPermissedBallots($voterReq); break; default: WrongRequestException::throwException(101, 'Error unknown command', $req); break; } } catch (ElectionServerException $e) { $result = array('cmd' => 'error', 'errorTxt' => $e->errortxt, 'errorNo' => $e->errorno); } $ret = json_encode($result); return $ret; }
} $showResult = ''; if (isset($_GET['showresult'])) { $showResult = '&showresult'; } header('Location: ' . $webclientUrlbase . '/index.html?confighash=' . $hash . $token . $showResult, true, 301); die; } } if (isset($hash)) { // TODO verify sigs try { $db = new DbElections($dbInfos); $result = $db->loadElectionConfigFromHash($hash); if (count($result) == 0) { $result = WrongRequestException::throwException(4000, 'Election not found', $hash); } $result['cmd'] = 'loadElectionConfig'; } catch (ElectionServerException $e) { $result = $e->makeServerAnswer(); } /* $result = array( 'electionId' => $electionId, 'auth' => 'userPassw', 'blinding' => 'blindedVoter', 'ballot' => array('opt1' => 'Europäische Zentralbank soll künftig direkt Kredit an Staaten geben', 'opt2' => 'Europäische Zentralbank soll weiterhin keine Kredite an Staaten geben dürfen'), 'tally' => 'publishOnly' ); */ // TODO sign the config
static function laodAuthModule($name) { global $dbInfos; switch ($name) { case 'userPassw': $auth = new UserPasswAuth($dbInfos); break; case 'sharedPassw': $auth = new SharedPasswAuth($dbInfos); break; case 'oAuth2': $auth = new OAuth2($dbInfos); break; case 'sharedAuth': $auth = new SharedAuth($dbInfos); break; case 'externalToken': $auth = new ExternalTokenAuth($dbInfos); break; default: WrongRequestException::throwException(7030, 'auth module not supported (supported: userPassw, sharedPassw, oAuth2, sharedAuth)', "auth module requested: " . $elconfig['auth']); break; } return $auth; }
/** * * @param unknown $electionId * @param unknown $req : $req['listId'] * @return auth config data to be saved with the election config because the client need to know it for obtaining voting permission */ function handleNewElectionReq($electionId, $req) { $authconfig = parent::handleNewElectionReq($electionId, $req); if (!isset($req["serverId"]) || !is_string($req['serverId'])) { WrongRequestException::throwException(12001, 'Missing /listId/ in election config', "request received: \n" . print_r($req, true)); } if (!isset($req["listId"]) || !is_string($req['listId'])) { WrongRequestException::throwException(12001, 'Missing /listId/ in election config', "request received: \n" . print_r($req, true)); } if (!isset($req["nested_groups"]) || !is_array($req['nested_groups'])) { WrongRequestException::throwException(12002, 'Missing /nested_groups/ in election config', "request received: \n" . print_r($req, true)); } if (!isset($req["verified"]) || !is_bool($req['verified'])) { WrongRequestException::throwException(12003, 'Missing /verified/ in election config', "request received: \n" . print_r($req, true)); } if (!isset($req["eligible"]) || !is_bool($req['eligible'])) { WrongRequestException::throwException(12004, 'Missing /eligible/ in election config', "request received: \n" . print_r($req, true)); } if (!isset($electionId) || !is_string($electionId)) { WrongRequestException::throwException(12005, '/ElectionId/ not set or of wrong type', "request received: \n" . print_r($req, true)); } $authconfig['serverId'] = $req['serverId']; $authconfig['listId'] = $req["listId"]; $authconfig['nested_groups'] = $req["nested_groups"]; $authconfig['verified'] = $req["verified"]; $authconfig['eligible'] = $req["eligible"]; // TODO don't save any data until everything is completed (no error occured in the further steps) // TODO don't save any public config data in separate data base - just use the config $ok = $this->newElection($electionId, $req['serverId'], $authconfig); // TODO think about taking serverId always from election-config if (!$ok) { InternalServerError::throwException(12020, 'Internal server error: error saving election auth information', "request received: \n" . print_r($req, true)); } return $authconfig; }
/** * * @param unknown $text string * @param unknown $unblindf string: hex encoded bigInt * @param unknown $blindedHash string: hex encoded bigInt */ function verifyBlindedHash($text, $unblindf, $blindedHash) { $hashByMe = hash('sha256', $text); $hashByMeBigInt = new Math_BigInteger($hashByMe, 16); $blindedHashBigInt = new Math_BigInteger($blindedHash, 16); $signedblindedHash = $this->myPrivateKey['privRsa']->_rsasp1($blindedHashBigInt); $unblindf = new Math_BigInteger($unblindf, 16); $unblindedSignedHash = $this->myPrivateKey['privRsa']->rsaUnblind($signedblindedHash, $unblindf); $verifyHash = $this->myPrivateKey['pubRsa']->_rsasp1($unblindedSignedHash); $hashOk = $hashByMeBigInt->equals($verifyHash); if ($hashOk !== true) { WrongRequestException::throwException(1002, "Error: blinded hash verification failed", "expected hash: {$hashByMe}, got unblinded hash: {$verifyHash}, blinded Hash {$blindedHash}, unblinding factor {$unblindf}"); } return $hashOk; }
global $dbInfos; $authm = new SharedAuth($dbInfos); $authTmp = $authm->handleNewElectionReq($electionId, $electionconfig); $newconfig['authConfig'] = $authTmp['authConfig']; $newconfig["auth"] = $authTmp['auth']; // blinder $newconfig['blinding'] = 'blindedVoter'; global $numVerifyBallots, $numSignBallots, $pServerKeys, $serverkey, $numAllBallots, $numPSigsRequiered; $blinder = new BlindedVoter($electionId, $numVerifyBallots, $numSignBallots, $pServerKeys, $serverkey, $numAllBallots, $numPSigsRequiered, $dbInfos, $authm); // tally $tallym = LoadModules::loadTally($electionconfig['tally'], $blinder); $newconfig['tally'] = constant(get_class($tallym) . '::name'); // $newconfig['tallyData'] = $tallym->handleNewElectionReq($electionId, $authm, $blinder, $electionconfig['tallyData']); // $this->subTally->handleNewElectionReq($req['subTallyData']); if (!isset($electionconfig["questions"]) || !is_array($electionconfig["questions"])) { WrongRequestException::throwException(2146, 'Request must contain an array of questions', print_r($electionconfig, true)); } foreach ($electionconfig['questions'] as $i => $question) { $completeElectionId = json_encode(array('mainElectionId' => $electionId, 'subElectionId' => $question['questionID'])); // $subAuthConf = $authm->newSubElection($completeElectionId); $subBlinderConf = $blinder->handleNewElectionReq($completeElectionId); $subTallyConf = $tallym->handleNewElectionReq($completeElectionId, $authm, $blinder, $question); $ret[$i] = array('questionID' => $question['questionID'], 'questionWording' => $question['questionWording'], 'blinderData' => $subBlinderConf, 'tallyData' => $subTallyConf); if (isset($question['options'])) { $ret[$i]['options'] = $question['options']; } } $newconfig['questions'] = $ret; $hash = $db->saveElectionConfig($electionId, $newconfig); //e.g. http://www.webhod.ra/vvvote2/backend/getelectionconfig.php?confighash= $configurl = "{$configUrlBase}/getelectionconfig.php?confighash={$hash}";
function handleNewElectionReq($electionId, $req) { $authconfig = array(); $now = time(); if (isset($req["RegistrationStartDate"])) { $regStartDate = strtotime($req["RegistrationStartDate"]); if ($regStartDate === false) { WrongRequestException::throwException(12010, '/RegistrationStartDate/ is set but could not be paresed', "request received: \n" . print_r($req, true)); } if (strtotime('+11 years', $now) < $regStartDate || strtotime('-11 years', $now) > $regStartDate) { WrongRequestException::throwException(12011, '/RegistrationStartDate/ is more than 10 years away from now which is not supported', "request received: \n" . print_r($req, true)); } // check if date is plausible $authconfig['RegistrationStartDate'] = date('c', $regStartDate); } if (isset($req["RegistrationEndDate"])) { $regEndDate = strtotime($req["RegistrationEndDate"]); if ($regEndDate === false) { WrongRequestException::throwException(12012, '/RegistrationEndDate/ is set but could not be paresed', "request received: \n" . print_r($req, true)); } if (strtotime('+11 years', $now) < $regEndDate || strtotime('-11 years', $now) > $regEndDate) { WrongRequestException::throwException(12013, '/RegistrationEndDate/ is more than 10 years away from now which is not supported', "request received: \n" . print_r($req, true)); } // check if date is plausible $authconfig['RegistrationEndDate'] = date('c', $regEndDate); } if (isset($req["VotingStart"])) { $regEndDate = strtotime($req["VotingStart"]); if ($regEndDate === false) { WrongRequestException::throwException(12014, '/VotingStart/ is set but could not be paresed', "request received: \n" . print_r($req, true)); } if (strtotime('+11 years', $now) < $regEndDate || strtotime('-11 years', $now) > $regEndDate) { WrongRequestException::throwException(12015, '/VotingStart/ is more than 10 years away from now which is not supported', "request received: \n" . print_r($req, true)); } // check if date is plausible $authconfig['VotingStart'] = date('c', $regEndDate); } if (isset($req["VotingEnd"])) { $regEndDate = strtotime($req["VotingEnd"]); if ($regEndDate === false) { WrongRequestException::throwException(12016, '/VotingEnd/ is set but could not be paresed', "request received: \n" . print_r($req, true)); } if (strtotime('+11 years', $now) < $regEndDate || strtotime('-11 years', $now) > $regEndDate) { WrongRequestException::throwException(12017, '/VotingEnd/ is more than 10 years away from now which is not supported', "request received: \n" . print_r($req, true)); } // check if date is plausible $authconfig['VotingEnd'] = date('c', $regEndDate); } if (isset($req["DelayUntil"])) { if (!is_array($req["DelayUntil"])) { WrongRequestException::throwException(12021, 'if DelayUntil is set, it must be an array', print_r($req['DelayUntil'], true)); } foreach ($req["DelayUntil"] as $i => $datumStr) { $datum = strtotime($datumStr); if ($datum === false) { WrongRequestException::throwException(12022, "DelayUntil date number {$i} could not be paresed", "request received: \n" . print_r($req['DelayUntil'], true)); } if (strtotime('+11 years', $now) < $datum || strtotime('-11 years', $now) > $datum) { WrongRequestException::throwException(12023, "DelayUntil date number {$i} is more than 10 years away from now which is not supported", "request received: \n" . print_r($req['DelayUntil'], true)); } // check if date is plausible } $authconfig['DelayUntil'] = $req["DelayUntil"]; } return $authconfig; }
function handleTallyReq($voterReq) { $result = array(); // print "voterReq\n"; // print_r($voterReq); // $this.verifysyntax($result); switch ($voterReq['cmd']) { case 'storeVote': $result = $this->storeVoteEvent($voterReq); break; case 'getAllVotes': $result = $this->getAllVotesEvent($voterReq); break; default: WrongRequestException::throwException(1101, 'Error unknown tally command (accepting "storeVote" and "getAllVotes" only)', $voterReq); break; } return $result; }
// this allows any cross-site scripting (needed for chrome) header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); // header("Access-Control-Allow-Origin: http://www.webhod.ra", false); // header("Access-Control-Allow-Origin: http://www2.webhod.ra", false); // echo ":: data received via GET ::\n\n"; // print_r($_GET); // echo "\n\n:: Data received via POST ::\n\n"; // print_r($_POST); // echo "\n\n:: Data received as \"raw\" (text/plain encoding) ::\n\n"; /** * error no start at 6000 */ if (isset($HTTP_RAW_POST_DATA)) { $electionIdPlace = function ($a) { if (!isset($a['electionId'])) { WrongRequestException::throwException(7200, 'Election id missing in client request', $GLOBALS['HTTP_RAW_POST_DATA']); } return $a['electionId']; }; try { $el = loadElectionModules($HTTP_RAW_POST_DATA, $electionIdPlace); $result = $el->handlePermissionReq($HTTP_RAW_POST_DATA); // print "\r\n"; } catch (ElectionServerException $e) { $result = json_encode($e->makeServerAnswer()); } // TODO catch all exceptions print "{$result}"; } // echo "\n\n:: Files received ::\n\n"; // print_r($_FILES);
/** * $req: { * 'auth': 'oAuth2' || 'sharedPassw' * 'authData': depends on auth * } */ function handleNewElectionReq($electionId, $req) { if (!isset($req["auth"]) || !is_string($req['auth'])) { WrongRequestException::throwException(30001, 'Missing /auth/ in election config', "request received: \n" . print_r($req, true)); } $subAuth = $req["auth"]; $authConfig = $this->newElection($electionId, $subAuth, $req['authData']); return $authConfig; }