mirror of
https://github.com/altlinux/gpupdate.git
synced 2025-12-02 16:23:52 +03:00
Compare commits
153 Commits
astra
...
fix_check_
| Author | SHA1 | Date | |
|---|---|---|---|
| 527c4f8172 | |||
|
|
c57d1bac9e | ||
| b9b5239448 | |||
| aae2776790 | |||
|
|
a20aa841d6 | ||
|
|
8c7819d96f | ||
|
|
3d9473f979 | ||
|
|
01f48be853 | ||
|
|
1638098fd4 | ||
|
|
047e5459af | ||
|
|
5baa4245e3 | ||
| ec6b9f7887 | |||
| 22d0d23b89 | |||
| fd3a32e8e1 | |||
|
|
9e849e8fe3 | ||
|
|
d65f3ed942 | ||
|
|
31298be840 | ||
|
|
5c889fd57e | ||
|
|
4e2874c972 | ||
|
|
63e50ac2df | ||
|
|
ad2a87e20d | ||
|
|
e9c3a4262a | ||
|
|
b5706ec6e1 | ||
|
|
61e7350429 | ||
|
|
c9a274fc79 | ||
|
|
127c9f7183 | ||
|
|
a27f8ba5dd | ||
|
|
fafe2c34b4 | ||
|
|
9c91ddc7ba | ||
|
|
1f02ed650b | ||
|
|
fc47df4649 | ||
|
|
42b8bdb82a | ||
|
|
2a174edeef | ||
|
|
9b8529b39b | ||
|
|
062ff742c3 | ||
|
|
1764560c49 | ||
|
|
b439e04a2f | ||
|
|
e413f95633 | ||
|
|
675f37ab85 | ||
|
|
9932c682ef | ||
|
|
018b30cdc4 | ||
|
|
249eb69ade | ||
|
|
1ab8c7aee0 | ||
|
|
400a5fab7d | ||
|
|
e7851e88b3 | ||
|
|
0761637666 | ||
|
|
dda4d987cb | ||
|
|
609ec0e8b8 | ||
|
|
c0b28a0655 | ||
|
|
78aad11e06 | ||
|
|
59bebbc45e | ||
|
|
e92656add0 | ||
|
|
5d24579d2f | ||
|
|
ce284b61be | ||
|
|
7a8118ac63 | ||
|
|
18d8e73acd | ||
|
|
58235cb1a1 | ||
|
|
e0d88cc076 | ||
|
|
c8b0927090 | ||
|
|
a4a79d8c99 | ||
|
|
408609fa58 | ||
|
|
6efebfad89 | ||
| 12865b0b43 | |||
| 9117dddcee | |||
| 1e267f5cb6 | |||
| 62ed015ea9 | |||
| 3e6b7cd040 | |||
| 209eb84d6d | |||
| 7f3b47a23c | |||
| 08ba87c8d8 | |||
| f2a45a2a6d | |||
| 9c544adc94 | |||
| a225c9aa7f | |||
| 51c8711da6 | |||
| 54eb4188a7 | |||
|
|
89d5e36d6c | ||
|
|
6cd5ab4ee2 | ||
|
|
0c913c68e3 | ||
|
|
12d746a1dc | ||
|
|
0a25f3a1d6 | ||
|
|
1eaab893c8 | ||
|
|
05ea872831 | ||
|
|
d0506dba29 | ||
|
|
dd28587b20 | ||
|
|
1a288c84f5 | ||
|
|
cadc3eda52 | ||
|
|
8d3e6691d4 | ||
|
|
cb54fa5d78 | ||
|
|
53ffc072f0 | ||
|
|
7a59bcb65b | ||
|
|
b81a727cd4 | ||
|
|
11b33dd148 | ||
|
|
1ccc18a31f | ||
|
|
9a3afeebdf | ||
|
|
0720471cca | ||
|
|
dd43ddaad6 | ||
|
|
6fc059aaac | ||
|
|
8cfb6f0bb3 | ||
|
|
ddcdc322f8 | ||
|
|
4ee52f06d6 | ||
|
|
603efc2deb | ||
|
|
9fc5007590 | ||
|
|
a6210f8b29 | ||
|
|
175f244a5f | ||
|
|
0d4ce533bc | ||
|
|
8e22235df2 | ||
|
|
0519d2703c | ||
|
|
1ca9b006e1 | ||
|
|
8cc5a8904b | ||
|
|
70cdef2e71 | ||
|
|
3baffeb12d | ||
|
|
a0d9dc585f | ||
|
|
388125415b | ||
|
|
14c7e5db21 | ||
|
|
582a85df88 | ||
|
|
18ddc54626 | ||
|
|
6bad9a331d | ||
|
|
16b5747620 | ||
|
|
47015ec312 | ||
|
|
666c88bdf1 | ||
|
|
bd5262353b | ||
|
|
e1d5712b83 | ||
|
|
bcb9108424 | ||
|
|
82bb88ca34 | ||
|
|
518685f361 | ||
|
|
39e3d15fa8 | ||
|
|
7a755bbb3e | ||
|
|
41260df1a1 | ||
|
|
0d1b60158a | ||
|
|
b244df8f2d | ||
|
|
e48ca4fc8e | ||
|
|
82d52d1c9f | ||
|
|
e6a51d02fb | ||
|
|
28e2d9c94b | ||
|
|
60137feed0 | ||
|
|
a86c49e471 | ||
|
|
8c5d0bbb06 | ||
|
|
c26fbf8042 | ||
|
|
83e70d5e7a | ||
|
|
c383b8df9b | ||
|
|
fc810c3362 | ||
|
|
7e225c837a | ||
|
|
b053544512 | ||
|
|
9b4527d334 | ||
|
|
3794ffa5be | ||
|
|
fe68f0cca8 | ||
|
|
d83cf4d29d | ||
|
|
47dc1df796 | ||
|
|
5d2fb3f719 | ||
|
|
3fded83c75 | ||
|
|
aeab315c3d | ||
|
|
446fa532db | ||
|
|
ac2190809a |
22
completions/gpoa
Normal file
22
completions/gpoa
Normal file
@@ -0,0 +1,22 @@
|
||||
_gpoa()
|
||||
{
|
||||
local cur prev words cword split
|
||||
_init_completion -s || return
|
||||
|
||||
case $prev in
|
||||
--dc)
|
||||
_filedir
|
||||
return
|
||||
;;
|
||||
--loglevel)
|
||||
COMPREPLY=($(compgen -W '0 1 2 3 4 5' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=($(compgen -W '--dc --nodomain --noupdate --noplugins --list-backends --loglevel --help' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
complete -F _gpoa gpoa
|
||||
27
completions/gpupdate
Normal file
27
completions/gpupdate
Normal file
@@ -0,0 +1,27 @@
|
||||
_gpupdate()
|
||||
{
|
||||
local cur prev words cword split
|
||||
_init_completion -s || return
|
||||
|
||||
case $prev in
|
||||
-u|--user)
|
||||
_filedir
|
||||
return
|
||||
;;
|
||||
-t|--target)
|
||||
COMPREPLY=($(compgen -W 'ALL USER COMPUTER' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
-l|--loglevel)
|
||||
COMPREPLY=($(compgen -W '0 1 2 3 4 5' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=($(compgen -W '--user --target --loglevel --system --help' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
complete -F _gpupdate gpupdate
|
||||
|
||||
18
completions/gpupdate-setup
Normal file
18
completions/gpupdate-setup
Normal file
@@ -0,0 +1,18 @@
|
||||
_gpupdate-setup()
|
||||
{
|
||||
local cur prev words cword split
|
||||
_init_completion -s || return
|
||||
|
||||
case $prev in
|
||||
set-backend)
|
||||
COMPREPLY=($(compgen -W 'local samba' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=($(compgen -W 'list list-backends status enable disable update write set-backend default-policy active-policy active-backend' -- "$cur"))
|
||||
return
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
complete -F _gpupdate-setup gpupdate-setup
|
||||
@@ -22,6 +22,9 @@ from .samba_backend import samba_backend
|
||||
from .nodomain_backend import nodomain_backend
|
||||
from util.logging import log
|
||||
from util.config import GPConfig
|
||||
from util.util import get_uid_by_username, touch_file
|
||||
from util.paths import get_dconf_config_path
|
||||
from storage.dconf_registry import Dconf_registry, create_dconf_ini_file
|
||||
|
||||
def backend_factory(dc, username, is_machine, no_domain = False):
|
||||
'''
|
||||
@@ -59,3 +62,12 @@ def backend_factory(dc, username, is_machine, no_domain = False):
|
||||
|
||||
return back
|
||||
|
||||
def save_dconf(username, is_machine):
|
||||
if is_machine:
|
||||
uid = None
|
||||
else:
|
||||
uid = get_uid_by_username(username) if not is_machine else None
|
||||
target_file = get_dconf_config_path(uid)
|
||||
touch_file(target_file)
|
||||
Dconf_registry.apply_template(uid)
|
||||
create_dconf_ini_file(target_file,Dconf_registry.global_registry_dict)
|
||||
|
||||
@@ -35,7 +35,7 @@ class nodomain_backend(applier_backend):
|
||||
domain = None
|
||||
machine_name = get_machine_name()
|
||||
machine_sid = get_sid(domain, machine_name, True)
|
||||
self.storage = registry_factory('registry')
|
||||
self.storage = registry_factory()
|
||||
self.storage.set_info('domain', domain)
|
||||
self.storage.set_info('machine_name', machine_name)
|
||||
self.storage.set_info('machine_sid', machine_sid)
|
||||
|
||||
@@ -24,7 +24,7 @@ except ImportError:
|
||||
from samba.gp.gpclass import check_safe_path
|
||||
|
||||
from .applier_backend import applier_backend
|
||||
from storage import cache_factory, registry_factory
|
||||
from storage import registry_factory
|
||||
from gpt.gpt import gpt, get_local_gpt
|
||||
from util.util import (
|
||||
get_machine_name,
|
||||
@@ -39,14 +39,15 @@ import util.preg
|
||||
from util.logging import log
|
||||
|
||||
class samba_backend(applier_backend):
|
||||
__user_policy_mode_key = 'Software\\Policies\\Microsoft\\Windows\\System\\UserPolicyMode'
|
||||
__user_policy_mode_key = '/SOFTWARE/Policies/Microsoft/Windows/System/UserPolicyMode'
|
||||
__user_policy_mode_key_win = '/Software/Policies/Microsoft/Windows/System/UserPolicyMode'
|
||||
|
||||
def __init__(self, sambacreds, username, domain, is_machine):
|
||||
self.cache_path = '/var/cache/gpupdate/creds/krb5cc_{}'.format(os.getpid())
|
||||
self.__kinit_successful = machine_kinit(self.cache_path)
|
||||
if not self.__kinit_successful:
|
||||
raise Exception('kinit is not successful')
|
||||
self.storage = registry_factory('registry')
|
||||
self.storage = registry_factory()
|
||||
self.storage.set_info('domain', domain)
|
||||
machine_name = get_machine_name()
|
||||
machine_sid = get_sid(domain, machine_name, is_machine)
|
||||
@@ -61,9 +62,6 @@ class samba_backend(applier_backend):
|
||||
else:
|
||||
self.sid = get_sid(self.storage.get_info('domain'), self.username)
|
||||
|
||||
self.cache = cache_factory('regpol_cache')
|
||||
self.gpo_names = cache_factory('gpo_names')
|
||||
|
||||
# Samba objects - LoadParm() and CredentialsOptions()
|
||||
self.sambacreds = sambacreds
|
||||
|
||||
@@ -81,9 +79,11 @@ class samba_backend(applier_backend):
|
||||
is possible to work with user's part of GPT. This value is
|
||||
checked only if working for user's SID.
|
||||
'''
|
||||
upm = self.storage.get_hklm_entry(self.__user_policy_mode_key)
|
||||
if upm and upm.data:
|
||||
upm = int(upm.data)
|
||||
upm_key = self.storage.get_key_value(self.__user_policy_mode_key)
|
||||
upm_win_key = self.storage.get_key_value(self.__user_policy_mode_key_win)
|
||||
upm = upm_key if upm_key else upm_win_key
|
||||
if upm:
|
||||
upm = int(upm)
|
||||
if upm < 0 or upm > 2:
|
||||
upm = 0
|
||||
else:
|
||||
@@ -176,7 +176,16 @@ class samba_backend(applier_backend):
|
||||
slogdata = dict({'sysvol_path': gpo.file_sys_path, 'gpo_name': gpo.display_name, 'gpo_path': path})
|
||||
log('D30', slogdata)
|
||||
gpt_abspath = os.path.join(self.cache_dir, 'gpo_cache', path)
|
||||
obj = gpt(gpt_abspath, sid)
|
||||
gpo_version=None
|
||||
try:
|
||||
gpo_version=gpo.version
|
||||
except:
|
||||
log('D210')
|
||||
|
||||
if self._is_machine_username:
|
||||
obj = gpt(gpt_abspath, sid, None, version=gpo_version)
|
||||
else:
|
||||
obj = gpt(gpt_abspath, sid, self.username, version=gpo_version)
|
||||
obj.set_name(gpo.display_name)
|
||||
gpts.append(obj)
|
||||
else:
|
||||
|
||||
@@ -18,43 +18,42 @@
|
||||
|
||||
from abc import ABC
|
||||
|
||||
import logging
|
||||
from util.logging import slogm
|
||||
from util.logging import log
|
||||
|
||||
def check_experimental_enabled(storage):
|
||||
experimental_enable_flag = 'Software\\BaseALT\\Policies\\GPUpdate\\GlobalExperimental'
|
||||
flag = storage.get_hklm_entry(experimental_enable_flag)
|
||||
experimental_enable_flag = '/Software/BaseALT/Policies/GPUpdate/GlobalExperimental'
|
||||
flag = storage.get_key_value(experimental_enable_flag)
|
||||
|
||||
result = False
|
||||
|
||||
if flag and '1' == flag.data:
|
||||
if flag and '1' == str(flag):
|
||||
result = True
|
||||
|
||||
return result
|
||||
|
||||
def check_windows_mapping_enabled(storage):
|
||||
windows_mapping_enable_flag = 'Software\\BaseALT\\Policies\\GPUpdate\\WindowsPoliciesMapping'
|
||||
flag = storage.get_hklm_entry(windows_mapping_enable_flag)
|
||||
windows_mapping_enable_flag = '/Software/BaseALT/Policies/GPUpdate/WindowsPoliciesMapping'
|
||||
flag = storage.get_key_value(windows_mapping_enable_flag)
|
||||
|
||||
result = True
|
||||
|
||||
if flag and '0' == flag.data:
|
||||
flag = str(flag)
|
||||
if flag and '0' == flag:
|
||||
result = False
|
||||
|
||||
return result
|
||||
|
||||
def check_module_enabled(storage, module_name):
|
||||
gpupdate_module_enable_branch = 'Software\\BaseALT\\Policies\\GPUpdate'
|
||||
gpupdate_module_flag = '{}\\{}'.format(gpupdate_module_enable_branch, module_name)
|
||||
flag = storage.get_hklm_entry(gpupdate_module_flag)
|
||||
gpupdate_module_enable_branch = '/Software/BaseALT/Policies/GPUpdate'
|
||||
gpupdate_module_flag = '{}/{}'.format(gpupdate_module_enable_branch, module_name)
|
||||
flag = storage.get_key_value(gpupdate_module_flag)
|
||||
|
||||
result = None
|
||||
|
||||
flag = str(flag)
|
||||
if flag:
|
||||
if '1' == flag.data:
|
||||
if '1' == flag:
|
||||
result = True
|
||||
if '0' == flag.data:
|
||||
result = False
|
||||
else:
|
||||
result = False
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -92,6 +92,8 @@ class Envvar:
|
||||
value = value.replace('\\', '/')
|
||||
exist_line = None
|
||||
for line in lines:
|
||||
if line == '\n':
|
||||
continue
|
||||
if line.split()[0] == name:
|
||||
exist_line = line
|
||||
break
|
||||
|
||||
@@ -44,14 +44,16 @@ def remove_dir_tree(path, delete_files=False, delete_folder=False, delete_sub_fo
|
||||
return content
|
||||
|
||||
def str2bool(boolstr):
|
||||
if boolstr and boolstr.lower() in ['true', 'yes', '1']:
|
||||
if isinstance(boolstr, bool):
|
||||
return boolstr
|
||||
elif boolstr and boolstr.lower() in ['true', 'yes', '1']:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class Folder:
|
||||
def __init__(self, folder_object, username=None):
|
||||
folder_path = expand_windows_var(folder_object.path, username).replace('\\', '/')
|
||||
folder_path = expand_windows_var(folder_object.path, username).replace('\\', '/').replace('//', '/')
|
||||
if username:
|
||||
folder_path = folder_path.replace(get_homedir(username), '')
|
||||
self.folder_path = Path(get_homedir(username)).joinpath(folder_path if folder_path [0] != '/' else folder_path [1:])
|
||||
|
||||
@@ -30,7 +30,7 @@ class chromium_applier(applier_frontend):
|
||||
__module_name = 'ChromiumApplier'
|
||||
__module_enabled = True
|
||||
__module_experimental = False
|
||||
__registry_branch = 'Software\\Policies\\Google\\Chrome'
|
||||
__registry_branch = 'Software/Policies/Google/Chrome'
|
||||
__managed_policies_path = '/etc/chromium/policies/managed'
|
||||
__recommended_policies_path = '/etc/chromium/policies/recommended'
|
||||
|
||||
@@ -168,7 +168,7 @@ class chromium_applier(applier_frontend):
|
||||
'''
|
||||
Parse registry path string and leave key parameters
|
||||
'''
|
||||
parts = hivekeyname.replace(self.__registry_branch, '').split('\\')
|
||||
parts = hivekeyname.replace(self.__registry_branch, '').split('/')
|
||||
return parts
|
||||
|
||||
|
||||
|
||||
@@ -222,7 +222,7 @@ class cifs_applier_user(applier_frontend):
|
||||
def check_enable_home_link(self, enable_home_link):
|
||||
if self.storage.get_hkcu_entry(self.sid, enable_home_link):
|
||||
data = self.storage.get_hkcu_entry(self.sid, enable_home_link).data
|
||||
return bool(int(data))
|
||||
return bool(int(data)) if data else None
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
@@ -29,11 +29,11 @@ class control_applier(applier_frontend):
|
||||
__module_name = 'ControlApplier'
|
||||
__module_experimental = False
|
||||
__module_enabled = True
|
||||
_registry_branch = 'Software\\BaseALT\\Policies\\Control'
|
||||
_registry_branch = 'Software/BaseALT/Policies/Control'
|
||||
|
||||
def __init__(self, storage):
|
||||
self.storage = storage
|
||||
self.control_settings = self.storage.filter_hklm_entries('Software\\BaseALT\\Policies\\Control%')
|
||||
self.control_settings = self.storage.filter_hklm_entries(self._registry_branch)
|
||||
self.controls = list()
|
||||
self.__module_enabled = check_enabled(
|
||||
self.storage
|
||||
@@ -43,7 +43,7 @@ class control_applier(applier_frontend):
|
||||
|
||||
def run(self):
|
||||
for setting in self.control_settings:
|
||||
valuename = setting.hive_key.rpartition('\\')[2]
|
||||
valuename = setting.hive_key.rpartition('/')[2]
|
||||
try:
|
||||
self.controls.append(control(valuename, int(setting.data)))
|
||||
logdata = dict()
|
||||
|
||||
@@ -33,13 +33,13 @@ from .applier_frontend import (
|
||||
, check_enabled
|
||||
)
|
||||
from util.logging import log
|
||||
from util.util import is_machine_name
|
||||
from util.util import is_machine_name, try_dict_to_literal_eval
|
||||
|
||||
class firefox_applier(applier_frontend):
|
||||
__module_name = 'FirefoxApplier'
|
||||
__module_experimental = False
|
||||
__module_enabled = True
|
||||
__registry_branch = 'Software\\Policies\\Mozilla\\Firefox\\'
|
||||
__registry_branch = 'Software/Policies/Mozilla/Firefox'
|
||||
__firefox_installdir1 = '/usr/lib64/firefox/distribution'
|
||||
__firefox_installdir2 = '/etc/firefox/policies'
|
||||
|
||||
@@ -69,7 +69,7 @@ class firefox_applier(applier_frontend):
|
||||
'''
|
||||
Parse registry path string and leave key parameters
|
||||
'''
|
||||
parts = hivekeyname.replace(self.__registry_branch, '').split('\\')
|
||||
parts = hivekeyname.replace(self.__registry_branch, '').split('/')
|
||||
return parts
|
||||
|
||||
def create_dict(self, firefox_keys):
|
||||
@@ -83,6 +83,10 @@ class firefox_applier(applier_frontend):
|
||||
try:
|
||||
if type(it_data.data) is bytes:
|
||||
it_data.data = it_data.data.decode(encoding='utf-16').replace('\x00','')
|
||||
json_data = try_dict_to_literal_eval(it_data.data)
|
||||
if json_data:
|
||||
it_data.data = json_data
|
||||
it_data.type = 7
|
||||
#Cases when it is necessary to create nested dictionaries
|
||||
if it_data.valuename != it_data.data:
|
||||
parts = self.get_parts(it_data.hive_key)
|
||||
@@ -95,6 +99,8 @@ class firefox_applier(applier_frontend):
|
||||
branch[parts[-1]] = int(it_data.data)
|
||||
else:
|
||||
branch[parts[-1]] = self.get_boolean(it_data.data)
|
||||
elif it_data.type == 7:
|
||||
branch[parts[-1]] = it_data.data
|
||||
else:
|
||||
branch[parts[-1]] = str(it_data.data).replace('\\', '/')
|
||||
#Cases when it is necessary to create lists in a dictionary
|
||||
@@ -164,6 +170,9 @@ def dict_item_to_list(dictionary:dict) -> dict:
|
||||
'''
|
||||
Replacing dictionaries with numeric keys with a List
|
||||
'''
|
||||
if '' in dictionary:
|
||||
dictionary = dictionary.pop('')
|
||||
|
||||
for key,val in dictionary.items():
|
||||
if type(val) == dict:
|
||||
if key_dict_is_digit(val):
|
||||
|
||||
@@ -128,8 +128,8 @@ class frontend_manager:
|
||||
'''
|
||||
|
||||
def __init__(self, username, is_machine):
|
||||
self.storage = registry_factory('registry')
|
||||
self.username = determine_username(username)
|
||||
self.storage = registry_factory('dconf', username=self.username)
|
||||
self.is_machine = is_machine
|
||||
self.process_uname = get_process_user()
|
||||
self.sid = get_sid(self.storage.get_info('domain'), self.username, is_machine)
|
||||
|
||||
@@ -59,14 +59,14 @@ class gsettings_applier(applier_frontend):
|
||||
__module_name = 'GSettingsApplier'
|
||||
__module_experimental = False
|
||||
__module_enabled = True
|
||||
__registry_branch = 'Software\\BaseALT\\Policies\\GSettings\\'
|
||||
__registry_branch = 'Software\\BaseALT\\Policies\\gsettings\\'
|
||||
__registry_locks_branch = 'Software\\BaseALT\\Policies\\GSettingsLocks\\'
|
||||
__wallpaper_entry = 'Software\\BaseALT\\Policies\\GSettings\\org.mate.background.picture-filename'
|
||||
__vino_authentication_methods_entry = 'Software\\BaseALT\\Policies\\GSettings\\org.gnome.Vino.authentication-methods'
|
||||
__wallpaper_entry = 'Software/BaseALT/Policies/gsettings/org.mate.background.picture-filename'
|
||||
__vino_authentication_methods_entry = 'Software/BaseALT/Policies/gsettings/org.gnome.Vino.authentication-methods'
|
||||
__global_schema = '/usr/share/glib-2.0/schemas'
|
||||
__override_priority_file = 'zzz_policy.gschema.override'
|
||||
__override_old_file = '0_policy.gschema.override'
|
||||
__windows_settings = dict()
|
||||
|
||||
|
||||
def __init__(self, storage, file_cache):
|
||||
self.storage = storage
|
||||
@@ -108,13 +108,13 @@ class gsettings_applier(applier_frontend):
|
||||
|
||||
# Get all configured gsettings locks
|
||||
for lock in self.gsettings_locks:
|
||||
valuename = lock.hive_key.rpartition('\\')[2]
|
||||
valuename = lock.hive_key.rpartition('/')[2]
|
||||
self.locks[valuename] = int(lock.data)
|
||||
|
||||
# Calculate all configured gsettings
|
||||
for setting in self.gsettings_keys:
|
||||
helper = None
|
||||
valuename = setting.hive_key.rpartition('\\')[2]
|
||||
valuename = setting.hive_key.rpartition('/')[2]
|
||||
rp = valuename.rpartition('.')
|
||||
schema = rp[0]
|
||||
path = rp[2]
|
||||
@@ -184,9 +184,9 @@ class gsettings_applier_user(applier_frontend):
|
||||
__module_name = 'GSettingsApplierUser'
|
||||
__module_experimental = False
|
||||
__module_enabled = True
|
||||
__registry_branch = 'Software\\BaseALT\\Policies\\GSettings\\'
|
||||
__wallpaper_entry = 'Software\\BaseALT\\Policies\\GSettings\\org.mate.background.picture-filename'
|
||||
__vino_authentication_methods_entry = 'Software\\BaseALT\\Policies\\GSettings\\org.gnome.Vino.authentication-methods'
|
||||
__registry_branch = 'Software\\BaseALT\\Policies\\gsettings\\'
|
||||
__wallpaper_entry = 'Software/BaseALT/Policies/gsettings/org.mate.background.picture-filename'
|
||||
__vino_authentication_methods_entry = 'Software/BaseALT/Policies/gsettings/org.gnome.Vino.authentication-methods'
|
||||
|
||||
def __init__(self, storage, file_cache, sid, username):
|
||||
self.storage = storage
|
||||
@@ -204,25 +204,25 @@ class gsettings_applier_user(applier_frontend):
|
||||
mapping = [
|
||||
# Disable or enable screen saver
|
||||
GSettingsMapping(
|
||||
'Software\\Policies\\Microsoft\\Windows\\Control Panel\\Desktop\\ScreenSaveActive'
|
||||
'Software/Policies/Microsoft/Windows/Control Panel/Desktop/ScreenSaveActive'
|
||||
, 'org.mate.screensaver'
|
||||
, 'idle-activation-enabled'
|
||||
)
|
||||
# Timeout in seconds for screen saver activation. The value of zero effectively disables screensaver start
|
||||
, GSettingsMapping(
|
||||
'Software\\Policies\\Microsoft\\Windows\\Control Panel\\Desktop\\ScreenSaveTimeOut'
|
||||
'Software/Policies/Microsoft/Windows/Control Panel/Desktop/ScreenSaveTimeOut'
|
||||
, 'org.mate.session'
|
||||
, 'idle-delay'
|
||||
)
|
||||
# Enable or disable password protection for screen saver
|
||||
, GSettingsMapping(
|
||||
'Software\\Policies\\Microsoft\\Windows\\Control Panel\\Desktop\\ScreenSaverIsSecure'
|
||||
'Software/Policies/Microsoft/Windows/Control Panel/Desktop/ScreenSaverIsSecure'
|
||||
, 'org.mate.screensaver'
|
||||
, 'lock-enabled'
|
||||
)
|
||||
# Specify image which will be used as a wallpaper
|
||||
, GSettingsMapping(
|
||||
'Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System\\Wallpaper'
|
||||
'Software/Microsoft/Windows/CurrentVersion/Policies/System/Wallpaper'
|
||||
, 'org.mate.background'
|
||||
, 'picture-filename'
|
||||
)
|
||||
@@ -251,15 +251,6 @@ class gsettings_applier_user(applier_frontend):
|
||||
return uri_fetch(schema, path, value, self.file_cache)
|
||||
|
||||
def run(self):
|
||||
#for setting in self.gsettings_keys:
|
||||
# valuename = setting.hive_key.rpartition('\\')[2]
|
||||
# rp = valuename.rpartition('.')
|
||||
# schema = rp[0]
|
||||
# path = rp[2]
|
||||
# self.gsettings.append(user_gsetting(schema, path, setting.data))
|
||||
|
||||
|
||||
# Calculate all mapped gsettings if mapping enabled
|
||||
if self.__windows_mapping_enabled:
|
||||
log('D83')
|
||||
self.windows_mapping_append()
|
||||
@@ -268,7 +259,7 @@ class gsettings_applier_user(applier_frontend):
|
||||
|
||||
# Calculate all configured gsettings
|
||||
for setting in self.gsettings_keys:
|
||||
valuename = setting.hive_key.rpartition('\\')[2]
|
||||
valuename = setting.hive_key.rpartition('/')[2]
|
||||
rp = valuename.rpartition('.')
|
||||
schema = rp[0]
|
||||
path = rp[2]
|
||||
@@ -293,7 +284,7 @@ class gsettings_applier_user(applier_frontend):
|
||||
try:
|
||||
entry = self.__wallpaper_entry
|
||||
filter_result = self.storage.get_hkcu_entry(self.sid, entry)
|
||||
if filter_result:
|
||||
if filter_result and filter_result.data:
|
||||
self.file_cache.store(filter_result.data)
|
||||
except NotUNCPathError:
|
||||
...
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2023 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2024 BaseALT Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -101,7 +101,7 @@ def create_dict(kde_settings, all_kde_settings, locks_settings, locks_dict, file
|
||||
locks_dict[locks.valuename] = locks.data
|
||||
for setting in kde_settings:
|
||||
try:
|
||||
file_name, section, value = setting.keyname.split("\\")[-2], setting.keyname.split("\\")[-1], setting.valuename
|
||||
file_name, section, value = setting.keyname.split("/")[-2], setting.keyname.split("/")[-1], setting.valuename
|
||||
data = setting.data
|
||||
if file_name == 'wallpaper':
|
||||
apply_for_wallpaper(data, file_cache, username)
|
||||
@@ -124,17 +124,31 @@ def create_dict(kde_settings, all_kde_settings, locks_settings, locks_dict, file
|
||||
def apply(all_kde_settings, locks_dict, username = None):
|
||||
logdata = dict()
|
||||
if username is None:
|
||||
system_path_settings = '/etc/xdg/'
|
||||
system_files = [
|
||||
"baloofilerc",
|
||||
"kcminputrc",
|
||||
"kded_device_automounterrc",
|
||||
"kdeglobals",
|
||||
"ksplashrc",
|
||||
"kwinrc",
|
||||
"plasma-localerc",
|
||||
"plasmarc",
|
||||
"powermanagementprofilesrc"
|
||||
]
|
||||
for file in system_files:
|
||||
file_to_remove = f'{system_path_settings}{file}'
|
||||
if os.path.exists(file_to_remove):
|
||||
os.remove(file_to_remove)
|
||||
for file_name, sections in all_kde_settings.items():
|
||||
file_path = f'/etc/xdg/{file_name}'
|
||||
if os.path.exists(file_path):
|
||||
os.remove(file_path)
|
||||
file_path = f'{system_path_settings}{file_name}'
|
||||
with open(file_path, 'w') as file:
|
||||
for section, keys in sections.items():
|
||||
section = section.replace(')(', '][')
|
||||
file.write(f'[{section}]\n')
|
||||
for key, value in keys.items():
|
||||
lock = f"{file_name}.{section}.{key}".replace('][', ')(')
|
||||
if lock in locks_dict and locks_dict[lock] == '1':
|
||||
if lock in locks_dict and locks_dict[lock] == 1:
|
||||
file.write(f'{key}[$i]={value}\n')
|
||||
else:
|
||||
file.write(f'{key}={value}\n')
|
||||
@@ -149,7 +163,7 @@ def apply(all_kde_settings, locks_dict, username = None):
|
||||
for section, keys in sections.items():
|
||||
for key, value in keys.items():
|
||||
lock = f"{file_name}.{section}.{key}"
|
||||
if lock in locks_dict and locks_dict[lock] == '1':
|
||||
if lock in locks_dict and locks_dict[lock] == 1:
|
||||
command = [
|
||||
'kwriteconfig5',
|
||||
'--file', file_name,
|
||||
@@ -275,4 +289,4 @@ def get_id_desktop(path_to_wallpaper):
|
||||
else:
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
return None
|
||||
|
||||
@@ -62,8 +62,7 @@ class package_applier(applier_frontend):
|
||||
)
|
||||
def run(self):
|
||||
for flag in self.sync_packages_setting:
|
||||
if flag.data:
|
||||
self.flagSync = bool(int(flag.data))
|
||||
self.flagSync = bool(flag.data)
|
||||
|
||||
if 0 < self.install_packages_setting.count() or 0 < self.remove_packages_setting.count():
|
||||
if self.flagSync:
|
||||
@@ -104,8 +103,8 @@ class package_applier_user(applier_frontend):
|
||||
self.username = username
|
||||
self.fulcmd = list()
|
||||
self.fulcmd.append('/usr/libexec/gpupdate/pkcon_runner')
|
||||
self.fulcmd.append('--sid')
|
||||
self.fulcmd.append(self.sid)
|
||||
self.fulcmd.append('--user')
|
||||
self.fulcmd.append(self.username)
|
||||
self.fulcmd.append('--loglevel')
|
||||
logger = logging.getLogger()
|
||||
self.fulcmd.append(str(logger.level))
|
||||
@@ -119,7 +118,7 @@ class package_applier_user(applier_frontend):
|
||||
self.sync_packages_setting = self.storage.filter_hkcu_entries(self.sid, sync_branch)
|
||||
self.flagSync = False
|
||||
|
||||
self.__module_enabled = check_enabled(self.storage, self.__module_name, self.__module_enabled)
|
||||
self.__module_enabled = check_enabled(self.storage, self.__module_name, self.__module_experimental)
|
||||
|
||||
def user_context_apply(self):
|
||||
'''
|
||||
|
||||
@@ -26,8 +26,8 @@ from util.logging import log
|
||||
|
||||
class polkit_applier(applier_frontend):
|
||||
__module_name = 'PolkitApplier'
|
||||
__module_experimental = True
|
||||
__module_enabled = False
|
||||
__module_experimental = False
|
||||
__module_enabled = True
|
||||
__deny_all_win = 'Software\\Policies\\Microsoft\\Windows\\RemovableStorageDevices\\Deny_All'
|
||||
__registry_branch = 'Software\\BaseALT\\Policies\\Polkit\\'
|
||||
__registry_locks_branch = 'Software\\BaseALT\\Policies\\PolkitLocks\\'
|
||||
@@ -106,8 +106,8 @@ class polkit_applier(applier_frontend):
|
||||
|
||||
class polkit_applier_user(applier_frontend):
|
||||
__module_name = 'PolkitApplierUser'
|
||||
__module_experimental = True
|
||||
__module_enabled = False
|
||||
__module_experimental = False
|
||||
__module_enabled = True
|
||||
__deny_all_win = 'Software\\Policies\\Microsoft\\Windows\\RemovableStorageDevices\\Deny_All'
|
||||
__registry_branch = 'Software\\BaseALT\\Policies\\Polkit\\'
|
||||
__polkit_map = {
|
||||
|
||||
@@ -148,10 +148,10 @@ def install_script(storage_script_entry, script_dir, access_permissions):
|
||||
shutil.copyfile(storage_script_entry.path, script_file)
|
||||
|
||||
os.chmod(script_file, int(access_permissions, base = 8))
|
||||
if storage_script_entry.arg:
|
||||
if storage_script_entry.args:
|
||||
dir_path = script_dir + '/' + script_name + '.arg'
|
||||
dir_arg = Path(dir_path)
|
||||
dir_arg.mkdir(parents=True, exist_ok=True)
|
||||
file_arg = open(dir_path + '/arg', 'w')
|
||||
file_arg.write(storage_script_entry.arg)
|
||||
file_arg.write(storage_script_entry.args)
|
||||
file_arg.close()
|
||||
|
||||
@@ -38,8 +38,7 @@ def storage_get_shortcuts(storage, sid, username=None):
|
||||
shortcut_objs = storage.get_shortcuts(sid)
|
||||
shortcuts = list()
|
||||
|
||||
for sc_obj in shortcut_objs:
|
||||
sc = json2sc(sc_obj.shortcut)
|
||||
for sc in shortcut_objs:
|
||||
if username:
|
||||
sc.set_expanded_path(expand_windows_var(sc.path, username))
|
||||
shortcuts.append(sc)
|
||||
|
||||
@@ -29,11 +29,11 @@ class systemd_applier(applier_frontend):
|
||||
__module_name = 'SystemdApplier'
|
||||
__module_experimental = False
|
||||
__module_enabled = True
|
||||
__registry_branch = 'Software\\BaseALT\\Policies\\SystemdUnits'
|
||||
__registry_branch = 'Software/BaseALT/Policies/SystemdUnits'
|
||||
|
||||
def __init__(self, storage):
|
||||
self.storage = storage
|
||||
self.systemd_unit_settings = self.storage.filter_hklm_entries('Software\\BaseALT\\Policies\\SystemdUnits%')
|
||||
self.systemd_unit_settings = self.storage.filter_hklm_entries(self.__registry_branch)
|
||||
self.units = []
|
||||
self.__module_enabled = check_enabled(
|
||||
self.storage
|
||||
@@ -43,7 +43,7 @@ class systemd_applier(applier_frontend):
|
||||
|
||||
def run(self):
|
||||
for setting in self.systemd_unit_settings:
|
||||
valuename = setting.hive_key.rpartition('\\')[2]
|
||||
valuename = setting.hive_key.rpartition('/')[2]
|
||||
try:
|
||||
self.units.append(systemd_unit(valuename, int(setting.data)))
|
||||
logdata = dict()
|
||||
@@ -76,7 +76,7 @@ class systemd_applier_user(applier_frontend):
|
||||
__module_name = 'SystemdApplierUser'
|
||||
__module_experimental = False
|
||||
__module_enabled = True
|
||||
__registry_branch = 'Software\\BaseALT\\Policies\\SystemdUnits'
|
||||
__registry_branch = 'Software/BaseALT/Policies/SystemdUnits'
|
||||
|
||||
def __init__(self, storage, sid, username):
|
||||
self.storage = storage
|
||||
|
||||
@@ -30,7 +30,7 @@ class yandex_browser_applier(applier_frontend):
|
||||
__module_name = 'YandexBrowserApplier'
|
||||
__module_enabled = True
|
||||
__module_experimental = False
|
||||
__registry_branch = 'Software\\Policies\\YandexBrowser'
|
||||
__registry_branch = 'Software/Policies/YandexBrowser'
|
||||
__managed_policies_path = '/etc/opt/yandex/browser/policies/managed'
|
||||
__recommended_policies_path = '/etc/opt/yandex/browser/policies/recommended'
|
||||
|
||||
@@ -152,7 +152,7 @@ class yandex_browser_applier(applier_frontend):
|
||||
'''
|
||||
Parse registry path string and leave key parameters
|
||||
'''
|
||||
parts = hivekeyname.replace(self.__registry_branch, '').split('\\')
|
||||
parts = hivekeyname.replace(self.__registry_branch, '').split('/')
|
||||
return parts
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import signal
|
||||
import gettext
|
||||
import locale
|
||||
|
||||
from backend import backend_factory
|
||||
from backend import backend_factory, save_dconf
|
||||
from frontend.frontend_manager import frontend_manager, determine_username
|
||||
from plugin import plugin_manager
|
||||
from messages import message_with_code
|
||||
@@ -159,6 +159,7 @@ class gpoa_controller:
|
||||
einfo = geterr()
|
||||
logdata.update(einfo)
|
||||
log('E3', logdata)
|
||||
save_dconf(self.username, self.is_machine)
|
||||
|
||||
def start_frontend(self):
|
||||
'''
|
||||
|
||||
@@ -70,6 +70,7 @@ def read_folders(folders_file):
|
||||
|
||||
folders.append(fld_obj)
|
||||
|
||||
|
||||
return folders
|
||||
|
||||
def merge_folders(storage, sid, folder_objects, policy_name):
|
||||
|
||||
@@ -153,10 +153,13 @@ def get_merger(preference_type):
|
||||
return mergers[preference_type]
|
||||
|
||||
class gpt:
|
||||
def __init__(self, gpt_path, sid):
|
||||
def __init__(self, gpt_path, sid, username='Machine', version=None):
|
||||
self.path = gpt_path
|
||||
self.username = username
|
||||
self.sid = sid
|
||||
self.storage = registry_factory('registry')
|
||||
self.storage = registry_factory()
|
||||
self.storage._gpt_read_flag = True
|
||||
self.version = version
|
||||
self.name = ''
|
||||
self.guid = self.path.rpartition('/')[2]
|
||||
if 'default' == self.guid:
|
||||
@@ -214,7 +217,7 @@ class gpt:
|
||||
if self.settings['machine']['regpol']:
|
||||
mlogdata = dict({'polfile': self.settings['machine']['regpol']})
|
||||
log('D34', mlogdata)
|
||||
util.preg.merge_polfile(self.settings['machine']['regpol'], policy_name=self.name)
|
||||
util.preg.merge_polfile(self.settings['machine']['regpol'], policy_name=self.name, version=self.version)
|
||||
# Merge machine preferences to registry if possible
|
||||
for preference_name, preference_path in self.settings['machine'].items():
|
||||
if preference_path:
|
||||
@@ -240,7 +243,11 @@ class gpt:
|
||||
if self.settings['user']['regpol']:
|
||||
mulogdata = dict({'polfile': self.settings['user']['regpol']})
|
||||
log('D35', mulogdata)
|
||||
util.preg.merge_polfile(self.settings['user']['regpol'], sid=self.sid, policy_name=self.name)
|
||||
util.preg.merge_polfile(self.settings['user']['regpol'],
|
||||
sid=self.sid,
|
||||
policy_name=self.name,
|
||||
username=self.username,
|
||||
version=self.version)
|
||||
# Merge user preferences to registry if possible
|
||||
for preference_name, preference_path in self.settings['user'].items():
|
||||
if preference_path:
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from util.xml import get_xml_root
|
||||
from storage.dconf_registry import Dconf_registry
|
||||
|
||||
def read_networkshares(networksharesxml):
|
||||
networkshares = list()
|
||||
|
||||
@@ -24,9 +24,10 @@ def read_polfile(filename):
|
||||
return load_preg(filename).entries
|
||||
|
||||
def merge_polfile(storage, sid, policy_objects, policy_name):
|
||||
for entry in policy_objects:
|
||||
if not sid:
|
||||
storage.add_hklm_entry(entry, policy_name)
|
||||
else:
|
||||
storage.add_hkcu_entry(entry, sid, policy_name)
|
||||
pass
|
||||
# for entry in policy_objects:
|
||||
# if not sid:
|
||||
# storage.add_hklm_entry(entry, policy_name)
|
||||
# else:
|
||||
# storage.add_hkcu_entry(entry, sid, policy_name)
|
||||
|
||||
|
||||
@@ -61,19 +61,19 @@ def read_scripts(scripts_file):
|
||||
section_scripts[key_index].set_args(config[act][key])
|
||||
if logon_scripts:
|
||||
for i in sorted(logon_scripts.keys()):
|
||||
scripts.add_script(act_upper, logon_scripts[i])
|
||||
scripts.add_script('LOGON', logon_scripts[i])
|
||||
|
||||
if logoff_scripts:
|
||||
for i in sorted(logoff_scripts.keys()):
|
||||
scripts.add_script(act_upper, logoff_scripts[i])
|
||||
scripts.add_script('LOGOFF', logoff_scripts[i])
|
||||
|
||||
if startup_scripts:
|
||||
for i in sorted(startup_scripts.keys()):
|
||||
scripts.add_script(act_upper, startup_scripts[i])
|
||||
scripts.add_script('STARTUP', startup_scripts[i])
|
||||
|
||||
if shutdown_scripts:
|
||||
for i in sorted(shutdown_scripts.keys()):
|
||||
scripts.add_script(act_upper, shutdown_scripts[i])
|
||||
scripts.add_script('SHUTDOWN', shutdown_scripts[i])
|
||||
|
||||
|
||||
return scripts
|
||||
|
||||
@@ -27,6 +27,7 @@ import json
|
||||
|
||||
from util.windows import transform_windows_path
|
||||
from util.xml import get_xml_root
|
||||
from util.paths import get_desktop_files_directory
|
||||
|
||||
class TargetType(Enum):
|
||||
FILESYSTEM = 'FILESYSTEM'
|
||||
@@ -115,6 +116,19 @@ def json2sc(json_str):
|
||||
|
||||
return sc
|
||||
|
||||
def find_desktop_entry(binary_path):
|
||||
desktop_dir = get_desktop_files_directory()
|
||||
binary_name = ''.join(binary_path.split('/')[-1])
|
||||
desktop_file_path = Path(f"{desktop_dir}/{binary_name}.desktop")
|
||||
|
||||
if desktop_file_path.exists():
|
||||
desktop_entry = DesktopEntry()
|
||||
desktop_entry.parse(desktop_file_path)
|
||||
return desktop_entry
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class shortcut:
|
||||
def __init__(self, dest, path, arguments, name=None, action=None, ttype=TargetType.FILESYSTEM):
|
||||
'''
|
||||
@@ -135,6 +149,7 @@ class shortcut:
|
||||
self.comment = ''
|
||||
self.is_in_user_context = self.set_usercontext()
|
||||
self.type = ttype
|
||||
self.desktop_file_template = None
|
||||
|
||||
def replace_slashes(self, input_path):
|
||||
if input_path.startswith('%'):
|
||||
@@ -233,6 +248,7 @@ class shortcut:
|
||||
if dest:
|
||||
self.desktop_file = DesktopEntry(dest)
|
||||
else:
|
||||
self.desktop_file_template = find_desktop_entry(self.path)
|
||||
self.desktop_file = DesktopEntry()
|
||||
self.desktop_file.addGroup('Desktop Entry')
|
||||
self.desktop_file.set('Version', '1.0')
|
||||
@@ -257,12 +273,18 @@ class shortcut:
|
||||
if self.type == TargetType.URL:
|
||||
self.desktop_file.set('URL', desktop_path)
|
||||
else:
|
||||
self.desktop_file.set('Terminal', 'false')
|
||||
str2bool_lambda = (lambda boolstr: boolstr if isinstance(boolstr, bool)
|
||||
else boolstr and boolstr.lower() in ['True', 'true', 'yes', '1'])
|
||||
if self.desktop_file_template:
|
||||
terminal_state = str2bool_lambda(self.desktop_file_template.get('Terminal'))
|
||||
self.desktop_file.set('Terminal', 'true' if terminal_state else 'false')
|
||||
self.desktop_file.set('Exec', '{} {}'.format(desktop_path, self.arguments))
|
||||
self.desktop_file.set('Comment', self.comment)
|
||||
|
||||
if self.icon:
|
||||
self.desktop_file.set('Icon', self.icon)
|
||||
elif self.desktop_file_template and self.desktop_file_template.get('Icon', False):
|
||||
self.desktop_file.set('Icon', self.desktop_file_template.get('Icon'))
|
||||
|
||||
def _write_desktop(self, dest, create_only=False, read_firstly=False):
|
||||
'''
|
||||
|
||||
@@ -240,6 +240,18 @@ msgstr "Ошибка создания переменных среды"
|
||||
msgid "Error running kwriteconfig5 command"
|
||||
msgstr "Ошибка выполнения команды kwriteconfig5"
|
||||
|
||||
msgid "Error getting list of keys"
|
||||
msgstr "Ошибка получения списка ключей"
|
||||
|
||||
msgid "Error getting key value"
|
||||
msgstr "Ошибка при получении значения ключей"
|
||||
|
||||
msgid "Failed to update dconf database"
|
||||
msgstr "Не удалось обновить базу данных dconf"
|
||||
|
||||
msgid "Exception occurred while updating dconf database"
|
||||
msgstr "Возникло исключение при обновлении базы данных dconf"
|
||||
|
||||
# Error_end
|
||||
|
||||
# Debug
|
||||
@@ -837,6 +849,27 @@ msgstr "Изменение конфигурационного файла"
|
||||
msgid "Widget command completed successfully"
|
||||
msgstr "Команда для виджетов выполнена успешно"
|
||||
|
||||
msgid "Getting a list of keys"
|
||||
msgstr "Получение списка ключей"
|
||||
|
||||
msgid "Getting the key value"
|
||||
msgstr "Получение значения ключа"
|
||||
|
||||
msgid "Successfully updated dconf database"
|
||||
msgstr "База данных dconf успешно обновлена"
|
||||
|
||||
msgid "Creating a dictionary with keys and values from the dconf database"
|
||||
msgstr "Формирование словаря с ключами и значениями из базы dconf"
|
||||
|
||||
msgid "No entry found for the specified path"
|
||||
msgstr "Не найдено записей по указанному пути"
|
||||
|
||||
msgid "Creating an ini file with policies for dconf"
|
||||
msgstr "Создание ini-файла с политиками для dconf"
|
||||
|
||||
msgid "GPO version was not found"
|
||||
msgstr "Версия GPO не найдена"
|
||||
|
||||
# Debug_end
|
||||
|
||||
# Warning
|
||||
@@ -904,12 +937,15 @@ msgstr "Ошибка при подключении к серверу"
|
||||
msgid "Wallpaper configuration file not found"
|
||||
msgstr "Конфигурационный файл для обоев не найден"
|
||||
|
||||
msgid "The user setting was not installed, conflict with computer setting."
|
||||
msgstr "Пользовательская настройка не была установлена, конфликт с настройкой компьютера."
|
||||
msgid "The user setting was not installed, conflict with computer setting"
|
||||
msgstr "Пользовательская настройка не была установлена, конфликт с настройкой компьютера"
|
||||
|
||||
msgid "Action for ini file failed"
|
||||
msgstr "Не удалось выполнить действие для INI-файла"
|
||||
|
||||
msgid "Couldn't get the uid"
|
||||
msgstr "Не удалось получить uid"
|
||||
|
||||
# Fatal
|
||||
msgid "Unable to refresh GPO list"
|
||||
msgstr "Невозможно обновить список объектов групповых политик"
|
||||
|
||||
@@ -103,6 +103,10 @@ def error_code(code):
|
||||
error_ids[66] = 'Error while executing command for widgets'
|
||||
error_ids[67] = 'Error creating environment variables'
|
||||
error_ids[68] = 'Error running kwriteconfig5 command'
|
||||
error_ids[69] = 'Error getting list of keys'
|
||||
error_ids[70] = 'Error getting key value'
|
||||
error_ids[71] = 'Failed to update dconf database'
|
||||
error_ids[72] = 'Exception occurred while updating dconf database'
|
||||
return error_ids.get(code, 'Unknown error code')
|
||||
|
||||
def debug_code(code):
|
||||
@@ -310,6 +314,14 @@ def debug_code(code):
|
||||
debug_ids[201] = 'KDE applier for user in user context will not be started'
|
||||
debug_ids[202] = 'Changing the configuration file'
|
||||
debug_ids[203] = 'Widget command completed successfully'
|
||||
debug_ids[204] = 'Getting a list of keys'
|
||||
debug_ids[205] = 'Getting the key value'
|
||||
debug_ids[206] = 'Successfully updated dconf database'
|
||||
debug_ids[207] = 'Creating a dictionary with keys and values from the dconf database'
|
||||
debug_ids[208] = 'No entry found for the specified path'
|
||||
debug_ids[209] = 'Creating an ini file with policies for dconf'
|
||||
debug_ids[210] = 'GPO version was not found'
|
||||
|
||||
return debug_ids.get(code, 'Unknown debug code')
|
||||
|
||||
def warning_code(code):
|
||||
@@ -341,8 +353,9 @@ def warning_code(code):
|
||||
warning_ids[19] = 'Failed to change KDE configuration file'
|
||||
warning_ids[20] = 'Error connecting to server'
|
||||
warning_ids[21] = 'Wallpaper configuration file not found'
|
||||
warning_ids[22] = 'The user setting was not installed, conflict with computer setting.'
|
||||
warning_ids[22] = 'The user setting was not installed, conflict with computer setting'
|
||||
warning_ids[23] = 'Action for ini file failed'
|
||||
warning_ids[24] = 'Couldn\'t get the uid'
|
||||
|
||||
|
||||
return warning_ids.get(code, 'Unknown warning code')
|
||||
|
||||
@@ -44,27 +44,21 @@ def is_rpm_installed(rpm_name):
|
||||
|
||||
class Pkcon_applier:
|
||||
|
||||
def __init__(self, sid = None):
|
||||
def __init__(self, user = None):
|
||||
self.__install_key_name = 'Install'
|
||||
self.__remove_key_name = 'Remove'
|
||||
self.__hkcu_branch = 'Software\\BaseALT\\Policies\\Packages'
|
||||
self.__hklm_branch = 'Software\\BaseALT\\Policies\\Packages'
|
||||
self.__hklm_branch = '/Software/BaseALT/Policies/Packages'
|
||||
self.__install_command = ['/usr/bin/pkcon', '-y', 'install']
|
||||
self.__remove_command = ['/usr/bin/pkcon', '-y', 'remove']
|
||||
self.__reinstall_command = ['/usr/bin/pkcon', '-y', 'reinstall']
|
||||
self.install_packages = set()
|
||||
self.remove_packages = set()
|
||||
self.storage = registry_factory('registry')
|
||||
if sid:
|
||||
install_branch_user = '{}\\{}%'.format(self.__hkcu_branch, self.__install_key_name)
|
||||
remove_branch_user = '{}\\{}%'.format(self.__hkcu_branch, self.__remove_key_name)
|
||||
self.install_packages_setting = self.storage.filter_hkcu_entries(sid, install_branch_user)
|
||||
self.remove_packages_setting = self.storage.filter_hkcu_entries(sid, remove_branch_user)
|
||||
else:
|
||||
install_branch = '{}\\{}%'.format(self.__hklm_branch, self.__install_key_name)
|
||||
remove_branch = '{}\\{}%'.format(self.__hklm_branch, self.__remove_key_name)
|
||||
self.install_packages_setting = self.storage.filter_hklm_entries(install_branch)
|
||||
self.remove_packages_setting = self.storage.filter_hklm_entries(remove_branch)
|
||||
self.storage = registry_factory(username=user)
|
||||
self.storage.filling_storage_from_dconf()
|
||||
install_branch = '{}/{}'.format(self.__hklm_branch, self.__install_key_name)
|
||||
remove_branch = '{}/{}'.format(self.__hklm_branch, self.__remove_key_name)
|
||||
self.install_packages_setting = self.storage.filter_hklm_entries(install_branch)
|
||||
self.remove_packages_setting = self.storage.filter_hklm_entries(remove_branch)
|
||||
for package in self.install_packages_setting:
|
||||
if not is_rpm_installed(package.data):
|
||||
self.install_packages.add(package.data)
|
||||
@@ -137,13 +131,13 @@ if __name__ == '__main__':
|
||||
gettext.textdomain('gpoa')
|
||||
logger = logging.getLogger()
|
||||
parser = argparse.ArgumentParser(description='Package applier')
|
||||
parser.add_argument('--sid', type = str, help = 'sid', nargs = '?', default = None)
|
||||
parser.add_argument('--user', type = str, help = 'user', nargs = '?', default = None)
|
||||
parser.add_argument('--loglevel', type = int, help = 'loglevel', nargs = '?', default = 30)
|
||||
|
||||
args = parser.parse_args()
|
||||
logger.setLevel(args.loglevel)
|
||||
if args.sid:
|
||||
applier = Pkcon_applier(args.sid)
|
||||
if args.user:
|
||||
applier = Pkcon_applier(args.user)
|
||||
else:
|
||||
applier = Pkcon_applier()
|
||||
applier.apply()
|
||||
|
||||
@@ -21,6 +21,8 @@ import subprocess
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
import psutil
|
||||
import time
|
||||
|
||||
class Scripts_runner:
|
||||
'''
|
||||
@@ -104,12 +106,39 @@ class Scripts_runner:
|
||||
|
||||
def run_cmd_subprocess(self, cmd):
|
||||
try:
|
||||
subprocess.Popen(cmd)
|
||||
subprocess.run(cmd)
|
||||
return 'Script run: {}'.format(cmd)
|
||||
except Exception as exc:
|
||||
return exc
|
||||
|
||||
def find_process_by_name_and_script(name, script_path):
|
||||
|
||||
for proc in psutil.process_iter(['pid', 'name', 'cmdline']):
|
||||
try:
|
||||
# Check if the process name matches and the script path is in the command line arguments
|
||||
if proc.info['name'] == name and script_path in proc.info['cmdline']:
|
||||
return proc
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
||||
continue
|
||||
return None
|
||||
|
||||
def wait_for_process(name, script_path, check_interval=1):
|
||||
|
||||
process = find_process_by_name_and_script(name, script_path)
|
||||
if not process:
|
||||
print(f"Process with name {name} and script path {script_path} not found.")
|
||||
return
|
||||
|
||||
try:
|
||||
# Loop to wait for the process to finish
|
||||
while process.is_running():
|
||||
print(f"Waiting for process {name} with PID {process.pid} to finish...")
|
||||
time.sleep(check_interval)
|
||||
print(f"Process {name} with PID {process.pid} has finished.")
|
||||
return
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
||||
print(f"Process {name} with PID {process.pid} is no longer accessible.")
|
||||
return
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description='Scripts runner')
|
||||
@@ -117,6 +146,9 @@ if __name__ == '__main__':
|
||||
parser.add_argument('--user', type = str, help = 'User name ', nargs = '?', default = None)
|
||||
parser.add_argument('--action', type = str, help = 'MACHINE : [STARTUP or SHUTDOWN], USER : [LOGON or LOGOFF]', nargs = '?', default = None)
|
||||
|
||||
process_name = "python3"
|
||||
script_path = "/usr/sbin/gpoa"
|
||||
wait_for_process(process_name, script_path)
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
Scripts_runner(args.mode, args.user, args.action)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2020 BaseALT Ltd.
|
||||
# Copyright (C) 2019-2023 BaseALT Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -16,12 +16,19 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from .sqlite_registry import sqlite_registry
|
||||
from .sqlite_cache import sqlite_cache
|
||||
|
||||
def cache_factory(cache_name):
|
||||
return sqlite_cache(cache_name)
|
||||
from storage.dconf_registry import Dconf_registry
|
||||
|
||||
def registry_factory(registry_name='registry', registry_dir=None):
|
||||
return sqlite_registry(registry_name, registry_dir)
|
||||
def registry_factory(registry_name='', envprofile=None , username=None):
|
||||
if username:
|
||||
Dconf_registry._username = username
|
||||
else:
|
||||
Dconf_registry._envprofile = 'system'
|
||||
if envprofile:
|
||||
Dconf_registry._envprofile = envprofile
|
||||
|
||||
if registry_name == 'dconf':
|
||||
return Dconf_registry()
|
||||
else:
|
||||
return Dconf_registry
|
||||
|
||||
|
||||
591
gpoa/storage/dconf_registry.py
Normal file
591
gpoa/storage/dconf_registry.py
Normal file
@@ -0,0 +1,591 @@
|
||||
#
|
||||
# GPOA - GPO Applier for Linux
|
||||
#
|
||||
# Copyright (C) 2019-2023 BaseALT Ltd.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# 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 subprocess
|
||||
from pathlib import Path
|
||||
from util.util import string_to_literal_eval, touch_file, get_uid_by_username
|
||||
from util.logging import log
|
||||
import re
|
||||
|
||||
|
||||
class PregDconf():
|
||||
def __init__(self, keyname, valuename, type_preg, data):
|
||||
self.keyname = keyname
|
||||
self.valuename = valuename
|
||||
self.hive_key = '{}/{}'.format(self.keyname, self.valuename)
|
||||
self.type = type_preg
|
||||
self.data = data
|
||||
|
||||
|
||||
class gplist(list):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def first(self):
|
||||
if self:
|
||||
return self[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def count(self):
|
||||
return len(self)
|
||||
|
||||
class Dconf_registry():
|
||||
'''
|
||||
A class variable that represents a global registry dictionary shared among instances of the class
|
||||
'''
|
||||
_ReadQueue = 'Software/BaseALT/Policies/ReadQueue'
|
||||
global_registry_dict = dict({_ReadQueue:{}})
|
||||
__template_file = '/usr/share/dconf/user_mandatory.template'
|
||||
_policies_path = 'Software/'
|
||||
_policies_win_path = 'SOFTWARE/'
|
||||
_gpt_read_flag = False
|
||||
__dconf_dict_flag = False
|
||||
__dconf_dict = dict()
|
||||
_username = None
|
||||
_envprofile = None
|
||||
|
||||
list_keys = list()
|
||||
_info = dict()
|
||||
|
||||
shortcuts = list()
|
||||
folders = list()
|
||||
files = list()
|
||||
drives = list()
|
||||
scheduledtasks = list()
|
||||
environmentvariables = list()
|
||||
inifiles = list()
|
||||
services = list()
|
||||
printers = list()
|
||||
scripts = list()
|
||||
networkshares = list()
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def set_info(cls, key , data):
|
||||
cls._info[key] = data
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_info(cls, key):
|
||||
return cls._info.setdefault(key, None)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_matching_keys(path):
|
||||
if path[0] != '/':
|
||||
path = '/' + path
|
||||
logdata = dict()
|
||||
envprofile = get_dconf_envprofile()
|
||||
try:
|
||||
process = subprocess.Popen(['dconf', 'list', path],
|
||||
env=envprofile, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
logdata['path'] = path
|
||||
log('D204', logdata)
|
||||
output, error = process.communicate()
|
||||
if not output and not error:
|
||||
return
|
||||
if not error:
|
||||
keys = output.strip().split('\n')
|
||||
for key in keys:
|
||||
Dconf_registry.get_matching_keys(f'{path}{key}')
|
||||
else:
|
||||
Dconf_registry.list_keys.append(path)
|
||||
return Dconf_registry.list_keys
|
||||
except Exception as exc:
|
||||
logdata['exc'] = exc
|
||||
log('E69', logdata)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def get_key_values(keys):
|
||||
key_values = {}
|
||||
for key in keys:
|
||||
key_values[key] = Dconf_registry.get_key_value(key)
|
||||
return key_values
|
||||
|
||||
@staticmethod
|
||||
def get_key_value(key):
|
||||
logdata = dict()
|
||||
envprofile = get_dconf_envprofile()
|
||||
try:
|
||||
process = subprocess.Popen(['dconf', 'read', key],
|
||||
env=envprofile, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
logdata['key'] = key
|
||||
output, error = process.communicate()
|
||||
|
||||
if not error:
|
||||
return string_to_literal_eval(string_to_literal_eval(output))
|
||||
else:
|
||||
return None
|
||||
except Exception as exc:
|
||||
logdata['exc'] = exc
|
||||
log('E70', logdata)
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def dconf_update():
|
||||
logdata = dict()
|
||||
try:
|
||||
process = subprocess.Popen(['dconf', 'update'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
output, error = process.communicate()
|
||||
|
||||
if error:
|
||||
logdata['error'] = error
|
||||
log('E71', logdata)
|
||||
else:
|
||||
logdata['outpupt'] = output
|
||||
log('D206', logdata)
|
||||
except Exception as exc:
|
||||
logdata['exc'] = exc
|
||||
log('E72', logdata)
|
||||
|
||||
@classmethod
|
||||
def check_profile_template(cls):
|
||||
if Path(cls.__template_file).exists():
|
||||
return True
|
||||
else:
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def apply_template(cls, uid):
|
||||
logdata = dict()
|
||||
if uid and cls.check_profile_template():
|
||||
with open(cls.__template_file, "r") as f:
|
||||
template = f.read()
|
||||
# Replace the "{uid}" placeholder with the actual UID value
|
||||
content = template.replace("{{uid}}", str(uid))
|
||||
|
||||
elif uid:
|
||||
content = f"user-db:user\n" \
|
||||
f"system-db:policy\n" \
|
||||
f"system-db:policy{uid}\n" \
|
||||
f"system-db:local\n" \
|
||||
f"system-db:default\n" \
|
||||
f"system-db:local\n" \
|
||||
f"system-db:policy{uid}\n" \
|
||||
f"system-db:policy\n"
|
||||
else:
|
||||
logdata['uid'] = uid
|
||||
log('W24', logdata)
|
||||
return
|
||||
|
||||
user_mandatory = f'/run/dconf/user/{uid}'
|
||||
touch_file(user_mandatory)
|
||||
|
||||
with open(user_mandatory, "w") as f:
|
||||
f.write(content)
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_policies_from_dconf(cls):
|
||||
return cls.get_dictionary_from_dconf(cls._policies_path, cls._policies_win_path)
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_dictionary_from_dconf(self, *startswith_list):
|
||||
output_dict = {}
|
||||
for startswith in startswith_list:
|
||||
dconf_dict = self.get_key_values(self.get_matching_keys(startswith))
|
||||
for key, value in dconf_dict.items():
|
||||
keys_tmp = key.split('/')
|
||||
update_dict(output_dict.setdefault('/'.join(keys_tmp[:-1])[1:], {}), {keys_tmp[-1]: value})
|
||||
|
||||
log('D207')
|
||||
return output_dict
|
||||
|
||||
|
||||
@classmethod
|
||||
def filter_entries(cls, startswith):
|
||||
if startswith[-1] == '%':
|
||||
startswith = startswith[:-1]
|
||||
if startswith[-1] == '/' or startswith[-1] == '\\':
|
||||
startswith = startswith[:-1]
|
||||
return filter_dict_keys(startswith, flatten_dictionary(cls.global_registry_dict))
|
||||
return filter_dict_keys(startswith, flatten_dictionary(cls.global_registry_dict))
|
||||
|
||||
|
||||
@classmethod
|
||||
def filter_hklm_entries(cls, startswith):
|
||||
pregs = cls.filter_entries(startswith)
|
||||
list_entiers = list()
|
||||
for keyname, value in pregs.items():
|
||||
if isinstance(value, dict):
|
||||
for valuename, data in value.items():
|
||||
list_entiers.append(PregDconf(
|
||||
keyname, convert_string_dconf(valuename), find_preg_type(data), data))
|
||||
elif isinstance(value, list):
|
||||
for data in value:
|
||||
list_entiers.append(PregDconf(
|
||||
keyname, convert_string_dconf(data), find_preg_type(data), data))
|
||||
else:
|
||||
list_entiers.append(PregDconf(
|
||||
'/'.join(keyname.split('/')[:-1]), convert_string_dconf(keyname.split('/')[-1]), find_preg_type(value), value))
|
||||
|
||||
|
||||
return gplist(list_entiers)
|
||||
|
||||
|
||||
@classmethod
|
||||
def filter_hkcu_entries(cls, sid, startswith):
|
||||
return cls.filter_hklm_entries(startswith)
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_storage(cls,dictionary = None):
|
||||
if dictionary:
|
||||
result = dictionary
|
||||
elif Dconf_registry._gpt_read_flag:
|
||||
result = Dconf_registry.global_registry_dict
|
||||
else:
|
||||
if Dconf_registry.__dconf_dict_flag:
|
||||
result = Dconf_registry.__dconf_dict
|
||||
else:
|
||||
Dconf_registry.__dconf_dict = Dconf_registry.get_policies_from_dconf()
|
||||
result = Dconf_registry.__dconf_dict
|
||||
Dconf_registry.__dconf_dict_flag = True
|
||||
return result
|
||||
|
||||
|
||||
@classmethod
|
||||
def filling_storage_from_dconf(cls):
|
||||
Dconf_registry.global_registry_dict = Dconf_registry.get_storage()
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_entry(cls, path, dictionary = None):
|
||||
logdata = dict()
|
||||
result = Dconf_registry.get_storage(dictionary)
|
||||
|
||||
keys = path.split("\\") if "\\" in path else path.split("/")
|
||||
key = '/'.join(keys[:-1]) if keys[0] else '/'.join(keys[:-1])[1:]
|
||||
|
||||
if isinstance(result, dict) and key in result.keys():
|
||||
data = result.get(key).get(keys[-1])
|
||||
return PregDconf(
|
||||
key, convert_string_dconf(keys[-1]), find_preg_type(data), data)
|
||||
else:
|
||||
logdata['path'] = path
|
||||
log('D208', logdata)
|
||||
return None
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_hkcu_entry(cls, sid, hive_key, dictionary = None):
|
||||
return cls.get_hklm_entry(hive_key, dictionary)
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_hklm_entry(cls, hive_key, dictionary = None):
|
||||
return cls.get_entry(hive_key, dictionary)
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_shortcut(cls, sid, sc_obj, policy_name):
|
||||
cls.shortcuts.append(sc_obj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_printer(cls, sid, pobj, policy_name):
|
||||
cls.printers.append(pobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_drive(cls, sid, dobj, policy_name):
|
||||
cls.drives.append(dobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_folder(cls, sid, fobj, policy_name):
|
||||
cls.folders.append(fobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_envvar(self, sid, evobj, policy_name):
|
||||
self.environmentvariables.append(evobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_script(cls, sid, scrobj, policy_name):
|
||||
cls.scripts.append(scrobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_file(cls, sid, fileobj, policy_name):
|
||||
cls.files.append(fileobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_ini(cls, sid, iniobj, policy_name):
|
||||
cls.inifiles.append(iniobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def add_networkshare(cls, sid, networkshareobj, policy_name):
|
||||
cls.networkshares.append(networkshareobj)
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_shortcuts(cls, sid):
|
||||
return cls.shortcuts
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_printers(cls, sid):
|
||||
return cls.printers
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_drives(cls, sid):
|
||||
return cls.drives
|
||||
|
||||
@classmethod
|
||||
def get_folders(cls, sid):
|
||||
return cls.folders
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_envvars(cls, sid):
|
||||
return cls.environmentvariables
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_scripts(cls, sid, action):
|
||||
action_scripts = list()
|
||||
for part in cls.scripts:
|
||||
if action == 'LOGON':
|
||||
action_scripts.append(part)
|
||||
elif action == 'LOGOFF':
|
||||
action_scripts.append(part)
|
||||
elif action == 'STARTUP':
|
||||
action_scripts.append(part)
|
||||
elif action == 'SHUTDOWN':
|
||||
action_scripts.append(part)
|
||||
return action_scripts
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_files(cls, sid):
|
||||
return cls.files
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_networkshare(cls, sid):
|
||||
return cls.networkshares
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_ini(cls, sid):
|
||||
return cls.inifiles
|
||||
|
||||
|
||||
@classmethod
|
||||
def wipe_user(cls, sid):
|
||||
cls.wipe_hklm()
|
||||
|
||||
|
||||
@classmethod
|
||||
def wipe_hklm(cls):
|
||||
cls.global_registry_dict = dict({cls._ReadQueue:{}})
|
||||
|
||||
|
||||
def filter_dict_keys(starting_string, input_dict):
|
||||
result = dict()
|
||||
for key in input_dict:
|
||||
key_list = remove_empty_values(re.split(r'\\|/', key))
|
||||
start_list = remove_empty_values(re.split(r'\\|/', starting_string))
|
||||
if key_list[:len(start_list)] == start_list:
|
||||
result[key] = input_dict.get(key)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def find_preg_type(argument):
|
||||
if isinstance(argument, int):
|
||||
return 4
|
||||
else:
|
||||
return 1
|
||||
|
||||
|
||||
def update_dict(dict1, dict2):
|
||||
'''
|
||||
Updates dict1 with the key-value pairs from dict2
|
||||
'''
|
||||
for key, value in dict2.items():
|
||||
if key in dict1:
|
||||
# If both values are dictionaries, recursively call the update_dict function
|
||||
if isinstance(dict1[key], dict) and isinstance(value, dict):
|
||||
update_dict(dict1[key], value)
|
||||
# If the value in dict1 is a list, extend it with unique values from value
|
||||
elif isinstance(dict1[key], list):
|
||||
dict1[key].extend(set(value) - set(dict1[key]))
|
||||
else:
|
||||
# If the value in dict1 is not a dictionary or the value in dict2 is not a dictionary,
|
||||
# replace the value in dict1 with the value from dict2
|
||||
dict1[key] = value
|
||||
else:
|
||||
# If the key does not exist in dict1, add the key-value pair from dict2 to dict1
|
||||
dict1[key] = value
|
||||
|
||||
|
||||
def add_to_dict(string, policy_name, username, version):
|
||||
if username is None:
|
||||
correct_path = '/'.join(string.split('/')[:-2])
|
||||
machine= '{}/Machine'.format(Dconf_registry._ReadQueue)
|
||||
dictionary = Dconf_registry.global_registry_dict.setdefault(machine, dict())
|
||||
else:
|
||||
correct_path = '/'.join(string.split('/')[:-2])
|
||||
user = '{}/User'.format(Dconf_registry._ReadQueue)
|
||||
dictionary = Dconf_registry.global_registry_dict.setdefault(user, dict())
|
||||
|
||||
dictionary[len(dictionary)] = (policy_name, correct_path, version)
|
||||
|
||||
|
||||
def load_preg_dconf(pregfile, pathfile, policy_name, username, version=None):
|
||||
'''
|
||||
Loads the configuration from preg registry into a dictionary
|
||||
'''
|
||||
dd = dict()
|
||||
for i in pregfile.entries:
|
||||
# Skip this entry if the valuename starts with '**del'
|
||||
if i.valuename.startswith('**del'):
|
||||
continue
|
||||
valuename = convert_string_dconf(i.valuename)
|
||||
data = check_data(i.data, i.type)
|
||||
if i.valuename != i.data and i.valuename:
|
||||
if i.keyname.replace('\\', '/') in dd:
|
||||
# If the key exists in dd, update its value with the new key-value pair
|
||||
dd[i.keyname.replace('\\', '/')].update({valuename.replace('\\', '/'):data})
|
||||
else:
|
||||
# If the key does not exist in dd, create a new key-value pair
|
||||
dd[i.keyname.replace('\\', '/')] = {valuename.replace('\\', '/'):data}
|
||||
|
||||
elif not i.valuename:
|
||||
keyname_tmp = i.keyname.replace('\\', '/').split('/')
|
||||
keyname = '/'.join(keyname_tmp[:-1])
|
||||
if keyname in dd:
|
||||
# If the key exists in dd, update its value with the new key-value pair
|
||||
dd[keyname].update({keyname_tmp[-1]:data})
|
||||
else:
|
||||
# If the key does not exist in dd, create a new key-value pair
|
||||
dd[keyname] = {keyname_tmp[-1]:data}
|
||||
|
||||
else:
|
||||
# If the value name is the same as the data,
|
||||
# split the keyname and add the data to the appropriate location in dd.
|
||||
all_list_key = i.keyname.split('\\')
|
||||
dd_target = dd.setdefault('/'.join(all_list_key[:-1]),{})
|
||||
dd_target.setdefault(all_list_key[-1], []).append(data)
|
||||
|
||||
# Update the global registry dictionary with the contents of dd
|
||||
add_to_dict(pathfile, policy_name, username, version)
|
||||
update_dict(Dconf_registry.global_registry_dict, dd)
|
||||
|
||||
|
||||
def create_dconf_ini_file(filename, data):
|
||||
'''
|
||||
Create an ini-file based on a dictionary of dictionaries.
|
||||
Args:
|
||||
data (dict): The dictionary of dictionaries containing the data for the ini-file.
|
||||
filename (str): The filename to save the ini-file.
|
||||
Returns:
|
||||
None
|
||||
Raises:
|
||||
None
|
||||
'''
|
||||
with open(filename, 'w') as file:
|
||||
for section, section_data in data.items():
|
||||
file.write(f'[{section}]\n')
|
||||
for key, value in section_data.items():
|
||||
if isinstance(value, int):
|
||||
file.write(f'{key} = {value}\n')
|
||||
else:
|
||||
file.write(f'{key} = "{value}"\n')
|
||||
file.write('\n')
|
||||
logdata = dict()
|
||||
logdata['path'] = filename
|
||||
log('D209', logdata)
|
||||
Dconf_registry.dconf_update()
|
||||
|
||||
def clean_data(data):
|
||||
try:
|
||||
cleaned_string = data.replace('\n', '').replace('\r', '')
|
||||
cleaned_string = cleaned_string.replace('"', "'")
|
||||
return cleaned_string
|
||||
except:
|
||||
return None
|
||||
|
||||
def check_data(data, t_data):
|
||||
if isinstance(data, bytes):
|
||||
if t_data == 7:
|
||||
return clean_data(data.decode('utf-16').replace('\x00',''))
|
||||
else:
|
||||
return None
|
||||
elif t_data == 4:
|
||||
return data
|
||||
return clean_data(data)
|
||||
|
||||
def convert_string_dconf(input_string):
|
||||
macros = {
|
||||
'#': '%sharp%',
|
||||
';': '%semicolon%',
|
||||
'//': '%doubleslash%'
|
||||
}
|
||||
output_string = input_string
|
||||
for key, value in macros.items():
|
||||
if key in input_string:
|
||||
output_string = input_string.replace(key, value)
|
||||
elif value in input_string:
|
||||
output_string = input_string.replace(value, key)
|
||||
|
||||
return output_string
|
||||
|
||||
def remove_empty_values(input_list):
|
||||
return list(filter(None, input_list))
|
||||
|
||||
def flatten_dictionary(input_dict, result=None, current_key=''):
|
||||
if result is None:
|
||||
result = {}
|
||||
|
||||
for key, value in input_dict.items():
|
||||
new_key = f"{current_key}/{key}" if current_key else key
|
||||
|
||||
if isinstance(value, dict):
|
||||
flatten_dictionary(value, result, new_key)
|
||||
else:
|
||||
result[new_key] = value
|
||||
|
||||
return result
|
||||
|
||||
def get_dconf_envprofile():
|
||||
dconf_envprofile = {'default': {'DCONF_PROFILE': 'default'},
|
||||
'local': {'DCONF_PROFILE': 'local'},
|
||||
'system': {'DCONF_PROFILE': 'system'}
|
||||
}
|
||||
|
||||
if Dconf_registry._envprofile:
|
||||
return dconf_envprofile.get(Dconf_registry._envprofile, dconf_envprofile['system'])
|
||||
|
||||
if not Dconf_registry._username:
|
||||
return dconf_envprofile['system']
|
||||
|
||||
profile = '/run/dconf/user/{}'.format(get_uid_by_username(Dconf_registry._username))
|
||||
return {'DCONF_PROFILE': profile}
|
||||
@@ -57,6 +57,9 @@ class fs_file_cache:
|
||||
file_path))
|
||||
else:
|
||||
destdir = destfile.parent
|
||||
except NotUNCPathError:
|
||||
return None
|
||||
|
||||
except Exception as exc:
|
||||
logdata = dict({'exception': str(exc)})
|
||||
log('D144', logdata)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#}
|
||||
|
||||
{% if Deny_All == '1' %}
|
||||
{% if Deny_All == 1 %}
|
||||
polkit.addRule(function (action, subject) {
|
||||
if ((action.id == "org.freedesktop.udisks2.filesystem-mount" ||
|
||||
action.id == "org.freedesktop.udisks2.filesystem-mount-system" ||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#}
|
||||
|
||||
{% if Deny_All == '1' %}
|
||||
{% if Deny_All == 1 %}
|
||||
polkit.addRule(function (action, subject) {
|
||||
if (action.id == "org.freedesktop.udisks2.filesystem-mount" ||
|
||||
action.id == "org.freedesktop.udisks2.filesystem-mount-system" ||
|
||||
|
||||
@@ -46,3 +46,10 @@ class NotUNCPathError(Exception):
|
||||
def __str__(self):
|
||||
return self.path
|
||||
|
||||
class GetGPOListFail(Exception):
|
||||
def __init__(self, exc):
|
||||
self.exc = exc
|
||||
|
||||
def __str__(self):
|
||||
return self.exc
|
||||
|
||||
|
||||
@@ -93,6 +93,15 @@ def local_policy_cache():
|
||||
|
||||
return lpcache
|
||||
|
||||
def get_dconf_config_path(uid = None):
|
||||
if uid:
|
||||
return f'/etc/dconf/db/policy{uid}.d/policy{uid}.ini'
|
||||
else:
|
||||
return '/etc/dconf/db/policy.d/policy.ini'
|
||||
|
||||
def get_desktop_files_directory():
|
||||
return '/usr/share/applications'
|
||||
|
||||
class UNCPath:
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
from xml.etree import ElementTree
|
||||
from storage import registry_factory
|
||||
from storage.dconf_registry import load_preg_dconf
|
||||
|
||||
from samba.gp_parse.gp_pol import GPPolParser
|
||||
|
||||
@@ -80,10 +81,16 @@ def preg_keymap(preg):
|
||||
return keymap
|
||||
|
||||
|
||||
def merge_polfile(preg, sid=None, reg_name='registry', reg_path=None, policy_name='Unknown'):
|
||||
def merge_polfile(preg, sid=None, reg_name='registry', reg_path=None, policy_name='Unknown', username='Machine', version=None):
|
||||
pregfile = load_preg(preg)
|
||||
if sid is None and username == 'Machine':
|
||||
load_preg_dconf(pregfile, preg, policy_name, None, version)
|
||||
else:
|
||||
load_preg_dconf(pregfile, preg, policy_name, username, version)
|
||||
logdata = dict({'pregfile': preg})
|
||||
log('D32', logdata)
|
||||
#log dconf
|
||||
return
|
||||
storage = registry_factory(reg_name, reg_path)
|
||||
for entry in pregfile.entries:
|
||||
if not sid:
|
||||
|
||||
@@ -47,7 +47,6 @@ def username_match_uid(username):
|
||||
'''
|
||||
Check the passed username matches current process UID.
|
||||
'''
|
||||
uid = os.getuid()
|
||||
process_username = get_process_user()
|
||||
|
||||
if process_username == username:
|
||||
|
||||
@@ -174,3 +174,25 @@ def string_to_literal_eval(string):
|
||||
except:
|
||||
literaleval = string
|
||||
return literaleval
|
||||
|
||||
def try_dict_to_literal_eval(string):
|
||||
try:
|
||||
literaleval = ast.literal_eval(string)
|
||||
if isinstance(literaleval ,dict):
|
||||
return literaleval
|
||||
else:
|
||||
return None
|
||||
except:
|
||||
return None
|
||||
|
||||
def touch_file(filename):
|
||||
path = Path(filename)
|
||||
path.parent.mkdir(parents=True, exist_ok=True)
|
||||
path.touch()
|
||||
|
||||
def get_uid_by_username(username):
|
||||
try:
|
||||
user_info = pwd.getpwnam(username)
|
||||
return user_info.pw_uid
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
@@ -30,16 +30,21 @@ except ImportError:
|
||||
from samba.netcmd.common import netcmd_get_domain_infos_via_cldap
|
||||
import samba.gpo
|
||||
|
||||
from storage import cache_factory
|
||||
from messages import message_with_code
|
||||
from .xdg import (
|
||||
xdg_get_desktop
|
||||
)
|
||||
from .util import get_homedir
|
||||
from .exceptions import GetGPOListFail
|
||||
from .logging import log
|
||||
from .samba import smbopts
|
||||
from gpoa.storage import registry_factory
|
||||
|
||||
from samba.samdb import SamDB
|
||||
from samba.auth import system_session
|
||||
import optparse
|
||||
import ldb
|
||||
import ipaddress
|
||||
import netifaces
|
||||
import random
|
||||
|
||||
class smbcreds (smbopts):
|
||||
|
||||
@@ -48,6 +53,13 @@ class smbcreds (smbopts):
|
||||
self.credopts = options.CredentialsOptions(self.parser)
|
||||
self.creds = self.credopts.get_credentials(self.lp, fallback_machine=True)
|
||||
self.set_dc(dc_fqdn)
|
||||
self.sDomain = SiteDomainScanner(self.creds, self.lp, self.selected_dc)
|
||||
self.dc_site_servers = self.sDomain.select_site_servers()
|
||||
self.all_servers = self.sDomain.select_all_servers()
|
||||
[self.all_servers.remove(element)
|
||||
for element in self.dc_site_servers
|
||||
if element in self.all_servers]
|
||||
self.pdc_emulator_server = self.sDomain.select_pdc_emulator_server()
|
||||
|
||||
def get_dc(self):
|
||||
return self.selected_dc
|
||||
@@ -113,17 +125,32 @@ class smbcreds (smbopts):
|
||||
log('I2', ldata)
|
||||
|
||||
except Exception as exc:
|
||||
if self.selected_dc != self.pdc_emulator_server:
|
||||
raise GetGPOListFail(exc)
|
||||
logdata = dict({'username': username, 'dc': self.selected_dc})
|
||||
log('E17', logdata)
|
||||
|
||||
return gpos
|
||||
|
||||
def update_gpos(self, username):
|
||||
gpos = self.get_gpos(username)
|
||||
|
||||
list_selected_dc = set()
|
||||
|
||||
|
||||
|
||||
if self.dc_site_servers:
|
||||
self.selected_dc = self.dc_site_servers.pop()
|
||||
|
||||
self.all_servers = [dc for dc in self.all_servers if dc != self.selected_dc]
|
||||
list_selected_dc.add(self.selected_dc)
|
||||
|
||||
try:
|
||||
gpos = self.get_gpos(username)
|
||||
|
||||
except GetGPOListFail:
|
||||
self.selected_dc = self.pdc_emulator_server
|
||||
gpos = self.get_gpos(username)
|
||||
|
||||
while list_selected_dc:
|
||||
logdata = dict()
|
||||
logdata['username'] = username
|
||||
@@ -136,22 +163,135 @@ class smbcreds (smbopts):
|
||||
except NTSTATUSError as smb_exc:
|
||||
logdata['smb_exc'] = str(smb_exc)
|
||||
if not check_scroll_enabled():
|
||||
log('F1', logdata)
|
||||
raise smb_exc
|
||||
self.selected_dc = get_dc_hostname(self.creds, self.lp)
|
||||
if self.selected_dc not in list_selected_dc:
|
||||
logdata['action'] = 'Search another dc'
|
||||
log('W11', logdata)
|
||||
list_selected_dc.add(self.selected_dc)
|
||||
if self.pdc_emulator_server and self.selected_dc != self.pdc_emulator_server:
|
||||
self.selected_dc = self.pdc_emulator_server
|
||||
logdata['action'] = 'Selected pdc'
|
||||
logdata['pdc'] = self.selected_dc
|
||||
log('W11', logdata)
|
||||
else:
|
||||
log('F1', logdata)
|
||||
raise smb_exc
|
||||
else:
|
||||
log('F1', logdata)
|
||||
raise smb_exc
|
||||
if self.dc_site_servers:
|
||||
self.selected_dc = self.dc_site_servers.pop()
|
||||
elif self.all_servers:
|
||||
self.selected_dc = self.all_servers.pop()
|
||||
else:
|
||||
self.selected_dc = self.pdc_emulator_server
|
||||
|
||||
|
||||
if self.selected_dc not in list_selected_dc:
|
||||
logdata['action'] = 'Search another dc'
|
||||
logdata['another_dc'] = self.selected_dc
|
||||
log('W11', logdata)
|
||||
list_selected_dc.add(self.selected_dc)
|
||||
else:
|
||||
log('F1', logdata)
|
||||
raise smb_exc
|
||||
except Exception as exc:
|
||||
logdata['exc'] = str(exc)
|
||||
log('F1', logdata)
|
||||
raise exc
|
||||
return gpos
|
||||
|
||||
|
||||
class SiteDomainScanner:
|
||||
def __init__(self, smbcreds, lp, dc):
|
||||
self.samdb = SamDB(url='ldap://{}'.format(dc), session_info=system_session(), credentials=smbcreds, lp=lp)
|
||||
self.pdc_emulator = self._search_pdc_emulator()
|
||||
|
||||
@staticmethod
|
||||
def _get_ldb_single_message_attr(ldb_message, attr_name, encoding='utf8'):
|
||||
if attr_name in ldb_message:
|
||||
return ldb_message[attr_name][0].decode(encoding)
|
||||
else:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _get_ldb_single_result_attr(ldb_result, attr_name, encoding='utf8'):
|
||||
if len(ldb_result) == 1 and attr_name in ldb_result[0]:
|
||||
return ldb_result[0][attr_name][0].decode(encoding)
|
||||
else:
|
||||
return None
|
||||
|
||||
def _get_server_hostname(self, ds_service_name):
|
||||
ds_service_name_dn = ldb.Dn(self.samdb, ds_service_name)
|
||||
server_dn = ds_service_name_dn.parent()
|
||||
res = self.samdb.search(server_dn, scope=ldb.SCOPE_BASE)
|
||||
return self._get_ldb_single_result_attr(res, 'dNSHostName')
|
||||
|
||||
def _search_pdc_emulator(self):
|
||||
res = self.samdb.search(self.samdb.domain_dn(), scope=ldb.SCOPE_BASE)
|
||||
pdc_settings_object = self._get_ldb_single_result_attr(res, 'fSMORoleOwner')
|
||||
return self._get_server_hostname(pdc_settings_object)
|
||||
|
||||
def get_ip_addresses(self):
|
||||
interface_list = netifaces.interfaces()
|
||||
addresses = []
|
||||
for iface in interface_list:
|
||||
address_entry = netifaces.ifaddresses(iface)
|
||||
if netifaces.AF_INET in address_entry:
|
||||
addresses.extend(ipaddress.ip_address(ipv4_address_entry['addr']) for ipv4_address_entry in address_entry[netifaces.AF_INET])
|
||||
if netifaces.AF_INET6 in address_entry:
|
||||
addresses.extend(ipaddress.ip_address(ipv6_address_entry['addr']) for ipv6_address_entry in address_entry[netifaces.AF_INET6])
|
||||
return addresses
|
||||
|
||||
def get_ad_subnets_sites(self):
|
||||
subnet_dn = ldb.Dn(self.samdb, "CN=Subnets,CN=Sites")
|
||||
config_dn = self.samdb.get_config_basedn()
|
||||
subnet_dn.add_base(config_dn)
|
||||
res = self.samdb.search(subnet_dn, ldb.SCOPE_ONELEVEL, expression='objectClass=subnet', attrs=['cn', 'siteObject'])
|
||||
subnets = {ipaddress.ip_network(self._get_ldb_single_message_attr(msg, 'cn')): self._get_ldb_single_message_attr(msg, 'siteObject') for msg in res}
|
||||
return subnets
|
||||
|
||||
def get_ad_site_servers(self, site):
|
||||
servers_dn = ldb.Dn(self.samdb, "CN=Servers")
|
||||
site_dn = ldb.Dn(self.samdb, site)
|
||||
servers_dn.add_base(site_dn)
|
||||
res = self.samdb.search(servers_dn, ldb.SCOPE_ONELEVEL, expression='objectClass=server', attrs=['dNSHostName'])
|
||||
servers = [self._get_ldb_single_message_attr(msg, 'dNSHostName') for msg in res]
|
||||
random.shuffle(servers)
|
||||
return servers
|
||||
|
||||
def get_ad_all_servers(self):
|
||||
sites_dn = ldb.Dn(self.samdb, "CN=Sites")
|
||||
config_dn = self.samdb.get_config_basedn()
|
||||
sites_dn.add_base(config_dn)
|
||||
res = self.samdb.search(sites_dn, ldb.SCOPE_SUBTREE, expression='objectClass=server', attrs=['dNSHostName'])
|
||||
servers = [self._get_ldb_single_message_attr(msg, 'dNSHostName') for msg in res]
|
||||
random.shuffle(servers)
|
||||
return servers
|
||||
|
||||
def check_ip_in_subnets(self, ip_addresses, subnets_sites):
|
||||
return next((subnets_sites[subnet] for subnet in subnets_sites.keys()
|
||||
if any(ip_address in subnet for ip_address in ip_addresses)), None)
|
||||
|
||||
def select_site_servers(self):
|
||||
try:
|
||||
ip_addresses = self.get_ip_addresses()
|
||||
subnets_sites = self.get_ad_subnets_sites()
|
||||
|
||||
our_site = self.check_ip_in_subnets(ip_addresses, subnets_sites)
|
||||
|
||||
servers = []
|
||||
if our_site:
|
||||
servers = self.get_ad_site_servers(our_site)
|
||||
random.shuffle(servers)
|
||||
return servers
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
def select_all_servers(self):
|
||||
try:
|
||||
servers = self.get_ad_all_servers()
|
||||
random.shuffle(servers)
|
||||
return servers
|
||||
except Exception as e:
|
||||
return []
|
||||
|
||||
def select_pdc_emulator_server(self):
|
||||
return self.pdc_emulator
|
||||
|
||||
def expand_windows_var(text, username=None):
|
||||
'''
|
||||
Scan the line for percent-encoded variables and expand them.
|
||||
@@ -194,9 +334,9 @@ def transform_windows_path(text):
|
||||
return result
|
||||
|
||||
def check_scroll_enabled():
|
||||
storage = registry_factory('registry')
|
||||
enable_scroll = 'Software\\BaseALT\\Policies\\GPUpdate\\ScrollSysvolDC'
|
||||
if storage.get_hklm_entry(enable_scroll):
|
||||
storage = registry_factory()
|
||||
enable_scroll = '/Software/BaseALT/Policies/GPUpdate/ScrollSysvolDC'
|
||||
if storage.get_key_value(enable_scroll):
|
||||
data = storage.get_hklm_entry(enable_scroll).data
|
||||
return bool(int(data))
|
||||
else:
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
%add_python3_req_skip messages
|
||||
%add_python3_req_skip storage
|
||||
%add_python3_req_skip storage.fs_file_cache
|
||||
%add_python3_req_skip storage.dconf_registry
|
||||
%add_python3_req_skip util
|
||||
%add_python3_req_skip util.arguments
|
||||
%add_python3_req_skip util.config
|
||||
@@ -32,7 +33,7 @@
|
||||
%add_python3_req_skip util.gpoa_ini_parsing
|
||||
|
||||
Name: gpupdate
|
||||
Version: 0.9.13.7
|
||||
Version: 0.10.3
|
||||
Release: alt1
|
||||
|
||||
Summary: GPT applier
|
||||
@@ -53,6 +54,7 @@ Requires: libnss-role >= 0.5.0
|
||||
Requires: local-policy >= 0.4.9
|
||||
Requires: pam-config >= 1.9.0
|
||||
Requires: autofs
|
||||
Requires: dconf-profile
|
||||
# This is needed by shortcuts_applier
|
||||
Requires: desktop-file-utils
|
||||
# This is needed for smb file cache support
|
||||
@@ -119,6 +121,9 @@ install -Dm0644 dist/%name-remote-policy %buildroot%_sysconfdir/pam.d/%name-remo
|
||||
install -Dm0644 dist/%name.ini %buildroot%_sysconfdir/%name/%name.ini
|
||||
install -Dm0644 doc/gpoa.1 %buildroot/%_man1dir/gpoa.1
|
||||
install -Dm0644 doc/gpupdate.1 %buildroot/%_man1dir/gpupdate.1
|
||||
install -Dm0644 completions/gpoa %buildroot/%_datadir/bash-completion/completions/gpoa
|
||||
install -Dm0644 completions/gpupdate %buildroot/%_datadir/bash-completion/completions/gpupdate
|
||||
install -Dm0644 completions/gpupdate-setup %buildroot/%_datadir/bash-completion/completions/gpupdate-setup
|
||||
|
||||
for i in gpupdate-localusers \
|
||||
gpupdate-group-users \
|
||||
@@ -165,9 +170,12 @@ fi
|
||||
%_unitdir/%name.timer
|
||||
%_man1dir/gpoa.1.*
|
||||
%_man1dir/gpupdate.1.*
|
||||
/usr/lib/systemd/user/%name-user.service
|
||||
/usr/lib/systemd/user/%name-user.timer
|
||||
/usr/lib/systemd/user/%name-scripts-run-user.service
|
||||
%_datadir/bash-completion/completions/gpoa
|
||||
%_datadir/bash-completion/completions/gpupdate
|
||||
%_datadir/bash-completion/completions/gpupdate-setup
|
||||
%_user_unitdir/%name-user.service
|
||||
%_user_unitdir/%name-user.timer
|
||||
%_user_unitdir/%name-scripts-run-user.service
|
||||
%dir %_sysconfdir/%name
|
||||
%_sysconfdir/control.d/facilities/*
|
||||
%config(noreplace) %_sysconfdir/%name/environment
|
||||
@@ -183,6 +191,33 @@ fi
|
||||
%exclude %python3_sitelibdir/gpoa/test
|
||||
|
||||
%changelog
|
||||
* Wed Jun 19 2024 Valery Sinelnikov <greh@altlinux.org> 0.10.3-alt1
|
||||
- Added autocompletion for gpoa, gpupdate, gpupdate-setup
|
||||
- Added correct work with json data in keys for the Firefox browser
|
||||
- Polkit_appliers changed to non-experimental
|
||||
- Fixed bug of not clearing kde applier settings (closes: 50336)
|
||||
- Fixed registry key reading (closes: 50553)
|
||||
- Added waiting for data generation for scripts (closes: 50667)
|
||||
|
||||
* Fri Jun 07 2024 Valery Sinelnikov <greh@altlinux.org> 0.10.2-alt1
|
||||
- Added some fixes to dconf_registry and scripts
|
||||
- Fixed windows registry key reading for loopback
|
||||
|
||||
* Tue Jun 04 2024 Valery Sinelnikov <greh@altlinux.org> 0.10.1-alt1
|
||||
- Added handling of unexpected data types when writing to dconf
|
||||
|
||||
* Mon May 13 2024 Valery Sinelnikov <greh@altlinux.org> 0.10.0-alt1
|
||||
- A method for storing registry keys obtained from GPOs (Group Policy Objects)
|
||||
has undergone significant repairs. We have switched from using SQLite
|
||||
to using Dconf to improve data storage efficiency
|
||||
|
||||
* Wed Mar 13 2024 Valery Sinelnikov <greh@altlinux.org> 0.9.13.9-alt1
|
||||
- Fixed premature removal of double slash
|
||||
|
||||
* Thu Feb 22 2024 Valery Sinelnikov <greh@altlinux.org> 0.9.13.8-alt1
|
||||
- Added search for dc on the site
|
||||
- Added compatibility support for the oldest versions of SQLAlchemy
|
||||
|
||||
* Mon Feb 05 2024 Valery Sinelnikov <greh@altlinux.org> 0.9.13.7-alt1
|
||||
- Editing the cache size in the Yandex browser has returned (closes: 44621)
|
||||
- Removed unnecessary calls to subprocess
|
||||
|
||||
Reference in New Issue
Block a user