Subversion Repositories oidplus

Compare Revisions

Regard whitespace Rev 1283 → Rev 1282

/trunk/doc/developer_notes/server_secret.md
11,7 → 11,7
Derivation of secrets and auth keys
-----------------------------------
 
The usage of `OIDplus::baseConfig()->getValue("SERVER_SECRET")`
Important: The usage of `OIDplus::baseConfig()->getValue("SERVER_SECRET")`
is deprecated due to security considerations.
 
Instead, please always use `OIDplus::authUtils()->makeSecret()`
22,49 → 22,58
use `OIDplus::authUtils()->makeAuthKey()`
with a unique `$data` argument (prefer a GUID)
in combination with `OIDplus::authUtils()->validateAuthKey()`.
An auth key is usually temporary; therefore `makeAuthKey` encodes a timestamp
which can be checked by `validateAuthKey` by providing
a validity period in seconds.
This auth key is NOT temporary by default so you need to make sure
that you encode a timestamp in it.
 
Implementation
--------------
 
`makeAuthKey(data) = makeSecret(data) = sha3_512_hmac(data, "OIDplus:" + SERVER_SECRET)`
 
Currently, the implementation of `makeAuthKey` and `makeSecret`
is the same, but you should only use `makeAuthKey`
if you combine it with `validateAuthKey`, otherwise, you
should use `makeSecret`. This makes the code easier to understand.
 
Where are makeAuthKey and makeSecret being used?
------------------------------------------------
 
System / Core:
- Auth content Store (OIDplusAuthContentStoreJWT.class.php):
Key to sign JWT tokens (used for Automated AJAX requests, REST API and logins with "Remember me")
Key to sign JWT tokens (used for Automated AJAX requests, REST API and logins with "Remember me") using PBKDF2+HMAC
* If a private/public key pair exists: Sign the JWT using that private key.
* Otherwise sign it using PBKDF2+HMAC:
`JWT = HS512(hash_pbkdf2("sha512", OIDplus::authUtils()->makeSecret(["0be35e52-f4ef-11ed-b67e-3c4a92df8582"]), "", 10000, 64/*256bit*/, false))`
* Otherwise sign it with:
`JWT = HS512(hash_pbkdf2("sha512", OIDplus::authUtils()->makeSecret("0be35e52-f4ef-11ed-b67e-3c4a92df8582"), "", 10000, 64/*256bit*/, false))`
- Session Handler (OIDplusSessionHandler.class.php):
Encryption of session contents (regular logins)
* if OpenSSL is installed: sha512-pbkdf2 + AES-256-CBC + sha3-512-hmac
* if OpenSSL is not installed: sha3-512-hmac
* In both cases, the key is `OIDplus::authUtils()->makeSecret(["b118abc8-f4ec-11ed-86ca-3c4a92df8582"])`.
* In both cases, the key is `OIDplus::authUtils()->makeSecret("b118abc8-f4ec-11ed-86ca-3c4a92df8582")`.
 
Temporary auth keys (sent via email etc.):
* used at plugin forgot RA password (public/091):
`makeAuthKey(["93a16dbe-f4fb-11ed-b67e-3c4a92df8582", email])`
`makeAuthKey("93a16dbe-f4fb-11ed-b67e-3c4a92df8582:" + email + "/" + timestamp)`
* used at plugin ViaThinkSoft FreeOID activation (public/200):
`makeAuthKey(["40c87e20-f4fb-11ed-86ca-3c4a92df8582", email])`
`makeAuthKey("40c87e20-f4fb-11ed-86ca-3c4a92df8582:" + email + "/" + timestamp)`
* used at plugin invite RA (ra/092):
`makeAuthKey(["ed840c3e-f4fa-11ed-b67e-3c4a92df8582", email])`
`makeAuthKey("ed840c3e-f4fa-11ed-b67e-3c4a92df8582:" + email + "/" + timestamp)`
* used at plugin change RA email (ra/102):
`makeAuthKey(["5ef24124-f4fb-11ed-b67e-3c4a92df8582", old_email, new_email])`
`makeAuthKey("5ef24124-f4fb-11ed-b67e-3c4a92df8582:" + old_email + "/" + new_email + "/" + timestamp)`
 
