mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-10-22 14:22:39 +00:00
Replace custom parsing of CNs with jdk methods
This commit is contained in:
@@ -35,6 +35,7 @@ open module org.cryptomator.desktop {
|
||||
requires org.cryptomator.integrations.api;
|
||||
// jdk:
|
||||
requires java.desktop;
|
||||
requires java.naming;
|
||||
requires java.net.http;
|
||||
requires javafx.base;
|
||||
requires javafx.graphics;
|
||||
|
||||
@@ -2,6 +2,10 @@ package org.cryptomator.common;
|
||||
|
||||
import com.google.common.io.BaseEncoding;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attribute;
|
||||
import javax.naming.ldap.LdapName;
|
||||
import javax.naming.ldap.Rdn;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.security.GeneralSecurityException;
|
||||
@@ -60,54 +64,18 @@ final class X509Helper {
|
||||
}
|
||||
|
||||
static Optional<String> extractCommonName(X509Certificate cert) {
|
||||
String rfc2253Name = cert.getSubjectX500Principal().getName(X500Principal.RFC2253);
|
||||
for (String rdn : splitRdns(rfc2253Name)) {
|
||||
int equalsPos = rdn.indexOf('=');
|
||||
if (equalsPos > 0 && "CN".equalsIgnoreCase(rdn.substring(0, equalsPos).trim())) {
|
||||
return Optional.of(unescapeRdnValue(rdn.substring(equalsPos + 1).trim()));
|
||||
try {
|
||||
var name = new LdapName(cert.getSubjectX500Principal().getName(X500Principal.RFC2253));
|
||||
for (Rdn rdn : name.getRdns().reversed()) { // LdapName lists RDNs right to left
|
||||
Attribute cn = rdn.toAttributes().get("CN");
|
||||
if (cn != null && cn.get() instanceof String value) {
|
||||
return Optional.of(value);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
} catch (NamingException e) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static List<String> splitRdns(String distinguishedName) {
|
||||
List<String> rdns = new ArrayList<>();
|
||||
StringBuilder current = new StringBuilder();
|
||||
boolean escaped = false;
|
||||
for (int i = 0; i < distinguishedName.length(); i++) {
|
||||
char c = distinguishedName.charAt(i);
|
||||
if (escaped) {
|
||||
current.append(c);
|
||||
escaped = false;
|
||||
} else if (c == '\\') {
|
||||
current.append(c);
|
||||
escaped = true;
|
||||
} else if (c == ',') {
|
||||
rdns.add(current.toString());
|
||||
current.setLength(0);
|
||||
} else {
|
||||
current.append(c);
|
||||
}
|
||||
}
|
||||
rdns.add(current.toString());
|
||||
return rdns;
|
||||
}
|
||||
|
||||
private static String unescapeRdnValue(String value) {
|
||||
StringBuilder unescaped = new StringBuilder(value.length());
|
||||
boolean escaped = false;
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
char c = value.charAt(i);
|
||||
if (escaped) {
|
||||
unescaped.append(c);
|
||||
escaped = false;
|
||||
} else if (c == '\\') {
|
||||
escaped = true;
|
||||
} else {
|
||||
unescaped.append(c);
|
||||
}
|
||||
}
|
||||
return unescaped.toString();
|
||||
}
|
||||
|
||||
private static X509Certificate parseDerCertificate(byte[] derEncodedCertificate) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.cryptomator.common;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Optional;
|
||||
|
||||
public class X509HelperTest {
|
||||
|
||||
@Test
|
||||
public void testExtractCommonNameFromMultiValuedRdn() {
|
||||
var cert = Mockito.mock(X509Certificate.class);
|
||||
Mockito.doReturn(new X500Principal("OU=Licensing+CN=License Issuer CA (Test), O=Skymatic GmbH, C=DE")).when(cert).getSubjectX500Principal();
|
||||
|
||||
Optional<String> cn = X509Helper.extractCommonName(cert);
|
||||
|
||||
Assertions.assertEquals(Optional.of("License Issuer CA (Test)"), cn);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user