/** * generate new vouchers * @param string $provider auth provider * @return array generated vouchers */ public function generateVouchersAction($provider) { $response = array("status" => "error"); if ($this->request->isPost()) { $authFactory = new AuthenticationFactory(); $auth = $authFactory->get($provider); if ($auth != null && method_exists($auth, 'generateVouchers')) { $count = $this->request->getPost('count', 'int', 0); $validity = $this->request->getPost('validity', 'int', 0); $vouchergroup = $this->request->getPost('vouchergroup', 'striptags', '---'); if ($count > 0 && $count <= 10000 && $validity > 0) { $response['status'] = 'created'; return $auth->generateVouchers($vouchergroup, $count, $validity); } } } return $response; }
/** * logon client to zone, must use post type of request * @param int|string zone id number * @return array */ public function logonAction($zoneid = 0) { $clientIp = $this->getClientIp(); if ($this->request->isOptions()) { // return empty result on CORS preflight return array(); } elseif ($this->request->isPost()) { // close session for long running action $this->sessionClose(); // init variables for authserver object and name $authServer = null; $authServerName = ""; // get username from post $userName = $this->request->getPost("user", "striptags", null); // search zone info, to retrieve list of authenticators $mdlCP = new CaptivePortal(); $cpZone = $mdlCP->getByZoneID($zoneid); if ($cpZone != null) { if (trim((string) $cpZone->authservers) != "") { // authenticate user $isAuthenticated = false; $authFactory = new AuthenticationFactory(); foreach (explode(',', (string) $cpZone->authservers) as $authServerName) { $authServer = $authFactory->get(trim($authServerName)); // try this auth method $isAuthenticated = $authServer->authenticate($userName, $this->request->getPost("password", "string")); if ($isAuthenticated) { // stop trying, when authenticated break; } } } else { // no authentication needed, set username to "anonymous@ip" $userName = "******" . $clientIp; $isAuthenticated = true; } if ($isAuthenticated) { // when authenticated, we have $authServer available to request additional data if needed $clientSession = $this->clientSession((string) $cpZone->zoneid); if ($clientSession['clientState'] == 'AUTHORIZED') { // already authorized, return current session return $clientSession; } else { // allow client to this captiveportal zone $backend = new Backend(); $CPsession = $backend->configdpRun("captiveportal allow", array((string) $cpZone->zoneid, $userName, $clientIp, $authServerName, 'json')); $CPsession = json_decode($CPsession, true); // push session restrictions, if they apply if ($CPsession != null && array_key_exists('sessionId', $CPsession) && $authServer != null) { $authProps = $authServer->getLastAuthProperties(); // when adding more client/session restrictions, extend next code // (currently only time is restricted) if (array_key_exists('session_timeout', $authProps)) { $backend->configdpRun("captiveportal set session_restrictions", array((string) $cpZone->zoneid, $CPsession['sessionId'], $authProps['session_timeout'])); } } if ($CPsession != null) { // only return session if configd return a valid json response, otherwise fallback to // returning "UNKNOWN" return $CPsession; } } } else { return array("clientState" => 'NOT_AUTHORIZED', "ipAddress" => $clientIp); } } } return array("clientState" => 'UNKNOWN', "ipAddress" => $clientIp); }
/** * before routing event. * Handles authentication and authentication of user requests * In case of API calls, also prevalidates if request can be executed to return a more readable response * to the user. * @param Dispatcher $dispatcher * @return null|bool */ public function beforeExecuteRoute($dispatcher) { // handle authentication / authorization if (!empty($this->request->getHeader('Authorization'))) { // Authorization header send, handle API request $authHeader = explode(' ', $this->request->getHeader('Authorization')); if (count($authHeader) > 1) { $key_secret_hash = $authHeader[1]; $key_secret = explode(':', base64_decode($key_secret_hash)); if (count($key_secret) > 1) { $apiKey = $key_secret[0]; $apiSecret = $key_secret[1]; $authFactory = new AuthenticationFactory(); $authenticator = $authFactory->get("Local API"); if ($authenticator->authenticate($apiKey, $apiSecret)) { $authResult = $authenticator->getLastAuthProperties(); if (array_key_exists('username', $authResult)) { // check ACL if user is returned by the Authenticator object $acl = new ACL(); if (!$acl->isPageAccessible($authResult['username'], $_SERVER['REQUEST_URI'])) { $this->getLogger()->error("uri " . $_SERVER['REQUEST_URI'] . " not accessible for user " . $authResult['username'] . " using api key " . $apiKey); } else { // authentication + authorization successful. // pre validate request and communicate back to the user on errors $callMethodName = $dispatcher->getActionName() . 'Action'; $dispatchError = null; // check number of parameters using reflection $object_info = new \ReflectionObject($this); $req_c = $object_info->getMethod($callMethodName)->getNumberOfRequiredParameters(); if ($req_c > count($dispatcher->getParams())) { $dispatchError = 'action ' . $dispatcher->getActionName() . ' expects at least ' . $req_c . ' parameter(s)'; } else { // if body is send as json data, parse to $_POST first $dispatchError = $this->parseJsonBodyData(); } if ($dispatchError != null) { // send error to client $this->response->setStatusCode(400, "Bad Request"); $this->response->setContentType('application/json', 'UTF-8'); $this->response->setJsonContent(array('message' => $dispatchError, 'status' => 400)); $this->response->send(); return false; } return true; } } } } } // not authenticated $this->response->setStatusCode(401, "Unauthorized"); $this->response->setContentType('application/json', 'UTF-8'); $this->response->setJsonContent(array('status' => 401, 'message' => 'Authentication Failed')); $this->response->send(); return false; } else { // handle UI ajax requests // use session data and ACL to validate request. if (!$this->doAuth()) { return false; } // check for valid csrf on post requests $csrf_tokenkey = $this->request->getHeader('X_CSRFTOKENKEY'); $csrf_token = $this->request->getHeader('X_CSRFTOKEN'); $csrf_valid = $this->security->checkToken($csrf_tokenkey, $csrf_token, false); if (($this->request->isPost() || $this->request->isPut() || $this->request->isDelete()) && !$csrf_valid) { // missing csrf, exit. $this->getLogger()->error("no matching csrf found for request"); return false; } } }
/** * logon client to zone, must use post type of request * @param string zone id number * @return array */ public function logonAction($zoneid = 0) { $clientIp = $this->getClientIp(); if ($this->request->isOptions()) { // return empty result on CORS preflight return array(); } elseif ($this->request->isPost() && $this->request->hasPost('user')) { // close session for long running action $this->sessionClose(); // get username from post $userName = $this->request->getPost("user", "striptags"); // search zone info, to retrieve list of authenticators $mdlCP = new CaptivePortal(); $cpZone = $mdlCP->getByZoneID($zoneid); if ($cpZone != null) { // authenticate user $isAuthenticated = false; $authFactory = new AuthenticationFactory(); foreach (explode(',', (string) $cpZone->authservers) as $authServerName) { $authServer = $authFactory->get(trim($authServerName)); // try this auth method $isAuthenticated = $authServer->authenticate($userName, $this->request->getPost("password", "string")); if ($isAuthenticated) { // stop trying, when authenticated break; } } if ($isAuthenticated) { // when authenticated, we have $authServer available to request additional data if needed $clientSession = $this->clientSession((string) $cpZone->zoneid); if ($clientSession['clientState'] == 'AUTHORIZED') { // already authorized, return current session return $clientSession; } else { // allow client to this captiveportal zone $backend = new Backend(); $CPsession = $backend->configdpRun("captiveportal allow", array((string) $cpZone->zoneid, $userName, $clientIp, $authServerName, 'json')); $CPsession = json_decode($CPsession, true); if ($CPsession != null) { // only return session if configd return a valid json response, otherwise fallback to // returning "UNKNOWN" return $CPsession; } } } else { return array("clientState" => 'NOT_AUTHORIZED', "ipAddress" => $clientIp); } } } return array("clientState" => 'UNKNOWN', "ipAddress" => $clientIp); }
select c.zoneid , c.sessionid , c.username , c.authenticated_via , c.deleted , c.created , accs.state from cp_clients c inner join session_restrictions sr on sr.zoneid = c.zoneid and sr.sessionid = c.sessionid left join session_info si on c.zoneid = si.zoneid and c.sessionid = si.sessionid left join accounting_state accs on accs.zoneid = c.zoneid and accs.sessionid = c.sessionid order by c.authenticated_via '); // process all sessions while ($row = $result->fetchArray(SQLITE3_ASSOC)) { $authFactory = new OPNsense\Auth\AuthenticationFactory(); $authenticator = $authFactory->get($row['authenticated_via']); if ($authenticator != null) { if ($row['state'] == null) { // new accounting state, send start event (if applicable) $stmt = $db->prepare('insert into accounting_state(zoneid, sessionid, state) values (:zoneid, :sessionid, \'RUNNING\')'); $stmt->bindParam(':zoneid', $row['zoneid']); $stmt->bindParam(':sessionid', $row['sessionid']); $stmt->execute(); if (method_exists($authenticator, 'startAccounting')) { // send start accounting event $authenticator->startAccounting($row['username'], $row['sessionid']); } } elseif ($row['deleted'] == 1 && $row['state'] != 'STOPPED') { // stop accounting, send stop event (if applicable)
/** * generate new vouchers * @param string $provider auth provider * @return array generated vouchers */ public function generateVouchersAction($provider) { if ($this->request->isPost()) { $authFactory = new AuthenticationFactory(); $auth = $authFactory->get($provider); if ($auth != null && method_exists($auth, 'generateVouchers')) { $count = $this->request->getPost('count', 'int', 0); $validity = $this->request->getPost('validity', 'int', 0); $vouchergroup = $this->request->getPost('vouchergroup', 'striptags', '---'); if ($count > 0 && $validity > 0) { return $auth->generateVouchers($vouchergroup, $count, $validity); } } } return array(); }