Esempio n. 1
0
def handler(dn, new, old, command):

	configRegistry = ConfigRegistry()
	configRegistry.load()
	interfaces = Interfaces(configRegistry)

	# dymanic module object filter
	current_fqdn = "%s.%s" % (configRegistry['hostname'], domainname)
	current_ip = str(interfaces.get_default_ip_address().ip)

	new_univentionShareHost = new.get('univentionShareHost', [None])[0]
	if new and not new_univentionShareHost in (current_fqdn, current_ip):
		new = {}	## new object is not for this host

	old_univentionShareHost = old.get('univentionShareHost', [None])[0]
	if old and not old_univentionShareHost in (current_fqdn, current_ip):
		old = {}	## old object is not for this host

	if not (new or old):
		return

	# create tmp dir
	tmpDir = os.path.dirname(tmpFile)
	listener.setuid(0)
	try:
		if not os.path.exists(tmpDir):
			os.makedirs(tmpDir)
	except Exception, e:
		univention.debug.debug(
			univention.debug.LISTENER, univention.debug.ERROR,
			"%s: could not create tmp dir %s (%s)" % (name, tmpDir, str(e)))
		return
Esempio n. 2
0
	def __init__(self, ucr, profile, options):
		self.ucr = ucr
		self.profile = profile
		self.options = options
		self.ucr_changes = {}
		self.old_interfaces = Interfaces(ucr)
		self.logger = logging.getLogger("uss.network.change")

		self.update_config(self.only_network_config(profile))
Esempio n. 3
0
 def test_ipv6_order(self):
     """Test IPv6 ordering."""
     t = Interfaces(
         ucr={
             'interfaces/eth0/ipv6/default/address': '1:2:3:4:5:6:7:8',
             'interfaces/eth0/ipv6/default/prefix': '64',
             'interfaces/eth1/ipv6/default/address': '2:3:4:5:6:7:8:9',
             'interfaces/eth1/ipv6/default/prefix': '72',
             'interfaces/eth2/order': '1',
             'interfaces/eth2/ipv6/default/address': '3:4:5:6:7:8:9:a',
             'interfaces/eth2/ipv6/default/prefix': '80',
         })
     assert [] == [s.name for _n, s in t.ipv4_interfaces]
     assert ['eth2', 'eth0',
             'eth1'] == [s.name for s, _n in t.ipv6_interfaces]
     assert IPv6Interface(
         u'1:2:3:4:5:6:7:8/64') == t.get_default_ip_address()
     assert t.get_default_ipv4_address() is None
     assert IPv6Interface(
         u'1:2:3:4:5:6:7:8/64') == t.get_default_ipv6_address()
Esempio n. 4
0
 def test_basis(self):
     """Test basic configuration."""
     t = Interfaces(
         ucr={
             'gateway': '1.2.3.4',
             'ipv6/gateway': '1:2:3:4:5:6:7:8',
             'interfaces/primary': 'br0',
         })
     assert 'br0' == t.primary
     assert IPv4Address(u'1.2.3.4') == t.ipv4_gateway
     assert IPv6Address(u'1:2:3:4:5:6:7:8') == t.ipv6_gateway
     assert t.ipv6_gateway_zone_index is None
Esempio n. 5
0
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <http://www.gnu.org/licenses/>.

__package__='' 	# workaround for PEP 366
import listener
import os
import re
import univention.debug
import univention.lib.listenerSharePath
import cPickle
from univention.config_registry.interfaces import Interfaces

hostname=listener.baseConfig['hostname']
domainname=listener.baseConfig['domainname']
interfaces = Interfaces(listener.configRegistry)
ip = interfaces.get_default_ip_address().ip

name='nfs-shares'
description='Create configuration for NFS shares'
filter='(&(objectClass=univentionShare)(|(univentionShareHost=%s.%s)(univentionShareHost=%s)))' % (hostname, domainname, ip)
modrdn='1'

__exports = '/etc/exports'
__comment_pattern = re.compile('^"*/.*#[ \t]*LDAP:[ \t]*(.*)')

tmpFile = os.path.join("/var", "cache", "univention-directory-listener", name + ".oldObject")

def handler(dn, new, old, command):

	# create tmp dir
