diff --git a/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
index 4ee173d..7769e44 100644
--- a/Properties/Resources.Designer.cs
+++ b/Properties/Resources.Designer.cs
@@ -980,6 +980,15 @@ namespace MeshCentralRouter.Properties {
}
}
+ ///
+ /// Looks up a localized string similar to Complete 2FA setup online first.
+ ///
+ internal static string TwoFactorSetupRequired {
+ get {
+ return ResourceManager.GetString("TwoFactorSetupRequired", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Unable to bind to local port.
///
diff --git a/Properties/Resources.resx b/Properties/Resources.resx
index 6a98f0c..023b2b5 100644
--- a/Properties/Resources.resx
+++ b/Properties/Resources.resx
@@ -478,4 +478,7 @@
Send token to registered messaging application?
+
+ Complete 2FA setup online first
+
\ No newline at end of file
diff --git a/src/MainForm.Designer.cs b/src/MainForm.Designer.cs
index 5058503..a0dc636 100644
--- a/src/MainForm.Designer.cs
+++ b/src/MainForm.Designer.cs
@@ -91,6 +91,9 @@
this.devicesTabPage = new System.Windows.Forms.TabPage();
this.devicesPanel = new System.Windows.Forms.Panel();
this.cancelAutoCloseButton1 = new System.Windows.Forms.Button();
+ this.devicesListView = new MeshCentralRouter.ListViewExtended();
+ this.nameColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+ this.stateColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.devicesContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
this.addMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.addRelayMapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
@@ -106,6 +109,7 @@
this.sshToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.scpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.wolToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.chatToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.devicesImageList = new System.Windows.Forms.ImageList(this.components);
this.noSearchResultsLabel = new System.Windows.Forms.Label();
this.noDevicesLabel = new System.Windows.Forms.Label();
@@ -138,10 +142,6 @@
this.customAppsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.openMapFileDialog = new System.Windows.Forms.OpenFileDialog();
this.saveMapFileDialog = new System.Windows.Forms.SaveFileDialog();
- this.chatToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
- this.devicesListView = new MeshCentralRouter.ListViewExtended();
- this.nameColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
- this.stateColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.panel5.SuspendLayout();
this.mainPanel.SuspendLayout();
this.mainTabControl.SuspendLayout();
@@ -635,6 +635,37 @@
this.cancelAutoCloseButton1.Click += new System.EventHandler(this.cancelAutoCloseButton_Click);
this.cancelAutoCloseButton1.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.MainForm_KeyPress);
//
+ // devicesListView
+ //
+ this.devicesListView.BackColor = System.Drawing.SystemColors.Window;
+ this.devicesListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this.nameColumnHeader,
+ this.stateColumnHeader});
+ this.devicesListView.ContextMenuStrip = this.devicesContextMenuStrip;
+ this.devicesListView.FullRowSelect = true;
+ this.devicesListView.GridLines = true;
+ this.devicesListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
+ this.devicesListView.HideSelection = false;
+ this.devicesListView.LargeImageList = this.devicesImageList;
+ resources.ApplyResources(this.devicesListView, "devicesListView");
+ this.devicesListView.MultiSelect = false;
+ this.devicesListView.Name = "devicesListView";
+ this.devicesListView.SmallImageList = this.devicesImageList;
+ this.devicesListView.Sorting = System.Windows.Forms.SortOrder.Ascending;
+ this.devicesListView.UseCompatibleStateImageBehavior = false;
+ this.devicesListView.View = System.Windows.Forms.View.Details;
+ this.devicesListView.Click += new System.EventHandler(this.devicesListView_Click);
+ this.devicesListView.DoubleClick += new System.EventHandler(this.devicesListView_DoubleClick);
+ this.devicesListView.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.MainForm_KeyPress);
+ //
+ // nameColumnHeader
+ //
+ resources.ApplyResources(this.nameColumnHeader, "nameColumnHeader");
+ //
+ // stateColumnHeader
+ //
+ resources.ApplyResources(this.stateColumnHeader, "stateColumnHeader");
+ //
// devicesContextMenuStrip
//
this.devicesContextMenuStrip.ImageScalingSize = new System.Drawing.Size(24, 24);
@@ -742,6 +773,12 @@
resources.ApplyResources(this.wolToolStripMenuItem, "wolToolStripMenuItem");
this.wolToolStripMenuItem.Click += new System.EventHandler(this.wolToolStripMenuItem_Click);
//
+ // chatToolStripMenuItem
+ //
+ this.chatToolStripMenuItem.Name = "chatToolStripMenuItem";
+ resources.ApplyResources(this.chatToolStripMenuItem, "chatToolStripMenuItem");
+ this.chatToolStripMenuItem.Click += new System.EventHandler(this.chatToolStripMenuItem_Click);
+ //
// devicesImageList
//
this.devicesImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("devicesImageList.ImageStream")));
@@ -978,43 +1015,6 @@
this.saveMapFileDialog.DefaultExt = "mcrouter";
resources.ApplyResources(this.saveMapFileDialog, "saveMapFileDialog");
//
- // chatToolStripMenuItem
- //
- this.chatToolStripMenuItem.Name = "chatToolStripMenuItem";
- resources.ApplyResources(this.chatToolStripMenuItem, "chatToolStripMenuItem");
- this.chatToolStripMenuItem.Click += new System.EventHandler(this.chatToolStripMenuItem_Click);
- //
- // devicesListView
- //
- this.devicesListView.BackColor = System.Drawing.SystemColors.Window;
- this.devicesListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
- this.nameColumnHeader,
- this.stateColumnHeader});
- this.devicesListView.ContextMenuStrip = this.devicesContextMenuStrip;
- this.devicesListView.FullRowSelect = true;
- this.devicesListView.GridLines = true;
- this.devicesListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
- this.devicesListView.HideSelection = false;
- this.devicesListView.LargeImageList = this.devicesImageList;
- resources.ApplyResources(this.devicesListView, "devicesListView");
- this.devicesListView.MultiSelect = false;
- this.devicesListView.Name = "devicesListView";
- this.devicesListView.SmallImageList = this.devicesImageList;
- this.devicesListView.Sorting = System.Windows.Forms.SortOrder.Ascending;
- this.devicesListView.UseCompatibleStateImageBehavior = false;
- this.devicesListView.View = System.Windows.Forms.View.Details;
- this.devicesListView.Click += new System.EventHandler(this.devicesListView_Click);
- this.devicesListView.DoubleClick += new System.EventHandler(this.devicesListView_DoubleClick);
- this.devicesListView.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.MainForm_KeyPress);
- //
- // nameColumnHeader
- //
- resources.ApplyResources(this.nameColumnHeader, "nameColumnHeader");
- //
- // stateColumnHeader
- //
- resources.ApplyResources(this.stateColumnHeader, "stateColumnHeader");
- //
// MainForm
//
resources.ApplyResources(this, "$this");
diff --git a/src/MainForm.cs b/src/MainForm.cs
index cdca0ff..8b869ed 100644
--- a/src/MainForm.cs
+++ b/src/MainForm.cs
@@ -1077,6 +1077,13 @@ namespace MeshCentralRouter
stateClearTimer.Enabled = true;
serverNameComboBox.Focus();
}
+ else if ((meshcentral.disconnectMsg != null) && meshcentral.disconnectMsg.StartsWith("2fasetuprequired"))
+ {
+ stateLabel.Text = Translate.T(Properties.Resources.TwoFactorSetupRequired);
+ stateLabel.Visible = true;
+ stateClearTimer.Enabled = true;
+ serverNameComboBox.Focus();
+ }
else if (meshcentral.disconnectMsg == "cert")
{
lastBadConnectCert = meshcentral.disconnectCert;
diff --git a/src/MainForm.resx b/src/MainForm.resx
index 50e7e8f..5c1f7e1 100644
--- a/src/MainForm.resx
+++ b/src/MainForm.resx
@@ -204,6 +204,9 @@
241, 225
+
+ 241, 0
+
88, 13
@@ -1474,7 +1477,7 @@
NoControl
- 6, 176
+ 6, 164
168, 35
@@ -1519,19 +1522,19 @@
Segoe UI, 9pt, style=Bold
- 180, 22
+ 170, 22
Add &Map...
- 180, 22
+ 170, 22
Add &Relay Map...
- 177, 6
+ 167, 6
171, 22
@@ -1552,61 +1555,61 @@
Privacy Bar
- 180, 22
+ 170, 22
Remote Desktop...
- 180, 22
+ 170, 22
Remote Files...
- 180, 22
+ 170, 22
HTTP
- 180, 22
+ 170, 22
HTTPS
- 180, 22
+ 170, 22
RDP
- 180, 22
+ 170, 22
SSH
- 180, 22
+ 170, 22
SCP
- 180, 22
+ 170, 22
Wake Up...
- 180, 22
+ 170, 22
Chat
- 181, 274
+ 171, 252
devicesContextMenuStrip
@@ -1622,7 +1625,7 @@
AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAADg
- HQAAAk1TRnQBSQFMAgEBEAEAAUABAQFAAQEBEAEAARABAAT/ARkBAAj/AUIBTQE2BwABNgMAASgDAAFA
+ HQAAAk1TRnQBSQFMAgEBEAEAAVgBAQFYAQEBEAEAARABAAT/ARkBAAj/AUIBTQE2BwABNgMAASgDAAFA
AwABUAMAAQEBAAEYBgABPP8A/wD/AP8A/wD/AP8A/wD/AP8A/wD/AJYAA/0D+AP3A/sD/yEAA/0D+gP5
A/wD/xgAAfoB+wH6A/4qAAP9A/8tAAP7A88D1QPbA88D1AO+A9QYAAP8A90D4APjA90D4APUA+MSAAP8
AZEBjwF9AU4BaAEhAfQB9QH0JAAD/gPRA8YD+ioAAcYCxwHPAtAB2ALZA90DywPBA68DmgP3FQAD2APd
@@ -1768,7 +1771,7 @@
devicesListView
- MeshCentralRouter.ListViewExtended, MeshCentralRouter, Version=1.8.8984.19540, Culture=neutral, PublicKeyToken=null
+ MeshCentralRouter.ListViewExtended, MeshCentralRouter, Version=1.8.9322.36929, Culture=neutral, PublicKeyToken=null
devicesPanel
@@ -1789,7 +1792,7 @@
2, 88
- 358, 52
+ 346, 52
5
@@ -1828,7 +1831,7 @@
2, 88
- 358, 52
+ 346, 52
4
@@ -1951,7 +1954,7 @@
6, 79
- 430, 52
+ 418, 52
4
@@ -5940,9 +5943,6 @@ Click "Add" to get started.
AADAPwAAwD8AAMA/AADAPwAA
-
- NoControl
-
MeshCentral Router
@@ -5994,6 +5994,18 @@ Click "Add" to get started.
System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ nameColumnHeader
+
+
+ System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ stateColumnHeader
+
+
+ System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
addMapToolStripMenuItem
@@ -6078,6 +6090,12 @@ Click "Add" to get started.
System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+ chatToolStripMenuItem
+
+
+ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
devicesImageList
@@ -6168,24 +6186,6 @@ Click "Add" to get started.
System.Windows.Forms.SaveFileDialog, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
- chatToolStripMenuItem
-
-
- System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- nameColumnHeader
-
-
- System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
-
- stateColumnHeader
-
-
- System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
MainForm
diff --git a/src/MeshCentralServer.cs b/src/MeshCentralServer.cs
index d5e99e1..887b3e4 100644
--- a/src/MeshCentralServer.cs
+++ b/src/MeshCentralServer.cs
@@ -68,6 +68,7 @@ namespace MeshCentralRouter
public int features = 0; // Bit flags of server features
public int features2 = 0; // Bit flags of server features
public Dictionary serverinfo = null;
+ public Dictionary userinfo = null;
public int connectionState { get { return constate; } }
@@ -206,6 +207,23 @@ namespace MeshCentralRouter
}
}
+ // Return the number of 2nd factor for this account
+ public int CountTwoFactorAuths()
+ {
+ if (userinfo == null) return -1;
+ int authFactorCount = 0;
+ object val;
+ if (userinfo.TryGetValue("otpsecret", out val) && Convert.ToInt32(val) == 1) authFactorCount++;
+ if (userinfo.TryGetValue("otpduo", out val) && Convert.ToInt32(val) == 1) authFactorCount++;
+ if (userinfo.TryGetValue("otpdev", out val) && Convert.ToInt32(val) == 1) authFactorCount++;
+ if (userinfo.TryGetValue("otphkeys", out val) && Convert.ToInt32(val) > 0) authFactorCount += Convert.ToInt32(val);
+ if ((features & 0x00800000) != 0 && userinfo.TryGetValue("otpekey", out val) && Convert.ToInt32(val) == 1) authFactorCount++;
+ if ((features & 0x02000000) != 0 && (features & 0x04000000) != 0 && userinfo.TryGetValue("phone", out val) && val != null) authFactorCount++;
+ if ((features2 & 0x02000000) != 0 && (features2 & 0x04000000) != 0 && userinfo.TryGetValue("msghandle", out val) && val != null) authFactorCount++;
+ if (authFactorCount > 0 && userinfo.TryGetValue("otpkeys", out val) && Convert.ToInt32(val) > 0 && (features2 & 0x40000) == 0) authFactorCount++;
+ return authFactorCount;
+ }
+
public void processServerData(webSocketClient sender, string data, int orglen)
{
if (debug) { try { File.AppendAllText("debug.log", "ServerData-" + data + "\r\n"); } catch (Exception) { } }
@@ -292,7 +310,7 @@ namespace MeshCentralRouter
}
case "userinfo":
{
- Dictionary userinfo = (Dictionary)jsonAction["userinfo"];
+ userinfo = (Dictionary)jsonAction["userinfo"];
userid = (string)userinfo["_id"];
if (userinfo.ContainsKey("name")) { username = (string)userinfo["name"]; }
userRights = new Dictionary();
@@ -308,6 +326,19 @@ namespace MeshCentralRouter
}
}
}
+
+ int twoFactorCount = -1;
+ try { twoFactorCount = CountTwoFactorAuths(); } catch (Exception) { }
+ if (debug) {
+ try { File.AppendAllText("debug.log", "CountTwoFactorAuths-" + twoFactorCount + "\r\n"); } catch (Exception) { }
+ }
+ // If no 2FA is setup and feature flag set, set message and change state
+ if (twoFactorCount == 0 && (features & 0x00040000) != 0)
+ {
+ disconnectMsg = "2fasetuprequired";
+ changeState(0);
+ }
+
break;
}
case "usergroups":
diff --git a/src/Translate.cs b/src/Translate.cs
index b6a4da2..a07744c 100644
--- a/src/Translate.cs
+++ b/src/Translate.cs
@@ -4920,6 +4920,29 @@ namespace MeshCentralRouter
{"it","Avanzamento del trasferimento"},
{"ru","Прогресс передачи"}
}
+ },
+ {
+ "Complete 2FA setup online first",
+ new Dictionary() {
+ {"de","Vervollständigen Sie zunächst die 2FA-Einrichtung online"},
+ {"hi","पहले ऑनलाइन 2FA सेटअप पूरा करें"},
+ {"fr","Terminez d'abord la configuration 2FA en ligne"},
+ {"zh-chs","首先在线完成 2FA 设置"},
+ {"fi","Suorita ensin 2FA-asennus verkossa"},
+ {"tr","Önce çevrimiçi 2FA kurulumunu tamamlayın"},
+ {"cs","Nejprve dokončete nastavení 2FA online"},
+ {"ja","まずオンラインで2FAのセットアップを完了してください"},
+ {"es","Complete primero la configuración de 2FA en línea"},
+ {"pl","Najpierw zakończ konfigurację 2FA online"},
+ {"pt","Primeiro, conclua a configuração do 2FA online"},
+ {"nl","Voltooi eerst de online 2FA-instelling"},
+ {"pt-br","Primeiro, conclua a configuração do 2FA online"},
+ {"sv","Slutför först 2FA-inställningen online"},
+ {"da","Færdiggør først 2FA-opsætningen online"},
+ {"ko","먼저 온라인으로 2FA 설정을 완료하세요."},
+ {"it","Completa prima la configurazione di 2FA online"},
+ {"ru","Сначала завершите настройку 2FA онлайн"}
+ }
}
};
// *** TRANSLATION TABLE END ***