Plugin OID-IP (public/100):
- Authentication token for hidden OIDs = `smallhash(OIDplus::authUtils()->makeSecret(["d8f44c7c-f4e9-11ed-86ca-3c4a92df8582", id]))`
- Authentication token for hidden OIDs = `smallhash(OIDplus::authUtils()->makeSecret("d8f44c7c-f4e9-11ed-86ca-3c4a92df8582:" + id))`
 
Plugin VNag version check (admin/901):
- Webreader password = `OIDplus::authUtils()->makeSecret(["65d9f488-f4eb-11ed-b67e-3c4a92df8582"])`
- Webreader password = `OIDplus::authUtils()->makeSecret("65d9f488-f4eb-11ed-b67e-3c4a92df8582")`
 
Plugin RDAP (frdl):
- `OIDplus::authUtils()->makeSecret(["cee75760-f4f8-11ed-b67e-3c4a92df8582"])` is used to generate a cache filename
- `OIDplus::authUtils()->makeSecret("cee75760-f4f8-11ed-b67e-3c4a92df8582")` is used to generate a cache filename
 
Plugin VTS Client Challenge Captcha:
- Challenge integrity : `OIDplus::authUtils()->makeAuthKey(["797bfc34-f4fa-11ed-86ca-3c4a92df8582", challenge])`
- Cache filename : `"vts_client_challenge_" + OIDplus::authUtils()->makeSecret(["461f4a9e-f4fa-11ed-86ca-3c4a92df8582", ipTarget, random]) + ".tmp"`
- Challenge integrity : `OIDplus::authUtils()->makeAuthKey("797bfc34-f4fa-11ed-86ca-3c4a92df8582:" + challenge)`
- Cache filename : `"vts_client_challenge_" + OIDplus::authUtils()->makeSecret("461f4a9e-f4fa-11ed-86ca-3c4a92df8582:" + ipTarget + "/" + random) + ".tmp"`
 
GUID Registry
-------------
 
