Skip to content

Commit 013cb36

Browse files
committed
v0.3.4 Update
Added a custom issuer setting Updated README
1 parent d7c0ae5 commit 013cb36

File tree

8 files changed

+41
-8
lines changed

8 files changed

+41
-8
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Users can be added to a restriction bypass whitelist which makes them behave as
2727

2828
| Setting | Default | Description |
2929
| - | - | - |
30+
| ***Issuer*** | `WebCTRL` | This field will be displayed in your authenticator app after scanning QR codes. It is intended to uniquely identify this server. A length limit of 40 characters is enforced. |
3031
| ***Enforce MFA*** | `false` | When MFA is enforced, all non-whitelisted users will be forced to configure MFA when they login. |
3132
| ***Allow Service Logins*** | `true` | When unchecked, non-whitelisted users with MFA enabled will be unable to login to WebCTRL services such as SOAP and TELNET (these services are incompatible with MFA). |
3233
| ***Bypass MFA on Email Server Failure*** | `true` | When WebCTRL fails to connect to its email server, MFA security codes cannot be sent. This option permits MFA to be bypassed in such a case. Otherwise, non-whitelisted users with MFA enabled will not be able to login. |

images/main_page.png

9.02 KB
Loading

root/info.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<extension version="1">
22
<name>MFA</name>
33
<description>Provides MFA for WebCTRL logins through an authenticator app or emailed security codes.</description>
4-
<version>0.3.3</version>
4+
<version>0.3.4</version>
55
<vendor>Automatic Controls Equipment Systems, Inc.</vendor>
66
<web-operator-provider>aces.webctrl.mfa.core.MFAProvider</web-operator-provider>
77
<system-menu-provider>aces.webctrl.mfa.web.SystemMenuEditor</system-menu-provider>