Esempio n. 6
0
def import_ou_with_existing_dc(use_cli_api=True, use_python_api=False):
    with univention.testing.ucr.UCSTestConfigRegistry() as ucr:
        with univention.testing.udm.UCSTestUDM() as udm:
            create_mail_domain(ucr, udm)
            dc_name = uts.random_name()

            dhcp_service_name = uts.random_name()

            dhcp_service = udm.create_object('dhcp/service',
                                             service=dhcp_service_name)

            dhcp_server = udm.create_object('dhcp/server',
                                            server=dc_name,
                                            superordinate=dhcp_service)

            dhcp_subnet_properties = {
                'subnet': '10.20.30.0',
                'subnetmask': '24',
            }
            dhcp_subnet1 = udm.create_object('dhcp/subnet',
                                             superordinate=dhcp_service,
                                             **dhcp_subnet_properties)

            default_ip = Interfaces().get_default_ip_address()
            dhcp_subnet_properties = {
                'subnet': default_ip.ip,
                'subnetmask': default_ip.prefixlen,
            }
            dhcp_subnet2 = udm.create_object('dhcp/subnet',
                                             superordinate=dhcp_service,
                                             **dhcp_subnet_properties)

            ou_name = uts.random_name()

            # creatd dc
            try:
                create_and_verify_ou(
                    ucr,
                    ou=ou_name,
                    ou_displayname=None,
                    dc=dc_name,
                    dc_administrative=None,
                    sharefileserver=None,
                    singlemaster=False,
                    noneducational_create_objects=True,
                    district_enable=False,
                    default_dcs=None,
                    dhcp_dns_clearou=False,
                    do_cleanup=False,
                    use_cli_api=use_cli_api,
                    use_python_api=use_python_api,
                )

                utils.verify_ldap_object(dhcp_subnet1, should_exist=True)
                utils.verify_ldap_object(dhcp_subnet2, should_exist=True)

                # dhcp subnet2 should be copied
                ou_base = get_ou_base(ou=ou_name, district_enable=False)
                new_dhcp_service_dn = 'cn=%(ou)s,cn=dhcp,%(ou_base)s' % {
                    'ou': ou_name,
                    'ou_base': ou_base
                }
                new_dhcp_subnet2_dn = 'cn=%s,%s' % (default_ip.ip,
                                                    new_dhcp_service_dn)
                utils.verify_ldap_object(new_dhcp_subnet2_dn,
                                         should_exist=True)

                # dhcp subnet1 should not be copied
                new_dhcp_subnet1_dn = 'cn=10.20.30.0,%s' % (
                    new_dhcp_service_dn)
                utils.verify_ldap_object(new_dhcp_subnet1_dn,
                                         should_exist=False)

                # dhcp server has been moved
                utils.verify_ldap_object('cn=%s,%s' %
                                         (dc_name, new_dhcp_service_dn),
                                         should_exist=True)
                utils.verify_ldap_object(dhcp_server, should_exist=False)
            finally:
                remove_ou(ou_name)

        utils.wait_for_replication()
