mirror of
https://github.com/google/nomulus.git
synced 2025-05-02 21:17:50 +02:00
We'll continue to use injected clocks for the rest of our tests that use signed marks files, so that they don't all fail after the current validity period. The new test TmchTestDataExpirationTest will let us know when the files are expired, so we can update them. All updated test data files come from https://newgtlds.icann.org/en/about/trademark-clearinghouse/registries-registrars ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=202208196
257 lines
9.4 KiB
Java
257 lines
9.4 KiB
Java
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package google.registry.flows.domain;
|
|
|
|
import static com.google.common.collect.Iterables.concat;
|
|
import static google.registry.flows.EppXmlTransformer.unmarshal;
|
|
|
|
import com.google.common.collect.ImmutableList;
|
|
import google.registry.flows.EppException;
|
|
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
|
|
import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
|
|
import google.registry.flows.EppException.RequiredParameterMissingException;
|
|
import google.registry.model.mark.Mark;
|
|
import google.registry.model.mark.ProtectedMark;
|
|
import google.registry.model.mark.Trademark;
|
|
import google.registry.model.smd.AbstractSignedMark;
|
|
import google.registry.model.smd.EncodedSignedMark;
|
|
import google.registry.model.smd.SignedMark;
|
|
import google.registry.model.smd.SignedMarkRevocationList;
|
|
import google.registry.tmch.TmchXmlSignature;
|
|
import google.registry.tmch.TmchXmlSignature.CertificateSignatureException;
|
|
import java.io.IOException;
|
|
import java.security.GeneralSecurityException;
|
|
import java.security.SignatureException;
|
|
import java.security.cert.CertificateExpiredException;
|
|
import java.security.cert.CertificateNotYetValidException;
|
|
import java.security.cert.CertificateRevokedException;
|
|
import javax.inject.Inject;
|
|
import javax.xml.crypto.MarshalException;
|
|
import javax.xml.crypto.dsig.XMLSignatureException;
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
import org.joda.time.DateTime;
|
|
import org.xml.sax.SAXException;
|
|
|
|
/** TMCH utility functions for domain flows. */
|
|
public final class DomainFlowTmchUtils {
|
|
|
|
private final TmchXmlSignature tmchXmlSignature;
|
|
|
|
@Inject
|
|
public DomainFlowTmchUtils(TmchXmlSignature tmchXmlSignature) {
|
|
this.tmchXmlSignature = tmchXmlSignature;
|
|
}
|
|
|
|
public SignedMark verifySignedMarks(
|
|
ImmutableList<AbstractSignedMark> signedMarks, String domainLabel, DateTime now)
|
|
throws EppException {
|
|
if (signedMarks.size() > 1) {
|
|
throw new TooManySignedMarksException();
|
|
}
|
|
if (!(signedMarks.get(0) instanceof EncodedSignedMark)) {
|
|
throw new SignedMarksMustBeEncodedException();
|
|
}
|
|
SignedMark signedMark =
|
|
verifyEncodedSignedMark((EncodedSignedMark) signedMarks.get(0), now);
|
|
return verifySignedMarkValidForDomainLabel(signedMark, domainLabel);
|
|
}
|
|
|
|
public SignedMark verifySignedMarkValidForDomainLabel(SignedMark signedMark, String domainLabel)
|
|
throws NoMarksFoundMatchingDomainException {
|
|
if (!containsMatchingLabel(signedMark.getMark(), domainLabel)) {
|
|
throw new NoMarksFoundMatchingDomainException();
|
|
}
|
|
return signedMark;
|
|
}
|
|
|
|
public SignedMark verifyEncodedSignedMark(EncodedSignedMark encodedSignedMark, DateTime now)
|
|
throws EppException {
|
|
if (!encodedSignedMark.getEncoding().equals("base64")) {
|
|
throw new Base64RequiredForEncodedSignedMarksException();
|
|
}
|
|
byte[] signedMarkData;
|
|
try {
|
|
signedMarkData = encodedSignedMark.getBytes();
|
|
} catch (IllegalStateException e) {
|
|
throw new SignedMarkEncodingErrorException();
|
|
}
|
|
|
|
SignedMark signedMark;
|
|
try {
|
|
signedMark = unmarshal(SignedMark.class, signedMarkData);
|
|
} catch (EppException e) {
|
|
throw new SignedMarkParsingErrorException();
|
|
}
|
|
|
|
if (SignedMarkRevocationList.get().isSmdRevoked(signedMark.getId(), now)) {
|
|
throw new SignedMarkRevokedErrorException();
|
|
}
|
|
|
|
try {
|
|
tmchXmlSignature.verify(signedMarkData);
|
|
} catch (CertificateExpiredException e) {
|
|
throw new SignedMarkCertificateExpiredException();
|
|
} catch (CertificateNotYetValidException e) {
|
|
throw new SignedMarkCertificateNotYetValidException();
|
|
} catch (CertificateRevokedException e) {
|
|
throw new SignedMarkCertificateRevokedException();
|
|
} catch (CertificateSignatureException e) {
|
|
throw new SignedMarkCertificateSignatureException();
|
|
} catch (SignatureException | XMLSignatureException e) {
|
|
throw new SignedMarkSignatureException();
|
|
} catch (GeneralSecurityException e) {
|
|
throw new SignedMarkCertificateInvalidException();
|
|
} catch (IOException
|
|
| MarshalException
|
|
| SAXException
|
|
| ParserConfigurationException e) {
|
|
throw new SignedMarkParsingErrorException();
|
|
}
|
|
|
|
if (now.isBefore(signedMark.getCreationTime())) {
|
|
throw new FoundMarkNotYetValidException();
|
|
}
|
|
|
|
if (now.isAfter(signedMark.getExpirationTime())) {
|
|
throw new FoundMarkExpiredException();
|
|
}
|
|
|
|
return signedMark;
|
|
}
|
|
|
|
/** Returns true if the mark contains a valid claim that matches the label. */
|
|
private static boolean containsMatchingLabel(Mark mark, String label) {
|
|
for (Trademark trademark : mark.getTrademarks()) {
|
|
if (trademark.getLabels().contains(label)) {
|
|
return true;
|
|
}
|
|
}
|
|
for (ProtectedMark protectedMark
|
|
: concat(mark.getTreatyOrStatuteMarks(), mark.getCourtMarks())) {
|
|
if (protectedMark.getLabels().contains(label)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/** Encoded signed marks must use base64 encoding. */
|
|
static class Base64RequiredForEncodedSignedMarksException
|
|
extends ParameterValuePolicyErrorException {
|
|
public Base64RequiredForEncodedSignedMarksException() {
|
|
super("Encoded signed marks must use base64 encoding");
|
|
}
|
|
}
|
|
|
|
/** The provided mark does not match the desired domain label. */
|
|
static class NoMarksFoundMatchingDomainException extends RequiredParameterMissingException {
|
|
public NoMarksFoundMatchingDomainException() {
|
|
super("The provided mark does not match the desired domain label");
|
|
}
|
|
}
|
|
|
|
/** The provided mark is not yet valid. */
|
|
static class FoundMarkNotYetValidException extends ParameterValuePolicyErrorException {
|
|
public FoundMarkNotYetValidException() {
|
|
super("The provided mark is not yet valid");
|
|
}
|
|
}
|
|
|
|
/** The provided mark has expired. */
|
|
static class FoundMarkExpiredException extends ParameterValuePolicyErrorException {
|
|
public FoundMarkExpiredException() {
|
|
super("The provided mark has expired");
|
|
}
|
|
}
|
|
|
|
/** Certificate used in signed mark signature was revoked by ICANN. */
|
|
static class SignedMarkCertificateRevokedException extends ParameterValuePolicyErrorException {
|
|
public SignedMarkCertificateRevokedException() {
|
|
super("Signed mark certificate was revoked");
|
|
}
|
|
}
|
|
|
|
/** Certificate used in signed mark signature has expired. */
|
|
static class SignedMarkCertificateNotYetValidException
|
|
extends ParameterValuePolicyErrorException {
|
|
public SignedMarkCertificateNotYetValidException() {
|
|
super("Signed mark certificate not yet valid");
|
|
}
|
|
}
|
|
|
|
/** Certificate used in signed mark signature has expired. */
|
|
static class SignedMarkCertificateExpiredException extends ParameterValuePolicyErrorException {
|
|
public SignedMarkCertificateExpiredException() {
|
|
super("Signed mark certificate has expired");
|
|
}
|
|
}
|
|
|
|
/** Certificate parsing error, or possibly a bad provider or algorithm. */
|
|
static class SignedMarkCertificateInvalidException extends ParameterValuePolicyErrorException {
|
|
public SignedMarkCertificateInvalidException() {
|
|
super("Signed mark certificate is invalid");
|
|
}
|
|
}
|
|
|
|
/** Invalid signature on a signed mark. */
|
|
static class SignedMarkCertificateSignatureException extends ParameterValuePolicyErrorException {
|
|
public SignedMarkCertificateSignatureException() {
|
|
super("Signed mark certificate not signed by ICANN");
|
|
}
|
|
}
|
|
|
|
/** Invalid signature on a signed mark. */
|
|
static class SignedMarkSignatureException extends ParameterValuePolicyErrorException {
|
|
public SignedMarkSignatureException() {
|
|
super("Signed mark signature is invalid");
|
|
}
|
|
}
|
|
|
|
/** Signed marks must be encoded. */
|
|
static class SignedMarksMustBeEncodedException extends ParameterValuePolicyErrorException {
|
|
public SignedMarksMustBeEncodedException() {
|
|
super("Signed marks must be encoded");
|
|
}
|
|
}
|
|
|
|
/** Only one signed mark is allowed per application. */
|
|
static class TooManySignedMarksException extends ParameterValuePolicyErrorException {
|
|
public TooManySignedMarksException() {
|
|
super("Only one signed mark is allowed per application");
|
|
}
|
|
}
|
|
|
|
/** Signed mark data is revoked. */
|
|
static class SignedMarkRevokedErrorException extends ParameterValuePolicyErrorException {
|
|
public SignedMarkRevokedErrorException() {
|
|
super("SMD has been revoked");
|
|
}
|
|
}
|
|
|
|
/** Error while parsing encoded signed mark data. */
|
|
static class SignedMarkParsingErrorException extends ParameterValueSyntaxErrorException {
|
|
public SignedMarkParsingErrorException() {
|
|
super("Error while parsing encoded signed mark data");
|
|
}
|
|
}
|
|
|
|
/** Signed mark data is improperly encoded. */
|
|
static class SignedMarkEncodingErrorException extends ParameterValueSyntaxErrorException {
|
|
public SignedMarkEncodingErrorException() {
|
|
super("Signed mark data is improperly encoded");
|
|
}
|
|
}
|
|
|
|
}
|