The "realm GUIDs" are documented at the [ViaThinkSoft OIDplus Registration Authority](https://oidplus.viathinksoft.com/oidplus/?goto=guid%3Aoidplus%2FauthRealms).
The "real GUIDs" are documented at the [ViaThinkSoft OIDplus Registration Authority](https://oidplus.viathinksoft.com/oidplus/?goto=guid%3Aoidplus%2FauthRealms).
/trunk/includes/classes/OIDplusAuthContentStoreJWT.class.php
414,7 → 414,7
$k = new \Firebase\JWT\Key($pubKey, 'RS256'); // RSA+SHA256 ist hardcoded in getPkiStatus() generation
$this->content = (array) \Firebase\JWT\JWT::decode($jwt, $k);
} else {
$key = OIDplus::authUtils()->makeSecret(['0be35e52-f4ef-11ed-b67e-3c4a92df8582']);
$key = OIDplus::authUtils()->makeSecret('0be35e52-f4ef-11ed-b67e-3c4a92df8582');
$key = hash_pbkdf2('sha512', $key, '', 10000, 32/*256bit*/, false);
$k = new \Firebase\JWT\Key($key, 'HS512'); // HMAC+SHA512 is hardcoded here
$this->content = (array) \Firebase\JWT\JWT::decode($jwt, $k);
436,7 → 436,7
$privKey = OIDplus::getSystemPrivateKey();
return \Firebase\JWT\JWT::encode($payload, $privKey, 'RS256'); // RSA+SHA256 ist hardcoded in getPkiStatus() generation
} else {
$key = OIDplus::authUtils()->makeSecret(['0be35e52-f4ef-11ed-b67e-3c4a92df8582']);
$key = OIDplus::authUtils()->makeSecret('0be35e52-f4ef-11ed-b67e-3c4a92df8582');
$key = hash_pbkdf2('sha512', $key, '', 10000, 32/*256bit*/, false);
return \Firebase\JWT\JWT::encode($payload, $key, 'HS512'); // HMAC+SHA512 is hardcoded here
}
/trunk/includes/classes/OIDplusAuthUtils.class.php
383,48 → 383,32
// Authentication keys for generating secrets or validating arguments (e.g. sent by mail)
 
/**
* @param array|string $data
* @param string $data
* @return string
* @throws OIDplusException
*/
public function makeSecret($data): string {
if (!is_array($data)) $data = [$data];
$data = json_encode($data);
public function makeSecret(string $data): string {
return sha3_512_hmac($data, 'OIDplus:'.OIDplus::baseConfig()->getValue('SERVER_SECRET'), false);
}
 
/**
* @param array|string $data Arbitary data to be validated later
* @return string A string that need to be validated with validateAuthKey
* @param string $data
* @return string
* @throws OIDplusException
*/
public function makeAuthKey($data): string {
if (!is_array($data)) $data = [$data];
$ts = time();
$data_ext = [$ts, $data];
$secret = $this->makeSecret($data_ext);
return $ts.'.'.$secret;
public function makeAuthKey(string $data): string {
return $this->makeSecret($data);
}
 
/**
* @param array|string $data The original data that had been passed to makeAuthKey()
* @param string $auth_key The result from makeAuthKey()
* @param int $valid_secs How many seconds is the auth key valid? (-1 for infinite)
* @return bool True if the key is valid and not expired.
* @param string $data
* @param string $auth_key
* @return bool
* @throws OIDplusException
*/
public function validateAuthKey($data, string $auth_key, int $valid_secs=-1): bool {
$auth_key_ary = explode('.', $auth_key, 2);
if (count($auth_key_ary) != 2) return false; // invalid auth key syntax
list($ts, $secret) = $auth_key_ary;
if (!is_numeric($ts)) return false; // invalid auth key syntax
if ($valid_secs >= 0) {
if (time() > ($ts+$valid_secs)) return false; // expired auth key
public function validateAuthKey(string $data, string $auth_key): bool {
return hash_equals($this->makeAuthKey($data), $auth_key);
}
if (!is_array($data)) $data = [$data];
$data_ext = [(int)$ts, $data];
return hash_equals($this->makeSecret($data_ext), $secret);
}
 
// "Veto" functions to force logout state
 
/trunk/includes/classes/OIDplusSessionHandler.class.php
40,7 → 40,7
*/
public function __construct() {
$this->sessionLifetime = OIDplus::baseConfig()->getValue('SESSION_LIFETIME', 30*60);
$this->secret = OIDplus::authUtils()->makeSecret(['b118abc8-f4ec-11ed-86ca-3c4a92df8582']);
$this->secret = OIDplus::authUtils()->makeSecret('b118abc8-f4ec-11ed-86ca-3c4a92df8582');
 
// **PREVENTING SESSION HIJACKING**
// Prevents javascript XSS attacks aimed to steal the session ID
/trunk/plugins/frdl/publicPages/1276945_rdap/OIDplusRDAP.class.php
81,7 → 81,7
$cacheFile = $this->rdapCacheDir. 'rdap_'
.sha1(\get_current_user()
. $this->rdapBaseUri.__FILE__.$query
.OIDplus::authUtils()->makeSecret(['cee75760-f4f8-11ed-b67e-3c4a92df8582'])
.OIDplus::authUtils()->makeSecret('cee75760-f4f8-11ed-b67e-3c4a92df8582')
)
.'.'
.strlen( $this->rdapBaseUri.$query )
/trunk/plugins/viathinksoft/adminPages/901_vnag_version_check/OIDplusPageAdminVNagVersionCheck.class.php
142,7 → 142,7
* @throws OIDplusException
*/
public static function vnag_password(): string {
return OIDplus::authUtils()->makeSecret(['65d9f488-f4eb-11ed-b67e-3c4a92df8582']);
return OIDplus::authUtils()->makeSecret('65d9f488-f4eb-11ed-b67e-3c4a92df8582');
}
 
}
/trunk/plugins/viathinksoft/captcha/vts_challenge/OIDplusCaptchaPluginVtsClientChallenge.class.php
65,7 → 65,7
$random = mt_rand($min,$max);
$ip_target = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
$challenge = sha3_512($starttime.'/'.$ip_target.'/'.$random); // $random is secret!
$challenge_integrity = OIDplus::authUtils()->makeAuthKey(['797bfc34-f4fa-11ed-86ca-3c4a92df8582',$challenge]);
$challenge_integrity = OIDplus::authUtils()->makeAuthKey('797bfc34-f4fa-11ed-86ca-3c4a92df8582:'.$challenge);
$send_to_client = array($starttime, $ip_target, $challenge, $min, $max, $challenge_integrity);
 
$open_trans_file = self::getOpenTransFileName($ip_target, $random);
102,7 → 102,7
@unlink($file);
}
 
return $dir.'/vts_client_challenge_'.OIDplus::authUtils()->makeSecret(['461f4a9e-f4fa-11ed-86ca-3c4a92df8582',$ip_target,$random]).'.tmp';
return $dir.'/vts_client_challenge_'.OIDplus::authUtils()->makeSecret('461f4a9e-f4fa-11ed-86ca-3c4a92df8582:'.$ip_target.'/'.$random).'.tmp';
}
 
/**
149,10 → 149,10
$current_ip = ($_SERVER['REMOTE_ADDR'] ?? 'unknown');
if ($ip_target != $current_ip) {
throw new OIDplusException(_L('IP address has changed. Please try again. (current IP %1, expected %2)', $current_ip, $ip_target));
//} else if (time()-$starttime > OIDplus::baseConfig()->getValue('VTS_CAPTCHA_MAXTIME', 10*60/*10 minutes*/)) {
// throw new OIDplusException(_L('Challenge expired. Please try again.'));
} else if (!OIDplus::authUtils()->validateAuthKey(['797bfc34-f4fa-11ed-86ca-3c4a92df8582',$challenge],$challenge_integrity,OIDplus::baseConfig()->getValue('VTS_CAPTCHA_MAXTIME', 10*60/*10 minutes*/))) {
throw new OIDplusException(_L('Invalid or expired authentication key'));
} else if (time()-$starttime > OIDplus::baseConfig()->getValue('VTS_CAPTCHA_MAXTIME', 10*60/*10 minutes*/)) {
throw new OIDplusException(_L('Challenge expired. Please try again.'));
} else if (!OIDplus::authUtils()->validateAuthKey('797bfc34-f4fa-11ed-86ca-3c4a92df8582:'.$challenge, $challenge_integrity)) {
throw new OIDplusException(_L('Challenge integrity failed'));
} else if ($challenge !== sha3_512($starttime.'/'.$ip_target.'/'.$answer)) {
throw new OIDplusException(_L('Wrong answer'));
} else if (!file_exists($open_trans_file)) {
/trunk/plugins/viathinksoft/language/dede/messages.xml
382,6 → 382,14
</message>
<message>
<source><![CDATA[
Activation link expired!
]]></source>
<target><![CDATA[
Aktivierungs-Link ist abgelaufen!
]]></target>
</message>
<message>
<source><![CDATA[
Add a file attachment
]]></source>
<target><![CDATA[
1150,6 → 1158,22
</message>
<message>
<source><![CDATA[
Challenge expired. Please try again.
]]></source>
<target><![CDATA[
Challenge abgelaufen. Bitte noch einmal versuchen.
]]></target>
</message>
<message>
<source><![CDATA[
Challenge integrity failed
]]></source>
<target><![CDATA[
Challenge ist möglicherweise manipuliert worden
]]></target>
</message>
<message>
<source><![CDATA[
Challenge response is invalid
]]></source>
<target><![CDATA[
3414,6 → 3438,14
</message>
<message>
<source><![CDATA[
Invalid auth key
]]></source>
<target><![CDATA[
Ungültiger Authentifizierungs-Schlüssel
]]></target>
</message>
<message>
<source><![CDATA[
Invalid auth plugin name. It is usually the folder name, without path, e.g. "%1"
]]></source>
<target><![CDATA[
3486,14 → 3518,6
</message>
<message>
<source><![CDATA[
Invalid or expired authentication key
]]></source>
<target><![CDATA[
Ungültiger oder abgelaufener Sicherheitsschlüssel
]]></target>
</message>
<message>
<source><![CDATA[
Invalid protection flag, use OIDplusConfig::PROTECTION_* constants
]]></source>
<target><![CDATA[
3526,6 → 3550,14
</message>
<message>
<source><![CDATA[
Invitation expired!
]]></source>
<target><![CDATA[
Einladung abgelaufen!
]]></target>
</message>
<message>
<source><![CDATA[
Invitations are disabled by the administrator.
]]></source>
<target><![CDATA[
/trunk/plugins/viathinksoft/publicPages/091_forgot_password/OIDplusPagePublicForgotPassword.class.php
45,7 → 45,8
 
OIDplus::logger()->log("V2:[WARN]RA(%1)", "A new password for '%1' was requested (forgot password)", $email);
 
$activate_url = OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL) . '?goto='.urlencode('oidplus:reset_password$'.$email.'$'.OIDplus::authUtils()->makeAuthKey(['93a16dbe-f4fb-11ed-b67e-3c4a92df8582',$email]));
$timestamp = time();
$activate_url = OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL) . '?goto='.urlencode('oidplus:reset_password$'.$email.'$'.$timestamp.'$'.OIDplus::authUtils()->makeAuthKey('93a16dbe-f4fb-11ed-b67e-3c4a92df8582:'.$email.'/'.$timestamp));
 
$message = $this->getForgotPasswordText($params['email']);
$message = str_replace('{{ACTIVATE_URL}}', $activate_url, $message);
60,16 → 61,22
_CheckParamExists($params, 'password2');
_CheckParamExists($params, 'email');
_CheckParamExists($params, 'auth');
_CheckParamExists($params, 'timestamp');
 
$password1 = $params['password1'];
$password2 = $params['password2'];
$email = $params['email'];
$auth = $params['auth'];
$timestamp = $params['timestamp'];
 
if (!OIDplus::authUtils()->validateAuthKey(['93a16dbe-f4fb-11ed-b67e-3c4a92df8582',$email], $auth, OIDplus::config()->getValue('max_ra_pwd_reset_time',-1))) {
throw new OIDplusException(_L('Invalid or expired authentication key'));
if (!OIDplus::authUtils()->validateAuthKey('93a16dbe-f4fb-11ed-b67e-3c4a92df8582:'.$email.'/'.$timestamp, $auth)) {
throw new OIDplusException(_L('Invalid auth key'));
}
 
if ((OIDplus::config()->getValue('max_ra_pwd_reset_time') > 0) && (time()-$timestamp > OIDplus::config()->getValue('max_ra_pwd_reset_time'))) {
throw new OIDplusException(_L('Invitation expired!'));
}
 
if ($password1 !== $password2) {
throw new OIDplusException(_L('Passwords do not match'));
}
136,12 → 143,13
$handled = true;
 
$email = explode('$',$id)[1];
$auth = explode('$',$id)[2];
$timestamp = explode('$',$id)[2];
$auth = explode('$',$id)[3];
 
$out['title'] = _L('Reset password');
$out['icon'] = OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/reset_password_icon.png';
 
if (!OIDplus::authUtils()->validateAuthKey(['93a16dbe-f4fb-11ed-b67e-3c4a92df8582',$email], $auth, OIDplus::config()->getValue('max_ra_pwd_reset_time',-1))) {
if (!OIDplus::authUtils()->validateAuthKey('reset_password;'.$email.';'.$timestamp, $auth)) {
throw new OIDplusException(_L('Invalid authorization. Is the URL OK?'), $out['title']);
} else {
$out['text'] = '<p>'._L('E-Mail-Address: %1','<b>'.$email.'</b>').'</p>
148,6 → 156,7
 
<form id="resetPasswordForm" action="javascript:void(0);" onsubmit="return OIDplusPagePublicForgotPassword.resetPasswordFormOnSubmit();">
<input type="hidden" id="email" value="'.htmlentities($email).'"/>
<input type="hidden" id="timestamp" value="'.htmlentities($timestamp).'"/>
<input type="hidden" id="auth" value="'.htmlentities($auth).'"/>
<div><label class="padding_label">'._L('New password').':</label><input type="password" id="password1" value=""/></div>
<div><label class="padding_label">'._L('Repeat').':</label><input type="password" id="password2" value=""/></div>
/trunk/plugins/viathinksoft/publicPages/100_whois/OIDplusPagePublicWhois.class.php
233,6 → 233,6
* @throws OIDplusException
*/
public static function genWhoisAuthToken(string $id): int {
return smallhash(OIDplus::authUtils()->makeSecret(['d8f44c7c-f4e9-11ed-86ca-3c4a92df8582',$id]));
return smallhash(OIDplus::authUtils()->makeSecret('d8f44c7c-f4e9-11ed-86ca-3c4a92df8582:'.$id));
}
}
/trunk/plugins/viathinksoft/publicPages/200_viathinksoft_freeoid/OIDplusPagePublicFreeOID.class.php
81,7 → 81,8
$root_oid = self::getFreeRootOid(false);
OIDplus::logger()->log("V2:[INFO]OID(oid:%1)+RA(%2)", "Requested a free OID for email '%2' to be placed into root '%1'", $root_oid, $email);
 
$activate_url = OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL) . '?goto='.urlencode('oidplus:com.viathinksoft.freeoid.activate_freeoid$'.$email.'$'.OIDplus::authUtils()->makeAuthKey(['40c87e20-f4fb-11ed-86ca-3c4a92df8582',$email]));
$timestamp = time();
$activate_url = OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL) . '?goto='.urlencode('oidplus:com.viathinksoft.freeoid.activate_freeoid$'.$email.'$'.$timestamp.'$'.OIDplus::authUtils()->makeAuthKey('40c87e20-f4fb-11ed-86ca-3c4a92df8582:'.$email.'/'.$timestamp));
 
$message = file_get_contents(__DIR__ . '/request_msg.tpl');
$message = str_replace('{{SYSTEM_URL}}', OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL), $message);
96,14 → 97,20
} else if ($actionID == 'activate_freeoid') {
_CheckParamExists($params, 'email');
_CheckParamExists($params, 'auth');
_CheckParamExists($params, 'timestamp');
 
$email = $params['email'];
$auth = $params['auth'];
$timestamp = $params['timestamp'];
 
if (!OIDplus::authUtils()->validateAuthKey(['40c87e20-f4fb-11ed-86ca-3c4a92df8582',$email], $auth, OIDplus::config()->getValue('max_ra_invite_time', -1))) {
throw new OIDplusException(_L('Invalid or expired authentication key'));
if (!OIDplus::authUtils()->validateAuthKey('40c87e20-f4fb-11ed-86ca-3c4a92df8582:'.$email.'/'.$timestamp, $auth)) {
throw new OIDplusException(_L('Invalid auth key'));
}
 
if ((OIDplus::config()->getValue('max_ra_invite_time') > 0) && (time()-$timestamp > OIDplus::config()->getValue('max_ra_invite_time'))) {
throw new OIDplusException(_L('Invitation expired!'));
}
 
// 1. step: Check entered data and add the RA to the database
 
$ra = new OIDplusRA($email);
279,7 → 286,8
$handled = true;
 
$email = explode('$',$id)[1];
$auth = explode('$',$id)[2];
$timestamp = explode('$',$id)[2];
$auth = explode('$',$id)[3];
 
$out['title'] = _L('Activate Free OID');
$out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : '';
287,7 → 295,7
if ($already_registered_oid = $this->alreadyHasFreeOid($email, true)) {
throw new OIDplusHtmlException(_L('This email address already has a FreeOID registered (%1)', '<a '.OIDplus::gui()->link($already_registered_oid).'>'.htmlentities($already_registered_oid).'</a>'));
} else {
if (!OIDplus::authUtils()->validateAuthKey(['40c87e20-f4fb-11ed-86ca-3c4a92df8582',$email], $auth, OIDplus::config()->getValue('max_ra_invite_time', -1))) {
if (!OIDplus::authUtils()->validateAuthKey('com.viathinksoft.freeoid.activate_freeoid;'.$email.';'.$timestamp, $auth)) {
throw new OIDplusException(_L('Invalid authorization. Is the URL OK?'), $out['title']);
} else {
$ra = new OIDplusRA($email);
297,6 → 305,7
 
$out['text'] .= ' <form id="activateFreeOIDForm" action="javascript:void(0);" onsubmit="return OIDplusPagePublicFreeOID.activateFreeOIDFormOnSubmit();">';
$out['text'] .= ' <input type="hidden" id="email" value="'.htmlentities($email).'"/>';
$out['text'] .= ' <input type="hidden" id="timestamp" value="'.htmlentities($timestamp).'"/>';
$out['text'] .= ' <input type="hidden" id="auth" value="'.htmlentities($auth).'"/>';
 
if ($ra_existing) {
/trunk/plugins/viathinksoft/raPages/092_invite/OIDplusPageRaInvite.class.php
46,7 → 46,8
// TODO: should we also log who has invited?
OIDplus::logger()->log("V2:[INFO]RA(%1)", "RA '%1' has been invited", $email);
 
$activate_url = OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL) . '?goto='.urlencode('oidplus:activate_ra$'.$email.'$'.OIDplus::authUtils()->makeAuthKey(['ed840c3e-f4fa-11ed-b67e-3c4a92df8582',$email]));
$timestamp = time();
$activate_url = OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL) . '?goto='.urlencode('oidplus:activate_ra$'.$email.'$'.$timestamp.'$'.OIDplus::authUtils()->makeAuthKey('ed840c3e-f4fa-11ed-b67e-3c4a92df8582:'.$email.'/'.$timestamp));
 
$message = $this->getInvitationText($email);
$message = str_replace('{{ACTIVATE_URL}}', $activate_url, $message);
61,16 → 62,22
_CheckParamExists($params, 'password2');
_CheckParamExists($params, 'email');
_CheckParamExists($params, 'auth');
_CheckParamExists($params, 'timestamp');
 
$password1 = $params['password1'];
$password2 = $params['password2'];
$email = $params['email'];
$auth = $params['auth'];
$timestamp = $params['timestamp'];
 
if (!OIDplus::authUtils()->validateAuthKey(['ed840c3e-f4fa-11ed-b67e-3c4a92df8582',$email], $auth, OIDplus::config()->getValue('max_ra_invite_time',-1))) {
throw new OIDplusException(_L('Invalid or expired authentication key'));
if (!OIDplus::authUtils()->validateAuthKey('ed840c3e-f4fa-11ed-b67e-3c4a92df8582:'.$email.'/'.$timestamp, $auth)) {
throw new OIDplusException(_L('Invalid auth key'));
}
 
if ((OIDplus::config()->getValue('max_ra_invite_time') > 0) && (time()-$timestamp > OIDplus::config()->getValue('max_ra_invite_time'))) {
throw new OIDplusException(_L('Invitation expired!'));
}
 
if ($password1 !== $password2) {
throw new OIDplusException(_L('Passwords do not match'));
}
154,7 → 161,8
$handled = true;
 
$email = explode('$',$id)[1];
$auth = explode('$',$id)[2];
$timestamp = explode('$',$id)[2];
$auth = explode('$',$id)[3];
 
$out['title'] = _L('Register as Registration Authority');
 
168,7 → 176,7
if ($res->any()) {
$out['text'] = _L('This RA is already registered and does not need to be invited.');
} else {
if (!OIDplus::authUtils()->validateAuthKey(['ed840c3e-f4fa-11ed-b67e-3c4a92df8582',$email], $auth, OIDplus::config()->getValue('max_ra_invite_time',-1))) {
if (!OIDplus::authUtils()->validateAuthKey('activate_ra;'.$email.';'.$timestamp, $auth)) {
throw new OIDplusException(_L('Invalid authorization. Is the URL OK?'), $out['title']);
} else {
// TODO: like in the FreeOID plugin, we could ask here at least for a name for the RA
176,6 → 184,7
 
<form id="activateRaForm" action="javascript:void(0);" onsubmit="return OIDplusPageRaInvite.activateRaFormOnSubmit();">
<input type="hidden" id="email" value="'.htmlentities($email).'"/>
<input type="hidden" id="timestamp" value="'.htmlentities($timestamp).'"/>
<input type="hidden" id="auth" value="'.htmlentities($auth).'"/>
<div><label class="padding_label">'._L('New password').':</label><input type="password" id="password1" value=""/></div>
<div><label class="padding_label">'._L('Repeat').':</label><input type="password" id="password2" value=""/></div>
/trunk/plugins/viathinksoft/raPages/102_change_email/OIDplusPageRaChangeEMail.class.php
94,7 → 94,8
} else {
OIDplus::logger()->log("V2:[INFO]RA(%1)+RA(%2)", "Requested email address change from '%1' to '%2'", $old_email, $new_email);
 
$activate_url = OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL) . '?goto='.urlencode('oidplus:activate_new_ra_email$'.$old_email.'$'.$new_email.'$'.OIDplus::authUtils()->makeAuthKey(['5ef24124-f4fb-11ed-b67e-3c4a92df8582',$old_email,$new_email]));
$timestamp = time();
$activate_url = OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL) . '?goto='.urlencode('oidplus:activate_new_ra_email$'.$old_email.'$'.$new_email.'$'.$timestamp.'$'.OIDplus::authUtils()->makeAuthKey('5ef24124-f4fb-11ed-b67e-3c4a92df8582:'.$old_email.'/'.$new_email.'/'.$timestamp));
 
$message = file_get_contents(__DIR__ . '/change_request_email.tpl');
$message = str_replace('{{SYSTEM_URL}}', OIDplus::webpath(null,OIDplus::PATH_ABSOLUTE_CANONICAL), $message);
118,6 → 119,7
_CheckParamExists($params, 'new_email');
_CheckParamExists($params, 'password');
_CheckParamExists($params, 'auth');
_CheckParamExists($params, 'timestamp');
 
$old_email = $params['old_email'];
$new_email = $params['new_email'];
124,6 → 126,7
$password = $params['password'];
 
$auth = $params['auth'];
$timestamp = $params['timestamp'];
 
$ra_was_logged_in = OIDplus::authUtils()->isRaLoggedIn($old_email);
 
132,10 → 135,14
throw new OIDplusException(_L('E-Mail-Address cannot be changed because this user does not have a password'));
}
 
if (!OIDplus::authUtils()->validateAuthKey(['5ef24124-f4fb-11ed-b67e-3c4a92df8582',$old_email,$new_email], $auth, OIDplus::config()->getValue('max_ra_email_change_time', -1))) {
throw new OIDplusException(_L('Invalid or expired authentication key'));
if (!OIDplus::authUtils()->validateAuthKey('5ef24124-f4fb-11ed-b67e-3c4a92df8582:'.$old_email.'/'.$new_email.'/'.$timestamp, $auth)) {
throw new OIDplusException(_L('Invalid auth key'));
}
 
if ((OIDplus::config()->getValue('max_ra_email_change_time') > 0) && (time()-$timestamp > OIDplus::config()->getValue('max_ra_email_change_time'))) {
throw new OIDplusException(_L('Activation link expired!'));
}
 
$res = OIDplus::db()->query("select * from ###ra where email = ?", array($old_email));
if (!$res->any()) {
throw new OIDplusException(_L('eMail address does not exist anymore. It was probably already changed.'));
267,7 → 274,8
 
$old_email = explode('$',$id)[1];
$new_email = explode('$',$id)[2];
$auth = explode('$',$id)[3];
$timestamp = explode('$',$id)[3];
$auth = explode('$',$id)[4];
 
$out['title'] = _L('Perform email address change');
$out['icon'] = file_exists(__DIR__.'/img/main_icon.png') ? OIDplus::webpath(__DIR__,OIDplus::PATH_RELATIVE).'img/main_icon.png' : '';
289,7 → 297,7
if ($res->any()) {
throw new OIDplusException(_L('eMail address is already used by another RA. To merge accounts, please contact the superior RA of your objects and request an owner change of your objects.'), $out['title']);
} else {
if (!OIDplus::authUtils()->validateAuthKey(['5ef24124-f4fb-11ed-b67e-3c4a92df8582',$old_email,$new_email], $auth, OIDplus::config()->getValue('max_ra_email_change_time', -1))) {
if (!OIDplus::authUtils()->validateAuthKey('activate_new_ra_email;'.$old_email.';'.$new_email.';'.$timestamp, $auth)) {
throw new OIDplusException(_L('Invalid authorization. Is the URL OK?'), $out['title']);
} else {
$out['text'] = '<p>'._L('Old eMail-Address').': <b>'.$old_email.'</b></p>
298,6 → 306,7
<form id="activateNewRaEmailForm" action="javascript:void(0);" onsubmit="return OIDplusPageRaChangeEMail.activateNewRaEmailFormOnSubmit();">
<input type="hidden" id="old_email" value="'.htmlentities($old_email).'"/>
<input type="hidden" id="new_email" value="'.htmlentities($new_email).'"/>
<input type="hidden" id="timestamp" value="'.htmlentities($timestamp).'"/>
<input type="hidden" id="auth" value="'.htmlentities($auth).'"/>
 
<div><label class="padding_label">'._L('Please verify your password').':</label><input type="password" id="password" value=""/></div>