Extension:Wget Authentication
From MediaWiki.org
|
Release status: stable |
|
|---|---|
| Implementation | User identity |
| Description | Allows you to securely use wget to authenticate against a pre-existing HTTP authentication login system. |
| Last version | 1.0 |
| MediaWiki | 1.13.1 |
| License | GPL |
| Download | http://hinespot.net/content/WgetAuthentication.txt |
|
Check usage (experimental) |
|
Contents |
[edit] What can this extension do?
This allows you to securely exec() a wget url within mediawiki to authenticate your users (by way of HTTP authentication, as you've probably guessed). Once the username and password are received, this extension creates a pipe between php and a fork'd wget and proceeds to retreive a URL to the effect of: https://username:password@yourwebserver.com. Once wget returns, the extension will check wget's exit code and return success only if the code is zero.
[edit] Installation
First edit the file extensions/WgetAuthentication.php and paste the code that you see below.
To install this extension, add the following to LocalSettings.php:
require_once("$IP/extensions/WgetAuthentication.php"); /* This line is critical. Make sure you include it */ $wgAuth = new WgetAuthentication();
[edit] Configuration parameters
Now, add the following configuration parameters to your LocalSettings.php file....
/* Provide a list of possible domains that you would like the plugin to allow * the user to select from. They're just chosen names to be displayed on the * login form and used to index into the next two arrays. */ $wgetDomains = array("Domain One", "Domain Two"); /* For each domain, provide the actual URL to which the user's username and * password should be sent. Note: this is not just a domain name, it's the full * URL of the HTTP-authenticated location in which you would normally get a * pop-up login box if you were using a web browser. */ $wgetDomainURLS = array( "Domain One" => "yourwebserverone.com/login/at/this/url", "Domain Two" => "yourwebservertwo.com/login/at/another/url" ); /* Indicate whether or not you want 'https' login or 'http' logins for each * domain */ $wgetSecurity = array( "Domain One" => "https", "Domain Two" => "http" ); /* Optional: you may specify the domain names of the above URLS to use for * filling in the email address of each user if a user is logging in for the * very first time. The plugin will set their email address as already confirmed * automatically when the account is created. */ $wgetEmailDomains = array( "Domain One" => "yourwebdomainone.com", "Domain Two" => "yourwebdomaintwo.com" ); /* Optional: this plugin doesn't support local authentication right now, so * you might find the following configuration setting useful: */ $wgGroupPermissions['*' ]['createaccount'] = false;
[edit] Code
<?php # Copyright (C) 2009 Michael R. Hines # <http://www.mediawiki.org/wiki/User:Darkbeethoven> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # http://www.gnu.org/copyleft/gpl.html /** * Wget Authentication plugin. * Does not support local accounts right now. Does not support NEW usernames, * BUT will auto-create an account if the user has been * authenticated when logging in for the first time. */ $wgExtensionCredits['other'][] = array( 'name' => 'Wget Authentication Plugin', 'version' => '1.0', 'author' => 'Michael R. Hines', 'description' => 'Allows you to securely use wget to authenticate against a pre-existing HTTP authentication login system.', 'url' => 'http://hinespot.net/content/WgetAuthenticationtxt', ); class WgetAuthentication extends AuthPlugin { function WgetAuthentication() { } /** * Check whether there exists a user account with the given name. * * @param $username String: username. * @return bool * @public */ function userExists( $username ) { /* Just assume the user exists and try to authenticate. * We have no way to test otherwise. */ return true; } /** * Check if a username+password pair is a valid login. * * @param $username String: username. * @param $password String: user password. * @return bool * @public */ function authenticate( $username, $password ) { global $_SERVER, $wgOut; global $wgetDomains, $wgetDomainURLS, $wgetSecurity; /* Disallow empty passwords */ if ( '' == $password ) { $wgOut->addHTML("<h2>Empty passwords not allowed.</h2>"); return false; } /* convert all usernames to lowercase first */ $username = strtolower( $username ); $rc = ""; $auth = ""; $descriptorspec = array( 0 => array("pipe", "r"), // stdin 1 => array("pipe", "w")); // stdout /* * Setup a two-way pipe to talk between php and the fork/exec'd * wget process later. Wget will take the authentication URL * from standard input and the shell will spit out the exit code * on standard output. */ $process = proc_open("wget -i - -o /dev/null -O /dev/null; echo $?", $descriptorspec, $pipes); /* Make sure the fork/exec succeeded and the pipes are setup */ if (!is_resource($process)) { $wgOut->addHTML("<h2>Failed to internally setup the authentication process please contact your system administrator.</h2>"); return false; } /* Grab the selected domain name */ $dom = $_SESSION['wsDomain']; /* Make sure the domain is valid (could be 'invaliddomain' */ if(!$this->validDomain($dom)) { $wgOut->addHTML("<h2>Invalid Domain name: $dom"); return false; } /* Setup the authentication URL based on LocalSetting parameters */ $auth = ""; $auth .= $wgetSecurity[$dom]."://"; $auth .= urlencode($username).":".urlencode($password)."@"; $auth .= $wgetDomainURLS[$dom]; /* wget is blocking. feed the beast. */ $err = fwrite($pipes[0], $auth); if(!err) return false; fclose($pipes[0]); /* wget is still blocking with the exit code. he needs to use the bathroom. */ while($s = fgets($pipes[1], 1024)) $rc .= $s; fclose($pipes[1]); /* Check exit code. Success if zero */ if($rc != 0) return false; return true; } /** * Modify options in the login template. * * @param $template UserLoginTemplate object. * @public */ function modifyUITemplate( &$template ) { global $wgetDomainURLS, $wgetSecurity, $wgetDomains, $wgAuth, $wgOut; /* Did you setup LocalSettings.php properly?? */ if(!isset($wgetDomainURLS) || !isset($wgetSecurity) || !isset($wgetDomains)) { $wgAuth = new AuthPlugin(); $wgOut->addHTML("<h2>NOTE: WgetAuthentication is not enabled. You are missing configuration parameters in LocalSettings.php</h2>"); return; } /* Support for multiple domains */ $template->set( 'usedomain', true ); $template->set( 'domainnames', $wgetDomains ); /* Disable new user account creation */ $template->set( 'create', false ); $template->set('useemail', false); $template->set('remember', false); } /** * Set the domain this plugin is supposed to use when authenticating. * * @param $domain String: authentication domain. * @public */ function setDomain( $domain ) { $_SESSION['wsDomain'] = $domain; } /** * Check to see if the specific domain is a valid domain. * * @param $domain String: authentication domain. * @return bool * @public */ function validDomain( $domain ) { global $wgetDomainURLS, $wgetSecurity, $wgetDomains, $wgAuth, $wgOut; /* Make sure the domain is valid */ if(in_array($domain, $wgetDomains)) return true; return false; } /** * When a user logs in, optionally fill in preferences and such. * For instance, you might pull the email address or real name from the * external user database. * * The User object is passed by reference so it can be modified; don't * forget the & on your function declaration. * * @param User $user * @public */ function updateUser( &$user ) { /* Nothing to do here, really. We've setup initUser, though * later */ return true; } /** * Return true if the wiki should create a new local account automatically * when asked to login a user who doesn't exist locally but does in the * external auth database. * * If you don't automatically create accounts, you must still create * accounts in some way. It's not possible to authenticate without * a local account. * * This is just a question, and shouldn't perform any actions. * * @return bool * @public */ function autoCreate() { return true; } /** * Can users change their passwords? * * @return bool */ function allowPasswordChange() { /* HTTP-authenticated users should change their passwords * elsewhere. */ return false; } /** * Set the given password in the authentication database. * As a special case, the password may be set to null to request * locking the password to an unusable value, with the expectation * that it will be set later through a mail reset or other method. * * Return true if successful. * * @param $user User object. * @param $password String: password. * @return bool * @public */ function setPassword( $user, $password ) { /* HTTP-authenticated users should change their passwords * elsewhere. */ return false; } /** * Update user information in the external authentication database. * Return true if successful. * * @param $user User object. * @return bool * @public */ function updateExternalDB( $user ) { /* Just assume it worked. */ return true; } /** * Check to see if external accounts can be created. * Return true if external accounts can be created. * @return bool * @public */ function canCreateAccounts() { return false; } /** * Add a user to the external authentication database. * Return true if successful. * * @param User $user - only the name should be assumed valid at this point * @param string $password * @param string $email * @param string $realname * @return bool * @public */ function addUser( $user, $password, $email='', $realname='' ) { return false; } /** * Return true to prevent logins that don't authenticate here from being * checked against the local database's password fields. * * This is just a question, and shouldn't perform any actions. * * @return bool * @public */ function strict() { /* local authentication not supported right now */ return true; } /** * Check if a user should authenticate locally if the global authentication fails. * If either this or strict() returns true, local authentication is not used. * * @param $username String: username. * @return bool * @public */ function strictUserAuth( $username ) { /* local authentication not supported right now */ return true; } /** * When creating a user account, optionally fill in preferences and such. * For instance, you might pull the email address or real name from the * external user database. * * The User object is passed by reference so it can be modified; don't * forget the & on your function declaration. * * @param $user User object. * @param $autocreate bool True if user is being autocreated on login * @public */ function initUser( &$user, $autocreate=false ) { global $_SESSION, $wgetDomainURLS, $wgetSecurity, $wgetDomains, $wgAuth, $wgOut, $wgetEmailDomains; /* Fill in the email address on first login? */ if(!isset($wgetEmailDomains)) { return; } $dom = $_SESSION['wsDomain']; if(!$this->validDomain($dom)) { return; } $user->setEmail(strtolower($user->getName()) . "@" . $wgetEmailDomains[$dom]); $user->mEmailAuthenticated = wfTimestampNow(); $user->setToken(); $user->saveSettings(); } /** * If you want to munge the case of an account name before the final * check, now is your chance. */ function getCanonicalName( $username ) { /* prevent multiple account names */ $username = strtolower( $username ); // uppercase first letter to make MediaWiki happy $username = ucfirst($username); return $username; } }
