@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.

Migrate VCS passwords to new shared password infrastructure

Summary:
Ref T13043. Migrate VCS passwords away from their dedicated table to new the new shared infrastructure.

Future changes will migrate account passwords and remove the old table.

Test Plan:
- Ran migrations.
- Cloned with the same password that was configured before the migrations (worked).
- Cloned with a different, invalid password (failed).
- Changed password.
- Cloned with old password (failed).
- Cloned with new password (worked).
- Deleted password in web UI.
- Cloned with old password (failed).
- Set password to the same password as it currently is set to (worked, no "unique" collision).
- Set password to account password. !!This (incorrectly) works for now until account passwords migrate, since the uniqueness check can't see them yet.!!
- Set password to a new unique password.
- Cloned (worked).
- Revoked the password with `bin/auth revoke`.
- Verified web UI shows "no password set".
- Verified that pull no longer works.
- Verified that I can no longer select the revoked password.
- Verified that accounts do not interact:
- Tried to set account B to account A's password (worked).
- Tried to set account B to a password revoked on account A (worked).
- Spot checked the `password` and `passwordtransaction` tables for saniity.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13043

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

+69 -37
+5
resources/sql/autopatches/20180120.auth.03.vcsdata.sql
··· 1 + INSERT INTO {$NAMESPACE}_auth.auth_password 2 + (objectPHID, phid, passwordType, passwordHash, isRevoked, 3 + dateCreated, dateModified) 4 + SELECT userPHID, '', 'vcs', passwordHash, 0, dateCreated, dateModified 5 + FROM {$NAMESPACE}_repository.repository_vcspassword;
+22
resources/sql/autopatches/20180120.auth.04.vcsphid.php
··· 1 + <?php 2 + 3 + // Populate VCS passwords (which we copied from the old "VCS Password" table 4 + // in the last migration) with new PHIDs. 5 + 6 + $table = new PhabricatorAuthPassword(); 7 + $conn = $table->establishConnection('w'); 8 + 9 + foreach (new LiskMigrationIterator($table) as $row) { 10 + if ($row->getPHID()) { 11 + continue; 12 + } 13 + 14 + $new_phid = $row->generatePHID(); 15 + 16 + queryfx( 17 + $conn, 18 + 'UPDATE %T SET phid = %s WHERE id = %d', 19 + $table->getTableName(), 20 + $new_phid, 21 + $row->getID()); 22 + }
+9 -20
src/applications/diffusion/controller/DiffusionServeController.php
··· 715 715 return null; 716 716 } 717 717 718 - $password_entry = id(new PhabricatorRepositoryVCSPassword()) 719 - ->loadOneWhere('userPHID = %s', $user->getPHID()); 720 - if (!$password_entry) { 721 - // User doesn't have a password set. 722 - return null; 723 - } 718 + $request = $this->getRequest(); 719 + $content_source = PhabricatorContentSource::newFromRequest($request); 720 + 721 + $engine = id(new PhabricatorAuthPasswordEngine()) 722 + ->setViewer($user) 723 + ->setContentSource($content_source) 724 + ->setPasswordType(PhabricatorAuthPassword::PASSWORD_TYPE_VCS) 725 + ->setObject($user); 724 726 725 - if (!$password_entry->comparePassword($password, $user)) { 726 - // Password doesn't match. 727 + if (!$engine->isValidPassword($password)) { 727 728 return null; 728 - } 729 - 730 - // If the user's password is stored using a less-than-optimal hash, upgrade 731 - // them to the strongest available hash. 732 - 733 - $hash_envelope = new PhutilOpaqueEnvelope( 734 - $password_entry->getPasswordHash()); 735 - if (PhabricatorPasswordHasher::canUpgradeHash($hash_envelope)) { 736 - $password_entry->setPassword($password, $user); 737 - $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites(); 738 - $password_entry->save(); 739 - unset($unguarded); 740 729 } 741 730 742 731 return $user;
+33 -17
src/applications/diffusion/panel/DiffusionSetPasswordSettingsPanel.php
··· 35 35 $request, 36 36 '/settings/'); 37 37 38 - $vcspassword = id(new PhabricatorRepositoryVCSPassword()) 39 - ->loadOneWhere( 40 - 'userPHID = %s', 41 - $user->getPHID()); 42 - if (!$vcspassword) { 43 - $vcspassword = id(new PhabricatorRepositoryVCSPassword()); 44 - $vcspassword->setUserPHID($user->getPHID()); 38 + $vcs_type = PhabricatorAuthPassword::PASSWORD_TYPE_VCS; 39 + 40 + $vcspasswords = id(new PhabricatorAuthPasswordQuery()) 41 + ->setViewer($viewer) 42 + ->withObjectPHIDs(array($user->getPHID())) 43 + ->withPasswordTypes(array($vcs_type)) 44 + ->withIsRevoked(false) 45 + ->execute(); 46 + if ($vcspasswords) { 47 + $vcspassword = head($vcspasswords); 48 + } else { 49 + $vcspassword = PhabricatorAuthPassword::initializeNewPassword( 50 + $user, 51 + $vcs_type); 45 52 } 46 53 47 54 $panel_uri = $this->getPanelURI('?saved=true'); ··· 77 84 78 85 if (!$errors) { 79 86 $envelope = new PhutilOpaqueEnvelope($new_password); 87 + $content_source = PhabricatorContentSource::newFromRequest($request); 80 88 81 - try { 82 - // NOTE: This test is against $viewer (not $user), so that the error 83 - // message below makes sense in the case that the two are different, 84 - // and because an admin reusing their own password is bad, while 85 - // system agents generally do not have passwords anyway. 89 + // NOTE: This test is against $viewer (not $user), so that the error 90 + // message below makes sense in the case that the two are different, 91 + // and because an admin reusing their own password is bad, while 92 + // system agents generally do not have passwords anyway. 93 + 94 + $engine = id(new PhabricatorAuthPasswordEngine()) 95 + ->setViewer($viewer) 96 + ->setContentSource($content_source) 97 + ->setObject($viewer) 98 + ->setPasswordType($vcs_type); 86 99 87 - $same_password = $viewer->comparePassword($envelope); 88 - } catch (PhabricatorPasswordHasherUnavailableException $ex) { 89 - // If we're missing the hasher, just let the user continue. 90 - $same_password = false; 91 - } 100 + $same_password = !$engine->isUniquePassword($envelope); 101 + $revoked_password = $engine->isRevokedPassword($envelope); 92 102 93 103 if ($new_password !== $confirm) { 94 104 $e_password = pht('Does Not Match'); 95 105 $e_confirm = pht('Does Not Match'); 96 106 $errors[] = pht('Password and confirmation do not match.'); 107 + } else if ($revoked_password) { 108 + $e_password = pht('Revoked'); 109 + $e_confirm = pht('Revoked'); 110 + $errors[] = pht( 111 + 'This password has been revoked. You must choose a new, unique '. 112 + 'password.'); 97 113 } else if ($same_password) { 98 114 $e_password = pht('Not Unique'); 99 115 $e_confirm = pht('Not Unique');