1
0
mirror of https://github.com/altlinux/gpupdate.git synced 2025-10-15 07:33:26 +03:00

Compare commits

...

50 Commits

Author SHA1 Message Date
Valery Sinelnikov
285e646986 Fixed a bug due to which gsettings could not cache the specified URI 2021-10-27 11:46:05 +04:00
Valery Sinelnikov
94d039653a Added exception for org.gnome.Vino authentication-methods 2021-10-25 20:03:23 +04:00
Valery Sinelnikov
e6f19a2116 Fixed bug for alternative-port in org.gnome.Vino 2021-10-21 19:16:43 +04:00
Evgeny Sinelnikov
86c240b9df VERSION: Bump version up to 0.9.8... 2021-09-29 08:43:27 +04:00
Evgeny Sinelnikov
dae3cf2c6c 0.9.7-alt1
- Fix regression with kestroy for user credential cache
- Update system-policy-gpupdate PAM-rules to ignore applying group policies
  for local users and system users with uid less than 500
- Add control facilities to rule system-policy-gpupdate rules:
  + gpupdate-group-users
  + gpupdate-localusers
  + gpupdate-system-uids
2021-09-29 08:42:25 +04:00
Evgeny Sinelnikov
4fe7d0a73e system-policy-gpupdate: fix with tested rules and add two special
controls facilities gpupdate-group-users and gpupdate-system-uids.
2021-09-29 08:35:04 +04:00
Evgeny Sinelnikov
54d0c7c2cb util/kerberos.py: fix regression with kestroy for user credential cache
in forked process with droped privileges.
2021-09-29 02:45:03 +04:00
Evgeny Sinelnikov
954a5598fb system-policy-gpupdate: apply group policy to users in users group only 2021-09-27 01:15:00 +04:00
Evgeny Sinelnikov
ba4eb4bf28 Add control gpupdate-localusers facility for group policy applying to local users 2021-09-26 20:01:41 +04:00
Evgeny Sinelnikov
aa10d5bbf9 system-policy-gpupdate: add PAM-rules for ignore applying group policies
for local users and system users with uid less than 500
2021-09-26 19:56:13 +04:00
Evgeny Sinelnikov
f3062668fa VERSION: Bump version up to 0.9.7... 2021-09-20 08:08:20 +04:00
Evgeny Sinelnikov
046079d4c9 0.9.6-alt1
- Add support changed GPO List Processing for '**DelVals.' value name
2021-09-20 07:57:50 +04:00
Evgeny Sinelnikov
414a827eb8 Add support changed GPO List Processing for '**DelVals.' value name 2021-09-20 07:56:04 +04:00
Evgeny Sinelnikov
8ce322d552 VERSION: Bump version up to 0.9.6... 2021-09-20 07:23:13 +04:00
Evgeny Sinelnikov
84d5122319 0.9.5-alt1
- Refix local policy path detection
- gpupdate-setup: revert settings to default when disabled
2021-09-20 03:31:30 +04:00
Evgeny Sinelnikov
436eeb3760 gpupdate-setup: revert settings to default when disabled 2021-09-14 06:56:27 +04:00
Evgeny Sinelnikov
4b9ef4335a Refix local policy path detection 2021-09-14 06:39:13 +04:00
Evgeny Sinelnikov
929f9678ad 0.9.4-alt1
- Add improvement with new local-policy system-policy control
- Fix gpupdate-setup and user service installation regressions
- Set empty local policy and local backend by default
- Fix local policy path detection
2021-09-14 04:00:27 +04:00
Evgeny Sinelnikov
03cada30cf Add gpo file_sys_path to common logs 2021-09-14 03:57:16 +04:00
Evgeny Sinelnikov
8199cac510 Fix local policy path detection 2021-09-14 02:22:34 +04:00
Evgeny Sinelnikov
e050889a07 Set empty local policy and local backend by default 2021-09-14 01:45:15 +04:00
Evgeny Sinelnikov
1bf2bd053d Fix gupdate-user.service installation 2021-09-14 00:58:33 +04:00
Evgeny Sinelnikov
950e132e2a gpupdate-setup: fix local policy setup regression after code moving 2021-09-14 00:46:26 +04:00
Evgeny Sinelnikov
82e255efc9 0.9.3-alt1
- Use NetBIOS name for Kerberos authentification
- Add support actions (create, update, delete, replace) for Shortcuts
- Add support GSettings with locks feature
- Add support file cache for special GSettings policy:
  Software\BaseALT\Policies\GSettings\org.mate.background.picture-filename
  (requires python smbc module with use_kerberos option support)
2021-09-09 18:10:18 +04:00
Evgeny Sinelnikov
011a3fbed3 gpupdate.service: add starting After syslog and network-online targets 2021-09-09 18:10:18 +04:00
Valery Sinelnikov
8eda2fbedb Fixed GSettings blocking errors 2021-09-09 17:50:08 +04:00
Evgeny Sinelnikov
3f3fa5f7d9 Merge pull request #140 from altlinux/file_cache
File cache
2021-09-06 15:18:00 +04:00
Evgeny Sinelnikov
0210f97e0d Fix GSettings locks profile db generating 2021-09-06 15:12:09 +04:00
Evgeny Sinelnikov
7e6dec6b3d Update file cache functionality for GSettings 2021-09-06 11:37:45 +04:00
Evgeny Sinelnikov
5e4ed2f655 Fix pathlib PosixPath type conversion, clean code from unused json import 2021-09-06 06:38:23 +04:00
Evgeny Sinelnikov
721ba96559 Add exception handling for not UNC path case in picture_fetch() 2021-09-06 05:29:24 +04:00
Evgeny Sinelnikov
c83568cc70 Fix bad raise Exception during UNCPath construction 2021-09-06 00:44:05 +04:00
Evgeny Sinelnikov
15f99e0171 Fix not unusefull logging 2021-09-03 05:12:54 +04:00
Evgeny Sinelnikov
f84af7e0e8 Fix gpupdate_file_cache directory name in gpupdate.spec 2021-09-03 03:47:34 +04:00
7bd1131d5d fs_file_cache() object moved to gsettings_applier.py 2021-09-02 18:12:09 +04:00
5fb8e6ff74 Create file cache directory on install 2021-09-02 17:49:21 +04:00
ce2797e5f1 File cache introduced for frontend
Introduced file cache for GSettings, specifically for wallpapers.
It is needed to work with wallpapers on remote resources.
2021-09-02 17:49:20 +04:00
6d9417fb94 storage.fs_file_cache.fs_file_cache
File caching mechanism utilizing /var/cache/gpupdate_file_cache
directory to cache files from remote locations, specifically, to
cache files specified as UNC paths.
2021-09-02 17:49:20 +04:00
301a77e90a util.paths: UNCPath primitive introduced
It is needed to allow parsing and conversion of UNC paths
2021-09-02 17:47:15 +04:00
Evgeny Sinelnikov
274d9d8555 Merge pull request #146 from altlinux/gsettings_locks
Add support GSettings locks with local profile
2021-09-02 17:43:55 +04:00
Evgeny Sinelnikov
04f5f98681 Merge pull request #145 from altlinux/realm_from_smb_conf
Use default realm taken from smb.conf, not krb5.conf
2021-09-02 17:43:32 +04:00
Evgeny Sinelnikov
9638e5fabb Merge pull request #141 from altlinux/netbios_name
Use NetBIOS name for Kerberos authentification
2021-09-02 17:43:12 +04:00
Evgeny Sinelnikov
393fd25cdb Merge pull request #139 from altlinux/gpo_initial
Fix startup user and computer gpoa initialization
2021-09-02 17:42:59 +04:00
Valery Sinelnikov
23f862f9a5 Add support GSettings locks with local profile 2021-08-20 16:48:43 +04:00
a85fed7cff Use default realm taken from smb.conf, not krb5.conf 2021-08-18 15:52:32 +04:00
bbcb98bb94 Use NetBIOS name for Kerberos authentification 2021-08-16 14:49:52 +04:00
Evgeny Sinelnikov
57f4f0678a Fix startup user and computer gpoa initialization 2021-08-06 09:21:38 +04:00
Evgeny Sinelnikov
306b8db34a Merge pull request #138 from altlinux/shortcuts_actions
Shortcuts actions
2021-08-02 12:22:47 +04:00
Evgeny Sinelnikov
7c8f9892b5 Fix Shortcuts update logic with reading firstly 2021-07-29 00:02:04 +04:00
Evgeny Sinelnikov
4c6a099529 Add support actions (create, update, delete, replace) for Shortcuts 2021-07-28 23:50:36 +04:00
28 changed files with 666 additions and 131 deletions

