View Javadoc
1   /*-
2    * Copyright (C) 2019, Salesforce. and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * https://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.lib.internal;
11  
12  import java.net.URISyntaxException;
13  import java.nio.file.Path;
14  import java.text.MessageFormat;
15  
16  import org.bouncycastle.openpgp.PGPException;
17  import org.bouncycastle.util.encoders.Hex;
18  import org.eclipse.jgit.api.errors.CanceledException;
19  import org.eclipse.jgit.errors.UnsupportedCredentialItem;
20  import org.eclipse.jgit.internal.JGitText;
21  import org.eclipse.jgit.transport.CredentialItem.CharArrayType;
22  import org.eclipse.jgit.transport.CredentialItem.InformationalMessage;
23  import org.eclipse.jgit.transport.CredentialsProvider;
24  import org.eclipse.jgit.transport.URIish;
25  
26  /**
27   * Prompts for a passphrase and caches it until {@link #clear() cleared}.
28   * <p>
29   * Implements {@link AutoCloseable} so it can be used within a
30   * try-with-resources block.
31   * </p>
32   */
33  class BouncyCastleGpgKeyPassphrasePrompt implements AutoCloseable {
34  
35  	private CharArrayType passphrase;
36  
37  	private CredentialsProvider credentialsProvider;
38  
39  	public BouncyCastleGpgKeyPassphrasePrompt(
40  			CredentialsProvider credentialsProvider) {
41  		this.credentialsProvider = credentialsProvider;
42  	}
43  
44  	/**
45  	 * Clears any cached passphrase
46  	 */
47  	public void clear() {
48  		if (passphrase != null) {
49  			passphrase.clear();
50  			passphrase = null;
51  		}
52  	}
53  
54  	@Override
55  	public void close() {
56  		clear();
57  	}
58  
59  	private URIish createURI(Path keyLocation) throws URISyntaxException {
60  		return new URIish(keyLocation.toUri().toString());
61  	}
62  
63  	/**
64  	 * Prompts use for a passphrase unless one was cached from a previous
65  	 * prompt.
66  	 *
67  	 * @param keyFingerprint
68  	 *            the fingerprint to show to the user during prompting
69  	 * @param keyLocation
70  	 *            the location the key was loaded from
71  	 * @return the passphrase (maybe <code>null</code>)
72  	 * @throws PGPException
73  	 * @throws CanceledException
74  	 *             in case passphrase was not entered by user
75  	 * @throws URISyntaxException
76  	 * @throws UnsupportedCredentialItem
77  	 */
78  	public char[] getPassphrase(byte[] keyFingerprint, Path keyLocation)
79  			throws PGPException, CanceledException, UnsupportedCredentialItem,
80  			URISyntaxException {
81  		if (passphrase == null) {
82  			passphrase = new CharArrayType(JGitText.get().credentialPassphrase,
83  					true);
84  		}
85  
86  		if (credentialsProvider == null) {
87  			throw new PGPException(JGitText.get().gpgNoCredentialsProvider);
88  		}
89  
90  		if (passphrase.getValue() == null
91  				&& !credentialsProvider.get(createURI(keyLocation),
92  						new InformationalMessage(
93  								MessageFormat.format(JGitText.get().gpgKeyInfo,
94  										Hex.toHexString(keyFingerprint))),
95  						passphrase)) {
96  			throw new CanceledException(JGitText.get().gpgSigningCancelled);
97  		}
98  		return passphrase.getValue();
99  	}
100 
101 }