/** * Static function to refresh src_org_cache from src_org * * @param Source|src_id|src_uuid $source * @return int number of rows cached */ public static function refresh_cache($source) { $conn = AIR2_DBManager::get_master_connection(); // get the src_id $src_id; if (is_numeric($source)) { $src_id = $source; } elseif (is_string($source)) { $q = 'select src_id from source where src_uuid = ?'; $src_id = $conn->fetchOne($q, array($source), 0); } elseif (is_object($source)) { $src_id = $source->src_id; } // sanity! if (!$src_id) { Carper::carp("Source !exists"); return; } // delete all src_org_cache recs for this source $conn->execute("delete from src_org_cache where soc_src_id = {$src_id}"); // array of org_id => status $org_status = Source::get_authz_status($src_id); // bulk-insert $vals = array(); foreach ($org_status as $org_id => $status) { $vals[] = "({$src_id},{$org_id},'{$status}')"; } if (count($vals)) { $vals = implode(',', $vals); $stmt = "insert into src_org_cache (soc_src_id, soc_org_id, soc_status)"; $conn->execute("{$stmt} values {$vals}"); } return count($vals); }
/** * initialize security for this controller * * This function determines what (if any) security the user has and * encapsulates it in the $AIR2User class variable. Will return a * login page and exit if the user cannot be authenticated. * * @access private * @return void */ public function init_security() { // load required libraries $this->authuser = new $this->auth_user_class(); // check if the credentials were good if (!$this->authuser->has_valid_tkt() || !$this->authuser->get_user()) { // user not authenticated $this_uri = current_url() . '?' . $this->input->server('QUERY_STRING'); Carper::carp("Permission denied for {$this_uri}"); $uri = $this->uri_for('login', array('back' => $this_uri)); //echo "Location: $uri\n"; redirect($uri); exit(0); } // authn ok return true; }
/** * Loads login view and authenticate users * * we do explicit load->view calls here because the login screen is * independent of the rest of the View architecture. */ public function index() { // redirect to original request, or home page $back = $this->input->get_post('back'); if (!isset($back) || !strlen($back)) { $back = site_url(''); } // admin allows overriding PIN SSO $admin = false; if (isset($this->input_all['admin']) && $this->input_all['admin']) { $admin = true; } if (isset($_GET['admin']) && $_GET['admin']) { $admin = true; } // create stash $stash = array('static_url' => site_url(), 'back' => $back, 'c' => $this, 'admin' => $admin); // GET requests show a login form if ($this->method == 'GET') { // special case. // if we are configured to trust the PIN SSO tkt (auth_tkt) // then check for it and use its "sso" data value // as the AIR2 username if (AIR2_PIN_SSO_TRUST && !$admin) { $tkt = $this->input->cookie(AIR2_PIN_SSO_TKT); if (!$tkt) { $tkt = $this->input->get_post(AIR2_PIN_SSO_TKT); } if ($tkt) { $at = new Apache_AuthTkt(array('conf' => AIR2_PIN_SSO_CONFIG, 'encrypt_data' => false)); //Carper::carp("got auth_tkt for trust pin sso"); if ($at->validate_ticket($tkt)) { $tkt_info = $at->parse_ticket($tkt); $tkt_data = json_decode($tkt_info['data'], true); if (isset($tkt_data['sso'])) { $username = $tkt_data['sso']; $user = $this->_fetch_user($username); if ($user) { // trust prior authentication. create the AIR2 tkt. $this->airuser->create_tkt($user, true, true); $user->user_login_dtim = air2_date(); $user->save(); //echo "Location: $back\n"; redirect($back); } else { Carper::carp("Invalid user in tkt"); redirect(AIR2_PIN_SSO_URL . '?back=' . $back); } } else { Carper::carp("Missing sso param in tkt"); redirect(AIR2_PIN_SSO_URL . '?back=' . $back); } } else { Carper::carp("Invalid tkt"); redirect(AIR2_PIN_SSO_URL . '?back=' . $back); } } else { // no PIN tkt; redirect to PIN login Carper::carp("No PIN SSO tkt"); redirect(AIR2_PIN_SSO_URL . '?back=' . $back); } } // print form $this->load->view('login', $stash); } elseif ($this->method == 'POST') { header('Access-Control-Allow-Origin: *'); // allow external $uname = isset($this->input_all['username']) ? $this->input_all['username'] : null; // #9505 - xss-filter messes up passwords, so get raw input $pwd = isset($_POST['password']) ? $_POST['password'] : null; // didn't enter username or password if (!$uname || !$pwd || strlen($uname) < 1 || strlen($pwd) < 1) { if ($this->view == "json") { header('X-AIR2: authentication failed', false, 400); $resp = array('success' => false, 'message' => 'invalid request'); print json_encode($resp); } elseif ($this->view == "xml") { header('X-AIR2: authentication failed', false, 400); // TODO use 'xml' view print "<air2><success>false</success><message>invalid request</message></air2>"; } else { $stash['errormsg'] = 'You must enter both a username and password'; $this->load->view('login', $stash); } return; } // bad username $user = $this->_fetch_user($uname); if (!$user || !$user->exists()) { if ($this->view == "json") { header('X-AIR2: authentication failed', false, 401); $resp = array('success' => false, 'message' => 'authentication failed'); print json_encode($resp); return; } elseif ($this->view == "xml") { header('X-AIR2: authentication failed', false, 401); // TODO use 'xml' view print "<air2><success>false</success><message>authentication failed</message></air2>"; return; } else { $stash['errormsg'] = 'The information you entered does not match an active account'; $this->load->view('login', $stash); return; } } // delegate to PIN SSO? $pw_ok = false; // the !$admin means we avoid infinite loop with the SSO service, // which just points back here. if (AIR2_PIN_SSO_TRUST && !$admin) { $pw_ok = $this->check_pin_sso($uname, $pwd); } else { $pw_ok = $user->check_password($pwd); } // bad password if (!$pw_ok) { if ($this->view == "json") { header('X-AIR2: authentication failed', false, 401); $resp = array('success' => false, 'message' => 'authentication failed'); print json_encode($resp); return; } elseif ($this->view == "xml") { header('X-AIR2: authentication failed', false, 401); // TODO use 'xml' view print "<air2><success>false</success><message>authentication failed</message></air2>"; return; } else { $stash['errormsg'] = 'The information you entered does not match an active account'; $this->load->view('login', $stash); //TODO -- form error msg return; } } // authenticated ok. create the tkt. $tkt = $this->airuser->create_tkt($user, true, true); $user->user_login_dtim = air2_date(); $user->save(); // non-html response does not redirect if ($this->view == "json") { $tkt['success'] = true; print json_encode($tkt); return; } elseif ($this->view == "xml") { header('X-AIR2: authentication failed', false, 401); // TODO use 'xml' view print "<air2><success>true</success><air2_tkt>" . $tkt['air2_tkt'] . "</air2_tkt></air2>"; return; } else { redirect($back); } } }
/** * Fix the question sequence numbers for this query, given the question * that has changed, and its new sequence number. * * @param Question $ques * @param int $seq */ protected function _fix_sequence(Question $ques = null, $seq = null) { if ($ques) { if (!is_int($seq) || $seq < 1) { throw new Rframe_Exception(Rframe::BAD_DATA, "Invalid sequence '{$seq}'"); } $ques->ques_dis_seq = $seq; } // get all existing questions $q = Doctrine_Query::create()->from('Question q'); // $q->setConnection(AIR2_DBManager::get_master_connection()); $q->where('q.ques_inq_id = ?', $this->parent_rec->inq_id); if ($ques && $ques->ques_id) { $q->addWhere('q.ques_id != ?', $ques->ques_id); } $q->orderBy('q.ques_dis_seq asc'); $rs = $q->execute(); $current_seq_num = 1; foreach ($rs as $idx => $rec) { if ($current_seq_num == $seq) { $current_seq_num++; } // update and save $rec->ques_dis_seq = $current_seq_num; // compensate for doctrines agressive caching if ($rec->exists()) { $rec->save(); } else { Carper::carp("tried to reorder a non-existant question " . "ques_uuid:{$rec->ques_uuid} ques_id:{$rec->ques_id} " . "ques_value:{$rec->ques_value} of inquery {$rec->ques_inq_id}"); } $current_seq_num++; } }
/** * DO THE RIGHT THING with an Exception, depending on what environment * we're running in. * * @param Exception $e */ function show_exception(Exception $e) { $msg = 'There was an error'; if (defined('AIR2_ENVIRONMENT') && AIR2_ENVIRONMENT != 'prod') { $msg = $e->__toString(); } else { Carper::carp($e->__toString()); } $this->show_error('An error was encountered', $msg); }
/** * initialize security for this controller * * This function determines what (if any) security the user has and * encapsulates it in the $AIR2User class variable. Will return a * login page and exit if the user cannot be authenticated. * * @access private * @return void */ private function _init_security() { // check if the credentials were good if (!$this->airuser->has_valid_tkt() || !$this->airuser->get_user()) { // user not authenticated $this_uri = current_url() . '?' . $this->input->server('QUERY_STRING'); //Carper::carp("Permission denied for $this_uri"); $uri = $this->uri_for('login', array('back' => $this_uri)); //echo "Location: $uri\n"; redirect($uri); exit(0); } // ok credentials. does the user have min authz? $air2_user = $this->airuser->get_user(); // skip authz check if SYSTEM or TEST user // TODO the TEST type really ought to be tested here as well // but that will require audit of existing unit tests. if ($air2_user['user_type'] != 'S' && $air2_user['user_type'] != 'T') { $cum_authz = 0; foreach ($air2_user->get_authz() as $org_id => $bitmask) { $cum_authz += $bitmask; } if ($cum_authz == 0) { Carper::carp("authn ok for " . $air2_user->user_username . " type=" . $air2_user['user_type'] . " but no authz"); show_error('Insufficient authz', 403); } } //set global remote user ID and TYPE (for upd/cre user stamps) define('AIR2_REMOTE_USER_ID', $this->airuser->get_id()); define('AIR2_REMOTE_USER_TYPE', $air2_user['user_type']); // enable activity logging // TODO: where else can this go? Would it be better to default to true? AIR2Logger::$ENABLE_LOGGING = true; // authn ok return true; }