openrat-cms

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit d572b2fdb7d1a8840b5cd3a42cd2df9fa29e15d6
parent 884cff104f219c12bd8e5a9bb6be278cebbc871c
Author: Jan Dankert <devnull@localhost>
Date:   Mon,  5 Nov 2012 22:50:24 +0100

Zusammenführen

Diffstat:
auth/Auth.class.php | 9+++++++++
auth/DatabaseAuth.class.php | 33+++++++++++++++++++++++++++++++++
auth/HttpAuth.class.php | 259+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
auth/IdentAuth.class.php | 31+++++++++++++++++++++++++++++++
auth/InternalAuth.class.php | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
auth/LdapAuth.class.php | 227+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
auth/OpenIdAuth.class.php | 480+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
auth/PersonasAuth.class.php | 0
auth/include.inc.php | 13+++++++++++++
init.php | 2++
util/OpenId.class.php | 495-------------------------------------------------------------------------------
util/include.inc.php | 6------
12 files changed, 1106 insertions(+), 501 deletions(-)

diff --git a/auth/Auth.class.php b/auth/Auth.class.php @@ -0,0 +1,8 @@ +<?php + +interface Auth +{ + function login( $username, $password ); +} + +?>+ \ No newline at end of file diff --git a/auth/DatabaseAuth.class.php b/auth/DatabaseAuth.class.php @@ -0,0 +1,32 @@ +<?php + +/** + * Authentifzierung über eine externe Datenbank. + * @author dankert + * + */ +class DatabaseAuth implements Auth +{ + + /** + * Login. + */ + public function login( $user, $password ) + { + global $conf; + + $authdb = new DB( $conf['security']['authdb'] ); + + $sql = new Sql( $conf['security']['authdb']['sql'] ); + $sql->setString('username',$this->name); + $sql->setString('password',$password); + $row = $authdb->getRow( $sql ); + $ok = !empty($row); + + // noch nicht implementiert: $authdb->close(); + + return $ok; + } +} + +?>+ \ No newline at end of file diff --git a/auth/HttpAuth.class.php b/auth/HttpAuth.class.php @@ -0,0 +1,258 @@ +<?php + +/** + * HTTP-Authentifzierung. + * Das vom Benutzer eingegebene Kennwort wird gegen eine HTTP-Adresse + * geprüft, bei der HTTP-Auth aktiviert ist. + * + * @author dankert + */ +class HttpAuth implements Auth +{ + + public function username() + { + return null; + } + + + /** + * Ueberpruefen des Kennwortes. + * + * Das Kennwort wird ueber Datenbank oder ueber LDAP-Verzeichnisdienst geprueft. + * Wenn + * - ein LDAP-Dn ("distinghished-name") vorhanden ist, dann Pruefung ueber den LDAP-Server, + * - sonst ueber die Benutzertabelle in der Datenbank. + */ + public function login( $user, $password ) + { + global $conf; + + $http = new Http( $conf['security']['http']['url'] ); + $http->method = 'HEAD'; + $http->setBasicAuthentication( $this->name, $password ); + + $ok = $http->request(); + + return $ok; + + + $db = db_connection(); + $this->mustChangePassword = false; + + // Lesen des Benutzers aus der DB-Tabelle + $sql = new Sql( <<<SQL +SELECT * FROM {t_user} + WHERE name={name} +SQL + ); + $sql->setString('name',$this->name); + + $row_user = $db->getRow( $sql ); + + $check = false; + $authType = $conf['security']['auth']['type']; // Entweder 'ldap', 'authdb', 'http', oder 'database' + + if ( !empty($row_user) ) + { + // Benutzername ist bereits in der Datenbank. + $this->userid = $row_user['id']; + $this->ldap_dn = $row_user['ldap_dn']; + $check = true; + $autoAdd = false; // Darf nicht hinzugef�gt werden, da schon vorhanden. + } + elseif( $authType == 'ldap' && $conf['ldap']['search']['add'] ) + { + // Benutzer noch nicht in der Datenbank vorhanden. + // Falls ein LDAP-Account gefunden wird, wird dieser �bernommen. + $check = true; + $autoAdd = true; + } + elseif( $authType == 'authdb' && $conf['security']['authdb']['add'] ) + { + $check = true; + $autoAdd = true; + } + elseif( $authType == 'http' && $conf['security']['http']['add'] ) + { + $check = true; + $autoAdd = true; + } + + if ( $check ) + { + // Falls benutzerspezifischer LDAP-dn vorhanden wird Benutzer per LDAP authentifiziert + if ( $conf['security']['auth']['userdn'] && !empty($this->ldap_dn ) ) + { + Logger::debug( 'checking login via ldap' ); + $ldap = new Ldap(); + $ldap->connect(); + + // Benutzer ist bereits in Datenbank + // LDAP-Login mit dem bereits vorhandenen DN versuchen + $ok = $ldap->bind( $this->ldap_dn, $password ); + + // Verbindung zum LDAP-Server brav beenden + $ldap->close(); + + return $ok; + } + elseif( $authType == 'ldap' ) + { + Logger::debug( 'checking login via ldap' ); + $ldap = new Ldap(); + $ldap->connect(); + + if ( empty($conf['ldap']['dn']) ) + { + // Der Benutzername wird im LDAP-Verzeichnis gesucht. + // Falls gefunden, wird der DN (=der eindeutige Schl�ssel im Verzeichnis) ermittelt. + $dn = $ldap->searchUser( $this->name ); + + if ( empty($dn) ) + { + Logger::debug( 'User not found in LDAP directory' ); + return false; // Kein LDAP-Account gefunden. + } + + Logger::debug( 'User found: '.$dn ); + } + else + { + $dn = str_replace( '{user}',$this->name,$conf['ldap']['dn'] ); + } + + // LDAP-Login versuchen + $ok = $ldap->bind( $dn, $password ); + + Logger::debug( 'LDAP bind: '.($ok?'success':'failed') ); + + if ( $ok && $conf['security']['authorize']['type'] == 'ldap' ) + { + $sucheAttribut = $conf['ldap']['authorize']['group_name']; + $sucheFilter = str_replace('{dn}',$dn,$conf['ldap']['authorize']['group_filter']); + + $ldap_groups = $ldap->searchAttribute( $sucheFilter, $sucheAttribut ); + $sql_ldap_groups = "'".implode("','",$ldap_groups)."'"; + + $sql = new Sql( <<<SQL +SELECT id,name FROM {t_group} + WHERE name IN($sql_ldap_groups) + ORDER BY name ASC +SQL + ); + $oldGroups = $this->getGroupIds(); + $this->groups = $db->getAssoc( $sql ); + + foreach( $this->groups as $groupid=>$groupname) + { + if ( ! in_array($groupid,$oldGroups)) + $this->addGroup($groupid); + } + foreach( $oldGroups as $groupid) + { + if ( !isset($this->groups[$groupid]) ) + $this->delGroup($groupid); + } + + + // Pr�fen, ob Gruppen fehlen. Diese dann ggf. in der OpenRat-Datenbank hinzuf�gen. + if ( $conf['ldap']['authorize']['auto_add'] ) + { + foreach( $ldap_groups as $group ) + { + if ( !in_array($group,$this->groups) ) // Gruppe schon da? + { + $g = new Group(); + $g->name = $group; + $g->add(); // Gruppe hinzuf�gen + + $this->groups[$g->groupid] = $group; + } + } + } +// Html::debug($this->groups,'Gruppen/Ids des Benutzers'); + } + + // Verbindung zum LDAP-Server brav beenden + $ldap->close(); + + if ( $ok && $autoAdd ) + { + // Falls die Authentifizierung geklappt hat, wird der + // LDAP-Account in die Datenbank �bernommen. + $this->ldap_dn = $dn; + $this->fullname = $this->name; + $this->add(); + $this->save(); + } + + return $ok; + } + elseif( $authType == 'database' ) + { + // Pruefen ob Kennwort mit Datenbank uebereinstimmt + if ( $row_user['password'] == $password ) + { + // Kennwort stimmt mit Datenbank �berein, aber nur im Klartext. + // Das Kennwort muss ge�ndert werden + $this->mustChangePassword = true; + + // Login nicht erfolgreich + return false; + } + elseif ( $row_user['password'] == md5( $this->saltPassword($password) ) ) + { + // Die Kennwort-Pr�fsumme stimmt mit dem aus der Datenbank �berein. + // Juchuu, Login ist erfolgreich. + return true; + } + else + { + // Kennwort stimmt garnicht �berein. + return false; + } + } + elseif( $authType == 'authdb' ) + { + $authdb = new DB( $conf['security']['authdb'] ); + $sql = new Sql( $conf['security']['authdb']['sql'] ); + $sql->setString('username',$this->name); + $sql->setString('password',$password); + $row = $authdb->getRow( $sql ); + $ok = !empty($row); + + if ( $ok && $autoAdd ) + { + // Falls die Authentifizierung geklappt hat, wird der + // Benutzername in der eigenen Datenbank eingetragen. + $this->fullname = $this->name; + $this->add(); + $this->save(); + } + // noch nicht implementiert: $authdb->close(); + + return $ok; + } + elseif( $authType == 'http' ) + { + $http = new Http( $conf['security']['http']['url'] ); + $http->method = 'HEAD'; + $http->setBasicAuthentication( $this->name, $password ); + + $ok = $http->request(); + + return $ok; + } + else + { + die( 'unknown authentication-type in configuration: '.$authType ); + } + } + + // Benutzername nicht in Datenbank. + return false; + } +} + +?>+ \ No newline at end of file diff --git a/auth/IdentAuth.class.php b/auth/IdentAuth.class.php @@ -0,0 +1,30 @@ +<?php + +/** + * Authentifizierung via Ident-Server. + * + * Der Benutzername wird über einen Ident-Server, der auf dem + * Client installiert sein muss, ermittelt. + * + * @author dankert + */ +class IdentAuth implements Auth +{ + + public function username() + { + // TODO: Ident. + return null; + } + + + /** + * Ueberpruefen des Kennwortes ist über Ident nicht möglich. + */ + public function login( $user, $password ) + { + return false; + } +} + +?>+ \ No newline at end of file diff --git a/auth/InternalAuth.class.php b/auth/InternalAuth.class.php @@ -0,0 +1,51 @@ +<?php + +class InternalAuth implements Auth +{ + var $mustChangePassword = false; + + /** + * Ueberpruefen des Kennwortes + * ueber die Benutzertabelle in der Datenbank. + */ + function login( $username, $password ) + { + global $conf; + + $db = db_connection(); + + // Lesen des Benutzers aus der DB-Tabelle + $sql = new Sql( <<<SQL +SELECT * FROM {t_user} + WHERE name={name} +SQL + ); + $sql->setString('name',$this->name); + + $row_user = $db->getRow( $sql ); + + // Pruefen ob Kennwort mit Datenbank uebereinstimmt + if ( $row_user['password'] == $password ) + { + // Kennwort stimmt mit Datenbank �berein, aber nur im Klartext. + // Das Kennwort muss ge�ndert werden + $this->mustChangePassword = true; + + // Login nicht erfolgreich + return false; + } + elseif ( $row_user['password'] == md5( $this->saltPassword($password) ) ) + { + // Die Kennwort-Pr�fsumme stimmt mit dem aus der Datenbank �berein. + // Juchuu, Login ist erfolgreich. + return true; + } + else + { + // Kennwort stimmt garnicht ueberein. + return false; + } + } +} + +?>+ \ No newline at end of file diff --git a/auth/LdapAuth.class.php b/auth/LdapAuth.class.php @@ -0,0 +1,226 @@ +<?php + +class LdapAuth implements Auth +{ + + public function login($username, $password) + { + $db = db_connection(); + $this->mustChangePassword = false; + + // Lesen des Benutzers aus der DB-Tabelle + $sql = new Sql( <<<SQL +SELECT * FROM {t_user} + WHERE name={name} +SQL + ); + $sql->setString('name',$this->name); + + $row_user = $db->getRow( $sql ); + + $check = false; + $authType = $conf['security']['auth']['type']; // Entweder 'ldap', 'authdb', 'http', oder 'database' + + if ( !empty($row_user) ) + { + // Benutzername ist bereits in der Datenbank. + $this->userid = $row_user['id']; + $this->ldap_dn = $row_user['ldap_dn']; + $check = true; + $autoAdd = false; // Darf nicht hinzugef�gt werden, da schon vorhanden. + } + elseif( $authType == 'ldap' && $conf['ldap']['search']['add'] ) + { + // Benutzer noch nicht in der Datenbank vorhanden. + // Falls ein LDAP-Account gefunden wird, wird dieser �bernommen. + $check = true; + $autoAdd = true; + } + elseif( $authType == 'authdb' && $conf['security']['authdb']['add'] ) + { + $check = true; + $autoAdd = true; + } + elseif( $authType == 'http' && $conf['security']['http']['add'] ) + { + $check = true; + $autoAdd = true; + } + + if ( $check ) + { + // Falls benutzerspezifischer LDAP-dn vorhanden wird Benutzer per LDAP authentifiziert + if ( $conf['security']['auth']['userdn'] && !empty($this->ldap_dn ) ) + { + Logger::debug( 'checking login via ldap' ); + $ldap = new Ldap(); + $ldap->connect(); + + // Benutzer ist bereits in Datenbank + // LDAP-Login mit dem bereits vorhandenen DN versuchen + $ok = $ldap->bind( $this->ldap_dn, $password ); + + // Verbindung zum LDAP-Server brav beenden + $ldap->close(); + + return $ok; + } + elseif( $authType == 'ldap' ) + { + Logger::debug( 'checking login via ldap' ); + $ldap = new Ldap(); + $ldap->connect(); + + if ( empty($conf['ldap']['dn']) ) + { + // Der Benutzername wird im LDAP-Verzeichnis gesucht. + // Falls gefunden, wird der DN (=der eindeutige Schl�ssel im Verzeichnis) ermittelt. + $dn = $ldap->searchUser( $this->name ); + + if ( empty($dn) ) + { + Logger::debug( 'User not found in LDAP directory' ); + return false; // Kein LDAP-Account gefunden. + } + + Logger::debug( 'User found: '.$dn ); + } + else + { + $dn = str_replace( '{user}',$this->name,$conf['ldap']['dn'] ); + } + + // LDAP-Login versuchen + $ok = $ldap->bind( $dn, $password ); + + Logger::debug( 'LDAP bind: '.($ok?'success':'failed') ); + + if ( $ok && $conf['security']['authorize']['type'] == 'ldap' ) + { + $sucheAttribut = $conf['ldap']['authorize']['group_name']; + $sucheFilter = str_replace('{dn}',$dn,$conf['ldap']['authorize']['group_filter']); + + $ldap_groups = $ldap->searchAttribute( $sucheFilter, $sucheAttribut ); + $sql_ldap_groups = "'".implode("','",$ldap_groups)."'"; + + $sql = new Sql( <<<SQL +SELECT id,name FROM {t_group} + WHERE name IN($sql_ldap_groups) + ORDER BY name ASC +SQL + ); + $oldGroups = $this->getGroupIds(); + $this->groups = $db->getAssoc( $sql ); + + foreach( $this->groups as $groupid=>$groupname) + { + if ( ! in_array($groupid,$oldGroups)) + $this->addGroup($groupid); + } + foreach( $oldGroups as $groupid) + { + if ( !isset($this->groups[$groupid]) ) + $this->delGroup($groupid); + } + + + // Pr�fen, ob Gruppen fehlen. Diese dann ggf. in der OpenRat-Datenbank hinzuf�gen. + if ( $conf['ldap']['authorize']['auto_add'] ) + { + foreach( $ldap_groups as $group ) + { + if ( !in_array($group,$this->groups) ) // Gruppe schon da? + { + $g = new Group(); + $g->name = $group; + $g->add(); // Gruppe hinzuf�gen + + $this->groups[$g->groupid] = $group; + } + } + } +// Html::debug($this->groups,'Gruppen/Ids des Benutzers'); + } + + // Verbindung zum LDAP-Server brav beenden + $ldap->close(); + + if ( $ok && $autoAdd ) + { + // Falls die Authentifizierung geklappt hat, wird der + // LDAP-Account in die Datenbank �bernommen. + $this->ldap_dn = $dn; + $this->fullname = $this->name; + $this->add(); + $this->save(); + } + + return $ok; + } + elseif( $authType == 'database' ) + { + // Pruefen ob Kennwort mit Datenbank uebereinstimmt + if ( $row_user['password'] == $password ) + { + // Kennwort stimmt mit Datenbank �berein, aber nur im Klartext. + // Das Kennwort muss ge�ndert werden + $this->mustChangePassword = true; + + // Login nicht erfolgreich + return false; + } + elseif ( $row_user['password'] == md5( $this->saltPassword($password) ) ) + { + // Die Kennwort-Pr�fsumme stimmt mit dem aus der Datenbank �berein. + // Juchuu, Login ist erfolgreich. + return true; + } + else + { + // Kennwort stimmt garnicht �berein. + return false; + } + } + elseif( $authType == 'authdb' ) + { + $authdb = new DB( $conf['security']['authdb'] ); + $sql = new Sql( $conf['security']['authdb']['sql'] ); + $sql->setString('username',$this->name); + $sql->setString('password',$password); + $row = $authdb->getRow( $sql ); + $ok = !empty($row); + + if ( $ok && $autoAdd ) + { + // Falls die Authentifizierung geklappt hat, wird der + // Benutzername in der eigenen Datenbank eingetragen. + $this->fullname = $this->name; + $this->add(); + $this->save(); + } + // noch nicht implementiert: $authdb->close(); + + return $ok; + } + elseif( $authType == 'http' ) + { + $http = new Http( $conf['security']['http']['url'] ); + $http->method = 'HEAD'; + $http->setBasicAuthentication( $this->name, $password ); + + $ok = $http->request(); + + return $ok; + } + else + { + die( 'unknown authentication-type in configuration: '.$authType ); + } + } + + // Benutzername nicht in Datenbank. + return false; + } +} + +?>+ \ No newline at end of file diff --git a/auth/OpenIdAuth.class.php b/auth/OpenIdAuth.class.php @@ -0,0 +1,479 @@ +<?php + + +/** + * Open-Id Authentisierung gem�� OpenId-Spezifikation 1.0. + * + */ +class OpenId +{ + /** + * Open-Id Server, an den die Authentisierungsanfrage gestellt wird. + * + * @var String + */ + var $server; + + + /** + * Informationen zum Benutzer. + * + * @var Array + */ + var $info; + + /** + * Open-Id Identity. + * + * @var String + */ + var $identity; + + /** + * Fehlermeldung (falls vorhanden). + * + * @var String + */ + var $error; + + /** + * OpenId-Benutzername. + * + * @var String + */ + var $user; + + /** + * OpenId-Provider. + * + * @var String + */ + var $provider; + + + var $supportAX; + var $supportSREG; + var $supportOpenId1_1; + var $supportOpenId2_0; + + + /** + * Neue Open-Id Anfrage. + * + * @param String $user + * @return OpenId + */ + function OpenId( $provider='',$user='' ) + { + $this->provider = $provider; + $this->user = $user; + } + + + /** + * Stellt fest, ob der Server vertrauenswuerdig ist. + * + * @return true, wenn vertrauenswuerdig. + */ + function serverOk() + { + global $conf; + $servers = $conf['security']['openid']['trusted_server']; + + if ( empty($servers) ) + { + return true; + } + else + { + $serverList = explode(',',$servers); + + $http = new Http($this->server); + if ( !in_array($http->url['host'],$serverList) ) + { + $this->error = 'Server '.$this->server.' is not trusted'; + return false; + } + else + return true; + } + + } + + + + /** + * Authentisierung Schritt 1.<br> + * Ermitteln der Identity. + * + * @return boolean TRUE, wenn Identity ermittelt wurde. + */ + function login() + { + if ( $this->provider != 'identity' ) + { + $this->user = config('security','openid','provider.'.$this->provider.'.xrds_uri'); + $this->identity = 'http://specs.openid.net/auth/2.0/identifier_select'; + } + $this->supportSREG = config('security','openid','provider.'.$this->provider.'.sreg_1_0'); + $this->supportAX = config('security','openid','provider.'.$this->provider.'.ax_1_0' ); + + // Schritt 1: Identity aus Yadis-Dokument laden. + $this->getIdentityFromYadis(); + + // Schritt 2: Fallback auf HTML-Dokument. + if ( empty($this->server) ) + { + $this->getIdentityFromHtmlMetaData(); + } + + // Falls immer noch kein Servername gefunden wurde, dann Abbruch. + if ( empty($this->server) ) + { + if ( empty($this->error) ) + $this->error = 'Unable to locate OpenId-Server in URL'; + return false; + } + + if ( !$this->serverOk() ) + return false; // Server nicht vertrauenswuerdig. + + if ( empty($this->identity) ) + // Falls die Identity bis hierher nicht deligiert wurde... + // Lt. Spezifikation mit Prefix "http://". + $this->identity = 'http://'.$this->user; + + return true; + } + + + + /** + * Erzeugt einen HTTP-Redirect auf den OpenId-Provider. + */ + public function getRedirectUrl() + { + global $conf; + + $this->handle = md5(microtime().session_id()); + + $redirHttp = new Http($this->server); + + if ( $this->supportOpenId2_0 ) + $redirHttp->requestParameter['openid.ns' ] = 'http://specs.openid.net/auth/2.0'; + + $redirHttp->requestParameter['openid.mode' ] = 'checkid_setup'; + $redirHttp->requestParameter['openid.identity' ] = $this->identity; + + if ( $this->supportOpenId2_0 ) + $redirHttp->requestParameter['openid.claimed_id'] = $this->identity; + + + // Profilangaben anfordern. E-Mail wird ben�tigt, Name und Sprache sind optional. + + if ( $this->supportAX ) + { + Logger::info("OpenId-Server is using OpenID Attribute Exchange 1.0"); + $redirHttp->requestParameter['openid.ns.ax' ] = 'http://openid.net/srv/ax/1.0'; + $redirHttp->requestParameter['openid.ax.mode' ] = 'fetch_request'; + $redirHttp->requestParameter['openid.ax.type.email' ] = 'http://axschema.org/contact/email'; + $redirHttp->requestParameter['openid.ax.type.username' ] = 'http://axschema.org/namePerson/friendly'; + $redirHttp->requestParameter['openid.ax.type.fullname' ] = 'http://axschema.org/namePerson'; + $redirHttp->requestParameter['openid.ax.type.language' ] = 'http://axschema.org/pref/language'; + $redirHttp->requestParameter['openid.ax.required' ] = 'username,email'; + $redirHttp->requestParameter['openid.ax.if_available' ] = 'language,fullname'; + } + + if ( $this->supportSREG ) + { + Logger::info("OpenId-Server is using OpenID Simple Registration Extension 1.0"); + $redirHttp->requestParameter['openid.ns.sreg' ] = 'http://openid.net/sreg/1.0'; + $redirHttp->requestParameter['openid.sreg.required'] = 'email,nickname'; + $redirHttp->requestParameter['openid.sreg.optional'] = 'fullname,language'; + } + + $trustRoot = @$conf['security']['openid']['trust_root']; + $server = Http::getServer(); + if ( empty($trustRoot) ) + $trustRoot = $server; + + $redirHttp->requestParameter['openid.trust_root' ] = slashify($trustRoot); + $redirHttp->requestParameter['openid.return_to' ] = slashify($server).'openid.'.PHP_EXT; + //$redirHttp->requestParameter['openid.realm' ] = slashify($server).'openid.'.PHP_EXT; + $redirHttp->requestParameter['openid.assoc_handle' ] = $this->handle; + + return $redirHttp->getUrl(); + } + + + + /** + * Ermittelt OpenId-Server und OpenId-Identity aus Yadis-Dokument.<br> + * + * @return unknown + */ + private function getIdentityFromYadis() + { + $http = new Http($this->user); +// $http->url['host'] = $this->user; + + $http->header[] = 'Accept: application/xrds+xml'; + if ( ! $http->request() ) + { + $this->error = 'Unable to get XML delegate information'; + return false; + } + + Logger::debug("OpenId: Found YADIS-document for ".$http->getUrl()); + //die(); + $p = xml_parser_create(); + $ok = xml_parse_into_struct($p, $http->body, $vals, $index); + xml_parser_free($p); + + foreach( $vals as $tag ) + { + if ( strtolower($tag['tag']) == 'type' ) + { + if ( $tag['value'] == 'http://openid.net/srv/ax/1.0' ) + $this->supportAX = true; + + if ( $tag['value'] == 'http://openid.net/sreg/1.0' ) + $this->supportSREG = true; + + if ( $tag['value'] == 'http://openid.net/signon/1.1' ) + $this->supportOpenId1_1 = true; + + if ( $tag['value'] == 'http://specs.openid.net/auth/2.0/server' ) + $this->supportOpenId2_0 = true; + } + + if ( strtolower($tag['tag']) == 'uri' ) + { + $this->server = $tag['value']; + } + + if ( strtolower($tag['tag']) == 'openid:delegate' ) + { + $this->identity = $tag['value']; + } + } + + if ( !$this->supportOpenId1_1 && !$this->supportOpenId2_0 ) + { + $this->error = 'Only OpenId 1.1 and 2.0 is supported but this identity-provider does not seem to support any of these.'; + return false; + } + if ( !$this->supportAX && !$this->supportSREG ) + { + $this->error = 'The identity-provider must support either Attribute-Exchange (AX) oder Simple-Registration (SREG), but it does not seem to support any of these.'; + return false; + } + } + + + /** + * Ermittelt OpenId-Server und OpenId-Identity aus HTML Meta-Tags.<br> + */ + private function getIdentityFromHtmlMetaData() + { + $http = new Http($this->user); +// $http = new Http(); +// $http->url['host'] = $this->user; + $http->header[] = 'Accept: text/html'; + + if ( ! $http->request() ) + { + $this->error = 'Unable to get HTML delegate information'; + return false; + } + + $seite = $http->body; + + // Die Meta-Tags mit regulaerem Ausdruck auslesen. + $treffer = array(); + preg_match('/rel="openid.server"\s+href="(\S+)"/',$seite,$treffer); + if ( count($treffer) >= 1 ) + { + $this->server = $treffer[1]; + $this->supportOpenId1_1 = true; + } + + $treffer = array(); + preg_match('/rel="openid2.provider"\s+href="(\S+)"/',$seite,$treffer); + if ( count($treffer) >= 1 ) + { + $this->supportOpenId2_0 = true; + $this->server = $treffer[1]; + } + + $treffer = array(); + preg_match('/rel="openid.delegate"\s+href="(\S+)"/',$seite,$treffer); + if ( count($treffer) >= 1 ) + $this->identity = $treffer[1]; + } + + + /** + * Ermittelt den Hostnamen aus der Identity. + * + * @return String + */ + public function getUserFromIdentiy() + { + if ( $this->provider == 'identity' ) + { + $http = new Http($this->identity); + return $http->url['host']; + } + else + { + $attribute_name = config('security','openid','provider.'.$this->provider.'.map_attribute'); + return $this->info[$attribute_name]; + } + } + + + /** + * Open-Id Login, �berpr�fen der Anmeldung.<br> + * Spezifikation: http://openid.net/specs/openid-authentication-1_1.html<br> + * Kapitel "4.4. check_authentication"<br> + * <br> + * Im 2. Schritt (Mode "id_res") erfolgte ein Redirect vom Open-Id Provider an OpenRat zur�ck.<br> + * Wir befinden uns nun im darauf folgenden Request des Browsers.<br> + * <br> + * Es muss noch beim OpenId-Provider die Best�tigung eingeholt werden, danach ist der + * Benutzer angemeldet.<br> + */ + public function checkAuthentication() + { + $queryVars = $this->getQueryParamList(); + + if ( $queryVars['openid.invalidate_handle'] != $this->handle ) + { + Http::notAuthorized('Association-Handle mismatch.'); + die(); + $this->error = 'Association-Handle mismatch.'; + return false; + } + + if ( $queryVars['openid.mode'] != 'id_res' ) + { + Http::notAuthorized('Open-Id: Unknown mode:'.$queryVars['openid.mode']); + die(); + + $this->error ='Open-Id: Unknown mode:'.$queryVars['openid.mode']; + return false; + } + + if ( $this->provider=='identity' && $queryVars['openid.identity'] != $this->identity ) + { + Http::notAuthorized('Open-Id: Identity mismatch. Wrong identity:'.$queryVars['openid.identity']); + die(); + + $this->error ='Open-Id: Identity mismatch. Wrong identity:'.$queryVars['openid.identity']; + return false; + } + + + $params = array(); + + if ( $this->supportAX ) + // Den Namespace-Prefix für AX (attribute exchange) herausfinden. + // Leider kann das ein anderer Prefix sein, als wir im Request verwendet haben. + foreach( $queryVars as $request_key=>$request_value ) + if ( substr($request_key,0,10)=='openid.ns.' && $request_value == 'http://openid.net/srv/ax/1.0' ) + $axPrefix = substr($request_key,10); + + foreach( $queryVars as $request_key=>$request_value ) + { + // Benutzer-Attribute ermitteln. + // Benutzer-Attribute über SREG ermitteln. + if ( $this->supportSREG && substr($request_key,0,12)=='openid.sreg.' ) + $this->info[ substr($request_key,12) ] = $request_value; + // Benutzer-Attribute über AX ermitteln. + elseif ( $this->supportAX && substr($request_key,0,14+strlen($axPrefix))=='openid.'.$axPrefix.'.value.' ) + $this->info[ substr($request_key,14+strlen($axPrefix)) ] = $request_value; + + // Alle OpenId-Parameter in den Check-Authentication-Request übertragen. + if ( substr($request_key,0,7)=='openid.' ) + $params['openid.'.substr($request_key,7) ] = $request_value; + } + $params['openid.mode'] = 'check_authentication'; + + $checkRequest = new Http($this->server); + + $checkRequest->method = 'POST'; // Spezifikation verlangt POST. + $checkRequest->header['Accept'] = 'text/plain'; + $checkRequest->requestParameter = $params; + + if ( ! $checkRequest->request() ) + { + // Der HTTP-Request ging in die Hose. + $this->error = $checkRequest->error; + return false; + } + //Html::debug($checkRequest); + + // Analyse der HTTP-Antwort, Parsen des BODYs. + // Die Anmeldung ist best�tigt, wenn im BODY die Zeile "is_valid:true" vorhanden ist. + // Siehe Spezifikation Kapitel 4.4.2 + $result = array(); + foreach( explode("\n",$checkRequest->body) as $line ) + { + $pair = explode(':',trim($line)); + if (count($pair)==2) + $result[strtolower($pair[0])] = strtolower($pair[1]); + } + + if ( !array_key_exists('is_valid',$result) ) + { + // Zeile nicht gefunden. + Http::notAuthorized('Undefined Open-Id response: "is_valid" expected, but not found'); + die(); + + $this->error = 'Undefined Open-Id response: "is_valid" expected, but not found'; + return false; + } + elseif ( $result['is_valid'] == 'true' ) + { + // Anmeldung wurde mit "is_valid:true" best�tigt. + return true; + } + else + { + // Bestaetigung wurde durch den OpenId-Provider abgelehnt. + Http::notAuthorized('Server refused login.'); + die(); + $this->error = 'Server refused login.'; + return false; + } + } + + + /** + * Liefert die Query-Parameter aus der aktuellen URL.<br> + * <br> + * PHP hat leider die sehr bescheuerte Angewohnheit, Punkte und Leerzeichen in Request-Variablen + * durch Unterstriche zu ersetzen. Diese Funktion liefert die GET-Parameter ohne diese Ersetzung. + * + * @return Parameter der aktuellen URL + */ + private function getQueryParamList() + { + // Quelle: php.net + $str = $_SERVER['QUERY_STRING']; + $op = array(); + $pairs = explode("&", $str); + foreach ($pairs as $pair) + { + list($k, $v) = array_map("urldecode", explode("=", $pair)); + $op[$k] = $v; + } + + return $op; + } + + +} + +?>+ \ No newline at end of file diff --git a/auth/PersonasAuth.class.php b/auth/PersonasAuth.class.php diff --git a/auth/include.inc.php b/auth/include.inc.php @@ -0,0 +1,12 @@ +<?php + +require_once( OR_AUTHCLASSES_DIR."Auth.class.".PHP_EXT ); +require_once( OR_AUTHCLASSES_DIR."DatabaseAuth.class.".PHP_EXT ); +require_once( OR_AUTHCLASSES_DIR."HttpAuth.class.".PHP_EXT ); +require_once( OR_AUTHCLASSES_DIR."IdentAuth.class.".PHP_EXT ); +require_once( OR_AUTHCLASSES_DIR."InternalAuth.class.".PHP_EXT ); +require_once( OR_AUTHCLASSES_DIR."LdapAuth.class.".PHP_EXT ); +require_once( OR_AUTHCLASSES_DIR."OpenIdAuth.class.".PHP_EXT ); +require_once( OR_AUTHCLASSES_DIR."PersonasAuth.class.".PHP_EXT ); + +?>+ \ No newline at end of file diff --git a/init.php b/init.php @@ -67,11 +67,13 @@ define('REQ_PARAM_DATABASE_ID' ,'dbid' ); define('REQ_PARAM_TARGET' ,'target' ); define('OR_SERVICECLASSES_DIR','./util/' ); +define('OR_AUTHCLASSES_DIR' ,'./auth/' ); require_once( "functions/request.inc.php" ); // Werkzeugklassen einbinden. require_once( OR_SERVICECLASSES_DIR."include.inc.".PHP_EXT ); +require_once( OR_AUTHCLASSES_DIR."include.inc.".PHP_EXT ); // TODO: Muss aus Datenbank kommen! $charset = 'US-ASCII'; diff --git a/util/OpenId.class.php b/util/OpenId.class.php @@ -1,494 +0,0 @@ -<?php -// OpenRat Content Management System -// Copyright (C) 2002-2012 Jan Dankert, cms@jandankert.de -// -// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -/** - * Open-Id Authentisierung gem�� OpenId-Spezifikation 1.0. - * - */ -class OpenId -{ - /** - * Open-Id Server, an den die Authentisierungsanfrage gestellt wird. - * - * @var String - */ - var $server; - - - /** - * Informationen zum Benutzer. - * - * @var Array - */ - var $info; - - /** - * Open-Id Identity. - * - * @var String - */ - var $identity; - - /** - * Fehlermeldung (falls vorhanden). - * - * @var String - */ - var $error; - - /** - * OpenId-Benutzername. - * - * @var String - */ - var $user; - - /** - * OpenId-Provider. - * - * @var String - */ - var $provider; - - - var $supportAX; - var $supportSREG; - var $supportOpenId1_1; - var $supportOpenId2_0; - - - /** - * Neue Open-Id Anfrage. - * - * @param String $user - * @return OpenId - */ - function OpenId( $provider='',$user='' ) - { - $this->provider = $provider; - $this->user = $user; - } - - - /** - * Stellt fest, ob der Server vertrauenswuerdig ist. - * - * @return true, wenn vertrauenswuerdig. - */ - function serverOk() - { - global $conf; - $servers = $conf['security']['openid']['trusted_server']; - - if ( empty($servers) ) - { - return true; - } - else - { - $serverList = explode(',',$servers); - - $http = new Http($this->server); - if ( !in_array($http->url['host'],$serverList) ) - { - $this->error = 'Server '.$this->server.' is not trusted'; - return false; - } - else - return true; - } - - } - - - - /** - * Authentisierung Schritt 1.<br> - * Ermitteln der Identity. - * - * @return boolean TRUE, wenn Identity ermittelt wurde. - */ - function login() - { - if ( $this->provider != 'identity' ) - { - $this->user = config('security','openid','provider.'.$this->provider.'.xrds_uri'); - $this->identity = 'http://specs.openid.net/auth/2.0/identifier_select'; - } - $this->supportSREG = config('security','openid','provider.'.$this->provider.'.sreg_1_0'); - $this->supportAX = config('security','openid','provider.'.$this->provider.'.ax_1_0' ); - - // Schritt 1: Identity aus Yadis-Dokument laden. - $this->getIdentityFromYadis(); - - // Schritt 2: Fallback auf HTML-Dokument. - if ( empty($this->server) ) - { - $this->getIdentityFromHtmlMetaData(); - } - - // Falls immer noch kein Servername gefunden wurde, dann Abbruch. - if ( empty($this->server) ) - { - if ( empty($this->error) ) - $this->error = 'Unable to locate OpenId-Server in URL'; - return false; - } - - if ( !$this->serverOk() ) - return false; // Server nicht vertrauenswuerdig. - - if ( empty($this->identity) ) - // Falls die Identity bis hierher nicht deligiert wurde... - // Lt. Spezifikation mit Prefix "http://". - $this->identity = 'http://'.$this->user; - - return true; - } - - - - /** - * Erzeugt einen HTTP-Redirect auf den OpenId-Provider. - */ - public function getRedirectUrl() - { - global $conf; - - $this->handle = md5(microtime().session_id()); - - $redirHttp = new Http($this->server); - - if ( $this->supportOpenId2_0 ) - $redirHttp->requestParameter['openid.ns' ] = 'http://specs.openid.net/auth/2.0'; - - $redirHttp->requestParameter['openid.mode' ] = 'checkid_setup'; - $redirHttp->requestParameter['openid.identity' ] = $this->identity; - - if ( $this->supportOpenId2_0 ) - $redirHttp->requestParameter['openid.claimed_id'] = $this->identity; - - - // Profilangaben anfordern. E-Mail wird ben�tigt, Name und Sprache sind optional. - - if ( $this->supportAX ) - { - Logger::info("OpenId-Server is using OpenID Attribute Exchange 1.0"); - $redirHttp->requestParameter['openid.ns.ax' ] = 'http://openid.net/srv/ax/1.0'; - $redirHttp->requestParameter['openid.ax.mode' ] = 'fetch_request'; - $redirHttp->requestParameter['openid.ax.type.email' ] = 'http://axschema.org/contact/email'; - $redirHttp->requestParameter['openid.ax.type.username' ] = 'http://axschema.org/namePerson/friendly'; - $redirHttp->requestParameter['openid.ax.type.fullname' ] = 'http://axschema.org/namePerson'; - $redirHttp->requestParameter['openid.ax.type.language' ] = 'http://axschema.org/pref/language'; - $redirHttp->requestParameter['openid.ax.required' ] = 'username,email'; - $redirHttp->requestParameter['openid.ax.if_available' ] = 'language,fullname'; - } - - if ( $this->supportSREG ) - { - Logger::info("OpenId-Server is using OpenID Simple Registration Extension 1.0"); - $redirHttp->requestParameter['openid.ns.sreg' ] = 'http://openid.net/sreg/1.0'; - $redirHttp->requestParameter['openid.sreg.required'] = 'email,nickname'; - $redirHttp->requestParameter['openid.sreg.optional'] = 'fullname,language'; - } - - $trustRoot = @$conf['security']['openid']['trust_root']; - $server = Http::getServer(); - if ( empty($trustRoot) ) - $trustRoot = $server; - - $redirHttp->requestParameter['openid.trust_root' ] = slashify($trustRoot); - $redirHttp->requestParameter['openid.return_to' ] = slashify($server).'openid.'.PHP_EXT; - //$redirHttp->requestParameter['openid.realm' ] = slashify($server).'openid.'.PHP_EXT; - $redirHttp->requestParameter['openid.assoc_handle' ] = $this->handle; - - return $redirHttp->getUrl(); - } - - - - /** - * Ermittelt OpenId-Server und OpenId-Identity aus Yadis-Dokument.<br> - * - * @return unknown - */ - private function getIdentityFromYadis() - { - $http = new Http($this->user); -// $http->url['host'] = $this->user; - - $http->header[] = 'Accept: application/xrds+xml'; - if ( ! $http->request() ) - { - $this->error = 'Unable to get XML delegate information'; - return false; - } - - Logger::debug("OpenId: Found YADIS-document for ".$http->getUrl()); - //die(); - $p = xml_parser_create(); - $ok = xml_parse_into_struct($p, $http->body, $vals, $index); - xml_parser_free($p); - - foreach( $vals as $tag ) - { - if ( strtolower($tag['tag']) == 'type' ) - { - if ( $tag['value'] == 'http://openid.net/srv/ax/1.0' ) - $this->supportAX = true; - - if ( $tag['value'] == 'http://openid.net/sreg/1.0' ) - $this->supportSREG = true; - - if ( $tag['value'] == 'http://openid.net/signon/1.1' ) - $this->supportOpenId1_1 = true; - - if ( $tag['value'] == 'http://specs.openid.net/auth/2.0/server' ) - $this->supportOpenId2_0 = true; - } - - if ( strtolower($tag['tag']) == 'uri' ) - { - $this->server = $tag['value']; - } - - if ( strtolower($tag['tag']) == 'openid:delegate' ) - { - $this->identity = $tag['value']; - } - } - - if ( !$this->supportOpenId1_1 && !$this->supportOpenId2_0 ) - { - $this->error = 'Only OpenId 1.1 and 2.0 is supported but this identity-provider does not seem to support any of these.'; - return false; - } - if ( !$this->supportAX && !$this->supportSREG ) - { - $this->error = 'The identity-provider must support either Attribute-Exchange (AX) oder Simple-Registration (SREG), but it does not seem to support any of these.'; - return false; - } - } - - - /** - * Ermittelt OpenId-Server und OpenId-Identity aus HTML Meta-Tags.<br> - */ - private function getIdentityFromHtmlMetaData() - { - $http = new Http($this->user); -// $http = new Http(); -// $http->url['host'] = $this->user; - $http->header[] = 'Accept: text/html'; - - if ( ! $http->request() ) - { - $this->error = 'Unable to get HTML delegate information'; - return false; - } - - $seite = $http->body; - - // Die Meta-Tags mit regulaerem Ausdruck auslesen. - $treffer = array(); - preg_match('/rel="openid.server"\s+href="(\S+)"/',$seite,$treffer); - if ( count($treffer) >= 1 ) - { - $this->server = $treffer[1]; - $this->supportOpenId1_1 = true; - } - - $treffer = array(); - preg_match('/rel="openid2.provider"\s+href="(\S+)"/',$seite,$treffer); - if ( count($treffer) >= 1 ) - { - $this->supportOpenId2_0 = true; - $this->server = $treffer[1]; - } - - $treffer = array(); - preg_match('/rel="openid.delegate"\s+href="(\S+)"/',$seite,$treffer); - if ( count($treffer) >= 1 ) - $this->identity = $treffer[1]; - } - - - /** - * Ermittelt den Hostnamen aus der Identity. - * - * @return String - */ - public function getUserFromIdentiy() - { - if ( $this->provider == 'identity' ) - { - $http = new Http($this->identity); - return $http->url['host']; - } - else - { - $attribute_name = config('security','openid','provider.'.$this->provider.'.map_attribute'); - return $this->info[$attribute_name]; - } - } - - - /** - * Open-Id Login, �berpr�fen der Anmeldung.<br> - * Spezifikation: http://openid.net/specs/openid-authentication-1_1.html<br> - * Kapitel "4.4. check_authentication"<br> - * <br> - * Im 2. Schritt (Mode "id_res") erfolgte ein Redirect vom Open-Id Provider an OpenRat zur�ck.<br> - * Wir befinden uns nun im darauf folgenden Request des Browsers.<br> - * <br> - * Es muss noch beim OpenId-Provider die Best�tigung eingeholt werden, danach ist der - * Benutzer angemeldet.<br> - */ - public function checkAuthentication() - { - $queryVars = $this->getQueryParamList(); - - if ( $queryVars['openid.invalidate_handle'] != $this->handle ) - { - Http::notAuthorized('Association-Handle mismatch.'); - die(); - $this->error = 'Association-Handle mismatch.'; - return false; - } - - if ( $queryVars['openid.mode'] != 'id_res' ) - { - Http::notAuthorized('Open-Id: Unknown mode:'.$queryVars['openid.mode']); - die(); - - $this->error ='Open-Id: Unknown mode:'.$queryVars['openid.mode']; - return false; - } - - if ( $this->provider=='identity' && $queryVars['openid.identity'] != $this->identity ) - { - Http::notAuthorized('Open-Id: Identity mismatch. Wrong identity:'.$queryVars['openid.identity']); - die(); - - $this->error ='Open-Id: Identity mismatch. Wrong identity:'.$queryVars['openid.identity']; - return false; - } - - - $params = array(); - - if ( $this->supportAX ) - // Den Namespace-Prefix für AX (attribute exchange) herausfinden. - // Leider kann das ein anderer Prefix sein, als wir im Request verwendet haben. - foreach( $queryVars as $request_key=>$request_value ) - if ( substr($request_key,0,10)=='openid.ns.' && $request_value == 'http://openid.net/srv/ax/1.0' ) - $axPrefix = substr($request_key,10); - - foreach( $queryVars as $request_key=>$request_value ) - { - // Benutzer-Attribute ermitteln. - // Benutzer-Attribute über SREG ermitteln. - if ( $this->supportSREG && substr($request_key,0,12)=='openid.sreg.' ) - $this->info[ substr($request_key,12) ] = $request_value; - // Benutzer-Attribute über AX ermitteln. - elseif ( $this->supportAX && substr($request_key,0,14+strlen($axPrefix))=='openid.'.$axPrefix.'.value.' ) - $this->info[ substr($request_key,14+strlen($axPrefix)) ] = $request_value; - - // Alle OpenId-Parameter in den Check-Authentication-Request übertragen. - if ( substr($request_key,0,7)=='openid.' ) - $params['openid.'.substr($request_key,7) ] = $request_value; - } - $params['openid.mode'] = 'check_authentication'; - - $checkRequest = new Http($this->server); - - $checkRequest->method = 'POST'; // Spezifikation verlangt POST. - $checkRequest->header['Accept'] = 'text/plain'; - $checkRequest->requestParameter = $params; - - if ( ! $checkRequest->request() ) - { - // Der HTTP-Request ging in die Hose. - $this->error = $checkRequest->error; - return false; - } - //Html::debug($checkRequest); - - // Analyse der HTTP-Antwort, Parsen des BODYs. - // Die Anmeldung ist best�tigt, wenn im BODY die Zeile "is_valid:true" vorhanden ist. - // Siehe Spezifikation Kapitel 4.4.2 - $result = array(); - foreach( explode("\n",$checkRequest->body) as $line ) - { - $pair = explode(':',trim($line)); - if (count($pair)==2) - $result[strtolower($pair[0])] = strtolower($pair[1]); - } - - if ( !array_key_exists('is_valid',$result) ) - { - // Zeile nicht gefunden. - Http::notAuthorized('Undefined Open-Id response: "is_valid" expected, but not found'); - die(); - - $this->error = 'Undefined Open-Id response: "is_valid" expected, but not found'; - return false; - } - elseif ( $result['is_valid'] == 'true' ) - { - // Anmeldung wurde mit "is_valid:true" best�tigt. - return true; - } - else - { - // Bestaetigung wurde durch den OpenId-Provider abgelehnt. - Http::notAuthorized('Server refused login.'); - die(); - $this->error = 'Server refused login.'; - return false; - } - } - - - /** - * Liefert die Query-Parameter aus der aktuellen URL.<br> - * <br> - * PHP hat leider die sehr bescheuerte Angewohnheit, Punkte und Leerzeichen in Request-Variablen - * durch Unterstriche zu ersetzen. Diese Funktion liefert die GET-Parameter ohne diese Ersetzung. - * - * @return Parameter der aktuellen URL - */ - private function getQueryParamList() - { - // Quelle: php.net - $str = $_SERVER['QUERY_STRING']; - $op = array(); - $pairs = explode("&", $str); - foreach ($pairs as $pair) - { - list($k, $v) = array_map("urldecode", explode("=", $pair)); - $op[$k] = $v; - } - - return $op; - } - - -} - -?>- \ No newline at end of file diff --git a/util/include.inc.php b/util/include.inc.php @@ -20,12 +20,6 @@ require_once( OR_SERVICECLASSES_DIR."JSON.class.".PHP_EXT ); require_once( OR_SERVICECLASSES_DIR."ProjectTree.class.".PHP_EXT ); } -// Login -//if ( !empty($REQ[REQ_PARAM_ACTION]) && in_array($REQ[REQ_PARAM_ACTION],array('index')) ) -{ - require_once( OR_SERVICECLASSES_DIR."OpenId.class.".PHP_EXT ); -} - // Veroeffentlichung //if ( !empty($REQ[REQ_PARAM_ACTION]) && in_array($REQ[REQ_PARAM_ACTION],array('file','page','pageelement','folder')) ) {