aboutsummaryrefslogtreecommitdiff
path: root/engine/classes/ElggPAM.php
diff options
context:
space:
mode:
Diffstat (limited to 'engine/classes/ElggPAM.php')
-rw-r--r--engine/classes/ElggPAM.php105
1 files changed, 105 insertions, 0 deletions
diff --git a/engine/classes/ElggPAM.php b/engine/classes/ElggPAM.php
new file mode 100644
index 000000000..f07095fc1
--- /dev/null
+++ b/engine/classes/ElggPAM.php
@@ -0,0 +1,105 @@
+<?php
+/**
+ * ElggPAM Pluggable Authentication Module
+ *
+ * @package Elgg.Core
+ * @subpackage Authentication
+ */
+class ElggPAM {
+ /**
+ * @var string PAM policy type: user, api or plugin-defined policies
+ */
+ protected $policy;
+
+ /**
+ * @var array Failure mesages
+ */
+ protected $messages;
+
+ /**
+ * ElggPAM constructor
+ *
+ * @param string $policy PAM policy type: user, api, or plugin-defined policies
+ */
+ public function __construct($policy) {
+ $this->policy = $policy;
+ $this->messages = array('sufficient' => array(), 'required' => array());
+ }
+
+ /**
+ * Authenticate a set of credentials against a policy
+ * This function will process all registered PAM handlers or stop when the first
+ * handler fails. A handler fails by either returning false or throwing an
+ * exception. The advantage of throwing an exception is that it returns a message
+ * that can be passed to the user. The processing order of the handlers is
+ * determined by the order that they were registered.
+ *
+ * If $credentials are provided, the PAM handler should authenticate using the
+ * provided credentials. If not, then credentials should be prompted for or
+ * otherwise retrieved (eg from the HTTP header or $_SESSION).
+ *
+ * @param array $credentials Credentials array dependant on policy type
+ * @return bool
+ */
+ public function authenticate($credentials = array()) {
+ global $_PAM_HANDLERS;
+
+ if (!isset($_PAM_HANDLERS[$this->policy]) ||
+ !is_array($_PAM_HANDLERS[$this->policy])) {
+ return false;
+ }
+
+ $authenticated = false;
+
+ foreach ($_PAM_HANDLERS[$this->policy] as $k => $v) {
+ $handler = $v->handler;
+ if (!is_callable($handler)) {
+ continue;
+ }
+ /* @var callable $handler */
+
+ $importance = $v->importance;
+
+ try {
+ // Execute the handler
+ // @todo don't assume $handler is a global function
+ $result = call_user_func($handler, $credentials);
+ if ($result) {
+ $authenticated = true;
+ } elseif ($result === false) {
+ if ($importance == 'required') {
+ $this->messages['required'][] = "$handler:failed";
+ return false;
+ } else {
+ $this->messages['sufficient'][] = "$handler:failed";
+ }
+ }
+ } catch (Exception $e) {
+ if ($importance == 'required') {
+ $this->messages['required'][] = $e->getMessage();
+ return false;
+ } else {
+ $this->messages['sufficient'][] = $e->getMessage();
+ }
+ }
+ }
+
+ return $authenticated;
+ }
+
+ /**
+ * Get a failure message to display to user
+ *
+ * @return string
+ */
+ public function getFailureMessage() {
+ $message = elgg_echo('auth:nopams');
+ if (!empty($this->messages['required'])) {
+ $message = $this->messages['required'][0];
+ } elseif (!empty($this->messages['sufficient'])) {
+ $message = $this->messages['sufficient'][0];
+ }
+
+ return elgg_trigger_plugin_hook('fail', 'auth', $this->messages, $message);
+ }
+}