def handler(dn, new, old, command):
    configRegistry = ConfigRegistry()
    configRegistry.load()
    interfaces = Interfaces(configRegistry)

    # dymanic module object filter
    current_fqdn = "%s.%s" % (configRegistry['hostname'], domainname)
    current_ip = str(interfaces.get_default_ip_address().ip)

    new_univentionShareHost = new.get('univentionShareHost', [None])[0]
    if new and new_univentionShareHost not in (current_fqdn, current_ip):
        new = {}  # new object is not for this host

    old_univentionShareHost = old.get('univentionShareHost', [None])[0]
    if old and old_univentionShareHost not in (current_fqdn, current_ip):
        old = {}  # old object is not for this host

    if not (new or old):
        return

    # create tmp dir
    tmpDir = os.path.dirname(tmpFile)
    listener.setuid(0)
    try:
        if not os.path.exists(tmpDir):
            os.makedirs(tmpDir)
    except Exception as e:
        univention.debug.debug(
            univention.debug.LISTENER, univention.debug.ERROR,
            "%s: could not create tmp dir %s (%s)" % (name, tmpDir, str(e)))
        return
    finally:
        listener.unsetuid()

    # modrdn stuff
    # 'r'+'a' -> renamed
    # command='r' and "not new and old"
    # command='a' and "new and not old"

    # write old object to pickle file
    oldObject = {}
    listener.setuid(0)
    try:
        # object was renamed -> save old object
        if command == "r" and old:
            f = open(tmpFile, "w+")
            os.chmod(tmpFile, 0o600)
            cPickle.dump({"dn": dn, "old": old}, f)
            f.close()
        elif command == "a" and not old and os.path.isfile(tmpFile):
            f = open(tmpFile, "r")
            p = cPickle.load(f)
            f.close()
            oldObject = p.get("old", {})
            os.remove(tmpFile)
    except Exception as e:
        if os.path.isfile(tmpFile):
            os.remove(tmpFile)
        univention.debug.debug(
            univention.debug.LISTENER, univention.debug.ERROR,
            "%s: could not read/write tmp file %s (%s)" %
            (name, tmpFile, str(e)))
    finally:
        listener.unsetuid()

    if old:
        share_name = old.get('univentionShareSambaName', [''])[0]
        share_name_mapped = urllib.quote(share_name, safe='')
        filename = '/etc/samba/shares.conf.d/%s' % (share_name_mapped, )
        listener.setuid(0)
        try:
            if os.path.exists(filename):
                os.unlink(filename)
        finally:
            listener.unsetuid()

    def _quote(arg):
        if ' ' in arg or '"' in arg or '\\' in arg:
            arg = '"%s"' % (arg.replace('\\', '\\\\').replace('"', '\\"'), )
        return arg.replace('\n', '')

    def _simple_quote(arg):
        return arg.replace('\n', '')

    def _map_quote(args):
        return (_quote(arg) for arg in args)

    if new:
        share_name = new.get('univentionShareSambaName', [''])[0]
        if not _validate_smb_share_name(share_name):
            univention.debug.debug(
                univention.debug.LISTENER, univention.debug.ERROR,
                "invalid samba share name: %r" % (share_name, ))
            return
        share_name_mapped = urllib.quote(share_name, safe='')
        filename = '/etc/samba/shares.conf.d/%s' % (share_name_mapped, )

        # important!: createOrRename() checks if the share path is allowed. this must be done prior to writing any files.
        # try to create directory to share
        if share_name != 'homes':
            # object was renamed
            if not old and oldObject and command == "a":
                old = oldObject
            listener.setuid(0)
            try:
                ret = univention.lib.listenerSharePath.createOrRename(
                    old, new, listener.configRegistry)
            finally:
                listener.unsetuid()
            if ret:
                univention.debug.debug(
                    univention.debug.LISTENER, univention.debug.ERROR,
                    "%s: rename/create of sharePath for %s failed (%s)" %
                    (name, dn, ret))
                return

        listener.setuid(0)
        try:
            fp = open(filename, 'w')

            print('[%s]' % (share_name, ), file=fp)
            if share_name != 'homes':
                print('path = %s' % _quote(new['univentionSharePath'][0]),
                      file=fp)
            mapping = [
                ('description', 'comment'),
                ('univentionShareSambaMSDFS', 'msdfs root'),
                ('univentionShareSambaWriteable', 'writeable'),
                ('univentionShareSambaBrowseable', 'browseable'),
                ('univentionShareSambaPublic', 'public'),
                ('univentionShareSambaDosFilemode', 'dos filemode'),
                ('univentionShareSambaHideUnreadable', 'hide unreadable'),
                ('univentionShareSambaCreateMode', 'create mode'),
                ('univentionShareSambaDirectoryMode', 'directory mode'),
                ('univentionShareSambaForceCreateMode', 'force create mode'),
                ('univentionShareSambaForceDirectoryMode',
                 'force directory mode'),
                ('univentionShareSambaLocking', 'locking'),
                ('univentionShareSambaBlockingLocks', 'blocking locks'),
                ('univentionShareSambaStrictLocking', 'strict locking'),
                ('univentionShareSambaOplocks', 'oplocks'),
                ('univentionShareSambaLevel2Oplocks', 'level2 oplocks'),
                ('univentionShareSambaFakeOplocks', 'fake oplocks'),
                ('univentionShareSambaBlockSize', 'block size'),
                ('univentionShareSambaCscPolicy', 'csc policy'),
                ('univentionShareSambaValidUsers', 'valid users'),
                ('univentionShareSambaInvalidUsers', 'invalid users'),
                ('univentionShareSambaForceUser', 'force user'),
                ('univentionShareSambaForceGroup', 'force group'),
                ('univentionShareSambaHideFiles', 'hide files'),
                ('univentionShareSambaNtAclSupport', 'nt acl support'),
                ('univentionShareSambaInheritAcls', 'inherit acls'),
                ('univentionShareSambaPostexec', 'postexec'),
                ('univentionShareSambaPreexec', 'preexec'),
                ('univentionShareSambaWriteList', 'write list'),
                ('univentionShareSambaVFSObjects', 'vfs objects'),
                ('univentionShareSambaInheritOwner', 'inherit owner'),
                ('univentionShareSambaInheritPermissions',
                 'inherit permissions'),
                ('univentionShareSambaHostsAllow', 'hosts allow'),
                ('univentionShareSambaHostsDeny', 'hosts deny'),
            ]

            vfs_objects = []
            samba4_ntacl_backend = listener.configRegistry.get(
                'samba4/ntacl/backend', 'native')
            if samba4_ntacl_backend == 'native':
                vfs_objects.append('acl_xattr')
                if listener.configRegistry.is_true(
                        'samba/vfs/acl_xattr/ignore_system_acls', False):
                    print('acl_xattr:ignore system acls = yes')
            elif samba4_ntacl_backend == 'tdb':
                vfs_objects.append('acl_tdb')

            additional_vfs_objects = new.get('univentionShareSambaVFSObjects',
                                             [])
            if additional_vfs_objects:
                vfs_objects.extend(additional_vfs_objects)

            if vfs_objects:
                print('vfs objects = %s' %
                      (' '.join(_map_quote(vfs_objects)), ),
                      file=fp)

            for attr, var in mapping:
                if not new.get(attr):
                    continue
                if attr == 'univentionShareSambaVFSObjects':
                    continue
                if attr == 'univentionShareSambaDirectoryMode' and new[
                        'univentionSharePath'] in ('/tmp', '/tmp/'):
                    continue
                if attr in ('univentionShareSambaHostsAllow',
                            'univentionShareSambaHostsDeny'):
                    print('%s = %s' % (var,
                                       (', '.join(_map_quote(new[attr])))),
                          file=fp)
                elif attr in ('univentionShareSambaValidUsers',
                              'univentionShareSambaInvalidUsers'):
                    print('%s = %s' % (var, _simple_quote(new[attr][0])),
                          file=fp)
                else:
                    print('%s = %s' % (var, _quote(new[attr][0])), file=fp)

            for setting in new.get(
                    'univentionShareSambaCustomSetting', []
            ):  # FIXME: vulnerable to injection of further paths and entries
                print(setting.replace('\n', ''), file=fp)

            # implicit settings

            # acl and inherit -> map acl inherit (Bug #47850)
            if '1' in new.get('univentionShareSambaNtAclSupport',
                              []) and '1' in new.get(
                                  'univentionShareSambaInheritAcls', []):
                print('map acl inherit = yes', file=fp)
        finally:
            listener.unsetuid()

    if (not (new and old)) or (new['univentionShareSambaName'][0] !=
                               old['univentionShareSambaName'][0]):
        global ucr_handlers
        listener.setuid(0)
        try:
            run_ucs_commit = False
            if not os.path.exists('/etc/samba/shares.conf'):
                run_ucs_commit = True
            fp = open('/etc/samba/shares.conf.temp', 'w')
            print(
                '# Warning: This file is auto-generated and will be overwritten by \n#          univention-directory-listener module. \n#          Please edit the following file instead: \n#          /etc/samba/local.conf \n  \n# Warnung: Diese Datei wurde automatisch generiert und wird durch ein \n#          univention-directory-listener Module überschrieben werden. \n#          Ergänzungen können an folgender Datei vorgenommen werden: \n# \n#          /etc/samba/local.conf \n#',
                file=fp)

            for f in os.listdir('/etc/samba/shares.conf.d'):
                print('include = %s' %
                      _quote(os.path.join('/etc/samba/shares.conf.d', f)),
                      file=fp)
            fp.close()
            os.rename('/etc/samba/shares.conf.temp', '/etc/samba/shares.conf')
            if run_ucs_commit:
                ucr_handlers.commit(listener.configRegistry,
                                    ['/etc/samba/smb.conf'])
        finally:
            listener.unsetuid()
