diff --git a/java/google/registry/flows/domain/DomainApplicationCreateFlow.java b/java/google/registry/flows/domain/DomainApplicationCreateFlow.java index 80617ae98..0a28790f5 100644 --- a/java/google/registry/flows/domain/DomainApplicationCreateFlow.java +++ b/java/google/registry/flows/domain/DomainApplicationCreateFlow.java @@ -36,7 +36,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyNoCodeMarks; import static google.registry.flows.domain.DomainFlowUtils.verifyNotReserved; import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked; import static google.registry.flows.domain.DomainFlowUtils.verifyRegistryStateAllowsLaunchFlows; -import static google.registry.flows.domain.DomainFlowUtils.verifySignedMarks; import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears; import static google.registry.model.EppResourceUtils.createDomainRepoId; import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName; @@ -109,7 +108,7 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.BadDomainNameCharacterException} * @error {@link DomainFlowUtils.BadDomainNamePartsCountException} * @error {@link DomainFlowUtils.BadPeriodUnitException} - * @error {@link DomainFlowUtils.Base64RequiredForEncodedSignedMarksException} + * @error {@link DomainFlowTmchUtils.Base64RequiredForEncodedSignedMarksException} * @error {@link DomainFlowUtils.ClaimsPeriodEndedException} * @error {@link DomainFlowUtils.CurrencyUnitMismatchException} * @error {@link DomainFlowUtils.CurrencyValueScaleException} @@ -135,24 +134,24 @@ import org.joda.time.DateTime; * @error {@link DomainFlowUtils.MissingContactTypeException} * @error {@link DomainFlowUtils.NameserversNotAllowedException} * @error {@link DomainFlowUtils.NameserversNotSpecifiedException} - * @error {@link DomainFlowUtils.NoMarksFoundMatchingDomainException} + * @error {@link DomainFlowTmchUtils.NoMarksFoundMatchingDomainException} * @error {@link DomainFlowUtils.NotAuthorizedForTldException} * @error {@link DomainFlowUtils.PremiumNameBlockedException} * @error {@link DomainFlowUtils.RegistrantNotAllowedException} - * @error {@link DomainFlowUtils.SignedMarksMustBeEncodedException} - * @error {@link DomainFlowUtils.SignedMarkCertificateExpiredException} - * @error {@link DomainFlowUtils.SignedMarkCertificateInvalidException} - * @error {@link DomainFlowUtils.SignedMarkCertificateNotYetValidException} - * @error {@link DomainFlowUtils.SignedMarkCertificateRevokedException} - * @error {@link DomainFlowUtils.SignedMarkCertificateSignatureException} - * @error {@link DomainFlowUtils.SignedMarkEncodingErrorException} - * @error {@link DomainFlowUtils.SignedMarkParsingErrorException} - * @error {@link DomainFlowUtils.SignedMarkRevokedErrorException} - * @error {@link DomainFlowUtils.SignedMarkSignatureException} + * @error {@link DomainFlowTmchUtils.SignedMarksMustBeEncodedException} + * @error {@link DomainFlowTmchUtils.SignedMarkCertificateExpiredException} + * @error {@link DomainFlowTmchUtils.SignedMarkCertificateInvalidException} + * @error {@link DomainFlowTmchUtils.SignedMarkCertificateNotYetValidException} + * @error {@link DomainFlowTmchUtils.SignedMarkCertificateRevokedException} + * @error {@link DomainFlowTmchUtils.SignedMarkCertificateSignatureException} + * @error {@link DomainFlowTmchUtils.SignedMarkEncodingErrorException} + * @error {@link DomainFlowTmchUtils.SignedMarkParsingErrorException} + * @error {@link DomainFlowTmchUtils.SignedMarkRevokedErrorException} + * @error {@link DomainFlowTmchUtils.SignedMarkSignatureException} * @error {@link DomainFlowUtils.TldDoesNotExistException} * @error {@link DomainFlowUtils.TooManyDsRecordsException} * @error {@link DomainFlowUtils.TooManyNameserversException} - * @error {@link DomainFlowUtils.TooManySignedMarksException} + * @error {@link DomainFlowTmchUtils.TooManySignedMarksException} * @error {@link DomainFlowUtils.TrailingDashException} * @error {@link DomainFlowUtils.UnexpectedClaimsNoticeException} * @error {@link DomainFlowUtils.UnsupportedFeeAttributeException} @@ -171,6 +170,7 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow { @Inject Trid trid; @Inject EppResponse.Builder responseBuilder; @Inject DomainApplicationCreateFlowCustomLogic customLogic; + @Inject DomainFlowTmchUtils tmchUtils; @Inject DomainPricingLogic pricingLogic; @Inject DomainApplicationCreateFlow() {} @@ -331,7 +331,7 @@ public final class DomainApplicationCreateFlow implements TransactionalFlow { validateLaunchCreateNotice(launchCreate.getNotice(), domainLabel, isSuperuser, now); // If a signed mark was provided, then it must match the desired domain label. if (!launchCreate.getSignedMarks().isEmpty()) { - verifySignedMarks(launchCreate.getSignedMarks(), domainLabel, now); + tmchUtils.verifySignedMarks(launchCreate.getSignedMarks(), domainLabel, now); } } diff --git a/java/google/registry/flows/domain/DomainCreateFlow.java b/java/google/registry/flows/domain/DomainCreateFlow.java index cf0dac15f..6d6d20ffb 100644 --- a/java/google/registry/flows/domain/DomainCreateFlow.java +++ b/java/google/registry/flows/domain/DomainCreateFlow.java @@ -34,7 +34,6 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyLaunchPhaseMatc import static google.registry.flows.domain.DomainFlowUtils.verifyNoCodeMarks; import static google.registry.flows.domain.DomainFlowUtils.verifyNotReserved; import static google.registry.flows.domain.DomainFlowUtils.verifyPremiumNameIsNotBlocked; -import static google.registry.flows.domain.DomainFlowUtils.verifySignedMarks; import static google.registry.flows.domain.DomainFlowUtils.verifyUnitIsYears; import static google.registry.model.EppResourceUtils.createDomainRepoId; import static google.registry.model.index.DomainApplicationIndex.loadActiveApplicationsByDomainName; @@ -164,6 +163,7 @@ public class DomainCreateFlow implements TransactionalFlow { @Inject HistoryEntry.Builder historyBuilder; @Inject EppResponse.Builder responseBuilder; @Inject DomainCreateFlowCustomLogic customLogic; + @Inject DomainFlowTmchUtils tmchUtils; @Inject DomainPricingLogic pricingLogic; @Inject DnsQueue dnsQueue; @Inject DomainCreateFlow() {} @@ -266,7 +266,7 @@ public class DomainCreateFlow implements TransactionalFlow { .setLaunchNotice(hasClaimsNotice ? launchCreate.getNotice() : null) .setSmdId(hasSignedMarks // If a signed mark was provided, then it must match the desired domain label. - ? verifySignedMarks(launchCreate.getSignedMarks(), domainLabel, now).getId() + ? tmchUtils.verifySignedMarks(launchCreate.getSignedMarks(), domainLabel, now).getId() : null) .setDsData(secDnsCreate == null ? null : secDnsCreate.getDsData()) .setRegistrant(command.getRegistrant()) diff --git a/java/google/registry/flows/domain/DomainFlowTmchUtils.java b/java/google/registry/flows/domain/DomainFlowTmchUtils.java new file mode 100644 index 000000000..0aa43fc36 --- /dev/null +++ b/java/google/registry/flows/domain/DomainFlowTmchUtils.java @@ -0,0 +1,226 @@ +// Copyright 2016 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 static google.registry.util.DateTimeUtils.isAtOrAfter; + +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 { + + @Inject public DomainFlowTmchUtils() {} + + public SignedMark verifySignedMarks( + ImmutableList signedMarks, String domainLabel, DateTime now) + throws EppException { + if (signedMarks.size() > 1) { + throw new TooManySignedMarksException(); + } + if (!(signedMarks.get(0) instanceof EncodedSignedMark)) { + throw new SignedMarksMustBeEncodedException(); + } + return verifyEncodedSignedMark((EncodedSignedMark) signedMarks.get(0), domainLabel, now); + } + + public SignedMark verifyEncodedSignedMark( + EncodedSignedMark encodedSignedMark, String domainLabel, 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 (!(isAtOrAfter(now, signedMark.getCreationTime()) + && now.isBefore(signedMark.getExpirationTime()) + && containsMatchingLabel(signedMark.getMark(), domainLabel))) { + throw new NoMarksFoundMatchingDomainException(); + } + 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"); + } + } + + /** 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"); + } + } + +} diff --git a/java/google/registry/flows/domain/DomainFlowUtils.java b/java/google/registry/flows/domain/DomainFlowUtils.java index cc3bd17ee..c01866eaa 100644 --- a/java/google/registry/flows/domain/DomainFlowUtils.java +++ b/java/google/registry/flows/domain/DomainFlowUtils.java @@ -18,10 +18,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Predicates.equalTo; import static com.google.common.collect.Iterables.any; -import static com.google.common.collect.Iterables.concat; import static com.google.common.collect.Sets.difference; import static com.google.common.collect.Sets.union; -import static google.registry.flows.EppXmlTransformer.unmarshal; import static google.registry.flows.domain.DomainPricingLogic.getMatchingLrpToken; import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.ofy.ObjectifyService.ofy; @@ -95,9 +93,6 @@ import google.registry.model.domain.secdns.SecDnsUpdateExtension.Remove; import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppoutput.EppResponse.ResponseExtension; import google.registry.model.host.HostResource; -import google.registry.model.mark.Mark; -import google.registry.model.mark.ProtectedMark; -import google.registry.model.mark.Trademark; import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse; import google.registry.model.poll.PollMessage; import google.registry.model.registrar.Registrar; @@ -105,35 +100,19 @@ import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.label.ReservationType; import google.registry.model.reporting.HistoryEntry; -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.model.tmch.ClaimsListShard; import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferResponse.DomainTransferResponse; -import google.registry.tmch.TmchXmlSignature; -import google.registry.tmch.TmchXmlSignature.CertificateSignatureException; import google.registry.util.Idn; -import java.io.IOException; import java.math.BigDecimal; -import java.security.GeneralSecurityException; -import java.security.SignatureException; -import java.security.cert.CertificateExpiredException; -import java.security.cert.CertificateNotYetValidException; -import java.security.cert.CertificateRevokedException; import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; import javax.annotation.Nullable; -import javax.xml.crypto.MarshalException; -import javax.xml.crypto.dsig.XMLSignatureException; -import javax.xml.parsers.ParserConfigurationException; import org.joda.money.CurrencyUnit; import org.joda.money.Money; import org.joda.time.DateTime; -import org.xml.sax.SAXException; /** Static utility functions for domain flows. */ public class DomainFlowUtils { @@ -496,86 +475,6 @@ public class DomainFlowUtils { .build()); } - static SignedMark verifySignedMarks( - ImmutableList signedMarks, String domainLabel, DateTime now) - throws EppException { - if (signedMarks.size() > 1) { - throw new TooManySignedMarksException(); - } - if (!(signedMarks.get(0) instanceof EncodedSignedMark)) { - throw new SignedMarksMustBeEncodedException(); - } - return verifyEncodedSignedMark((EncodedSignedMark) signedMarks.get(0), domainLabel, now); - } - - public static SignedMark verifyEncodedSignedMark( - EncodedSignedMark encodedSignedMark, String domainLabel, 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 (!(isAtOrAfter(now, signedMark.getCreationTime()) - && now.isBefore(signedMark.getExpirationTime()) - && containsMatchingLabel(signedMark.getMark(), domainLabel))) { - throw new NoMarksFoundMatchingDomainException(); - } - return signedMark; - } - - /** Returns true if the mark contains a valid claim that matches the label. */ - 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; - } - /** * Validates a {@link FeeQueryCommandExtensionItem} and sets the appropriate fields on a {@link * FeeQueryResponseExtensionItem} builder. @@ -997,14 +896,6 @@ public class DomainFlowUtils { .build(); } - /** Encoded signed marks must use base64 encoding. */ - static class Base64RequiredForEncodedSignedMarksException - extends ParameterValuePolicyErrorException { - public Base64RequiredForEncodedSignedMarksException() { - super("Encoded signed marks must use base64 encoding"); - } - } - /** Resource linked to this domain does not exist. */ static class LinkedResourcesDoNotExistException extends ObjectDoesNotExistException { public LinkedResourcesDoNotExistException(Class type, ImmutableSet resourceIds) { @@ -1162,91 +1053,6 @@ public class DomainFlowUtils { } } - /** Signed mark data is improperly encoded. */ - static class SignedMarkEncodingErrorException extends ParameterValueSyntaxErrorException { - public SignedMarkEncodingErrorException() { - super("Signed mark data is improperly encoded"); - } - } - - /** Error while parsing encoded signed mark data. */ - static class SignedMarkParsingErrorException extends ParameterValueSyntaxErrorException { - public SignedMarkParsingErrorException() { - super("Error while parsing encoded signed mark data"); - } - } - - /** Invalid signature on a signed mark. */ - static class SignedMarkSignatureException extends ParameterValuePolicyErrorException { - public SignedMarkSignatureException() { - super("Signed mark signature is invalid"); - } - } - - /** Invalid signature on a signed mark. */ - static class SignedMarkCertificateSignatureException extends ParameterValuePolicyErrorException { - public SignedMarkCertificateSignatureException() { - super("Signed mark certificate not signed by ICANN"); - } - } - - /** 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 SignedMarkCertificateExpiredException extends ParameterValuePolicyErrorException { - public SignedMarkCertificateExpiredException() { - super("Signed mark certificate has expired"); - } - } - - /** Certificate used in signed mark signature has expired. */ - static class SignedMarkCertificateNotYetValidException - extends ParameterValuePolicyErrorException { - public SignedMarkCertificateNotYetValidException() { - super("Signed mark certificate not yet valid"); - } - } - - /** Certificate parsing error, or possibly a bad provider or algorithm. */ - static class SignedMarkCertificateInvalidException extends ParameterValuePolicyErrorException { - public SignedMarkCertificateInvalidException() { - super("Signed mark certificate is invalid"); - } - } - - /** Signed mark data is revoked. */ - static class SignedMarkRevokedErrorException extends ParameterValuePolicyErrorException { - public SignedMarkRevokedErrorException() { - super("SMD has been revoked"); - } - } - - /** 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 marks must be encoded. */ - static class SignedMarksMustBeEncodedException extends ParameterValuePolicyErrorException { - public SignedMarksMustBeEncodedException() { - super("Signed marks must be encoded"); - } - } - - /** 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"); - } - } - /** Unknown fee command name. */ static class UnknownFeeCommandException extends ParameterValuePolicyErrorException { UnknownFeeCommandException(String commandName) { diff --git a/java/google/registry/tools/UpdateSmdCommand.java b/java/google/registry/tools/UpdateSmdCommand.java index 719ba3654..e44839794 100644 --- a/java/google/registry/tools/UpdateSmdCommand.java +++ b/java/google/registry/tools/UpdateSmdCommand.java @@ -15,7 +15,6 @@ package google.registry.tools; import static com.google.common.base.Preconditions.checkArgument; -import static google.registry.flows.domain.DomainFlowUtils.verifyEncodedSignedMark; import static google.registry.model.EppResourceUtils.loadDomainApplication; import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.tmch.TmchData.readEncodedSignedMark; @@ -27,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.net.InternetDomainName; import com.googlecode.objectify.VoidWork; import google.registry.flows.EppException; +import google.registry.flows.domain.DomainFlowTmchUtils; import google.registry.model.domain.DomainApplication; import google.registry.model.reporting.HistoryEntry; import google.registry.model.smd.EncodedSignedMark; @@ -34,12 +34,16 @@ import google.registry.tools.Command.RemoteApiCommand; import google.registry.tools.params.PathParameter; import java.nio.file.Files; import java.nio.file.Path; +import javax.inject.Inject; import org.joda.time.DateTime; /** Command to update the SMD on a domain application. */ @Parameters(separators = " =", commandDescription = "Update the SMD on an application.") final class UpdateSmdCommand implements RemoteApiCommand { + @Inject DomainFlowTmchUtils tmchUtils; + @Inject UpdateSmdCommand() {} + @Parameter( names = "--id", description = "Application ID to update.", @@ -74,7 +78,7 @@ final class UpdateSmdCommand implements RemoteApiCommand { }}); } - private static void updateSmd( + private void updateSmd( String applicationId, EncodedSignedMark encodedSignedMark, String reason) throws EppException { ofy().assertInTransaction(); @@ -91,7 +95,7 @@ final class UpdateSmdCommand implements RemoteApiCommand { // Verify the new SMD. String domainLabel = InternetDomainName.from(domainApplication.getFullyQualifiedDomainName()) .parts().get(0); - verifyEncodedSignedMark(encodedSignedMark, domainLabel, now); + tmchUtils.verifyEncodedSignedMark(encodedSignedMark, domainLabel, now); DomainApplication updatedApplication = domainApplication.asBuilder() .setEncodedSignedMarks(ImmutableList.of(encodedSignedMark)) diff --git a/javatests/google/registry/flows/EppTestComponent.java b/javatests/google/registry/flows/EppTestComponent.java index f56ea4979..3a0f0c4bd 100644 --- a/javatests/google/registry/flows/EppTestComponent.java +++ b/javatests/google/registry/flows/EppTestComponent.java @@ -25,6 +25,7 @@ import google.registry.config.ConfigModule; import google.registry.dns.DnsQueue; import google.registry.flows.custom.CustomLogicFactory; import google.registry.flows.custom.TestCustomLogicFactory; +import google.registry.flows.domain.DomainFlowTmchUtils; import google.registry.monitoring.whitebox.BigQueryMetricsEnqueuer; import google.registry.monitoring.whitebox.EppMetric; import google.registry.request.RequestScope; @@ -49,15 +50,17 @@ interface EppTestComponent { @Module static class FakesAndMocksModule { - final FakeClock clock; - final Sleeper sleeper; - final DnsQueue dnsQueue; final BigQueryMetricsEnqueuer metricsEnqueuer; + final DnsQueue dnsQueue; + final DomainFlowTmchUtils domainFlowTmchUtils; final EppMetric.Builder metricBuilder; + final FakeClock clock; final ModulesService modulesService; + final Sleeper sleeper; FakesAndMocksModule(FakeClock clock) { this.clock = clock; + this.domainFlowTmchUtils = new DomainFlowTmchUtils(); this.sleeper = new FakeSleeper(clock); this.dnsQueue = DnsQueue.create(); this.metricBuilder = EppMetric.builderForRequest("request-id-1", clock); @@ -65,14 +68,19 @@ interface EppTestComponent { this.metricsEnqueuer = mock(BigQueryMetricsEnqueuer.class); } + @Provides + BigQueryMetricsEnqueuer provideBigQueryMetricsEnqueuer() { + return metricsEnqueuer; + } + @Provides Clock provideClock() { return clock; } @Provides - Sleeper provideSleeper() { - return sleeper; + CustomLogicFactory provideCustomLogicFactory() { + return new TestCustomLogicFactory(); } @Provides @@ -80,6 +88,11 @@ interface EppTestComponent { return dnsQueue; } + @Provides + DomainFlowTmchUtils provideDomainFlowTmchUtils() { + return domainFlowTmchUtils; + } + @Provides EppMetric.Builder provideMetrics() { return metricBuilder; @@ -91,13 +104,8 @@ interface EppTestComponent { } @Provides - BigQueryMetricsEnqueuer provideBigQueryMetricsEnqueuer() { - return metricsEnqueuer; - } - - @Provides - CustomLogicFactory provideCustomLogicFactory() { - return new TestCustomLogicFactory(); + Sleeper provideSleeper() { + return sleeper; } } diff --git a/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java b/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java index 9b06541f7..a2c88d988 100644 --- a/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java +++ b/javatests/google/registry/flows/domain/DomainApplicationCreateFlowTest.java @@ -48,12 +48,24 @@ import google.registry.flows.domain.DomainApplicationCreateFlow.LandrushApplicat import google.registry.flows.domain.DomainApplicationCreateFlow.NoticeCannotBeUsedWithSignedMarkException; import google.registry.flows.domain.DomainApplicationCreateFlow.SunriseApplicationDisallowedDuringLandrushException; import google.registry.flows.domain.DomainApplicationCreateFlow.UncontestedSunriseApplicationBlockedInLandrushException; +import google.registry.flows.domain.DomainFlowTmchUtils.Base64RequiredForEncodedSignedMarksException; +import google.registry.flows.domain.DomainFlowTmchUtils.NoMarksFoundMatchingDomainException; +import google.registry.flows.domain.DomainFlowTmchUtils.SignedMarkCertificateExpiredException; +import google.registry.flows.domain.DomainFlowTmchUtils.SignedMarkCertificateInvalidException; +import google.registry.flows.domain.DomainFlowTmchUtils.SignedMarkCertificateNotYetValidException; +import google.registry.flows.domain.DomainFlowTmchUtils.SignedMarkCertificateRevokedException; +import google.registry.flows.domain.DomainFlowTmchUtils.SignedMarkCertificateSignatureException; +import google.registry.flows.domain.DomainFlowTmchUtils.SignedMarkEncodingErrorException; +import google.registry.flows.domain.DomainFlowTmchUtils.SignedMarkParsingErrorException; +import google.registry.flows.domain.DomainFlowTmchUtils.SignedMarkRevokedErrorException; +import google.registry.flows.domain.DomainFlowTmchUtils.SignedMarkSignatureException; +import google.registry.flows.domain.DomainFlowTmchUtils.SignedMarksMustBeEncodedException; +import google.registry.flows.domain.DomainFlowTmchUtils.TooManySignedMarksException; import google.registry.flows.domain.DomainFlowUtils.AcceptedTooLongAgoException; import google.registry.flows.domain.DomainFlowUtils.BadCommandForRegistryPhaseException; import google.registry.flows.domain.DomainFlowUtils.BadDomainNameCharacterException; import google.registry.flows.domain.DomainFlowUtils.BadDomainNamePartsCountException; import google.registry.flows.domain.DomainFlowUtils.BadPeriodUnitException; -import google.registry.flows.domain.DomainFlowUtils.Base64RequiredForEncodedSignedMarksException; import google.registry.flows.domain.DomainFlowUtils.ClaimsPeriodEndedException; import google.registry.flows.domain.DomainFlowUtils.CurrencyUnitMismatchException; import google.registry.flows.domain.DomainFlowUtils.CurrencyValueScaleException; @@ -79,24 +91,12 @@ import google.registry.flows.domain.DomainFlowUtils.MissingClaimsNoticeException import google.registry.flows.domain.DomainFlowUtils.MissingContactTypeException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotAllowedException; import google.registry.flows.domain.DomainFlowUtils.NameserversNotSpecifiedException; -import google.registry.flows.domain.DomainFlowUtils.NoMarksFoundMatchingDomainException; import google.registry.flows.domain.DomainFlowUtils.NotAuthorizedForTldException; import google.registry.flows.domain.DomainFlowUtils.PremiumNameBlockedException; import google.registry.flows.domain.DomainFlowUtils.RegistrantNotAllowedException; -import google.registry.flows.domain.DomainFlowUtils.SignedMarkCertificateExpiredException; -import google.registry.flows.domain.DomainFlowUtils.SignedMarkCertificateInvalidException; -import google.registry.flows.domain.DomainFlowUtils.SignedMarkCertificateNotYetValidException; -import google.registry.flows.domain.DomainFlowUtils.SignedMarkCertificateRevokedException; -import google.registry.flows.domain.DomainFlowUtils.SignedMarkCertificateSignatureException; -import google.registry.flows.domain.DomainFlowUtils.SignedMarkEncodingErrorException; -import google.registry.flows.domain.DomainFlowUtils.SignedMarkParsingErrorException; -import google.registry.flows.domain.DomainFlowUtils.SignedMarkRevokedErrorException; -import google.registry.flows.domain.DomainFlowUtils.SignedMarkSignatureException; -import google.registry.flows.domain.DomainFlowUtils.SignedMarksMustBeEncodedException; import google.registry.flows.domain.DomainFlowUtils.TldDoesNotExistException; import google.registry.flows.domain.DomainFlowUtils.TooManyDsRecordsException; import google.registry.flows.domain.DomainFlowUtils.TooManyNameserversException; -import google.registry.flows.domain.DomainFlowUtils.TooManySignedMarksException; import google.registry.flows.domain.DomainFlowUtils.TrailingDashException; import google.registry.flows.domain.DomainFlowUtils.UnexpectedClaimsNoticeException; import google.registry.flows.domain.DomainFlowUtils.UnsupportedFeeAttributeException; diff --git a/javatests/google/registry/tools/UpdateSmdCommandTest.java b/javatests/google/registry/tools/UpdateSmdCommandTest.java index 02ed43703..8d8944010 100644 --- a/javatests/google/registry/tools/UpdateSmdCommandTest.java +++ b/javatests/google/registry/tools/UpdateSmdCommandTest.java @@ -29,6 +29,7 @@ import com.google.common.collect.ImmutableMap; import google.registry.flows.EppException.ParameterValuePolicyErrorException; import google.registry.flows.EppException.ParameterValueSyntaxErrorException; import google.registry.flows.EppException.RequiredParameterMissingException; +import google.registry.flows.domain.DomainFlowTmchUtils; import google.registry.model.domain.DomainApplication; import google.registry.model.reporting.HistoryEntry; import google.registry.model.smd.EncodedSignedMark; @@ -65,6 +66,7 @@ public class UpdateSmdCommandTest extends CommandTestCase { .setCurrentSponsorClientId("TheRegistrar") .setEncodedSignedMarks(ImmutableList.of(EncodedSignedMark.create("base64", "garbage"))) .build()); + command.tmchUtils = new DomainFlowTmchUtils(); } private DomainApplication reloadDomainApplication() {