| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | final class PassphraseCredentialEditController extends PassphraseController { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-27 09:06:01 -07:00
										 |  |  |   public function handleRequest(AphrontRequest $request) { | 
					
						
							|  |  |  |     $viewer = $request->getViewer(); | 
					
						
							|  |  |  |     $id = $request->getURIData('id'); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-07-27 09:06:01 -07:00
										 |  |  |     if ($id) { | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |       $credential = id(new PassphraseCredentialQuery()) | 
					
						
							|  |  |  |         ->setViewer($viewer) | 
					
						
							| 
									
										
										
										
											2015-07-27 09:06:01 -07:00
										 |  |  |         ->withIDs(array($id)) | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |         ->requireCapabilities( | 
					
						
							|  |  |  |           array( | 
					
						
							|  |  |  |             PhabricatorPolicyCapability::CAN_VIEW, | 
					
						
							|  |  |  |             PhabricatorPolicyCapability::CAN_EDIT, | 
					
						
							|  |  |  |           )) | 
					
						
							|  |  |  |         ->executeOne(); | 
					
						
							|  |  |  |       if (!$credential) { | 
					
						
							|  |  |  |         return new Aphront404Response(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-26 05:46:26 -07:00
										 |  |  |       $type = $this->getCredentialType($credential->getCredentialType()); | 
					
						
							| 
									
										
										
										
											2016-04-12 19:25:00 -07:00
										 |  |  |       $type_const = $type->getCredentialType(); | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |       $is_new = false; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       $type_const = $request->getStr('type'); | 
					
						
							| 
									
										
										
										
											2014-05-26 05:46:26 -07:00
										 |  |  |       $type = $this->getCredentialType($type_const); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!$type->isCreateable()) { | 
					
						
							|  |  |  |         throw new Exception( | 
					
						
							|  |  |  |           pht( | 
					
						
							|  |  |  |             'Credential has noncreateable type "%s"!', | 
					
						
							| 
									
										
											  
											
												Implement a rough AlmanacService blueprint in Drydock
Summary:
Ref T9253. Broadly, this realigns Allocator behavior to be more consistent and straightforward and amenable to intended future changes.
This attempts to make language more consistent: resources are "allocated" and leases are "acquired".
This prepares for (but does not implement) optimistic "slot locking", as discussed in D10304. Although I suspect some blueprints will need to perform other locking eventually, this does feel like a good fit for most of the locking blueprints need to do.
In particular, I've made the blueprint operations on `$resource` and `$lease` objects more purposeful: they need to invoke an activator on the appropriate object to be implemented correctly. Before they invoke this activator method, they configure the object. In a future diff, this configuration will include specifying slot locks that the lease or resource must acquire. So the API will be something like:
  $lease
    ->setActivateWhenAcquired(true)
    ->needSlotLock('x')
    ->needSlotLock('y')
    ->acquireOnResource($resource);
In the common case where slot locks are a good fit, I think this should make correct blueprint implementation very straightforward.
This prepares for (but does not implement) resources and leases which need significant setup steps. I've basically carved out two modes:
  - The "activate immediately" mode, as here, immediately opens the resource or activates the lease. This is appropriate if little or no setup is required. I expect many leases to operate in this mode, although I expect many resources will operate in the other mode.
  - The "allocate now, activate later" mode, which is not fully implemented yet. This will queue setup workers when the allocator exits. Overall, this will work very similarly to Harbormaster.
  - This new structure makes it acceptable for blueprints to sleep as long as they want during resource allocation and lease acquisition, so long as they are not waiting on anything which needs to be completed by the queue. Putting a `sleep(15 * 60)` in your EC2Blueprint to wait for EC2 to bring a machine up will perform worse than using delayed activation, but won't deadlock the queue or block any locks.
Overall, this flow is more similar to Harbormaster's flow. Having consistency between Harbormaster's model and Drydock's model is good, and I think Harbormaster's model is also simply much better than Drydock's (what exists today in Drydock was implemented a long time ago, and we had more support and infrastructure by the time Harbormaster was implemented, as well as a more clearly defined problem).
The particular strength of Harbormaster is that objects always (or almost always, at least) have a single, clearly defined writer. Ensuring objects have only one writer prevents races and makes reasoning about everything easier.
Drydock does not currently have a clearly defined single writer, but this moves us in that direction. We'll probably need more primitives eventually to flesh this out, like Harbormaster's command queue for messaging objects which you can't write to.
This blueprint was originally implemented in D13843. This makes a few changes to the blueprint itself:
  - A bunch of code from that (e.g., interfaces) doesn't exist yet.
  - I let the blueprint have multiple services. This simplifies the code a little and seems like it costs us nothing.
This also removes `bin/drydock create-resource`, which no longer makes sense to expose. It won't get locking, leasing, etc., correct, and can not be made correct.
NOTE: This technically works but doesn't do anything useful yet.
Test Plan: Used `bin/drydock lease --type host` to acquire leases against these blueprints.
Reviewers: hach-que, chad
Reviewed By: hach-que, chad
Subscribers: Mnkras
Maniphest Tasks: T9253
Differential Revision: https://secure.phabricator.com/D14117
											
										 
											2015-09-21 04:43:53 -07:00
										 |  |  |             $type_const)); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       $credential = PassphraseCredential::initializeNewCredential($viewer) | 
					
						
							|  |  |  |         ->setCredentialType($type->getCredentialType()) | 
					
						
							| 
									
										
										
										
											2016-03-22 18:51:39 -07:00
										 |  |  |         ->setProvidesType($type->getProvidesType()) | 
					
						
							|  |  |  |         ->attachImplementation($type); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       $is_new = true; | 
					
						
							| 
									
										
										
										
											2013-11-22 14:35:35 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |       // Prefill username if provided.
 | 
					
						
							| 
									
										
										
										
											2015-06-16 13:44:51 -07:00
										 |  |  |       $credential->setUsername((string)$request->getStr('username')); | 
					
						
							| 
									
										
										
										
											2014-03-12 18:58:25 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (!$request->getStr('isInitialized')) { | 
					
						
							|  |  |  |         $type->didInitializeNewCredential($viewer, $credential); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $errors = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $v_name = $credential->getName(); | 
					
						
							|  |  |  |     $e_name = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $v_desc = $credential->getDescription(); | 
					
						
							| 
									
										
										
										
											2015-06-22 11:28:54 -07:00
										 |  |  |     $v_space = $credential->getSpacePHID(); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     $v_username = $credential->getUsername(); | 
					
						
							|  |  |  |     $e_username = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-04 05:00:14 -07:00
										 |  |  |     $v_is_locked = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |     $bullet = "\xE2\x80\xA2"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $v_secret = $credential->getSecretID() ? str_repeat($bullet, 32) : null; | 
					
						
							| 
									
										
										
										
											2014-03-12 18:58:25 -07:00
										 |  |  |     if ($is_new && ($v_secret === null)) { | 
					
						
							|  |  |  |       // If we're creating a new credential, the credential type may have
 | 
					
						
							|  |  |  |       // populated the secret for us (for example, generated an SSH key). In
 | 
					
						
							|  |  |  |       // this case,
 | 
					
						
							|  |  |  |       try { | 
					
						
							|  |  |  |         $v_secret = $credential->getSecret()->openEnvelope(); | 
					
						
							|  |  |  |       } catch (Exception $ex) { | 
					
						
							|  |  |  |         // Ignore this.
 | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     $validation_exception = null; | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |     $errors = array(); | 
					
						
							|  |  |  |     $e_password = null; | 
					
						
							| 
									
										
											  
											
												Correctly identify more SSH private key problems as "formatting" or "passphrase" related
Summary:
Ref T13454. Fixes T13006. When a user provide us with an SSH private key and (possibly) a passphrase:
  # Try to verify that they're correct by extracting the public key.
  # If that fails, try to figure out why it didn't work.
Our success in step (2) will vary depending on what the problem is, and we may end up falling through to a very generic error, but the outcome should generally be better than the old approach.
Previously, we had a very unsophisticated test for the text "ENCRYPTED" in the key body and questionable handling of the results: for example, providing a passphrase when a key did not require one did not raise an error.
Test Plan:
Created and edited credentials with:
  - Valid, passphrase-free keys.
  - Valid, passphrased keys with the right passphrase.
  - Valid, passphrase-free keys with a passphrase ("surplus passphrase" error).
  - Valid, passphrased keys with no passphrase ("missing passphrase" error).
  - Valid, passphrased keys with an invalid passphrase ("invalid passphrase" error).
  - Invalid keys ("format" error).
The precision of these errors will vary depending on how helpful "ssh-keygen" is.
Maniphest Tasks: T13454, T13006
Differential Revision: https://secure.phabricator.com/D20905
											
										 
											2019-11-09 08:32:24 -08:00
										 |  |  |     $e_secret = null; | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |     if ($request->isFormPost()) { | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |       $v_name = $request->getStr('name'); | 
					
						
							|  |  |  |       $v_desc = $request->getStr('description'); | 
					
						
							|  |  |  |       $v_username = $request->getStr('username'); | 
					
						
							|  |  |  |       $v_view_policy = $request->getStr('viewPolicy'); | 
					
						
							|  |  |  |       $v_edit_policy = $request->getStr('editPolicy'); | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |       $v_is_locked = $request->getStr('lock'); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |       $v_secret = $request->getStr('secret'); | 
					
						
							| 
									
										
										
										
											2015-06-22 11:28:54 -07:00
										 |  |  |       $v_space = $request->getStr('spacePHID'); | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |       $v_password = $request->getStr('password'); | 
					
						
							|  |  |  |       $v_decrypt = $v_secret; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       $env_secret = new PhutilOpaqueEnvelope($v_secret); | 
					
						
							|  |  |  |       $env_password = new PhutilOpaqueEnvelope($v_password); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Correctly identify more SSH private key problems as "formatting" or "passphrase" related
Summary:
Ref T13454. Fixes T13006. When a user provide us with an SSH private key and (possibly) a passphrase:
  # Try to verify that they're correct by extracting the public key.
  # If that fails, try to figure out why it didn't work.
Our success in step (2) will vary depending on what the problem is, and we may end up falling through to a very generic error, but the outcome should generally be better than the old approach.
Previously, we had a very unsophisticated test for the text "ENCRYPTED" in the key body and questionable handling of the results: for example, providing a passphrase when a key did not require one did not raise an error.
Test Plan:
Created and edited credentials with:
  - Valid, passphrase-free keys.
  - Valid, passphrased keys with the right passphrase.
  - Valid, passphrase-free keys with a passphrase ("surplus passphrase" error).
  - Valid, passphrased keys with no passphrase ("missing passphrase" error).
  - Valid, passphrased keys with an invalid passphrase ("invalid passphrase" error).
  - Invalid keys ("format" error).
The precision of these errors will vary depending on how helpful "ssh-keygen" is.
Maniphest Tasks: T13454, T13006
Differential Revision: https://secure.phabricator.com/D20905
											
										 
											2019-11-09 08:32:24 -08:00
										 |  |  |       $has_secret = !preg_match('/^('.$bullet.')+$/', trim($v_decrypt)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Validate and repair SSH private keys, and apply passwords if they
 | 
					
						
							|  |  |  |       // are provided. See T13454 for discussion.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // This should eventually be refactored to be modular rather than a
 | 
					
						
							|  |  |  |       // hard-coded set of behaviors here in the Controller, but this is
 | 
					
						
							|  |  |  |       // likely a fairly extensive change.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       $is_ssh = ($type instanceof PassphraseSSHPrivateKeyTextCredentialType); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if ($is_ssh && $has_secret) { | 
					
						
							|  |  |  |         $old_object = PhabricatorAuthSSHPrivateKey::newFromRawKey($env_secret); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |         if (strlen($v_password)) { | 
					
						
							| 
									
										
											  
											
												Correctly identify more SSH private key problems as "formatting" or "passphrase" related
Summary:
Ref T13454. Fixes T13006. When a user provide us with an SSH private key and (possibly) a passphrase:
  # Try to verify that they're correct by extracting the public key.
  # If that fails, try to figure out why it didn't work.
Our success in step (2) will vary depending on what the problem is, and we may end up falling through to a very generic error, but the outcome should generally be better than the old approach.
Previously, we had a very unsophisticated test for the text "ENCRYPTED" in the key body and questionable handling of the results: for example, providing a passphrase when a key did not require one did not raise an error.
Test Plan:
Created and edited credentials with:
  - Valid, passphrase-free keys.
  - Valid, passphrased keys with the right passphrase.
  - Valid, passphrase-free keys with a passphrase ("surplus passphrase" error).
  - Valid, passphrased keys with no passphrase ("missing passphrase" error).
  - Valid, passphrased keys with an invalid passphrase ("invalid passphrase" error).
  - Invalid keys ("format" error).
The precision of these errors will vary depending on how helpful "ssh-keygen" is.
Maniphest Tasks: T13454, T13006
Differential Revision: https://secure.phabricator.com/D20905
											
										 
											2019-11-09 08:32:24 -08:00
										 |  |  |           $old_object->setPassphrase($env_password); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |           $new_object = $old_object->newBarePrivateKey(); | 
					
						
							|  |  |  |           $v_decrypt = $new_object->getKeyBody()->openEnvelope(); | 
					
						
							|  |  |  |         } catch (PhabricatorAuthSSHPrivateKeyException $ex) { | 
					
						
							|  |  |  |           $errors[] = $ex->getMessage(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if ($ex->isFormatException()) { | 
					
						
							|  |  |  |             $e_secret = pht('Invalid'); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           if ($ex->isPassphraseException()) { | 
					
						
							|  |  |  |             $e_password = pht('Invalid'); | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |       if (!$errors) { | 
					
						
							| 
									
										
										
										
											2017-05-04 11:17:47 -07:00
										 |  |  |         $type_name = | 
					
						
							|  |  |  |           PassphraseCredentialNameTransaction::TRANSACTIONTYPE; | 
					
						
							|  |  |  |         $type_desc = | 
					
						
							|  |  |  |           PassphraseCredentialDescriptionTransaction::TRANSACTIONTYPE; | 
					
						
							|  |  |  |         $type_username = | 
					
						
							|  |  |  |           PassphraseCredentialUsernameTransaction::TRANSACTIONTYPE; | 
					
						
							|  |  |  |         $type_destroy = | 
					
						
							|  |  |  |           PassphraseCredentialDestroyTransaction::TRANSACTIONTYPE; | 
					
						
							|  |  |  |         $type_secret_id = | 
					
						
							|  |  |  |           PassphraseCredentialSecretIDTransaction::TRANSACTIONTYPE; | 
					
						
							|  |  |  |         $type_is_locked = | 
					
						
							|  |  |  |           PassphraseCredentialLockTransaction::TRANSACTIONTYPE; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |         $type_view_policy = PhabricatorTransactions::TYPE_VIEW_POLICY; | 
					
						
							|  |  |  |         $type_edit_policy = PhabricatorTransactions::TYPE_EDIT_POLICY; | 
					
						
							| 
									
										
										
										
											2015-06-22 11:28:54 -07:00
										 |  |  |         $type_space = PhabricatorTransactions::TYPE_SPACE; | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |         $xactions = array(); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |         $xactions[] = id(new PassphraseCredentialTransaction()) | 
					
						
							|  |  |  |           ->setTransactionType($type_name) | 
					
						
							|  |  |  |           ->setNewValue($v_name); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |         $xactions[] = id(new PassphraseCredentialTransaction()) | 
					
						
							|  |  |  |           ->setTransactionType($type_desc) | 
					
						
							|  |  |  |           ->setNewValue($v_desc); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         $xactions[] = id(new PassphraseCredentialTransaction()) | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |           ->setTransactionType($type_view_policy) | 
					
						
							|  |  |  |           ->setNewValue($v_view_policy); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |         $xactions[] = id(new PassphraseCredentialTransaction()) | 
					
						
							|  |  |  |           ->setTransactionType($type_edit_policy) | 
					
						
							|  |  |  |           ->setNewValue($v_edit_policy); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-22 11:28:54 -07:00
										 |  |  |         $xactions[] = id(new PassphraseCredentialTransaction()) | 
					
						
							|  |  |  |           ->setTransactionType($type_space) | 
					
						
							|  |  |  |           ->setNewValue($v_space); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |         // Open a transaction in case we're writing a new secret; this limits
 | 
					
						
							|  |  |  |         // the amount of code which handles secret plaintexts.
 | 
					
						
							|  |  |  |         $credential->openTransaction(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |         if (!$credential->getIsLocked()) { | 
					
						
							| 
									
										
										
										
											2015-06-16 13:44:51 -07:00
										 |  |  |           if ($type->shouldRequireUsername()) { | 
					
						
							|  |  |  |             $xactions[] = id(new PassphraseCredentialTransaction()) | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |             ->setTransactionType($type_username) | 
					
						
							|  |  |  |             ->setNewValue($v_username); | 
					
						
							| 
									
										
										
										
											2015-06-16 13:44:51 -07:00
										 |  |  |           } | 
					
						
							| 
									
										
											  
											
												Correctly identify more SSH private key problems as "formatting" or "passphrase" related
Summary:
Ref T13454. Fixes T13006. When a user provide us with an SSH private key and (possibly) a passphrase:
  # Try to verify that they're correct by extracting the public key.
  # If that fails, try to figure out why it didn't work.
Our success in step (2) will vary depending on what the problem is, and we may end up falling through to a very generic error, but the outcome should generally be better than the old approach.
Previously, we had a very unsophisticated test for the text "ENCRYPTED" in the key body and questionable handling of the results: for example, providing a passphrase when a key did not require one did not raise an error.
Test Plan:
Created and edited credentials with:
  - Valid, passphrase-free keys.
  - Valid, passphrased keys with the right passphrase.
  - Valid, passphrase-free keys with a passphrase ("surplus passphrase" error).
  - Valid, passphrased keys with no passphrase ("missing passphrase" error).
  - Valid, passphrased keys with an invalid passphrase ("invalid passphrase" error).
  - Invalid keys ("format" error).
The precision of these errors will vary depending on how helpful "ssh-keygen" is.
Maniphest Tasks: T13454, T13006
Differential Revision: https://secure.phabricator.com/D20905
											
										 
											2019-11-09 08:32:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-04 12:48:05 -07:00
										 |  |  |           // If some value other than a sequence of bullets was provided for
 | 
					
						
							|  |  |  |           // the credential, update it. In particular, note that we are
 | 
					
						
							|  |  |  |           // explicitly allowing empty secrets: one use case is HTTP auth where
 | 
					
						
							|  |  |  |           // the username is a secret token which covers both identity and
 | 
					
						
							|  |  |  |           // authentication.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												Correctly identify more SSH private key problems as "formatting" or "passphrase" related
Summary:
Ref T13454. Fixes T13006. When a user provide us with an SSH private key and (possibly) a passphrase:
  # Try to verify that they're correct by extracting the public key.
  # If that fails, try to figure out why it didn't work.
Our success in step (2) will vary depending on what the problem is, and we may end up falling through to a very generic error, but the outcome should generally be better than the old approach.
Previously, we had a very unsophisticated test for the text "ENCRYPTED" in the key body and questionable handling of the results: for example, providing a passphrase when a key did not require one did not raise an error.
Test Plan:
Created and edited credentials with:
  - Valid, passphrase-free keys.
  - Valid, passphrased keys with the right passphrase.
  - Valid, passphrase-free keys with a passphrase ("surplus passphrase" error).
  - Valid, passphrased keys with no passphrase ("missing passphrase" error).
  - Valid, passphrased keys with an invalid passphrase ("invalid passphrase" error).
  - Invalid keys ("format" error).
The precision of these errors will vary depending on how helpful "ssh-keygen" is.
Maniphest Tasks: T13454, T13006
Differential Revision: https://secure.phabricator.com/D20905
											
										 
											2019-11-09 08:32:24 -08:00
										 |  |  |           if ($has_secret) { | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |             // If the credential was previously destroyed, restore it when it is
 | 
					
						
							|  |  |  |             // edited if a secret is provided.
 | 
					
						
							|  |  |  |             $xactions[] = id(new PassphraseCredentialTransaction()) | 
					
						
							|  |  |  |               ->setTransactionType($type_destroy) | 
					
						
							|  |  |  |               ->setNewValue(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             $new_secret = id(new PassphraseSecret()) | 
					
						
							|  |  |  |               ->setSecretData($v_decrypt) | 
					
						
							|  |  |  |               ->save(); | 
					
						
							| 
									
										
											  
											
												Correctly identify more SSH private key problems as "formatting" or "passphrase" related
Summary:
Ref T13454. Fixes T13006. When a user provide us with an SSH private key and (possibly) a passphrase:
  # Try to verify that they're correct by extracting the public key.
  # If that fails, try to figure out why it didn't work.
Our success in step (2) will vary depending on what the problem is, and we may end up falling through to a very generic error, but the outcome should generally be better than the old approach.
Previously, we had a very unsophisticated test for the text "ENCRYPTED" in the key body and questionable handling of the results: for example, providing a passphrase when a key did not require one did not raise an error.
Test Plan:
Created and edited credentials with:
  - Valid, passphrase-free keys.
  - Valid, passphrased keys with the right passphrase.
  - Valid, passphrase-free keys with a passphrase ("surplus passphrase" error).
  - Valid, passphrased keys with no passphrase ("missing passphrase" error).
  - Valid, passphrased keys with an invalid passphrase ("invalid passphrase" error).
  - Invalid keys ("format" error).
The precision of these errors will vary depending on how helpful "ssh-keygen" is.
Maniphest Tasks: T13454, T13006
Differential Revision: https://secure.phabricator.com/D20905
											
										 
											2019-11-09 08:32:24 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |             $xactions[] = id(new PassphraseCredentialTransaction()) | 
					
						
							|  |  |  |               ->setTransactionType($type_secret_id) | 
					
						
							|  |  |  |               ->setNewValue($new_secret->getID()); | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |           $xactions[] = id(new PassphraseCredentialTransaction()) | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |             ->setTransactionType($type_is_locked) | 
					
						
							|  |  |  |             ->setNewValue($v_is_locked); | 
					
						
							| 
									
										
										
										
											2013-11-21 12:35:36 -08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |         try { | 
					
						
							|  |  |  |           $editor = id(new PassphraseCredentialTransactionEditor()) | 
					
						
							|  |  |  |             ->setActor($viewer) | 
					
						
							|  |  |  |             ->setContinueOnNoEffect(true) | 
					
						
							|  |  |  |             ->setContentSourceFromRequest($request) | 
					
						
							|  |  |  |             ->applyTransactions($credential, $xactions); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           $credential->saveTransaction(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           if ($request->isAjax()) { | 
					
						
							|  |  |  |             return id(new AphrontAjaxResponse())->setContent( | 
					
						
							|  |  |  |               array( | 
					
						
							|  |  |  |                 'phid' => $credential->getPHID(), | 
					
						
							|  |  |  |                 'name' => 'K'.$credential->getID().' '.$credential->getName(), | 
					
						
							|  |  |  |               )); | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             return id(new AphrontRedirectResponse()) | 
					
						
							|  |  |  |               ->setURI('/K'.$credential->getID()); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } catch (PhabricatorApplicationTransactionValidationException $ex) { | 
					
						
							|  |  |  |           $credential->killTransaction(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           $validation_exception = $ex; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           $e_name = $ex->getShortMessage($type_name); | 
					
						
							|  |  |  |           $e_username = $ex->getShortMessage($type_username); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           $credential->setViewPolicy($v_view_policy); | 
					
						
							|  |  |  |           $credential->setEditPolicy($v_edit_policy); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $policies = id(new PhabricatorPolicyQuery()) | 
					
						
							|  |  |  |       ->setViewer($viewer) | 
					
						
							|  |  |  |       ->setObject($credential) | 
					
						
							|  |  |  |       ->execute(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $secret_control = $type->newSecretControl(); | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |     $credential_is_locked = $credential->getIsLocked(); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-13 07:31:04 -07:00
										 |  |  |     $form = id(new AphrontFormView()) | 
					
						
							|  |  |  |       ->setUser($viewer) | 
					
						
							| 
									
										
										
										
											2014-03-12 18:58:25 -07:00
										 |  |  |       ->addHiddenInput('isInitialized', true) | 
					
						
							| 
									
										
										
										
											2016-04-12 19:25:00 -07:00
										 |  |  |       ->addHiddenInput('type', $type_const) | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |       ->appendChild( | 
					
						
							|  |  |  |         id(new AphrontFormTextControl()) | 
					
						
							|  |  |  |           ->setName('name') | 
					
						
							|  |  |  |           ->setLabel(pht('Name')) | 
					
						
							|  |  |  |           ->setValue($v_name) | 
					
						
							|  |  |  |           ->setError($e_name)) | 
					
						
							|  |  |  |       ->appendChild( | 
					
						
							| 
									
										
										
										
											2017-05-08 15:04:28 -07:00
										 |  |  |         id(new PhabricatorRemarkupControl()) | 
					
						
							|  |  |  |           ->setUser($viewer) | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |           ->setName('description') | 
					
						
							|  |  |  |           ->setLabel(pht('Description')) | 
					
						
							|  |  |  |           ->setValue($v_desc)) | 
					
						
							|  |  |  |       ->appendChild( | 
					
						
							|  |  |  |         id(new AphrontFormDividerControl())) | 
					
						
							| 
									
										
										
										
											2015-06-22 11:28:54 -07:00
										 |  |  |       ->appendControl( | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |         id(new AphrontFormPolicyControl()) | 
					
						
							|  |  |  |           ->setName('viewPolicy') | 
					
						
							|  |  |  |           ->setPolicyObject($credential) | 
					
						
							| 
									
										
										
										
											2015-10-14 08:15:14 -07:00
										 |  |  |           ->setSpacePHID($v_space) | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |           ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) | 
					
						
							|  |  |  |           ->setPolicies($policies)) | 
					
						
							| 
									
										
										
										
											2015-06-22 11:28:54 -07:00
										 |  |  |       ->appendControl( | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |         id(new AphrontFormPolicyControl()) | 
					
						
							|  |  |  |           ->setName('editPolicy') | 
					
						
							|  |  |  |           ->setPolicyObject($credential) | 
					
						
							|  |  |  |           ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) | 
					
						
							|  |  |  |           ->setPolicies($policies)) | 
					
						
							|  |  |  |       ->appendChild( | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |         id(new AphrontFormDividerControl())); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ($credential_is_locked) { | 
					
						
							|  |  |  |       $form->appendRemarkupInstructions( | 
					
						
							|  |  |  |         pht('This credential is permanently locked and can not be edited.')); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-16 13:44:51 -07:00
										 |  |  |     if ($type->shouldRequireUsername()) { | 
					
						
							| 
									
										
										
										
											2016-05-18 12:31:20 -07:00
										 |  |  |       $form->appendChild( | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |         id(new AphrontFormTextControl()) | 
					
						
							|  |  |  |           ->setName('username') | 
					
						
							|  |  |  |           ->setLabel(pht('Login/Username')) | 
					
						
							|  |  |  |           ->setValue($v_username) | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |           ->setDisabled($credential_is_locked) | 
					
						
							| 
									
										
										
										
											2015-06-16 13:44:51 -07:00
										 |  |  |           ->setError($e_username)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2016-05-18 12:31:20 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     $form->appendChild( | 
					
						
							|  |  |  |       $secret_control | 
					
						
							|  |  |  |         ->setName('secret') | 
					
						
							|  |  |  |         ->setLabel($type->getSecretLabel()) | 
					
						
							|  |  |  |         ->setDisabled($credential_is_locked) | 
					
						
							| 
									
										
											  
											
												Correctly identify more SSH private key problems as "formatting" or "passphrase" related
Summary:
Ref T13454. Fixes T13006. When a user provide us with an SSH private key and (possibly) a passphrase:
  # Try to verify that they're correct by extracting the public key.
  # If that fails, try to figure out why it didn't work.
Our success in step (2) will vary depending on what the problem is, and we may end up falling through to a very generic error, but the outcome should generally be better than the old approach.
Previously, we had a very unsophisticated test for the text "ENCRYPTED" in the key body and questionable handling of the results: for example, providing a passphrase when a key did not require one did not raise an error.
Test Plan:
Created and edited credentials with:
  - Valid, passphrase-free keys.
  - Valid, passphrased keys with the right passphrase.
  - Valid, passphrase-free keys with a passphrase ("surplus passphrase" error).
  - Valid, passphrased keys with no passphrase ("missing passphrase" error).
  - Valid, passphrased keys with an invalid passphrase ("invalid passphrase" error).
  - Invalid keys ("format" error).
The precision of these errors will vary depending on how helpful "ssh-keygen" is.
Maniphest Tasks: T13454, T13006
Differential Revision: https://secure.phabricator.com/D20905
											
										 
											2019-11-09 08:32:24 -08:00
										 |  |  |         ->setValue($v_secret) | 
					
						
							|  |  |  |         ->setError($e_secret)); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |     if ($type->shouldShowPasswordField()) { | 
					
						
							|  |  |  |       $form->appendChild( | 
					
						
							|  |  |  |         id(new AphrontFormPasswordControl()) | 
					
						
							| 
									
										
										
										
											2014-08-13 10:06:48 -07:00
										 |  |  |           ->setDisableAutocomplete(true) | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |           ->setName('password') | 
					
						
							|  |  |  |           ->setLabel($type->getPasswordLabel()) | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |           ->setDisabled($credential_is_locked) | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |           ->setError($e_password)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |     if ($is_new) { | 
					
						
							|  |  |  |       $form->appendChild( | 
					
						
							|  |  |  |         id(new AphrontFormCheckboxControl()) | 
					
						
							|  |  |  |           ->addCheckbox( | 
					
						
							|  |  |  |             'lock', | 
					
						
							|  |  |  |             1, | 
					
						
							| 
									
										
										
										
											2014-05-14 09:25:58 -07:00
										 |  |  |             array( | 
					
						
							|  |  |  |               phutil_tag('strong', array(), pht('Lock Permanently:')), | 
					
						
							|  |  |  |               ' ', | 
					
						
							|  |  |  |               pht('Prevent the secret from being revealed or changed.'), | 
					
						
							|  |  |  |             ), | 
					
						
							| 
									
										
										
										
											2014-05-02 18:05:19 -07:00
										 |  |  |             $v_is_locked) | 
					
						
							|  |  |  |           ->setDisabled($credential_is_locked)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |     $crumbs = $this->buildApplicationCrumbs(); | 
					
						
							| 
									
										
										
										
											2016-04-04 13:37:44 -07:00
										 |  |  |     $crumbs->setBorder(true); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ($is_new) { | 
					
						
							| 
									
										
										
										
											2017-09-07 13:08:10 -07:00
										 |  |  |       $title = pht('New Credential: %s', $type->getCredentialTypeName()); | 
					
						
							| 
									
										
										
										
											2013-12-18 17:47:34 -08:00
										 |  |  |       $crumbs->addTextCrumb(pht('Create')); | 
					
						
							| 
									
										
										
										
											2014-03-19 19:25:31 -07:00
										 |  |  |       $cancel_uri = $this->getApplicationURI(); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2016-04-04 13:37:44 -07:00
										 |  |  |       $title = pht('Edit Credential: %s', $credential->getName()); | 
					
						
							| 
									
										
										
										
											2013-12-18 17:47:34 -08:00
										 |  |  |       $crumbs->addTextCrumb( | 
					
						
							|  |  |  |         'K'.$credential->getID(), | 
					
						
							|  |  |  |         '/K'.$credential->getID()); | 
					
						
							|  |  |  |       $crumbs->addTextCrumb(pht('Edit')); | 
					
						
							| 
									
										
										
										
											2014-03-19 19:25:31 -07:00
										 |  |  |       $cancel_uri = '/K'.$credential->getID(); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-21 12:35:36 -08:00
										 |  |  |     if ($request->isAjax()) { | 
					
						
							| 
									
										
										
										
											2014-03-13 07:31:04 -07:00
										 |  |  |       if ($errors) { | 
					
						
							| 
									
										
										
										
											2015-03-01 14:45:56 -08:00
										 |  |  |         $errors = id(new PHUIInfoView())->setErrors($errors); | 
					
						
							| 
									
										
										
										
											2014-03-13 07:31:04 -07:00
										 |  |  |       } | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-04 13:37:44 -07:00
										 |  |  |       return $this->newDialog() | 
					
						
							| 
									
										
										
										
											2013-11-21 12:35:36 -08:00
										 |  |  |         ->setWidth(AphrontDialogView::WIDTH_FORM) | 
					
						
							|  |  |  |         ->setTitle($title) | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |         ->appendChild($errors) | 
					
						
							| 
									
										
										
										
											2014-03-13 07:31:04 -07:00
										 |  |  |         ->appendChild($form->buildLayoutView()) | 
					
						
							| 
									
										
										
										
											2013-11-21 12:35:36 -08:00
										 |  |  |         ->addSubmitButton(pht('Create Credential')) | 
					
						
							| 
									
										
										
										
											2014-03-19 19:25:31 -07:00
										 |  |  |         ->addCancelButton($cancel_uri); | 
					
						
							| 
									
										
										
										
											2013-11-21 12:35:36 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     $form->appendChild( | 
					
						
							|  |  |  |       id(new AphrontFormSubmitControl()) | 
					
						
							|  |  |  |         ->setValue(pht('Save')) | 
					
						
							| 
									
										
										
										
											2014-03-19 19:25:31 -07:00
										 |  |  |         ->addCancelButton($cancel_uri)); | 
					
						
							| 
									
										
										
										
											2013-11-21 12:35:36 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |     $box = id(new PHUIObjectBoxView()) | 
					
						
							| 
									
										
										
										
											2017-09-07 13:08:10 -07:00
										 |  |  |       ->setHeaderText($title) | 
					
						
							| 
									
										
										
											
												Detect and prompt for passwords on SSH private keys, then strip them
Summary:
Fixes T4356. Currently, if users add a passworded private key to the Passphrase application, we never ask for the password and can not use it later. This makes several changes:
  - Prompt for the password.
  - Detect passworded private keys, and don't accept them until we can decrypt them.
  - Try to decrypt passworded private keys, and tell the user if the password is missing or incorrect.
  - Stop further creation of path-based private keys, which are really just for compatibility. We can't do anything reasonable about passwords with these, since users can change the files.
Test Plan: Created a private key with a password, was prompted to provide it, tried empty/bad passwords, provided the correct password and had the key decrypted for use.
Reviewers: btrahan
Reviewed By: btrahan
CC: aran
Maniphest Tasks: T4356
Differential Revision: https://secure.phabricator.com/D8102
											
										 
											2014-01-30 11:43:06 -08:00
										 |  |  |       ->setFormErrors($errors) | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |       ->setValidationException($validation_exception) | 
					
						
							| 
									
										
										
										
											2017-09-07 13:08:10 -07:00
										 |  |  |       ->setBackground(PHUIObjectBoxView::WHITE_CONFIG) | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |       ->setForm($form); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-04 13:37:44 -07:00
										 |  |  |     $view = id(new PHUITwoColumnView()) | 
					
						
							|  |  |  |       ->setFooter(array( | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |         $box, | 
					
						
							|  |  |  |       )); | 
					
						
							| 
									
										
										
										
											2016-04-04 13:37:44 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return $this->newPage() | 
					
						
							|  |  |  |       ->setTitle($title) | 
					
						
							|  |  |  |       ->setCrumbs($crumbs) | 
					
						
							|  |  |  |       ->appendChild($view); | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-26 05:46:26 -07:00
										 |  |  |   private function getCredentialType($type_const) { | 
					
						
							|  |  |  |     $type = PassphraseCredentialType::getTypeByConstant($type_const); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!$type) { | 
					
						
							|  |  |  |       throw new Exception( | 
					
						
							|  |  |  |         pht('Credential has invalid type "%s"!', $type_const)); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return $type; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-20 09:13:35 -08:00
										 |  |  | } |