Esempio n. 8
0
from tempfile import NamedTemporaryFile

from saml2 import BINDING_HTTP_REDIRECT, BINDING_HTTP_POST
from saml2.saml import NAME_FORMAT_URI

from univention.config_registry.interfaces import Interfaces
from univention.config_registry import ConfigRegistry

ucr = ConfigRegistry()
ucr.load()

if ucr.get('umc/saml/sp-server'):
    fqdn = ucr.get('umc/saml/sp-server')
    addresses = [fqdn]
else:
    i = Interfaces()
    try:
        fqdn = '%s.%s' % (ucr['hostname'], ucr['domainname'])
    except KeyError:
        fqdn = ''
    addresses = [fqdn]
    addresses.extend(
        [y['address'] for x, y in i.all_interfaces if y and y.get('address')])

bases = [
    '%s://%s/univention/saml' % (scheme, addr) for addr in addresses
    for scheme in ('https', 'http')
]
CONFIG = {
    "entityid": "https://%s/univention/saml/metadata" % (fqdn, ),
    "name_form": NAME_FORMAT_URI,
Esempio n. 9
0
def _handler(ucr, changes):
    changed_entries = set()
    for key in changes.keys():
        match = re.match('ucs/web/overview/entries/(admin|service)/([^/]+)/.*',
                         key)
        if match:
            changed_entries.add(match.group(2))
    changed_entries -= set(
        ['umc', 'invalid-certificate-list', 'root-certificate', 'ldap-master'])
    portal_logger.debug('Changed: %r' % changed_entries)
    if not changed_entries:
        return
    lo, pos = get_machine_connection()
    pos.setDn('cn=entry,cn=portals,cn=univention,%s' % ucr.get('ldap/base'))
    hostname = '%s.%s' % (ucr.get('hostname'), ucr.get('domainname'))

    # iterate over all ipv4 and ipv6 addresses and append them to the link
    local_hosts = [hostname]
    interfaces = Interfaces(ucr)
    for idev, iconf in interfaces.all_interfaces:
        # get ipv4 address of device
        if iconf.ipv4_address():
            local_hosts.append(str(iconf.ipv4_address().ip))

        # get ipv6 addresses of device
        for iname in iconf.ipv6_names:
            local_hosts.append('[%s]' % (iconf.ipv6_address(iname).ip, ))

    portal_logger.debug('Local hosts are: %r' % local_hosts)
    attr_entries = {}
    for changed_entry in changed_entries:
        attr_entries[changed_entry] = {}
    for ucr_key in ucr.keys():
        match = re.match('ucs/web/overview/entries/([^/]+)/([^/]+)/(.*)',
                         ucr_key)
        if not match:
            continue
        category = match.group(1)
        cn = match.group(2)
        key = match.group(3)
        value = ucr.get(ucr_key)
        if cn in attr_entries:
            portal_logger.debug('Matched %r -> %r' % (ucr_key, value))
            entry = attr_entries[cn]
            entry['name'] = cn
            if '_links' not in entry:
                links = []
                for host in local_hosts:
                    if host:
                        links.append(_Link(host=host))
                entry['_links'] = links
            if key == 'link':
                for link in entry['_links']:
                    if value.startswith('http'):
                        link.full = value
                    else:
                        link.path = value
            elif key == 'port_http':
                if value:
                    for link in entry['_links'][:]:
                        if link.protocol == 'https':
                            link = copy(link)
                            entry['_links'].append(link)
                        link.protocol = 'http'
                        link.port = value
            elif key == 'port_https':
                if value:
                    for link in entry['_links'][:]:
                        if link.protocol == 'http':
                            link = copy(link)
                            entry['_links'].append(link)
                        link.protocol = 'https'
                        link.port = value
            elif key == 'icon':
                try:
                    if value.startswith('/univention-management-console'):
                        value = '/univention%s' % value[30:]
                    with open('/var/www/%s' % value, 'rb') as fd:
                        entry['icon'] = b64encode(fd.read()).decode('ASCII')
                except EnvironmentError:
                    pass
            elif key == 'label':
                entry.setdefault('displayName', [])
                entry['displayName'].append(('en_US', value))
            elif key == 'label/de':
                entry.setdefault('displayName', [])
                entry['displayName'].append(('de_DE', value))
            elif key == 'label/fr':
                entry.setdefault('displayName', [])
                entry['displayName'].append(('fr_FR', value))
            elif key == 'description':
                entry.setdefault('description', [])
                entry['description'].append(('en_US', value))
            elif key == 'description/de':
                entry.setdefault('description', [])
                entry['description'].append(('de_DE', value))
            elif key == 'description/fr':
                entry.setdefault('description', [])
                entry['description'].append(('fr_FR', value))
            elif key == 'link-target':
                entry['linkTarget'] = value
            elif key == 'background-color':
                entry['backgroundColor'] = value
            else:
                portal_logger.info('Don\'t know how to handle UCR key %s' %
                                   ucr_key)
    for cn, attrs in attr_entries.items():
        dn = 'cn=%s,%s' % (escape_dn_chars(cn), pos.getDn())
        unprocessed_links = attrs.pop('_links', [])
        my_links = set()
        no_ports = all(not link.port for link in unprocessed_links)
        for link in unprocessed_links:
            if no_ports:
                if link.protocol == 'http':
                    link.port = '80'
                elif link.protocol == 'https':
                    link.port = '443'
            if link:
                my_links.add(('en_US', str(link)))
            if not link.protocol:
                link.protocol = 'http'
                if link:
                    my_links.add(('en_US', str(link)))
                link.protocol = 'https'
                if link:
                    my_links.add(('en_US', str(link)))
        my_links = list(my_links)
        portal_logger.debug('Processing %s' % dn)
        portal_logger.debug('Attrs: %r' % attrs)
        portal_logger.debug('Links: %r' % my_links)
        try:
            obj = init_object('portals/entry', lo, pos, dn)
        except AttributeError:
            portal_logger.error(
                'The handler is not ready yet. Portal modules are not installed. You may have to set the variables again.'
            )
            return
        except udm_errors.noObject:
            portal_logger.debug('DN not found...')
            if my_links:
                portal_logger.debug('... creating')
                attrs['link'] = my_links
                attrs['activated'] = True
                try:
                    create_object_if_not_exists('portals/entry', lo, pos,
                                                **attrs)
                except udm_errors.insufficientInformation as exc:
                    portal_logger.info('Cannot create: %s' % exc)
                try:
                    category_pos = position(ucr.get('ldap/base'))
                    category_pos.setDn('cn=category,cn=portals,cn=univention')
                    category_dn = 'cn=domain-%s,%s' % (
                        escape_dn_chars(category),
                        category_pos.getDn(),
                    )
                    portal_logger.debug('Adding entry to %s' % (category_dn, ))
                    obj = init_object('portals/category', lo, category_pos,
                                      category_dn)
                    entries = obj['entries']
                    entries.append(dn)
                    modify_object('portals/category',
                                  lo,
                                  category_pos,
                                  category_dn,
                                  entries=entries)
                except udm_errors.noObject:
                    portal_logger.debug('DN not found...')
            continue
        links = obj['link']
        portal_logger.debug('Existing links: %r' % links)
        links = [
            _link for _link in links
            if urlsplit(_link[1]).hostname not in local_hosts
        ]
        links.extend(my_links)
        portal_logger.debug('New links: %r' % links)
        if not links:
            portal_logger.debug('Removing DN')
            remove_object_if_exists('portals/entry', lo, pos, dn)
        else:
            portal_logger.debug('Modifying DN')
            attrs['link'] = links
            modify_object('portals/entry', lo, pos, dn, **attrs)
	def update_config(self, changes):
		self.ucr_changes.update(changes)
		new_ucr = dict(self.ucr.items())  # Bug #33101
		new_ucr.update(changes)
		self.new_interfaces = Interfaces(new_ucr)
Esempio n. 11
0
def handler(dn, new, old, command):
    configRegistry = ConfigRegistry()
    configRegistry.load()
    interfaces = Interfaces(configRegistry)

    # dymanic module object filter
    current_fqdn = "%s.%s" % (configRegistry['hostname'], domainname)
    current_ip = str(interfaces.get_default_ip_address().ip)

    new_univentionShareHost = new.get('univentionShareHost', [None])[0]
    if new and new_univentionShareHost not in (current_fqdn, current_ip):
        new = {}  # new object is not for this host

    old_univentionShareHost = old.get('univentionShareHost', [None])[0]
    if old and old_univentionShareHost not in (current_fqdn, current_ip):
        old = {}  # old object is not for this host

    if not (new or old):
        return

    # create tmp dir
    tmpDir = os.path.dirname(tmpFile)
    listener.setuid(0)
    try:
        if not os.path.exists(tmpDir):
            os.makedirs(tmpDir)
    except Exception as e:
        univention.debug.debug(
            univention.debug.LISTENER, univention.debug.ERROR,
            "%s: could not create tmp dir %s (%s)" % (name, tmpDir, str(e)))
        return
    finally:
        listener.unsetuid()

    # modrdn stuff
    # 'r'+'a' -> renamed
    # command='r' and "not new and old"
    # command='a' and "new and not old"

    # write old object to pickle file
    oldObject = {}
    listener.setuid(0)
    try:
        # object was renamed -> save old object
        if command == "r" and old:
            f = open(tmpFile, "w+")
            os.chmod(tmpFile, 0o600)
            cPickle.dump({"dn": dn, "old": old}, f)
            f.close()
        elif command == "a" and not old and os.path.isfile(tmpFile):
            f = open(tmpFile, "r")
            p = cPickle.load(f)
            f.close()
            oldObject = p.get("old", {})
            os.remove(tmpFile)
    except Exception as e:
        if os.path.isfile(tmpFile):
            os.remove(tmpFile)
        univention.debug.debug(
            univention.debug.LISTENER, univention.debug.ERROR,
            "%s: could not read/write tmp file %s (%s)" %
            (name, tmpFile, str(e)))
    finally:
        listener.unsetuid()

    if old:
        share_name = old.get('univentionShareSambaName', [''])[0]
        share_name_mapped = urllib.quote(share_name, safe='')
        filename = '/etc/samba/shares.conf.d/%s' % (share_name_mapped, )
        listener.setuid(0)
        try:
            if os.path.exists(filename):
                os.unlink(filename)
        finally:
            listener.unsetuid()

    def _quote(arg):
        if ' ' in arg or '"' in arg or '\\' in arg:
            arg = '"%s"' % (arg.replace('\\', '\\\\').replace('"', '\\"'), )
        return arg.replace('\n', '')

    def _simple_quote(arg):
        return arg.replace('\n', '')

    def _map_quote(args):
        return (_quote(arg) for arg in args)

    if new:
        share_name = new['univentionShareSambaName'][0]
        if not _validate_smb_share_name(share_name):
            univention.debug.debug(
                univention.debug.LISTENER, univention.debug.ERROR,
                "invalid samba share name: %r" % (share_name, ))
            return
        share_name_mapped = urllib.quote(share_name, safe='')
        filename = '/etc/samba/shares.conf.d/%s' % (share_name_mapped, )

        # important!: createOrRename() checks if the share path is allowed. this must be done prior to writing any files.
        # try to create directory to share
        if share_name != 'homes':
            # object was renamed
            if not old and oldObject and command == "a":
                old = oldObject
            listener.setuid(0)
            try:
                ret = univention.lib.listenerSharePath.createOrRename(
                    old, new, listener.configRegistry)
            finally:
                listener.unsetuid()
            if ret:
                univention.debug.debug(
                    univention.debug.LISTENER, univention.debug.ERROR,
                    "%s: rename/create of sharePath for %s failed (%s)" %
                    (name, dn, ret))
                return

        listener.setuid(0)
        try:
            fp = open(filename, 'w')

            print >> fp, '[%s]' % (share_name, )
            if share_name != 'homes':
                print >> fp, 'path = %s' % _quote(
                    new['univentionSharePath'][0])
            mapping = [
                ('description', 'comment'),
                ('univentionShareSambaMSDFS', 'msdfs root'),
                ('univentionShareSambaWriteable', 'writeable'),
                ('univentionShareSambaBrowseable', 'browseable'),
                ('univentionShareSambaPublic', 'public'),
                ('univentionShareSambaDosFilemode', 'dos filemode'),
                ('univentionShareSambaHideUnreadable', 'hide unreadable'),
                ('univentionShareSambaCreateMode', 'create mode'),
                ('univentionShareSambaDirectoryMode', 'directory mode'),
                ('univentionShareSambaForceCreateMode', 'force create mode'),
                ('univentionShareSambaForceDirectoryMode',
                 'force directory mode'),
                ('univentionShareSambaLocking', 'locking'),
                ('univentionShareSambaBlockingLocks', 'blocking locks'),
                ('univentionShareSambaStrictLocking', 'strict locking'),
                ('univentionShareSambaOplocks', 'oplocks'),
                ('univentionShareSambaLevel2Oplocks', 'level2 oplocks'),
                ('univentionShareSambaFakeOplocks', 'fake oplocks'),
                ('univentionShareSambaBlockSize', 'block size'),
                ('univentionShareSambaCscPolicy', 'csc policy'),
                ('univentionShareSambaValidUsers', 'valid users'),
                ('univentionShareSambaInvalidUsers', 'invalid users'),
                ('univentionShareSambaForceUser', 'force user'),
                ('univentionShareSambaForceGroup', 'force group'),
                ('univentionShareSambaHideFiles', 'hide files'),
                ('univentionShareSambaNtAclSupport', 'nt acl support'),
                ('univentionShareSambaInheritAcls', 'inherit acls'),
                ('univentionShareSambaPostexec', 'postexec'),
                ('univentionShareSambaPreexec', 'preexec'),
                ('univentionShareSambaWriteList', 'write list'),
                ('univentionShareSambaVFSObjects', 'vfs objects'),
                ('univentionShareSambaInheritOwner', 'inherit owner'),
                ('univentionShareSambaInheritPermissions',
                 'inherit permissions'),
                ('univentionShareSambaHostsAllow', 'hosts allow'),
                ('univentionShareSambaHostsDeny', 'hosts deny'),
            ]

            vfs_objects = []
            samba4_ntacl_backend = listener.configRegistry.get(
                'samba4/ntacl/backend', 'native')
            if samba4_ntacl_backend == 'native':
                vfs_objects.append('acl_xattr')
            elif samba4_ntacl_backend == 'tdb':
                vfs_objects.append('acl_tdb')

            additional_vfs_objects = new.get('univentionShareSambaVFSObjects',
                                             [])
            if additional_vfs_objects:
                vfs_objects.extend(additional_vfs_objects)

            if vfs_objects:
                print >> fp, 'vfs objects = %s' % (' '.join(
                    _map_quote(vfs_objects)), )

            for attr, var in mapping:
                if not new.get(attr):
                    continue
                if attr == 'univentionShareSambaVFSObjects':
                    continue
                if attr == 'univentionShareSambaDirectoryMode' and new[
                        'univentionSharePath'] in ('/tmp', '/tmp/'):
                    continue
                if attr in ('univentionShareSambaHostsAllow',
                            'univentionShareSambaHostsDeny'):
                    print >> fp, '%s = %s' % (var, (', '.join(
                        _map_quote(new[attr]))))
                elif attr in ('univentionShareSambaValidUsers',
                              'univentionShareSambaInvalidUsers'):
                    print >> fp, '%s = %s' % (var, _simple_quote(new[attr][0]))
                else:
                    print >> fp, '%s = %s' % (var, _quote(new[attr][0]))

            for setting in new.get(
                    'univentionShareSambaCustomSetting', []
            ):  # FIXME: vulnerable to injection of further paths and entries
                print >> fp, setting.replace('\n', '')

            # implicit settings

            # acl and inherit -> map acl inherit (Bug #47850)
            if '1' in new.get('univentionShareSambaNtAclSupport',
                              []) and '1' in new.get(
                                  'univentionShareSambaInheritAcls', []):
                print >> fp, 'map acl inherit = yes'
        finally:
            listener.unsetuid()

    if (not (new and old)) or (new['univentionShareSambaName'][0] !=
                               old['univentionShareSambaName'][0]):
        global ucr_handlers
        listener.setuid(0)
        try:
            run_ucs_commit = False
            if not os.path.exists('/etc/samba/shares.conf'):
                run_ucs_commit = True
            fp = open('/etc/samba/shares.conf.temp', 'w')
            print >> fp, '# Warning: This file is auto-generated and will be overwritten by \n#          univention-directory-listener module. \n#          Please edit the following file instead: \n#          /etc/samba/local.conf \n  \n# Warnung: Diese Datei wurde automatisch generiert und wird durch ein \n#          univention-directory-listener Modul überschrieben werden. \n#          Ergänzungen können an folgende Datei vorgenommen werden: \n# \n#          /etc/samba/local.conf \n#'

            for f in os.listdir('/etc/samba/shares.conf.d'):
                print >> fp, 'include = %s' % _quote(
                    os.path.join('/etc/samba/shares.conf.d', f))
            fp.close()
            os.rename('/etc/samba/shares.conf.temp', '/etc/samba/shares.conf')
            if run_ucs_commit:
                ucr_handlers.commit(listener.configRegistry,
                                    ['/etc/samba/smb.conf'])
        finally:
            listener.unsetuid()

    if 'univentionShareSambaBaseDirAppendACL' in new or 'univentionShareSambaBaseDirAppendACL' in old:
        listener.setuid(0)
        try:
            proc = subprocess.Popen(
                [
                    'samba-tool', 'ntacl', 'get', '--as-sddl',
                    new['univentionSharePath'][0]
                ],
                stdout=subprocess.PIPE,
                close_fds=True,
            )
            stdout, stderr = proc.communicate()
            stdout = str(stdout)
            prev_aces = set()
            new_aces = set()
            re_ace = re.compile(r'\(.+?\)')
            if 'univentionShareSambaBaseDirAppendACL' in old:
                prev_aces = set(
                    sum([
                        re.findall(re_ace, acl)
                        for acl in old['univentionShareSambaBaseDirAppendACL']
                    ], []))
            if 'univentionShareSambaBaseDirAppendACL' in new:
                new_aces = set(
                    sum([
                        re.findall(re_ace, acl)
                        for acl in new['univentionShareSambaBaseDirAppendACL']
                    ], []))

            if (new_aces and new_aces != prev_aces) or (prev_aces
                                                        and not new_aces):
                # if old != new -> delete everything from old!
                for ace in prev_aces:
                    stdout = stdout.replace(ace, '')

                # Aces might be in there from something else (like explicit setting)
                # We don't want duplicates.
                new_aces = [ace for ace in new_aces if ace not in stdout]
                # Deny must be placed before rest. This is not done implicitly.
                # Since deny might be present before, add allow.
                # Be as explicit as possible, because aliases like Du (domain users)
                # are possible.

                res = re.search(r'(O:.+?G:.+?)D:[^\(]*(.+)', stdout)
                if res:
                    # dacl-flags are removed implicitly.
                    owner = res.group(1)
                    old_aces = res.group(2)

                    old_aces = re.findall(re_ace, old_aces)
                    allow_aces = "".join(
                        [ace for ace in old_aces if 'A;' in ace])
                    deny_aces = "".join(
                        [ace for ace in old_aces if 'D;' in ace])
                    allow_aces += "".join(
                        [ace for ace in new_aces if 'A;' in ace])
                    deny_aces += "".join(
                        [ace for ace in new_aces if 'D;' in ace])

                    dacl_flags = ""
                    if new_aces:
                        dacl_flags = "PAI"
                    sddl = "{}D:{}{}{}".format(owner, dacl_flags,
                                               deny_aces.strip(),
                                               allow_aces.strip())
                    univention.debug.debug(
                        univention.debug.LISTENER, univention.debug.PROCESS,
                        "Set new nt %s acl for dir %s" %
                        (sddl, new['univentionSharePath'][0]))
                    proc = subprocess.Popen([
                        'samba-tool', 'ntacl', 'set', sddl,
                        new['univentionSharePath'][0]
                    ],
                                            stdout=subprocess.PIPE,
                                            close_fds=True)
                    _, stderr = proc.communicate()
                    if stderr:
                        univention.debug.debug(
                            univention.debug.LISTENER, univention.debug.ERROR,
                            "could not set nt acl for dir %s (%s)" %
                            (new['univentionSharePath'][0], stderr))
        finally:
            listener.unsetuid()
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <http://www.gnu.org/licenses/>.

from __future__ import absolute_import
import listener
import os
import re
import univention.debug
import univention.lib.listenerSharePath
import cPickle
from univention.config_registry.interfaces import Interfaces

hostname = listener.baseConfig['hostname']
domainname = listener.baseConfig['domainname']
interfaces = Interfaces(listener.configRegistry)
ip = interfaces.get_default_ip_address().ip

name = 'nfs-shares'
description = 'Create configuration for NFS shares'
filter = '(&(objectClass=univentionShare)(|(univentionShareHost=%s.%s)(univentionShareHost=%s)))' % (hostname, domainname, ip)
modrdn = '1'

__exports = '/etc/exports'
__comment_pattern = re.compile('^"*/.*#[ \t]*LDAP:[ \t]*(.*)')

tmpFile = '/var/cache/univention-directory-listener/nfs-shares.oldObject'


def handler(dn, new, old, command):
	# create tmp dir
Esempio n. 13
0
 def test_non_vengeful(self):
     """Test ConfigRegistry not raining KeyError."""
     try:
         Interfaces(None)
     except AttributeError:
         self.fail('Failed to create Interfaces(None)')
Esempio n. 14
0
	def setup_parser(self, parser):
		interfaces = Interfaces(ucr_instance())
		ip_address = interfaces.get_default_ip_address()
		super(DevSetupLocalAppcenter, self).setup_parser(parser)
		parser.add_argument('--appcenter-host', default=ip_address.ip, help='The hostname of the new App Center. Default: %(default)s')
		parser.add_argument('--revert', action='store_true', help='Reverts the changes of a previous dev-setup-local-appcenter')
def _handler(ucr, changes):
	changed_entries = set()
	for key in changes.keys():
		match = re.match('ucs/web/overview/entries/(admin|service)/([^/]+)/.*', key)
		if match:
			changed_entries.add(match.group(2))
	changed_entries -= set(['umc', 'invalid-certificate-list', 'root-certificate', 'ldap-master'])
	portal_logger.debug('Changed: %r' % changed_entries)
	if not changed_entries:
		return
	lo, pos = get_machine_connection()
	pos.setDn('cn=portal,cn=univention,%s' % ucr.get('ldap/base'))
	interfaces = Interfaces(ucr)
	hostname = '%s.%s' % (ucr.get('hostname'), ucr.get('domainname'))
	default_ipv4_address = interfaces.get_default_ipv4_address()
	if default_ipv4_address:
		default_ipv4_address = str(default_ipv4_address.ip)
	default_ipv6_address = interfaces.get_default_ipv6_address()
	if default_ipv6_address:
		default_ipv6_address = str(default_ipv6_address.ip)
	local_hosts = [hostname, default_ipv4_address, default_ipv6_address]
	portal_logger.debug('Local hosts are: %r' % local_hosts)
	attr_entries = {}
	for changed_entry in changed_entries:
		attr_entries[changed_entry] = {}
	for ucr_key in ucr.keys():
		match = re.match('ucs/web/overview/entries/([^/]+)/([^/]+)/(.*)', ucr_key)
		if not match:
			continue
		category = match.group(1)
		cn = match.group(2)
		key = match.group(3)
		value = ucr.get(ucr_key)
		if cn in attr_entries:
			portal_logger.debug('Matched %r -> %r' % (ucr_key, value))
			entry = attr_entries[cn]
			entry['category'] = category
			entry['name'] = cn
			if '_links' not in entry:
				links = []
				for host in local_hosts:
					if host:
						links.append(_Link(host=host))
				entry['_links'] = links
			if key == 'link':
				for link in entry['_links']:
					if value.startswith('http'):
						link.full = value
					else:
						link.path = value
			elif key == 'port_http':
				if value:
					for link in entry['_links'][:]:
						if link.protocol == 'https':
							link = copy(link)
							entry['_links'].append(link)
						link.protocol = 'http'
						link.port = value
			elif key == 'port_https':
				if value:
					for link in entry['_links'][:]:
						if link.protocol == 'http':
							link = copy(link)
							entry['_links'].append(link)
						link.protocol = 'https'
						link.port = value
			elif key == 'icon':
				try:
					if value.startswith('/univention-management-console'):
						value = '/univention%s' % value[30:]
					with open('/var/www/%s' % value) as fd:
						entry['icon'] = b64encode(fd.read())
				except EnvironmentError:
					pass
			elif key == 'label':
				entry.setdefault('displayName', [])
				entry['displayName'].append(('en_US', value))
			elif key == 'label/de':
				entry.setdefault('displayName', [])
				entry['displayName'].append(('de_DE', value))
			elif key == 'label/fr':
				entry.setdefault('displayName', [])
				entry['displayName'].append(('fr_FR', value))
			elif key == 'description':
				entry.setdefault('description', [])
				entry['description'].append(('en_US', value))
			elif key == 'description/de':
				entry.setdefault('description', [])
				entry['description'].append(('de_DE', value))
			elif key == 'description/fr':
				entry.setdefault('description', [])
				entry['description'].append(('fr_FR', value))
			else:
				portal_logger.info('Don\'t know how to handle UCR key %s' % ucr_key)
	for cn, attrs in attr_entries.items():
		dn = 'cn=%s,%s' % (escape_dn_chars(cn), pos.getDn())
		unprocessed_links = attrs.pop('_links', [])
		my_links = set()
		no_ports = all(not link.port for link in unprocessed_links)
		for link in unprocessed_links:
			if no_ports:
				if link.protocol == 'http':
					link.port = '80'
				elif link.protocol == 'https':
					link.port = '443'
			if link:
				my_links.add(str(link))
			if not link.protocol:
				link.protocol = 'http'
				if link:
					my_links.add(str(link))
				link.protocol = 'https'
				if link:
					my_links.add(str(link))
		my_links = list(my_links)
		portal_logger.debug('Processing %s' % dn)
		portal_logger.debug('Attrs: %r' % attrs)
		portal_logger.debug('Links: %r' % my_links)
		try:
			obj = init_object('settings/portal_entry', lo, pos, dn)
		except udm_errors.noObject:
			portal_logger.debug('DN not found...')
			if my_links:
				portal_logger.debug('... creating')
				attrs['link'] = my_links
				attrs['portal'] = ['cn=domain,cn=portal,cn=univention,%s' % ucr_get('ldap/base')]
				attrs['activated'] = True
				attrs['authRestriction'] = 'anonymous'
				try:
					create_object_if_not_exists('settings/portal_entry', lo, pos, **attrs)
				except udm_errors.insufficientInformation as exc:
					portal_logger.info('Cannot create: %s' % exc)
			continue
		links = obj['link']
		portal_logger.debug('Existing links: %r' % links)
		links = [_link for _link in links if urlsplit(_link).hostname not in local_hosts]
		links.extend(my_links)
		portal_logger.debug('New links: %r' % links)
		if not links:
			portal_logger.debug('Removing DN')
			remove_object_if_exists('settings/portal_entry', lo, pos, dn)
		else:
			portal_logger.debug('Modifying DN')
			attrs['link'] = links
			modify_object('settings/portal_entry', lo, pos, dn, **attrs)