19
dist/gpupdate-group-users vendored Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/sh
. /etc/control.d/functions
CONFIG=/etc/pam.d/system-policy-gpupdate
new_subst disabled \
'^[[:space:]]*session[[:space:]]+\[.*default=1.*\][[:space:]]+pam_succeed_if.so user ingroup users.*' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)default=[[:alnum:]]\+\(.*pam_succeed_if.so user ingroup users.*\)$,\1default=1\2,'
new_subst enabled \
'^[[:space:]]*session[[:space:]]+\[.*default=ignore.*\][[:space:]]+pam_succeed_if.so user ingroup users.*' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)default=[[:alnum:]]\+\(.*pam_succeed_if.so user ingroup users.*\)$,\1default=ignore\2,'
new_help disabled "Disable group policy applying for users in 'users' group only"
new_help enabled "Enable group policy applying for users in 'users' group only"
new_summary "Group policy applying for users in 'users' group only"
control_subst "$CONFIG" "$*"

19
dist/gpupdate-localusers vendored Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/sh
. /etc/control.d/functions
CONFIG=/etc/pam.d/system-policy-gpupdate
new_subst disabled \
'^[[:space:]]*session[[:space:]]+\[.*success=2.*\][[:space:]]+pam_localuser.so' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)success=[[:alnum:]]\+\(.*pam_localuser.so.*\)$,\1success=2\2,'
new_subst enabled \
'^[[:space:]]*session[[:space:]]+\[.*success=1.*\][[:space:]]+pam_localuser.so' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)success=[[:alnum:]]\+\(.*pam_localuser.so.*\)$,\1success=1\2,'
new_help disabled 'Disable group policy applying for local users'
new_help enabled 'Enable group policy applying for local users'
new_summary 'Group policy applying for local users'
control_subst "$CONFIG" "$*"

19
dist/gpupdate-system-uids vendored Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/sh
. /etc/control.d/functions
CONFIG=/etc/pam.d/system-policy-gpupdate
new_subst disabled \
'^[[:space:]]*session[[:space:]]+\[.*default=1.*\][[:space:]]+pam_succeed_if.so uid >= 500.*' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)default=[[:alnum:]]\+\(.*pam_succeed_if.so uid >= 500.*\)$,\1default=1\2,'
new_subst enabled \
'^[[:space:]]*session[[:space:]]+\[.*default=ignore.*\][[:space:]]+pam_succeed_if.so uid >= 500.*' \
's,^\([[:space:]]*session[[:space:]]\+\[.*\)default=[[:alnum:]]\+\(.*pam_succeed_if.so uid >= 500.*\)$,\1default=ignore\2,'
new_help disabled "Disable group policy applying for users with not system uids only"
new_help enabled "Enable group policy applying for users with not system uids only"
new_summary "Group policy applying for users with not system uids (greater or equal 500) only"
control_subst "$CONFIG" "$*"

4
dist/gpupdate.ini vendored
View File

@@ -1,4 +1,4 @@
[gpoa]
backend = samba
local-policy = auto
backend = local
local-policy = default

View File

@@ -1,6 +1,6 @@
[Unit]
Description=Group policy update for machine
After=sssd.service
After=syslog.target network-online.target sssd.service
[Service]
Environment="PATH=/bin:/sbin:/usr/bin:/usr/sbin"

View File

@@ -1,4 +1,12 @@
#%PAM-1.0
session [success=2 perm_denied=ignore default=die] pam_localuser.so
session required pam_mkhomedir.so silent
session [default=1] pam_permit.so
session [default=6] pam_permit.so
session [success=1 default=ignore] pam_succeed_if.so user ingroup users quiet
session [default=4] pam_permit.so
session [success=1 default=ignore] pam_succeed_if.so uid >= 500 quiet
session [default=2] pam_permit.so
-session required pam_oddjob_gpupdate.so
session optional pam_env.so user_readenv=1 conffile=/etc/gpupdate/environment user_envfile=.gpupdate_environment
session required pam_permit.so

View File

@@ -41,7 +41,7 @@ def backend_factory(dc, username, is_machine, no_domain = False):
log('D52', ld)
sc = smbcreds(dc)
domain = sc.get_domain()
ldata = dict({'domain': domain})
ldata = dict({'domain': domain, "username": username, 'is_machine': is_machine})
log('D9', ldata)
try:
back = samba_backend(sc, username, domain, is_machine)

View File

@@ -126,7 +126,7 @@ class samba_backend(applier_backend):
def _get_gpts(self, username, sid):
gpts = list()
log('D45')
log('D45', {'username': username, 'sid': sid})
# util.windows.smbcreds
gpos = self.sambacreds.update_gpos(username)
log('D46')

View File

