Check for an empty/null allocation token (#489)

* Check for an empty/null allocation token

In addition, we should be returning an authorization exception for an
invalid token, not a parameter syntax exception. See https://tools.ietf.org/html/draft-ietf-regext-allocation-token-04#section-2.1

* Add comment
This commit is contained in:
gbrodman 2020-02-20 15:50:10 -05:00 committed by GitHub
parent ecf1721755
commit 05ed4fd849
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 3 deletions

View file

@ -17,6 +17,7 @@ package google.registry.flows.domain.token;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@ -24,7 +25,7 @@ import com.google.common.net.InternetDomainName;
import com.googlecode.objectify.Key; import com.googlecode.objectify.Key;
import google.registry.flows.EppException; import google.registry.flows.EppException;
import google.registry.flows.EppException.AssociationProhibitsOperationException; import google.registry.flows.EppException.AssociationProhibitsOperationException;
import google.registry.flows.EppException.ParameterValueSyntaxErrorException; import google.registry.flows.EppException.AuthorizationErrorException;
import google.registry.flows.EppException.StatusProhibitsOperationException; import google.registry.flows.EppException.StatusProhibitsOperationException;
import google.registry.model.domain.DomainCommand; import google.registry.model.domain.DomainCommand;
import google.registry.model.domain.token.AllocationToken; import google.registry.model.domain.token.AllocationToken;
@ -137,6 +138,12 @@ public class AllocationTokenFlowUtils {
/** Loads a given token and validates that it is not redeemed */ /** Loads a given token and validates that it is not redeemed */
private AllocationToken loadToken(String token) throws EppException { private AllocationToken loadToken(String token) throws EppException {
if (Strings.isNullOrEmpty(token)) {
// We load the token directly from the input XML. If it's null or empty we should throw
// an InvalidAllocationTokenException before the Datastore load attempt fails.
// See https://tools.ietf.org/html/draft-ietf-regext-allocation-token-04#section-2.1
throw new InvalidAllocationTokenException();
}
AllocationToken tokenEntity = ofy().load().key(Key.create(AllocationToken.class, token)).now(); AllocationToken tokenEntity = ofy().load().key(Key.create(AllocationToken.class, token)).now();
if (tokenEntity == null) { if (tokenEntity == null) {
throw new InvalidAllocationTokenException(); throw new InvalidAllocationTokenException();
@ -181,7 +188,7 @@ public class AllocationTokenFlowUtils {
} }
/** The allocation token is invalid. */ /** The allocation token is invalid. */
public static class InvalidAllocationTokenException extends ParameterValueSyntaxErrorException { public static class InvalidAllocationTokenException extends AuthorizationErrorException {
public InvalidAllocationTokenException() { public InvalidAllocationTokenException() {
super("The allocation token is invalid"); super("The allocation token is invalid");
} }

View file

@ -90,6 +90,22 @@ public class AllocationTokenFlowUtilsTest extends ShardableTestCase {
assertValidateThrowsEppException(InvalidAllocationTokenException.class); assertValidateThrowsEppException(InvalidAllocationTokenException.class);
} }
@Test
public void test_validateToken_failsOnNullToken() {
assertAboutEppExceptions()
.that(
assertThrows(
InvalidAllocationTokenException.class,
() ->
flowUtils.loadTokenAndValidateDomainCreate(
createCommand("blah.tld"),
null,
Registry.get("tld"),
"TheRegistrar",
DateTime.now(UTC))))
.marshalsToXml();
}
@Test @Test
public void test_validateToken_callsCustomLogic() { public void test_validateToken_callsCustomLogic() {
AllocationTokenFlowUtils failingFlowUtils = AllocationTokenFlowUtils failingFlowUtils =

View file

@ -324,7 +324,6 @@ An EPP flow that creates a new domain resource.
* The checksum in the specified TCNID does not validate. * The checksum in the specified TCNID does not validate.
* Domain name is under tld which doesn't exist. * Domain name is under tld which doesn't exist.
* 2005 * 2005
* The allocation token is invalid.
* Domain name must have exactly one part above the TLD. * Domain name must have exactly one part above the TLD.
* Domain name must not equal an existing multi-part TLD. * Domain name must not equal an existing multi-part TLD.
* The requested fee is expressed in a scale that is invalid for the given * The requested fee is expressed in a scale that is invalid for the given
@ -337,6 +336,7 @@ An EPP flow that creates a new domain resource.
* 2103 * 2103
* Specified extension is not implemented. * Specified extension is not implemented.
* 2201 * 2201
* The allocation token is invalid.
* Only a tool can pass a metadata extension. * Only a tool can pass a metadata extension.
* Registrar is not authorized to access this TLD. * Registrar is not authorized to access this TLD.
* Registrar must be active in order to perform this operation. * Registrar must be active in order to perform this operation.