@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Move LDAP to new registration flow

Summary:
Ref T1536. LDAP is very likely the worst thing in existence.

This has some rough edges (error handling isn't perfect) but is already better than the current LDAP experience! durrr

Test Plan: Registered and logged in using LDAP.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran, mbishopim3

Maniphest Tasks: T1536

Differential Revision: https://secure.phabricator.com/D6177

+170 -7
+2
src/__phutil_library_map__.php
··· 817 817 'PhabricatorAuthController' => 'applications/auth/controller/PhabricatorAuthController.php', 818 818 'PhabricatorAuthLoginController' => 'applications/auth/controller/PhabricatorAuthLoginController.php', 819 819 'PhabricatorAuthProvider' => 'applications/auth/provider/PhabricatorAuthProvider.php', 820 + 'PhabricatorAuthProviderLDAP' => 'applications/auth/provider/PhabricatorAuthProviderLDAP.php', 820 821 'PhabricatorAuthProviderOAuth' => 'applications/auth/provider/PhabricatorAuthProviderOAuth.php', 821 822 'PhabricatorAuthProviderOAuthDisqus' => 'applications/auth/provider/PhabricatorAuthProviderOAuthDisqus.php', 822 823 'PhabricatorAuthProviderOAuthFacebook' => 'applications/auth/provider/PhabricatorAuthProviderOAuthFacebook.php', ··· 2680 2681 'PhabricatorAuditReplyHandler' => 'PhabricatorMailReplyHandler', 2681 2682 'PhabricatorAuthController' => 'PhabricatorController', 2682 2683 'PhabricatorAuthLoginController' => 'PhabricatorAuthController', 2684 + 'PhabricatorAuthProviderLDAP' => 'PhabricatorAuthProvider', 2683 2685 'PhabricatorAuthProviderOAuth' => 'PhabricatorAuthProvider', 2684 2686 'PhabricatorAuthProviderOAuthDisqus' => 'PhabricatorAuthProviderOAuth', 2685 2687 'PhabricatorAuthProviderOAuthFacebook' => 'PhabricatorAuthProviderOAuth',
+162
src/applications/auth/provider/PhabricatorAuthProviderLDAP.php
··· 1 + <?php 2 + 3 + final class PhabricatorAuthProviderLDAP 4 + extends PhabricatorAuthProvider { 5 + 6 + private $adapter; 7 + 8 + public function getProviderName() { 9 + return pht('LDAP'); 10 + } 11 + 12 + public function isEnabled() { 13 + return parent::isEnabled() && 14 + PhabricatorEnv::getEnvConfig('ldap.auth-enabled'); 15 + } 16 + 17 + public function getAdapter() { 18 + if (!$this->adapter) { 19 + $adapter = id(new PhutilAuthAdapterLDAP()) 20 + ->setHostname(PhabricatorEnv::getEnvConfig('ldap.hostname')) 21 + ->setPort(PhabricatorEnv::getEnvConfig('ldap.port')) 22 + ->setBaseDistinguishedName(PhabricatorEnv::getEnvConfig('ldap.base_dn')) 23 + ->setSearchAttribute( 24 + PhabricatorEnv::getEnvConfig('ldap.search_attribute')) 25 + ->setUsernameAttribute( 26 + PhabricatorEnv::getEnvConfig('ldap.username-attribute')) 27 + ->setLDAPVersion(PhabricatorEnv::getEnvConfig('ldap.version')) 28 + ->setLDAPReferrals(PhabricatorEnv::getEnvConfig('ldap.referrals')) 29 + ->setLDAPStartTLS(PhabricatorEnv::getEnvConfig('ldap.start-tls')) 30 + ->setAnonymousUsername( 31 + PhabricatorEnv::getEnvConfig('ldap.anonymous-user-name')) 32 + ->setAnonymousPassword( 33 + new PhutilOpaqueEnvelope( 34 + PhabricatorEnv::getEnvConfig('ldap.anonymous-user-password'))) 35 + ->setSearchFirst(PhabricatorEnv::getEnvConfig('ldap.search-first')) 36 + ->setActiveDirectoryDomain( 37 + PhabricatorEnv::getEnvConfig('ldap.activedirectory_domain')); 38 + $this->adapter = $adapter; 39 + } 40 + return $this->adapter; 41 + } 42 + 43 + public function shouldAllowLogin() { 44 + return true; 45 + } 46 + 47 + public function shouldAllowRegistration() { 48 + return true; 49 + } 50 + 51 + public function shouldAllowAccountLink() { 52 + return false; 53 + } 54 + 55 + public function shouldAllowAccountUnlink() { 56 + return false; 57 + } 58 + 59 + public function buildLoginForm( 60 + PhabricatorAuthStartController $controller) { 61 + 62 + $request = $controller->getRequest(); 63 + return $this->renderLoginForm($request); 64 + } 65 + 66 + private function renderLoginForm(AphrontRequest $request) { 67 + 68 + $viewer = $request->getUser(); 69 + 70 + $submit = id(new AphrontFormSubmitControl()) 71 + ->setValue(pht('Login or Register')); 72 + 73 + $header = id(new PhabricatorHeaderView()) 74 + ->setHeader(pht('Login with LDAP')); 75 + 76 + $v_user = $request->getStr('ldap_username'); 77 + 78 + $e_user = null; 79 + $e_pass = null; 80 + 81 + $errors = array(); 82 + if ($request->isHTTPPost()) { 83 + // NOTE: This is intentionally vague so as not to disclose whether a 84 + // given username exists. 85 + $e_user = pht('Invalid'); 86 + $e_pass = pht('Invalid'); 87 + $errors[] = pht('Username or password are incorrect.'); 88 + } 89 + 90 + $form = id(new AphrontFormView()) 91 + ->setAction($this->getLoginURI()) 92 + ->setUser($viewer) 93 + ->setFlexible(true) 94 + ->appendChild( 95 + id(new AphrontFormTextControl()) 96 + ->setLabel('LDAP Username') 97 + ->setName('ldap_username') 98 + ->setValue($v_user) 99 + ->setError($e_user)) 100 + ->appendChild( 101 + id(new AphrontFormPasswordControl()) 102 + ->setLabel('LDAP Password') 103 + ->setName('ldap_password') 104 + ->setError($e_pass)) 105 + ->appendChild($submit); 106 + 107 + if ($errors) { 108 + $errors = id(new AphrontErrorView())->setErrors($errors); 109 + } 110 + 111 + return array( 112 + $errors, 113 + $header, 114 + $form, 115 + ); 116 + } 117 + 118 + public function processLoginRequest( 119 + PhabricatorAuthLoginController $controller) { 120 + 121 + $request = $controller->getRequest(); 122 + $viewer = $request->getUser(); 123 + $response = null; 124 + $account = null; 125 + 126 + $username = $request->getStr('ldap_username'); 127 + $password = $request->getStr('ldap_password'); 128 + $has_password = strlen($password); 129 + $password = new PhutilOpaqueEnvelope($password); 130 + 131 + if (!strlen($username) || !$has_password) { 132 + $response = $controller->buildProviderPageResponse( 133 + $this, 134 + $this->renderLoginForm($request)); 135 + return array($account, $response); 136 + } 137 + 138 + try { 139 + if (strlen($username) && $has_password) { 140 + $adapter = $this->getAdapter(); 141 + $adapter->setLoginUsername($username); 142 + $adapter->setLoginPassword($password); 143 + 144 + // TODO: This calls ldap_bind() eventually, which dumps cleartext 145 + // passwords to the error log. See note in PhutilAuthAdapterLDAP. 146 + // See T3351. 147 + 148 + DarkConsoleErrorLogPluginAPI::enableDiscardMode(); 149 + $account_id = $adapter->getAccountID(); 150 + DarkConsoleErrorLogPluginAPI::disableDiscardMode(); 151 + } else { 152 + throw new Exception("Username and password are required!"); 153 + } 154 + } catch (Exception $ex) { 155 + // TODO: Make this cleaner. 156 + throw $ex; 157 + } 158 + 159 + return array($this->loadOrCreateAccount($account_id), $response); 160 + } 161 + 162 + }
+6 -7
src/applications/auth/provider/PhabricatorAuthProviderPassword.php
··· 164 164 165 165 if (!$require_captcha || $captcha_valid) { 166 166 $username_or_email = $request->getStr('username'); 167 - 168 167 if (strlen($username_or_email)) { 169 168 $user = id(new PhabricatorUser())->loadOneWhere( 170 169 'username = %s', ··· 173 172 if (!$user) { 174 173 $user = PhabricatorUser::loadOneWithEmailAddress($username_or_email); 175 174 } 176 - } 177 175 178 - if ($user) { 179 - $envelope = new PhutilOpaqueEnvelope($request->getStr('password')); 180 - if ($user->comparePassword($envelope)) { 181 - $account = $this->loadOrCreateAccount($user->getPHID()); 182 - $log_user = $user; 176 + if ($user) { 177 + $envelope = new PhutilOpaqueEnvelope($request->getStr('password')); 178 + if ($user->comparePassword($envelope)) { 179 + $account = $this->loadOrCreateAccount($user->getPHID()); 180 + $log_user = $user; 181 + } 183 182 } 184 183 } 185 184 }