src/aces/webctrl/mfa/core/Config.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ public class Config {
8383
* Specifies the next time to load the serverURL.
8484
*/
8585
private volatile static long nextURLCheck = 0;
86+
/**
87+
* Specifies the name of the issuer for the TOTP tokens.
88+
*/
89+
public volatile static String issuerName = "WebCTRL";
8690
/**
8791
* Sets the path to the saved data file and attempts to load any available data.
8892
*/
@@ -796,8 +800,11 @@ public static boolean loadData(){
796800
whitelistLock.writeLock().unlock();
797801
}
798802
if (!s.end()){
799-
Initializer.log("Data file corrupted.");
800-
return false;
803+
issuerName = s.readString();
804+
if (!s.end()){
805+
Initializer.log("Data file corrupted.");
806+
return false;
807+
}
801808
}
802809
}
803810
if (Files.exists(cookieFile)){
@@ -881,6 +888,7 @@ public static boolean saveData(){
881888
}finally{
882889
whitelistLock.readLock().unlock();
883890
}
891+
s.write(issuerName);
884892
ByteBuffer buf = s.getBuffer();
885893
synchronized(Config.class){
886894
try(

src/aces/webctrl/mfa/core/Initializer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
import java.nio.file.*;
77
import java.util.*;
88
import java.net.URISyntaxException;
9+
// # TODO
10+
// - Implement **Bypass MFA on Upstream Server Failure** option that is enabled by default
11+
// - Maybe implement cache so that only api users are blocked when the api server is inaccessible
912
/**
1013
* This class contains most of the life-cycle management logic for this add-on.
1114
*/

src/aces/webctrl/mfa/core/Utility.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public static String createOTP(String user) throws URISyntaxException {
7676
builder.withAlgorithm(HMACAlgorithm.SHA1);//deprecated, but Google Authenticator does not support any stronger algorithms
7777
})
7878
.withPeriod(java.time.Duration.ofSeconds(30))
79-
.build().getURI("WebCTRL", user).toString();
79+
.build().getURI(Config.issuerName, user).toString();
8080
}
8181
/**
8282
* @return a hex string representation of the given bytes.

src/aces/webctrl/mfa/resources/MainPage.html

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@
7474
const cookiesEnabled = cookiesEnabledCheckbox.checked;
7575
const trustProxyHeaders = trustProxyHeadersCheckbox.checked;
7676
const apiEnabled = apiEnabledCheckbox.checked;
77+
const _issuer = issuerField.value?.trim() || "WebCTRL";
78+
const issuer = _issuer.length>40?_issuer.substring(0,40):_issuer;
79+
issuerField.value = issuer;
80+
resize(issuerField);
7781
const _mappings = [];
7882
for (const e of document.getElementById("mappingBody").getElementsByTagName("TR")){
7983
if (e.mfa_operator && e.mfa_email){
@@ -116,6 +120,7 @@
116120
"&cookiesEnabled="+encodeURIComponent(cookiesEnabled)+
117121
"&trustProxyHeaders="+encodeURIComponent(trustProxyHeaders)+
118122
"&apiEnabled="+encodeURIComponent(apiEnabled)+
123+
"&issuer="+encodeURIComponent(issuer)+
119124
"&mappings="+encodeURIComponent(mappings)+
120125
"&whitelist="+encodeURIComponent(whitelist)
121126
);
@@ -268,6 +273,8 @@
268273
cookiesEnabledCheckbox.checked = data["cookiesEnabled"];
269274
trustProxyHeadersCheckbox.checked = data["trustProxyHeaders"];
270275
apiEnabledCheckbox.checked = data["apiEnabled"];
276+
issuerField.value = data["issuer"];
277+
resize(issuerField);
271278
const mappingBody = document.getElementById("mappingBody");
272279
while (mappingBody.children.length>1){
273280
mappingBody.removeChild(mappingBody.firstElementChild);
@@ -487,7 +494,11 @@ <h1 id="mainTitle">Configure MFA</h1>
487494
</div>
488495
</div>
489496
<div class="column">
490-
<div style="text-align:left">
497+
<div style="text-align:left;margin-left:2em">
498+
<div class="divGrouping" title="This field will be displayed in your authenticator app after scanning QR codes. It is intended to uniquely identify this server.">
499+
<label for="issuerField">Issuer:</label>
500+
<input class="c" type="text" id="issuerField" spellcheck="false" oninput="resize(this);registerChange()">
501+
</div>
491502
<div class="divGrouping2" title="Specifies whether to force all users to use MFA.">
492503
<input type="checkbox" id="enforceMFACheckbox" oninput="registerChange()" style="width:1.3em;height:1.3em;vertical-align:middle">
493504
<label for="enforceMFACheckbox" style="vertical-align:middle">Enforce MFA</label>
@@ -555,6 +566,7 @@ <h1 id="mainTitle">Configure MFA</h1>
555566
resize(usernameField);
556567
resize(usernameField2);
557568
resize(emailField);
569+
resize(issuerField);
558570
usernameField.addEventListener("keypress", function (e){
559571
if (e.key==="Enter"){
560572
e.preventDefault();

src/aces/webctrl/mfa/web/MainPage.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ public class MainPage extends ServletBase {
4343
final String cookiesEnabled = req.getParameter("cookiesEnabled");
4444
final String mappings = req.getParameter("mappings");
4545
final String whitelist = req.getParameter("whitelist");
46-
if (enforceMFA==null || allowServiceLogins==null || bypassOnEmailFailure==null || mappings==null || whitelist==null || emailEnabled==null || apiEnabled==null || trustProxyHeaders==null || cookiesEnabled==null){
46+
final String issuer = req.getParameter("issuer");
47+
if (enforceMFA==null || allowServiceLogins==null || bypassOnEmailFailure==null || mappings==null || whitelist==null || emailEnabled==null || apiEnabled==null || trustProxyHeaders==null || cookiesEnabled==null || issuer==null){
4748
res.setStatus(400);
4849
return;
4950
}
@@ -54,6 +55,7 @@ public class MainPage extends ServletBase {
5455
boolean _apiEnabled;
5556
boolean _trustProxyHeaders;
5657
boolean _cookiesEnabled;
58+
String _issuer;
5759
ArrayList<String> _mappings;
5860
ArrayList<String> _whitelist;
5961
try{
@@ -66,6 +68,11 @@ public class MainPage extends ServletBase {
6668
_cookiesEnabled = Boolean.parseBoolean(cookiesEnabled);
6769
_mappings = Utility.decodeList(mappings);
6870
_whitelist = Utility.decodeList(whitelist);
71+
_issuer = issuer.trim();
72+
_issuer = _issuer.isEmpty()?"WebCTRL":_issuer;
73+
if (_issuer.length()>40){
74+
_issuer = _issuer.substring(0,40);
75+
}
6976
}catch(Throwable t){
7077
Initializer.log(t);
7178
res.setStatus(400);
@@ -91,6 +98,7 @@ public class MainPage extends ServletBase {
9198
Config.apiEnabled = _apiEnabled;
9299
Config.trustProxyHeaders = _trustProxyHeaders;
93100
Config.cookiesEnabled = _cookiesEnabled;
101+
Config.issuerName = _issuer;
94102
Config.setWhitelist(_whitelist);
95103
Config.checkCookies(map.keySet());
96104
Config.setEmails(map);
@@ -100,14 +108,15 @@ public class MainPage extends ServletBase {
100108
case "load":{
101109
final StringBuilder sb = new StringBuilder(1024);
102110
sb.append(Utility.format(
103-
"{\"enforceMFA\":$0,\"allowServiceLogins\":$1,\"bypassOnEmailFailure\":$2,\"emailEnabled\":$3,\"apiEnabled\":$4,\"trustProxyHeaders\":$5,\"cookiesEnabled\":$6,",
111+
"{\"enforceMFA\":$0,\"allowServiceLogins\":$1,\"bypassOnEmailFailure\":$2,\"emailEnabled\":$3,\"apiEnabled\":$4,\"trustProxyHeaders\":$5,\"cookiesEnabled\":$6,\"issuer\":\"$7\",",
104112
Config.enforceMFA,
105113
Config.allowServiceLogins,
106114
Config.bypassOnEmailFailure,
107115
Config.emailEnabled,
108116
Config.apiEnabled,
109117
Config.trustProxyHeaders,
110-
Config.cookiesEnabled
118+
Config.cookiesEnabled,
119+
Utility.escapeJSON(Config.issuerName)
111120
));
112121
sb.append("\"mappings\":");
113122
Config.printEmails(sb);

0 commit comments

Comments
 (0)