All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.shredzone.acme4j.Identifier Maven / Gradle / Ivy

The newest version!
/*
 * acme4j - Java ACME client
 *
 * Copyright (C) 2018 Richard "Shred" Körber
 *   http://acme4j.shredzone.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */
package org.shredzone.acme4j;

import static java.util.Collections.unmodifiableMap;
import static java.util.Objects.requireNonNull;
import static org.shredzone.acme4j.toolbox.AcmeUtils.toAce;

import java.io.Serializable;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.TreeMap;

import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.toolbox.JSON;

/**
 * Represents an identifier.
 * 

* The ACME protocol only defines the DNS identifier, which identifies a domain name. * acme4j also supports IP identifiers. *

* CAs, and other acme4j modules, may define further, proprietary identifier types. * * @since 2.3 */ public class Identifier implements Serializable { private static final long serialVersionUID = -7777851842076362412L; /** * Type constant for DNS identifiers. */ public static final String TYPE_DNS = "dns"; /** * Type constant for IP identifiers. * * @see RFC 8738 */ public static final String TYPE_IP = "ip"; static final String KEY_TYPE = "type"; static final String KEY_VALUE = "value"; static final String KEY_ANCESTOR_DOMAIN = "ancestorDomain"; static final String KEY_SUBDOMAIN_AUTH_ALLOWED = "subdomainAuthAllowed"; private final Map content = new TreeMap<>(); /** * Creates a new {@link Identifier}. *

* This is a generic constructor for identifiers. Refer to the documentation of your * CA to find out about the accepted identifier types and values. *

* Note that for DNS identifiers, no ASCII encoding of unicode domain takes place * here. Use {@link #dns(String)} instead. * * @param type * Identifier type * @param value * Identifier value */ public Identifier(String type, String value) { content.put(KEY_TYPE, requireNonNull(type, KEY_TYPE)); content.put(KEY_VALUE, requireNonNull(value, KEY_VALUE)); } /** * Creates a new {@link Identifier} from the given {@link JSON} structure. * * @param json * {@link JSON} containing the identifier data */ public Identifier(JSON json) { if (!json.contains(KEY_TYPE)) { throw new AcmeProtocolException("Required key " + KEY_TYPE + " is missing"); } if (!json.contains(KEY_VALUE)) { throw new AcmeProtocolException("Required key " + KEY_VALUE + " is missing"); } content.putAll(json.toMap()); } /** * Makes a copy of the given Identifier. */ private Identifier(Identifier identifier) { content.putAll(identifier.content); } /** * Creates a new DNS identifier for the given domain name. * * @param domain * Domain name. Unicode domains are automatically ASCII encoded. * @return New {@link Identifier} */ public static Identifier dns(String domain) { return new Identifier(TYPE_DNS, toAce(domain)); } /** * Creates a new IP identifier for the given {@link InetAddress}. * * @param ip * {@link InetAddress} * @return New {@link Identifier} */ public static Identifier ip(InetAddress ip) { return new Identifier(TYPE_IP, ip.getHostAddress()); } /** * Creates a new IP identifier for the given {@link InetAddress}. * * @param ip * IP address as {@link String} * @return New {@link Identifier} * @since 2.7 */ public static Identifier ip(String ip) { try { return ip(InetAddress.getByName(ip)); } catch (UnknownHostException ex) { throw new IllegalArgumentException("Bad IP: " + ip, ex); } } /** * Sets an ancestor domain, as required in RFC-9444. * * @param domain * The ancestor domain to be set. Unicode domains are automatically ASCII * encoded. * @return An {@link Identifier} that contains the ancestor domain. * @since 3.3.0 */ public Identifier withAncestorDomain(String domain) { expectType(TYPE_DNS); var result = new Identifier(this); result.content.put(KEY_ANCESTOR_DOMAIN, toAce(domain)); return result; } /** * Gives the permission to authorize subdomains of this domain, as required in * RFC-9444. * * @return An {@link Identifier} that allows subdomain auths. * @since 3.3.0 */ public Identifier allowSubdomainAuth() { expectType(TYPE_DNS); var result = new Identifier(this); result.content.put(KEY_SUBDOMAIN_AUTH_ALLOWED, true); return result; } /** * Returns the identifier type. */ public String getType() { return content.get(KEY_TYPE).toString(); } /** * Returns the identifier value. */ public String getValue() { return content.get(KEY_VALUE).toString(); } /** * Returns the domain name if this is a DNS identifier. * * @return Domain name. Unicode domains are ASCII encoded. * @throws AcmeProtocolException * if this is not a DNS identifier. */ public String getDomain() { expectType(TYPE_DNS); return getValue(); } /** * Returns the IP address if this is an IP identifier. * * @return {@link InetAddress} * @throws AcmeProtocolException * if this is not a DNS identifier. */ public InetAddress getIP() { expectType(TYPE_IP); try { return InetAddress.getByName(getValue()); } catch (UnknownHostException ex) { throw new AcmeProtocolException("bad ip identifier value", ex); } } /** * Returns the identifier as JSON map. */ public Map toMap() { return unmodifiableMap(content); } /** * Makes sure this identifier is of the given type. * * @param type * Expected type * @throws AcmeProtocolException * if this identifier is of a different type */ private void expectType(String type) { if (!type.equals(getType())) { throw new AcmeProtocolException("expected '" + type + "' identifier, but found '" + getType() + "'"); } } @Override public String toString() { if (content.size() == 2) { return getType() + '=' + getValue(); } return content.toString(); } @Override public boolean equals(Object obj) { if (!(obj instanceof Identifier)) { return false; } var i = (Identifier) obj; return content.equals(i.content); } @Override public int hashCode() { return content.hashCode(); } @Override protected final void finalize() { // CT_CONSTRUCTOR_THROW: Prevents finalizer attack } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy