PushCertificate.java
- /*
- * Copyright (C) 2015, Google Inc. and others
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Distribution License v. 1.0 which is available at
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- package org.eclipse.jgit.transport;
- import static org.eclipse.jgit.transport.PushCertificateParser.NONCE;
- import static org.eclipse.jgit.transport.PushCertificateParser.PUSHEE;
- import static org.eclipse.jgit.transport.PushCertificateParser.PUSHER;
- import static org.eclipse.jgit.transport.PushCertificateParser.VERSION;
- import java.text.MessageFormat;
- import java.util.List;
- import java.util.Objects;
- import org.eclipse.jgit.internal.JGitText;
- /**
- * The required information to verify the push.
- * <p>
- * A valid certificate will not return null from any getter methods; callers may
- * assume that any null value indicates a missing or invalid certificate.
- *
- * @since 4.0
- */
- public class PushCertificate {
- /** Verification result of the nonce returned during push. */
- public enum NonceStatus {
- /** Nonce was not expected, yet client sent one anyway. */
- UNSOLICITED,
- /** Nonce is invalid and did not match server's expectations. */
- BAD,
- /** Nonce is required, but was not sent by client. */
- MISSING,
- /**
- * Received nonce matches sent nonce, or is valid within the accepted slop
- * window.
- */
- OK,
- /** Received nonce is valid, but outside the accepted slop window. */
- SLOP
- }
- private final String version;
- private final PushCertificateIdent pusher;
- private final String pushee;
- private final String nonce;
- private final NonceStatus nonceStatus;
- private final List<ReceiveCommand> commands;
- private final String signature;
- PushCertificate(String version, PushCertificateIdent pusher, String pushee,
- String nonce, NonceStatus nonceStatus, List<ReceiveCommand> commands,
- String signature) {
- if (version == null || version.isEmpty()) {
- throw new IllegalArgumentException(MessageFormat.format(
- JGitText.get().pushCertificateInvalidField, VERSION));
- }
- if (pusher == null) {
- throw new IllegalArgumentException(MessageFormat.format(
- JGitText.get().pushCertificateInvalidField, PUSHER));
- }
- if (nonce == null || nonce.isEmpty()) {
- throw new IllegalArgumentException(MessageFormat.format(
- JGitText.get().pushCertificateInvalidField, NONCE));
- }
- if (nonceStatus == null) {
- throw new IllegalArgumentException(MessageFormat.format(
- JGitText.get().pushCertificateInvalidField,
- "nonce status")); //$NON-NLS-1$
- }
- if (commands == null || commands.isEmpty()) {
- throw new IllegalArgumentException(MessageFormat.format(
- JGitText.get().pushCertificateInvalidField,
- "command")); //$NON-NLS-1$
- }
- if (signature == null || signature.isEmpty()) {
- throw new IllegalArgumentException(
- JGitText.get().pushCertificateInvalidSignature);
- }
- if (!signature.startsWith(PushCertificateParser.BEGIN_SIGNATURE)
- || !signature.endsWith(PushCertificateParser.END_SIGNATURE + '\n')) {
- throw new IllegalArgumentException(
- JGitText.get().pushCertificateInvalidSignature);
- }
- this.version = version;
- this.pusher = pusher;
- this.pushee = pushee;
- this.nonce = nonce;
- this.nonceStatus = nonceStatus;
- this.commands = commands;
- this.signature = signature;
- }
- /**
- * Get the certificate version string.
- *
- * @return the certificate version string.
- * @since 4.1
- */
- public String getVersion() {
- return version;
- }
- /**
- * Get the raw line that signed the cert, as a string.
- *
- * @return the raw line that signed the cert, as a string.
- * @since 4.0
- */
- public String getPusher() {
- return pusher.getRaw();
- }
- /**
- * Get identity of the pusher who signed the cert.
- *
- * @return identity of the pusher who signed the cert.
- * @since 4.1
- */
- public PushCertificateIdent getPusherIdent() {
- return pusher;
- }
- /**
- * Get URL of the repository the push was originally sent to.
- *
- * @return URL of the repository the push was originally sent to.
- * @since 4.0
- */
- public String getPushee() {
- return pushee;
- }
- /**
- * Get the raw nonce value that was presented by the pusher.
- *
- * @return the raw nonce value that was presented by the pusher.
- * @since 4.1
- */
- public String getNonce() {
- return nonce;
- }
- /**
- * Get verification status of the nonce embedded in the certificate.
- *
- * @return verification status of the nonce embedded in the certificate.
- * @since 4.0
- */
- public NonceStatus getNonceStatus() {
- return nonceStatus;
- }
- /**
- * Get the list of commands as one string to be feed into the signature
- * verifier.
- *
- * @return the list of commands as one string to be feed into the signature
- * verifier.
- * @since 4.1
- */
- public List<ReceiveCommand> getCommands() {
- return commands;
- }
- /**
- * Get the raw signature
- *
- * @return the raw signature, consisting of the lines received between the
- * lines {@code "----BEGIN GPG SIGNATURE-----\n"} and
- * {@code "----END GPG SIGNATURE-----\n}", inclusive.
- * @since 4.0
- */
- public String getSignature() {
- return signature;
- }
- /**
- * Get text payload of the certificate for the signature verifier.
- *
- * @return text payload of the certificate for the signature verifier.
- * @since 4.1
- */
- public String toText() {
- return toStringBuilder().toString();
- }
- /**
- * Get original text payload plus signature
- *
- * @return original text payload plus signature; the final output will be
- * valid as input to
- * {@link org.eclipse.jgit.transport.PushCertificateParser#fromString(String)}.
- * @since 4.1
- */
- public String toTextWithSignature() {
- return toStringBuilder().append(signature).toString();
- }
- private StringBuilder toStringBuilder() {
- StringBuilder sb = new StringBuilder()
- .append(VERSION).append(' ').append(version).append('\n')
- .append(PUSHER).append(' ').append(getPusher())
- .append('\n');
- if (pushee != null) {
- sb.append(PUSHEE).append(' ').append(pushee).append('\n');
- }
- sb.append(NONCE).append(' ').append(nonce).append('\n')
- .append('\n');
- for (ReceiveCommand cmd : commands) {
- sb.append(cmd.getOldId().name())
- .append(' ').append(cmd.getNewId().name())
- .append(' ').append(cmd.getRefName()).append('\n');
- }
- return sb;
- }
- /** {@inheritDoc} */
- @Override
- public int hashCode() {
- return signature.hashCode();
- }
- /** {@inheritDoc} */
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof PushCertificate)) {
- return false;
- }
- PushCertificate p = (PushCertificate) o;
- return version.equals(p.version)
- && pusher.equals(p.pusher)
- && Objects.equals(pushee, p.pushee)
- && nonceStatus == p.nonceStatus
- && signature.equals(p.signature)
- && commandsEqual(this, p);
- }
- private static boolean commandsEqual(PushCertificate c1, PushCertificate c2) {
- if (c1.commands.size() != c2.commands.size()) {
- return false;
- }
- for (int i = 0; i < c1.commands.size(); i++) {
- ReceiveCommand cmd1 = c1.commands.get(i);
- ReceiveCommand cmd2 = c2.commands.get(i);
- if (!cmd1.getOldId().equals(cmd2.getOldId())
- || !cmd1.getNewId().equals(cmd2.getNewId())
- || !cmd1.getRefName().equals(cmd2.getRefName())) {
- return false;
- }
- }
- return true;
- }
- /** {@inheritDoc} */
- @Override
- public String toString() {
- return getClass().getSimpleName() + '['
- + toTextWithSignature() + ']';
- }
- }