advancing on new actor

This commit is contained in:
Adolfo Gómez García 2019-11-21 14:00:28 +01:00
parent 4df7c18ddc
commit 2cf869150f
7 changed files with 136 additions and 128 deletions

View File

@ -48,7 +48,6 @@ if typing.TYPE_CHECKING:
logger = logging.getLogger('actor')
class UDSConfigDialog(QDialog):
_host: str = ''
@ -103,7 +102,7 @@ class UDSConfigDialog(QDialog):
data: udsactor.types.InterfaceInfo = next(udsactor.operations.getNetworkInfo())
try:
key = self.api.register(
token = self.api.register(
self.ui.authenticators.currentData().auth,
self.ui.username.text(),
self.ui.password.text(),
@ -115,7 +114,13 @@ class UDSConfigDialog(QDialog):
(self.ui.logLevelComboBox.currentIndex() + 1) * 10000 # Loglevel
)
# Store parameters on register for later use, notify user of registration
udsactor.store.writeConfig(
udsactor.types.ActorConfigurationType(
host=self.ui.host.text(),
validateCertificate=self.ui.validateCertificate.currentIndex() == 1,
master_token=token
)
)
# Inform the user
QMessageBox.information(self, 'UDS Registration', 'Registration with UDS completed.', QMessageBox.Ok)
except udsactor.rest.RESTError as e:

View File

@ -34,9 +34,9 @@ from . import types
from . import rest
if sys.platform == 'win32':
from .windows import operations
from .windows import operations, store
else:
from .linux import operations
from .linux import operations, store
from .info import VERSION

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014 Virtual Cable S.L.
# Copyright (c) 2014-2019 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -29,45 +29,50 @@
'''
@author: Adolfo Gómez, dkmaster at dkmon dot com
'''
import six
import os
import configparser
import base64
import pickle
DEBUG = False
from .. import types
CONFIGFILE = '/etc/udsactor/udsactor.cfg' if DEBUG is False else '/tmp/udsactor.cfg'
PRECONNECT_CMD = '/etc/udsactor/pre'
CONFIGFILE = '/etc/udsactor/udsactor.cfg'
def checkPermissions() -> bool:
return os.getuid() == 0
def checkPermissions():
return True if DEBUG else os.getuid() == 0
def readConfig():
res = {}
def readConfig() -> types.ActorConfigurationType:
try:
cfg = six.moves.configparser.SafeConfigParser() # @UndefinedVariable
cfg.optionxform = six.text_type
cfg = configparser.ConfigParser()
cfg.read(CONFIGFILE)
# Just reads 'uds' section
for key in cfg.options('uds'):
res[key] = cfg.get('uds', key)
if res[key].lower() in ('true', 'yes', 'si'):
res[key] = True
elif res[key].lower() in ('false', 'no'):
res[key] = False
uds: configparser.SectionProxy = cfg['uds']
# Extract data:
base64Data = uds.get('data', None)
data = pickle.loads(base64.b64decode(base64Data.encode())) if base64Data else None
return types.ActorConfigurationType(
host=uds.get('host', ''),
validateCertificate=uds.getboolean('validate', fallback=False),
master_token=uds.get('master_token', None),
own_token=uds.get('own_token', None),
data=data
)
except Exception:
pass
return res
return types.ActorConfigurationType('', False)
def writeConfig(data):
cfg = six.moves.configparser.SafeConfigParser() # @UndefinedVariable
cfg.optionxform = six.text_type
def writeConfig(config: types.ActorConfigurationType) -> None:
cfg = configparser.ConfigParser()
cfg.add_section('uds')
for key, val in data.items():
cfg.set('uds', key, str(val))
uds: configparser.SectionProxy = cfg['uds']
uds['host'] = config.host
uds['validate'] = 'yes' if config.validateCertificate else 'no'
if config.master_token:
uds['master_token'] = config.master_token
if config.own_token:
uds['own_token'] = config.own_token
if config.data:
uds['data'] = base64.b64encode(pickle.dumps(config.data)).decode()
# Ensures exists destination folder
dirname = os.path.dirname(CONFIGFILE)
@ -77,17 +82,8 @@ def writeConfig(data):
with open(CONFIGFILE, 'w') as f:
cfg.write(f)
os.chmod(CONFIGFILE, 0o0600)
os.chmod(CONFIGFILE, 0o0600) # Ensure only readable by root
def useOldJoinSystem():
return False
# Right now, we do not really need an application to be run on "startup" as could ocur with windows
def runApplication():
return None
def preApplication():
return PRECONNECT_CMD

View File

@ -12,3 +12,10 @@ class AuthenticatorType(typing.NamedTuple):
type: str
priority: int
isCustom: bool
class ActorConfigurationType(typing.NamedTuple):
host: str
validateCertificate: bool
master_token: typing.Optional[str] = None
own_token: typing.Optional[str] = None
data: typing.Optional[typing.Dict[str, str]] = None

View File

@ -29,115 +29,75 @@
'''
@author: Adolfo Gómez, dkmaster at dkmon dot com
'''
from __future__ import unicode_literals
import pickle
from win32com.shell import shell # @UnresolvedImport, pylint: disable=import-error
try:
import typing
from win32com.shell import shell
import winreg as wreg
except ImportError: # Python 2.7 fallback
import _winreg as wreg # @UnresolvedImport, pylint: disable=import-error
import win32security # @UnresolvedImport, pylint: disable=import-error
import win32security
DEBUG = False
from .. import types
PATH = 'Software\\UDSActor'
BASEKEY = wreg.HKEY_LOCAL_MACHINE
# Can be changed to whatever we want, but registry key is protected by permissions
def encoder(data):
return data.encode('bz2')
def checkPermissions() -> bool:
return shell.IsUserAnAdmin()
def decoder(data):
return data.decode('bz2')
path = 'Software\\UDSActor'
baseKey = wreg.HKEY_CURRENT_USER if DEBUG is True else wreg.HKEY_LOCAL_MACHINE # @UndefinedVariable
def checkPermissions():
return True if DEBUG else shell.IsUserAnAdmin()
def fixRegistryPermissions(handle):
if DEBUG:
return
def fixRegistryPermissions(handle) -> None:
# Fix permissions so users can't read this key
v = win32security.GetSecurityInfo(handle, win32security.SE_REGISTRY_KEY, win32security.DACL_SECURITY_INFORMATION)
dacl = v.GetSecurityDescriptorDacl()
n = 0
# Remove all normal users access permissions to the registry key
while n < dacl.GetAceCount():
if unicode(dacl.GetAce(n)[2]) == u'PySID:S-1-5-32-545': # Whell known Users SID
if str(dacl.GetAce(n)[2]) == 'PySID:S-1-5-32-545': # Whell known Users SID
dacl.DeleteAce(n)
else:
n += 1
win32security.SetSecurityInfo(handle, win32security.SE_REGISTRY_KEY,
win32security.SetSecurityInfo(
handle,
win32security.SE_REGISTRY_KEY,
win32security.DACL_SECURITY_INFORMATION | win32security.PROTECTED_DACL_SECURITY_INFORMATION,
None, None, dacl, None)
None,
None,
dacl,
None
)
def readConfig():
def readConfig() -> types.ActorConfigurationType:
try:
key = wreg.OpenKey(baseKey, path, 0, wreg.KEY_QUERY_VALUE) # @UndefinedVariable
key = wreg.OpenKey(BASEKEY, PATH, 0, wreg.KEY_QUERY_VALUE) # @UndefinedVariable
data, _ = wreg.QueryValueEx(key, '') # @UndefinedVariable
wreg.CloseKey(key) # @UndefinedVariable
return pickle.loads(decoder(data))
return pickle.loads(data)
except Exception:
return None
return types.ActorConfigurationType('', False)
def writeConfig(data, fixPermissions=True):
def writeConfig(config: types.ActorConfigurationType) -> None:
try:
key = wreg.OpenKey(baseKey, path, 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
key = wreg.OpenKey(BASEKEY, PATH, 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
except Exception:
key = wreg.CreateKeyEx(baseKey, path, 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
if fixPermissions is True:
key = wreg.CreateKeyEx(BASEKEY, PATH, 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
fixRegistryPermissions(key.handle)
wreg.SetValueEx(key, "", 0, wreg.REG_BINARY, encoder(pickle.dumps(data))) # @UndefinedVariable
wreg.SetValueEx(key, "", 0, wreg.REG_BINARY, pickle.dumps(config)) # @UndefinedVariable
wreg.CloseKey(key) # @UndefinedVariable
def useOldJoinSystem():
def useOldJoinSystem() -> bool:
try:
key = wreg.OpenKey(baseKey, 'Software\\UDSEnterpriseActor', 0, wreg.KEY_QUERY_VALUE) # @UndefinedVariable
key = wreg.OpenKey(BASEKEY, 'Software\\UDSEnterpriseActor', 0, wreg.KEY_QUERY_VALUE) # @UndefinedVariable
try:
data, _ = wreg.QueryValueEx(key, 'join') # @UndefinedVariable
except Exception:
data = ''
wreg.CloseKey(key) # @UndefinedVariable
except:
except Exception:
data = ''
return data == 'old'
# Gives the oportunity to run an application ONE TIME (because, the registry key "run" will be deleted after read)
def runApplication():
try:
key = wreg.OpenKey(baseKey, 'Software\\UDSEnterpriseActor', 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
try:
data, _ = wreg.QueryValueEx(key, 'run') # @UndefinedVariable
wreg.DeleteValue(key, 'run') # @UndefinedVariable
except Exception:
data = None
wreg.CloseKey(key) # @UndefinedVariable
except Exception:
data = None
return data
def preApplication():
try:
key = wreg.OpenKey(baseKey, 'Software\\UDSEnterpriseActor', 0, wreg.KEY_ALL_ACCESS) # @UndefinedVariable
try:
data, _ = wreg.QueryValueEx(key, 'pre') # @UndefinedVariable
except Exception:
data = None
wreg.CloseKey(key) # @UndefinedVariable
except Exception:
data = None
return data

View File

@ -0,0 +1,29 @@
# Generated by Django 2.2.7 on 2019-11-21 12:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('uds', '0033_auto_20190814_0951'),
]
operations = [
migrations.CreateModel(
name='ActorToken',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('username', models.CharField(max_length=128)),
('ip_from', models.CharField(max_length=128)),
('ip', models.CharField(max_length=128)),
('mac', models.CharField(db_index=True, max_length=128, unique=True)),
('pre_command', models.CharField(blank=True, default='', max_length=255)),
('post_command', models.CharField(blank=True, default='', max_length=255)),
('runonce_command', models.CharField(blank=True, default='', max_length=255)),
('log_level', models.IntegerField()),
('token', models.CharField(db_index=True, max_length=48, unique=True)),
('stamp', models.DateTimeField()),
],
),
]

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014 Virtual Cable S.L.
# Copyright (c) 2012-2019 Virtual Cable S.L.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification,
@ -25,15 +25,26 @@
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'''
@author: Adolfo Gómez, dkmaster at dkmon dot com
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
'''
# pylint: disable=unused-wildcard-import, wildcard-import
from __future__ import unicode_literals
from django.db import models
import sys
if sys.platform == 'win32':
from udsactor.windows.store import * # @UnusedWildImport
else:
from udsactor.linux.store import * # @UnusedWildImport
class ActorToken(models.Model):
"""
UDS Actors tokens on DB
"""
username = models.CharField(max_length=128)
ip_from = models.CharField(max_length=128)
ip = models.CharField(max_length=128)
mac = models.CharField(max_length=128, db_index=True, unique=True)
pre_command = models.CharField(max_length=255, blank=True, default='')
post_command = models.CharField(max_length=255, blank=True, default='')
runonce_command = models.CharField(max_length=255, blank=True, default='')
log_level = models.IntegerField()
token = models.CharField(max_length=48, db_index=True, unique=True)
stamp = models.DateTimeField() # Date creation or validation of this entry
def __str__(self):
return '<ActorToken {} created on {} by {} from {}/{}>'.format(self.token, self.stamp, self.username, self.ip_from, self.ip)