package org.littleshoot.proxy.mitm; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.regex.Pattern; import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.x509.Extension; import org.bouncycastle.asn1.x509.GeneralName; import org.bouncycastle.cert.CertIOException; import org.bouncycastle.cert.X509v3CertificateBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SubjectAlternativeNameHolder { private static final Logger log = LoggerFactory.getLogger(SubjectAlternativeNameHolder.class); /** * @see org.bouncycastle.asn1.x509.GeneralName * @see <a href="https://tools.ietf.org/html/rfc5280#section-4.2.1.6">RFC 5280, ยง 4.2.1.6. Subject Alternative Name</a> */ private static final Pattern TAGS_PATTERN = Pattern.compile("[012345678]"); private final List<ASN1Encodable> sans = new ArrayList<ASN1Encodable>(); public void addIpAddress(String ipAddress) { sans.add(new GeneralName(GeneralName.iPAddress, ipAddress)); } public void addDomainName(String subjectAlternativeName) { sans.add(new GeneralName(GeneralName.dNSName, subjectAlternativeName)); } public void fillInto(X509v3CertificateBuilder certGen) throws CertIOException { if (!sans.isEmpty()) { ASN1Encodable[] encodables = sans.toArray(new ASN1Encodable[sans .size()]); certGen.addExtension(Extension.subjectAlternativeName, false, new DERSequence(encodables)); } } public void addAll(Collection<List<?>> subjectAlternativeNames) { if (subjectAlternativeNames != null) { for (List<?> each : subjectAlternativeNames) { if (isValidNameEntry(each)) { int tag = Integer.valueOf(String.valueOf(each.get(0))); String name = String.valueOf(each.get(1)); sans.add(new GeneralName(tag, name)); } else { log.warn("Invalid name entry ignored: {}", each); } } } } private boolean isValidNameEntry(List<?> nameEntry) { if (nameEntry == null || nameEntry.size() != 2) { return false; } String tag = String.valueOf(nameEntry.get(0)); return TAGS_PATTERN.matcher(tag).matches(); } }