@@ -24,44 +24,89 @@ from gi.repository import Gio, GLib
from util.logging import slogm
class system_gsetting:
def __init__(self, schema, path, value, override_priority_file):
def __init__(self, schema, path, value, lock, helper_function=None):
self.schema = schema
self.path = path
self.value = value
self.file_path = override_priority_file
self.lock = lock
self.helper_function = helper_function
def apply(self):
config = configparser.ConfigParser()
try:
config.read(self.file_path)
except Exception as exc:
logging.error(slogm(exc))
def apply(self, settings, config, locks):
try:
config.add_section(self.schema)
except configparser.DuplicateSectionError:
pass
value = glib_value(self.schema, self.path, self.value)
config.set(self.schema, self.path, str(value))
#logging.debug('Setting GSettings key {} (in {}) to {}'.format(self.path, self.schema, str(value)))
value = self.value
if self.helper_function:
value = self.helper_function(self.schema, self.path, value)
result = glib_value(self.schema, self.path, value, settings)
config.set(self.schema, self.path, str(result))
with open(self.file_path, 'w') as f:
if self.lock:
lock_path = dconf_path(settings, self.path)
locks.append(lock_path)
class system_gsettings:
__path_local_dir = '/etc/dconf/db/local.d'
__path_locks = '/etc/dconf/db/policy.d/locks/policy'
__path_profile = '/etc/dconf/profile/user'
__profile_data = 'user-db:user\nsystem-db:policy\nsystem-db:local\n'
def __init__(self, override_file_path):
self.gsettings = list()
self.locks = list()
self.override_file_path = override_file_path
def append(self, schema, path, data, lock, helper):
self.gsettings.append(system_gsetting(schema, path, data, lock, helper))
def apply(self):
config = configparser.ConfigParser()
for gsetting in self.gsettings:
settings = Gio.Settings(schema=gsetting.schema)
logging.debug(slogm('Applying machine setting {}.{} to {} {}'.format(gsetting.schema,
gsetting.path,
gsetting.value,
gsetting.value,
'locked' if gsetting.lock else 'unlocked')))
gsetting.apply(settings, config, self.locks)
with open(self.override_file_path, 'w') as f:
config.write(f)
os.makedirs(self.__path_local_dir, mode=0o755, exist_ok=True)
os.makedirs(os.path.dirname(self.__path_locks), mode=0o755, exist_ok=True)
os.makedirs(os.path.dirname(self.__path_profile), mode=0o755, exist_ok=True)
try:
os.remove(self.__path_locks)
except OSError as error:
pass
file_locks = open(self.__path_locks,'w')
for lock in self.locks:
file_locks.write(lock +'\n')
file_locks.close()
profile = open(self.__path_profile ,'w')
profile.write(self.__profile_data)
profile.close()
def glib_map(value, glib_type):
result_value = value
if glib_type == 'i' or glib_type == 'b':
if glib_type == 'i' or glib_type == 'b' or glib_type == 'q':
result_value = GLib.Variant(glib_type, int(value))
else:
result_value = GLib.Variant(glib_type, value)
return result_value
def glib_value(schema, path, value, settings=None):
# Access the current schema if not initialized
if not settings:
settings = Gio.Settings(schema=schema)
def dconf_path(settings, path):
return settings.get_property("path") + path
def glib_value(schema, path, value, settings):
# Get the key to modify
key = settings.get_value(path)
# Query the data type for the key
@@ -71,27 +116,20 @@ def glib_value(schema, path, value, settings=None):
class user_gsetting:
def __init__(self, schema, path, value, helper_function=None):
#logging.debug('Creating User GSettings element {} (in {}) with value {}'.format(path, schema, value))
self.schema = schema
self.path = path
self.value = value
self.helper_function = helper_function
def apply(self):
#logging.debug('Setting User GSettings key {} (in {}) to {}'.format(self.path, self.schema, self.value))
if self.helper_function:
self.helper_function(self.schema, self.path, self.value)
# Access the current schema
settings = Gio.Settings(schema=self.schema)
# Update result with helper function
value = self.value
if self.helper_function:
value = self.helper_function(self.schema, self.path, value)
# Get typed value by schema
val = glib_value(self.schema, self.path, self.value, settings)
result = glib_value(self.schema, self.path, value, settings)
# Set the value
settings.set_value(self.path, val)
settings.set_value(self.path, result)
settings.sync()
#gso = Gio.Settings.new(self.schema)
#variants = gso.get_property(self.path)
#if (variants.has_key(self.path)):
# key = variants.get_key(self.path)
# print(key.get_range())

View File

