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
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))
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()
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
# 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
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()
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,
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)
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
def test_non_vengeful(self): """Test ConfigRegistry not raining KeyError.""" try: Interfaces(None) except AttributeError: self.fail('Failed to create Interfaces(None)')
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)