mirror of
https://github.com/token2/fido2-manage.git
synced 2026-04-09 18:55:38 +00:00
Add terminal support for other than x-terminal-emulator
This gets the terminal from which `gui.py` is executed and saves it into the global `TERM` variable. Defaults to `x-terminal-emulator`. Also autoformats the imports and code via black.
This commit is contained in:
330
gui.py
330
gui.py
@@ -1,106 +1,129 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk, messagebox, simpledialog
|
from tkinter import messagebox, simpledialog, ttk
|
||||||
import re
|
|
||||||
|
|
||||||
# Define the command to execute
|
# Define the command to execute
|
||||||
FIDO_COMMAND = './fido2-manage.sh'
|
FIDO_COMMAND = "./fido2-manage.sh"
|
||||||
#Command below for Windows
|
|
||||||
#FIDO_COMMAND = 'fido2-manage-ui.exe'
|
# Checks the terminal emulator from which "gui.py" is executed
|
||||||
|
# and sets it for the subprocess commands
|
||||||
|
TERM = os.environ.get("TERM", "x-terminal-emulator")
|
||||||
|
|
||||||
|
# Command below for Windows
|
||||||
|
# FIDO_COMMAND = 'fido2-manage-ui.exe'
|
||||||
# Global variable to store the PIN
|
# Global variable to store the PIN
|
||||||
pin = None
|
PIN = None
|
||||||
|
|
||||||
|
|
||||||
# Function to get device list from fido2-manage-ui.exe
|
# Function to get device list from fido2-manage-ui.exe
|
||||||
def get_device_list():
|
def get_device_list():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Execute the command with '-list' argument and capture the output
|
# Execute the command with '-list' argument and capture the output
|
||||||
result = subprocess.run([FIDO_COMMAND, '-list'], capture_output=True, text=True)
|
result = subprocess.run([FIDO_COMMAND, "-list"], capture_output=True, text=True)
|
||||||
# Split the output into lines and return as a list
|
# Split the output into lines and return as a list
|
||||||
device_list = result.stdout.strip().split('\n')
|
device_list = result.stdout.strip().split("\n")
|
||||||
|
|
||||||
return device_list
|
return device_list
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Handle exceptions (e.g., file not found or command error)
|
# Handle exceptions (e.g., file not found or command error)
|
||||||
print(f"Error executing device list command: {e}")
|
print(f"Error executing device list command: {e}")
|
||||||
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
# Function to execute storage command and prepend its output to the grid
|
# Function to execute storage command and prepend its output to the grid
|
||||||
def execute_storage_command(device_digit):
|
def execute_storage_command(device_digit):
|
||||||
global pin
|
global PIN
|
||||||
command = [FIDO_COMMAND, '-storage', '-pin', pin, '-device', device_digit]
|
command = [FIDO_COMMAND, "-storage", "-pin", PIN, "-device", device_digit]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(command, capture_output=True, text=True)
|
result = subprocess.run(command, capture_output=True, text=True)
|
||||||
# Check if the subprocess was executed successfully
|
# Check if the subprocess was executed successfully
|
||||||
#print (result)
|
# print (result)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
# Parse the output and insert into the treeview
|
# Parse the output and insert into the treeview
|
||||||
for line in reversed(result.stdout.splitlines()): # Insert in reversed order to prepend
|
for line in reversed(
|
||||||
|
result.stdout.splitlines()
|
||||||
|
): # Insert in reversed order to prepend
|
||||||
if ": " in line:
|
if ": " in line:
|
||||||
key, value = line.split(": ", 1)
|
key, value = line.split(": ", 1)
|
||||||
tree.insert("", 0, values=(key, value)) # Insert at the top of the grid
|
tree.insert(
|
||||||
|
"", 0, values=(key, value)
|
||||||
|
) # Insert at the top of the grid
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise subprocess.CalledProcessError(result.returncode, command)
|
raise subprocess.CalledProcessError(result.returncode, command)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
messagebox.showerror("Error", f"Command execution failed: {e}\nOutput: {result.stderr}")
|
messagebox.showerror(
|
||||||
|
"Error", f"Command execution failed: {e}\nOutput: {result.stderr}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Function to execute info command and append its output to the grid
|
# Function to execute info command and append its output to the grid
|
||||||
def execute_info_command(device_digit):
|
def execute_info_command(device_digit):
|
||||||
global pin
|
global PIN
|
||||||
tree.delete(*tree.get_children())
|
tree.delete(*tree.get_children())
|
||||||
command = [FIDO_COMMAND, '-storage', '-pin', pin, '-device', device_digit]
|
command = [FIDO_COMMAND, "-storage", "-pin", PIN, "-device", device_digit]
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(command, capture_output=True, text=True)
|
result = subprocess.run(command, capture_output=True, text=True)
|
||||||
|
|
||||||
if result.stderr.find("FIDO_ERR_PIN_INVALID")!= -1:
|
if result.stderr.find("FIDO_ERR_PIN_INVALID") != -1:
|
||||||
#exit
|
# exit
|
||||||
messagebox.showerror("Error", f"Invalid PIN provided")
|
messagebox.showerror("Error", f"Invalid PIN provided")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check FIDO_ERR_PIN_AUTH_BLOCKED
|
# Check FIDO_ERR_PIN_AUTH_BLOCKED
|
||||||
if result.stderr.find("FIDO_ERR_PIN_AUTH_BLOCKED")!= -1:
|
if result.stderr.find("FIDO_ERR_PIN_AUTH_BLOCKED") != -1:
|
||||||
#exit
|
# exit
|
||||||
messagebox.showerror("Error", f"Wrong PIN provided to many times. Reinsert the key")
|
messagebox.showerror(
|
||||||
|
"Error", f"Wrong PIN provided to many times. Reinsert the key"
|
||||||
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Check FIDO_ERR_PIN_REQUIRED
|
# Check FIDO_ERR_PIN_REQUIRED
|
||||||
if result.stderr.find("FIDO_ERR_PIN_REQUIRED")!= -1:
|
if result.stderr.find("FIDO_ERR_PIN_REQUIRED") != -1:
|
||||||
#exit
|
# exit
|
||||||
messagebox.showerror("Error", f"No PIN set for this key. Passkeys can be managed only with a PIN set. You will be prompted to create a PIN on the next window")
|
messagebox.showerror(
|
||||||
command = [FIDO_COMMAND, '-setPIN', '-device', device_digit]
|
"Error",
|
||||||
if sys.platform.startswith('win'):
|
f"No PIN set for this key. Passkeys can be managed only with a PIN set. You will be prompted to create a PIN on the next window",
|
||||||
subprocess.Popen(['start', 'cmd', '/c'] + command, shell=True)
|
)
|
||||||
elif sys.platform.startswith('linux'):
|
command = [FIDO_COMMAND, "-setPIN", "-device", device_digit]
|
||||||
subprocess.Popen(['x-terminal-emulator', '-e'] + command)
|
if sys.platform.startswith("win"):
|
||||||
|
subprocess.Popen(["start", "cmd", "/c"] + command, shell=True)
|
||||||
|
elif sys.platform.startswith("linux"):
|
||||||
|
subprocess.Popen([TERM, "-e"] + command)
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Check FIDO version
|
||||||
|
if result.stderr.find("FIDO_ERR_INVALID_CBOR") != -1:
|
||||||
|
# exit
|
||||||
|
messagebox.showerror(
|
||||||
|
"Error",
|
||||||
|
f"This is an older key (probably FIDO2.0). No passkey management is possible with this key. Only basic information will be shown.",
|
||||||
|
)
|
||||||
|
|
||||||
# Check FIDO version
|
|
||||||
if result.stderr.find("FIDO_ERR_INVALID_CBOR")!= -1:
|
|
||||||
#exit
|
|
||||||
messagebox.showerror("Error", f"This is an older key (probably FIDO2.0). No passkey management is possible with this key. Only basic information will be shown.")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Check if the subprocess was executed successfully
|
# Check if the subprocess was executed successfully
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
# Parse the output and insert into the treeview
|
# Parse the output and insert into the treeview
|
||||||
for line in result.stdout.splitlines():
|
for line in result.stdout.splitlines():
|
||||||
if ": " in line:
|
if ": " in line:
|
||||||
key, value = line.split(": ", 1)
|
key, value = line.split(": ", 1)
|
||||||
tree.insert("", tk.END, values=(key, value)) # Append to the end of the grid
|
tree.insert(
|
||||||
|
"", tk.END, values=(key, value)
|
||||||
|
) # Append to the end of the grid
|
||||||
else:
|
else:
|
||||||
raise subprocess.CalledProcessError(result.returncode, command)
|
raise subprocess.CalledProcessError(result.returncode, command)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
messagebox.showerror("Error", f"Command execution failed: {e}\nOutput: {result.stderr}")
|
messagebox.showerror(
|
||||||
command = [FIDO_COMMAND, '-info', '-pin', pin, '-device', device_digit]
|
"Error", f"Command execution failed: {e}\nOutput: {result.stderr}"
|
||||||
|
)
|
||||||
|
command = [FIDO_COMMAND, "-info", "-pin", PIN, "-device", device_digit]
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(command, capture_output=True, text=True)
|
result = subprocess.run(command, capture_output=True, text=True)
|
||||||
# Check if the subprocess was executed successfully
|
# Check if the subprocess was executed successfully
|
||||||
@@ -109,46 +132,52 @@ def execute_info_command(device_digit):
|
|||||||
for line in result.stdout.splitlines():
|
for line in result.stdout.splitlines():
|
||||||
if ": " in line:
|
if ": " in line:
|
||||||
key, value = line.split(": ", 1)
|
key, value = line.split(": ", 1)
|
||||||
tree.insert("", tk.END, values=(key, value)) # Append to the end of the grid
|
tree.insert(
|
||||||
|
"", tk.END, values=(key, value)
|
||||||
|
) # Append to the end of the grid
|
||||||
else:
|
else:
|
||||||
raise subprocess.CalledProcessError(result.returncode, command)
|
raise subprocess.CalledProcessError(result.returncode, command)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
messagebox.showerror("Error", f"Command execution failed: {e}\nOutput: {result.stderr}")
|
messagebox.showerror(
|
||||||
|
"Error", f"Command execution failed: {e}\nOutput: {result.stderr}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Function to set the PIN
|
# Function to set the PIN
|
||||||
def set_pin():
|
def set_pin():
|
||||||
global pin
|
global PIN
|
||||||
pin = simpledialog.askstring("PIN Code", "Enter PIN code (enter 0000 if no PIN is set/known):", show='*')
|
PIN = simpledialog.askstring(
|
||||||
|
"PIN Code", "Enter PIN code (enter 0000 if no PIN is set/known):", show="*"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Function to handle selection event
|
# Function to handle selection event
|
||||||
def on_device_selected(event):
|
def on_device_selected(event):
|
||||||
global pin
|
global PIN
|
||||||
selected_device = device_var.get()
|
selected_device = device_var.get()
|
||||||
# Extract the digit inside the first pair of square brackets
|
# Extract the digit inside the first pair of square brackets
|
||||||
match = re.search(r'\[(\d+)\]', selected_device)
|
match = re.search(r"\[(\d+)\]", selected_device)
|
||||||
pin = None
|
PIN = None
|
||||||
|
|
||||||
set_pin()
|
set_pin()
|
||||||
#print (pin)
|
# print (pin)
|
||||||
if match:
|
if match:
|
||||||
device_digit = match.group(1)
|
device_digit = match.group(1)
|
||||||
|
|
||||||
if pin is not None:
|
if PIN is not None:
|
||||||
execute_info_command(device_digit)
|
execute_info_command(device_digit)
|
||||||
check_passkeys_button_state()
|
check_passkeys_button_state()
|
||||||
check_changepin_button_state()
|
check_changepin_button_state()
|
||||||
else:
|
else:
|
||||||
messagebox.showinfo("Device Selected", "No digit found in the selected device")
|
messagebox.showinfo("Device Selected", "No digit found in the selected device")
|
||||||
|
|
||||||
|
|
||||||
# Function to check if the "passkeys" button should be enabled
|
# Function to check if the "passkeys" button should be enabled
|
||||||
def check_passkeys_button_state():
|
def check_passkeys_button_state():
|
||||||
passkeys_button_state = tk.DISABLED
|
passkeys_button_state = tk.DISABLED
|
||||||
for child in tree.get_children():
|
for child in tree.get_children():
|
||||||
values = tree.item(child, 'values')
|
values = tree.item(child, "values")
|
||||||
if values and len(values) == 2 and values[0] == 'existing rk(s)':
|
if values and len(values) == 2 and values[0] == "existing rk(s)":
|
||||||
try:
|
try:
|
||||||
rk_count = int(values[1])
|
rk_count = int(values[1])
|
||||||
if rk_count > 0:
|
if rk_count > 0:
|
||||||
@@ -156,7 +185,7 @@ def check_passkeys_button_state():
|
|||||||
break
|
break
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
passkeys_button.config(state=passkeys_button_state)
|
passkeys_button.config(state=passkeys_button_state)
|
||||||
|
|
||||||
|
|
||||||
@@ -164,8 +193,8 @@ def check_passkeys_button_state():
|
|||||||
def check_changepin_button_state():
|
def check_changepin_button_state():
|
||||||
passkeys_button_state = tk.DISABLED
|
passkeys_button_state = tk.DISABLED
|
||||||
for child in tree.get_children():
|
for child in tree.get_children():
|
||||||
values = tree.item(child, 'values')
|
values = tree.item(child, "values")
|
||||||
if values and len(values) == 2 and values[0] == 'remaining rk(s)':
|
if values and len(values) == 2 and values[0] == "remaining rk(s)":
|
||||||
try:
|
try:
|
||||||
rk_count = int(values[1])
|
rk_count = int(values[1])
|
||||||
if rk_count > 0:
|
if rk_count > 0:
|
||||||
@@ -173,47 +202,65 @@ def check_changepin_button_state():
|
|||||||
break
|
break
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
change_pin_button.config(state=passkeys_button_state)
|
change_pin_button.config(state=passkeys_button_state)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Function to handle "passkeys" button click
|
# Function to handle "passkeys" button click
|
||||||
def on_passkeys_button_click():
|
def on_passkeys_button_click():
|
||||||
global pin
|
global PIN
|
||||||
# Get the selected device and PIN
|
# Get the selected device and PIN
|
||||||
selected_device = device_var.get()
|
selected_device = device_var.get()
|
||||||
match = re.search(r'\[(\d+)\]', selected_device)
|
match = re.search(r"\[(\d+)\]", selected_device)
|
||||||
if match:
|
if match:
|
||||||
device_digit = match.group(1)
|
device_digit = match.group(1)
|
||||||
#pin = simpledialog.askstring("PIN Code", "Enter PIN code (enter 0000 if no PIN is set/known):", show='*')
|
# pin = simpledialog.askstring("PIN Code", "Enter PIN code (enter 0000 if no PIN is set/known):", show='*')
|
||||||
if pin is not None:
|
if PIN is not None:
|
||||||
# Execute the command to get resident keys
|
# Execute the command to get resident keys
|
||||||
command = [FIDO_COMMAND, '-residentKeys', '-pin', pin, '-device', device_digit]
|
command = [
|
||||||
|
FIDO_COMMAND,
|
||||||
|
"-residentKeys",
|
||||||
|
"-pin",
|
||||||
|
PIN,
|
||||||
|
"-device",
|
||||||
|
device_digit,
|
||||||
|
]
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(command, capture_output=True, text=True)
|
result = subprocess.run(command, capture_output=True, text=True)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
# Parse the domains from the output
|
# Parse the domains from the output
|
||||||
domains = []
|
domains = []
|
||||||
for line in result.stdout.splitlines():
|
for line in result.stdout.splitlines():
|
||||||
match = re.search(r'= (.+)$', line)
|
match = re.search(r"= (.+)$", line)
|
||||||
if match:
|
if match:
|
||||||
domains.append(match.group(1))
|
domains.append(match.group(1))
|
||||||
|
|
||||||
# Execute the command for each domain
|
# Execute the command for each domain
|
||||||
cumulated_output = []
|
cumulated_output = []
|
||||||
for domain in domains:
|
for domain in domains:
|
||||||
|
|
||||||
domain_command = [FIDO_COMMAND, '-residentKeys', '-domain', domain, '-pin', pin, '-device', device_digit]
|
domain_command = [
|
||||||
domain_result = subprocess.run(domain_command, capture_output=True, text=True)
|
FIDO_COMMAND,
|
||||||
|
"-residentKeys",
|
||||||
|
"-domain",
|
||||||
|
domain,
|
||||||
|
"-pin",
|
||||||
|
PIN,
|
||||||
|
"-device",
|
||||||
|
device_digit,
|
||||||
|
]
|
||||||
|
domain_result = subprocess.run(
|
||||||
|
domain_command, capture_output=True, text=True
|
||||||
|
)
|
||||||
|
|
||||||
if domain_result.returncode == 0:
|
if domain_result.returncode == 0:
|
||||||
cumulated_output.append(f"Domain: {domain}\n{domain_result.stdout}")
|
cumulated_output.append(
|
||||||
|
f"Domain: {domain}\n{domain_result.stdout}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise subprocess.CalledProcessError(domain_result.returncode, domain_command)
|
raise subprocess.CalledProcessError(
|
||||||
|
domain_result.returncode, domain_command
|
||||||
|
)
|
||||||
|
|
||||||
# Show the cumulated output in a new window
|
# Show the cumulated output in a new window
|
||||||
cumulated_output_str = "\n\n".join(cumulated_output)
|
cumulated_output_str = "\n\n".join(cumulated_output)
|
||||||
@@ -221,30 +268,29 @@ def on_passkeys_button_click():
|
|||||||
else:
|
else:
|
||||||
raise subprocess.CalledProcessError(result.returncode, command)
|
raise subprocess.CalledProcessError(result.returncode, command)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
messagebox.showerror("Error", f"Command execution failed: {e}\nOutput: {result.stderr}")
|
messagebox.showerror(
|
||||||
|
"Error", f"Command execution failed: {e}\nOutput: {result.stderr}"
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
messagebox.showinfo("Device Selected", "No digit found in the selected device")
|
messagebox.showinfo("Device Selected", "No digit found in the selected device")
|
||||||
|
|
||||||
|
|
||||||
def change_pin():
|
def change_pin():
|
||||||
# Get the selected device and PIN
|
# Get the selected device and PIN
|
||||||
selected_device = device_var.get()
|
selected_device = device_var.get()
|
||||||
# Extract the digit inside the first pair of square brackets
|
# Extract the digit inside the first pair of square brackets
|
||||||
match = re.search(r'\[(\d+)\]', selected_device)
|
match = re.search(r"\[(\d+)\]", selected_device)
|
||||||
if match:
|
if match:
|
||||||
device_digit = match.group(1)
|
device_digit = match.group(1)
|
||||||
command = [FIDO_COMMAND, '-changePIN', '-device', device_digit]
|
command = [FIDO_COMMAND, "-changePIN", "-device", device_digit]
|
||||||
if sys.platform.startswith('win'):
|
if sys.platform.startswith("win"):
|
||||||
subprocess.Popen(['start', 'cmd', '/c'] + command, shell=True)
|
subprocess.Popen(["start", "cmd", "/c"] + command, shell=True)
|
||||||
elif sys.platform.startswith('linux'):
|
elif sys.platform.startswith("linux"):
|
||||||
subprocess.Popen(['x-terminal-emulator', '-e'] + command)
|
subprocess.Popen([TERM, "-e"] + command)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def refresh_combobox():
|
def refresh_combobox():
|
||||||
# Implement your refresh logic here
|
# Implement your refresh logic here
|
||||||
# For example, you can update the values in the combobox
|
# For example, you can update the values in the combobox
|
||||||
@@ -253,14 +299,13 @@ def refresh_combobox():
|
|||||||
tree.delete(*tree.get_children())
|
tree.delete(*tree.get_children())
|
||||||
passkeys_button.config(state=tk.DISABLED)
|
passkeys_button.config(state=tk.DISABLED)
|
||||||
change_pin_button.config(state=tk.DISABLED)
|
change_pin_button.config(state=tk.DISABLED)
|
||||||
device_list = get_device_list() # Assuming you have a function to get the device list
|
device_list = (
|
||||||
|
get_device_list()
|
||||||
|
) # Assuming you have a function to get the device list
|
||||||
if not device_list:
|
if not device_list:
|
||||||
print("No devices found.")
|
print("No devices found.")
|
||||||
device_combobox['values'] = device_list # Update the combobox values
|
device_combobox["values"] = device_list # Update the combobox values
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Function to show the output in a new window
|
# Function to show the output in a new window
|
||||||
def show_output_in_new_window(output, device_digit):
|
def show_output_in_new_window(output, device_digit):
|
||||||
@@ -270,7 +315,9 @@ def show_output_in_new_window(output, device_digit):
|
|||||||
new_window.title("Resident Keys / Passkeys")
|
new_window.title("Resident Keys / Passkeys")
|
||||||
|
|
||||||
# Create a Treeview widget for displaying output
|
# Create a Treeview widget for displaying output
|
||||||
tree_new_window = ttk.Treeview(new_window, columns=("Domain", "Credential ID", "User"), show="headings")
|
tree_new_window = ttk.Treeview(
|
||||||
|
new_window, columns=("Domain", "Credential ID", "User"), show="headings"
|
||||||
|
)
|
||||||
# Set column headings
|
# Set column headings
|
||||||
tree_new_window.heading("Domain", text="Domain")
|
tree_new_window.heading("Domain", text="Domain")
|
||||||
tree_new_window.heading("Credential ID", text="Credential ID")
|
tree_new_window.heading("Credential ID", text="Credential ID")
|
||||||
@@ -278,10 +325,14 @@ def show_output_in_new_window(output, device_digit):
|
|||||||
tree_new_window.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
|
tree_new_window.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
|
||||||
|
|
||||||
# Add scrollbars to the Treeview
|
# Add scrollbars to the Treeview
|
||||||
tree_scrollbar_y = ttk.Scrollbar(new_window, orient="vertical", command=tree_new_window.yview)
|
tree_scrollbar_y = ttk.Scrollbar(
|
||||||
|
new_window, orient="vertical", command=tree_new_window.yview
|
||||||
|
)
|
||||||
tree_scrollbar_y.pack(side="right", fill="y")
|
tree_scrollbar_y.pack(side="right", fill="y")
|
||||||
tree_new_window.configure(yscrollcommand=tree_scrollbar_y.set)
|
tree_new_window.configure(yscrollcommand=tree_scrollbar_y.set)
|
||||||
tree_scrollbar_x = ttk.Scrollbar(new_window, orient="horizontal", command=tree_new_window.xview)
|
tree_scrollbar_x = ttk.Scrollbar(
|
||||||
|
new_window, orient="horizontal", command=tree_new_window.xview
|
||||||
|
)
|
||||||
tree_scrollbar_x.pack(side="bottom", fill="x")
|
tree_scrollbar_x.pack(side="bottom", fill="x")
|
||||||
tree_new_window.configure(xscrollcommand=tree_scrollbar_x.set)
|
tree_new_window.configure(xscrollcommand=tree_scrollbar_x.set)
|
||||||
|
|
||||||
@@ -294,31 +345,44 @@ def show_output_in_new_window(output, device_digit):
|
|||||||
credential_id = line.split("Credential ID: ")[1].split(",")[0].strip()
|
credential_id = line.split("Credential ID: ")[1].split(",")[0].strip()
|
||||||
user = line.split("User: ")[1].strip()
|
user = line.split("User: ")[1].strip()
|
||||||
user = re.sub(re.escape(credential_id), "", user).strip()
|
user = re.sub(re.escape(credential_id), "", user).strip()
|
||||||
tree_new_window.insert("", tk.END, values=(current_domain, credential_id, user))
|
tree_new_window.insert(
|
||||||
|
"", tk.END, values=(current_domain, credential_id, user)
|
||||||
|
)
|
||||||
|
|
||||||
# Function to handle show value button click
|
# Function to handle show value button click
|
||||||
def show_selected_value():
|
def show_selected_value():
|
||||||
selected_item = tree_new_window.selection()
|
selected_item = tree_new_window.selection()
|
||||||
if selected_item:
|
if selected_item:
|
||||||
value = tree_new_window.item(selected_item, 'values')[1] # Get the Credential ID of the selected item
|
value = tree_new_window.item(selected_item, "values")[
|
||||||
|
1
|
||||||
|
] # Get the Credential ID of the selected item
|
||||||
new_window.destroy()
|
new_window.destroy()
|
||||||
command = [FIDO_COMMAND, '-delete', '-device', device_digit, '-credential', value]
|
command = [
|
||||||
if sys.platform.startswith('win'):
|
FIDO_COMMAND,
|
||||||
subprocess.Popen(['start', 'cmd', '/c'] + command, shell=True)
|
"-delete",
|
||||||
elif sys.platform.startswith('linux'):
|
"-device",
|
||||||
subprocess.Popen(['x-terminal-emulator', '-e'] + command)
|
device_digit,
|
||||||
|
"-credential",
|
||||||
|
value,
|
||||||
|
]
|
||||||
|
if sys.platform.startswith("win"):
|
||||||
|
subprocess.Popen(["start", "cmd", "/c"] + command, shell=True)
|
||||||
|
elif sys.platform.startswith("linux"):
|
||||||
|
subprocess.Popen([TERM, "-e"] + command)
|
||||||
|
|
||||||
# Create the "Show Value" button
|
# Create the "Show Value" button
|
||||||
show_value_button = tk.Button(new_window, text="delete passkey", command=show_selected_value)
|
show_value_button = tk.Button(
|
||||||
|
new_window, text="delete passkey", command=show_selected_value
|
||||||
|
)
|
||||||
show_value_button.pack(pady=10)
|
show_value_button.pack(pady=10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def show_about_message():
|
def show_about_message():
|
||||||
messagebox.showinfo("About", "The FIDO2.1 Security Key Management Tool is a utility designed to manage and interact with FIDO2.1 security keys.\r\nIt provides functionalities to view information, manage relying parties, and perform various operations on connected FIDO2.1 devices.\r\n\r\n(c)TOKEN2 Sarl\r\nVersoix, Switzerland")
|
messagebox.showinfo(
|
||||||
|
"About",
|
||||||
|
"The FIDO2.1 Security Key Management Tool is a utility designed to manage and interact with FIDO2.1 security keys.\r\nIt provides functionalities to view information, manage relying parties, and perform various operations on connected FIDO2.1 devices.\r\n\r\n(c)TOKEN2 Sarl\r\nVersoix, Switzerland",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Create the main application window
|
# Create the main application window
|
||||||
root = tk.Tk()
|
root = tk.Tk()
|
||||||
@@ -338,7 +402,9 @@ device_list = get_device_list()
|
|||||||
if not device_list:
|
if not device_list:
|
||||||
device_list = "No devices found."
|
device_list = "No devices found."
|
||||||
device_var = tk.StringVar()
|
device_var = tk.StringVar()
|
||||||
device_combobox = ttk.Combobox(top_frame, textvariable=device_var, values=device_list, width=60)
|
device_combobox = ttk.Combobox(
|
||||||
|
top_frame, textvariable=device_var, values=device_list, width=60
|
||||||
|
)
|
||||||
device_combobox.pack(side=tk.LEFT, padx=10, pady=10)
|
device_combobox.pack(side=tk.LEFT, padx=10, pady=10)
|
||||||
device_combobox.bind("<<ComboboxSelected>>", on_device_selected)
|
device_combobox.bind("<<ComboboxSelected>>", on_device_selected)
|
||||||
# Create the refresh button
|
# Create the refresh button
|
||||||
@@ -351,7 +417,13 @@ tree_frame = ttk.Frame(root)
|
|||||||
tree_frame.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
|
tree_frame.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)
|
||||||
tree_scrollbar_y = ttk.Scrollbar(tree_frame, orient="vertical")
|
tree_scrollbar_y = ttk.Scrollbar(tree_frame, orient="vertical")
|
||||||
tree_scrollbar_x = ttk.Scrollbar(tree_frame, orient="horizontal")
|
tree_scrollbar_x = ttk.Scrollbar(tree_frame, orient="horizontal")
|
||||||
tree = ttk.Treeview(tree_frame, columns=("Key", "Value"), show="headings", yscrollcommand=tree_scrollbar_y.set, xscrollcommand=tree_scrollbar_x.set)
|
tree = ttk.Treeview(
|
||||||
|
tree_frame,
|
||||||
|
columns=("Key", "Value"),
|
||||||
|
show="headings",
|
||||||
|
yscrollcommand=tree_scrollbar_y.set,
|
||||||
|
xscrollcommand=tree_scrollbar_x.set,
|
||||||
|
)
|
||||||
tree_scrollbar_y.config(command=tree.yview)
|
tree_scrollbar_y.config(command=tree.yview)
|
||||||
tree_scrollbar_x.config(command=tree.xview)
|
tree_scrollbar_x.config(command=tree.xview)
|
||||||
tree_scrollbar_y.pack(side="right", fill="y")
|
tree_scrollbar_y.pack(side="right", fill="y")
|
||||||
@@ -362,21 +434,21 @@ tree.heading("Value", text="Value")
|
|||||||
tree.pack(expand=True, fill=tk.BOTH)
|
tree.pack(expand=True, fill=tk.BOTH)
|
||||||
|
|
||||||
# Create the "passkeys" button
|
# Create the "passkeys" button
|
||||||
passkeys_button = ttk.Button(root, text="Passkeys", state=tk.DISABLED, command=on_passkeys_button_click)
|
passkeys_button = ttk.Button(
|
||||||
|
root, text="Passkeys", state=tk.DISABLED, command=on_passkeys_button_click
|
||||||
|
)
|
||||||
passkeys_button.pack(side=tk.LEFT, padx=5, pady=10)
|
passkeys_button.pack(side=tk.LEFT, padx=5, pady=10)
|
||||||
|
|
||||||
# Create the "Change PIN" button
|
# Create the "Change PIN" button
|
||||||
change_pin_button = ttk.Button(root, text="Change PIN", state=tk.DISABLED, command=change_pin)
|
change_pin_button = ttk.Button(
|
||||||
|
root, text="Change PIN", state=tk.DISABLED, command=change_pin
|
||||||
|
)
|
||||||
change_pin_button.pack(side=tk.LEFT, padx=5, pady=10)
|
change_pin_button.pack(side=tk.LEFT, padx=5, pady=10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
about_button = ttk.Button(root, text="About", command=show_about_message)
|
about_button = ttk.Button(root, text="About", command=show_about_message)
|
||||||
about_button.pack(side=tk.RIGHT, padx=5, pady=10)
|
about_button.pack(side=tk.RIGHT, padx=5, pady=10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Run the Tkinter main loop
|
# Run the Tkinter main loop
|
||||||
root.mainloop()
|
root.mainloop()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user