@@ -17,6 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from storage import registry_factory
from storage.fs_file_cache import fs_file_cache
from .control_applier import control_applier
from .polkit_applier import (
@@ -107,6 +108,7 @@ class frontend_manager:
self.is_machine = is_machine
self.process_uname = get_process_user()
self.sid = get_sid(self.storage.get_info('domain'), self.username, is_machine)
self.file_cache = fs_file_cache('file_cache')
self.machine_appliers = dict()
self.machine_appliers['control'] = control_applier(self.storage)
@@ -115,7 +117,7 @@ class frontend_manager:
self.machine_appliers['firefox'] = firefox_applier(self.storage, self.sid, self.username)
self.machine_appliers['chromium'] = chromium_applier(self.storage, self.sid, self.username)
self.machine_appliers['shortcuts'] = shortcut_applier(self.storage)
self.machine_appliers['gsettings'] = gsettings_applier(self.storage)
self.machine_appliers['gsettings'] = gsettings_applier(self.storage, self.file_cache)
self.machine_appliers['cups'] = cups_applier(self.storage)
self.machine_appliers['firewall'] = firewall_applier(self.storage)
self.machine_appliers['folders'] = folder_applier(self.storage, self.sid)
@@ -128,7 +130,7 @@ class frontend_manager:
self.user_appliers = dict()
self.user_appliers['shortcuts'] = shortcut_applier_user(self.storage, self.sid, self.username)
self.user_appliers['folders'] = folder_applier_user(self.storage, self.sid, self.username)
self.user_appliers['gsettings'] = gsettings_applier_user(self.storage, self.sid, self.username)
self.user_appliers['gsettings'] = gsettings_applier_user(self.storage, self.file_cache, self.sid, self.username)
try:
self.user_appliers['cifs'] = cifs_applier_user(self.storage, self.sid, self.username)
except Exception as exc:
@@ -148,6 +150,7 @@ class frontend_manager:
log('E13')
return
log('D16')
for applier_name, applier_object in self.machine_appliers.items():
try:
applier_object.apply()

View File

@@ -20,6 +20,7 @@ import logging
import os
import pwd
import subprocess
import urllib.parse
from gi.repository import (
Gio
@@ -32,34 +33,70 @@ from .applier_frontend import (
, check_windows_mapping_enabled
)
from .appliers.gsettings import (
system_gsetting,
system_gsettings,
user_gsetting
)
from util.logging import slogm
def uri_fetch(schema, path, value, cache):
'''
Function to fetch and cache uri
'''
retval = value
logdata = dict()
logdata['schema'] = schema
logdata['path'] = path
logdata['src'] = value
try:
retval = cache.get(value)
logdata['dst'] = retval
logging.debug(slogm('Getting cached file for URI: {}'.format(logdata)))
except Exception as exc:
pass
return retval
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'
__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):
def __init__(self, storage, file_cache):
self.storage = storage
self.file_cache = file_cache
gsettings_filter = '{}%'.format(self.__registry_branch)
gsettings_locks_filter = '{}%'.format(self.__registry_locks_branch)
self.gsettings_keys = self.storage.filter_hklm_entries(gsettings_filter)
self.gsettings = list()
self.gsettings_locks = self.storage.filter_hklm_entries(gsettings_locks_filter)
self.override_file = os.path.join(self.__global_schema, self.__override_priority_file)
self.override_old_file = os.path.join(self.__global_schema, self.__override_old_file)
self.gsettings = system_gsettings(self.override_file)
self.locks = dict()
self.__module_enabled = check_enabled(
self.storage
, self.__module_name
, self.__module_experimental
)
def update_file_cache(self, data):
try:
self.file_cache.store(data)
except Exception as exc:
logdata = dict()
logdata['exception'] = str(exc)
logging.debug(slogm('Unable to cache specified URI for machine: {}'.format(logdata)))
def uri_fetch_helper(self, schema, path, value):
return uri_fetch(schema, path, value, self.file_cache)
def run(self):
# Compatility cleanup of old settings
if os.path.exists(self.override_old_file):
@@ -70,18 +107,31 @@ class gsettings_applier(applier_frontend):
logging.debug(slogm('Removing GSettings policy file from previous run'))
os.remove(self.override_file)
# Get all configured gsettings locks
for lock in self.gsettings_locks:
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]
rp = valuename.rpartition('.')
schema = rp[0]
path = rp[2]
self.gsettings.append(system_gsetting(schema, path, setting.data, self.override_file))
data = setting.data
lock = bool(self.locks[valuename]) if valuename in self.locks else None
if setting.hive_key.lower() == self.__wallpaper_entry.lower():
check = urllib.parse.urlparse(setting.data)
if check.scheme:
self.update_file_cache(setting.data)
helper = self.uri_fetch_helper
elif setting.hive_key.lower() == self.__vino_authentication_methods_entry.lower():
data = [setting.data]
self.gsettings.append(schema, path, data, lock, helper)
# Create GSettings policy with highest available priority
for gsetting in self.gsettings:
logging.debug(slogm('Applying setting {}/{} to {}'.format(gsetting.schema, gsetting.path, gsetting.value)))
gsetting.apply()
self.gsettings.apply()
# Recompile GSettings schemas with overrides
try:
@@ -89,6 +139,12 @@ class gsettings_applier(applier_frontend):
except Exception as exc:
logging.debug(slogm('Error recompiling global GSettings schemas'))
# Update desktop configuration system backend
try:
proc = subprocess.run(args=['/usr/bin/dconf', "update"], capture_output=True, check=True)
except Exception as exc:
logging.debug(slogm('Error update desktop configuration system backend'))
def apply(self):
if self.__module_enabled:
logging.debug(slogm('Running GSettings applier for machine'))
@@ -131,10 +187,13 @@ class gsettings_applier_user(applier_frontend):
__module_name = 'GSettingsApplierUser'
__module_experimental = False
__module_enabled = True
__registry_branch = 'Software\\BaseALT\\Policies\\gsettings'
__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, sid, username):
def __init__(self, storage, file_cache, sid, username):
self.storage = storage
self.file_cache = file_cache
self.sid = sid
self.username = username
gsettings_filter = '{}%'.format(self.__registry_branch)
@@ -179,14 +238,17 @@ class gsettings_applier_user(applier_frontend):
def windows_mapping_append(self):
for setting_key in self.__windows_settings.keys():
#logging.debug('Checking for GSettings mapping {}'.format(setting_key))
value = self.storage.get_hkcu_entry(self.sid, setting_key)
if value:
logging.debug(slogm('Found GSettings windows mapping {} to {}'.format(setting_key, value.data)))
mapping = self.__windows_settings[setting_key]
self.gsettings.append(user_gsetting(mapping.gsettings_schema, mapping.gsettings_key, value.data))
#else:
# logging.debug('GSettings windows mapping for {} not found'.format(setting_key))
try:
self.gsettings.append(user_gsetting(mapping.gsettings_schema, mapping.gsettings_key, value.data))
except Exception as exc:
print(exc)
def uri_fetch_helper(self, schema, path, value):
return uri_fetch(schema, path, value, self.file_cache)
def run(self):
#for setting in self.gsettings_keys:
@@ -210,11 +272,17 @@ class gsettings_applier_user(applier_frontend):
rp = valuename.rpartition('.')
schema = rp[0]
path = rp[2]
self.gsettings.append(user_gsetting(schema, path, setting.data))
data = setting.data
helper = self.uri_fetch_helper if setting.hive_key.lower() == self.__wallpaper_entry.lower() else None
if setting.hive_key.lower() == self.__vino_authentication_methods_entry.lower():
data = [setting.data]
self.gsettings.append(user_gsetting(schema, path, data, helper))
# Create GSettings policy with highest available priority
for gsetting in self.gsettings:
logging.debug(slogm('Applying user setting {}/{} to {}'.format(gsetting.schema, gsetting.path, gsetting.value)))
logging.debug(slogm('Applying user setting {}.{} to {}'.format(gsetting.schema,
gsetting.path,
gsetting.value)))
gsetting.apply()
def user_context_apply(self):
@@ -225,8 +293,14 @@ class gsettings_applier_user(applier_frontend):
logging.debug(slogm('GSettings applier for user in user context will not be started'))
def admin_context_apply(self):
'''
Not implemented because there is no point of doing so.
'''
pass
# Cache files on remote locations
try:
entry = self.__wallpaper_entry
filter_result = self.storage.get_hkcu_entry(self.sid, entry)
if filter_result:
self.file_cache.store(filter_result.data)
except Exception as exc:
logdata = dict()
logdata['exception'] = str(exc)
logging.debug(slogm('Unable to cache specified URI for user: {}'.format(logdata)))

View File

@@ -46,9 +46,9 @@ def storage_get_shortcuts(storage, sid, username=None):
return shortcuts
def write_shortcut(shortcut, username=None):
def apply_shortcut(shortcut, username=None):
'''
Write the single shortcut file to the disk.
Apply the single shortcut file to the disk.
:username: None means working with machine variables and paths
'''
@@ -66,22 +66,22 @@ def write_shortcut(shortcut, username=None):
if dest_abspath.startswith(get_homedir(username)):
# Don't try to operate on non-existent directory
if not homedir_exists(username):
logging.warning(slogm('No home directory exists for user {}: will not create link {}'.format(username, dest_abspath)))
logging.warning(slogm('No home directory exists for user {}: will not apply link {}'.format(username, dest_abspath)))
return None
else:
logging.warning(slogm('User\'s shortcut not placed to home directory for {}: bad path {}'.format(username, dest_abspath)))
return None
if '%' in dest_abspath:
logging.debug(slogm('Fail for writing shortcut to file with \'%\': {}'.format(dest_abspath)))
logging.debug(slogm('Fail for applying shortcut to file with \'%\': {}'.format(dest_abspath)))
return None
if not dest_abspath.startswith('/'):
logging.debug(slogm('Fail for writing shortcut to not absolute path \'%\': {}'.format(dest_abspath)))
logging.debug(slogm('Fail for applying shortcut to not absolute path \'%\': {}'.format(dest_abspath)))
return None
logging.debug(slogm('Writing shortcut file to {}'.format(dest_abspath)))
shortcut.write_desktop(dest_abspath)
logging.debug(slogm('Applying shortcut file to {} with action {}'.format(dest_abspath, shortcut.action)))
shortcut.apply_desktop(dest_abspath)
class shortcut_applier(applier_frontend):
__module_name = 'ShortcutsApplier'
@@ -100,7 +100,7 @@ class shortcut_applier(applier_frontend):
shortcuts = storage_get_shortcuts(self.storage, self.storage.get_info('machine_sid'))
if shortcuts:
for sc in shortcuts:
write_shortcut(sc)
apply_shortcut(sc)
if len(shortcuts) > 0:
# According to ArchWiki - this thing is needed to rebuild MIME
# type cache in order file bindings to work. This rebuilds
@@ -133,9 +133,9 @@ class shortcut_applier_user(applier_frontend):
if shortcuts:
for sc in shortcuts:
if in_usercontext and sc.is_usercontext():
write_shortcut(sc, self.username)
apply_shortcut(sc, self.username)
if not in_usercontext and not sc.is_usercontext():
write_shortcut(sc, self.username)
apply_shortcut(sc, self.username)
else:
logging.debug(slogm('No shortcuts to process for {}'.format(self.sid)))

