1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-08-02 03:28:28 -04:00

fix(network): authenticate Fortinet VPNs natively (#2959)

* fix(network): authenticate Fortinet VPNs natively

* cleanup and add test

---------

Co-authored-by: Grant Mosha <grant.mosha@nida.go.tz>
Co-authored-by: bbedward <bbedward@gmail.com>
This commit is contained in:
Grant Mosha
2026-07-30 23:45:53 +03:00
committed by GitHub
parent 0033e3f0e0
commit 01832856d4
8 changed files with 649 additions and 94 deletions
+83 -3
View File
@@ -31,6 +31,7 @@ DankModal {
property string promptToken: ""
property string promptReason: ""
property var promptFields: []
property var promptHints: []
property string promptSetting: ""
property bool isVpnPrompt: false
@@ -40,17 +41,21 @@ DankModal {
property var fieldsInfo: []
property var secretValues: ({})
readonly property bool isCertificateChangedPrompt: promptReason === "server-certificate-changed"
readonly property bool isCertificatePrompt: promptReason === "server-certificate" || isCertificateChangedPrompt
readonly property string serverCertificateFingerprint: promptHints.length > 0 ? promptHints[0] : ""
readonly property bool showUsernameField: requiresEnterprise && !isVpnPrompt && fieldsInfo.length === 0
readonly property bool showPasswordField: fieldsInfo.length === 0
readonly property bool showPasswordField: fieldsInfo.length === 0 && !isCertificatePrompt
readonly property bool showAnonField: requiresEnterprise && !isVpnPrompt
readonly property bool showDomainField: requiresEnterprise && !isVpnPrompt
readonly property bool showSavePasswordCheckbox: (isVpnPrompt || fieldsInfo.length > 0) && promptReason !== "pkcs11"
readonly property bool showSavePasswordCheckbox: (isVpnPrompt || fieldsInfo.length > 0) && promptReason !== "pkcs11" && !isCertificatePrompt
readonly property int inputFieldHeight: Theme.fontSizeMedium + Theme.spacingL * 2
readonly property int inputFieldWithSpacing: inputFieldHeight + Theme.spacingM
readonly property int checkboxRowHeight: Theme.fontSizeMedium + Theme.spacingS
readonly property int headerHeight: Theme.fontSizeLarge + Theme.fontSizeMedium + Theme.spacingM * 2
readonly property int buttonRowHeight: 36 + Theme.spacingM
readonly property int certificateWarningHeight: certificateWarningColumn.implicitHeight + Theme.spacingM * 2
property int calculatedHeight: {
let h = headerHeight + buttonRowHeight + Theme.spacingL * 2;
@@ -67,10 +72,16 @@ DankModal {
h += inputFieldWithSpacing;
if (showSavePasswordCheckbox)
h += checkboxRowHeight;
if (isCertificatePrompt)
h += certificateWarningHeight + Theme.spacingM;
return h;
}
function focusFirstField() {
if (isCertificatePrompt) {
connectButton.forceActiveFocus();
return;
}
if (fieldsInfo.length > 0) {
if (dynamicFieldsRepeater.count > 0) {
const firstItem = dynamicFieldsRepeater.itemAt(0);
@@ -101,6 +112,7 @@ DankModal {
promptToken = "";
promptReason = "";
promptFields = [];
promptHints = [];
promptSetting = "";
isVpnPrompt = false;
connectionName = "";
@@ -127,6 +139,7 @@ DankModal {
promptToken = "";
promptReason = "";
promptFields = [];
promptHints = [];
promptSetting = "";
isVpnPrompt = false;
connectionName = "";
@@ -145,6 +158,7 @@ DankModal {
promptToken = token;
promptReason = reason;
promptFields = fields || [];
promptHints = hints || [];
promptSetting = setting || "802-11-wireless-security";
connectionType = connType || "802-11-wireless";
connectionName = connName || ssid || "";
@@ -324,6 +338,8 @@ DankModal {
text: {
if (promptReason === "pkcs11")
return I18n.tr("Smartcard Authentication");
if (isCertificatePrompt)
return I18n.tr("Untrusted VPN certificate", "Title for VPN server certificate trust confirmation");
if (isVpnPrompt)
return I18n.tr("Connect to VPN");
if (isHiddenNetwork)
@@ -343,6 +359,8 @@ DankModal {
text: {
if (promptReason === "pkcs11")
return I18n.tr("Enter PIN for ") + wifiPasswordSSID;
if (isCertificatePrompt)
return wifiPasswordSSID;
if (fieldsInfo.length > 0)
return I18n.tr("Enter credentials for ") + wifiPasswordSSID;
if (isVpnPrompt)
@@ -383,6 +401,45 @@ DankModal {
}
}
Rectangle {
id: certificateWarningBox
readonly property color warningTone: isCertificateChangedPrompt ? Theme.error : Theme.warning
width: parent.width
height: certificateWarningHeight
radius: Theme.cornerRadius
color: Theme.withAlpha(warningTone, 0.12)
border.color: Theme.withAlpha(warningTone, 0.5)
border.width: 1
visible: isCertificatePrompt
Column {
id: certificateWarningColumn
anchors.fill: parent
anchors.margins: Theme.spacingM
spacing: Theme.spacingS
StyledText {
width: parent.width
text: isCertificateChangedPrompt ? I18n.tr("The server certificate has changed since it was last trusted. Only continue if you recognize the new fingerprint.", "Warning shown when a trusted VPN server certificate no longer matches") : I18n.tr("Only continue if you recognize this server certificate fingerprint.", "Warning shown before trusting an unverified VPN server certificate")
wrapMode: Text.Wrap
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceText
}
StyledText {
width: parent.width
text: serverCertificateFingerprint
wrapMode: Text.WrapAnywhere
font.family: SettingsData.monoFontFamily
font.pixelSize: Theme.fontSizeSmall
color: certificateWarningBox.warningTone
}
}
}
Rectangle {
width: parent.width
height: inputFieldHeight
@@ -690,10 +747,15 @@ DankModal {
}
Rectangle {
id: connectButton
width: Math.max(80, connectText.contentWidth + Theme.spacingM * 2)
height: 36
radius: Theme.cornerRadius
color: connectArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
border.color: activeFocus ? Theme.surfaceText : "transparent"
border.width: activeFocus ? 2 : 0
activeFocusOnTab: true
enabled: {
if (fieldsInfo.length > 0) {
for (var i = 0; i < fieldsInfo.length; i++) {
@@ -705,6 +767,8 @@ DankModal {
}
return true;
}
if (isCertificatePrompt)
return serverCertificateFingerprint.length > 0;
if (isVpnPrompt)
return passwordInput.text.length > 0;
if (isHiddenNetwork)
@@ -716,7 +780,7 @@ DankModal {
StyledText {
id: connectText
anchors.centerIn: parent
text: I18n.tr("Connect")
text: isCertificatePrompt ? I18n.tr("Trust", "Button that approves a VPN server certificate fingerprint") : I18n.tr("Connect")
font.pixelSize: Theme.fontSizeMedium
color: Theme.background
font.weight: Font.Medium
@@ -731,6 +795,22 @@ DankModal {
onClicked: submitCredentialsAndClose()
}
Keys.onReturnPressed: event => {
if (enabled)
submitCredentialsAndClose();
event.accepted = true;
}
Keys.onEnterPressed: event => {
if (enabled)
submitCredentialsAndClose();
event.accepted = true;
}
Keys.onSpacePressed: event => {
if (enabled)
submitCredentialsAndClose();
event.accepted = true;
}
Behavior on color {
ColorAnimation {
duration: Theme.shortDuration