Changeset 2513920
- Timestamp:
- 04/13/2021 09:05:31 AM (5 years ago)
- Location:
- next-active-directory-integration/trunk
- Files:
-
- 16 added
- 57 edited
-
Autoloader.php (modified) (1 diff)
-
classes/ActiveDirectory (added)
-
classes/ActiveDirectory/Context.php (added)
-
classes/ActiveDirectory/Sid.php (added)
-
classes/Adi/Authentication/Credentials.php (modified) (7 diffs)
-
classes/Adi/Authentication/LoginService.php (modified) (17 diffs)
-
classes/Adi/Authentication/SingleSignOn/Profile (added)
-
classes/Adi/Authentication/SingleSignOn/Profile/Locator.php (added)
-
classes/Adi/Authentication/SingleSignOn/Profile/Match.php (added)
-
classes/Adi/Authentication/SingleSignOn/Service.php (modified) (14 diffs)
-
classes/Adi/Authentication/SingleSignOn/Validator.php (modified) (3 diffs)
-
classes/Adi/Authentication/VerificationService.php (modified) (1 diff)
-
classes/Adi/Configuration/Options.php (modified) (4 diffs)
-
classes/Adi/Configuration/Ui/Layout.php (modified) (11 diffs)
-
classes/Adi/Dependencies.php (modified) (8 diffs)
-
classes/Adi/Mail/Notification.php (modified) (2 diffs)
-
classes/Adi/Role/Manager.php (modified) (1 diff)
-
classes/Adi/Synchronization/Abstract.php (modified) (9 diffs)
-
classes/Adi/Synchronization/WordPress.php (modified) (7 diffs)
-
classes/Adi/User/LoginSucceededService.php (modified) (8 diffs)
-
classes/Core/Persistence/WordPressRepository.php (modified) (1 diff)
-
classes/Core/Util/StringUtil.php (modified) (1 diff)
-
classes/Ldap/Attribute/Repository.php (modified) (1 diff)
-
classes/Ldap/Attribute/Service.php (modified) (10 diffs)
-
classes/Ldap/Connection.php (modified) (16 diffs)
-
classes/Ldap/UserQuery.php (added)
-
classes/Multisite/Configuration/Persistence/BlogConfigurationRepository.php (modified) (24 diffs)
-
classes/Multisite/Configuration/Persistence/ConfigurationRepository.php (modified) (1 diff)
-
classes/Multisite/Configuration/Persistence/DefaultProfileRepository.php (modified) (1 diff)
-
classes/Multisite/Configuration/Persistence/ProfileConfigurationRepository.php (modified) (1 diff)
-
classes/Multisite/Configuration/Service.php (modified) (11 diffs)
-
classes/Multisite/Ui/BlogConfigurationPage.php (modified) (14 diffs)
-
classes/Multisite/Ui/ProfileConfigurationPage.php (modified) (10 diffs)
-
classes/Multisite/View/TwigContainer.php (modified) (1 diff)
-
index.php (modified) (1 diff)
-
js/app/blog-options/controllers/environment.controller.js (modified) (8 diffs)
-
js/app/blog-options/controllers/security.controller.js (modified) (4 diffs)
-
js/app/blog-options/controllers/sso.controller.js (added)
-
js/app/profile-options/controllers/environment.controller.js (modified) (8 diffs)
-
js/app/profile-options/controllers/security.controller.js (modified) (4 diffs)
-
js/app/profile-options/controllers/sso.controller.js (added)
-
readme.txt (modified) (5 diffs)
-
vendor/adLDAP/adLDAP.php (modified) (7 diffs)
-
vendor/autoload.php (modified) (1 diff)
-
vendor/composer/ClassLoader.php (modified) (5 diffs)
-
vendor/composer/InstalledVersions.php (added)
-
vendor/composer/autoload_classmap.php (modified) (1 diff)
-
vendor/composer/autoload_real.php (modified) (5 diffs)
-
vendor/composer/autoload_static.php (modified) (3 diffs)
-
vendor/composer/installed.json (modified) (1 diff)
-
vendor/composer/installed.php (added)
-
vendor/composer/platform_check.php (added)
-
vendor/monolog/monolog/CHANGELOG.md (modified) (1 diff)
-
vendor/monolog/monolog/composer.json (modified) (2 diffs)
-
vendor/monolog/monolog/phpstan.neon.dist (added)
-
vendor/monolog/monolog/src/Monolog/ErrorHandler.php (modified) (1 diff)
-
vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php (modified) (1 diff)
-
vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php (modified) (1 diff)
-
vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php (modified) (1 diff)
-
vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php (modified) (1 diff)
-
vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php (modified) (2 diffs)
-
vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php (modified) (1 diff)
-
vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php (modified) (2 diffs)
-
vendor/monolog/monolog/src/Monolog/Logger.php (modified) (1 diff)
-
vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php (modified) (2 diffs)
-
vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php (modified) (2 diffs)
-
vendor/monolog/monolog/src/Monolog/Utils.php (modified) (1 diff)
-
vendor/paragonie/random_compat/phpunit-autoload.php (added)
-
vendor/symfony/polyfill-ctype/bootstrap.php (modified) (1 diff)
-
vendor/symfony/polyfill-ctype/bootstrap80.php (added)
-
vendor/symfony/polyfill-ctype/composer.json (modified) (2 diffs)
-
views/option/element.twig (modified) (2 diffs)
-
views/option/element/textarea.twig (added)
Legend:
- Unmodified
- Added
- Removed
-
next-active-directory-integration/trunk/Autoloader.php
r1541870 r2513920 99 99 private function isPluginClass($class) 100 100 { 101 $prefixes = array('Adi', 'Core', 'Ldap', 'Multisite', 'Migration' );101 $prefixes = array('Adi', 'Core', 'Ldap', 'Multisite', 'Migration', 'ActiveDirectory'); 102 102 103 103 foreach ($prefixes as $prefix) { -
next-active-directory-integration/trunk/classes/Adi/Authentication/Credentials.php
r2029919 r2513920 1 1 <?php 2 if ( !defined('ABSPATH')) {2 if (!defined('ABSPATH')) { 3 3 die('Access denied.'); 4 4 } … … 12 12 * This class is mutable so parts of the credentials can be updated due to AD/LDAP lookups. 13 13 * 14 * @author Christopher Klein < ckl@neos-it.de>14 * @author Christopher Klein <me[at]schakko[dot]de> 15 15 * @access public 16 16 */ … … 46 46 47 47 /** 48 * a specific Kerberos realm 49 * @since 2.2.0 50 * @var string 51 */ 52 private $kerberosRealm; 53 54 /** 55 * options for this context 56 * @since 2.2.0 57 * @var array 58 */ 59 private $options = array(); 60 61 /** 48 62 * NextADInt_Adi_Authentication_Credentials constructor. 49 63 * 50 * @param string $login Login in form 'username' (sAMAccountName), 'username@domain' (userPrincipalName) or 'NETBIOS\sAMAccountName'64 * @param string $login Login in form 'username' (sAMAccountName), 'username@domain' (userPrincipalName) 'sAMAccountName@REALM' (Kerberors) or 'NETBIOS\sAMAccountName' 51 65 * @param string $password 52 66 */ … … 75 89 76 90 /** 91 * Add an additional option to the credential's context 92 * 93 * @param $key 94 * @param $value 95 * @since 2.2.0 96 */ 97 public function setOption($key, $value) 98 { 99 $this->options[$key] = $value; 100 } 101 102 /** 103 * Return an option's value. it returns null if the option has not been set. 104 * 105 * @param $key 106 * @return mixed|null 107 * @since 2.2.0 108 */ 109 public function getOption($key) 110 { 111 if (isset($this->options[$key])) { 112 return $this->options[$key]; 113 } 114 115 return NULL; 116 } 117 118 /** 77 119 * Get suffix without any '@' character 78 120 * @return string … … 105 147 $r = $this->upnUsername; 106 148 107 if ( !empty($this->upnSuffix)) {149 if (!empty($this->upnSuffix)) { 108 150 $r .= '@' . $this->upnSuffix; 109 151 } … … 123 165 if ($parts >= 2) { 124 166 $this->upnUsername = $parts[0]; 125 $this->upnSuffix = $parts[1];167 $this->upnSuffix = $parts[1]; 126 168 } 127 169 } … … 228 270 } 229 271 272 /** 273 * Get the user's Kerberos realm 274 * @return string 275 * @since 2.2.0 276 */ 277 public function getKerberosRealm() 278 { 279 return $this->kerberosRealm; 280 } 281 282 /** 283 * Set the user's Kerberos realm 284 * @param $kerberosRealm 285 * @since 2.2.0 286 */ 287 public function setKerberosRealm($kerberosRealm) 288 { 289 $this->kerberosRealm = $kerberosRealm; 290 } 291 292 /** 293 * Based upon this credential, a new LDAP query will be created 294 * 295 * @return NextADInt_Ldap_UserQuery|QueryForUser 296 * @since 2.2.0 297 */ 298 public function toUserQuery() 299 { 300 return NextADInt_Ldap_UserQuery::forPrincipal($this->login, $this); 301 } 302 230 303 public function __toString() 231 304 { 232 305 return "Credentials={login='" . $this->login . "',sAMAccountName='" . $this->sAMAccountName 233 . "',userPrincipalName='" . $this->getUserPrincipalName() . "',netbios='" . $this->netbiosName 234 . "',objectGuid='" . $this->objectGuid . "',wordPressUserId='" . $this->wordPressUserId . "'}"; 306 . "',userPrincipalName='" . $this->getUserPrincipalName() . "',netbios='" . $this->netbiosName 307 . "',objectGuid='" . $this->objectGuid . "',wordPressUserId='" . $this->wordPressUserId 308 . "',kerberosRealm='" . $this->kerberosRealm . "'}"; 235 309 } 236 310 } -
next-active-directory-integration/trunk/classes/Adi/Authentication/LoginService.php
r2224724 r2513920 42 42 private $logger; 43 43 44 /**45 * @var NextADInt_Adi_LoginState46 */44 /** 45 * @var NextADInt_Adi_LoginState 46 */ 47 47 private $loginState; 48 48 … … 71 71 NextADInt_Adi_Authentication_Ui_ShowBlockedMessage $userBlockedMessage = null, 72 72 NextADInt_Ldap_Attribute_Service $attributeService, 73 NextADInt_Adi_LoginState $loginState,73 NextADInt_Adi_LoginState $loginState, 74 74 NextADInt_Adi_User_LoginSucceededService $loginSucceededService 75 75 ) … … 93 93 public function register() 94 94 { 95 // don't allow multiple registrations of the same LoginService instance96 if ($this->isRegistered) {97 return;98 }95 // don't allow multiple registrations of the same LoginService instance 96 if ($this->isRegistered) { 97 return; 98 } 99 99 100 100 add_filter('authenticate', array($this, 'authenticate'), 10, 3); … … 156 156 // Check if this looks like a ProxyAddress and look up sAMAccountName if we are allowing ProxyAddresses as login. 157 157 $allowProxyAddressLogin = $this->configuration->getOptionValue(NextADInt_Adi_Configuration_Options::ALLOW_PROXYADDRESS_LOGIN); 158 if ($allowProxyAddressLogin && strpos($login, '@') !== false) {158 if ($allowProxyAddressLogin && strpos($login, '@') !== false) { 159 159 $login = $this->lookupFromProxyAddresses($login); 160 160 } … … 168 168 $password = stripslashes($password); 169 169 170 $credentials = self::createCredentials($login, $password);170 $credentials = $this->buildCredentials($login, $password); 171 171 $suffixes = $this->detectAuthenticatableSuffixes($credentials->getUpnSuffix()); 172 172 … … 208 208 * @return The associated sAMAccountName or $proxyAddress if not found. 209 209 */ 210 public function lookupFromProxyAddresses($proxyAddress) { 210 public function lookupFromProxyAddresses($proxyAddress) 211 { 211 212 212 213 // Use the Sync to WordpPress username and password since anonymous bind can't search. … … 221 222 $domainControllerIsAvailable = $this->ldapConnection->checkPorts(); 222 223 223 if ($domainControllerIsAvailable) {224 if ($domainControllerIsAvailable) { 224 225 $samaccountname = $this->ldapConnection->findByProxyAddress($proxyAddress); 225 226 226 227 // If this email address wasn't specified in anyone's proxyAddresses attributes, just return the original value. 227 if ($samaccountname === false) {228 if ($samaccountname === false) { 228 229 return $proxyAddress; 229 230 } … … 266 267 return $this->postAuthentication($credentials); 267 268 } 268 269 269 } 270 270 … … 275 275 276 276 /** 277 * Create a new instance of Adi_Authentication_ActiveDirectory277 * Create a new instance of NextADInt_Adi_Authentication_Credentials 278 278 * 279 279 * @param $login … … 281 281 * 282 282 * @return NextADInt_Adi_Authentication_Credentials 283 */ 284 public static function createCredentials($login, $password) 285 { 286 return NextADInt_Adi_Authentication_PrincipalResolver::createCredentials($login, $password); 283 * @since 2.0.0 284 */ 285 public function buildCredentials($login, $password) 286 { 287 $r = NextADInt_Adi_Authentication_PrincipalResolver::createCredentials($login, $password); 288 289 /** 290 * @var NextADInt_Adi_Authentication_Credentials 291 */ 292 $r = apply_filters(NEXT_AD_INT_PREFIX . 'auth_configure_credentials', $r); 293 294 return $r; 287 295 } 288 296 … … 380 388 $this->logger->debug("User domain '{$suffix}' is in list of account suffixes. Using this as first testable account suffix."); 381 389 382 unset($arrAuthenticatableSuffixes[$idx]);383 array_unshift($arrAuthenticatableSuffixes,$suffix);390 // ADI-716: only return the user's suffix if it is inside the list of authenticatable suffixes 391 return array($suffix); 384 392 } 385 393 … … 415 423 // Otherwise, local authentication could still succeed and the counter would still be 416 424 // incremented 417 if ($domainControllerIsAvailable) {425 if ($domainControllerIsAvailable) { 418 426 // block or unblock user (depends on the authentication) 419 427 $this->refreshBruteForceProtectionStatusForUser($username, $accountSuffix, $success); … … 441 449 * @param $accountSuffix 442 450 * @internal param string $fullUsername 443 * @deprecated 1.0.13 use external plugin for brute force protection444 * @see https://wordpress.org/plugins/better-wp-security/451 * @deprecated 1.0.13 use external plugin for brute force protection 452 * @see https://wordpress.org/plugins/better-wp-security/ 445 453 */ 446 454 function bruteForceProtection($username, $accountSuffix) … … 496 504 * @param boolean $successfulLogin if true, the user is un-blocked; otherwise, he is blocked 497 505 * @internal param string $fullUsername 498 * @deprecated 1.0.13 use external plugin for brute force protection499 * @see https://wordpress.org/plugins/better-wp-security/506 * @deprecated 1.0.13 use external plugin for brute force protection 507 * @see https://wordpress.org/plugins/better-wp-security/ 500 508 */ 501 509 function refreshBruteForceProtectionStatusForUser($username, $accountSuffix, $successfulLogin) … … 514 522 if ($successfulLogin) { 515 523 $this->failedLogin->deleteLoginAttempts($fullUsername); 516 } 517 // ADI-705: check for existing variable and *not* null; findByActiveDirectoryUsername returns false 524 } // ADI-705: check for existing variable and *not* null; findByActiveDirectoryUsername returns false 518 525 elseif ($wpUser && $this->userManager->isNadiUser($wpUser)) { 519 526 $this->failedLogin->increaseLoginAttempts($fullUsername); … … 538 545 539 546 // ADI-204: during login we have to use the authenticated user principal name 540 $ldapAttributes = $this->attributeService-> findLdapAttributesOfUser($credentials, null);547 $ldapAttributes = $this->attributeService->resolveLdapAttributes($credentials->toUserQuery()); 541 548 542 549 // ADI-395: wrong base DN leads to exception during Test Authentication … … 548 555 549 556 // update the real sAMAccountName of the credentials. This could be totally different from the userPrincipalName user for login 557 $this->updateCredentials($credentials, $ldapAttributes); 558 559 // state: user is authenticated 560 $this->loginState->setAuthenticationSucceeded(); 561 562 return $credentials; 563 } 564 565 /** 566 * Update the credential data (sAMAccountName, userPrincipalName, objectGUID) based upon the filtered LDAP attributes 567 * 568 * @param NextADInt_Adi_Authentication_Credentials $credentials 569 * @param NextADInt_Ldap_Attributes $ldapAttributes 570 * @pack 571 * @since 2.0.0 572 */ 573 function updateCredentials(NextADInt_Adi_Authentication_Credentials $credentials, NextADInt_Ldap_Attributes $ldapAttributes) 574 { 550 575 $credentials->setSAMAccountName($ldapAttributes->getFilteredValue('samaccountname')); 551 576 $credentials->setObjectGuid($ldapAttributes->getFilteredValue('objectguid')); 552 553 // state: user is authenticated 554 $this->loginState->setAuthenticationSucceeded(); 555 556 return $credentials; 577 $credentials->setUserPrincipalName($ldapAttributes->getFilteredValue('userprincipalname')); 557 578 } 558 579 -
next-active-directory-integration/trunk/classes/Adi/Authentication/SingleSignOn/Service.php
r2069979 r2513920 17 17 class NextADInt_Adi_Authentication_SingleSignOn_Service extends NextADInt_Adi_Authentication_LoginService 18 18 { 19 /** 20 * If Kerberos or certificate authentication failed 21 */ 22 const FAILED_SSO_UPN = 'failedSsoUpn'; 23 24 /** 25 * If NTLM authentication failed 26 */ 27 const FAILED_SSO_NETBIOS_NAME = 'failedSsoNetbios'; 19 const FAILED_SSO_PRINCIPAL = "failedSsoPrincipal"; 28 20 29 21 const USER_LOGGED_OUT = 'userLoggedOut'; … … 37 29 /** @var NextADInt_Adi_User_LoginSucceededService $loginSucceededService */ 38 30 private $loginSucceededService; 31 32 /** 33 * @since 2.0.0 34 * @var NextADInt_Adi_Authentication_SingleSignOn_Profile_Locator 35 */ 36 private $ssoProfileLocator; 39 37 40 38 public function __construct(NextADInt_Adi_Authentication_Persistence_FailedLoginRepository $failedLogin = null, … … 46 44 NextADInt_Ldap_Attribute_Service $attributeService, 47 45 NextADInt_Adi_Authentication_SingleSignOn_Validator $validation, 48 NextADInt_Adi_LoginState $loginState, 49 NextADInt_Adi_User_LoginSucceededService $loginSucceededService 46 NextADInt_Adi_LoginState $loginState, 47 NextADInt_Adi_User_LoginSucceededService $loginSucceededService, 48 NextADInt_Adi_Authentication_SingleSignOn_Profile_Locator $ssoProfileLocator 50 49 ) 51 50 { … … 56 55 $this->logger = NextADInt_Core_Logger::getLogger(); 57 56 $this->loginSucceededService = $loginSucceededService; 57 $this->ssoProfileLocator = $ssoProfileLocator; 58 58 } 59 59 … … 77 77 } 78 78 79 /**80 * Check if the user can be authenticated using user from the client machine.81 *82 * @param null $user83 * @param string $login84 * @param string $password85 *86 * @return bool87 * @throws Exception88 */79 /** 80 * Check if the user can be authenticated using user from the client machine. 81 * 82 * @param null $user 83 * @param string $login 84 * @param string $password 85 * 86 * @return bool 87 * @throws Exception 88 */ 89 89 public function authenticate($user = null /* required for WordPress callback */, $login = '', $password = '') 90 90 { … … 105 105 } 106 106 107 $credentials = self::createCredentials($username, '');107 $credentials = $this->buildCredentials($username, ''); 108 108 $sessionHandler = $this->getSessionHandler(); 109 109 … … 122 122 $validation->validateAuthenticationState($credentials); 123 123 124 $netbiosName = $credentials->getNetbiosName(); 125 126 if (isset($netbiosName)) { 127 $credentials = $this->ntlmAuth($credentials, $validation); 128 } else { 129 // $username or $username@$upnSuffix 130 $credentials = $this->kerberosAuth($credentials, $validation); 131 } 124 // encapsulate the authentication process 125 $credentials = $this->delegateAuth($credentials, $validation); 132 126 133 127 // authenticate the given user and run the default procedure form the LoginService 134 128 $authenticatedCredentials = $this->parentAuthenticate($credentials); 135 if(!$authenticatedCredentials) { 136 throw new NextADInt_Adi_Authentication_Exception("Unable to authenticate user" . $credentials->getUserPrincipalName()); 129 130 if (!$authenticatedCredentials) { 131 throw new NextADInt_Adi_Authentication_Exception("Unable to authenticate user " . $credentials->getUserPrincipalName()); 137 132 } 138 139 133 140 134 // as SSO runs during the "init" phase, we need to call the 'authorize' filter on our own … … 143 137 144 138 // if our user is authenticated and we have a WordPress user, we 145 $sessionHandler->clearValue(self::FAILED_SSO_ UPN);139 $sessionHandler->clearValue(self::FAILED_SSO_PRINCIPAL); 146 140 } catch (NextADInt_Adi_Authentication_Exception $e) { 147 141 $this->logger->error('User could not be authenticated using SSO. ' . $e->getMessage()); 148 $sessionHandler->setValue(self::FAILED_SSO_ UPN, $credentials->getUserPrincipalName());142 $sessionHandler->setValue(self::FAILED_SSO_PRINCIPAL, $credentials->getLogin()); 149 143 150 144 return false; … … 152 146 153 147 return true; 148 } 149 150 /** 151 * Execute the authentication by looking up the username (sAMAccountName, userPrincipalName or Kerberos principal) inside the Active Directory. 152 * 153 * @param NextADInt_Adi_Authentication_Credentials $credentials 154 * @param $validation 155 * @return NextADInt_Adi_Authentication_Credentials 156 * @throws NextADInt_Adi_Authentication_Exception 157 * @since 2.2.0 158 */ 159 function delegateAuth(NextADInt_Adi_Authentication_Credentials $credentials, $validation) 160 { 161 // let our locator find a matching profile, based upon the given credentials 162 $profileMatch = $this->ssoProfileLocator->locate($credentials); 163 164 // a valid profile is required for login 165 $validation->validateProfile($profileMatch->getProfile()); 166 167 $this->logger->debug("Valid SSO profile for type '" . $profileMatch->getType() . "' found"); 168 // fire a hook to inform that one of the SSO profiles has been matched 169 do_action(NEXT_AD_INT_PREFIX . 'sso_profile_located', $credentials, $profileMatch); 170 171 $this->openLdapConnection($profileMatch->getProfile()); 172 173 $ldapAttributes = $this->getAttributeService()->resolveLdapAttributes($credentials->toUserQuery()); 174 175 if ($ldapAttributes->getRaw() == false) { 176 throw new NextADInt_Adi_Authentication_Exception("User '" . $credentials->getLogin() . "' does not exist in Active Directory'"); 177 } 178 179 // update the user's credentials, so we have valid a userPrincipalName, GUID and sAMAccountName based upon recent Active Directory data 180 $this->updateCredentials($credentials, $ldapAttributes); 181 182 return $credentials; 154 183 } 155 184 … … 168 197 169 198 /** 170 * Create new credentials based upon sAMAccountName or userPrincipalName171 *172 * @throws NextADInt_Adi_Authentication_Exception If the user's attribute could not be found173 * @param NextADInt_Adi_Authentication_Credentials $credentials174 * @return NextADInt_Adi_Authentication_Credentials175 */176 function createUpnCredentials(NextADInt_Adi_Authentication_Credentials $credentials)177 {178 // findLdapAttributesOfUser tries both sAMAccountName and userPrincipalName179 $ldapAttributes = $this->getAttributeService()->findLdapAttributesOfUser($credentials, '');180 181 if ($ldapAttributes->getRaw() == false) {182 throw new NextADInt_Adi_Authentication_Exception("User '" . $credentials->getLogin() . "' does not exist in Active Directory'");183 }184 185 $upn = $ldapAttributes->getFilteredValue('userprincipalname');186 $samaccountname = $ldapAttributes->getFilteredValue('samaccountname');187 $credentials = self::createCredentials($upn, '');188 // ADI-620: make sure that the sAMAccountName is explicitly set as it does not have to correlate with the userPrincipalName189 $credentials->setSAMAccountName($samaccountname);190 191 return $credentials;192 }193 194 /**195 * Authenticate given credentials by using an internal lookup of the provided NETBIOS name.196 *197 * @throws NextADInt_Adi_Authentication_Exception if the profile could not be found198 * @param NextADInt_Adi_Authentication_Credentials $credentials199 * @param NextADInt_Adi_Authentication_SingleSignOn_Validator $validation200 * @return NextADInt_Adi_Authentication_Credentials201 */202 function ntlmAuth(NextADInt_Adi_Authentication_Credentials $credentials, NextADInt_Adi_Authentication_SingleSignOn_Validator $validation)203 {204 $this->logger->info('SSO authentication triggered using NTLM for user ' . $credentials->getLogin());205 $profile = null;206 207 // find assigned profile by previously detected nETBIOSName208 try {209 $profile = $this->findBestConfigurationMatchForProfile(NextADInt_Adi_Configuration_Options::NETBIOS_NAME, $credentials->getNetbiosName());210 211 $validation->validateProfile($profile);212 } catch (NextADInt_Adi_Authentication_Exception $e) {213 $this->logger->error("Validation of profile for NETBIOS name '" . $credentials->getNetbiosName() . "' failed: " . $e->getMessage());214 215 throw new NextADInt_Adi_Authentication_Exception("Unable to find matching NADI profile for NETBIOS name '" . $credentials->getNetbiosName() . "'. Is NADI connected to a valid Active Directory domain?");216 }217 218 $this->openLdapConnection($profile);219 220 // create required credentials with userPrincipalName and upnSuffix. At the moment we got only nETBIOSName and sAMAccountName221 $credentials = $this->createUpnCredentials($credentials);222 223 return $credentials;224 }225 226 /**227 * Authenticate given credentials by using an internal lookup of the provided UPN suffix.228 *229 * @param NextADInt_Adi_Authentication_Credentials $credentials230 * @param NextADInt_Adi_Authentication_SingleSignOn_Validator $validation231 *232 * @return NextADInt_Adi_Authentication_Credentials233 * @throws NextADInt_Adi_Authentication_Exception234 */235 function kerberosAuth(NextADInt_Adi_Authentication_Credentials $credentials, NextADInt_Adi_Authentication_SingleSignOn_Validator $validation)236 {237 $this->logger->info('SSO authentication triggered using Kerberos for user ' . $credentials->getLogin());238 239 // normalize our suffix, to prevent inconsistencies240 $suffix = $this->normalizeSuffix($credentials->getUpnSuffix());241 242 // get the profile and check if it is valid243 $profile = $this->findBestConfigurationMatchForProfile(NextADInt_Adi_Configuration_Options::ACCOUNT_SUFFIX, $suffix);244 $validation->validateProfile($profile);245 $this->openLdapConnection($profile);246 247 // try to resolve the user using the sAMAccountName, if no suffix has been found248 if (null === $credentials->getUpnSuffix()) {249 $credentials = $this->createUpnCredentials($credentials);250 }251 252 return $credentials;253 }254 255 /**256 199 * Clear the session values for failed sso or manual logout if the user wants to retry authentication over SSO. 257 200 */ … … 259 202 { 260 203 if ('sso' === NextADInt_Core_Util_ArrayUtil::get('reauth', $_GET, false)) { 261 $this->getSessionHandler()->clearValue(self::FAILED_SSO_ UPN);204 $this->getSessionHandler()->clearValue(self::FAILED_SSO_PRINCIPAL); 262 205 $this->getSessionHandler()->clearValue(self::USER_LOGGED_OUT); 263 206 } … … 296 239 297 240 $this->validation->validateLdapConnection($this->getLdapConnection()); 298 }299 300 /**301 * Get account suffix for given credentials302 *303 * @param string $suffix304 *305 * @return array306 */307 public function detectAuthenticatableSuffixes($suffix)308 {309 $profile = $this->findBestConfigurationMatchForProfile(NextADInt_Adi_Configuration_Options::ACCOUNT_SUFFIX, $suffix);310 311 if (null === $profile) {312 return array($suffix);313 }314 315 return NextADInt_Core_Util_StringUtil::split($profile[NextADInt_Adi_Configuration_Options::ACCOUNT_SUFFIX], ';');316 }317 318 /**319 * Find the profile with SSO enabled and its configuration option contains the provided value.320 *321 * @param $option name of profile option322 * @param $value value of given option to match323 *324 * @return mixed325 */326 public function findBestConfigurationMatchForProfile($option, $value)327 {328 $ssoEnabledProfiles = $this->findSsoEnabledProfiles();329 330 // find all profiles with given option value331 $profiles = $this->getProfilesWithOptionValue($option, $value, $ssoEnabledProfiles);332 333 // if multiple profiles were found, log a warning and return the first result334 if (sizeof($profiles) > 1) {335 $this->logger->warn('Multiple profiles with the same option "' . $option . '" and enabled SSO were found.');336 }337 338 // if no profile given suffix and sso enabled was found, search for profiles with SSO enabled and no suffixes339 if (sizeof($profiles) == 0) {340 $profiles = $this->getProfilesWithoutOptionValue($option, $ssoEnabledProfiles);341 }342 343 // return the first found profile or null344 return NextADInt_Core_Util_ArrayUtil::findFirstOrDefault($profiles, null);345 }346 347 /**348 * Get all profiles with the given option value.349 *350 * @param $option name of configuration option to search for351 * @param $requiredValue352 * @param $profiles353 *354 * @return array355 */356 protected function getProfilesWithOptionValue($option, $requiredValue, $profiles)357 {358 return NextADInt_Core_Util_ArrayUtil::filter(function ($profile) use ($option, $requiredValue) {359 $values = array();360 361 if (isset($profile[$option])) {362 $values = NextADInt_Core_Util_StringUtil::split($profile[$option], ';');363 }364 365 return (NextADInt_Core_Util_ArrayUtil::containsIgnoreCase($requiredValue, $values));366 }, $profiles);367 }368 369 /**370 * Get all profiles which have no option specified.371 *372 * @param $option name of configuration option373 * @param $profiles374 *375 * @return array376 */377 protected function getProfilesWithoutOptionValue($option, $profiles)378 {379 return NextADInt_Core_Util_ArrayUtil::filter(function ($profile) use ($option) {380 $value = '';381 382 if (isset($profile[$option])) {383 $value = $profile[$option];384 }385 386 return NextADInt_Core_Util_StringUtil::isEmptyOrWhitespace($value);387 }, $profiles);388 241 } 389 242 … … 394 247 * find a problem with this solution. 395 248 * 396 * @param string $username 397 * @param null|string $accountSuffix 398 * @param string $password 399 * 400 * @return bool 401 */ 402 public function authenticateAtActiveDirectory($username, $accountSuffix, $password) 403 { 404 return true; 249 * @param NextADInt_Adi_Authentication_Credentials $credentials 250 * @param array $suffixes 251 * @return bool|NextADInt_Adi_Authentication_Credentials 252 * @throws Exception 253 * @since 2.0.0 254 */ 255 public function tryAuthenticatableSuffixes(NextADInt_Adi_Authentication_Credentials $credentials, $suffixes = array()) 256 { 257 $this->logger->info("User has been authenticated through SSO, running post authentication"); 258 return $this->postAuthentication($credentials); 259 } 260 261 /** 262 * It returns the suffix itself as we have been already authenticated previously 263 * 264 * @param string $suffix 265 * @return array 266 */ 267 public function detectAuthenticatableSuffixes($suffix) 268 { 269 // there is no more logic required; we just want to make sure that the parent's tryAuthenticatableSuffixes method call is executed 270 $this->logger->info("Authenticatable suffixes are ignored"); 271 return array($suffix); 405 272 } 406 273 … … 424 291 425 292 return $connection; 426 }427 428 /**429 * Return the suffix with an '@' prefix.430 *431 * @param $suffix432 *433 * @return string434 */435 protected function normalizeSuffix($suffix)436 {437 if (!empty($suffix) && '@' !== $suffix[0]) {438 $suffix = '@' . $suffix;439 }440 441 return $suffix;442 }443 444 /**445 * Find all profiles with the necessary roles.446 *447 * @return array448 */449 protected function findSsoEnabledProfiles()450 {451 // find all profiles with the given options and add them to our $profiles array452 $profiles = $this->getConfiguration()->findAllProfiles(array(453 NextADInt_Adi_Configuration_Options::ACCOUNT_SUFFIX,454 NextADInt_Adi_Configuration_Options::SSO_ENABLED,455 NextADInt_Adi_Configuration_Options::SSO_USER,456 NextADInt_Adi_Configuration_Options::SSO_PASSWORD,457 NextADInt_Adi_Configuration_Options::DOMAIN_CONTROLLERS,458 NextADInt_Adi_Configuration_Options::PORT,459 NextADInt_Adi_Configuration_Options::ENCRYPTION,460 NextADInt_Adi_Configuration_Options::NETWORK_TIMEOUT,461 NextADInt_Adi_Configuration_Options::BASE_DN,462 NextADInt_Adi_Configuration_Options::SSO_USER,463 NextADInt_Adi_Configuration_Options::SSO_PASSWORD,464 NextADInt_Adi_Configuration_Options::NETBIOS_NAME465 ));466 467 // get the current configuration and add it as first option468 // this is required in a single site environment, as the profile will not be listed above469 array_unshift($profiles, $this->getConfiguration()->getAllOptions());470 471 // filter all profiles and get profiles with SSO enabled472 $profiles = NextADInt_Core_Util_ArrayUtil::filter(function ($profile) {473 if (!isset($profile[NextADInt_Adi_Configuration_Options::SSO_ENABLED]['option_value'])) {474 return false;475 }476 477 return $profile[NextADInt_Adi_Configuration_Options::SSO_ENABLED]['option_value'] === true;478 }, $profiles);479 480 return $this->normalizeProfiles($profiles);481 }482 483 /**484 * Normalize the given profiles for further usage.485 *486 * @param $profiles487 *488 * @return array489 */490 protected function normalizeProfiles($profiles)491 {492 // go through all found profiles and normalize the values493 return NextADInt_Core_Util_ArrayUtil::map(function ($profile) {494 // set the option_value as the real value495 return NextADInt_Core_Util_ArrayUtil::map(function ($profileOption) {496 return $profileOption['option_value'];497 }, $profile);498 }, $profiles);499 293 } 500 294 -
next-active-directory-integration/trunk/classes/Adi/Authentication/SingleSignOn/Validator.php
r2029919 r2513920 18 18 class NextADInt_Adi_Authentication_SingleSignOn_Validator 19 19 { 20 const FAILED_SSO_UPN = NextADInt_Adi_Authentication_SingleSignOn_Service::FAILED_SSO_UPN;21 22 const USER_LOGGED_OUT = NextADInt_Adi_Authentication_SingleSignOn_Service::USER_LOGGED_OUT;23 24 20 /** 25 21 * Check if the given {@link NextADInt_Ldap_Connection} is connected. … … 73 69 public function validateAuthenticationState(NextADInt_Adi_Authentication_Credentials $credentials) 74 70 { 75 $failedAuthenticateUsername = $this->getSessionHandler()->getValue( self::FAILED_SSO_UPN);71 $failedAuthenticateUsername = $this->getSessionHandler()->getValue(NextADInt_Adi_Authentication_SingleSignOn_Service::FAILED_SSO_PRINCIPAL); 76 72 77 if ( $failedAuthenticateUsername === $credentials->getUserPrincipalName()) {73 if (!empty($failedAuthenticateUsername) && ($failedAuthenticateUsername === $credentials->getLogin())) { 78 74 $this->throwAuthenticationException('User has already failed to authenticate. Stop retrying.'); 79 75 } … … 87 83 public function validateLogoutState() 88 84 { 89 $userLoggedOut = $this->getSessionHandler()->getValue( self::USER_LOGGED_OUT, false);85 $userLoggedOut = $this->getSessionHandler()->getValue(NextADInt_Adi_Authentication_SingleSignOn_Service::USER_LOGGED_OUT, false); 90 86 91 87 if ($userLoggedOut) { -
next-active-directory-integration/trunk/classes/Adi/Authentication/VerificationService.php
r2331595 r2513920 41 41 * @param array $data 42 42 * 43 * @return bool false || string $objectId43 * @return bool|ActiveDirectory_Sid 44 44 */ 45 45 public function findActiveDirectoryDomainSid($data) -
next-active-directory-integration/trunk/classes/Adi/Configuration/Options.php
r2331595 r2513920 36 36 const DOMAIN_SID = 'domain_sid'; 37 37 const NETBIOS_NAME = 'netbios_name'; 38 const ADDITIONAL_DOMAIN_SIDS = 'additional_domain_sids'; 39 40 // Forest 41 const KERBEROS_REALM_MAPPINGS = 'kerberos_realm_mappings'; 38 42 39 43 // User - User Settings … … 508 512 $transient => false, 509 513 ), 510 511 514 self::NETBIOS_NAME => array( 512 515 $title => __('NetBIOS name', 'next-active-directory-integration'), … … 524 527 $default => '', 525 528 $sanitizer => array('string'), 529 $showPermission => true, 530 $transient => false, 531 ), 532 // additional domain SIDs when using a Global Catalog 533 self::ADDITIONAL_DOMAIN_SIDS => array( 534 $title => __('Additional domain SIDs', 'next-active-directory-integration'), 535 $type => NextADInt_Multisite_Option_Type::EDITABLE_LIST, 536 $description => __( 537 'Recognize users during import from these domain SIDs. The specified SIDs are used in <strong>addition</strong> to the already connected domain above.', 538 'next-active-directory-integration' 539 ), 540 $detail => array( 541 __( 542 'When using a <em>Global Catalog</em> handling more than one domain, you have to specify each additional domain inside it', 543 'next-active-directory-integration' 544 ), 545 ), 546 $angularAttributes => '', 547 $angularButtonAttributes => 'ng-show="!$parent.is_input_empty(new_additional_domain_sids)"', 548 $default => '', 549 $sanitizer => array('accumulation', ';', array('string', false, true)), 526 550 $showPermission => true, 527 551 $transient => false, … … 1117 1141 $transient => false, 1118 1142 ), 1119 // Allows users who usually require a smart card to log in using NADI 1143 // Kerberos realm mappings 1144 self::KERBEROS_REALM_MAPPINGS => array( 1145 $title => __('Kerberos realm mappings', 'next-active-directory-integration'), 1146 $type => NextADInt_Multisite_Option_Type::TEXTAREA, 1147 $description => __( 1148 'Specify all Kerberos realms and their designated UPN suffixes', 1149 'next-active-directory-integration' 1150 ), 1151 $detail => array( 1152 __( 1153 'This is only required if you are inside an Active Directory forest with a Global Catalog and Kerberos enabled. You need the <em>Multi-domain Forest Premium Extension</em>em>', 1154 'next-active-directory-integration' 1155 ), 1156 __('Example:', 'next-active-directory-integration'), 1157 __('FIRSTKRBREALM.COM=upnsuffix1.com;', 'next-active-directory-integration'), 1158 __('SECONDKRBREALM.COM=upnsuffix2.de,upnsuffix3.org;', 'next-active-directory-integration'), 1159 __( 1160 'Please take a look at our documentation at <a href="https://active-directory-wp.com/docs/Configuration/Sso" target="__blank">https://active-directory-wp.com/docs/Configuration/Sso</a>', 1161 'next-active-directory-integration' 1162 ), 1163 ), 1164 $angularAttributes => 'ng-disabled="((!option.sso) || ((permission.sso == 2) || (permission.sso == 1))', 1165 $default => '', 1166 $showPermission => true, 1167 $transient => false, 1168 ), 1169 // Allows users who usually require a smart card to log in using NADI 1120 1170 self::ENABLE_SMARTCARD_USER_LOGIN => array( 1121 1171 $title => __('Enable login for smart card Users', 'next-active-directory-integration'), -
next-active-directory-integration/trunk/classes/Adi/Configuration/Ui/Layout.php
r2331595 r2513920 85 85 ), 86 86 ), 87 // Tab name87 // Environment tab 88 88 __('Environment', 'next-active-directory-integration') => array( 89 89 // Group Name … … 117 117 ) 118 118 ), 119 ), 120 // Tab name 119 __('Forest configuration', 'next-active-directory-integration') => array( 120 self::DESCRIPTION => __( 121 'This is only relevant if you are using NADI inside an AD forest. You need the premium extension <a href="https://active-directory-wp.com/premium-extension/active-directory-forest/" target="__blank">Active Directory Forest</a> to have any effect for the forest configuration.', 122 'next-active-directory-integration' 123 ), 124 self::OPTIONS => array( 125 NextADInt_Adi_Configuration_Options::ADDITIONAL_DOMAIN_SIDS, 126 ) 127 ) 128 ), 129 // User tab 121 130 __('User', 'next-active-directory-integration') => array( 122 131 // Group Name … … 145 154 ), 146 155 ), 147 // Tab name156 // Password tab 148 157 __('Password', 'next-active-directory-integration') => array( 149 158 self::ANGULAR_CONTROLLER => 'PasswordController', … … 165 174 ), 166 175 ), 167 // Tab name176 // Permissions tab 168 177 __('Permissions', 'next-active-directory-integration') => array( 169 178 self::ANGULAR_CONTROLLER => 'PermissionController', … … 189 198 ), 190 199 ), 191 // Tab name192 __('S ecurity', 'next-active-directory-integration') => array(193 self::ANGULAR_CONTROLLER => 'S ecurityController',200 // SSO tab 201 __('SSO', 'next-active-directory-integration') => array( 202 self::ANGULAR_CONTROLLER => 'SsoController', 194 203 self::MULTISITE_ONLY => false, 195 204 // Group name … … 200 209 ), 201 210 __( 202 '<span class="adi-pe-message"><b>Premium Extensions: </b> SingleSignOn for BuddyPress, WooCommerce und Ultimate Member <a href="https://active-directory-wp.com/premium-extension/">available</a>.</span>',211 '<span class="adi-pe-message"><b>Premium Extensions: </b>Active Directory Forest, SingleSignOn for BuddyPress, WooCommerce und Ultimate Member <a href="https://active-directory-wp.com/premium-extension/">available</a>.</span>', 203 212 'next-active-directory-integration' 204 213 )), … … 209 218 NextADInt_Adi_Configuration_Options::SSO_PASSWORD, 210 219 NextADInt_Adi_Configuration_Options::SSO_ENVIRONMENT_VARIABLE, 211 NextADInt_Adi_Configuration_Options::SSO_DISABLE_FOR_XMLRPC 212 ), 213 ), 220 NextADInt_Adi_Configuration_Options::SSO_DISABLE_FOR_XMLRPC, 221 NextADInt_Adi_Configuration_Options::KERBEROS_REALM_MAPPINGS, 222 ), 223 ), 224 ), 225 // Security tab 226 __('Security', 'next-active-directory-integration') => array( 227 self::ANGULAR_CONTROLLER => 'SecurityController', 228 self::MULTISITE_ONLY => false, 214 229 // Group name 215 230 __('Login', 'next-active-directory-integration') => array( … … 249 264 ), 250 265 ), 251 // Tab name266 // Attributes tab 252 267 __('Attributes', 'next-active-directory-integration') => array( 253 268 self::ANGULAR_CONTROLLER => 'AttributesController', … … 278 293 ), 279 294 ), 280 // Tab name295 // Sync to AD tab 281 296 __('Sync to AD', 'next-active-directory-integration') => array( 282 297 self::ANGULAR_CONTROLLER => 'SyncToAdController', … … 298 313 ), 299 314 ), 300 // Tab name315 // Sync to WordPress tab 301 316 __('Sync to WordPress', 'next-active-directory-integration') => array( 302 317 self::ANGULAR_CONTROLLER => 'SyncToWordpressController', … … 321 336 ), 322 337 ), 323 // Tab name338 // Logging tab 324 339 __('Logging', 'next-active-directory-integration') => array( 325 340 self::ANGULAR_CONTROLLER => 'LoggingController', -
next-active-directory-integration/trunk/classes/Adi/Dependencies.php
r2069979 r2513920 27 27 * @return NextADInt_Adi_Dependencies 28 28 */ 29 public static function getInstance() { 29 public static function getInstance() 30 { 30 31 if (self::$_instance === null) { 31 32 self::$_instance = new NextADInt_Adi_Dependencies(); … … 316 317 if ($this->ldapConnection == null) { 317 318 $this->ldapConnection = new NextADInt_Ldap_Connection( 318 $this->getConfiguration() 319 ); 319 $this->getConfiguration(), 320 $this->getActiveDirectoryContext() 321 ); 322 323 $this->ldapConnection->register(); 320 324 } 321 325 … … 509 513 $this->getShowBlockedMessage(), 510 514 $this->getAttributeService(), 511 $this->getLoginState(),515 $this->getLoginState(), 512 516 $this->getLoginSucceededService() 513 517 ); … … 1106 1110 $this->getAttributeService(), 1107 1111 $this->getSsoValidator(), 1108 $this->getLoginState(), 1109 $this->getLoginSucceededService() 1112 $this->getLoginState(), 1113 $this->getLoginSucceededService(), 1114 $this->getSsoProfileLocator() 1110 1115 ); 1111 1116 } … … 1125 1130 { 1126 1131 if ($this->ssoPage == null) { 1127 // TODO SSO Error wp-login1132 // TODO SSO Error wp-login 1128 1133 $this->ssoPage = new NextADInt_Adi_Authentication_Ui_SingleSignOn(); 1129 1134 } … … 1149 1154 } 1150 1155 1151 /**1152 * @var NextADInt_Adi_LoginState1153 */1156 /** 1157 * @var NextADInt_Adi_LoginState 1158 */ 1154 1159 private $loginState = null; 1155 1160 1156 /** 1157 * @return NextADInt_Adi_LoginState 1158 */ 1159 public function getLoginState() { 1160 if ($this->loginState == null) { 1161 $this->loginState = new NextADInt_Adi_LoginState(); 1162 } 1163 1164 return $this->loginState; 1165 } 1166 1167 /** 1168 * @var NextADInt_Adi_Authorization_Service 1169 */ 1161 /** 1162 * @return NextADInt_Adi_LoginState 1163 */ 1164 public function getLoginState() 1165 { 1166 if ($this->loginState == null) { 1167 $this->loginState = new NextADInt_Adi_LoginState(); 1168 } 1169 1170 return $this->loginState; 1171 } 1172 1173 /** 1174 * @var NextADInt_Adi_Authorization_Service 1175 */ 1170 1176 private $authorizationService = null; 1171 1177 1172 /** 1173 * @return NextADInt_Adi_Authorization_Service 1174 */ 1175 public function getAuthorizationService() { 1176 if ($this->authorizationService == null) { 1177 $this->authorizationService = new NextADInt_Adi_Authorization_Service( 1178 $this->getConfiguration(), 1179 $this->getUserManager(), 1180 $this->getRoleManager(), 1181 $this->getLoginState() 1182 ); 1183 } 1184 1185 return $this->authorizationService; 1186 } 1178 /** 1179 * @return NextADInt_Adi_Authorization_Service 1180 */ 1181 public function getAuthorizationService() 1182 { 1183 if ($this->authorizationService == null) { 1184 $this->authorizationService = new NextADInt_Adi_Authorization_Service( 1185 $this->getConfiguration(), 1186 $this->getUserManager(), 1187 $this->getRoleManager(), 1188 $this->getLoginState() 1189 ); 1190 } 1191 1192 return $this->authorizationService; 1193 } 1187 1194 1188 1195 /** … … 1194 1201 * @return NextADInt_Adi_User_LoginSucceededService 1195 1202 */ 1196 public function getLoginSucceededService() { 1203 public function getLoginSucceededService() 1204 { 1197 1205 if ($this->loginSucceededService == null) { 1198 1206 $this->loginSucceededService = new NextADInt_Adi_User_LoginSucceededService( … … 1207 1215 return $this->loginSucceededService; 1208 1216 } 1217 1218 /** 1219 * @var NextADInt_ActiveDirectory_Context 1220 */ 1221 private $activeDirectoryContext; 1222 1223 /** 1224 * @return mixed|NextADInt_ActiveDirectory_Context|void 1225 */ 1226 public function getActiveDirectoryContext() 1227 { 1228 if ($this->activeDirectoryContext == null) { 1229 // factory callback to create a new context 1230 add_filter(NEXT_AD_INT_PREFIX . 'create_dependency_active_directory_context', function ($instance, NextADInt_Multisite_Configuration_Service $configuration) { 1231 if (empty($instance)) { 1232 $instance = new NextADInt_ActiveDirectory_Context([$configuration->getOptionValue(NextADInt_Adi_Configuration_Options::DOMAIN_SID)]); 1233 } 1234 1235 return $instance; 1236 }, 10, 2); 1237 1238 $this->activeDirectoryContext = apply_filters(NEXT_AD_INT_PREFIX . 'create_dependency_active_directory_context', null, $this->getConfiguration()); 1239 } 1240 1241 return $this->activeDirectoryContext; 1242 } 1243 1244 /** 1245 * @var NextADInt_Adi_Authentication_SingleSignOn_Profile_Locator 1246 */ 1247 private $ssoProfileLocator = null; 1248 1249 /** 1250 * @return NextADInt_Adi_Authentication_SingleSignOn_Profile_Locator 1251 * @since 2.0.0 1252 */ 1253 public function getSsoProfileLocator() 1254 { 1255 if ($this->ssoProfileLocator == null) { 1256 $this->ssoProfileLocator = new NextADInt_Adi_Authentication_SingleSignOn_Profile_Locator( 1257 $this->getConfiguration() 1258 ); 1259 } 1260 1261 return $this->ssoProfileLocator; 1262 } 1209 1263 } -
next-active-directory-integration/trunk/classes/Adi/Mail/Notification.php
r1756617 r2513920 77 77 * @return bool 78 78 */ 79 public function sendNotification(NextADInt_Adi_Mail_Message $mail, $useLocalWordPressUser = false, WP_User $wpUser)79 public function sendNotification(NextADInt_Adi_Mail_Message $mail, $useLocalWordPressUser, WP_User $wpUser) 80 80 { 81 81 $url = get_bloginfo('url'); … … 150 150 { 151 151 $attributes = array('sn', 'givenname', 'mail'); 152 $userAttributeValues = $this->ldapConnection->findSanitizedAttributesOfUser( $username, $attributes);152 $userAttributeValues = $this->ldapConnection->findSanitizedAttributesOfUser(NextADInt_Ldap_UserQuery::forPrincipal($username), $attributes); 153 153 154 154 return array( -
next-active-directory-integration/trunk/classes/Adi/Role/Manager.php
r2224724 r2513920 299 299 300 300 $wpRoles = new WP_Roles(); 301 301 302 foreach ($wpRoles->roles as $id => $object) { 302 if ($id === 'zocker') {303 continue;304 }305 303 $result[$id] = $id; 306 304 } -
next-active-directory-integration/trunk/classes/Adi/Synchronization/Abstract.php
r1944146 r2513920 25 25 protected $connectionDetails; 26 26 27 /* @var int */27 /* @var int */ 28 28 private $time = 0; 29 29 … … 35 35 /** 36 36 * @param NextADInt_Multisite_Configuration_Service $configuration 37 * @param NextADInt_Ldap_Connection $connection38 * @param NextADInt_Ldap_Attribute_Service $attributeService37 * @param NextADInt_Ldap_Connection $connection 38 * @param NextADInt_Ldap_Attribute_Service $attributeService 39 39 * */ 40 40 public function __construct(NextADInt_Multisite_Configuration_Service $configuration, 41 NextADInt_Ldap_Connection $connection, 42 NextADInt_Ldap_Attribute_Service $attributeService 43 ) { 41 NextADInt_Ldap_Connection $connection, 42 NextADInt_Ldap_Attribute_Service $attributeService 43 ) 44 { 44 45 $this->configuration = $configuration; 45 46 $this->connection = $connection; … … 56 57 { 57 58 if (NextADInt_Core_Util::native()->iniGet('max_execution_time') >= self::REQUIRED_EXECUTION_TIME_IN_SECONDS) { 58 return; 59 return; 59 60 } 60 61 … … 120 121 foreach ($users as $user) { 121 122 $guid = get_user_meta($user->ID, NEXT_AD_INT_PREFIX . NextADInt_Adi_User_Persistence_Repository::META_KEY_OBJECT_GUID, true); 122 $userDomainSid = get_user_meta( 123 $user->ID, NEXT_AD_INT_PREFIX . NextADInt_Adi_User_Persistence_Repository::META_KEY_DOMAINSID, true 124 ); 125 126 if ($this->isVerifiedDomainMember($userDomainSid)) { 127 $wpUsername = $user->user_login; 128 $r[NextADInt_Core_Util_StringUtil::toLowerCase($guid)] = $wpUsername; 129 } else { 130 $this->logger->warning('User with name ' . $user->user_login . 'is not a member of the target domain.'); 131 } 123 $wpUsername = $user->user_login; 124 $r[NextADInt_Core_Util_StringUtil::toLowerCase($guid)] = $wpUsername; 132 125 } 133 126 … … 147 140 { 148 141 $args = array( 149 'blog_id' => get_current_blog_id(),150 'meta_key' => NEXT_AD_INT_PREFIX . NextADInt_Adi_User_Persistence_Repository::META_KEY_ACTIVE_DIRECTORY_SAMACCOUNTNAME,142 'blog_id' => get_current_blog_id(), 143 'meta_key' => NEXT_AD_INT_PREFIX . NextADInt_Adi_User_Persistence_Repository::META_KEY_ACTIVE_DIRECTORY_SAMACCOUNTNAME, 151 144 'meta_query' => array( 152 145 'relation' => 'AND', 153 146 array( 154 'key' => NEXT_AD_INT_PREFIX . NextADInt_Adi_User_Persistence_Repository::META_KEY_ACTIVE_DIRECTORY_SAMACCOUNTNAME,155 'value' => '',147 'key' => NEXT_AD_INT_PREFIX . NextADInt_Adi_User_Persistence_Repository::META_KEY_ACTIVE_DIRECTORY_SAMACCOUNTNAME, 148 'value' => '', 156 149 'compare' => '!=', 157 150 ), 158 151 ), 159 'exclude' => array(1)152 'exclude' => array(1) 160 153 ); 161 154 … … 174 167 ); 175 168 176 if ($this->isVerifiedDomainMember($userDomainSid)) { 177 array_push($r, $user); 169 $sid = NextADInt_ActiveDirectory_Sid::of($userDomainSid); 170 171 if (!$this->connection->getActiveDirectoryContext()->isMember($sid)) { 172 $this->logger->warning('User with name ' . $user->user_login . 'is not a member of one of the configured domains.'); 173 continue; 178 174 } 179 } 180 181 $this->logger->debug(sizeof($r) . " of " . sizeof($users) . " users in this blog are assigned to the domain SID '" . $this->connection->getDomainSid() . "'"); 175 176 array_push($r, $user); 177 } 178 179 $this->logger->debug(sizeof($r) . " of " . sizeof($users) . " users in this blog are assigned to one of configured domain SIDs " . $this->connection->getActiveDirectoryContext()); 182 180 183 181 return $r; … … 188 186 * Workaround to prevent adLDAP from syncing "Array" as a value for an attribute to the Active Directory. 189 187 * 190 * @param array $attributesToSync188 * @param array $attributesToSync 191 189 * @param string $metaKey 192 190 * … … 203 201 204 202 /** 205 * Check if the user is a member of the Active Directory domain connected to the WordPress site via its domain SID206 *207 * @param string $userDomainSid208 *209 * @return bool true if user is member of domain210 */211 public function isVerifiedDomainMember($userDomainSid)212 {213 if ($userDomainSid == $this->connection->getDomainSid()) {214 return true;215 }216 217 return false;218 }219 220 /**221 203 * Check if username is inside the current linked domain 222 204 * … … 224 206 * @return bool 225 207 */ 226 public function isUsernameInDomain($username) { 208 public function isUsernameInDomain($username) 209 { 227 210 // TODO this method is only called from the child classes after the authentication is succeeded. Can we re-use the user_info from the authentication? 228 211 // TODO this would prevent a second LDAP call 229 212 $adLdap = $this->connection->getAdLdap(); 230 $binarySid = $adLdap->user_info($username, array("objectsid")); 231 $stringSid = $adLdap->convertObjectSidBinaryToString($binarySid[0]["objectsid"][0]); 232 $usersDomainSid = NextADInt_Core_Util_StringUtil::objectSidToDomainSid($stringSid); 233 234 if (empty($binarySid)) { 213 $userInfo = $adLdap->user_info($username, array("objectsid")); 214 215 if (empty($userInfo)) { 235 216 $this->logger->error("SID of user '$username' could not be retrieved. Is the base DN correct? Does the userPrincipalName '$username' exist and not only its sAMAccountName?'"); 236 217 return false; 237 218 } 238 219 239 if ($this->isVerifiedDomainMember($usersDomainSid)) { 220 $objectSid = NextADInt_ActiveDirectory_Sid::of($userInfo[0]["objectsid"][0]); 221 222 try { 223 $this->connection->getActiveDirectoryContext()->checkMembership($objectSid); 240 224 return true; 241 } 242 243 $this->logger->warn('User ' . $username . ' with SID ' . $usersDomainSid . ' (domain SID: ' . $usersDomainSid . ') is not member of domain with domain SID "' . $this->connection->getDomainSid() . "'"); 225 } catch (Exception $e) { 226 $this->logger->warn('User ' . $username . ' is not a domain member: ' . $e->getMessage()); 227 } 228 244 229 return false; 245 230 } -
next-active-directory-integration/trunk/classes/Adi/Synchronization/WordPress.php
r2331595 r2513920 228 228 * Convert the given array into our necessary format. 229 229 * 230 * @param $adUsers 230 * @param $adUsers list of sAMAccountNames 231 231 * 232 232 * @return array|hashmap key is Active Directory objectGUID, value is username … … 237 237 238 238 foreach ($adUsers as $adUser) { 239 $attributes = $this->attributeService->findLdapAttributesOfUser name($adUser);239 $attributes = $this->attributeService->findLdapAttributesOfUser(NextADInt_Ldap_UserQuery::forPrincipal($adUser)); 240 240 $guid = $attributes->getFilteredValue(NextADInt_Adi_User_Persistence_Repository::META_KEY_OBJECT_GUID); 241 241 … … 275 275 $uac = $attributes[$key][0]; 276 276 277 return $uac; 278 } 279 280 /** 281 * Is the account a normal account ? 277 // @see GH-132: https://github.com/NeosIT/active-directory-integration2/issues/132 278 // With PHP 8 we got hit by https://github.com/php/php-src/pull/5331 279 return (int)$uac; 280 } 281 282 /** 283 * Is the account a normal account? 282 284 * Checking for flags that should not be set for a normal user account ( http://www.selfadsi.org/ads-attributes/user-userAccountControl.htm ) 283 285 * … … 289 291 { 290 292 291 // ADI-517Improved logging for UAC Binary Flag check to make it more transparent for the user and improve debugging.293 // @see ADI-517: Improved logging for UAC Binary Flag check to make it more transparent for the user and improve debugging. 292 294 switch ($uac) { 293 295 case (($uac & self::UF_INTERDOMAIN_TRUST_ACCOUNT) === self::UF_INTERDOMAIN_TRUST_ACCOUNT): … … 357 359 */ 358 360 public function disableUserWithoutValidGuid($ldapAttributes, $credentials) { 359 360 if (null === $ldapAttributes->getFilteredValue('objectguid')) {361 // Set domain sid to empty, to prevent non existing user from getting used for sync to wordpress362 $ldapAttributes->setDomainSid('empty'); 363 364 $adiUser = $this->userManager->createAdiUser($credentials, $ldapAttributes);365 $status = $this->createOrUpdateUser($adiUser);366 367 $this->userManager->disable($adiUser->getId(), 'User no longer exists in Active Directory.');368 369 $this->logger->warn('Removed domain sid for user ' . $credentials->getLogin()); 370 371 return $status; 372 }361 if (!empty($ldapAttributes->getFilteredValue('objectguid'))) { 362 return; 363 } 364 365 // Set domain sid to empty, to prevent non existing user from getting used for sync to wordpress 366 $ldapAttributes->setDomainSid('empty'); 367 $this->logger->warn('Removed domain sid for user ' . $credentials->getLogin()); 368 369 $adiUser = $this->userManager->createAdiUser($credentials, $ldapAttributes); 370 $status = $this->createOrUpdateUser($adiUser); 371 372 $this->userManager->disable($adiUser->getId(), 'User no longer exists in Active Directory.'); 373 374 return $status; 373 375 } 374 376 … … 398 400 399 401 // ADI-204: in contrast to the login process we use the guid to determine the LDAP attributes 400 $ldapAttributes = $this->attributeService->findLdapAttributesOfUser($credentials, $guid); 401 402 $ldapAttributes = $this->attributeService->resolveLdapAttributes(NextADInt_Ldap_UserQuery::forGuid($guid, $credentials)); 402 403 403 404 // NADIS-1: Checking if the GUID of a user is valid when user does not exist in the active directory anymore. Therefore, disable user and remove domain sid … … 415 416 416 417 // ADI-235: add domain SID 417 $ldapAttributes->setDomainSid($this->connection->getDomainSid()); 418 $userSid = $ldapAttributes->getFilteredValue('objectsid'); 419 $ldapAttributes->setDomainSid(NextADInt_ActiveDirectory_Sid::of($userSid)->getDomainPartAsSid()->getFormatted()); 418 420 419 421 $elapsedTimeLdap = time() - $startTimerLdap; -
next-active-directory-integration/trunk/classes/Adi/User/LoginSucceededService.php
r2069979 r2513920 50 50 NextADInt_Ldap_Connection $ldapConnection, 51 51 NextADInt_Multisite_Configuration_Service $configuration 52 ) { 52 ) 53 { 53 54 $this->loginState = $loginState; 54 55 $this->attributeService = $attributeService; … … 93 94 public function updateOrCreateUser( 94 95 $wpUser 95 ) { 96 if ( ! $this->loginState->isAuthenticated() || $this->loginState->isAuthorized() === false) { 96 ) 97 { 98 if (!$this->loginState->isAuthenticated() || $this->loginState->isAuthorized() === false) { 97 99 return false; 98 100 } … … 104 106 $authenticatedCredentials = $wpUser; 105 107 108 106 109 // ADI-204: during login we have to use the authenticated user principal name 107 $ldapAttributes = $this->attributeService-> findLdapAttributesOfUser($authenticatedCredentials, null);110 $ldapAttributes = $this->attributeService->resolveLdapAttributes($authenticatedCredentials->toUserQuery()); 108 111 109 112 // ADI-395: wrong base DN leads to exception during Test Authentication … … 129 132 $authenticatedCredentials, $ldapAttributes); 130 133 131 if ( !$preCreateStatus) {134 if (!$preCreateStatus) { 132 135 $this->logger->debug('The preCreateStatus returned false. The user will not be created or updated. If this behavior is not intended, please verify your custom logic using the "auth_before_create_or_update_user" filter works properly.'); 133 136 … … 138 141 139 142 // ADI-309: domain SID gets not synchronized 140 $ domainSid = $this->ldapConnection->getDomainSid();141 $adiUser->getLdapAttributes()->setDomainSid($ domainSid);143 $userSid = NextADInt_ActiveDirectory_Sid::of($ldapAttributes->getFilteredValue('objectsid')); 144 $adiUser->getLdapAttributes()->setDomainSid($userSid->getDomainPartAsSid()->getFormatted()); 142 145 143 146 if ($adiUser->getId()) { … … 182 185 // In 1.0.x users were created even if auoCreateUser was false but they had a role equivalent group. 183 186 // With 2.0.x the user is only created if the option "Auto Create User" is enabled. 184 if ( !$autoCreateUser) {187 if (!$autoCreateUser) { 185 188 $error = 'This user exists in Active Directory, but not in the local WordPress instance. The option "Auto Create User" is __not__ enabled but should be.'; 186 189 $this->logger->error($error); … … 195 198 196 199 // if $this->userManager is null, then do not create the user 197 if ( !$this->userManager) {200 if (!$this->userManager) { 198 201 $this->logger->warn( 199 202 "User '{$user->getUsername()}' will not be created because the user login is only simulated." … … 207 210 } 208 211 209 /**210 * If "Auto Update User" is enabled, the user's profile data is updated. In any case if a $userRole is present, it is synchronized with the backend.211 *212 * @param NextADInt_Adi_User $user213 *214 * @return false|WP_User false if creation is only simulated; int if user has been updated.215 * @throws Exception216 */212 /** 213 * If "Auto Update User" is enabled, the user's profile data is updated. In any case if a $userRole is present, it is synchronized with the backend. 214 * 215 * @param NextADInt_Adi_User $user 216 * 217 * @return false|WP_User false if creation is only simulated; int if user has been updated. 218 * @throws Exception 219 */ 217 220 function updateUser(NextADInt_Adi_User $user) 218 221 { 219 222 $this->logger->debug("Checking preconditions for updating existing user " . $user); 220 223 221 $autoUpdateUser = $this->configuration->getOptionValue(NextADInt_Adi_Configuration_Options::AUTO_UPDATE_USER);224 $autoUpdateUser = $this->configuration->getOptionValue(NextADInt_Adi_Configuration_Options::AUTO_UPDATE_USER); 222 225 $autoUpdatePassword = $this->configuration->getOptionValue(NextADInt_Adi_Configuration_Options::AUTO_UPDATE_PASSWORD); 223 226 -
next-active-directory-integration/trunk/classes/Core/Persistence/WordPressRepository.php
r1541870 r2513920 108 108 * @param array $args 109 109 * @param $mode 110 * @deprecated 110 111 * 111 112 * @return array|null|object 112 113 */ 113 public function wpdb_get_results($sql, $args = array(), $mode)114 public function wpdb_get_results($sql, $args, $mode) 114 115 { 115 116 global $wpdb; -
next-active-directory-integration/trunk/classes/Core/Util/StringUtil.php
r1608780 r2513920 254 254 } 255 255 256 257 /** 258 * Check if the given text ends with the given string. 259 * 260 * Thanks to: 261 * http://stackoverflow.com/questions/834303/startswith-and-endswith-functions-in-php?answertab=votes#tab-top 262 * 263 * @param $needle 264 * @param $haystack 265 * 266 * @return bool 267 */ 268 public static function endsWith($needle, $haystack) 269 { 270 $length = strlen( $needle ); 271 if( !$length ) { 272 return true; 273 } 274 return substr( $haystack, -$length ) === $needle; 275 } 276 256 277 /** 257 278 * Convert the given string to lowercase using {@link mb_strtolower}. -
next-active-directory-integration/trunk/classes/Ldap/Attribute/Repository.php
r1944146 r2513920 58 58 'objectguid', 59 59 'domainsid', 60 'objectsid', 60 61 ); 61 62 -
next-active-directory-integration/trunk/classes/Ldap/Attribute/Service.php
r1756617 r2513920 56 56 * @return array 57 57 */ 58 function parseLdapResponse($attributeNames = array(), $ldapData)58 function parseLdapResponse($attributeNames, $ldapData) 59 59 { 60 60 NextADInt_Core_Assert::notNull($attributeNames); … … 141 141 142 142 /** 143 * Find all LDAP attributes for the user which have been enabled in the blog or multisite 144 * 145 * @param string $username GUID, sAMAccountName or userPrincipalName 146 * @param bool $isGUID 143 * Find all LDAP attributes for a user based upon the given query 144 * 145 * @param NextADInt_Ldap_UserQuery $userQuery GUID, sAMAccountName or userPrincipalName 147 146 * 148 147 * @return NextADInt_Ldap_Attributes 149 148 */ 150 public function findLdapAttributesOfUser name($username, $isGUID = false)149 public function findLdapAttributesOfUser(NextADInt_Ldap_UserQuery $userQuery) 151 150 { 152 151 $attributeNames = $this->attributeRepository->getAttributeNames(); … … 154 153 155 154 // ADI-145: provide API 156 $attributeNames = apply_filters(NEXT_AD_INT_PREFIX . 'ldap_filter_synchronizable_attributes', $attributeNames, $username, $isGUID);157 158 if (!empty($user name)) {155 $attributeNames = apply_filters(NEXT_AD_INT_PREFIX . 'ldap_filter_synchronizable_attributes', $attributeNames, $userQuery); 156 157 if (!empty($userQuery->getPrincipal())) { 159 158 // make sure that only non-empty usernames are resolved 160 $raw = $this->ldapConnection->findAttributesOfUser($user name, $attributeNames, $isGUID);159 $raw = $this->ldapConnection->findAttributesOfUser($userQuery, $attributeNames); 161 160 } 162 161 … … 167 166 168 167 /** 169 * Find the LDAP attributes for the given credentials or guid. 170 * 171 * @param NextADInt_Adi_Authentication_Credentials $credentials 172 * @param string $guid 173 * 168 * Based upon the query, different markers are tried to find the user: 169 * <ul> 170 * <li>if the query is specified as GUID; this if searched first</li> 171 * <li>userPrincipalName is tried as second</li> 172 * <li>sAMAccountNAme is tried last in line. This can deliver multiple results in an AD forest. You have to use the Active Directory Forest premium extension</li> 173 * </ul> 174 * 175 * @param NextADInt_Ldap_UserQuery $userQuery 174 176 * @return NextADInt_Ldap_Attributes 175 */ 176 public function findLdapAttributesOfUser(NextADInt_Adi_Authentication_Credentials $credentials, $guid) 177 { 178 if (isset($guid)) { 179 $ldapAttributes = $this->findLdapAttributesOfUsername($guid, true); 180 } 181 177 * @see ADI-713 178 */ 179 public function resolveLdapAttributes(NextADInt_Ldap_UserQuery $userQuery) 180 { 181 /** 182 * @var NextADInt_Ldap_Attributes 183 */ 184 $ldapAttributes = null; 185 186 // GUID has priority 187 if ($userQuery->isGuid()) { 188 $ldapAttributes = $this->findLdapAttributesOfUser($userQuery); 189 } 190 191 // NADIS-133: When using a Global Catalog (GC), users with same sAMAccountName but different userPrincipalNames are not assigned correct during authentication 192 // this requires us to lookup the userPrincipalName *before* the sAMAccountName 182 193 if (empty($ldapAttributes) || (false == $ldapAttributes->getRaw())) { 183 $ldapAttributes = $this->findLdapAttributesOfUsername($credentials->getSAMAccountName()); 184 } 185 194 $ldapAttributes = $this->findLdapAttributesOfUser($userQuery->withPrincipal($userQuery->getCredentials()->getUserPrincipalName())); 195 } 196 197 // fallback to the sAMAccountName 186 198 if (empty($ldapAttributes) || (false == $ldapAttributes->getRaw())) { 187 $ldapAttributes = $this->findLdapAttributesOfUser name($credentials->getUserPrincipalName());199 $ldapAttributes = $this->findLdapAttributesOfUser($userQuery->withPrincipal($userQuery->getCredentials()->getSAMAccountName())); 188 200 } 189 201 … … 196 208 197 209 /** 198 * Find the custom LDAP attribute for the given user name199 * @param string $username210 * Find the custom LDAP attribute for the given user query 211 * @param NextADInt_Ldap_UserQuery $userQuery 200 212 * @param string $attribute 201 213 * @return bool|string false if attribute is empty or not inside the returned array of attribute values 202 214 */ 203 public function findLdapCustomAttributeOfUser name($username, $attribute)215 public function findLdapCustomAttributeOfUser(NextADInt_Ldap_UserQuery $userQuery, $attribute) 204 216 { 205 217 $attributes = array($attribute); 206 218 207 $raw = $this->ldapConnection->findAttributesOfUser($user name, $attributes, false);219 $raw = $this->ldapConnection->findAttributesOfUser($userQuery, $attributes); 208 220 $filtered = $this->parseLdapResponse($attributes, $raw); 209 221 … … 217 229 218 230 /** 219 * Find a single attribute for the give credentials. It first tests the sAMAccountName and then the userPrincipalName of the credentials231 * Find a single attribute for the given credentials. It first tests the userPrincipalName and then the sAMAccountName of the credentials 220 232 * 221 233 * @param NextADInt_Adi_Authentication_Credentials $credentials … … 223 235 * @return string|bool if attribute could not be found it returns false 224 236 */ 225 public function findLdapCustomAttributeOfUser(NextADInt_Adi_Authentication_Credentials $credentials, $attribute)226 { 227 $value = $this->findLdapCustomAttributeOfUser name($credentials->getUserPrincipalName(), $attribute);237 public function resolveLdapCustomAttribute(NextADInt_Ldap_UserQuery $userQuery, $attribute) 238 { 239 $value = $this->findLdapCustomAttributeOfUser($userQuery->withPrincipal($userQuery->getCredentials()->getUserPrincipalName()), $attribute); 228 240 229 241 if (false === $value) { 230 $this->logger->warn("Could not locate custom attribute '" . $attribute . "' for userPrincipalName '" . $credentials->getUserPrincipalName() . "'. Fall back to sAMAccountName...'");231 232 $value = $this->findLdapCustomAttributeOfUser name($credentials->getSAMAccountName(), $attribute);242 $this->logger->warn("Could not locate custom attribute '" . $attribute . "' for query '" . $userQuery->getCredentials()->getUserPrincipalName() . "'. Fall back to sAMAccountName...'"); 243 244 $value = $this->findLdapCustomAttributeOfUser($userQuery->withPrincipal($userQuery->getCredentials()->getSAMAccountName()), $attribute); 233 245 } 234 246 … … 240 252 * 241 253 * @param NextADInt_Adi_Authentication_Credentials $credentials 242 * @return NextADInt_Ldap_Attributes|false false if username account could not be found254 * @return ActiveDirectory_Sid|false false if username account could not be found 243 255 */ 244 256 public function getObjectSid(NextADInt_Adi_Authentication_Credentials $credentials) 245 257 { 246 258 NextADInt_Core_Assert::notNull($credentials, "credentials must not be null"); 247 $objectSid = $this->findLdapCustomAttributeOfUser($credentials , 'objectsid');259 $objectSid = $this->findLdapCustomAttributeOfUser($credentials->toUserQuery(), 'objectsid'); 248 260 249 261 if (false === $objectSid) { … … 251 263 } 252 264 253 return $this->ldapConnection->getAdLdap()->convertObjectSidBinaryToString($objectSid);265 return NextADInt_ActiveDirectory_Sid::of($objectSid); 254 266 } 255 267 … … 259 271 * @return string|boolean 260 272 */ 261 public function getNetBiosName() { 273 public function getNetBiosName() 274 { 262 275 $netBiosName = $this->ldapConnection->findNetBiosName(); 263 276 -
next-active-directory-integration/trunk/classes/Ldap/Connection.php
r2331595 r2513920 28 28 private $logger; 29 29 30 /* @var string*/31 private $ siteDomainSid;30 /* @var NextADInt_ActiveDirectory_Context */ 31 private $activeDirectoryContext; 32 32 33 33 /** 34 34 * @param NextADInt_Multisite_Configuration_Service $configuration 35 */ 36 public function __construct(NextADInt_Multisite_Configuration_Service $configuration) 35 * @param NextADInt_ActiveDirectory_Context $activeDirectoryContext 36 */ 37 public function __construct(NextADInt_Multisite_Configuration_Service $configuration, 38 NextADInt_ActiveDirectory_Context $activeDirectoryContext 39 ) 37 40 { 38 41 if (!class_exists('adLDAP')) { … … 40 43 require_once NEXT_AD_INT_PATH . '/vendor/adLDAP/adLDAP.php'; 41 44 } 42 45 43 46 $this->configuration = $configuration; 47 $this->activeDirectoryContext = $activeDirectoryContext; 44 48 45 49 $this->logger = NextADInt_Core_Logger::getLogger(); 50 } 51 52 /** 53 * Register additional hooks 54 * @since 2.0.0 55 */ 56 public function register() 57 { 58 // ADI-713: Map user information when search for GUID, userPrincipalName or sAMAccountName 59 add_filter(NEXT_AD_INT_PREFIX . 'ldap_map_userinfo', array($this, 'mapUserInfo'), 10, 5); 46 60 } 47 61 … … 81 95 82 96 $config = array( 83 'account_suffix' => '',84 'base_dn' => $this->getBaseDn($connectionDetails),97 'account_suffix' => '', 98 'base_dn' => $this->getBaseDn($connectionDetails), 85 99 'domain_controllers' => $this->getDomainControllers($connectionDetails), 86 'ad_port' => $this->getAdPort($connectionDetails),87 'use_tls' => $useTls, //StartTLS88 //ADI-482 enable LDAPS support89 'use_ssl' => $useSsl, //LDAP over Ssl 90 'network_timeout' => $this->getNetworkTimeout($connectionDetails),91 'allow_self_signed'=> $this->getAllowSelfSigned($connectionDetails),92 'ad_username' => $connectionDetails->getUsername(),93 'ad_password' => $connectionDetails->getPassword(),100 'ad_port' => $this->getAdPort($connectionDetails), 101 'use_tls' => $useTls, // STARTTLS 102 // ADI-482 enable LDAPS support 103 'use_ssl' => $useSsl, // LDAP over SSL 104 'network_timeout' => $this->getNetworkTimeout($connectionDetails), 105 'allow_self_signed' => $this->getAllowSelfSigned($connectionDetails), 106 'ad_username' => $connectionDetails->getUsername(), 107 'ad_password' => $connectionDetails->getPassword(), 94 108 ); 95 109 … … 189 203 } 190 204 191 /**192 * Return the usage of SSL based upon the $connectionDetails. If the usage of SSL is not set the usage of SSL of the current blog instance is returned.193 *194 * @param NextADInt_Ldap_ConnectionDetails $connectionDetails195 *196 * @return bool197 */198 public function getUseSsl(NextADInt_Ldap_ConnectionDetails $connectionDetails)199 {200 return $this->getEncryption($connectionDetails) === NextADInt_Multisite_Option_Encryption::LDAPS;201 }205 /** 206 * Return the usage of SSL based upon the $connectionDetails. If the usage of SSL is not set the usage of SSL of the current blog instance is returned. 207 * 208 * @param NextADInt_Ldap_ConnectionDetails $connectionDetails 209 * 210 * @return bool 211 */ 212 public function getUseSsl(NextADInt_Ldap_ConnectionDetails $connectionDetails) 213 { 214 return $this->getEncryption($connectionDetails) === NextADInt_Multisite_Option_Encryption::LDAPS; 215 } 202 216 203 217 /** … … 233 247 $allowSelfSigned = $this->configuration->getOptionValue(NextADInt_Adi_Configuration_Options::ALLOW_SELF_SIGNED); 234 248 } 235 249 236 250 return $allowSelfSigned; 237 251 } … … 284 298 return is_object($this->adldap); 285 299 } 286 300 287 301 /** 288 302 * Find the sAMAccountName associated with a ProxyAddress 289 * 290 * @param string $proxyAddress The proxy address to check291 * 292 * @return false if not found or the sAMAccountName.303 * 304 * @param string $proxyAddress The proxy address to check 305 * 306 * @return false if not found or the sAMAccountName. 293 307 */ 294 308 public function findByProxyAddress($proxyAddress) … … 382 396 * Lookup the requested LDAP attributes for the user from the underlying Active Directory connection 383 397 * 384 * @param string $username 385 * @param array $attributeNames 386 * @param bool $isGUID 398 * @param NextADInt_Ldap_UserQuery $userQuery 399 * @param array $attributeNames 387 400 * 388 401 * @return array 389 402 */ 390 public function findAttributesOfUser( $username, $attributeNames, $isGUID = false)403 public function findAttributesOfUser(NextADInt_Ldap_UserQuery $userQuery, $attributeNames) 391 404 { 392 405 $adLdap = $this->getAdLdap(); 393 406 394 $ userInfo = $adLdap->user_info($username, $attributeNames, $isGUID);395 396 if ($ userInfo=== false) {397 $this->logger->warn(" Attributes for '$username': could not be loaded. Does the sAMAccountName or userPrincipalName exist? Is the provided base DN valid?");407 $matchesFromLdap = $adLdap->user_info($userQuery->getPrincipal(), $attributeNames, $userQuery->isGuid()); 408 409 if ($matchesFromLdap === false) { 410 $this->logger->warn("Query '$userQuery' did not return any values. Does the sAMAccountName or userPrincipalName exist? Is the provided base DN valid? Is the Kerberos realm mapped"); 398 411 399 412 return false; 400 413 } 401 414 402 // user does exist, get first element 403 $userInfo = $userInfo[0]; 404 405 $this->logger->debug("UserInfo for user '$username': " . $this->__debug($userInfo)); 415 // ADI-713: try to extract the user's information from a list of arrays 416 $userInfo = apply_filters(NEXT_AD_INT_PREFIX . 'ldap_map_userinfo', false, $matchesFromLdap, $matchesFromLdap['count'], $userQuery, $attributeNames); 417 418 if ($userInfo) { 419 $this->logger->debug("UserInfo for user '" . $userQuery . "': " . $this->__debug($userInfo)); 420 } 406 421 407 422 return $userInfo; 423 } 424 425 /** 426 * After the Active Directory has been queried to look for a GUID, userPrincipalName or sAMAccountName, this method will be called. 427 * 428 * @param boolean|mixed $bestMatch The best match being used. It is false if no match has been found yet. 429 * @param array $matchesFromLdap 430 * @param integer $totalMatches number of matches; due to the adLDAP structure 431 * @param NextADInt_Ldap_UserQuery $userQuery 432 * @param array $attributeNames 433 * @return array|boolean the $bestMatch exactly one match or false 434 * @see ADI-713 435 * @since 2.1.13 436 */ 437 public function mapUserInfo($bestMatch, $matchesFromLdap, $totalMatches, NextADInt_Ldap_UserQuery $userQuery, $attributeNames) 438 { 439 // there has not been a best match specified; this method is the fallback option 440 if (!$bestMatch) { 441 // we got more than one result for the DC/GC; this can happen if a sAMAccountName is queried inside a AD forest 442 if ($totalMatches > 1) { 443 $this->logger->error('The user query "' . $userQuery . "' returned " . $totalMatches . ' results. You have to do additional configuration if you are running NADI inside an AD forest.'); 444 $bestMatch = false; 445 } // we have exactly one result, so we will use it 446 else { 447 $bestMatch = $matchesFromLdap[0]; 448 } 449 } 450 451 return $bestMatch; 408 452 } 409 453 … … 427 471 } 428 472 429 $this->logger->debug("Found NetBIOS name '" . $netbios . "' for '" . $this->getDomainSid());473 $this->logger->debug("Found NetBIOS name '" . $netbios . "' for domain SIDs " . $this->activeDirectoryContext); 430 474 431 475 return $netbios; … … 440 484 * @return string 441 485 */ 442 public function __debug($userInfo = array()) { 486 private function __debug($userInfo = array()) 487 { 443 488 $result = ""; 444 489 $maxOutputChars = 32; … … 458 503 459 504 // remove any linebreaks or carriagereturns from the attributes 460 $element = preg_replace("/\r\n|\r|\n/", '',$element);505 $element = preg_replace("/\r\n|\r|\n/", '', $element); 461 506 462 507 if ($attribute === "objectguid") { … … 466 511 $this->logger->error("An exception occurred trying to convert binary to GUID. Exception: " . $exception->getMessage()); 467 512 } 468 469 513 } 470 514 471 $result .= NextADInt_Core_Util_StringUtil::firstChars($element, 500);515 $result .= NextADInt_Core_Util_StringUtil::firstChars($element, 500); 472 516 473 517 } … … 488 532 * Lookup all requested attributes and instantly sanitize them. 489 533 * 490 * @param string $username491 * @param array $attributes534 * @param NextADInt_Ldap_UserQuery $userQuery 535 * @param array $attributes 492 536 * 493 537 * @return array 494 538 */ 495 public function findSanitizedAttributesOfUser( $username, $attributes)496 { 497 $userInfo = $this->findAttributesOfUser($user name, $attributes);539 public function findSanitizedAttributesOfUser(NextADInt_Ldap_UserQuery $userQuery, $attributes) 540 { 541 $userInfo = $this->findAttributesOfUser($userQuery, $attributes); 498 542 $sanitized = array(); 499 543 … … 512 556 * 513 557 * @param WP_User $wpUser 514 * @param array $attributes Map with attributes and their values558 * @param array $attributes Map with attributes and their values 515 559 * 516 560 * @return bool … … 587 631 * 588 632 * @param string $domainController 589 * @param int $port590 * @param int $timeout633 * @param int $port 634 * @param int $timeout 591 635 * 592 636 * @return bool true if port could be opened, false if port could not be opened or fsockopen is not available. … … 675 719 * @return array 676 720 */ 677 function filterDomainMembers($members = array()) { 721 function filterDomainMembers($members = array()) 722 { 678 723 $adLdap = $this->getAdLdap(); 679 $siteDomainSid = $this->getDomainSid();680 724 $r = array(); 681 725 682 726 foreach ($members as $member) { 683 727 $userInfo = $adLdap->user_info($member, array('objectsid')); 684 $userSid = $adLdap->convertObjectSidBinaryToString($userInfo[0]["objectsid"][0]); 685 686 if (strpos($userSid, $siteDomainSid) !== false) { 687 $r[NextADInt_Core_Util_StringUtil::toLowerCase($member)] = $member; 688 } 728 729 $objectSid = NextADInt_ActiveDirectory_Sid::of($userInfo[0]["objectsid"][0]); 730 731 if (!$this->activeDirectoryContext->isMember($objectSid)) { 732 $this->logger->debug("Object '" . $objectSid->getFormatted() . "' does not belong to one of the configured domains of " . $this->activeDirectoryContext); 733 continue; 734 } 735 736 $r[NextADInt_Core_Util_StringUtil::toLowerCase($member)] = $member; 689 737 } 690 738 691 739 return $r; 692 }693 694 /**695 * Return the domain SID of the current synchronization696 *697 * @return mixed|string698 */699 public function getDomainSid() {700 if (empty($this->siteDomainSid)) {701 $this->siteDomainSid = $this->configuration->getOptionValue(NextADInt_Adi_Configuration_Options::DOMAIN_SID);702 }703 704 return $this->siteDomainSid;705 740 } 706 741 … … 739 774 return false; 740 775 } 776 777 /** 778 * @return NextADInt_ActiveDirectory_Context 779 */ 780 public function getActiveDirectoryContext() 781 { 782 return $this->activeDirectoryContext; 783 } 741 784 } -
next-active-directory-integration/trunk/classes/Multisite/Configuration/Persistence/BlogConfigurationRepository.php
r2331595 r2513920 41 41 private $defaultProfileRepository; 42 42 43 /** 44 * @param NextADInt_Multisite_Option_Sanitizer $sanitizer 45 * @param NextADInt_Core_Encryption $encryptionHandler 46 * @param NextADInt_Multisite_Option_Provider $optionProvider 43 private $siteToProfileCache = array(); 44 45 /** 46 * @param NextADInt_Multisite_Option_Sanitizer $sanitizer 47 * @param NextADInt_Core_Encryption $encryptionHandler 48 * @param NextADInt_Multisite_Option_Provider $optionProvider 47 49 * @param NextADInt_Multisite_Configuration_Persistence_ProfileConfigurationRepository $profileConfigurationRepository 48 * @param NextADInt_Multisite_Configuration_Persistence_DefaultProfileRepository $defaultProfileRepository50 * @param NextADInt_Multisite_Configuration_Persistence_DefaultProfileRepository $defaultProfileRepository 49 51 */ 50 52 public function __construct(NextADInt_Multisite_Option_Sanitizer $sanitizer, … … 53 55 NextADInt_Multisite_Configuration_Persistence_ProfileConfigurationRepository $profileConfigurationRepository, 54 56 NextADInt_Multisite_Configuration_Persistence_DefaultProfileRepository $defaultProfileRepository 55 ) { 57 ) 58 { 56 59 $this->sanitizer = $sanitizer; 57 60 $this->encryptionHandler = $encryptionHandler; … … 107 110 * Moreover this method sanitize, decrypt etc. the value. 108 111 * 109 * @param int $siteSiteId112 * @param int $siteId 110 113 * @param string $optionName 111 114 * 112 115 * @return null|string 113 116 */ 114 public function findSanitizedValue($site SiteId, $optionName)115 { 116 // prevent change of associated profile117 public function findSanitizedValue($siteId, $optionName) 118 { 119 // prevent change of associated profile 117 120 if (self::PROFILE_ID === $optionName) { 118 121 return null; 119 122 } 120 123 121 if ($this->isOptionHandledByProfile($siteSiteId, $optionName)) { 122 $profileId = $this->findProfileId($siteSiteId); 123 124 return $this->profileConfigurationRepository->findSanitizedValue($profileId, $optionName); 125 } 126 127 $optionValue = $this->findRawValue($siteSiteId, $optionName); 124 $optionValue = $this->findRawValue($siteId, $optionName); 125 $noOptionValueInSite = $optionValue == null; 126 $profileId = $this->findProfileId($siteId); 127 128 // #124: when a profile is connected and no value has been yet inside the blog, we have to return the profile's value 129 if ($profileId) { 130 // and either no value for this option has been defined or it's handled by the profile 131 if ($noOptionValueInSite || $this->isOptionHandledByProfile($siteId, $optionName)) { 132 return $this->profileConfigurationRepository->findSanitizedValue($profileId, $optionName); 133 } 134 } 135 128 136 $optionMetadata = $this->optionProvider->get($optionName); 129 137 130 if ( false=== $optionValue) {131 $optionValue = $this->getDefaultValue($site SiteId, $optionName, $optionMetadata);138 if (null === $optionValue) { 139 $optionValue = $this->getDefaultValue($siteId, $optionName, $optionMetadata); 132 140 } 133 141 … … 149 157 * Check if the current option is handled by a profile. 150 158 * 151 * @param int $siteId159 * @param int $siteId 152 160 * @param string $optionName 153 161 * … … 157 165 { 158 166 $profileId = $this->findProfileId($siteId); 159 $ permission = $this->profileConfigurationRepository->findSanitizedPermission($profileId, $optionName);160 161 if (NextADInt_Multisite_Configuration_Service::EDITABLE > $ permission) {167 $forcePermission = $this->profileConfigurationRepository->findSanitizedPermission($profileId, $optionName); 168 169 if (NextADInt_Multisite_Configuration_Service::EDITABLE > $forcePermission) { 162 170 return true; 163 171 } … … 170 178 * the sanitizer will create a new value from the default value. This value will be persist, requested and returned. 171 179 * 172 * @param int $siteId180 * @param int $siteId 173 181 * @param string $optionName 174 182 * @param array $option … … 176 184 * @return bool|mixed|null|string 177 185 */ 178 publicfunction getDefaultValue($siteId, $optionName, $option)186 function getDefaultValue($siteId, $optionName, $option) 179 187 { 180 188 // gh-#127: PHP 7.4 compatibility; warning if $option is not an array but null … … 199 207 /** 200 208 * This method should not be called by the outside (expect for the migration of the encrypted passwords). 201 * Read the value for option $optionName and site /blog $blogId.202 * 203 * @param int $siteId209 * Read the value for option $optionName and site $siteId. 210 * 211 * @param int $siteId 204 212 * @param string $optionName 205 213 * … … 211 219 212 220 if (is_multisite()) { 213 return get_blog_option($siteId, $name, false); 214 } 215 216 return get_option($name, false); 221 $r = get_blog_option($siteId, $name, null); 222 return $r; 223 } 224 225 return get_option($name, null); 217 226 } 218 227 … … 221 230 * Moreover this method sanitize, encrypt etc. the value. 222 231 * 223 * @param int $siteSiteId232 * @param int $siteId 224 233 * @param string $optionName 225 234 * @param string $optionValue … … 227 236 * @return string $optionValue return the sanitized value 228 237 */ 229 public function persistSanitizedValue($site SiteId, $optionName, $optionValue)238 public function persistSanitizedValue($siteId, $optionName, $optionValue) 230 239 { 231 240 if (self::PROFILE_ID === $optionName) { … … 246 255 } 247 256 248 return $this->persist($site SiteId, $optionName, $optionValue);257 return $this->persist($siteId, $optionName, $optionValue); 249 258 } 250 259 … … 253 262 * Write the value $optionValue for option $optionName and blog/site $blogId. 254 263 * 255 * @param int $siteId264 * @param int $siteId 256 265 * @param string $optionName 257 266 * @param mixed $optionValue … … 275 284 } 276 285 277 // Singlesite286 // Singlesite 278 287 } else { 279 288 $optionExists = $this->doesOptionExist($optionName); … … 304 313 * @return bool 305 314 */ 306 protected function createOption($optionName, $optionValue, $siteId = null) { 315 protected function createOption($optionName, $optionValue, $siteId = null) 316 { 307 317 308 318 // Create Multi Site option 309 319 if ($siteId) { 310 320 $success = add_blog_option($siteId, $optionName, $optionValue); 311 } 312 // Create Single Site option 321 } // Create Single Site option 313 322 else { 314 323 $success = add_option($optionName, $optionValue, false); … … 333 342 * @return bool 334 343 */ 335 protected function updateOption($optionName, $optionValue, $siteId = null) { 344 protected function updateOption($optionName, $optionValue, $siteId = null) 345 { 336 346 337 347 // Update Multi Site option 338 348 if ($siteId) { 339 349 $success = update_blog_option($siteId, $optionName, $optionValue); 340 } 341 // Update Single Site option 350 } // Update Single Site option 342 351 else { 343 352 $success = update_option($optionName, $optionValue, false); … … 361 370 * @return bool 362 371 */ 363 protected function doesOptionExist($optionName, $siteId = null) { 372 protected function doesOptionExist($optionName, $siteId = null) 373 { 364 374 365 375 if ($siteId) { … … 392 402 393 403 /** 394 * Get id of the associated profile of this blog $blogId. 404 * Get id of the associated profile of this site's $siteId. 405 * To make it more performant, the linked profile is cached. 395 406 * 396 407 * @param int $siteId … … 400 411 public function findProfileId($siteId) 401 412 { 402 $profileId = $this->findRawValue($siteId, self::PROFILE_ID); 403 404 if (false === $profileId) { 405 $profileId = $this->defaultProfileRepository->findProfileId(); 406 } 407 408 return $profileId; 413 $key = "K-" . $siteId; 414 415 if (!isset($this->siteToProfileCache[$key])) { 416 $profileId = $this->findRawValue($siteId, self::PROFILE_ID); 417 418 // no profile for this site has been specified, so find the default profile 419 if (!is_numeric($profileId)) { 420 $profileId = $this->defaultProfileRepository->findProfileId(); 421 } 422 423 $this->siteToProfileCache[$key] = (int)$profileId; 424 } 425 426 return $this->siteToProfileCache[$key]; 409 427 } 410 428 … … 412 430 * Set id of the associated profile of this blog $blogId. 413 431 * 414 * @param int $siteId432 * @param int $siteId 415 433 * @param string $profileId 416 434 * … … 425 443 * Delete the associated of the profile with a blog $siteId. 426 444 * 427 * @param int $siteId445 * @param int $siteId 428 446 * @param string $profileId 429 447 * … … 439 457 * Delete an option value. 440 458 * 441 * @param int $siteId459 * @param int $siteId 442 460 * @param string $optionName 443 461 * … … 519 537 * Get the option permission for the profile and the option. 520 538 * 521 * @param int $profileId539 * @param int $profileId 522 540 * @param string $optionName 523 541 * … … 530 548 531 549 /** 532 * @param int $profileId533 * @param string $optionName 534 * @param int $optionPermission between [0,3]550 * @param int $profileId 551 * @param string $optionName 552 * @param int $optionPermission between [0,3] 535 553 * 536 554 * @return bool -
next-active-directory-integration/trunk/classes/Multisite/Configuration/Persistence/ConfigurationRepository.php
r1608780 r2513920 19 19 * Find the value of the given option 20 20 * 21 * @param int $ siteId21 * @param int $id 22 22 * @param string $optionName 23 23 * 24 24 * @return mixed 25 25 */ 26 public function findSanitizedValue($ siteId, $optionName);26 public function findSanitizedValue($id, $optionName); 27 27 28 28 /** -
next-active-directory-integration/trunk/classes/Multisite/Configuration/Persistence/DefaultProfileRepository.php
r1541870 r2513920 29 29 $profileId = get_site_option($name, false); 30 30 31 return (false === $profileId) ? -1 : $profileId;31 return (false === $profileId) ? -1 : (int)$profileId; 32 32 } 33 33 -
next-active-directory-integration/trunk/classes/Multisite/Configuration/Persistence/ProfileConfigurationRepository.php
r1756617 r2513920 67 67 * Get the option $optionName for the profile $profileId. 68 68 * 69 * @param int $profile SiteId69 * @param int $profileId 70 70 * @param string $optionName 71 71 * 72 72 * @return object 73 73 */ 74 public function findSanitizedValue($profile SiteId, $optionName)75 { 76 $value = $this->findRawValue($profile SiteId, $optionName);74 public function findSanitizedValue($profileId, $optionName) 75 { 76 $value = $this->findRawValue($profileId, $optionName); 77 77 $optionMetadata = $this->optionProvider->get($optionName); 78 78 79 79 if (false === $value) { 80 $optionValue = $this->getDefaultValue($profile SiteId, $optionName, $optionMetadata);80 $optionValue = $this->getDefaultValue($profileId, $optionName, $optionMetadata); 81 81 } 82 82 -
next-active-directory-integration/trunk/classes/Multisite/Configuration/Service.php
r2331595 r2513920 9 9 10 10 /** 11 * Multisite_Configura iton_Service returns the value for an option name.11 * Multisite_Configuration_Service returns the value for an option name. 12 12 * 13 * Multisite_Configura iton_Service return the option value depending on the WordPress installation (single/multi side), profile settings and blog settings.13 * Multisite_Configuration_Service return the option value depending on the WordPress installation (single/multi side), profile settings and blog settings. 14 14 * 15 15 * @author Tobias Hellmann <[email protected]> … … 53 53 /* @var array */ 54 54 private $cache = array(); 55 56 55 57 56 /** … … 96 95 * 97 96 * @param string $optionName 98 * @param int|null $ blogId if null, the current blog is used97 * @param int|null $siteId if null, the current blog is used 99 98 * 100 99 * @return mixed 101 100 */ 102 public function getOptionValue($optionName, $ blogId = null)103 { 104 $option = $this->getOption($optionName, $ blogId);101 public function getOptionValue($optionName, $siteId = null) 102 { 103 $option = $this->getOption($optionName, $siteId); 105 104 106 105 return NextADInt_Core_Util_ArrayUtil::get('option_value', $option); … … 108 107 109 108 /** 110 * Get the option hashmap with keys 'option_value', 'option_name', 'option_permission' for the option $optionName of blog $blogId. 111 * If $blogId is null, then the current blog will be used. 109 * Get the option hashmap with keys 'option_value', 'option_name', 'option_permission' for the option $optionName of site $siteId. 112 110 * 113 111 * @param string $optionName name of option to lookup 114 * @param int|null $ blogId if null, the current blog is used112 * @param int|null $siteId if null, the current blog is used 115 113 * 116 114 * @return array 117 115 */ 118 public function getOption($optionName, $blogId = null) 119 { 120 if ($blogId === null) { 121 $blogId = get_current_blog_id(); 122 } 123 124 if (isset($this->cache[$blogId][$optionName]) && is_array($this->cache[$blogId][$optionName])) { 125 return $this->cache[$blogId][$optionName]; 126 } 127 128 $blogOptionValue = $this->blogConfigurationRepository->findSanitizedValue($blogId, $optionName); 129 $profileId = $this->blogConfigurationRepository->findProfileId($blogId); 116 public function getOption($optionName, $siteId = null) 117 { 118 if ($siteId === null) { 119 $siteId = get_current_blog_id(); 120 } 121 122 if (isset($this->cache[$siteId][$optionName]) && is_array($this->cache[$siteId][$optionName])) { 123 return $this->cache[$siteId][$optionName]; 124 } 125 126 $blogOptionValue = $this->blogConfigurationRepository->findSanitizedValue($siteId, $optionName); 127 128 $profileId = $this->blogConfigurationRepository->findProfileId($siteId); 129 130 130 $profileHasLinkedDomain = false; 131 131 132 132 if ($profileId != null) { 133 $profileDomainSid = $this->getProfileOptionValue(NextADInt_Adi_Configuration_Options::DOMAIN_SID, $ blogId);133 $profileDomainSid = $this->getProfileOptionValue(NextADInt_Adi_Configuration_Options::DOMAIN_SID, $siteId); 134 134 135 135 if (!empty($profileDomainSid)) { … … 138 138 } 139 139 140 $profileOptionValue = $this->getProfileOptionValue($optionName, $ blogId);140 $profileOptionValue = $this->getProfileOptionValue($optionName, $siteId); 141 141 $permission = $this->getPermission($optionName, $profileId); 142 142 … … 161 161 ); 162 162 163 $this->cache[$ blogId][$optionName] = $optionArray;163 $this->cache[$siteId][$optionName] = $optionArray; 164 164 165 165 return $optionArray; … … 171 171 * Do not call this method from the outside. 172 172 * 173 * @param int|null $ blogId173 * @param int|null $siteId 174 174 * @param string $optionName 175 175 * 176 176 * @return null|array null if singlesite installation 177 177 */ 178 public function getProfileOptionValue($optionName, $blogId = null)178 function getProfileOptionValue($optionName, $siteId = null) 179 179 { 180 180 if (!is_multisite()) { … … 182 182 } 183 183 184 $profileId = $this->blogConfigurationRepository->findProfileId($ blogId);184 $profileId = $this->blogConfigurationRepository->findProfileId($siteId); 185 185 $profileOption = $this->profileConfigurationRepository->findSanitizedValue($profileId, $optionName); 186 186 … … 197 197 * @param mixed $blogOptionValue 198 198 * 199 * @return mixed $blogOp otionValue if $permission is EDITABLE, otherwise $profileOptionValue199 * @return mixed $blogOptionValue if $permission is EDITABLE, otherwise $profileOptionValue 200 200 */ 201 201 protected function getValue($permission, $profileOptionValue, $blogOptionValue) … … 229 229 230 230 /** 231 * Find all options for the current site 231 * Find all options for the current site. 232 * It merges the default profile options with its overriden settings fo the current site. 233 * 232 234 * @return array|mixed 233 235 */ 234 236 public function getAllOptions() 235 237 { 238 $siteId = get_current_blog_id(); 239 240 236 241 $allOptionNames = $this->blogConfigurationRepository->getAllOptionNames(); 237 $profileId = $this->blogConfigurationRepository->findProfileId(get_current_blog_id()); 238 239 $options = array(); 242 $profileId = $this->blogConfigurationRepository->findProfileId($siteId); 240 243 241 244 foreach ($allOptionNames as $name) { 242 $buffer = $this->getOption($name );245 $buffer = $this->getOption($name, $siteId); 243 246 244 247 if ($name == "additional_user_attributes") { //TODO find better solution … … 334 337 NextADInt_Adi_Configuration_Options::VERIFICATION_USERNAME, 335 338 NextADInt_Adi_Configuration_Options::VERIFICATION_PASSWORD, 336 NextADInt_Adi_Configuration_Options::ENCRYPTION 339 NextADInt_Adi_Configuration_Options::ENCRYPTION, 340 NextADInt_Adi_Configuration_Options::ADDITIONAL_DOMAIN_SIDS 337 341 ); //TODO move somewhere else 338 342 -
next-active-directory-integration/trunk/classes/Multisite/Ui/BlogConfigurationPage.php
r2331595 r2513920 45 45 private $actionMapping 46 46 = array( 47 self::SUB_ACTION_GENERATE_AUTHCODE => self::SUB_ACTION_GENERATE_AUTHCODE,47 self::SUB_ACTION_GENERATE_AUTHCODE => self::SUB_ACTION_GENERATE_AUTHCODE, 48 48 self::SUB_ACTION_GET_ALL_OPTION_VALUES => self::SUB_ACTION_GET_ALL_OPTION_VALUES, 49 49 self::SUB_ACTION_PERSIST_OPTION_VALUES => self::SUB_ACTION_PERSIST_OPTION_VALUES, 50 self::SUB_ACTION_VERIFY_AD_CONNECTION => self::SUB_ACTION_VERIFY_AD_CONNECTION,51 ); 52 53 /** 54 * @param NextADInt_Multisite_View_TwigContainer $twigContainer50 self::SUB_ACTION_VERIFY_AD_CONNECTION => self::SUB_ACTION_VERIFY_AD_CONNECTION, 51 ); 52 53 /** 54 * @param NextADInt_Multisite_View_TwigContainer $twigContainer 55 55 * @param NextADInt_Multisite_Ui_BlogConfigurationController $blogConfigurationConfigurationControllerController 56 56 */ 57 57 public function __construct(NextADInt_Multisite_View_TwigContainer $twigContainer, 58 58 NextADInt_Multisite_Ui_BlogConfigurationController $blogConfigurationConfigurationControllerController 59 ) { 59 ) 60 { 60 61 parent::__construct($twigContainer); 61 62 … … 98 99 public function renderAdmin() 99 100 { 100 // translate twig text101 $i18n = array(102 'title' => __('Next Active Directory Integration Blog Configuration', 'next-active-directory-integration'),103 'regenerateAuthCode' => __('Regenerate Auth Code', 'next-active-directory-integration'),104 'securityGroup' => __('Security group', 'next-active-directory-integration'),105 'wordpressRole' => __('WordPress role', 'next-active-directory-integration'),106 'selectRole' => __('Please select a role', 'next-active-directory-integration'),107 'verify' => __('Verify', 'next-active-directory-integration'),108 'adAttributes' => __('AD Attributes', 'next-active-directory-integration'),109 'dataType' => __('Data Type', 'next-active-directory-integration'),110 'wordpressAttribute' => __('WordPress Attribute', 'next-active-directory-integration'),111 'description' => __('Description', 'next-active-directory-integration'),112 'viewInUserProfile' => __('View in User Profile', 'next-active-directory-integration'),113 'syncToAd' => __('Sync to AD', 'next-active-directory-integration'),114 'overwriteWithEmptyValue' => __('Overwrite with empty value', 'next-active-directory-integration'),115 'wantToRegenerateAuthCode' => __('Do you really want to regenerate a new AuthCode?', 'next-active-directory-integration'),116 'wordPressIsConnectedToDomain' => __('WordPress Site is currently connected to Domain: ', 'next-active-directory-integration'),117 'domainConnectionVerificationSuccessful' => __('Verification successful! WordPress site is now connected to Domain: ', 'next-active-directory-integration'),118 'verificationSuccessful' => __('Verification successful!', 'next-active-directory-integration'),119 'domainConnectionVerificationFailed' => __('Verification failed! Please check your logfile for further information.', 'next-active-directory-integration'),120 'managePermissions' => __('Manage Permissions', 'next-active-directory-integration'),121 'noOptionsExists' => __('No options exists', 'next-active-directory-integration'),122 'pleaseWait' => __('Please wait...', 'next-active-directory-integration'),123 'save' => __('Save', 'next-active-directory-integration'),124 'haveToVerifyDomainConnection' => __('You have to verify the connection to the AD before saving.', 'next-active-directory-integration'),125 'errorWhileSaving' => __('An error occurred while saving the configuration.', 'next-active-directory-integration'),126 'savingSuccessful' => __('The configuration has been saved successfully.', 'next-active-directory-integration')127 );101 // translate twig text 102 $i18n = array( 103 'title' => __('Next Active Directory Integration Blog Configuration', 'next-active-directory-integration'), 104 'regenerateAuthCode' => __('Regenerate Auth Code', 'next-active-directory-integration'), 105 'securityGroup' => __('Security group', 'next-active-directory-integration'), 106 'wordpressRole' => __('WordPress role', 'next-active-directory-integration'), 107 'selectRole' => __('Please select a role', 'next-active-directory-integration'), 108 'verify' => __('Verify', 'next-active-directory-integration'), 109 'adAttributes' => __('AD Attributes', 'next-active-directory-integration'), 110 'dataType' => __('Data Type', 'next-active-directory-integration'), 111 'wordpressAttribute' => __('WordPress Attribute', 'next-active-directory-integration'), 112 'description' => __('Description', 'next-active-directory-integration'), 113 'viewInUserProfile' => __('View in User Profile', 'next-active-directory-integration'), 114 'syncToAd' => __('Sync to AD', 'next-active-directory-integration'), 115 'overwriteWithEmptyValue' => __('Overwrite with empty value', 'next-active-directory-integration'), 116 'wantToRegenerateAuthCode' => __('Do you really want to regenerate a new AuthCode?', 'next-active-directory-integration'), 117 'wordPressIsConnectedToDomain' => __('WordPress Site is currently connected to Domain: ', 'next-active-directory-integration'), 118 'domainConnectionVerificationSuccessful' => __('Verification successful! WordPress site is now connected to Domain: ', 'next-active-directory-integration'), 119 'verificationSuccessful' => __('Verification successful!', 'next-active-directory-integration'), 120 'domainConnectionVerificationFailed' => __('Verification failed! Please check your logfile for further information.', 'next-active-directory-integration'), 121 'managePermissions' => __('Manage Permissions', 'next-active-directory-integration'), 122 'noOptionsExists' => __('No options exists', 'next-active-directory-integration'), 123 'pleaseWait' => __('Please wait...', 'next-active-directory-integration'), 124 'save' => __('Save', 'next-active-directory-integration'), 125 'haveToVerifyDomainConnection' => __('You have to verify the connection to the AD before saving.', 'next-active-directory-integration'), 126 'errorWhileSaving' => __('An error occurred while saving the configuration.', 'next-active-directory-integration'), 127 'savingSuccessful' => __('The configuration has been saved successfully.', 'next-active-directory-integration') 128 ); 128 129 $i18n = NextADInt_Core_Util_EscapeUtil::escapeHarmfulHtml($i18n); 129 130 … … 131 132 self::TEMPLATE, array( 132 133 'nonce' => wp_create_nonce(self::NONCE),// create nonce for security 133 'i18n' => $i18n134 'i18n' => $i18n 134 135 ) 135 136 ); … … 190 191 'next_ad_int_blog_options_controller_security', NEXT_AD_INT_URL . 191 192 '/js/app/blog-options/controllers/security.controller.js', array(), self::VERSION_BLOG_OPTIONS_JS 193 ); 194 wp_enqueue_script( 195 'next_ad_int_blog_options_controller_sso', NEXT_AD_INT_URL . 196 '/js/app/blog-options/controllers/sso.controller.js', array(), self::VERSION_BLOG_OPTIONS_JS 192 197 ); 193 198 wp_enqueue_script( … … 355 360 356 361 return array( 357 'options' => $data,362 'options' => $data, 358 363 'ldapAttributes' => NextADInt_Ldap_Attribute_Description::findAll(), 359 'dataTypes' => NextADInt_Ldap_Attribute_Repository::findAllAttributeTypes(),360 'wpRoles' => NextADInt_Adi_Role_Manager::getRoles(),364 'dataTypes' => NextADInt_Ldap_Attribute_Repository::findAllAttributeTypes(), 365 'wpRoles' => NextADInt_Adi_Role_Manager::getRoles(), 361 366 ); 362 367 } … … 390 395 391 396 // only call verifyInternal if no validation errors were found (warnings are excluded) 392 if (!$validation->containsErrors()) {397 if (!$validation->containsErrors()) { 393 398 $connection = $this->verifyInternal($data); 394 399 } … … 405 410 * 406 411 * @param array $data 407 * @param null $profileId412 * @param null $profileId 408 413 * 409 414 * @return array … … 421 426 } 422 427 423 $domainSid = NextADInt_Core_Util_StringUtil::objectSidToDomainSid($objectSid);428 $domainSid = $objectSid->getDomainPartAsSid()->getFormatted(); 424 429 $domainSidData = $this->prepareDomainSid($domainSid); 425 430 … … 430 435 $netBiosName = $this->twigContainer->findActiveDirectoryNetBiosName($data); 431 436 432 $netBiosData = array();433 if ($netBiosName) {437 $netBiosData = array(); 438 if ($netBiosName) { 434 439 $netBiosData = $this->prepareNetBiosName($netBiosName); 435 440 $this->persistNetBiosName($netBiosData, $profileId); … … 457 462 } 458 463 459 protected function prepareNetBiosName($netBiosName) { 464 protected function prepareNetBiosName($netBiosName) 465 { 460 466 if (is_string($netBiosName) && $netBiosName !== '') { 461 467 return $this->getNetBiosNameForPersistence($netBiosName); … … 477 483 } 478 484 479 protected function getNetBiosNameForPersistence($netBiosName) { 485 protected function getNetBiosNameForPersistence($netBiosName) 486 { 480 487 return array("netbios_name" => $netBiosName); 481 488 } … … 512 519 $validation = $this->validate($data); 513 520 // only call saveBlogOptions if no validation errors are present (warnings are excluded) 514 if (!$validation->containsErrors()) {521 if (!$validation->containsErrors()) { 515 522 $connection = $this->blogConfigurationController->saveBlogOptions($data); 516 523 } … … 686 693 // PERMISSIONS 687 694 $disallowedRoleMessage = __('The role super admin can only be set inside a profile.', 'next-active-directory-integration'); 688 $invalidRoleMessage = __('At least one security group is associated with a non existing WordPress role. Please select an existing role for the group.', 'next-active-directory-integration');695 $invalidRoleMessage = __('At least one security group is associated with a non existing WordPress role. Please select an existing role for the group.', 'next-active-directory-integration'); 689 696 $disallowedRoleRule = new NextADInt_Multisite_Validator_Rule_DisallowInvalidWordPressRoles(array($disallowedRoleMessage, $invalidRoleMessage)); 690 697 $validator->addRule(NextADInt_Adi_Configuration_Options::ROLE_EQUIVALENT_GROUPS, $disallowedRoleRule); … … 791 798 792 799 $domainControllerMessage = __('Domain Controller cannot be empty.', 'next-active-directory-integration'); 793 $domainControllerRule = new NextADInt_Multisite_Validator_Rule_NotEmptyOrWhitespace($domainControllerMessage);794 $validator->addRule(NextADInt_Adi_Configuration_Options::DOMAIN_CONTROLLERS, $domainControllerRule);800 $domainControllerRule = new NextADInt_Multisite_Validator_Rule_NotEmptyOrWhitespace($domainControllerMessage); 801 $validator->addRule(NextADInt_Adi_Configuration_Options::DOMAIN_CONTROLLERS, $domainControllerRule); 795 802 796 803 return $validator; -
next-active-directory-integration/trunk/classes/Multisite/Ui/ProfileConfigurationPage.php
r2331595 r2513920 45 45 /** @var array map the given subActions to the corresponding methods */ 46 46 private $actionMapping = array( 47 self::SUB_ACTION_SAVE_PROFILE => self::SUB_ACTION_SAVE_PROFILE,48 self::SUB_ACTION_REMOVE_PROFILE => self::SUB_ACTION_REMOVE_PROFILE,49 self::SUB_ACTION_GET_PROFILE_OPTION_VALUES => self::SUB_ACTION_GET_PROFILE_OPTION_VALUES,47 self::SUB_ACTION_SAVE_PROFILE => self::SUB_ACTION_SAVE_PROFILE, 48 self::SUB_ACTION_REMOVE_PROFILE => self::SUB_ACTION_REMOVE_PROFILE, 49 self::SUB_ACTION_GET_PROFILE_OPTION_VALUES => self::SUB_ACTION_GET_PROFILE_OPTION_VALUES, 50 50 self::SUB_ACTION_PERSIST_PROFILE_OPTION_VALUES => self::SUB_ACTION_PERSIST_PROFILE_OPTION_VALUES, 51 self::SUB_ACTION_LOAD_PROFILES => self::SUB_ACTION_LOAD_PROFILES,52 self::SUB_ACTION_GENERATE_AUTHCODE => self::SUB_ACTION_GENERATE_AUTHCODE,53 parent::SUB_ACTION_VERIFY_AD_CONNECTION => parent::SUB_ACTION_VERIFY_AD_CONNECTION,51 self::SUB_ACTION_LOAD_PROFILES => self::SUB_ACTION_LOAD_PROFILES, 52 self::SUB_ACTION_GENERATE_AUTHCODE => self::SUB_ACTION_GENERATE_AUTHCODE, 53 parent::SUB_ACTION_VERIFY_AD_CONNECTION => parent::SUB_ACTION_VERIFY_AD_CONNECTION, 54 54 ); 55 55 56 56 /** 57 * @param NextADInt_Multisite_View_TwigContainer $twigContainer58 * @param NextADInt_Multisite_Ui_BlogConfigurationController $blogConfigurationController57 * @param NextADInt_Multisite_View_TwigContainer $twigContainer 58 * @param NextADInt_Multisite_Ui_BlogConfigurationController $blogConfigurationController 59 59 * @param NextADInt_Multisite_Ui_ProfileConfigurationController $profileConfigurationController 60 * @param NextADInt_Multisite_Ui_ProfileController $profileController61 * @param NextADInt_Multisite_Configuration_Service $configurationService60 * @param NextADInt_Multisite_Ui_ProfileController $profileController 61 * @param NextADInt_Multisite_Configuration_Service $configurationService 62 62 */ 63 63 public function __construct(NextADInt_Multisite_View_TwigContainer $twigContainer, … … 66 66 NextADInt_Multisite_Ui_ProfileController $profileController, 67 67 NextADInt_Multisite_Configuration_Service $configurationService 68 ) { 68 ) 69 { 69 70 parent::__construct($twigContainer, $blogConfigurationController); 70 71 … … 111 112 $relativeUrl = add_query_arg('page', NextADInt_Multisite_Ui_BlogProfileRelationshipPage::buildSlug()); 112 113 113 // translate twig text114 $i18n = array(115 'warningDiscardChanges' => __('The current profile contains unsaved changes. Are you sure you want to continue?', 'next-active-directory-integration'),116 'deleteProfileAssociatedSites' => __('The current profile is associated with the following sites:', 'next-active-directory-integration'),117 'deleteProfileAssociated' => __('The current profile is associated with {{ associations.length }} sites. Are you sure you want to delete this profile?', 'next-active-directory-integration'),118 'assignNewProfile' => __('Assign to profile:', 'next-active-directory-integration'),119 'newProfile' => __('New Profile', 'next-active-directory-integration'),120 'none' => __('None', 'next-active-directory-integration'),121 'configureSettingsForProfile' => __('Configure Settings for Profile : ', 'next-active-directory-integration'),122 'createNewProfile' => __('Create new profile', 'next-active-directory-integration'),123 'deleteProfile' => __('Delete profile', 'next-active-directory-integration'),124 'viewAssociatedProfiles' => __('View associated profiles', 'next-active-directory-integration'),125 'regenerateAuthCode' => __('Regenerate Auth Code', 'next-active-directory-integration'),126 'securityGroup' => __('Security group', 'next-active-directory-integration'),127 'wordpressRole' => __('WordPress role', 'next-active-directory-integration'),128 'selectRole' => __('Please select a role', 'next-active-directory-integration'),129 'verify' => __('Verify', 'next-active-directory-integration'),130 'adAttributes' => __('AD Attributes', 'next-active-directory-integration'),131 'dataType' => __('Data Type', 'next-active-directory-integration'),132 'wordpressAttribute' => __('WordPress Attribute', 'next-active-directory-integration'),133 'description' => __('Description', 'next-active-directory-integration'),134 'viewInUserProfile' => __('View in User Profile', 'next-active-directory-integration'),135 'syncToAd' => __('Sync to AD', 'next-active-directory-integration'),136 'overwriteWithEmptyValue' => __('Overwrite with empty value', 'next-active-directory-integration'),137 'wantToRegenerateAuthCode' => __('Do you really want to regenerate a new AuthCode?', 'next-active-directory-integration'),138 'wordPressIsConnectedToDomain' => __('WordPress Site is currently connected to Domain: ', 'next-active-directory-integration'),139 'domainConnectionVerificationSuccessful' => __('Verification successful! WordPress site is now connected to Domain: ', 'next-active-directory-integration'),140 'verificationSuccessful' => __('Verification successful!', 'next-active-directory-integration'),141 'domainConnectionVerificationFailed' => __('Verification failed! Please check your logfile for further information.', 'next-active-directory-integration'),142 'managePermissions' => __('Manage Permissions', 'next-active-directory-integration'),143 'noOptionsExists' => __('No options exists', 'next-active-directory-integration'),144 'pleaseWait' => __('Please wait...', 'next-active-directory-integration'),145 'save' => __('Save', 'next-active-directory-integration'),146 'haveToVerifyDomainConnection' => __('You have to verify the connection to the AD before saving.', 'next-active-directory-integration'),147 'errorWhileSaving' => __('An error occurred while saving the configuration.', 'next-active-directory-integration'),148 'savingSuccessful' => __('The configuration has been saved successfully.', 'next-active-directory-integration')149 );114 // translate twig text 115 $i18n = array( 116 'warningDiscardChanges' => __('The current profile contains unsaved changes. Are you sure you want to continue?', 'next-active-directory-integration'), 117 'deleteProfileAssociatedSites' => __('The current profile is associated with the following sites:', 'next-active-directory-integration'), 118 'deleteProfileAssociated' => __('The current profile is associated with {{ associations.length }} sites. Are you sure you want to delete this profile?', 'next-active-directory-integration'), 119 'assignNewProfile' => __('Assign to profile:', 'next-active-directory-integration'), 120 'newProfile' => __('New Profile', 'next-active-directory-integration'), 121 'none' => __('None', 'next-active-directory-integration'), 122 'configureSettingsForProfile' => __('Configure Settings for Profile : ', 'next-active-directory-integration'), 123 'createNewProfile' => __('Create new profile', 'next-active-directory-integration'), 124 'deleteProfile' => __('Delete profile', 'next-active-directory-integration'), 125 'viewAssociatedProfiles' => __('View associated profiles', 'next-active-directory-integration'), 126 'regenerateAuthCode' => __('Regenerate Auth Code', 'next-active-directory-integration'), 127 'securityGroup' => __('Security group', 'next-active-directory-integration'), 128 'wordpressRole' => __('WordPress role', 'next-active-directory-integration'), 129 'selectRole' => __('Please select a role', 'next-active-directory-integration'), 130 'verify' => __('Verify', 'next-active-directory-integration'), 131 'adAttributes' => __('AD Attributes', 'next-active-directory-integration'), 132 'dataType' => __('Data Type', 'next-active-directory-integration'), 133 'wordpressAttribute' => __('WordPress Attribute', 'next-active-directory-integration'), 134 'description' => __('Description', 'next-active-directory-integration'), 135 'viewInUserProfile' => __('View in User Profile', 'next-active-directory-integration'), 136 'syncToAd' => __('Sync to AD', 'next-active-directory-integration'), 137 'overwriteWithEmptyValue' => __('Overwrite with empty value', 'next-active-directory-integration'), 138 'wantToRegenerateAuthCode' => __('Do you really want to regenerate a new AuthCode?', 'next-active-directory-integration'), 139 'wordPressIsConnectedToDomain' => __('WordPress Site is currently connected to Domain: ', 'next-active-directory-integration'), 140 'domainConnectionVerificationSuccessful' => __('Verification successful! WordPress site is now connected to Domain: ', 'next-active-directory-integration'), 141 'verificationSuccessful' => __('Verification successful!', 'next-active-directory-integration'), 142 'domainConnectionVerificationFailed' => __('Verification failed! Please check your logfile for further information.', 'next-active-directory-integration'), 143 'managePermissions' => __('Manage Permissions', 'next-active-directory-integration'), 144 'noOptionsExists' => __('No options exists', 'next-active-directory-integration'), 145 'pleaseWait' => __('Please wait...', 'next-active-directory-integration'), 146 'save' => __('Save', 'next-active-directory-integration'), 147 'haveToVerifyDomainConnection' => __('You have to verify the connection to the AD before saving.', 'next-active-directory-integration'), 148 'errorWhileSaving' => __('An error occurred while saving the configuration.', 'next-active-directory-integration'), 149 'savingSuccessful' => __('The configuration has been saved successfully.', 'next-active-directory-integration') 150 ); 150 151 151 152 $i18n = NextADInt_Core_Util_EscapeUtil::escapeHarmfulHtml($i18n); … … 153 154 $this->display(self::TEMPLATE, array( 154 155 'blog_profile_relationship_url' => $relativeUrl, 155 'nonce' => wp_create_nonce(self::NONCE), //create nonce for security156 'blog_rel_nonce' => wp_create_nonce(NextADInt_Multisite_Ui_BlogProfileRelationshipPage::NONCE),157 'i18n' => $i18n156 'nonce' => wp_create_nonce(self::NONCE), //create nonce for security 157 'blog_rel_nonce' => wp_create_nonce(NextADInt_Multisite_Ui_BlogProfileRelationshipPage::NONCE), 158 'i18n' => $i18n 158 159 )); 159 160 } … … 207 208 '/js/app/profile-options/controllers/security.controller.js', 208 209 array(), self::VERSION_PROFILE_CONFIGURATION_JS); 210 wp_enqueue_script('next_ad_int_profile_options_controller_sso', NEXT_AD_INT_URL . 211 '/js/app/profile-options/controllers/sso.controller.js', 212 array(), self::VERSION_PROFILE_CONFIGURATION_JS); 209 213 wp_enqueue_script('next_ad_int_profile_options_controller_attributes', NEXT_AD_INT_URL . 210 214 '/js/app/profile-options/controllers/attributes.controller.js', … … 301 305 return array( 302 306 "domain_sid" => array( 303 "option_value" => $domainSid,307 "option_value" => $domainSid, 304 308 "option_permission" => 3, //TODO revisit (default value to prevent saving errors) 305 309 ), … … 396 400 { 397 401 return array( 398 'profiles' => $this->profileController->findAll(),402 'profiles' => $this->profileController->findAll(), 399 403 'associatedProfiles' => $this->profileController->findAllProfileAssociations(), 400 404 'defaultProfileData' => $this->configuration->getProfileOptionsValues(-1), 401 'ldapAttributes' => NextADInt_Ldap_Attribute_Description::findAll(),402 'dataTypes' => NextADInt_Ldap_Attribute_Repository::findAllAttributeTypes(),403 'permissionItems' => $this->getPermission(),404 'wpRoles' => NextADInt_Adi_Role_Manager::getRoles(),405 'ldapAttributes' => NextADInt_Ldap_Attribute_Description::findAll(), 406 'dataTypes' => NextADInt_Ldap_Attribute_Repository::findAllAttributeTypes(), 407 'permissionItems' => $this->getPermission(), 408 'wpRoles' => NextADInt_Adi_Role_Manager::getRoles(), 405 409 ); 406 410 } … … 416 420 $permissionItems = array( 417 421 0 => array( 418 "value" => "0",422 "value" => "0", 419 423 "description" => __("Input field is invisible.", 'next-active-directory-integration'), 420 424 ), 421 425 1 => array( 422 "value" => "1",426 "value" => "1", 423 427 "description" => __("Deactivated and option value not shown.", 'next-active-directory-integration'), 424 428 ), 425 429 2 => array( 426 "value" => "2",430 "value" => "2", 427 431 "description" => __("Deactivated and option value shown.", 'next-active-directory-integration'), 428 432 ), 429 433 3 => array( 430 "value" => "3",434 "value" => "3", 431 435 "description" => __("Blog admin sets the option value.", 'next-active-directory-integration'), 432 436 ), … … 474 478 } 475 479 476 private function getErrorMessage($profileId, $profileName, $result) { 480 private function getErrorMessage($profileId, $profileName, $result) 481 { 477 482 $errorMessage = NextADInt_Core_Message::error(__('An error occurred while saving the configuration.', 'next-active-directory-integration'))->toArray(); 478 483 $errorMessage['additionalInformation'] = array( 479 'profileId' => $profileId,484 'profileId' => $profileId, 480 485 'profileName' => $profileName, 481 486 ); … … 486 491 } 487 492 488 private function getPersistStatusMessage($profileId, $profileName, $persistStatusMessage, $validationResult) { 493 private function getPersistStatusMessage($profileId, $profileName, $persistStatusMessage, $validationResult) 494 { 489 495 $persistStatusMessage['additionalInformation'] = array( 490 'profileId' => $profileId,496 'profileId' => $profileId, 491 497 'profileName' => $profileName, 492 498 ); -
next-active-directory-integration/trunk/classes/Multisite/View/TwigContainer.php
r1608780 r2513920 418 418 * @param $data 419 419 * 420 * @return bool 420 * @return bool|ActiveDirectory_Sid 421 421 */ 422 422 public function findActiveDirectoryDomainSid($data) -
next-active-directory-integration/trunk/index.php
r2331601 r2513920 4 4 Plugin URI: https://www.active-directory-wp.com 5 5 Description: Enterprise-ready solution to authenticate, authorize and synchronize your Active Directory users to WordPress. Next Active Directory Authentication supports NTLM and Kerberos for Single Sign On. 6 Version: 2. 1.126 Version: 2.2.0 7 7 Author: active-directory-wp.com 8 8 Author URI: http://active-directory-wp.com -
next-active-directory-integration/trunk/js/app/blog-options/controllers/environment.controller.js
r2331595 r2513920 11 11 $scope.permissionOptions = DataService.getPermissionOptions(); 12 12 $scope.new_domain_controllers = ''; 13 $scope.new_additional_domain_sids = ''; 13 14 14 $scope.remove_domain_controllers = function (index) { 15 $scope.option.domain_controllers = ListService.removeListItem(index, $scope.option.domain_controllers); 16 }; 15 $scope.remove_domain_controllers = function (index) { 16 $scope.option.domain_controllers = ListService.removeListItem(index, $scope.option.domain_controllers); 17 }; 18 19 $scope.remove_additional_domain_sids = function (index) { 20 $scope.option.additional_domain_sids = ListService.removeListItem(index, $scope.option.additional_domain_sids); 21 }; 17 22 18 23 $scope.add_domain_controllers = function (newItem) { … … 20 25 $scope.new_domain_controllers = ""; 21 26 }; 27 28 $scope.add_additional_domain_sids = function (newItem) { 29 $scope.option.additional_domain_sids = ListService.addListItem(newItem, $scope.option.additional_domain_sids); 30 $scope.new_additional_domain_sids = ""; 31 }; 22 32 23 33 $scope.$on('options', function (event, data) { … … 33 43 domain_sid: $valueHelper.findValue("domain_sid", data), 34 44 netbios_name: $valueHelper.findValue("netbios_name", data), 35 verification_status_message: '' 36 }; 45 verification_status_message: '', 46 additional_domain_sids: $valueHelper.findValue('additional_domain_sids', data, '').split(";") 47 }; 37 48 38 49 if ($valueHelper.findValue("domain_sid", data) == '') { … … 50 61 verification_password : $valueHelper.findPermission("verification_password", data), 51 62 domain_sid: $valueHelper.findPermission("domain_sid", data), 52 netbios_name: $valueHelper.findPermission("netbios_name", data) 63 netbios_name: $valueHelper.findPermission("netbios_name", data), 64 additional_domain_sids: $valueHelper.findPermission('additional_domain_sids', data) 53 65 }; 54 66 … … 69 81 verification_password : $valueHelper.findMessage("verification_password", data), 70 82 domain_sid: $valueHelper.findMessage("domain_sid", data), 71 netbios_name: $valueHelper.findMessage("netbios_name", data) 83 netbios_name: $valueHelper.findMessage("netbios_name", data), 84 additional_domain_sids: $valueHelper.findMessage('additional_domain_sids', data) 72 85 }; 73 86 }); … … 75 88 $scope.getPreparedOptions = function () { 76 89 var data = DataService.cleanOptions($scope.option); 90 77 91 data['domain_controllers'] = ListService.parseListArrayToString($scope.option.domain_controllers); 92 data['additional_domain_sids'] = ListService.parseListArrayToString($scope.option.additional_domain_sids); 93 78 94 return data; 79 95 }; … … 86 102 87 103 // check if the input field is not empty 88 if ($scope.new_domain_controllers != '') {104 if ($scope.new_domain_controllers != '') { 89 105 // add the input field value to the list of objects to be saved 90 106 ListService.addListItem($scope.new_domain_controllers, $scope.option.domain_controllers); 91 107 $scope.new_domain_controllers = ''; 92 108 } 109 110 if ($scope.new_additional_domain_sids != '') { 111 // add the input field value to the list of objects to be saved 112 ListService.addListItem($scope.new_additional_domain_sids, $scope.option.additional_domain_sids); 113 $scope.new_additional_domain_sids = ''; 114 } 93 115 94 116 var data = { … … 100 122 base_dn: $scope.option.base_dn, 101 123 verification_username: $scope.option.verification_username, 102 verification_password: $scope.option.verification_password 103 }; 124 verification_password: $scope.option.verification_password, 125 additional_domain_sids: ListService.parseListArrayToString($scope.option.additional_domain_sids), 126 }; 104 127 105 128 $http.post('admin-ajax.php', { -
next-active-directory-integration/trunk/js/app/blog-options/controllers/security.controller.js
r2069979 r2513920 24 24 $scope.$on('options', function (event, data) { 25 25 $scope.option = { 26 sso: $valueHelper.findValue("sso", data),27 sso_user: $valueHelper.findValue("sso_user", data),28 sso_password: $valueHelper.findValue("sso_password", data),29 sso_environment_variable: $valueHelper.findValue("sso_environment_variable", data),30 sso_disable_for_xmlrpc: $valueHelper.findValue("sso_disable_for_xmlrpc", data),31 26 enable_smartcard_user_login: $valueHelper.findValue("enable_smartcard_user_login", data), 32 27 custom_login_page_enabled: $valueHelper.findValue("custom_login_page_enabled", data), … … 45 40 46 41 $scope.permission = { 47 sso: $valueHelper.findPermission("sso", data),48 sso_user: $valueHelper.findPermission("sso_user", data),49 sso_password: $valueHelper.findPermission("sso_password", data),50 sso_environment_variable: $valueHelper.findPermission("sso_environment_variable", data),51 sso_disable_for_xmlrpc: $valueHelper.findPermission("sso_disable_for_xmlrpc", data),52 42 enable_smartcard_user_login: $valueHelper.findPermission("enable_smartcard_user_login", data), 53 43 custom_login_page_enabled: $valueHelper.findPermission("custom_login_page_enabled", data), … … 59 49 from_email: $valueHelper.findPermission("from_email", data), 60 50 allow_xmlrpc_login: $valueHelper.findPermission("allow_xmlrpc_login", data), 61 verification_username : $valueHelper.findPermission("verification_username", data),62 verification_password : $valueHelper.findPermission("verification_password", data)63 51 }; 64 52 }); … … 66 54 $scope.$on('validation', function (event, data) { 67 55 $scope.messages = { 68 sso: $valueHelper.findMessage("sso", data),69 sso_user: $valueHelper.findMessage("sso_user", data),70 sso_password: $valueHelper.findMessage("sso_password", data),71 sso_environment_variable: $valueHelper.findMessage("sso_environment_variable", data),72 56 enable_smartcard_user_login: $valueHelper.findMessage("enable_smartcard_user_login", data), 73 57 custom_login_page_enabled: $valueHelper.findMessage("custom_login_page_enabled", data), -
next-active-directory-integration/trunk/js/app/profile-options/controllers/environment.controller.js
r2331595 r2513920 14 14 15 15 $scope.new_domain_controllers = ''; 16 $scope.new_additional_domain_sids = ''; 16 17 17 18 $scope.remove_domain_controllers = function (index) { … … 19 20 }; 20 21 22 $scope.remove_additional_domain_sids = function (index) { 23 $scope.option.additional_domain_sids = ListService.removeListItem(index, $scope.option.additional_domain_sids); 24 }; 25 21 26 $scope.add_domain_controllers = function (newItem) { 22 27 $scope.option.domain_controllers = ListService.addListItem(newItem, $scope.option.domain_controllers); 23 28 $scope.new_domain_controllers = ""; 24 29 }; 30 31 $scope.add_additional_domain_sids = function (newItem) { 32 $scope.option.additional_domain_sids = ListService.addListItem(newItem, $scope.option.additional_domain_sids); 33 $scope.new_additional_domain_sids = ""; 34 }; 25 35 26 36 $scope.$on('options', function (event, data) { … … 36 46 domain_sid: $valueHelper.findValue("domain_sid", data), 37 47 netbios_name: $valueHelper.findValue("netbios_name", data), 38 verification_status_message: '' 39 }; 48 verification_status_message: '', 49 additional_domain_sids: $valueHelper.findValue('additional_domain_sids', data, '').split(";") 50 }; 40 51 41 52 if ($scope.option.domain_sid == '') { … … 55 66 verification_password : $valueHelper.findPermission("verification_password", data), 56 67 domain_sid: $valueHelper.findPermission("domain_sid", data), 57 netbios_name: $valueHelper.findPermission("netbios_name", data) 58 }; 68 netbios_name: $valueHelper.findPermission("netbios_name", data), 69 additional_domain_sids: $valueHelper.findPermission('additional_domain_sids', data) 70 }; 59 71 60 72 … … 75 87 verification_password : $valueHelper.findMessage("verification_password", data), 76 88 domain_sid: $valueHelper.findMessage("domain_sid", data), 77 netbios_name: $valueHelper.findValue("netbios_name", data) 89 netbios_name: $valueHelper.findValue("netbios_name", data), 90 additional_domain_sids: $valueHelper.findMessage('additional_domain_sids', data) 78 91 }; 79 92 }); … … 81 94 $scope.getPreparedOptions = function () { 82 95 var data = DataService.cleanOptions($scope.option); 96 83 97 data['domain_controllers'] = ListService.parseListArrayToString($scope.option.domain_controllers); 98 data['additional_domain_sids'] = ListService.parseListArrayToString($scope.option.additional_domain_sids); 99 84 100 return data; 85 101 }; … … 98 114 } 99 115 116 if ($scope.new_additional_domain_sids != '') { 117 // add the input field value to the list of objects to be saved 118 ListService.addListItem($scope.new_additional_domain_sids, $scope.option.additional_domain_sids); 119 $scope.new_additional_domain_sids = ''; 120 } 121 100 122 var data = { 101 123 domain_controllers: ListService.parseListArrayToString($scope.option.domain_controllers), … … 107 129 verification_username: $scope.option.verification_username, 108 130 verification_password: $scope.option.verification_password, 131 additional_domain_sids: ListService.parseListArrayToString($scope.option.additional_domain_sids), 109 132 profile: $scope.activeProfile.profileId 110 133 }; -
next-active-directory-integration/trunk/js/app/profile-options/controllers/security.controller.js
r2069979 r2513920 26 26 $scope.$on('options', function (event, data) { 27 27 $scope.option = { 28 sso: $valueHelper.findValue("sso", data),29 sso_user: $valueHelper.findValue("sso_user", data),30 sso_password: $valueHelper.findValue("sso_password", data),31 sso_environment_variable: $valueHelper.findValue("sso_environment_variable", data),32 sso_disable_for_xmlrpc: $valueHelper.findValue("sso_disable_for_xmlrpc", data),33 28 enable_smartcard_user_login: $valueHelper.findValue("enable_smartcard_user_login", data), 34 29 custom_login_page_enabled: $valueHelper.findValue("custom_login_page_enabled", data), … … 38 33 admin_notification: $valueHelper.findValue("admin_notification", data), 39 34 admin_email: $valueHelper.findValue("admin_email", data).split(";"), 40 from_email: $valueHelper.findValue("from_email", data) .split(";"),35 from_email: $valueHelper.findValue("from_email", data), 41 36 allow_xmlrpc_login: $valueHelper.findValue("allow_xmlrpc_login", data) 42 37 }; … … 49 44 50 45 $scope.permission = { 51 sso: $valueHelper.findPermission("sso", data),52 sso_user: $valueHelper.findPermission("sso_user", data),53 sso_password: $valueHelper.findPermission("sso_password", data),54 sso_environment_variable: $valueHelper.findPermission("sso_environment_variable", data),55 sso_disable_for_xmlrpc: $valueHelper.findPermission("sso_disable_for_xmlrpc", data),56 46 enable_smartcard_user_login: $valueHelper.findPermission("enable_smartcard_user_login", data), 57 47 custom_login_page_enabled: $valueHelper.findPermission("custom_login_page_enabled", data), … … 68 58 $scope.$on('validation', function (event, data) { 69 59 $scope.messages = { 70 sso: $valueHelper.findMessage("sso", data),71 sso_user: $valueHelper.findMessage("sso_user", data),72 sso_password: $valueHelper.findMessage("sso_password", data),73 sso_environment_variable: $valueHelper.findMessage("sso_environment_variable", data),74 60 enable_smartcard_user_login: $valueHelper.findMessage("enable_smartcard_user_login", data), 75 61 custom_login_page_enabled: $valueHelper.findMessage("custom_login_page_enabled", data), -
next-active-directory-integration/trunk/readme.txt
r2331601 r2513920 2 2 Contributors: neosit,tobi823,fatsquirrel,schakko,medan123 3 3 Tags: authentication, active directory, ldap, authorization, security, windows, sso 4 Requires at least: 5. 05 Tested up to: 5. 46 Stable tag: 2. 1.124 Requires at least: 5.4 5 Tested up to: 5.7 6 Stable tag: 2.2.0 7 7 License: GPLv3 8 8 … … 36 36 * Set users local WordPress password on first and/or on every successful login 37 37 * Option to disable fallback to local (WordPress) authentication. 38 * Support for Active Directory forest environments. 38 39 * and much much more 39 40 … … 48 49 * Login with WooCommerce: Let WooCommerce users log in by using NADI 49 50 * WP-CLI: Execute common NADI tasks (Sync to WordPress, Sync to AD) with help of WP-CLI 51 * Active Directory Forest: Be able to use one WordPress instance with your whole Active Directory forest environment 50 52 51 53 = Requirements = 52 54 53 * WordPress since 5. 055 * WordPress since 5.4 54 56 * PHP >= 7.2 55 57 * LDAP support … … 80 82 81 83 = Requirements = 82 To install Next Active Directory Integration you need at least WordPress 5. 0and PHP 7.284 To install Next Active Directory Integration you need at least WordPress 5.4 and PHP 7.2 83 85 84 86 Although only tested with Apache 2.2 and 2.4 *NADI* should work with all other common web servers like nginx and IIS. … … 127 129 128 130 For detailed information you can visit the official [GitHub repository of Next Active Directory Integration](https://github.com/NeosIT/active-directory-integration2) 131 132 133 = 2.2.0 = 134 * ADDED: Kerberos principals are no longer treated as userPrincipalNames (ADI-715) 135 * ADDED: When using Kerberos SSO principals, you can map the Kerberos realm to multiple UPN suffixes (requires *Active Directory Forest* premium extension) (ADI-715) 136 * ADDED: When using NADI in an AD forest, you can now specify all SIDs of the connected domains (requires *Active Directory Forest* premium extension) (ADI-715) 137 * FIXED: When using a Global Catalog (GC), users with same sAMAccountName but different userPrincipalNames are not assigned correct during authentication (NADIS-133) 138 * FIXED-SECURITY: Users with same UPN prefix and password but different UPN suffix would be logged in with the wrong account (ADI-716) 139 * CHANGED: WordPress 5.6.1 compatibility has been checked 140 * CHANGED: WordPress 5.7 compatibility has been checked 141 * CHANGED: PHP 8.0 compatibility has been added (ADI-718, gh-#132, gh-#137) 142 * FIXED: Deprecation warning when trying to send mail notification for blocked users (ADI-719) 143 * FIXED: Option "Blog admin sets the option value." had no effect in Multisite environments (gh-#124) 144 * DEPRECATION-WARNING: For the upcoming release 2.3.0 we will remove "Internal password migration" (gh-#136), "Automatic user creation" (gh-#134) and "Email address conflict handling" (gh-#133) 145 * DEV: Slightly transition new issues to GitHub instead of internal Jira 129 146 130 147 = 2.1.12 = -
next-active-directory-integration/trunk/vendor/adLDAP/adLDAP.php
r2331595 r2513920 1331 1331 1332 1332 if ($isGUID === true) { 1333 $username = $this->strguid2hex($username);1333 $username = self::strguid2hex($username); 1334 1334 $filter="objectguid=".$username; 1335 1335 } … … 1369 1369 1370 1370 /** 1371 * Get a configuration e tnry form the CN=Partitions,CN=Configuration object1371 * Get a configuration entry form the CN=Partitions,CN=Configuration object 1372 1372 * 1373 1373 * @param $filter … … 2585 2585 2586 2586 $gsid = substr_replace($usersid,pack('V',$gid),strlen($usersid)-4,4); 2587 $filter='(objectsid='. $this->getTextSID($gsid).')';2587 $filter='(objectsid='. self::convertBinarySidToString($gsid).')'; 2588 2588 $fields=array("samaccountname","distinguishedname"); 2589 2589 $sr=ldap_search($this->_conn,$this->_base_dn,$filter,$fields); … … 2597 2597 return false; 2598 2598 } 2599 2600 /** 2601 * Convert a binary SID to a text SID 2602 * 2603 * @param string $binsid A Binary SID 2604 * @return string 2605 */ 2606 protected function getTextSID($binsid) { 2607 $hex_sid = bin2hex($binsid); 2608 $rev = hexdec(substr($hex_sid, 0, 2)); 2609 $subcount = hexdec(substr($hex_sid, 2, 2)); 2610 $auth = hexdec(substr($hex_sid, 4, 12)); 2611 $result = "$rev-$auth"; 2612 2613 for ($x=0;$x < $subcount; $x++) { 2614 $subauth[$x] = 2615 hexdec($this->little_endian(substr($hex_sid, 16 + ($x * 8), 8))); 2616 $result .= "-" . $subauth[$x]; 2617 } 2618 2619 // Cheat by tacking on the S- 2620 return 'S-' . $result; 2621 } 2599 2600 /** 2601 * Convert a binary SID to a text SID 2602 * 2603 * @param string $binsid A Binary SID 2604 * @return string 2605 */ 2606 public static function convertBinarySidToString($binsid) 2607 { 2608 $hex_sid = bin2hex($binsid); 2609 $rev = hexdec(substr($hex_sid, 0, 2)); 2610 $subcount = hexdec(substr($hex_sid, 2, 2)); 2611 $auth = hexdec(substr($hex_sid, 4, 12)); 2612 $result = "$rev-$auth"; 2613 2614 for ($x = 0; $x < $subcount; $x++) { 2615 $subauth[$x] = 2616 hexdec(self::little_endian(substr($hex_sid, 16 + ($x * 8), 8))); 2617 $result .= "-" . $subauth[$x]; 2618 } 2619 2620 // Cheat by tacking on the S- 2621 return 'S-' . $result; 2622 } 2623 2624 /** 2625 * Converts the given string into little endian hex format 2626 * @param string $int 2627 * @return string 2628 */ 2629 public static function toInt32LittleEndianHex($int) 2630 { 2631 $endian = unpack("N", pack("L", intval($int))); 2632 return sprintf("%'08X", $endian[1]); 2633 } 2634 2635 /** 2636 * Converts a SID string to hex. 2637 * "S-1-5-21-2127521184-1604012920-1887927527-72713" will be converted to "010500000000000515000000A065CF7E784B9B5FE77C8770091C0100" 2638 * 2639 * @see https://devblogs.microsoft.com/oldnewthing/20040315-00/?p=40253 2640 * @see https://docs.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-sid 2641 * @see https://en.wikipedia.org/wiki/Security_Identifier 2642 * 2643 * @param string $sid "S-1-5-21-2127521184-1604012920-1887927527-72713" 2644 * @return string "010500000000000515000000A065CF7E784B9B5FE77C8770091C0100" 2645 */ 2646 public static function sidStringToHex($sid) 2647 { 2648 $parts = explode("-", $sid); 2649 2650 $revision = sprintf('%02X', $parts[1]); // 1 2651 $numberOfDashes = sprintf('%02X', substr_count($sid, '-') - 2); // 2652 $identifierAuthority = sprintf('%012X', $parts[2]); // 5 2653 $subAuthorities = ""; // 21-2127521184-1604012920-1887927527-72713 2654 2655 for ($i = 3; $i < sizeof($parts); $i++) { 2656 $subAuthorities .= self::toInt32LittleEndianHex($parts[$i]); 2657 } 2658 2659 return $revision . $numberOfDashes . $identifierAuthority . $subAuthorities; 2660 } 2622 2661 2623 2662 /** … … 2627 2666 * @return string 2628 2667 */ 2629 p rotectedfunction little_endian($hex) {2668 public static function little_endian($hex) { 2630 2669 $result = ''; 2631 2670 for ($x = strlen($hex) - 2; $x >= 0; $x = $x - 2) { … … 2635 2674 } 2636 2675 2637 /**2638 * Convert binary Object SID to string2639 *2640 * @author [email protected]2641 * @param $bin2642 * @return $string2643 */2644 public function convertObjectSidBinaryToString($bin) {2645 return $this->getTextSID($bin);2646 }2647 2648 2676 /** 2649 2677 * Converts a binary attribute to a string … … 2690 2718 * @return string 2691 2719 */ 2692 p rotectedfunction strguid2hex($strGUID) {2720 public static function strguid2hex($strGUID) { 2693 2721 $strGUID = str_replace('-', '', $strGUID); 2694 2722 -
next-active-directory-integration/trunk/vendor/autoload.php
r2331603 r2513920 5 5 require_once __DIR__ . '/composer/autoload_real.php'; 6 6 7 return ComposerAutoloaderInit 1f93e1293d0d14fe15942807ee39d508::getLoader();7 return ComposerAutoloaderInitde0ddec4866a627b4af09bbe789ba7cd::getLoader(); -
next-active-directory-integration/trunk/vendor/composer/ClassLoader.php
r2069979 r2513920 38 38 * @author Fabien Potencier <[email protected]> 39 39 * @author Jordi Boggiano <[email protected]> 40 * @see http ://www.php-fig.org/psr/psr-0/41 * @see http ://www.php-fig.org/psr/psr-4/40 * @see https://www.php-fig.org/psr/psr-0/ 41 * @see https://www.php-fig.org/psr/psr-4/ 42 42 */ 43 43 class ClassLoader 44 44 { 45 private $vendorDir; 46 45 47 // PSR-4 46 48 private $prefixLengthsPsr4 = array(); … … 58 60 private $apcuPrefix; 59 61 62 private static $registeredLoaders = array(); 63 64 public function __construct($vendorDir = null) 65 { 66 $this->vendorDir = $vendorDir; 67 } 68 60 69 public function getPrefixes() 61 70 { 62 71 if (!empty($this->prefixesPsr0)) { 63 return call_user_func_array('array_merge', $this->prefixesPsr0);72 return call_user_func_array('array_merge', array_values($this->prefixesPsr0)); 64 73 } 65 74 … … 301 310 { 302 311 spl_autoload_register(array($this, 'loadClass'), true, $prepend); 312 313 if (null === $this->vendorDir) { 314 return; 315 } 316 317 if ($prepend) { 318 self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders; 319 } else { 320 unset(self::$registeredLoaders[$this->vendorDir]); 321 self::$registeredLoaders[$this->vendorDir] = $this; 322 } 303 323 } 304 324 … … 309 329 { 310 330 spl_autoload_unregister(array($this, 'loadClass')); 331 332 if (null !== $this->vendorDir) { 333 unset(self::$registeredLoaders[$this->vendorDir]); 334 } 311 335 } 312 336 … … 366 390 367 391 return $file; 392 } 393 394 /** 395 * Returns the currently registered loaders indexed by their corresponding vendor directories. 396 * 397 * @return self[] 398 */ 399 public static function getRegisteredLoaders() 400 { 401 return self::$registeredLoaders; 368 402 } 369 403 -
next-active-directory-integration/trunk/vendor/composer/autoload_classmap.php
r1756617 r2513920 7 7 8 8 return array( 9 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php', 9 10 'Defuse\\Crypto\\Core' => $vendorDir . '/defuse/php-encryption/src/Core.php', 10 11 'Defuse\\Crypto\\Crypto' => $vendorDir . '/defuse/php-encryption/src/Crypto.php', -
next-active-directory-integration/trunk/vendor/composer/autoload_real.php
r2331603 r2513920 3 3 // autoload_real.php @generated by Composer 4 4 5 class ComposerAutoloaderInit 1f93e1293d0d14fe15942807ee39d5085 class ComposerAutoloaderInitde0ddec4866a627b4af09bbe789ba7cd 6 6 { 7 7 private static $loader; … … 14 14 } 15 15 16 /** 17 * @return \Composer\Autoload\ClassLoader 18 */ 16 19 public static function getLoader() 17 20 { … … 20 23 } 21 24 22 spl_autoload_register(array('ComposerAutoloaderInit1f93e1293d0d14fe15942807ee39d508', 'loadClassLoader'), true, true); 23 self::$loader = $loader = new \Composer\Autoload\ClassLoader(); 24 spl_autoload_unregister(array('ComposerAutoloaderInit1f93e1293d0d14fe15942807ee39d508', 'loadClassLoader')); 25 require __DIR__ . '/platform_check.php'; 26 27 spl_autoload_register(array('ComposerAutoloaderInitde0ddec4866a627b4af09bbe789ba7cd', 'loadClassLoader'), true, true); 28 self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__))); 29 spl_autoload_unregister(array('ComposerAutoloaderInitde0ddec4866a627b4af09bbe789ba7cd', 'loadClassLoader')); 25 30 26 31 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); 27 32 if ($useStaticLoader) { 28 require _once__DIR__ . '/autoload_static.php';33 require __DIR__ . '/autoload_static.php'; 29 34 30 call_user_func(\Composer\Autoload\ComposerStaticInit 1f93e1293d0d14fe15942807ee39d508::getInitializer($loader));35 call_user_func(\Composer\Autoload\ComposerStaticInitde0ddec4866a627b4af09bbe789ba7cd::getInitializer($loader)); 31 36 } else { 32 37 $map = require __DIR__ . '/autoload_namespaces.php'; … … 49 54 50 55 if ($useStaticLoader) { 51 $includeFiles = Composer\Autoload\ComposerStaticInit 1f93e1293d0d14fe15942807ee39d508::$files;56 $includeFiles = Composer\Autoload\ComposerStaticInitde0ddec4866a627b4af09bbe789ba7cd::$files; 52 57 } else { 53 58 $includeFiles = require __DIR__ . '/autoload_files.php'; 54 59 } 55 60 foreach ($includeFiles as $fileIdentifier => $file) { 56 composerRequire 1f93e1293d0d14fe15942807ee39d508($fileIdentifier, $file);61 composerRequirede0ddec4866a627b4af09bbe789ba7cd($fileIdentifier, $file); 57 62 } 58 63 … … 61 66 } 62 67 63 function composerRequire 1f93e1293d0d14fe15942807ee39d508($fileIdentifier, $file)68 function composerRequirede0ddec4866a627b4af09bbe789ba7cd($fileIdentifier, $file) 64 69 { 65 70 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { -
next-active-directory-integration/trunk/vendor/composer/autoload_static.php
r2331603 r2513920 5 5 namespace Composer\Autoload; 6 6 7 class ComposerStaticInit 1f93e1293d0d14fe15942807ee39d5087 class ComposerStaticInitde0ddec4866a627b4af09bbe789ba7cd 8 8 { 9 9 public static $files = array ( … … 61 61 62 62 public static $classMap = array ( 63 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php', 63 64 'Defuse\\Crypto\\Core' => __DIR__ . '/..' . '/defuse/php-encryption/src/Core.php', 64 65 'Defuse\\Crypto\\Crypto' => __DIR__ . '/..' . '/defuse/php-encryption/src/Crypto.php', … … 80 81 { 81 82 return \Closure::bind(function () use ($loader) { 82 $loader->prefixLengthsPsr4 = ComposerStaticInit 1f93e1293d0d14fe15942807ee39d508::$prefixLengthsPsr4;83 $loader->prefixDirsPsr4 = ComposerStaticInit 1f93e1293d0d14fe15942807ee39d508::$prefixDirsPsr4;84 $loader->prefixesPsr0 = ComposerStaticInit 1f93e1293d0d14fe15942807ee39d508::$prefixesPsr0;85 $loader->classMap = ComposerStaticInit 1f93e1293d0d14fe15942807ee39d508::$classMap;83 $loader->prefixLengthsPsr4 = ComposerStaticInitde0ddec4866a627b4af09bbe789ba7cd::$prefixLengthsPsr4; 84 $loader->prefixDirsPsr4 = ComposerStaticInitde0ddec4866a627b4af09bbe789ba7cd::$prefixDirsPsr4; 85 $loader->prefixesPsr0 = ComposerStaticInitde0ddec4866a627b4af09bbe789ba7cd::$prefixesPsr0; 86 $loader->classMap = ComposerStaticInitde0ddec4866a627b4af09bbe789ba7cd::$classMap; 86 87 87 88 }, null, ClassLoader::class); -
next-active-directory-integration/trunk/vendor/composer/installed.json
r2331595 r2513920 1 [ 2 { 3 "name": "defuse/php-encryption", 4 "version": "2.0.3", 5 "version_normalized": "2.0.3.0", 6 "source": { 7 "type": "git", 8 "url": "https://github.com/defuse/php-encryption.git", 9 "reference": "2c6fea3d9a4eaaa8cef86b2a89f3660818117b33" 1 { 2 "packages": [ 3 { 4 "name": "defuse/php-encryption", 5 "version": "2.0.3", 6 "version_normalized": "2.0.3.0", 7 "source": { 8 "type": "git", 9 "url": "https://github.com/defuse/php-encryption.git", 10 "reference": "2c6fea3d9a4eaaa8cef86b2a89f3660818117b33" 11 }, 12 "dist": { 13 "type": "zip", 14 "url": "https://api.github.com/repos/defuse/php-encryption/zipball/2c6fea3d9a4eaaa8cef86b2a89f3660818117b33", 15 "reference": "2c6fea3d9a4eaaa8cef86b2a89f3660818117b33", 16 "shasum": "" 17 }, 18 "require": { 19 "ext-openssl": "*", 20 "paragonie/random_compat": "~2.0", 21 "php": ">=5.4.0" 22 }, 23 "require-dev": { 24 "nikic/php-parser": "^2.0" 25 }, 26 "time": "2016-10-10T15:20:26+00:00", 27 "type": "library", 28 "installation-source": "dist", 29 "autoload": { 30 "classmap": [ 31 "src" 32 ] 33 }, 34 "notification-url": "https://packagist.org/downloads/", 35 "license": [ 36 "MIT" 37 ], 38 "authors": [ 39 { 40 "name": "Taylor Hornby", 41 "email": "[email protected]", 42 "homepage": "https://defuse.ca/" 43 }, 44 { 45 "name": "Scott Arciszewski", 46 "email": "[email protected]", 47 "homepage": "https://paragonie.com" 48 } 49 ], 50 "description": "Secure PHP Encryption Library", 51 "keywords": [ 52 "aes", 53 "authenticated encryption", 54 "cipher", 55 "crypto", 56 "cryptography", 57 "encrypt", 58 "encryption", 59 "openssl", 60 "security", 61 "symmetric key cryptography" 62 ], 63 "support": { 64 "issues": "https://github.com/defuse/php-encryption/issues", 65 "source": "https://github.com/defuse/php-encryption/tree/master" 66 }, 67 "install-path": "../defuse/php-encryption" 10 68 }, 11 "dist": { 12 "type": "zip", 13 "url": "https://api.github.com/repos/defuse/php-encryption/zipball/2c6fea3d9a4eaaa8cef86b2a89f3660818117b33", 14 "reference": "2c6fea3d9a4eaaa8cef86b2a89f3660818117b33", 15 "shasum": "" 69 { 70 "name": "monolog/monolog", 71 "version": "1.26.0", 72 "version_normalized": "1.26.0.0", 73 "source": { 74 "type": "git", 75 "url": "https://github.com/Seldaek/monolog.git", 76 "reference": "2209ddd84e7ef1256b7af205d0717fb62cfc9c33" 77 }, 78 "dist": { 79 "type": "zip", 80 "url": "https://api.github.com/repos/Seldaek/monolog/zipball/2209ddd84e7ef1256b7af205d0717fb62cfc9c33", 81 "reference": "2209ddd84e7ef1256b7af205d0717fb62cfc9c33", 82 "shasum": "" 83 }, 84 "require": { 85 "php": ">=5.3.0", 86 "psr/log": "~1.0" 87 }, 88 "provide": { 89 "psr/log-implementation": "1.0.0" 90 }, 91 "require-dev": { 92 "aws/aws-sdk-php": "^2.4.9 || ^3.0", 93 "doctrine/couchdb": "~1.0@dev", 94 "graylog2/gelf-php": "~1.0", 95 "php-amqplib/php-amqplib": "~2.4", 96 "php-console/php-console": "^3.1.3", 97 "phpstan/phpstan": "^0.12.59", 98 "phpunit/phpunit": "~4.5", 99 "ruflin/elastica": ">=0.90 <3.0", 100 "sentry/sentry": "^0.13", 101 "swiftmailer/swiftmailer": "^5.3|^6.0" 102 }, 103 "suggest": { 104 "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 105 "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 106 "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 107 "ext-mongo": "Allow sending log messages to a MongoDB server", 108 "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 109 "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", 110 "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", 111 "php-console/php-console": "Allow sending log messages to Google Chrome", 112 "rollbar/rollbar": "Allow sending log messages to Rollbar", 113 "ruflin/elastica": "Allow sending log messages to an Elastic Search server", 114 "sentry/sentry": "Allow sending log messages to a Sentry server" 115 }, 116 "time": "2020-12-14T12:56:38+00:00", 117 "type": "library", 118 "installation-source": "dist", 119 "autoload": { 120 "psr-4": { 121 "Monolog\\": "src/Monolog" 122 } 123 }, 124 "notification-url": "https://packagist.org/downloads/", 125 "license": [ 126 "MIT" 127 ], 128 "authors": [ 129 { 130 "name": "Jordi Boggiano", 131 "email": "[email protected]", 132 "homepage": "http://seld.be" 133 } 134 ], 135 "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 136 "homepage": "http://github.com/Seldaek/monolog", 137 "keywords": [ 138 "log", 139 "logging", 140 "psr-3" 141 ], 142 "support": { 143 "issues": "https://github.com/Seldaek/monolog/issues", 144 "source": "https://github.com/Seldaek/monolog/tree/1.26.0" 145 }, 146 "funding": [ 147 { 148 "url": "https://github.com/Seldaek", 149 "type": "github" 150 }, 151 { 152 "url": "https://tidelift.com/funding/github/packagist/monolog/monolog", 153 "type": "tidelift" 154 } 155 ], 156 "install-path": "../monolog/monolog" 16 157 }, 17 "require": { 18 "ext-openssl": "*", 19 "paragonie/random_compat": "~2.0", 20 "php": ">=5.4.0" 158 { 159 "name": "paragonie/random_compat", 160 "version": "v2.0.19", 161 "version_normalized": "2.0.19.0", 162 "source": { 163 "type": "git", 164 "url": "https://github.com/paragonie/random_compat.git", 165 "reference": "446fc9faa5c2a9ddf65eb7121c0af7e857295241" 166 }, 167 "dist": { 168 "type": "zip", 169 "url": "https://api.github.com/repos/paragonie/random_compat/zipball/446fc9faa5c2a9ddf65eb7121c0af7e857295241", 170 "reference": "446fc9faa5c2a9ddf65eb7121c0af7e857295241", 171 "shasum": "" 172 }, 173 "require": { 174 "php": ">=5.2.0" 175 }, 176 "require-dev": { 177 "phpunit/phpunit": "4.*|5.*" 178 }, 179 "suggest": { 180 "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." 181 }, 182 "time": "2020-10-15T10:06:57+00:00", 183 "type": "library", 184 "installation-source": "dist", 185 "autoload": { 186 "files": [ 187 "lib/random.php" 188 ] 189 }, 190 "notification-url": "https://packagist.org/downloads/", 191 "license": [ 192 "MIT" 193 ], 194 "authors": [ 195 { 196 "name": "Paragon Initiative Enterprises", 197 "email": "[email protected]", 198 "homepage": "https://paragonie.com" 199 } 200 ], 201 "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", 202 "keywords": [ 203 "csprng", 204 "polyfill", 205 "pseudorandom", 206 "random" 207 ], 208 "support": { 209 "email": "[email protected]", 210 "issues": "https://github.com/paragonie/random_compat/issues", 211 "source": "https://github.com/paragonie/random_compat" 212 }, 213 "install-path": "../paragonie/random_compat" 21 214 }, 22 "require-dev": { 23 "nikic/php-parser": "^2.0" 215 { 216 "name": "psr/log", 217 "version": "1.1.3", 218 "version_normalized": "1.1.3.0", 219 "source": { 220 "type": "git", 221 "url": "https://github.com/php-fig/log.git", 222 "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" 223 }, 224 "dist": { 225 "type": "zip", 226 "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", 227 "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", 228 "shasum": "" 229 }, 230 "require": { 231 "php": ">=5.3.0" 232 }, 233 "time": "2020-03-23T09:12:05+00:00", 234 "type": "library", 235 "extra": { 236 "branch-alias": { 237 "dev-master": "1.1.x-dev" 238 } 239 }, 240 "installation-source": "dist", 241 "autoload": { 242 "psr-4": { 243 "Psr\\Log\\": "Psr/Log/" 244 } 245 }, 246 "notification-url": "https://packagist.org/downloads/", 247 "license": [ 248 "MIT" 249 ], 250 "authors": [ 251 { 252 "name": "PHP-FIG", 253 "homepage": "http://www.php-fig.org/" 254 } 255 ], 256 "description": "Common interface for logging libraries", 257 "homepage": "https://github.com/php-fig/log", 258 "keywords": [ 259 "log", 260 "psr", 261 "psr-3" 262 ], 263 "support": { 264 "source": "https://github.com/php-fig/log/tree/1.1.3" 265 }, 266 "install-path": "../psr/log" 24 267 }, 25 "time": "2016-10-10T15:20:26+00:00", 26 "type": "library", 27 "installation-source": "dist", 28 "autoload": { 29 "classmap": [ 30 "src" 31 ] 268 { 269 "name": "symfony/polyfill-ctype", 270 "version": "v1.22.1", 271 "version_normalized": "1.22.1.0", 272 "source": { 273 "type": "git", 274 "url": "https://github.com/symfony/polyfill-ctype.git", 275 "reference": "c6c942b1ac76c82448322025e084cadc56048b4e" 276 }, 277 "dist": { 278 "type": "zip", 279 "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/c6c942b1ac76c82448322025e084cadc56048b4e", 280 "reference": "c6c942b1ac76c82448322025e084cadc56048b4e", 281 "shasum": "" 282 }, 283 "require": { 284 "php": ">=7.1" 285 }, 286 "suggest": { 287 "ext-ctype": "For best performance" 288 }, 289 "time": "2021-01-07T16:49:33+00:00", 290 "type": "library", 291 "extra": { 292 "branch-alias": { 293 "dev-main": "1.22-dev" 294 }, 295 "thanks": { 296 "name": "symfony/polyfill", 297 "url": "https://github.com/symfony/polyfill" 298 } 299 }, 300 "installation-source": "dist", 301 "autoload": { 302 "psr-4": { 303 "Symfony\\Polyfill\\Ctype\\": "" 304 }, 305 "files": [ 306 "bootstrap.php" 307 ] 308 }, 309 "notification-url": "https://packagist.org/downloads/", 310 "license": [ 311 "MIT" 312 ], 313 "authors": [ 314 { 315 "name": "Gert de Pagter", 316 "email": "[email protected]" 317 }, 318 { 319 "name": "Symfony Community", 320 "homepage": "https://symfony.com/contributors" 321 } 322 ], 323 "description": "Symfony polyfill for ctype functions", 324 "homepage": "https://symfony.com", 325 "keywords": [ 326 "compatibility", 327 "ctype", 328 "polyfill", 329 "portable" 330 ], 331 "support": { 332 "source": "https://github.com/symfony/polyfill-ctype/tree/v1.22.1" 333 }, 334 "funding": [ 335 { 336 "url": "https://symfony.com/sponsor", 337 "type": "custom" 338 }, 339 { 340 "url": "https://github.com/fabpot", 341 "type": "github" 342 }, 343 { 344 "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 345 "type": "tidelift" 346 } 347 ], 348 "install-path": "../symfony/polyfill-ctype" 32 349 }, 33 "notification-url": "https://packagist.org/downloads/", 34 "license": [ 35 "MIT" 36 ], 37 "authors": [ 38 { 39 "name": "Taylor Hornby", 40 "email": "[email protected]", 41 "homepage": "https://defuse.ca/" 42 }, 43 { 44 "name": "Scott Arciszewski", 45 "email": "[email protected]", 46 "homepage": "https://paragonie.com" 47 } 48 ], 49 "description": "Secure PHP Encryption Library", 50 "keywords": [ 51 "aes", 52 "authenticated encryption", 53 "cipher", 54 "crypto", 55 "cryptography", 56 "encrypt", 57 "encryption", 58 "openssl", 59 "security", 60 "symmetric key cryptography" 61 ] 62 }, 63 { 64 "name": "monolog/monolog", 65 "version": "1.25.4", 66 "version_normalized": "1.25.4.0", 67 "source": { 68 "type": "git", 69 "url": "https://github.com/Seldaek/monolog.git", 70 "reference": "3022efff205e2448b560c833c6fbbf91c3139168" 71 }, 72 "dist": { 73 "type": "zip", 74 "url": "https://api.github.com/repos/Seldaek/monolog/zipball/3022efff205e2448b560c833c6fbbf91c3139168", 75 "reference": "3022efff205e2448b560c833c6fbbf91c3139168", 76 "shasum": "" 77 }, 78 "require": { 79 "php": ">=5.3.0", 80 "psr/log": "~1.0" 81 }, 82 "provide": { 83 "psr/log-implementation": "1.0.0" 84 }, 85 "require-dev": { 86 "aws/aws-sdk-php": "^2.4.9 || ^3.0", 87 "doctrine/couchdb": "~1.0@dev", 88 "graylog2/gelf-php": "~1.0", 89 "php-amqplib/php-amqplib": "~2.4", 90 "php-console/php-console": "^3.1.3", 91 "php-parallel-lint/php-parallel-lint": "^1.0", 92 "phpunit/phpunit": "~4.5", 93 "ruflin/elastica": ">=0.90 <3.0", 94 "sentry/sentry": "^0.13", 95 "swiftmailer/swiftmailer": "^5.3|^6.0" 96 }, 97 "suggest": { 98 "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 99 "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 100 "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 101 "ext-mongo": "Allow sending log messages to a MongoDB server", 102 "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 103 "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", 104 "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", 105 "php-console/php-console": "Allow sending log messages to Google Chrome", 106 "rollbar/rollbar": "Allow sending log messages to Rollbar", 107 "ruflin/elastica": "Allow sending log messages to an Elastic Search server", 108 "sentry/sentry": "Allow sending log messages to a Sentry server" 109 }, 110 "time": "2020-05-22T07:31:27+00:00", 111 "type": "library", 112 "extra": { 113 "branch-alias": { 114 "dev-master": "2.0.x-dev" 115 } 116 }, 117 "installation-source": "dist", 118 "autoload": { 119 "psr-4": { 120 "Monolog\\": "src/Monolog" 121 } 122 }, 123 "notification-url": "https://packagist.org/downloads/", 124 "license": [ 125 "MIT" 126 ], 127 "authors": [ 128 { 129 "name": "Jordi Boggiano", 130 "email": "[email protected]", 131 "homepage": "http://seld.be" 132 } 133 ], 134 "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 135 "homepage": "http://github.com/Seldaek/monolog", 136 "keywords": [ 137 "log", 138 "logging", 139 "psr-3" 140 ] 141 }, 142 { 143 "name": "paragonie/random_compat", 144 "version": "v2.0.18", 145 "version_normalized": "2.0.18.0", 146 "source": { 147 "type": "git", 148 "url": "https://github.com/paragonie/random_compat.git", 149 "reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db" 150 }, 151 "dist": { 152 "type": "zip", 153 "url": "https://api.github.com/repos/paragonie/random_compat/zipball/0a58ef6e3146256cc3dc7cc393927bcc7d1b72db", 154 "reference": "0a58ef6e3146256cc3dc7cc393927bcc7d1b72db", 155 "shasum": "" 156 }, 157 "require": { 158 "php": ">=5.2.0" 159 }, 160 "require-dev": { 161 "phpunit/phpunit": "4.*|5.*" 162 }, 163 "suggest": { 164 "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." 165 }, 166 "time": "2019-01-03T20:59:08+00:00", 167 "type": "library", 168 "installation-source": "dist", 169 "autoload": { 170 "files": [ 171 "lib/random.php" 172 ] 173 }, 174 "notification-url": "https://packagist.org/downloads/", 175 "license": [ 176 "MIT" 177 ], 178 "authors": [ 179 { 180 "name": "Paragon Initiative Enterprises", 181 "email": "[email protected]", 182 "homepage": "https://paragonie.com" 183 } 184 ], 185 "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", 186 "keywords": [ 187 "csprng", 188 "polyfill", 189 "pseudorandom", 190 "random" 191 ] 192 }, 193 { 194 "name": "psr/log", 195 "version": "1.1.3", 196 "version_normalized": "1.1.3.0", 197 "source": { 198 "type": "git", 199 "url": "https://github.com/php-fig/log.git", 200 "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc" 201 }, 202 "dist": { 203 "type": "zip", 204 "url": "https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc", 205 "reference": "0f73288fd15629204f9d42b7055f72dacbe811fc", 206 "shasum": "" 207 }, 208 "require": { 209 "php": ">=5.3.0" 210 }, 211 "time": "2020-03-23T09:12:05+00:00", 212 "type": "library", 213 "extra": { 214 "branch-alias": { 215 "dev-master": "1.1.x-dev" 216 } 217 }, 218 "installation-source": "dist", 219 "autoload": { 220 "psr-4": { 221 "Psr\\Log\\": "Psr/Log/" 222 } 223 }, 224 "notification-url": "https://packagist.org/downloads/", 225 "license": [ 226 "MIT" 227 ], 228 "authors": [ 229 { 230 "name": "PHP-FIG", 231 "homepage": "http://www.php-fig.org/" 232 } 233 ], 234 "description": "Common interface for logging libraries", 235 "homepage": "https://github.com/php-fig/log", 236 "keywords": [ 237 "log", 238 "psr", 239 "psr-3" 240 ] 241 }, 242 { 243 "name": "symfony/polyfill-ctype", 244 "version": "v1.17.1", 245 "version_normalized": "1.17.1.0", 246 "source": { 247 "type": "git", 248 "url": "https://github.com/symfony/polyfill-ctype.git", 249 "reference": "2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d" 250 }, 251 "dist": { 252 "type": "zip", 253 "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d", 254 "reference": "2edd75b8b35d62fd3eeabba73b26b8f1f60ce13d", 255 "shasum": "" 256 }, 257 "require": { 258 "php": ">=5.3.3" 259 }, 260 "suggest": { 261 "ext-ctype": "For best performance" 262 }, 263 "time": "2020-06-06T08:46:27+00:00", 264 "type": "library", 265 "extra": { 266 "branch-alias": { 267 "dev-master": "1.17-dev" 268 }, 269 "thanks": { 270 "name": "symfony/polyfill", 271 "url": "https://github.com/symfony/polyfill" 272 } 273 }, 274 "installation-source": "dist", 275 "autoload": { 276 "psr-4": { 277 "Symfony\\Polyfill\\Ctype\\": "" 278 }, 279 "files": [ 280 "bootstrap.php" 281 ] 282 }, 283 "notification-url": "https://packagist.org/downloads/", 284 "license": [ 285 "MIT" 286 ], 287 "authors": [ 288 { 289 "name": "Gert de Pagter", 290 "email": "[email protected]" 291 }, 292 { 293 "name": "Symfony Community", 294 "homepage": "https://symfony.com/contributors" 295 } 296 ], 297 "description": "Symfony polyfill for ctype functions", 298 "homepage": "https://symfony.com", 299 "keywords": [ 300 "compatibility", 301 "ctype", 302 "polyfill", 303 "portable" 304 ] 305 }, 306 { 307 "name": "twig/twig", 308 "version": "v1.41.0", 309 "version_normalized": "1.41.0.0", 310 "source": { 311 "type": "git", 312 "url": "https://github.com/twigphp/Twig.git", 313 "reference": "575cd5028362da591facde1ef5d7b94553c375c9" 314 }, 315 "dist": { 316 "type": "zip", 317 "url": "https://api.github.com/repos/twigphp/Twig/zipball/575cd5028362da591facde1ef5d7b94553c375c9", 318 "reference": "575cd5028362da591facde1ef5d7b94553c375c9", 319 "shasum": "" 320 }, 321 "require": { 322 "php": ">=5.4.0", 323 "symfony/polyfill-ctype": "^1.8" 324 }, 325 "require-dev": { 326 "psr/container": "^1.0", 327 "symfony/debug": "^2.7", 328 "symfony/phpunit-bridge": "^3.4.19|^4.1.8" 329 }, 330 "time": "2019-05-14T11:59:08+00:00", 331 "type": "library", 332 "extra": { 333 "branch-alias": { 334 "dev-master": "1.41-dev" 335 } 336 }, 337 "installation-source": "dist", 338 "autoload": { 339 "psr-0": { 340 "Twig_": "lib/" 341 }, 342 "psr-4": { 343 "Twig\\": "src/" 344 } 345 }, 346 "notification-url": "https://packagist.org/downloads/", 347 "license": [ 348 "BSD-3-Clause" 349 ], 350 "authors": [ 351 { 352 "name": "Fabien Potencier", 353 "email": "[email protected]", 354 "homepage": "http://fabien.potencier.org", 355 "role": "Lead Developer" 356 }, 357 { 358 "name": "Armin Ronacher", 359 "email": "[email protected]", 360 "role": "Project Founder" 361 }, 362 { 363 "name": "Twig Team", 364 "homepage": "https://twig.symfony.com/contributors", 365 "role": "Contributors" 366 } 367 ], 368 "description": "Twig, the flexible, fast, and secure template language for PHP", 369 "homepage": "https://twig.symfony.com", 370 "keywords": [ 371 "templating" 372 ] 373 } 374 ] 350 { 351 "name": "twig/twig", 352 "version": "v1.41.0", 353 "version_normalized": "1.41.0.0", 354 "source": { 355 "type": "git", 356 "url": "https://github.com/twigphp/Twig.git", 357 "reference": "575cd5028362da591facde1ef5d7b94553c375c9" 358 }, 359 "dist": { 360 "type": "zip", 361 "url": "https://api.github.com/repos/twigphp/Twig/zipball/575cd5028362da591facde1ef5d7b94553c375c9", 362 "reference": "575cd5028362da591facde1ef5d7b94553c375c9", 363 "shasum": "" 364 }, 365 "require": { 366 "php": ">=5.4.0", 367 "symfony/polyfill-ctype": "^1.8" 368 }, 369 "require-dev": { 370 "psr/container": "^1.0", 371 "symfony/debug": "^2.7", 372 "symfony/phpunit-bridge": "^3.4.19|^4.1.8" 373 }, 374 "time": "2019-05-14T11:59:08+00:00", 375 "type": "library", 376 "extra": { 377 "branch-alias": { 378 "dev-master": "1.41-dev" 379 } 380 }, 381 "installation-source": "dist", 382 "autoload": { 383 "psr-0": { 384 "Twig_": "lib/" 385 }, 386 "psr-4": { 387 "Twig\\": "src/" 388 } 389 }, 390 "notification-url": "https://packagist.org/downloads/", 391 "license": [ 392 "BSD-3-Clause" 393 ], 394 "authors": [ 395 { 396 "name": "Fabien Potencier", 397 "email": "[email protected]", 398 "homepage": "http://fabien.potencier.org", 399 "role": "Lead Developer" 400 }, 401 { 402 "name": "Armin Ronacher", 403 "email": "[email protected]", 404 "role": "Project Founder" 405 }, 406 { 407 "name": "Twig Team", 408 "homepage": "https://twig.symfony.com/contributors", 409 "role": "Contributors" 410 } 411 ], 412 "description": "Twig, the flexible, fast, and secure template language for PHP", 413 "homepage": "https://twig.symfony.com", 414 "keywords": [ 415 "templating" 416 ], 417 "support": { 418 "issues": "https://github.com/twigphp/Twig/issues", 419 "source": "https://github.com/twigphp/Twig/tree/1.x" 420 }, 421 "install-path": "../twig/twig" 422 } 423 ], 424 "dev": false, 425 "dev-package-names": [] 426 } -
next-active-directory-integration/trunk/vendor/monolog/monolog/CHANGELOG.md
r2331595 r2513920 1 ### 1.26.0 (2020-12-14) 2 3 * Added $dateFormat and $removeUsedContextFields arguments to PsrLogMessageProcessor (backport from 2.x) 4 5 ### 1.25.5 (2020-07-23) 6 7 * Fixed array access on null in RavenHandler 8 * Fixed unique_id in WebProcessor not being disableable 9 1 10 ### 1.25.4 (2020-05-22) 2 11 -
next-active-directory-integration/trunk/vendor/monolog/monolog/composer.json
r2331595 r2513920 27 27 "swiftmailer/swiftmailer": "^5.3|^6.0", 28 28 "php-console/php-console": "^3.1.3", 29 "php -parallel-lint/php-parallel-lint": "^1.0"29 "phpstan/phpstan": "^0.12.59" 30 30 }, 31 31 "suggest": { … … 51 51 "psr/log-implementation": "1.0.0" 52 52 }, 53 "extra": {54 "branch-alias": {55 "dev-master": "2.0.x-dev"56 }57 },58 53 "scripts": { 59 "test": [ 60 "parallel-lint . --exclude vendor --exclude src/Monolog/Handler/FormattableHandlerInterface.php --exclude src/Monolog/Handler/FormattableHandlerTrait.php --exclude src/Monolog/Handler/ProcessableHandlerInterface.php --exclude src/Monolog/Handler/ProcessableHandlerTrait.php", 61 "phpunit" 62 ] 54 "test": "vendor/bin/phpunit", 55 "phpstan": "vendor/bin/phpstan analyse" 63 56 }, 64 57 "lock": false -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/ErrorHandler.php
r2331595 r2513920 63 63 class_exists('\\Psr\\Log\\LogLevel', true); 64 64 65 /** @phpstan-ignore-next-line */ 65 66 $handler = new static($logger); 66 67 if ($errorLevelMap !== false) { -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php
r1756617 r2513920 78 78 $formatted = $this->marshaler->marshalItem($filtered); 79 79 } else { 80 /** @phpstan-ignore-next-line */ 80 81 $formatted = $this->client->formatAttributes($filtered); 81 82 } -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.php
r1986677 r2513920 73 73 * @see createHeader() 74 74 * @param array $record 75 * @return string75 * @return array 76 76 */ 77 77 protected function createRecordHeader(array $record) -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.php
r1986677 r2513920 28 28 { 29 29 /** 30 * @var Publisher the publisher object that sends the message to the server30 * @var Publisher|PublisherInterface|IMessagePublisher the publisher object that sends the message to the server 31 31 */ 32 32 protected $publisher; -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/Handler/HipChatHandler.php
r2224724 r2513920 271 271 * from the first record. 272 272 * 273 * @param $records273 * @param array $records 274 274 * @return array 275 275 */ 276 private function combineRecords( $records)276 private function combineRecords(array $records) 277 277 { 278 278 $batchRecord = null; -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php
r2224724 r2513920 51 51 52 52 /** 53 * @var LineFormatterThe formatter to use for the logs generated via handleBatch()53 * @var FormatterInterface The formatter to use for the logs generated via handleBatch() 54 54 */ 55 55 protected $batchFormatter; … … 87 87 // the record with the highest severity is the "main" one 88 88 $record = array_reduce($records, function ($highest, $record) { 89 if ( $record['level'] > $highest['level']) {89 if (null === $highest || $record['level'] > $highest['level']) { 90 90 return $record; 91 91 } -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php
r2224724 r2513920 37 37 * @param int $level The minimum logging level at which this handler will be triggered 38 38 * @param bool $bubble Whether the messages that are handled can bubble up the stack or not 39 * @param int $capSize Number of entries to limit list size to39 * @param int|false $capSize Number of entries to limit list size to 40 40 */ 41 41 public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true, $capSize = false) -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php
r2331595 r2513920 107 107 if (!is_resource($this->stream)) { 108 108 $this->stream = null; 109 throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage, $this->url)); 109 110 throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: '.$this->errorMessage, $this->url)); 110 111 } 111 112 } … … 154 155 } 155 156 156 return ;157 return null; 157 158 } 158 159 -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/Logger.php
r2224724 r2513920 523 523 * Converts PSR-3 levels to Monolog ones if necessary 524 524 * 525 * @param string|int Level number (monolog) or name (PSR-3)525 * @param string|int $level Level number (monolog) or name (PSR-3) 526 526 * @return int 527 527 */ -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php
r1986677 r2513920 23 23 class PsrLogMessageProcessor implements ProcessorInterface 24 24 { 25 const SIMPLE_DATE = "Y-m-d\TH:i:s.uP"; 26 27 /** @var string|null */ 28 private $dateFormat; 29 30 /** @var bool */ 31 private $removeUsedContextFields; 32 33 /** 34 * @param string|null $dateFormat The format of the timestamp: one supported by DateTime::format 35 * @param bool $removeUsedContextFields If set to true the fields interpolated into message gets unset 36 */ 37 public function __construct($dateFormat = null, $removeUsedContextFields = false) 38 { 39 $this->dateFormat = $dateFormat; 40 $this->removeUsedContextFields = $removeUsedContextFields; 41 } 42 25 43 /** 26 44 * @param array $record … … 35 53 $replacements = array(); 36 54 foreach ($record['context'] as $key => $val) { 55 $placeholder = '{' . $key . '}'; 56 if (strpos($record['message'], $placeholder) === false) { 57 continue; 58 } 59 37 60 if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) { 38 $replacements['{'.$key.'}'] = $val; 61 $replacements[$placeholder] = $val; 62 } elseif ($val instanceof \DateTime) { 63 $replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE); 39 64 } elseif (is_object($val)) { 40 $replacements['{'.$key.'}'] = '[object '.Utils::getClass($val).']'; 65 $replacements[$placeholder] = '[object '.Utils::getClass($val).']'; 66 } elseif (is_array($val)) { 67 $replacements[$placeholder] = 'array'.Utils::jsonEncode($val, null, true); 41 68 } else { 42 $replacements['{'.$key.'}'] = '['.gettype($val).']'; 69 $replacements[$placeholder] = '['.gettype($val).']'; 70 } 71 72 if ($this->removeUsedContextFields) { 73 unset($record['context'][$key]); 43 74 } 44 75 } -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php
r1986677 r2513920 53 53 } 54 54 55 if (isset($this->serverData['UNIQUE_ID'])) { 56 $this->extraFields['unique_id'] = 'UNIQUE_ID'; 57 } 58 55 59 if (null !== $extraFields) { 56 60 if (isset($extraFields[0])) { … … 105 109 } 106 110 107 if (isset($this->serverData['UNIQUE_ID'])) {108 $extra['unique_id'] = $this->serverData['UNIQUE_ID'];109 }110 111 111 return $extra; 112 112 } -
next-active-directory-integration/trunk/vendor/monolog/monolog/src/Monolog/Utils.php
r2331595 r2513920 169 169 * can be used as a callback for array_walk_recursive. 170 170 * 171 * @param mixed &$data Input to check and convert if needed171 * @param mixed $data Input to check and convert if needed, passed by ref 172 172 * @private 173 173 */ -
next-active-directory-integration/trunk/vendor/symfony/polyfill-ctype/bootstrap.php
r2331595 r2513920 11 11 12 12 use Symfony\Polyfill\Ctype as p; 13 14 if (\PHP_VERSION_ID >= 80000) { 15 return require __DIR__.'/bootstrap80.php'; 16 } 13 17 14 18 if (!function_exists('ctype_alnum')) { -
next-active-directory-integration/trunk/vendor/symfony/polyfill-ctype/composer.json
r2331595 r2513920 17 17 ], 18 18 "require": { 19 "php": ">= 5.3.3"19 "php": ">=7.1" 20 20 }, 21 21 "autoload": { … … 29 29 "extra": { 30 30 "branch-alias": { 31 "dev-ma ster": "1.17-dev"31 "dev-main": "1.22-dev" 32 32 }, 33 33 "thanks": { -
next-active-directory-integration/trunk/views/option/element.twig
r1595001 r2513920 43 43 {% import "option/element/table.twig" as table %} 44 44 {{ table.create(optionName, permission, inputId, false, false, i18n) }} 45 45 46 46 {% elseif type == constant('NextADInt_Multisite_Option_Type::VERIFICATION_PASSWORD') %} 47 47 … … 58 58 {% import "option/element/label.twig" as text %} 59 59 {{ text.create(optionName, permission, inputId) }} 60 61 {% elseif type == constant('NextADInt_Multisite_Option_Type::TEXTAREA') %} 62 63 {% import "option/element/textarea.twig" as textarea %} 64 {{ textarea.create(optionName, permission, inputId) }} 60 65 61 66 {% else %}
Note: See TracChangeset
for help on using the changeset viewer.