View File

@@ -73,25 +73,44 @@ class gpoa_controller:
def __init__(self):
self.__args = parse_arguments()
self.is_machine = False
if not self.__args.user:
user = get_machine_name()
self.is_machine = True
self.noupdate = self.__args.noupdate
set_loglevel(self.__args.loglevel)
locale.bindtextdomain('gpoa', '/usr/lib/python3/site-packages/gpoa/locale')
gettext.bindtextdomain('gpoa', '/usr/lib/python3/site-packages/gpoa/locale')
gettext.textdomain('gpoa')
if not self.__args.user:
self.username = get_machine_name()
self.is_machine = True
else:
self.username = self.__args.user
uname = get_process_user()
uid = os.getuid()
logdata = dict()
logdata['username'] = uname
logdata['uid'] = uid
log('D1', logdata)
logdata['username'] = self.username
logdata['is_machine'] = self.is_machine
logdata['process_username'] = uname
logdata['process_uid'] = uid
if self.is_machine:
log('D61', logdata)
else:
log('D1', logdata)
self.username = determine_username(self.username)
if not is_root():
self.username = uname
self.noupdate = True
if self.is_machine:
msgtext = message_with_code('E34')
log('E34', {'username': self.username})
raise Exception(msgtext)
log('D59', {'username': self.username})
else:
self.username = determine_username(self.__args.user)
log('D60', {'username': self.username})
def run(self):
'''
@@ -113,7 +132,7 @@ class gpoa_controller:
if self.__args.nodomain:
nodomain = True
if not self.__args.noupdate:
if not self.noupdate:
if is_root():
back = None
try:

View File

@@ -68,7 +68,7 @@ from .tasks import (
import util
import util.preg
from util.paths import (
default_policy_path,
local_policy_path,
cache_dir,
local_policy_cache
)
@@ -326,7 +326,7 @@ def lp2gpt():
'''
Convert local-policy to full-featured GPT.
'''
lppath = os.path.join(default_policy_path(), 'Machine/Registry.pol.xml')
lppath = os.path.join(local_policy_path(), 'Machine/Registry.pol.xml')
# Load settings from XML PolFile
polparser = GPPolParser()

View File

@@ -79,7 +79,7 @@ def read_shortcuts(shortcuts_file):
# URL or FILESYSTEM
target_type = get_ttype(props.get('targetType'))
sc = shortcut(dest, path, arguments, link.get('name'), target_type)
sc = shortcut(dest, path, arguments, link.get('name'), props.get('action'), target_type)
sc.set_changed(link.get('changed'))
sc.set_clsid(link.get('clsid'))
sc.set_guid(link.get('uid'))
@@ -100,7 +100,7 @@ def json2sc(json_str):
json_obj = json.loads(json_str)
link_type = get_ttype(json_obj['type'])
sc = shortcut(json_obj['dest'], json_obj['path'], json_obj['arguments'], json_obj['name'], link_type)
sc = shortcut(json_obj['dest'], json_obj['path'], json_obj['arguments'], json_obj['name'], json_obj['action'], link_type)
sc.set_changed(json_obj['changed'])
sc.set_clsid(json_obj['clsid'])
sc.set_guid(json_obj['guid'])
@@ -111,7 +111,7 @@ def json2sc(json_str):
return sc
class shortcut:
def __init__(self, dest, path, arguments, name=None, ttype=TargetType.FILESYSTEM):
def __init__(self, dest, path, arguments, name=None, action=None, ttype=TargetType.FILESYSTEM):
'''
:param dest: Path to resulting file on file system
:param path: Path where the link should point to
@@ -124,6 +124,7 @@ class shortcut:
self.expanded_path = None
self.arguments = arguments
self.name = name
self.action = action
self.changed = ''
self.icon = None
self.is_in_user_context = self.set_usercontext()
@@ -188,6 +189,7 @@ class shortcut:
content['clsid'] = self.clsid
content['guid'] = self.guid
content['changed'] = self.changed
content['action'] = self.action
content['is_in_user_context'] = self.is_in_user_context
content['type'] = ttype2str(self.type)
if self.icon:
@@ -197,19 +199,29 @@ class shortcut:
return json.dumps(result.content)
def desktop(self):
def desktop(self, dest=None):
'''
Returns desktop file object which may be written to disk.
'''
self.desktop_file = DesktopEntry()
self.desktop_file.addGroup('Desktop Entry')
if dest:
self.desktop_file = DesktopEntry(dest)
else:
self.desktop_file = DesktopEntry()
self.desktop_file.addGroup('Desktop Entry')
self.desktop_file.set('Version', '1.0')
self._update_desktop()
return self.desktop_file
def _update_desktop(self):
'''
Update desktop file object from internal data.
'''
if self.type == TargetType.URL:
self.desktop_file.set('Type', 'Link')
else:
self.desktop_file.set('Type', 'Application')
self.desktop_file.set('Version', '1.0')
self.desktop_file.set('Name', self.name)
desktop_path = self.path
@@ -224,15 +236,41 @@ class shortcut:
if self.icon:
self.desktop_file.set('Icon', self.icon)
return self.desktop_file
def write_desktop(self, dest):
def _write_desktop(self, dest, create_only=False, read_firstly=False):
'''
Write .desktop file to disk using path 'dest'. Please note that
.desktop files must have executable bit set in order to work in
GUI.
'''
self.desktop().write(dest)
sc = Path(dest)
if sc.exists() and create_only:
return
if sc.exists() and read_firstly:
self.desktop(dest).write(dest)
else:
self.desktop().write(dest)
sc.chmod(sc.stat().st_mode | stat.S_IEXEC)
def _remove_desktop(self, dest):
'''
Remove .desktop file fromo disk using path 'dest'.
'''
sc = Path(dest)
if sc.exists():
sc.unlink()
def apply_desktop(self, dest):
'''
Apply .desktop file by action.
'''
if self.action == 'U':
self._write_desktop(dest, read_firstly=True)
elif self.action == 'D':
self._remove_desktop(dest)
elif self.action == 'R':
self._remove_desktop(dest)
self._write_desktop(dest)
elif self.action == 'C':
self._write_desktop(dest, create_only=True)

View File

