From a4474cec96c62725397a5a5ee1473f16aac70ed4 Mon Sep 17 00:00:00 2001 From: Siddesh Devarakonda Date: Wed, 20 Dec 2023 14:32:55 +0530 Subject: [PATCH 1/8] TOML Changes --- ui/components/software/gdm.py | 15 ++++++++++++--- ui/components/software/time_sync.py | 24 +++++++++++++++++++----- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/ui/components/software/gdm.py b/ui/components/software/gdm.py index a34faa0..9fedf06 100644 --- a/ui/components/software/gdm.py +++ b/ui/components/software/gdm.py @@ -43,9 +43,9 @@ def init_ui(self): hlayout = QHBoxLayout() # Lock on Idle Label - self.lockon_lable = QLabel('Lock on Idle(seconds)') - self.lockon_lable.setToolTip(self.gdm_tooltip['lock_on_idle']) - self.lockon_lable.setProperty('class', 'normal-label-for') + self.lockon_lable = QCheckBox('Enable Lock on Idle (seconds): ') + self.lockon_lable.setToolTip(self.gdm_tooltip['enable_lock_on_idle']) + self.lockon_lable.stateChanged.connect(self.enable_lock_on_idle_changed) self.time_input = QLineEdit() self.time_input.setText(str(self.toml_gdm['lock_on_idle'])) @@ -70,6 +70,7 @@ def init_ui(self): def refresh_config(self, config): self.config = config self.toml_gdm = self.config['gdm'] + self.lockon_lable.setChecked(self.toml_gdm['enable_lock_on_idle']) for name, state in self.toml_gdm.items(): if name == 'lock_on_idle': continue @@ -100,4 +101,12 @@ def time_changed(self, new_size): self.toml_gdm['lock_on_idle'] = int(new_size) else: self.time_input.setText('0') + config_file.write(self.config) + + def enable_lock_on_idle_changed(self, state): + self.toml_gdm['enable_lock_on_idle'] = (state == 2) + if state == 2: + self.time_input.setEnabled(True) + else: + self.time_input.setEnabled(False) config_file.write(self.config) \ No newline at end of file diff --git a/ui/components/software/time_sync.py b/ui/components/software/time_sync.py index c8a4a6b..2f144b5 100644 --- a/ui/components/software/time_sync.py +++ b/ui/components/software/time_sync.py @@ -42,10 +42,10 @@ def init_ui(self): self.enable_user.stateChanged.connect(lambda state, name = 'enable_ntp_user': self.save_checkbox_state(name, state)) self.container_layout.addWidget(self.enable_user) - ntp_server_lable = QLabel('NTP Servers') - ntp_server_lable.setToolTip(self.time_sync_tooltip['ntp_servers']) - ntp_server_lable.setProperty('class', 'normal-label-for') - self.container_layout.addWidget(ntp_server_lable) + self.ntp_server_checkbox = QCheckBox('Enable NTP Servers') + self.ntp_server_checkbox.setToolTip(self.time_sync_tooltip['enable_ntp_servers']) + self.ntp_server_checkbox.stateChanged.connect(self.enable_ntp_servers_changed) + self.container_layout.addWidget(self.ntp_server_checkbox) hlayout = QHBoxLayout() @@ -121,7 +121,7 @@ def refresh_config(self, config): self.toml_time_sync = self.config['time-sync'] self.enable_ntp.setChecked(self.toml_time_sync['enable_ntp']) self.enable_user.setChecked(self.toml_time_sync['enable_ntp_user']) - + self.ntp_server_checkbox.setChecked(self.toml_time_sync['enable_ntp_servers']) if not self.toml_time_sync['enable_ntp']: self.enable_user.setEnabled(False) self.servers_table.setEnabled(False) @@ -144,3 +144,17 @@ def save_checkbox_state(self, name, state): for i in range(self.servers_table.rowCount()): self.servers_table.cellWidget(i, 1).setEnabled(state == 2) config_file.write(self.config) + + def enable_ntp_servers_changed(self, state): + self.toml_time_sync['enable_ntp_servers'] = (state == 2) + if state == 2: + self.new_server.setEnabled(True) + self.add_button.setEnabled(True) + for i in range(self.servers_table.rowCount()): + self.servers_table.cellWidget(i, 1).setEnabled(True) + else: + self.new_server.setEnabled(False) + self.add_button.setEnabled(False) + for i in range(self.servers_table.rowCount()): + self.servers_table.cellWidget(i, 1).setEnabled(False) + config_file.write(self.config) \ No newline at end of file From c608c89f0eca0f094638cf66efde78bd31ebd84d Mon Sep 17 00:00:00 2001 From: Abhishek M J Date: Wed, 20 Dec 2023 14:34:41 +0530 Subject: [PATCH 2/8] Add PAM config --- config/sampleconfig.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/sampleconfig.toml b/config/sampleconfig.toml index f29b13a..138c354 100644 --- a/config/sampleconfig.toml +++ b/config/sampleconfig.toml @@ -132,5 +132,10 @@ authentication_timeout = 15 # in minutes restrict_su = true [pam] # PAM +enable_password_level = true required_password_level = "strong" # weak, medium, strong, stronger +enable_password_length = true minimum_password_length = 14 +limit_password_reuse = true +password_reuse_limit = 5 +configure_hashing_algorithm = true From 8e93ce43b1b0bbd147675cbd07bed9f7487e1747 Mon Sep 17 00:00:00 2001 From: Abhishek M J Date: Wed, 20 Dec 2023 14:39:20 +0530 Subject: [PATCH 3/8] Add pam tooltip --- config/tooltip.toml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/config/tooltip.toml b/config/tooltip.toml index 219a579..64f406b 100644 --- a/config/tooltip.toml +++ b/config/tooltip.toml @@ -125,4 +125,13 @@ disable_nopassword = "false" enable_reauthentication = "true" enable_authentication_timeout = "true" authentication_timeout = "15" # in minutes -restrict_su = "true" \ No newline at end of file +restrict_su = "true" + +[pam] # PAM +enable_password_level = "true" +required_password_level = "strong" # weak, medium, strong, stronger +enable_password_length = "true" +minimum_password_length = "14" +limit_password_reuse = "true" +password_reuse_limit = "5" +configure_hashing_algorithm = "true" From c2bd37331bb8348a32d39ac283101b2124a5c09a Mon Sep 17 00:00:00 2001 From: Abhishek M J Date: Wed, 20 Dec 2023 15:50:15 +0530 Subject: [PATCH 4/8] update levels with pam --- config/server/level-1.toml | 11 ++++++++++- config/server/level-2.toml | 11 ++++++++++- config/workstation/level-1.toml | 11 ++++++++++- config/workstation/level-2.toml | 11 ++++++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/config/server/level-1.toml b/config/server/level-1.toml index eee62f2..242182b 100644 --- a/config/server/level-1.toml +++ b/config/server/level-1.toml @@ -128,4 +128,13 @@ disable_nopasswd = false enable_reauthentication = true enable_authentication_timeout = true authentication_timeout = 15 # in minutes -restrict_su = true \ No newline at end of file +restrict_su = true + +[pam] # PAM +enable_password_level = true +required_password_level = "strong" # weak, medium, strong, stronger +enable_password_length = true +minimum_password_length = 14 +limit_password_reuse = true +password_reuse_limit = 5 +configure_hashing_algorithm = true diff --git a/config/server/level-2.toml b/config/server/level-2.toml index 5858962..12b4a57 100644 --- a/config/server/level-2.toml +++ b/config/server/level-2.toml @@ -127,4 +127,13 @@ disable_nopasswd = false enable_reauthentication = true enable_authentication_timeout = true authentication_timeout = 15 # in minutes -restrict_su = true \ No newline at end of file +restrict_su = true + +[pam] # PAM +enable_password_level = true +required_password_level = "strong" # weak, medium, strong, stronger +enable_password_length = true +minimum_password_length = 14 +limit_password_reuse = true +password_reuse_limit = 5 +configure_hashing_algorithm = true diff --git a/config/workstation/level-1.toml b/config/workstation/level-1.toml index 8978cc8..7d11214 100644 --- a/config/workstation/level-1.toml +++ b/config/workstation/level-1.toml @@ -124,4 +124,13 @@ disable_nopasswd = false enable_reauthentication = true enable_authentication_timeout = true authentication_timeout = 15 # in minutes -restrict_su = true \ No newline at end of file +restrict_su = true + +[pam] # PAM +enable_password_level = true +required_password_level = "strong" # weak, medium, strong, stronger +enable_password_length = true +minimum_password_length = 14 +limit_password_reuse = true +password_reuse_limit = 5 +configure_hashing_algorithm = true diff --git a/config/workstation/level-2.toml b/config/workstation/level-2.toml index d81e663..f010ac5 100644 --- a/config/workstation/level-2.toml +++ b/config/workstation/level-2.toml @@ -127,4 +127,13 @@ disable_nopasswd = false enable_reauthentication = true enable_authentication_timeout = true authentication_timeout = 15 # in minutes -restrict_su = true \ No newline at end of file +restrict_su = true + +[pam] # PAM +enable_password_level = true +required_password_level = "strong" # weak, medium, strong, stronger +enable_password_length = true +minimum_password_length = 14 +limit_password_reuse = true +password_reuse_limit = 5 +configure_hashing_algorithm = true From 43af870ad3f666cd8bbac816894c6044a7e4053f Mon Sep 17 00:00:00 2001 From: Siddesh Devarakonda Date: Wed, 20 Dec 2023 15:50:29 +0530 Subject: [PATCH 5/8] Add PAM UI --- ui/components/software/pam.py | 148 ++++++++++++++++++++++++++++++++++ ui/pages/software_page.py | 9 ++- 2 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 ui/components/software/pam.py diff --git a/ui/components/software/pam.py b/ui/components/software/pam.py new file mode 100644 index 0000000..a89a44a --- /dev/null +++ b/ui/components/software/pam.py @@ -0,0 +1,148 @@ +from PyQt6.QtWidgets import QWidget, QVBoxLayout, QLabel, QCheckBox \ + , QHBoxLayout, QComboBox, QLineEdit +from harden import config_file +from PyQt6.QtGui import QIntValidator + +class PAM(QWidget): + def __init__(self, config, tooltip): + super().__init__() + self.config = config + self.tooltip = tooltip + self.toml_pam = self.config['pam'] + self.pam_tooltip = self.tooltip['pam'] + self.init_ui() + self.refresh_config(config) + + def init_ui(self): + self.layout = QVBoxLayout() + self.setLayout(self.layout) + self.layout.setSpacing(0) + self.layout.setContentsMargins(0, 0, 0, 0) + + self.main_label = QLabel("PAM") + self.layout.addWidget(self.main_label) + self.main_label.setObjectName("component-title") + + # container widget + self.container_widget = QWidget() + self.container_layout = QVBoxLayout() + self.container_widget.setLayout(self.container_layout) + self.layout.addWidget(self.container_widget) + self.container_layout.setSpacing(0) + self.container_layout.setContentsMargins(30, 30, 30, 30) + self.container_widget.setObjectName("container-widget") + + # Enable Password Checkbox + self.enable_password_checkbox = QCheckBox('Enable Password Level') + self.enable_password_checkbox.setToolTip(self.pam_tooltip['enable_password_level']) + self.enable_password_checkbox.stateChanged.connect(lambda state: self.save_checkbox_state(state, 'enable_password_level')) + self.container_layout.addWidget(self.enable_password_checkbox) + + # Enable Password Dropdown + hlayout = QHBoxLayout() + + # Select Mode Label + self.mode_label = QLabel('Required Password Level:') + self.mode_label.setToolTip(self.pam_tooltip['enable_password_level']) + self.mode_label.setProperty('class', 'normal-label-for') + + # Mode Dropdown + self.mode_list = QComboBox() + self.mode_list.addItems(['weak', 'medium', 'strong', 'stronger']) + self.mode_list.currentTextChanged.connect(lambda text: self.new_item_selected(text, 'required_password_level')) + + hlayout.addWidget(self.mode_label) + hlayout.addWidget(self.mode_list) + self.container_layout.addLayout(hlayout) + + # Enable Password Length Checkbox + self.enable_password_len_checkbox = QCheckBox('Enable Password Length') + self.enable_password_len_checkbox.setToolTip(self.pam_tooltip['enable_password_length']) + self.enable_password_len_checkbox.stateChanged.connect(lambda state: self.save_checkbox_state(state, 'enable_password_length')) + self.container_layout.addWidget(self.enable_password_len_checkbox) + + # Enable Password Dropdown + hlayout = QHBoxLayout() + + self.len_label = QLabel('Minimum Password Length: ') + self.len_label.setToolTip(self.pam_tooltip['enable_password_length']) + self.len_label.setProperty('class', 'normal-label-for') + + self.size_input = QLineEdit() + validator = QIntValidator() + self.size_input.setValidator(validator) + self.size_input.textChanged.connect(lambda text: self.size_changed(text, 'minimum_password_length', self.size_input)) + + hlayout.addWidget(self.len_label) + hlayout.addWidget(self.size_input) + self.container_layout.addLayout(hlayout) + + # Enable Password Length Checkbox + self.limit_password_reuse_checkbox = QCheckBox('Enable Limit Password Reuse') + self.limit_password_reuse_checkbox.setToolTip(self.pam_tooltip['limit_password_reuse']) + self.limit_password_reuse_checkbox.stateChanged.connect(lambda state: self.save_checkbox_state(state, 'limit_password_reuse')) + self.container_layout.addWidget(self.limit_password_reuse_checkbox) + + # Enable Password Dropdown + hlayout = QHBoxLayout() + + self.reuse_label = QLabel('Minimum Password Length: ') + self.reuse_label.setToolTip(self.pam_tooltip['limit_password_reuse']) + self.reuse_label.setProperty('class', 'normal-label-for') + + self.size_input_2 = QLineEdit() + validator = QIntValidator() + self.size_input_2.setValidator(validator) + self.size_input_2.textChanged.connect(lambda text: self.size_changed(text, 'password_reuse_limit', self.size_input_2)) + + hlayout.addWidget(self.reuse_label) + hlayout.addWidget(self.size_input_2) + self.container_layout.addLayout(hlayout) + + # Configure Hashing Algorithm + self.configure_hashing_algorithm = QCheckBox('Configure Hashing Algorithm') + self.configure_hashing_algorithm.setToolTip(self.pam_tooltip['configure_hashing_algorithm']) + self.configure_hashing_algorithm.stateChanged.connect(lambda state: self.save_checkbox_state(state, 'configure_hashing_algorithm')) + self.container_layout.addWidget(self.configure_hashing_algorithm) + + def refresh_config(self, config): + self.config = config + self.toml_pam = self.config['pam'] + self.enable_password_checkbox.setChecked(self.toml_pam['enable_password_level']) + self.enable_password_len_checkbox.setChecked(self.toml_pam['enable_password_length']) + self.limit_password_reuse_checkbox.setChecked(self.toml_pam['limit_password_reuse']) + self.configure_hashing_algorithm.setChecked(self.toml_pam['configure_hashing_algorithm']) + self.mode_list.setCurrentText(self.toml_pam['required_password_level']) + self.size_input.setText(str(self.toml_pam['minimum_password_length'])) + self.size_input_2.setText(str(self.toml_pam['password_reuse_limit'])) + + def save_checkbox_state(self, state, key): + self.toml_pam[key] = (state == 2) + if state == 0: + if key == 'enable_password_level': + self.mode_list.setEnabled(False) + elif key == 'enable_password_length': + self.size_input.setEnabled(False) + elif key == 'limit_password_reuse': + self.size_input_2.setEnabled(False) + else: + if key == 'enable_password_level': + self.mode_list.setEnabled(True) + elif key == 'enable_password_length': + self.size_input.setEnabled(True) + elif key == 'limit_password_reuse': + self.size_input_2.setEnabled(True) + config_file.write(self.config) + + def new_item_selected(self, text, key): + self.toml_pam[key] = text + config_file.write(self.config) + + def size_changed(self, new_size, key, input): + if new_size.startswith('0') and len(new_size) > 1: + input.setText(new_size[1:]) + if new_size: + self.toml_pam[key] = int(new_size) + else: + input.setText('0') + config_file.write(self.config) \ No newline at end of file diff --git a/ui/pages/software_page.py b/ui/pages/software_page.py index 94ae49b..5963579 100644 --- a/ui/pages/software_page.py +++ b/ui/pages/software_page.py @@ -6,6 +6,7 @@ from ui.components.software.services import Services from ui.components.software.service_clients import ServiceClients from ui.components.software.privilege_escalation import PrivilegeEscalation +from ui.components.software.pam import PAM from PyQt6.QtCore import Qt @@ -51,6 +52,10 @@ def init_ui(self): self.privilege_escalation = PrivilegeEscalation(self.config, self.tooltip) self.privilege_escalation.setObjectName("privilege_escalation") + # PAM Widget + self.pam = PAM(self.config, self.tooltip) + self.pam.setObjectName("pam") + self.layout.addWidget(self.process_hardening) self.layout.addWidget(self.apparmor) self.layout.addWidget(self.gdm) @@ -58,6 +63,7 @@ def init_ui(self): self.layout.addWidget(self.services) self.layout.addWidget(self.service_clients) self.layout.addWidget(self.privilege_escalation) + self.layout.addWidget(self.pam) def refresh_config(self, config): self.config = config @@ -67,4 +73,5 @@ def refresh_config(self, config): self.time_sync.refresh_config(config) self.services.refresh_config(config) self.service_clients.refresh_config(config) - self.privilege_escalation.refresh_config(config) \ No newline at end of file + self.privilege_escalation.refresh_config(config) + self.pam.refresh_config(config) \ No newline at end of file From 5c3b87df1fe9563d02c6c8c57bf92f4a9440f06c Mon Sep 17 00:00:00 2001 From: Siddesh Devarakonda Date: Wed, 20 Dec 2023 15:50:53 +0530 Subject: [PATCH 6/8] Refactor Add Button --- ui/components/software/time_sync.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/components/software/time_sync.py b/ui/components/software/time_sync.py index 2f144b5..97bf41a 100644 --- a/ui/components/software/time_sync.py +++ b/ui/components/software/time_sync.py @@ -54,8 +54,8 @@ def init_ui(self): self.add_button.clicked.connect(self.add_new_server) self.add_button.setProperty('class', 'add-btn') - hlayout.addWidget(self.new_server) hlayout.addWidget(self.add_button) + hlayout.addWidget(self.new_server) self.container_layout.addLayout(hlayout) From 4bc381a776fa53510d0d00dd82721e01eb4b3daf Mon Sep 17 00:00:00 2001 From: Siddesh Devarakonda Date: Wed, 20 Dec 2023 15:51:01 +0530 Subject: [PATCH 7/8] Change Font Size --- ui/qss/light.qss | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ui/qss/light.qss b/ui/qss/light.qss index 7d90f6c..8107d6a 100644 --- a/ui/qss/light.qss +++ b/ui/qss/light.qss @@ -68,7 +68,9 @@ QMainWindow { padding: 2.5px 10px; border-radius: 5px; color: #382F27; - font: 18px; + font: 14px; + margin-right: 10px; + margin-bottom: 5px; font-weight: 500; } .add-btn:hover { @@ -146,7 +148,7 @@ QLineEdit { border-radius: 4px; padding: 2px 5px; color: #382F27; - background-color: #FFF6ED; + background-color: #ffffff; margin: 0px 15px 5px 0px; selection-background-color: #AA8F75; } @@ -175,8 +177,10 @@ QComboBox { border-radius: 4px; padding: 2px 5px; color: #382F27; - background-color: #FFF6ED; + background-color: #ffffff; margin: 0px 15px 5px 0px; + font: 15px; + font-weight: 400; selection-background-color: #AA8F75; } From 43a30fa3f2c6ba52a8b19bdcd3556ce8e1dd6a05 Mon Sep 17 00:00:00 2001 From: Siddesh Devarakonda Date: Wed, 20 Dec 2023 16:13:53 +0530 Subject: [PATCH 8/8] fix key error in privilege escalation --- config/server/level-1.toml | 2 +- config/server/level-2.toml | 2 +- config/workstation/level-1.toml | 2 +- config/workstation/level-2.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/server/level-1.toml b/config/server/level-1.toml index 242182b..3497389 100644 --- a/config/server/level-1.toml +++ b/config/server/level-1.toml @@ -124,7 +124,7 @@ client_alive_count_max = 3 [privilege_escalation] # Privilege Escalation use_pty = true enable_logfile = true -disable_nopasswd = false +disable_nopassword = false enable_reauthentication = true enable_authentication_timeout = true authentication_timeout = 15 # in minutes diff --git a/config/server/level-2.toml b/config/server/level-2.toml index 12b4a57..9769535 100644 --- a/config/server/level-2.toml +++ b/config/server/level-2.toml @@ -123,7 +123,7 @@ client_alive_count_max = 3 [privilege_escalation] # Privilege Escalation use_pty = true enable_logfile = true -disable_nopasswd = false +disable_nopassword = false enable_reauthentication = true enable_authentication_timeout = true authentication_timeout = 15 # in minutes diff --git a/config/workstation/level-1.toml b/config/workstation/level-1.toml index 7d11214..606dc8b 100644 --- a/config/workstation/level-1.toml +++ b/config/workstation/level-1.toml @@ -120,7 +120,7 @@ client_alive_count_max = {enable = true, value = 3} [privilege_escalation] # Privilege Escalation use_pty = true enable_logfile = true -disable_nopasswd = false +disable_nopassword = false enable_reauthentication = true enable_authentication_timeout = true authentication_timeout = 15 # in minutes diff --git a/config/workstation/level-2.toml b/config/workstation/level-2.toml index f010ac5..edf5364 100644 --- a/config/workstation/level-2.toml +++ b/config/workstation/level-2.toml @@ -123,7 +123,7 @@ client_alive_count_max = 3 [privilege_escalation] # Privilege Escalation use_pty = true enable_logfile = true -disable_nopasswd = false +disable_nopassword = false enable_reauthentication = true enable_authentication_timeout = true authentication_timeout = 15 # in minutes