Skip to content

Commit 9936ace

Browse files
committed
implement hostname whitelist and blacklist
1 parent 529101d commit 9936ace

File tree

2 files changed

+97
-1
lines changed

2 files changed

+97
-1
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.acuity.iot.dsa.dslink.sys.cert;
2+
3+
import org.iot.dsa.node.DSBool;
4+
import org.iot.dsa.node.DSElement;
5+
import org.iot.dsa.node.DSIValue;
6+
import org.iot.dsa.node.DSInfo;
7+
import org.iot.dsa.node.DSJavaEnum;
8+
import org.iot.dsa.node.DSMap;
9+
import org.iot.dsa.node.DSNode;
10+
import org.iot.dsa.node.DSValueType;
11+
import org.iot.dsa.node.action.ActionInvocation;
12+
import org.iot.dsa.node.action.ActionResult;
13+
import org.iot.dsa.node.action.DSAbstractAction;
14+
15+
public class HostnameWhitelist extends DSNode {
16+
17+
public static enum WhitelistValue {
18+
ALLOWED, FORBIDDEN;
19+
}
20+
21+
private static final String ENABLED = "Enabled";
22+
private static final String ADD_HOSTNAME = "Add Hostname";
23+
24+
private DSInfo enabled = getInfo(ENABLED);
25+
26+
@Override
27+
protected void declareDefaults() {
28+
super.declareDefaults();
29+
declareDefault(ENABLED, DSBool.FALSE);
30+
declareDefault(ADD_HOSTNAME, getAddHostnameAction());
31+
}
32+
33+
public boolean isEnabled() {
34+
return enabled.getElement().toBoolean();
35+
}
36+
37+
private DSAbstractAction getAddHostnameAction() {
38+
DSAbstractAction act = new DSAbstractAction() {
39+
40+
@Override
41+
public void prepareParameter(DSInfo info, DSMap parameter) {
42+
}
43+
44+
@Override
45+
public ActionResult invoke(DSInfo info, ActionInvocation invocation) {
46+
((HostnameWhitelist) info.getParent()).addHostname(invocation.getParameters());
47+
return null;
48+
}
49+
};
50+
act.addParameter("Hostname", DSValueType.STRING, null);
51+
act.addParameter("Status", DSJavaEnum.valueOf(WhitelistValue.ALLOWED), "Whether this hostname should be whitelisted or blacklisted");
52+
return act;
53+
}
54+
55+
private void addHostname(DSMap parameters) {
56+
String hostname = parameters.getString("Hostname");
57+
DSElement status = parameters.get("Status");
58+
put(hostname, status).setRemovable(true);
59+
}
60+
61+
public WhitelistValue checkHostname(String hostname) {
62+
DSIValue value = getValue(hostname);
63+
String str = null;
64+
if (value != null) {
65+
str = value.toElement().toString();
66+
}
67+
try {
68+
return WhitelistValue.valueOf(str);
69+
} catch (Exception e) {
70+
return null;
71+
}
72+
}
73+
74+
}

dslink-v2/src/main/java/com/acuity/iot/dsa/dslink/sys/cert/SysCertManager.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
//import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
2424
import org.iot.dsa.node.DSBool;
2525
import org.iot.dsa.node.DSInfo;
26+
import org.iot.dsa.node.DSList;
2627
import org.iot.dsa.node.DSMap;
2728
import org.iot.dsa.node.DSNode;
2829
import org.iot.dsa.node.DSString;
@@ -34,6 +35,7 @@
3435
import org.iot.dsa.node.action.DSActionValues;
3536
import org.iot.dsa.security.DSPasswordAes128;
3637
import org.iot.dsa.util.DSException;
38+
import com.acuity.iot.dsa.dslink.sys.cert.HostnameWhitelist.WhitelistValue;
3739

3840
/**
3941
* Certificate management for the whole process. This is basically a stub for future
@@ -51,6 +53,7 @@ public class SysCertManager extends DSNode {
5153
private static final String ALLOW_CLIENTS = "Allow_Anonymous_Clients";
5254
private static final String ALLOW_SERVERS = "Allow_Anonymous_Servers";
5355
private static final String VERIFY_HOSTNAMES = "Enable Hostname Verification";
56+
private static final String HOSTNAME_WHITELIST = "Hostname Whitelist";
5457
private static final String CERTFILE = "Cert_File";
5558
private static final String CERTFILE_PASS = "Cert_File_Pass";
5659
private static final String CERTFILE_TYPE = "Cert_File_Type";
@@ -74,6 +77,7 @@ public class SysCertManager extends DSNode {
7477
private DSInfo keystoreType = getInfo(CERTFILE_TYPE);
7578
private CertCollection localTruststore;
7679
private CertCollection quarantine;
80+
private HostnameWhitelist whitelist;
7781
private static SysCertManager inst;
7882

7983
private static HostnameVerifier oldHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
@@ -104,6 +108,13 @@ private CertCollection getQuarantine() {
104108
return quarantine;
105109
}
106110

111+
private HostnameWhitelist getHostnameWhitelist() {
112+
if (whitelist == null) {
113+
whitelist = (HostnameWhitelist) getInfo(HOSTNAME_WHITELIST).getObject();
114+
}
115+
return whitelist;
116+
}
117+
107118
// Methods
108119
// -------
109120

@@ -130,6 +141,7 @@ public void declareDefaults() {
130141
declareDefault(ALLOW_CLIENTS, DSBool.FALSE);
131142
declareDefault(ALLOW_SERVERS, DSBool.TRUE);
132143
declareDefault(VERIFY_HOSTNAMES, DSBool.TRUE);
144+
declareDefault(HOSTNAME_WHITELIST, new HostnameWhitelist());
133145
declareDefault(CERTFILE, DSString.valueOf("dslink.jks"));
134146
declareDefault(CERTFILE_TYPE, DSString.valueOf("JKS"));
135147
declareDefault(CERTFILE_PASS, DSPasswordAes128.valueOf("dsarocks"));
@@ -343,8 +355,18 @@ public void allow(DSInfo certInfo) {
343355
private class SysHostnameVerifier implements HostnameVerifier {
344356
@Override
345357
public boolean verify(String hostname, SSLSession session) {
358+
if (getHostnameWhitelist().isEnabled()) {
359+
WhitelistValue wlval = getHostnameWhitelist().checkHostname(hostname);
360+
if (wlval != null) {
361+
switch (wlval) {
362+
case ALLOWED:
363+
return true;
364+
case FORBIDDEN:
365+
return false;
366+
}
367+
}
368+
}
346369
if (hostnameVerificationEnabled()) {
347-
//TODO implement whitelist
348370
return oldHostnameVerifier.verify(hostname, session);
349371
} else {
350372
return true;

0 commit comments

Comments
 (0)