@@ -23,8 +23,6 @@ import sys
import argparse
import subprocess
import re
from util.util import (
runcmd
, get_backends
@@ -33,17 +31,14 @@ from util.util import (
, get_policy_variants
)
from util.config import GPConfig
from util.paths import get_custom_policy_dir
class Runner:
__control_path = '/usr/sbin/control'
__systemctl_path = '/bin/systemctl'
__etc_policy_dir = '/etc/local-policy'
__usr_policy_dir = '/usr/share/local-policy'
def __init__(self):
self.etc_policies = get_policy_entries(self.__etc_policy_dir)
self.usr_policies = get_policy_entries(self.__usr_policy_dir)
self.arguments = parse_arguments()
def parse_arguments():
@@ -194,13 +189,13 @@ def disable_gp():
runcmd(cmd_set_local_policy)
runcmd(cmd_disable_gpupdate_service)
runcmd(cmd_disable_gpupdate_user_service)
config.set_local_policy_template()
config.set_backend()
def enable_gp(policy_name, backend_type):
'''
Consistently enable group policy services
'''
policy_dir = '/usr/share/local-policy'
etc_policy_dir = '/etc/local-policy'
cmd_set_gpupdate_policy = ['/usr/sbin/control', 'system-policy', 'gpupdate']
cmd_gpoa_nodomain = ['/usr/sbin/gpoa', '--nodomain', '--loglevel', '5']
cmd_enable_gpupdate_service = ['/bin/systemctl', 'enable', 'gpupdate.service']
@@ -208,18 +203,17 @@ def enable_gp(policy_name, backend_type):
config = GPConfig()
custom_policy_dir = get_custom_policy_dir()
if not os.path.isdir(custom_policy_dir):
os.makedirs(custom_policy_dir)
target_policy_name = get_default_policy_name()
if policy_name:
if validate_policy_name(policy_name):
target_policy_name = policy_name
print (target_policy_name)
default_policy_name = os.path.join(policy_dir, target_policy_name)
if not os.path.isdir(etc_policy_dir):
os.makedirs(etc_policy_dir)
config.set_local_policy_template(default_policy_name)
config.set_local_policy_template(target_policy_name)
config.set_backend(backend_type)
# Enable oddjobd_gpupdate in PAM config

View File

@@ -61,6 +61,11 @@ def error_code(code):
error_ids[31] = 'Error connecting to DBus Session daemon'
error_ids[32] = 'No reply from DBus Session'
error_ids[33] = 'Error occured while running forked process with dropped privileges'
error_ids[34] = 'Error running GPOA directly for computer'
error_ids[35] = 'Error caching URI to file'
error_ids[36] = 'Error getting cached file for URI'
error_ids[37] = 'Error caching file URIs'
error_ids[38] = 'Unable to cache specified URI'
return error_ids.get(code, 'Unknown error code')
@@ -124,6 +129,14 @@ def debug_code(code):
debug_ids[56] = 'Kill dbus-daemon and dconf-service in user context'
debug_ids[57] = 'Found connection by org.freedesktop.DBus.GetConnectionUnixProcessID'
debug_ids[58] = 'Connection search return org.freedesktop.DBus.Error.NameHasNoOwner'
debug_ids[59] = 'Running GPOA without GPT update directly for user'
debug_ids[60] = 'Running GPOA by root for user'
debug_ids[61] = 'The GPOA process was started for computer'
debug_ids[62] = 'Path not resolved as UNC URI'
debug_ids[63] = 'Delete HKLM branch key'
debug_ids[64] = 'Delete HKCU branch key'
debug_ids[65] = 'Delete HKLM branch key error'
debug_ids[66] = 'Delete HKCU branch key error'
return debug_ids.get(code, 'Unknown debug code')

View File

@@ -0,0 +1,97 @@
#
# GPOA - GPO Applier for Linux
#
# Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
# Copyright (C) 2021 Igor Chudov <nir@nir.org.ru>
#
# 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 os
import os.path
from pathlib import Path
import smbc
from util.logging import log
from util.paths import file_cache_dir, UNCPath
from util.exceptions import NotUNCPathError
class fs_file_cache:
__read_blocksize = 4096
def __init__(self, cache_name):
self.cache_name = cache_name
self.storage_uri = file_cache_dir()
logdata = dict({'cache_file': self.storage_uri})
log('D20', logdata)
self.samba_context = smbc.Context(use_kerberos=1)
#, debug=10)
def store(self, uri):
destdir = uri
try:
uri_path = UNCPath(uri)
file_name = os.path.basename(uri_path.get_path())
file_path = os.path.dirname(uri_path.get_path())
destdir = Path('{}/{}/{}'.format(self.storage_uri,
uri_path.get_domain(),
file_path))
except Exception as exc:
logdata = dict({'exception': str(exc)})
log('E38', logdata)
raise exc
if not destdir.exists():
destdir.mkdir(parents=True, exist_ok=True)
destfile = Path('{}/{}/{}'.format(self.storage_uri,
uri_path.get_domain(),
uri_path.get_path()))
with open(destfile, 'wb') as df:
df.truncate()
df.flush()
try:
file_handler = self.samba_context.open(str(uri_path), os.O_RDONLY)
while True:
data = file_handler.read(self.__read_blocksize)
if not data:
break
df.write(data)
df.flush()
except Exception as exc:
logdata = dict({'exception': str(exc)})
log('E35', logdata)
raise exc
def get(self, uri):
destfile = uri
try:
uri_path = UNCPath(uri)
file_name = os.path.basename(uri_path.get_path())
file_path = os.path.dirname(uri_path.get_path())
destfile = Path('{}/{}/{}'.format(self.storage_uri,
uri_path.get_domain(),
uri_path.get_path()))
except NotUNCPathError as exc:
logdata = dict({'path': str(exc)})
log('D62', logdata)
except Exception as exc:
logdata = dict({'exception': str(exc)})
log('E36', logdata)
raise exc
return str(destfile)

View File

@@ -22,7 +22,9 @@ class samba_preg(object):
'''
def __init__(self, preg_obj, policy_name):
self.policy_name = policy_name
self.hive_key = '{}\\{}'.format(preg_obj.keyname, preg_obj.valuename)
self.keyname = preg_obj.keyname
self.valuename = preg_obj.valuename
self.hive_key = '{}\\{}'.format(self.keyname, self.valuename)
self.type = preg_obj.type
self.data = preg_obj.data
@@ -41,7 +43,9 @@ class samba_hkcu_preg(object):
def __init__(self, sid, preg_obj, policy_name):
self.sid = sid
self.policy_name = policy_name
self.hive_key = '{}\\{}'.format(preg_obj.keyname, preg_obj.valuename)
self.keyname = preg_obj.keyname
self.valuename = preg_obj.valuename
self.hive_key = '{}\\{}'.format(self.keyname, self.valuename)
self.type = preg_obj.type
self.data = preg_obj.data

View File

@@ -68,6 +68,8 @@ class sqlite_registry(registry):
, Column('id', Integer, primary_key=True)
, Column('hive_key', String(65536, collation='NOCASE'),
unique=True)
, Column('keyname', String(collation='NOCASE'))
, Column('valuename', String(collation='NOCASE'))
, Column('policy_name', String)
, Column('type', Integer)
, Column('data', String)
@@ -78,6 +80,8 @@ class sqlite_registry(registry):
, Column('id', Integer, primary_key=True)
, Column('sid', String)
, Column('hive_key', String(65536, collation='NOCASE'))
, Column('keyname', String(collation='NOCASE'))
, Column('valuename', String(collation='NOCASE'))
, Column('policy_name', String)
, Column('type', Integer)
, Column('data', String)
@@ -240,16 +244,52 @@ class sqlite_registry(registry):
log('D19', logdata)
self._info_upsert(ientry)
def _delete_hklm_keyname(self, keyname):
'''
Delete PReg hive_key from HKEY_LOCAL_MACHINE
'''
logdata = dict({'keyname': keyname})
try:
(self
.db_session
.query(samba_preg)
.filter(samba_preg.keyname == keyname)
.delete(synchronize_session=False))
self.db_session.commit()
log('D65', logdata)
except Exception as exc:
log('D63', logdata)
def add_hklm_entry(self, preg_entry, policy_name):
'''
Write PReg entry to HKEY_LOCAL_MACHINE
'''
pentry = samba_preg(preg_entry, policy_name)
if not pentry.hive_key.rpartition('\\')[2].startswith('**'):
if not pentry.valuename.startswith('**'):
self._hklm_upsert(pentry)
else:
logdata = dict({'key': pentry.hive_key})
log('D27', logdata)
if pentry.valuename.lower() == '**delvals.':
self._delete_hklm_keyname(pentry.keyname)
else:
log('D27', logdata)
def _delete_hkcu_keyname(self, keyname, sid):
'''
Delete PReg hive_key from HKEY_CURRENT_USER
'''
logdata = dict({'sid': sid, 'keyname': keyname})
try:
(self
.db_session
.query(samba_hkcu_preg)
.filter(samba_hkcu_preg.sid == sid)
.filter(samba_hkcu_preg.keyname == keyname)
.delete(synchronize_session=False))
self.db_session.commit()
log('D66', logdata)
except:
log('D64', logdata)
def add_hkcu_entry(self, preg_entry, sid, policy_name):
'''
@@ -257,11 +297,14 @@ class sqlite_registry(registry):
'''
hkcu_pentry = samba_hkcu_preg(sid, preg_entry, policy_name)
logdata = dict({'sid': sid, 'policy': policy_name, 'key': hkcu_pentry.hive_key})
if not hkcu_pentry.hive_key.rpartition('\\')[2].startswith('**'):
if not hkcu_pentry.valuename.startswith('**'):
log('D26', logdata)
self._hkcu_upsert(hkcu_pentry)
else:
log('D51', logdata)
if hkcu_pentry.valuename.lower() == '**delvals.':
self._delete_hkcu_keyname(hkcu_pentry.keyname, sid)
else:
log('D51', logdata)
def add_shortcut(self, sid, sc_obj, policy_name):
'''
@@ -335,6 +378,7 @@ class sqlite_registry(registry):
.db_session
.query(row_object)
.filter(row_object.sid == sid)
.order_by(row_object.id)
.all())
return res

