summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--op-mode-definitions/generate-openconnect-user-key.xml.in67
-rwxr-xr-xsrc/op_mode/generate_openconnect_otp_key.py65
2 files changed, 132 insertions, 0 deletions
diff --git a/op-mode-definitions/generate-openconnect-user-key.xml.in b/op-mode-definitions/generate-openconnect-user-key.xml.in
new file mode 100644
index 000000000..80cdfb3d7
--- /dev/null
+++ b/op-mode-definitions/generate-openconnect-user-key.xml.in
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="generate">
+ <children>
+ <node name="openconnect">
+ <properties>
+ <help>Generate OpenConnect client parameters</help>
+ </properties>
+ <children>
+ <tagNode name="username">
+ <properties>
+ <help>Username used for authentication</help>
+ <completionHelp>
+ <list>&lt;username&gt;</list>
+ </completionHelp>
+ </properties>
+ <children>
+ <node name="otp-key">
+ <properties>
+ <help>Generate OpenConnect OTP token</help>
+ </properties>
+ <children>
+ <node name="hotp-time">
+ <properties>
+ <help>HOTP time-based token</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/generate_openconnect_otp_key.py --username "$4" --interval 30 --digits 6</command>
+ <children>
+ <tagNode name="interval">
+ <properties>
+ <help>Duration of single time interval</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/generate_openconnect_otp_key.py --username "$4" --interval "$8" --digits 6</command>
+ <children>
+ <tagNode name="digits">
+ <properties>
+ <help>The number of digits in the one-time password</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/generate_openconnect_otp_key.py --username "$4" --interval "$8" --digits "${10}"</command>
+ </tagNode>
+ </children>
+ </tagNode>
+ <tagNode name="digits">
+ <properties>
+ <help>The number of digits in the one-time password</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/generate_openconnect_otp_key.py --username "$4" --interval 30 --digits "$8"</command>
+ <children>
+ <tagNode name="interval">
+ <properties>
+ <help>Duration of single time interval</help>
+ </properties>
+ <command>sudo ${vyos_op_scripts_dir}/generate_openconnect_otp_key.py --username "$4" --interval "${10}" --digits $8</command>
+ </tagNode>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </tagNode>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/src/op_mode/generate_openconnect_otp_key.py b/src/op_mode/generate_openconnect_otp_key.py
new file mode 100755
index 000000000..363bcf3ea
--- /dev/null
+++ b/src/op_mode/generate_openconnect_otp_key.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2022 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import argparse
+import os
+
+from vyos.util import popen
+from secrets import token_hex
+from base64 import b32encode
+
+if os.geteuid() != 0:
+ exit("You need to have root privileges to run this script.\nPlease try again, this time using 'sudo'. Exiting.")
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-u", "--username", type=str, help='Username used for authentication', required=True)
+ parser.add_argument("-i", "--interval", type=str, help='Duration of single time interval', default="30", required=False)
+ parser.add_argument("-d", "--digits", type=str, help='The number of digits in the one-time password', default="6", required=False)
+ args = parser.parse_args()
+
+ hostname = os.uname()[1]
+ username = args.username
+ digits = args.digits
+ period = args.interval
+
+ # check variables:
+ if int(digits) < 6 or int(digits) > 8:
+ print("")
+ quit("The number of digits in the one-time password must be between '6' and '8'")
+
+ if int(period) < 5 or int(period) > 86400:
+ print("")
+ quit("Time token interval must be between '5' and '86400' seconds")
+
+ # generate OTP key, URL & QR:
+ key_hex = token_hex(20)
+ key_base32 = b32encode(bytes.fromhex(key_hex)).decode()
+
+ otp_url=''.join(["otpauth://totp/",username,"@",hostname,"?secret=",key_base32,"&digits=",digits,"&period=",period])
+ qrcode,err = popen('qrencode -t ansiutf8', input=otp_url)
+
+ print("# You can share it with the user, he just needs to scan the QR in his OTP app")
+ print("# username: ", username)
+ print("# OTP KEY: ", key_base32)
+ print("# OTP URL: ", otp_url)
+ print(qrcode)
+ print('# To add this OTP key to configuration, run the following commands:')
+ print(f"set vpn openconnect authentication local-users username {username} otp key '{key_hex}'")
+ if period != "30":
+ print(f"set vpn openconnect authentication local-users username {username} otp interval '{period}'")
+ if digits != "6":
+ print(f"set vpn openconnect authentication local-users username {username} otp otp-length '{digits}'")