View File

@@ -45,7 +45,7 @@ class GPConfig:
return 'samba'
def set_backend(self, backend_name):
def set_backend(self, backend_name='local'):
self.full_config['gpoa']['backend'] = backend_name
self.write_config()
@@ -71,7 +71,7 @@ class GPConfig:
return get_default_policy_name()
def set_local_policy_template(self, template_name):
def set_local_policy_template(self, template_name='default'):
self.full_config['gpoa']['local-policy'] = template_name
self.write_config()

View File

@@ -39,3 +39,10 @@ def geterr():
return traceinfo
class NotUNCPathError(Exception):
def __init__(self, path):
self.path = path
def __str__(self):
return self.path

View File

@@ -21,15 +21,19 @@ import subprocess
from .util import get_machine_name
from .logging import log
from .samba import smbopts
def machine_kinit(cache_name=None):
'''
Perform kinit with machine credentials
'''
opts = smbopts()
host = get_machine_name()
realm = opts.get_realm()
with_realm = '{}@{}'.format(host, realm)
os.environ['KRB5CCNAME'] = 'FILE:{}'.format(cache_name)
kinit_cmd = ['kinit', '-k', host]
kinit_cmd = ['kinit', '-k', with_realm]
if cache_name:
kinit_cmd.extend(['-c', cache_name])
proc = subprocess.Popen(kinit_cmd)
@@ -55,8 +59,9 @@ def machine_kdestroy(cache_name=None):
if cache_name:
kdestroy_cmd.extend(['-c', cache_name])
proc = subprocess.Popen(kdestroy_cmd, stderr=subprocess.DEVNULL)
proc.wait()
if cache_name or 'KRB5CCNAME' in os.environ:
proc = subprocess.Popen(kdestroy_cmd, stderr=subprocess.DEVNULL)
proc.wait()
if cache_name and os.path.exists(cache_name):
os.unlink(cache_name)

View File

@@ -1,7 +1,8 @@
#
# GPOA - GPO Applier for Linux
#
# Copyright (C) 2019-2020 BaseALT Ltd.
# Copyright (C) 2019-2021 BaseALT Ltd. <org@basealt.ru>
# Copyright (C) 2019-2021 Igor Chudov <nir@nir.org.ru>
#
# 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
@@ -18,26 +19,38 @@
import pathlib
import os
from pathlib import Path
from urllib.parse import urlparse
from .config import GPConfig
from .util import get_default_policy_name
from .exceptions import NotUNCPathError
def default_policy_path():
def get_custom_policy_dir():
'''
Returns path pointing to Default Policy directory.
Returns path pointing to Custom Policy directory.
'''
local_policy_default = '/usr/share/local-policy/{}'.format(get_default_policy_name())
return '/etc/local-policy'
def local_policy_path(default_template_name="default"):
'''
Returns path pointing to Local Policy template directory.
'''
local_policy_dir = '/usr/share/local-policy'
config = GPConfig()
local_policy_template = config.get_local_policy_template()
local_policy_template_path = os.path.join(local_policy_dir, local_policy_template)
local_policy_default = os.path.join(local_policy_dir, default_template_name)
result_path = pathlib.Path(local_policy_default)
if os.path.exists(config.get_local_policy_template()):
result_path = pathlib.Path(config.get_local_policy_template())
if os.path.exists(local_policy_template):
result_path = pathlib.Path(local_policy_template)
elif os.path.exists(local_policy_template_path):
result_path = pathlib.Path(local_policy_template_path)
return pathlib.Path(result_path)
def cache_dir():
'''
Returns path pointing to gpupdate's cache directory
@@ -49,6 +62,16 @@ def cache_dir():
return cachedir
def file_cache_dir():
'''
Returns path pointing to gpupdate's cache directory
'''
cachedir = pathlib.Path('/var/cache/gpupdate_file_cache')
if not cachedir.exists():
cachedir.mkdir(parents=True, exist_ok=True)
return cachedir
def local_policy_cache():
'''
@@ -62,3 +85,46 @@ def local_policy_cache():
return lpcache
class UNCPath:
def __init__(self, path):
self.path = path
self.type = None
if self.path.startswith(r'smb://'):
self.type = 'uri'
if self.path.startswith(r'\\'):
self.type = 'unc'
if not self.type:
raise NotUNCPathError(path)
def get_uri(self):
path = self.path
if self.type == 'unc':
path = self.path.replace('\\', '/')
path = path.replace('//', 'smb://')
else:
pass
return path
def get_unc(self):
path = self.path
if self.type == 'uri':
path = self.path.replace('//', '\\\\')
path = path.replace('smb:\\\\', '\\\\')
path = path.replace('/', '\\')
else:
pass
return path
def get_domain(self):
schema_struct = urlparse(self.get_uri())
return schema_struct.netloc
def get_path(self):
schema_struct = urlparse(self.get_uri())
return schema_struct.path
def __str__(self):
return self.get_uri()

View File

@@ -18,6 +18,7 @@
import optparse
import socket
from samba import getopt as options
@@ -28,11 +29,32 @@ class smbopts:
self.sambaopts = options.SambaOptions(self.parser)
self.lp = self.sambaopts.get_loadparm()
def get_realm(self):
'''
Get the default realm specified in smb.conf file.
'''
return self._get_prop('realm')
def get_cache_dir(self):
return self._get_prop('cache directory')
def get_server_role(self):
return self._get_prop('server role')
def get_machine_name(self):
'''
Get localhost name looking like DC0$
'''
nb_name = self.get_netbios_name()
result = nb_name + "$"
if result == '':
result = socket.gethostname().split('.', 1)[0].upper() + "$"
return result
def get_netbios_name(self):
return self._get_prop('netbios name')
def _get_prop(self, property_name):
return self.lp.get(property_name)

View File

@@ -17,10 +17,10 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import socket
import os
import pwd
import subprocess
import re
from pathlib import Path
from .samba import smbopts
@@ -29,7 +29,10 @@ def get_machine_name():
'''
Get localhost name looking like DC0$
'''
return socket.gethostname().split('.', 1)[0].upper() + "$"
loadparm = smbopts()
result = loadparm.get_machine_name()
return result
def is_machine_name(name):

View File

@@ -105,7 +105,7 @@ class smbcreds (smbopts):
for gpo in gpos:
# These setters are taken from libgpo/pygpo.c
# print(gpo.ds_path) # LDAP entry
ldata = dict({'gpo_name': gpo.display_name, 'gpo_uuid': gpo.name})
ldata = dict({'gpo_name': gpo.display_name, 'gpo_uuid': gpo.name, 'file_sys_path': gpo.file_sys_path})
log('I2', ldata)
except Exception as exc:

View File

@@ -1,8 +1,8 @@
%define _unpackaged_files_terminate_build 1
Name: gpupdate
Version: 0.9.2
Release: alt1
Version: 0.9.8
Release: alt0.dev1
Summary: GPT applier
License: GPLv3+
@@ -18,11 +18,13 @@ Requires: python3-module-rpm
Requires: python3-module-dbus
Requires: oddjob-%name >= 0.2.0
Requires: libnss-role >= 0.5.0
Requires: local-policy >= 0.4.0
Requires: local-policy >= 0.4.9
Requires: pam-config >= 1.9.0
Requires: autofs
# This is needed by shortcuts_applier
Requires: desktop-file-utils
# This is needed for smb file cache support
Requires: python3-module-smbc >= 1.0.23-alt3
Source0: %name-%version.tar
@@ -48,6 +50,7 @@ mkdir -p \
%buildroot%_bindir/ \
%buildroot%_sbindir/ \
%buildroot%_cachedir/%name/ \
%buildroot%_cachedir/%{name}_file_cache/ \
%buildroot%_cachedir/%name/creds
ln -s %python3_sitelibdir/gpoa/gpoa \
@@ -65,12 +68,20 @@ mkdir -p %buildroot%_sysconfdir/%name
touch %buildroot%_sysconfdir/%name/environment
install -Dm0644 dist/%name.service %buildroot%_unitdir/%name.service
install -Dm0644 dist/%name.service %buildroot/usr/lib/systemd/user/%name-user.service
install -Dm0644 dist/%name-user.service %buildroot/usr/lib/systemd/user/%name-user.service
install -Dm0644 dist/system-policy-%name %buildroot%_sysconfdir/pam.d/system-policy-%name
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
for i in gpupdate-localusers \
gpupdate-group-users \
gpupdate-system-uids
do
install -pD -m755 "dist/$i" \
"%buildroot%_sysconfdir/control.d/facilities/$i"
done
%preun
%preun_service gpupdate
@@ -80,7 +91,7 @@ install -Dm0644 doc/gpupdate.1 %buildroot/%_man1dir/gpupdate.1
# Remove storage in case we've lost compatibility between versions.
# The storage will be regenerated on GPOA start.
%define active_policy %_sysconfdir/local-policy/active
%triggerpostun -- %name < 0.8.0
%triggerpostun -- %name < 0.9.6
rm -f %_cachedir/%name/registry.sqlite
if test -L %active_policy; then
sed -i "s|^\s*local-policy\s*=.*|local-policy = $(readlink -f %active_policy)|" \
@@ -101,10 +112,12 @@ fi
%_man1dir/gpupdate.1.*
/usr/lib/systemd/user/%name-user.service
%dir %_sysconfdir/%name
%_sysconfdir/control.d/facilities/*
%config(noreplace) %_sysconfdir/%name/environment
%config(noreplace) %_sysconfdir/%name/%name.ini
%config(noreplace) %_sysconfdir/pam.d/system-policy-%name
%dir %attr(0700, root, root) %_cachedir/%name
%dir %attr(0755, root, root) %_cachedir/%{name}_file_cache
%dir %attr(0700, root, root) %_cachedir/%name/creds
%exclude %python3_sitelibdir/gpoa/.pylintrc
%exclude %python3_sitelibdir/gpoa/.prospector.yaml
@@ -112,6 +125,36 @@ fi
%exclude %python3_sitelibdir/gpoa/test
%changelog
* Wed Sep 29 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.7-alt1
- Fix regression with kestroy for user credential cache
- Update system-policy-gpupdate PAM-rules to ignore applying group policies
for local users and system users with uid less than 500
- Add control facilities to rule system-policy-gpupdate rules:
+ gpupdate-group-users
+ gpupdate-localusers
+ gpupdate-system-uids
* Mon Sep 20 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.6-alt1
- Add support changed GPO List Processing for '**DelVals.' value name
* Tue Sep 14 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.5-alt1
- Refix local policy path detection
- gpupdate-setup: revert settings to default when disabled
* Tue Sep 14 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.4-alt1
- Add improvement with new local-policy system-policy control
- Fix gpupdate-setup and user service installation regressions
- Set empty local policy and local backend by default
- Fix local policy path detection
* Mon Sep 06 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.3-alt1
- Use NetBIOS name for Kerberos authentification
- Add support actions (create, update, delete, replace) for Shortcuts
- Add support GSettings with locks feature
- Add support file cache for special GSettings policy:
Software\BaseALT\Policies\GSettings\org.mate.background.picture-filename
(requires python smbc module with use_kerberos option support)
* Wed Jul 28 2021 Evgeny Sinelnikov <sin@altlinux.org> 0.9.2-alt1
- Fix Shortcuts applier double running in user context
- Add LogonUser variable to expand_windows_var() function