def cups_printer_enable( self, object ): cmd = '/usr/bin/univention-cups-enable %s' % ' '.join( object.options[ 'printers' ] ) ud.debug( ud.ADMIN, ud.INFO, 'CUPS.enable: command: %s' % cmd ) proc = notifier.popen.Shell( cmd, stdout = False ) cb = notifier.Callback( self._cups_printer_enable_return, object ) proc.signal_connect( 'finished', cb ) proc.start()
def action( self, object ): ud.debug(ud.ADMIN, ud.INFO, 'UVMM.DW.action(current: %s)' % str( self.current ) ) if self.current is None: # read pool ud.debug( ud.ADMIN, ud.INFO, 'UVMM.DW.action: node storage pools: %s' % self.node_uri) self.set_defaults( object ) return umcd.IWizard.action( self, object )
def get_object_real( self, module, dn ): if self._cached.has_key( dn ): return self._cached[ dn ] if isinstance( module, basestring ): if self._modules.has_key( module ): module = self._modules[ module ] else: name = module module = ua_modules.get( name ) ua_modules.init( self._access, self._position, module ) self._modules[ name ] = module elif module == None: module = self.identify( dn ) if not module: return None ua_modules.init( self._access, self._position, module ) new = ua_objects.get( module, self._config, self._access, position = self._position, dn = dn ) # if the object is not valid it should be displayed as an empty object try: new.open() except Exception, e: # write the traceback in the logfile import traceback ud.debug( ud.ADMIN, ud.ERROR, 'The object %s could not be opened' % dn ) try: tb = traceback.format_exc().encode( 'ascii', 'replace' ).replace( '%', '?' ) # this might fail because of problems with univention.debug ud.debug( ud.ADMIN, ud.ERROR, 'Traceback: %s' % tb ) except: pass
def reload_daemon(daemon, prefix): script = os.path.join ('/etc/init.d', daemon) if os.path.exists(script): ud.debug(ud.LISTENER, ud.INFO, "%s %s reload" % (prefix, daemon) ) listener.run(script, [daemon,'reload'], uid=0) else: ud.debug(ud.LISTENER, ud.INFO, "%s no %s to reload found" % (prefix, daemon) )
def _pykota_set_quota( callback, **kwargs ): cmd = '/usr/bin/edpykota ' # check for boolean arguments for arg in [ 'add', 'delete', 'reset', 'hardreset' ]: if kwargs.get(arg) == True: cmd += '--%s ' % arg if kwargs.get('printers'): cmd += '--printer %s ' % ','.join(kwargs['printers']) if kwargs.get('softlimit'): cmd += '-S %s ' % kwargs['softlimit'] if kwargs.get('hardlimit'): cmd += '-H %s ' % kwargs['hardlimit'] if kwargs.get('lifetimecounter'): cmd += '--used %s ' % kwargs['lifetimecounter'] if kwargs.get('balance'): cmd += '--balance %s ' % str(kwargs['balance']) if kwargs.get('balance'): cmd += '--overcharge %s ' % str(kwargs['balance']) if kwargs.get('userlist'): cmd += ' %s ' % ' '.join(kwargs['userlist']) ud.debug( ud.ADMIN, ud.PROCESS, 'run: %s' % cmd ) proc = notifier.popen.RunIt( cmd ) proc.signal_connect( 'finished', callback ) proc.start()
def handler(dn, new, old, cmd): ud.debug(ud.LISTENER, ud.INFO, '2 master2 handler') if cmd == 'n': return name = new.get('cn', [None])[0] port = new.get('univentionOpenvpnPort', [None])[0] addr = new.get('univentionOpenvpnAddress', [None])[0] if not name or not port or not addr: return listener.setuid(0) lo = ul.getMachineConnection() vpnusers = lo.search('(univentionOpenvpnAccount=1)') if not univention_openvpn_common.check_user_count(2): return # do nothing for user in vpnusers: uid = user[1].get('uid', [None])[0] home = user[1].get('homeDirectory', ['/dev/null'])[0] ud.debug(ud.LISTENER, ud.INFO, '2 Create new certificate for %s in %s' % (uid, home)) proto = 'udp6' if addr and addr.count(':') else 'udp' if uid and home: # update bundle for this openvpn server with new config try: listener.run('/usr/lib/openvpn-int/create-bundle', ['create-bundle', 'no', uid, home, name, addr, port, proto], uid=0) finally: listener.unsetuid() listener.unsetuid()
def cups_printer_disable(self, object): cmd = "/usr/bin/univention-cups-disable %s" % " ".join(object.options["printers"]) ud.debug(ud.ADMIN, ud.INFO, "CUPS.enable: command: %s" % cmd) proc = notifier.popen.Shell(cmd, stdout=False) cb = notifier.Callback(self._cups_printer_disable_return, object) proc.signal_connect("finished", cb) proc.start()
def cups_quota_user_show(self, object): if object.options.get("printer") and object.options.get("user"): cb = notifier.Callback(self._cups_quota_user_show_return, object) pykota._pykota_get_quota_users([object.options["printer"]], cb) else: self._cups_quota_user_show_return(0, None, object) ud.debug(ud.ADMIN, ud.WARN, "CUPS.quota_user_show: no printer or no user turned over")
def update_extended_options(lo, module, position): """Overwrite options defined via LDAP.""" # get current language lang = locale.getlocale(locale.LC_MESSAGES)[0] ud.debug(ud.ADMIN, ud.INFO, 'modules update_extended_options: LANG=%s' % lang) if lang: lang = lang.replace('_','-').lower() else: lang = 'xxxxx' # append UDM extended options for dn, attrs in lo.search(base=position.getDomainConfigBase(), filter='(&(objectClass=univentionUDMOption)(univentionUDMOptionModule=%s))' % name(module)): oname = attrs['cn'][0] shortdesc = attrs.get('univentionUDMOptionTranslationShortDescription;entry-%s' % lang, attrs['univentionUDMOptionShortDescription'])[0] longdesc = attrs.get('univentionUDMOptionTranslationLongDescription;entry-%s' % lang, attrs.get('univentionUDMOptionLongDescription', ['']))[0] default = attrs.get('univentionUDMOptionDefault', ['0'])[0] == '1' editable = attrs.get('univentionUDMOptionEditable', ['0'])[0] == '1' classes = attrs.get('univentionUDMOptionObjectClass', []) module.options[oname] = univention.admin.option( short_description=shortdesc, long_description=longdesc, default=default, editable=editable, objectClasses=classes)
def _create_type_select_button(self, options, items): """Create list to select driver-type allowed by current driver-pool.""" # FIXME: items are ignored for some unknown reason opts = copy.deepcopy(options) opts['action'] = 'type-selected' action = umcd.Action(umcp.SimpleCommand(self.command, options=opts), items) choices = ( ('RAW', _('Simple format (raw)')), ) try: pool_name = options['pool-name'] ud.debug(ud.ADMIN, ud.ALL, 'UVMM.DW.ts(pool-name=%s)' % pool_name) if self._is_file_pool(pool_name): if self.node_uri.startswith('qemu'): choices = ( #('qcow', _('Extended format (qcow)')), ('qcow2', _('Extended format (qcow2)')), #('vmdk', _('VMWare Disk')), ('raw', _('Simple format (raw)')), ) elif self.node_uri.startswith('xen'): choices = ( ('raw', _('Simple format (raw)')), #('qcow2', _('Qemu copy-on-write 2')), #('vhd', _('Virtual Hard Disk')), #('vmdk', _('VMWare Disk')), ) except LookupError, e: ud.debug(ud.ADMIN, ud.ALL, 'UVMM.DW.ts exception=%s' % e)
def check_sitetosite(no): listener.setuid(0) lo = ul.getMachineConnection() servers = lo.search('(univentionOpenvpnLicense=*)') sitetosite = False for server in servers: key = server[1].get('univentionOpenvpnLicense', [None])[0] try: l = license(no, key) ud.debug(ud.LISTENER, ud.INFO, '%d Processing license with ID %s:' % (no, l['id'])) ud.debug(ud.LISTENER, ud.INFO, '%d Valid until: %s' % (no, date.fromordinal(l['vdate']))) ud.debug(ud.LISTENER, ud.INFO, '%d Users: %s' % (no, l['u'])) ud.debug(ud.LISTENER, ud.INFO, '%d Site-2-Site: %s' % (no, l['s2s'])) if l.get('s2s'): sitetosite = True break except: pass listener.unsetuid() if not sitetosite: ud.debug(ud.LISTENER, ud.INFO, '%d Skipping actions' % no) return False else: return True
def license(no, key): try: enc = b64decode(key) raw = '' while len(enc) > pbs: d, key = (enc[:pbs], enc[pbs:]) raw = raw + pub.public_decrypt(d, 1) if len(enc) != pbs: return None # invalid license raw = raw + pub.public_decrypt(enc, 1) # items = raw.rstrip().split('\n') if not items: return None # invalid license vdate = int(items.pop(0)) if date.today().toordinal() > vdate: ud.debug(ud.LISTENER, ud.ERROR, '%d License has expired' % no) return None # expired l = {'valid': True, 'vdate': vdate} # at least one feature returned while items: kv = items.pop(0).split('=', 1) kv.append(True) l[kv[0]] = kv[1] return l # valid license except: return None # invalid license
def maxvpnusers(no, key): mnlu = 5 try: return max(int(license(no, key)['u']), mnlu) except: ud.debug(ud.LISTENER, ud.ERROR, '%d Invalid license' % no) return mnlu # invalid license
def _pykota_get_quota_users( printernamelist, callback ): cmd = 'LC_ALL="C" LANG="C" /usr/bin/repykota -P%s' % ','.join(printernamelist) ud.debug( ud.ADMIN, ud.INFO, 'CUPS.quota command: %s' % cmd ) proc = notifier.popen.Shell( cmd, stdout = True ) cb = notifier.Callback( _pykota_get_quota_users_return, callback ) proc.signal_connect( 'finished', cb ) proc.start()
def cups_quota_user_reset(self, object): ud.debug(ud.ADMIN, ud.INFO, "cups_quota_user_reset: %s" % str(object.options)) pykota._pykota_set_quota( notifier.Callback(self._cups_quota_user_reset_return, object), printers=[object.options["printer"]], userlist=object.options["user"], reset=True, )
def _kill_children(pids, timeout=5): """Kill children.""" for pid in pids: try: os.kill(pid, signal.SIGTERM) except OSError, ex: if ex.errno != errno.ESRCH: ud.debug(ud.LISTENER, ud.WARN, 'DNS: Unexpected error: %s' % (ex,))
def write_rc(no, flist, wfile): listener.setuid(0) try: f = open(wfile,"w") f.writelines(flist) f.close() except Exception, e: ud.debug(ud.LISTENER, ud.ERROR, '%d Failed to write file "%s": %s' % (no, wfile, str(e)))
def _ldap_modlist(self): # we get a list of modifications to be done (called 'ml' down below) # this lists looks like this: # [('univentionMailHomeServer', [u'ugs-master.hosts.invalid'], u'ugs-master.hosts.invalid'), ('univentionMailUserQuota', u'100', u'101')] # we can modify those entries to conform to the LDAP schema ml=univention.admin.handlers.simpleLdap._ldap_modlist(self) if self.hasChanged( 'mailPrimaryAddress' ) and self[ 'mailPrimaryAddress' ]: for i, j in self.alloc: if i == 'mailPrimaryAddress': break else: ml.append( ( 'univentionMailSharedFolderDeliveryAddress', self.oldattr.get( 'univentionMailSharedFolderDeliveryAddress', [] ), [ 'univentioninternalpostuser+shared/%s@%s' % ( self[ 'name' ].lower(), self[ 'mailDomain' ].lower() ) ] ) ) address = '%s@%s' % ( self[ 'name' ], self[ 'mailDomain' ] ) if self[ 'mailPrimaryAddress' ] != address: try: self.alloc.append( ( 'mailPrimaryAddress', self[ 'mailPrimaryAddress' ] ) ) univention.admin.allocators.request( self.lo, self.position, 'mailPrimaryAddress', value = self[ 'mailPrimaryAddress' ] ) except: univention.admin.allocators.release( self.lo, self.position, 'mailPrimaryAddress', value = self[ 'mailPrimaryAddress' ] ) raise univention.admin.uexceptions.mailAddressUsed if not self[ 'mailPrimaryAddress' ]: ml.append( ( 'univentionMailSharedFolderDeliveryAddress', self.oldattr.get( 'univentionMailSharedFolderDeliveryAddress', [] ), [] ) ) rewrite_acl = False new_acls_tmp = [] for attr in [ 'sharedFolderUserACL', 'sharedFolderGroupACL' ]: ud.debug( ud.ADMIN, ud.INFO, 'ACLs: %s' % str( self[ attr ] ) ) if self.hasChanged( attr ): rewrite_acl = True # re-use regular expressions from syntax definitions if attr=='sharedFolderUserACL': _sre = univention.admin.syntax.UserMailAddress.regex else: _sre = univention.admin.syntax.GroupName.regex for acl in self[ attr ]: if acl == '': continue if _sre.match( acl[ 0 ] ): new_acls_tmp.append( ' '.join( acl ) ) else: for acl in self[attr]: if acl == '': continue new_acls_tmp.append( ' '.join( acl ) ) if rewrite_acl: for (a, b, c) in ml: if a in ['sharedFolderUserACL', 'sharedFolderGroupACL']: ml.remove((a, b, c)) ml.append( ( 'univentionMailACL', self.oldattr.get( 'univentionMailACL', [] ), new_acls_tmp ) ) return ml
def identifyNIC( self, domain_info, options ): typ, src, mac = self.optionsNIC( options ) for iface in domain_info.interfaces: if self.sameNIC( iface, typ, src, mac ): ud.debug( ud.ADMIN, ud.INFO, 'NIC identify: found %s: %s, %s, %s' % ( str( iface ), typ, src, mac ) ) return iface ud.debug( ud.ADMIN, ud.INFO, 'NIC identify: NOT found' )
def load_rc(no, ofile): l = None listener.setuid(0) try: f = open(ofile,"r") l = f.readlines() f.close() except Exception, e: ud.debug(ud.LISTENER, ud.ERROR, '%d Failed to read file "%s": %s' % (no, ofile, str(e)) )
def uvmm_nic_edit( self, object ): ud.debug( ud.ADMIN, ud.INFO, 'Network interface edit' ) tv = TreeView(self.uvmm, object) try: res = tv.get_tree_response(TreeView.LEVEL_DOMAIN) node_uri = tv.node_uri domain_info = tv.domain_info except (uvmmd.UvmmError, KeyError), e: return self.uvmm_node_overview( object )
def write_ip_map(no, ip_map, path): listener.setuid(0) try: with open(path, 'wb') as f: w = csv.writer(f, delimiter=' ', quotechar='|', quoting=csv.QUOTE_MINIMAL) for i in ip_map: w.writerow(i) except Exception, e: ud.debug(ud.LISTENER, ud.ERROR, '%d Failed to write ip map: %s' % (no, str(e)))
def handler(dn, new, old): """Handle changes to 'dn'.""" setuid(0) try: if configRegistry["server/role"] != "domaincontroller_master": return global uidNumber try: uidNumber = int(new.get("uidNumber", ["0"])[0]) except (LookupError, TypeError, ValueError): uidNumber = 0 global gidNumber try: gidNumber = int(grp.getgrnam("DC Backup Hosts")[2]) except (LookupError, TypeError, ValueError): ud.debug(ud.LISTENER, ud.WARN, 'CERTIFICATE: Failed to get groupID for "%s"' % dn) gidNumber = 0 if new and not old: # changeType: add try: domain = new["associatedDomain"][0] except LookupError: domain = configRegistry["domainname"] create_certificate(new["cn"][0], domainname=domain) elif old and not new: # changeType: delete try: domain = old["associatedDomain"][0] except LookupError: domain = configRegistry["domainname"] remove_certificate(old["cn"][0], domainname=domain) else: # changeType: modify try: old_domain = old["associatedDomain"][0] except LookupError: old_domain = configRegistry["domainname"] try: new_domain = new["associatedDomain"][0] except LookupError: new_domain = configRegistry["domainname"] if new_domain != old_domain: remove_certificate(old["cn"][0], domainname=old_domain) create_certificate(new["cn"][0], domainname=new_domain) else: # Reset permissions fqdn = "%s.%s" % (new["cn"][0], new_domain) certpath = os.path.join(SSLDIR, fqdn) os.path.walk(certpath, set_permissions, None) finally: unsetuid()
def uvmm_nic_remove( self, object ): ud.debug( ud.ADMIN, ud.INFO, 'Network interface remove' ) res = umcp.Response( object ) report = '' try: node_uri, node_name = self.uvmm.node_uri_name(object.options['node']) node_info, domain_info = self.uvmm.get_domain_info_ext(node_uri, object.options['domain']) except UvmmError, e: return self.uvmm_node_overview( object )
def load_ip_map(no, path): ip_map = [] listener.setuid(0) try: with open(path, 'rb') as f: r = csv.reader(f, delimiter=' ', quotechar='|') for row in r: ip_map.append(row) except Exception, e: ud.debug(ud.LISTENER, ud.ERROR, '%d Failed to load ip map: %s' % (no, str(e)))
def setup( self, object, prev = None, next = None, finish = None, cancel = None ): """Setup page self.current and render it to UMC primitives.""" ud.debug(ud.ADMIN, ud.INFO, 'UVMM.DW.setup(current=%s, prev_first_page=%s)' % (str(self.current), self.prev_first_page)) page = self[self.current] # this page we're going to present if self.current == DriveWizard.PAGE_INIT and self.prev_first_page: prev = True if self.change and self.current <= DriveWizard.PAGE_HD: prev = False if self.current == DriveWizard.PAGE_HD: drive_type = object.options['drive-type'] if drive_type == 'disk': self.disk_select.set_choices() elif drive_type in ('cdrom', 'floppy'): self.disk_select.set_choices(with_new=False) else: raise ValueError('Invalid drive-type "%(drive-type)s"' % object.options) if self.current == DriveWizard.PAGE_OLD: drive_type = object.options['drive-type'] self.pool_selected(object) self.type_selected(object) if drive_type == 'disk': page.description = _('Each hard drive image is located within a so called storage pool, which might be a local directory, a device, an LVM volume or any type of share (e.g. mounted via iSCSI, NFS or CIFS). When selecting a storage pool the list of available images is updated.') elif drive_type in ('cdrom', 'floppy'): page.description = _('Each image is located within a so called storage pool, which might be a local directory, a device, an LVM volume or any type of share (e.g. mounted via iSCSI, NFS or CIFS). When selecting a storage pool the list of available images is updated.') else: raise ValueError('Invalid drive-type "%s"' % drive_type) if self.current == DriveWizard.PAGE_NEW: self.pool_selected(object) self.type_selected(object) if self.current == DriveWizard.PAGE_SUMMARY: r = self.request_data(object) page.options = options = [] conf = umcd.List() conf.add_row([umcd.HTML('<i>%s</i>' % _('Drive type')), self._disk_type_text(r.drive_type)]) if r.pool_path: conf.add_row([umcd.HTML('<i>%s</i>' % _('Storage pool')), _('path: %(path)s') % {'path': r.pool_path}]) if len(r.vol_path) > 60: conf.add_row([umcd.HTML('<i>%s</i>' % _('Image filename')), umcd.HTML('<p title="%s">%s...</p>' %(xml_escape(r.vol_path), xml_escape(r.vol_path[0:60])))]) else: conf.add_row([umcd.HTML('<i>%s</i>' % _('Image filename')), r.vol_path]) conf.add_row([umcd.HTML('<i>%s</i>' % _('Image format')), r.driver_type]) conf.add_row([umcd.HTML('<i>%s</i>' % _('Image size')), r.vol_size]) elif r.vol_path: conf.add_row([umcd.HTML('<i>%s</i>' % _('Device filename')), r.vol_path]) else: conf.add_row([umcd.HTML('<i>%s</i>' % _('Device filename')), '-']) options.append(conf) return umcd.IWizard.setup( self, object, prev = prev, next = next, finish = finish, cancel = cancel )
def uvmm_drive_bootdevice( self, object ): """Change boot device for Xen-PV.""" ud.debug(ud.ADMIN, ud.INFO, 'UVMM.drive_bootdevice(%(disk)s)' % object.options) res = umcp.Response( object ) try: node_uri, node_name = self.uvmm.node_uri_name(object.options['node']) node_info, domain_info = self.uvmm.get_domain_info_ext(node_uri, object.options['domain']) except UvmmError, e: ud.debug(ud.ADMIN, ud.INFO, 'UVMM.drive_bootdevice: node %(node)s#%(domain)s not found' % request.options) return self.uvmm_node_overview( object )
def cups_printer_quota_show( self, object ): if object.incomplete: self.finished( object.id(), [] ) return cmd = '/usr/bin/lpstat -o %s' % object.options[ 'printer' ] ud.debug( ud.ADMIN, ud.INFO, 'CUPS.show: command: %s' % cmd ) proc = notifier.popen.Shell( cmd, stdout = True ) cb = notifier.Callback( self._cups_printer_show_return, object ) proc.signal_connect( 'finished', cb ) proc.start()
def remove_ldap_server(ucr, name, domain, role): """Remove LDAP server.""" ud.debug(ud.LISTENER, ud.INFO, 'LDAP_SERVER: Remove ldap_server %s' % name) server_name = "%s.%s" % (name, domain) if role == 'backup': backup_list = ucr.get('ldap/backup', '').split() if server_name in backup_list: backup_list.remove(server_name) univention.config_registry.handler_set(['ldap/backup=%s' % (' '.join(backup_list),)])
def open(self): # find the producer univention.admin.handlers.simpleLdap.open(self) models = printermodel.lookup( self.co, self.lo, 'printerModel="%s*' % self[ 'model' ] ) ud.debug( ud.ADMIN, ud.ERROR, "printermodel: %s" % str( models ) ) if not models or len( models ) > 1: self[ 'producer' ] = [] else: self[ 'producer' ] = models[ 0 ].dn self.save()
def handler(self, dn, new, old, name=None): """Handle LDAP ACL extensions on Master, Backup and Slave""" if not listener.configRegistry.get('ldap/server/type'): return if not listener.configRegistry.get('server/role') in ('domaincontroller_master'): # new, ignore first *inactive* appearance, has to be activated on master first if new and not old and new.get('univentionLDAPACLActive', ['FALSE'])[0] != 'TRUE': ud.debug(ud.LISTENER, ud.PROCESS, '%s: ignore first appearance of %s, not yet activated' % (name, dn)) return # ignore change unless (re) activated if new and old: if not new.get('univentionLDAPACLActive', ['FALSE'])[0] == 'TRUE': ud.debug(ud.LISTENER, ud.PROCESS, '%s: ignore modify of %s, not yet activated' % (name, dn)) return # Check UCS version requirements first and skip new if they are not met. if new: univentionUCSVersionStart = new.get('univentionUCSVersionStart', [None])[0] univentionUCSVersionEnd = new.get('univentionUCSVersionEnd', [None])[0] current_UCS_version = "%s-%s" % (listener.configRegistry.get('version/version'), listener.configRegistry.get('version/patchlevel')) if univentionUCSVersionStart and UCS_Version(current_UCS_version) < UCS_Version(univentionUCSVersionStart): ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s requires at least UCR version %s.' % (name, new['cn'][0], univentionUCSVersionStart)) new = None elif univentionUCSVersionEnd and UCS_Version(current_UCS_version) > UCS_Version(univentionUCSVersionEnd): ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s specifies compatibility only up to and including UCR version %s.' % (name, new['cn'][0], univentionUCSVersionEnd)) new = None if new: new_version = new.get('univentionOwnedByPackageVersion', [None])[0] if not new_version: return new_pkgname = new.get('univentionOwnedByPackage', [None])[0] if not new_pkgname: return ud.debug(ud.LISTENER, ud.PROCESS, '%s: %s active? %s' % (name, dn, new.get('univentionLDAPACLActive'))) if old: # check for trivial changes diff_keys = [key for key in new.keys() if new.get(key) != old.get(key) and key not in ('entryCSN', 'modifyTimestamp', 'modifiersName')] if diff_keys == ['univentionLDAPACLActive'] and new.get('univentionLDAPACLActive')[0] == 'TRUE': # ignore status change on master, already activated if listener.configRegistry.get('server/role') in ('domaincontroller_master'): ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: activation status changed.' % (name, new['cn'][0])) return elif diff_keys == ['univentionAppIdentifier']: ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: App identifier changed.' % (name, new['cn'][0])) return ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: changed attributes: %s' % (name, new['cn'][0], diff_keys)) if new_pkgname == old.get('univentionOwnedByPackage', [None])[0]: old_version = old.get('univentionOwnedByPackageVersion', ['0'])[0] rc = apt.apt_pkg.version_compare(new_version, old_version) if not rc > -1: ud.debug(ud.LISTENER, ud.WARN, '%s: New version is lower than version of old object (%s), skipping update.' % (name, old_version)) return try: new_object_data = bz2.decompress(new.get('univentionLDAPACLData')[0]) except TypeError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error uncompressing data of object %s.' % (name, dn)) return new_basename = new.get('univentionLDAPACLFilename')[0] new_filename = os.path.join(self.ucr_slapd_conf_subfile_dir, new_basename) listener.setuid(0) try: backup_filename = None backup_ucrinfo_filename = None backup_backlink_filename = None if old: old_filename = os.path.join(self.ucr_slapd_conf_subfile_dir, old.get('univentionLDAPACLFilename')[0]) if os.path.exists(old_filename): backup_fd, backup_filename = tempfile.mkstemp() ud.debug(ud.LISTENER, ud.INFO, '%s: Moving old file %s to %s.' % (name, old_filename, backup_filename)) try: shutil.move(old_filename, backup_filename) except IOError: ud.debug(ud.LISTENER, ud.WARN, '%s: Error renaming old file %s, removing it.' % (name, old_filename)) os.unlink(old_filename) backup_filename = None os.close(backup_fd) # plus the old backlink file old_backlink_filename = "%s.info" % old_filename if os.path.exists(old_backlink_filename): backup_backlink_fd, backup_backlink_filename = tempfile.mkstemp() ud.debug(ud.LISTENER, ud.INFO, '%s: Moving old backlink file %s to %s.' % (name, old_backlink_filename, backup_backlink_filename)) try: shutil.move(old_backlink_filename, backup_backlink_filename) except IOError: ud.debug(ud.LISTENER, ud.WARN, '%s: Error renaming old backlink file %s, removing it.' % (name, old_backlink_filename)) os.unlink(old_backlink_filename) backup_backlink_filename = None os.close(backup_backlink_fd) # and the old UCR registration old_ucrinfo_filename = os.path.join(self.ucr_info_basedir, "%s%s.info" % (self.file_prefix, old.get('univentionLDAPACLFilename')[0])) if os.path.exists(old_ucrinfo_filename): backup_ucrinfo_fd, backup_ucrinfo_filename = tempfile.mkstemp() ud.debug(ud.LISTENER, ud.INFO, '%s: Moving old UCR info file %s to %s.' % (name, old_ucrinfo_filename, backup_ucrinfo_filename)) try: shutil.move(old_ucrinfo_filename, backup_ucrinfo_filename) except IOError: ud.debug(ud.LISTENER, ud.WARN, '%s: Error renaming old UCR info file %s, removing it.' % (name, old_ucrinfo_filename)) os.unlink(old_ucrinfo_filename) backup_ucrinfo_filename = None os.close(backup_ucrinfo_fd) if not os.path.isdir(self.ucr_slapd_conf_subfile_dir): if os.path.exists(self.ucr_slapd_conf_subfile_dir): ud.debug(ud.LISTENER, ud.WARN, '%s: Directory name %s occupied, renaming blocking file.' % (name, self.ucr_slapd_conf_subfile_dir)) shutil.move(self.ucr_slapd_conf_subfile_dir, "%s.bak" % self.ucr_slapd_conf_subfile_dir) ud.debug(ud.LISTENER, ud.INFO, '%s: Create directory %s.' % (name, self.ucr_slapd_conf_subfile_dir)) os.makedirs(self.ucr_slapd_conf_subfile_dir, 0o755) # Create new extension file try: ud.debug(ud.LISTENER, ud.INFO, '%s: Writing new extension file %s.' % (name, new_filename)) with open(new_filename, 'w') as f: f.write(new_object_data) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error writing file %s.' % (name, new_filename)) return # plus backlink file try: new_backlink_filename = "%s.info" % new_filename ud.debug(ud.LISTENER, ud.INFO, '%s: Writing backlink file %s.' % (name, new_backlink_filename)) with open(new_backlink_filename, 'w') as f: f.write("%s\n" % dn) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error writing backlink file %s.' % (name, new_backlink_filename)) return # and UCR registration try: new_ucrinfo_filename = os.path.join(self.ucr_info_basedir, "%s%s.info" % (self.file_prefix, new.get('univentionLDAPACLFilename')[0])) ud.debug(ud.LISTENER, ud.INFO, '%s: Writing UCR info file %s.' % (name, new_ucrinfo_filename)) with open(new_ucrinfo_filename, 'w') as f: f.write("Type: multifile\nMultifile: etc/ldap/slapd.conf\n\nType: subfile\nMultifile: etc/ldap/slapd.conf\nSubfile: etc/ldap/slapd.conf.d/%s\n" % new_basename) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error writing UCR info file %s.' % (name, new_ucrinfo_filename)) return # Commit to slapd.conf ucr = ConfigRegistry() ucr.load() ucr_handlers = configHandlers() ucr_handlers.load() ucr_handlers.update() ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) # validate p = subprocess.Popen(['/usr/sbin/slaptest', '-u'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True) stdout, stderr = p.communicate() if p.returncode != 0: ud.debug(ud.LISTENER, ud.ERROR, '%s: slapd.conf validation failed:\n%s.' % (name, stdout)) # Revert changes ud.debug(ud.LISTENER, ud.ERROR, '%s: Removing new file %s.' % (name, new_filename)) os.unlink(new_filename) os.unlink(new_backlink_filename) os.unlink(new_ucrinfo_filename) if backup_filename: ud.debug(ud.LISTENER, ud.ERROR, '%s: Restoring previous file %s.' % (name, old_filename)) try: shutil.move(backup_filename, old_filename) os.close(backup_fd) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error reverting to old file %s.' % (name, old_filename)) # plus backlink file if backup_backlink_filename: ud.debug(ud.LISTENER, ud.ERROR, '%s: Restoring previous backlink file %s.' % (name, old_backlink_filename)) try: shutil.move(backup_backlink_filename, old_backlink_filename) os.close(backup_backlink_fd) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error reverting to old backlink file %s.' % (name, old_backlink_filename)) # and the old UCR registration if backup_ucrinfo_filename: ud.debug(ud.LISTENER, ud.ERROR, '%s: Restoring previous UCR info file %s.' % (name, old_ucrinfo_filename)) try: shutil.move(backup_ucrinfo_filename, old_ucrinfo_filename) os.close(backup_ucrinfo_fd) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error reverting to old UCR info file %s.' % (name, old_ucrinfo_filename)) # Commit and exit ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) return ud.debug(ud.LISTENER, ud.INFO, '%s: validation successful.' % (name,)) # cleanup backup if backup_filename: ud.debug(ud.LISTENER, ud.INFO, '%s: Removing backup of old file %s.' % (name, backup_filename)) os.unlink(backup_filename) os.close(backup_fd) # plus backlink file if backup_backlink_filename: ud.debug(ud.LISTENER, ud.INFO, '%s: Removing backup of old backlink file %s.' % (name, backup_backlink_filename)) os.unlink(backup_backlink_filename) os.close(backup_backlink_fd) # and the old UCR registration if backup_ucrinfo_filename: ud.debug(ud.LISTENER, ud.INFO, '%s: Removing backup of old UCR info file %s.' % (name, backup_ucrinfo_filename)) os.unlink(backup_ucrinfo_filename) os.close(backup_ucrinfo_fd) self._todo_list.append(dn) self._do_reload = True finally: listener.unsetuid() elif old: old_filename = os.path.join(self.ucr_slapd_conf_subfile_dir, old.get('univentionLDAPACLFilename')[0]) # plus backlink file old_backlink_filename = "%s.info" % old_filename # and the old UCR registration old_ucrinfo_filename = os.path.join(self.ucr_info_basedir, "%s%s.info" % (self.file_prefix, old.get('univentionLDAPACLFilename')[0])) if os.path.exists(old_filename): listener.setuid(0) try: ud.debug(ud.LISTENER, ud.INFO, '%s: Removing extension %s.' % (name, old['cn'][0])) if os.path.exists(old_ucrinfo_filename): os.unlink(old_ucrinfo_filename) if os.path.exists(old_backlink_filename): os.unlink(old_backlink_filename) os.unlink(old_filename) ucr = ConfigRegistry() ucr.load() ucr_handlers = configHandlers() ucr_handlers.load() ucr_handlers.update() ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) self._todo_list.append(dn) self._do_reload = True finally: listener.unsetuid()
def __update_membership(self): if self.exists(): old_groups = self.oldinfo.get('memberOf', []) old_name = self.oldinfo.get('name', '') new_name = self.info.get('name', '') else: old_groups = [] old_name = "" new_name = "" # rewrite membership attributes in "supergroup" if we have a new name (rename) if old_name and old_name != new_name: ud.debug(ud.ADMIN, ud.INFO, 'groups/group: rewrite memberuid after rename') for group in self.info.get('memberOf', []): if isinstance(group, list): group = group[0] members = self.lo.getAttr(group, 'uniqueMember') newmembers = copy.deepcopy(members) newmembers = self.__case_insensitive_remove_from_list( self.old_dn, newmembers) newmembers.append(self.dn) self.__set_membership_attributes(group, members, newmembers) add_to_group = [] remove_from_group = [] for group in old_groups: if group and not self.__case_insensitive_in_list( group, self.info.get('memberOf', [])): remove_from_group.append(group) for group in self.info.get('memberOf', []): if group and not self.__case_insensitive_in_list( group, old_groups): add_to_group.append(group) for group in add_to_group: if isinstance(group, list): group = group[0] members = self.lo.getAttr(group, 'uniqueMember') if self.__case_insensitive_in_list(self.dn, members): continue newmembers = copy.deepcopy(members) newmembers.append(self.dn) ud.debug(ud.ADMIN, ud.INFO, 'groups/group: add to supergroup %s' % group) self.__set_membership_attributes(group, members, newmembers) for group in remove_from_group: if isinstance(group, list): group = group[0] members = self.lo.getAttr(group, 'uniqueMember') newmembers = copy.deepcopy(members) if self.__case_insensitive_in_list(self.dn, members): newmembers = self.__case_insensitive_remove_from_list( self.dn, newmembers) if self.__case_insensitive_in_list(self.old_dn, newmembers): newmembers = self.__case_insensitive_remove_from_list( self.old_dn, newmembers) if members != newmembers: ud.debug(ud.ADMIN, ud.INFO, 'groups/group: remove from supergroup %s' % group) self.__set_membership_attributes(group, members, newmembers)
def unmapHWAddress(old): ud.debug(ud.ADMIN, ud.INFO, 'host.py: unmapHWAddress: old: %s' % old) if not old: return ['', ''] return old[0].split(' ')
def handler(dn, new, old, command): # type: (str, dict, dict, str) -> None # create tmp dir tmpDir = os.path.dirname(tmpFile) listener.setuid(0) try: if not os.path.exists(tmpDir): os.makedirs(tmpDir) except Exception as exc: ud.debug(ud.LISTENER, ud.ERROR, "%s: could not create tmp dir %s (%s)" % (name, tmpDir, exc)) 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: with open(tmpFile, "wb") as fp: os.chmod(tmpFile, 0o600) pickle.dump({"dn": dn, "old": old}, fp) elif command == "a" and not old: if os.path.isfile(tmpFile): with open(tmpFile, "rb") as fp: p = pickle.load(fp) oldObject = p.get("old", {}) os.remove(tmpFile) except Exception as exc: if os.path.isfile(tmpFile): os.remove(tmpFile) ud.debug(ud.LISTENER, ud.ERROR, "%s: could not read/write tmp file %s (%s)" % (name, tmpFile, exc)) finally: listener.unsetuid() # update exports file lines = _read(lambda match: not match or match.group(1) != _quote(dn)) if new and b'univentionShareNFS' in new.get('objectClass', []): path = new['univentionSharePath'][0].decode('UTF-8') options = [ 'rw' if new.get('univentionShareWriteable', [b''])[0] == b'yes' else 'ro', 'root_squash' if new.get('univentionShareNFSRootSquash', [b''])[0] == b'yes' else 'no_root_squash', 'async' if new.get('univentionShareNFSSync', [b''])[0] == b'async' else 'sync', 'subtree_check' if new.get('univentionShareNFSSubTree', [b''])[0] == b'yes' else 'no_subtree_check', ] + [cs.decode('UTF-8') for cs in new.get('univentionShareNFSCustomSetting', [])] lines.append('%s -%s %s # LDAP:%s' % ( _exports_escape(path), _quote(','.join(options)), _quote(' '.join(nfs_allowed.decode('ASCII') for nfs_allowed in new.get('univentionShareNFSAllowed', [b'*']))), _quote(dn) )) _write(lines) listener.setuid(0) try: # object was renamed if not old and oldObject and command == "a": old = oldObject ret = univention.lib.listenerSharePath.createOrRename(old, new, listener.configRegistry) if ret: ud.debug(ud.LISTENER, ud.ERROR, "%s: rename/create of sharePath for %s failed (%s)" % (name, dn, ret)) finally: listener.unsetuid() else: _write(lines)
def handler(dn, new, listener_old, operation): global reconnect if not slave: return 1 check_file_system_space() ud.debug(ud.LISTENER, ud.INFO, 'replication: Running handler %s for: %s' % (operation, dn)) if dn == 'cn=Subschema': return update_schema(new) connect_count = 0 connected = 0 while connect_count < 31 and not connected: try: l = connect() except ldap.LDAPError as ex: connect_count += 1 if connect_count >= 30: log_ldap(ud.ERROR, 'going into LDIF mode', ex) reconnect = 1 l = connect(ldif=1) else: log_ldap(ud.WARN, 'Can not connect LDAP Server, retry in 10 seconds', ex) reconnect = 1 time.sleep(10) else: connected = 1 if 'pwdAttribute' in new: if new['pwdAttribute'][0] == 'userPassword': new['pwdAttribute'] = ['2.5.4.35'] try: # Read old entry directly from LDAP server if not isinstance(l, LDIFObject): old = getOldValues(l, dn) if ud.get_level(ud.LISTENER) >= ud.INFO: # Check if both entries really match match = 1 if len(old) != len(listener_old): ud.debug( ud.LISTENER, ud.INFO, 'replication: LDAP keys=%s; listener keys=%s' % (list(old.keys()), list(listener_old.keys()))) match = 0 else: for k in old: if k in EXCLUDE_ATTRIBUTES: continue if k not in listener_old: ud.debug( ud.LISTENER, ud.INFO, 'replication: listener does not have key %s' % (k, )) match = 0 break if len(old[k]) != len(listener_old[k]): ud.debug( ud.LISTENER, ud.INFO, 'replication: LDAP and listener values diff for %s' % (k, )) match = 0 break for v in old[k]: if v not in listener_old[k]: ud.debug( ud.LISTENER, ud.INFO, 'replication: listener does not have value for key %s' % (k, )) match = 0 break if not match: ud.debug( ud.LISTENER, ud.INFO, 'replication: old entries from LDAP server and Listener do not match' ) else: old = listener_old # add if new: if os.path.exists(CURRENT_MODRDN) and not isinstance( l, LDIFObject): target_uuid_file = os.readlink(CURRENT_MODRDN) old_dn = _read_dn_from_file(CURRENT_MODRDN) new_entryUUID = new['entryUUID'][0] modrdn_cache = os.path.join(STATE_DIR, new_entryUUID) if modrdn_cache == target_uuid_file: ud.debug( ud.LISTENER, ud.PROCESS, 'replication: rename phase II: %s (entryUUID=%s)' % (dn, new_entryUUID)) if old: # this means the target already exists, we have to delete this old object ud.debug( ud.LISTENER, ud.PROCESS, 'replication: the rename target already exists in the local LDAP, backup and remove the dn: %s' % (dn, )) _backup_dn_recursive(l, dn) _delete_dn_recursive(l, dn) if getOldValues(l, old_dn): # the normal rename is possible new_dn = ldap.dn.str2dn(dn) new_parent = ldap.dn.dn2str(new_dn[1:]) new_rdn = ldap.dn.dn2str([new_dn[0]]) delold = 0 for (key, value, _typ) in ldap.dn.str2dn(old_dn)[0]: if key not in new: ud.debug( ud.LISTENER, ud.ALL, 'replication: move: attr %s not present' % (key, )) delold = 1 elif value not in new[key]: ud.debug( ud.LISTENER, ud.ALL, 'replication: move: val %s not present in attr %s' % (value, new[key])) delold = 1 ud.debug( ud.LISTENER, ud.PROCESS, 'replication: rename from %s to %s' % (old_dn, dn)) l.rename_s(old_dn, new_rdn, new_parent, delold=delold) _remove_file(modrdn_cache) else: # the old object does not exists, so we have to re-create the new object ud.debug( ud.LISTENER, ud.ALL, 'replication: the local target does not exist, so the object will be added: %s' % dn) _add_object_from_new(l, dn, new) _remove_file(modrdn_cache) else: # current_modrdn points to a different file ud.debug( ud.LISTENER, ud.PROCESS, 'replication: the current modrdn points to a different entryUUID: %s' % (target_uuid_file, )) if old_dn: ud.debug( ud.LISTENER, ud.PROCESS, 'replication: the DN %s from the %s has to be backuped and removed' % (old_dn, CURRENT_MODRDN)) _backup_dn_recursive(l, old_dn) _delete_dn_recursive(l, old_dn) else: ud.debug(ud.LISTENER, ud.WARN, 'replication: no old dn has been found') if not old: _add_object_from_new(l, dn, new) elif old: _modify_object_from_old_and_new(l, dn, old, new) _remove_file(CURRENT_MODRDN) elif old: # modify: new and old _modify_object_from_old_and_new(l, dn, old, new) else: # add: new and not old _add_object_from_new(l, dn, new) # delete elif old and not new: if operation == 'r': # check for modrdn phase 1 old_entryUUID = old['entryUUID'][0] ud.debug( ud.LISTENER, ud.PROCESS, 'replication: rename phase I: %s (entryUUID=%s)' % (dn, old_entryUUID)) modrdn_cache = os.path.join(STATE_DIR, old_entryUUID) try: with open(modrdn_cache, 'w') as f: os.fchmod(f.fileno(), 0o600) f.write(dn) _remove_file(CURRENT_MODRDN) os.symlink(modrdn_cache, CURRENT_MODRDN) # that's it for now for command 'r' ==> modrdn will follow in the next step return except EnvironmentError as ex: # d'oh! output some message and continue doing a delete+add instead ud.debug( ud.LISTENER, ud.ERROR, 'replication: failed to open/write modrdn file %s: %s' % (modrdn_cache, ex)) ud.debug(ud.LISTENER, ud.ALL, 'replication: delete: %s' % dn) _delete_dn_recursive(l, dn) except ldap.SERVER_DOWN as ex: log_ldap(ud.WARN, 'retrying', ex) reconnect = 1 handler(dn, new, listener_old, operation) except ldap.ALREADY_EXISTS as ex: log_ldap(ud.WARN, 'trying to apply changes', ex, dn=dn) try: cur = l.search_s(dn, ldap.SCOPE_BASE, '(objectClass=*)')[0][1] except ldap.LDAPError as ex: log_ldap(ud.ERROR, 'going into LDIF mode', ex) reconnect = 1 connect(ldif=1) handler(dn, new, listener_old, operation) else: handler(dn, new, cur, operation) except ldap.CONSTRAINT_VIOLATION as ex: log_ldap(ud.ERROR, 'Constraint violation', ex, dn=dn) except ldap.LDAPError as ex: log_ldap(ud.ERROR, 'Error', ex, dn=dn) if listener.baseConfig.get('ldap/replication/fallback', 'ldif') == 'restart': ud.debug( ud.LISTENER, ud.ERROR, 'replication: Uncaught LDAPError. Exiting Univention Directory Listener to retry replication with an updated copy of the current upstream object.' ) sys.exit(1) # retry a bit later after restart via runsv else: reconnect = 1 connect(ldif=1) handler(dn, new, listener_old, operation)
def cancel(self): for i, j in self.alloc: ud.debug(ud.ADMIN, ud.WARN, 'cancel: release (%s): %s' % (i, j)) univention.admin.allocators.release(self.lo, self.position, i, j)
'YQ==' >>> unmapBase64(['a', 'b']) ['YQ==', 'Yg=='] >>> unmapBase64([None]) '' """ if len(value) > 1: try: return map(base64.b64encode, value) except Exception, e: ud.debug(ud.ADMIN, ud.ERROR, 'ERROR in unmapBase64: %s' % e) else: try: return base64.b64encode(value[0]) except Exception, e: ud.debug(ud.ADMIN, ud.ERROR, 'ERROR in unmapBase64: %s' % e) return "" def mapBase64(value): # type: (Union[List[str], str]) -> Union[List[str], str] # @overload (List[str]) -> List[str] # @overload (str) -> str """ Convert Base64 encoded |UDM| property values to binary data (for storage in |LDAP|). :param value: some base64 encoded value. :returns: the decoded binary data. >>> mapBase64('*') '*'
self.alloc.append(('groupName', self['name'])) name = univention.admin.allocators.request(self.lo, self.position, 'groupName', value=self['name']) ud.debug(ud.ADMIN, ud.INFO, 'groups/group: requested groupname without exception') except univention.admin.uexceptions.permissionDenied, e: ud.debug( ud.ADMIN, ud.INFO, 'groups/group: requested groupname with permissionDenied exception' ) raise e except univention.admin.uexceptions.licenseNotFound, e: ud.debug( ud.ADMIN, ud.INFO, 'groups/group: requested groupname with licenseNotFound exception' ) raise e except univention.admin.uexceptions.licenseInvalid, e: ud.debug( ud.ADMIN, ud.INFO, 'groups/group: requested groupname with licenseInvalid exception' ) raise e except univention.admin.uexceptions.licenseExpired, e: ud.debug( ud.ADMIN, ud.INFO, 'groups/group: requested groupname with licenseExpired exception' ) raise e except univention.admin.uexceptions.licenseWrongBaseDn, e:
EXCLUDE_ATTRIBUTES = set( attr.lower() for attr in { 'subschemaSubentry', 'hasSubordinates', 'entryDN', 'authTimestamp', 'pwdChangedTime', 'pwdAccountLockedTime', 'pwdFailureTime', 'pwdHistory', 'pwdGraceUseTime', 'pwdReset', 'pwdPolicySubentry', } | (set() if listener.baseConfig.is_true('ldap/overlay/memberof' ) else {'memberOf'})) ud.debug(ud.LISTENER, ud.ALL, 'replication: EXCLUDE_ATTRIBUTES=%r' % (EXCLUDE_ATTRIBUTES, )) # don't use built-in OIDs from slapd BUILTIN_OIDS = [ # attributeTypes '1.3.6.1.1.4', # vendorName '1.3.6.1.1.5', # vendorVersion '1.3.6.1.4.1.250.1.57', # labeledURI '1.3.6.1.4.1.250.1.32', # krbName '1.3.6.1.4.1.1466.101.119.2', # dynamicObject '1.3.6.1.4.1.1466.101.119.3', # entryTtl '1.3.6.1.4.1.1466.101.119.4', # dynamicSubtrees '1.3.6.1.4.1.1466.101.120.5', # namingContexts '1.3.6.1.4.1.1466.101.120.6', # altServer '1.3.6.1.4.1.1466.101.120.7', # supportedExtension '1.3.6.1.4.1.1466.101.120.13', # supportedControla
def handler(dn, new, old): """Handle changes to 'dn'.""" global changed ucr = univention.config_registry.ConfigRegistry() ud.debug(ud.LISTENER, ud.INFO, "plucs: DN '%s' changed" % dn) ud.debug(ud.LISTENER, ud.INFO, "plucs: old = '%s'" % old.get('xmppDomains')) ud.debug(ud.LISTENER, ud.INFO, "plucs: new = '%s'" % new.get('xmppDomains')) # It should be possible to switch off an XMPP host by removing the # XMPP service entry, without losing its xmppDomains. hasService = 'XMPP' in new.get('univentionService') ud.debug(ud.LISTENER, ud.INFO, "plucs: service XMPP = %s" % hasService) # Old LDAP value doesn't matter. # We have to compare with the old value currently stored in UCR. oldval = ucr.get('xmpp/domains') msg = '' if not hasService: msg = 'service XMPP not assigned' newval = '' elif new.get('xmppDomains') is None: msg = 'no XMPP domains set' newval = '' else: newval = ' '.join(new.get('xmppDomains')) if newval == '': msg = 'list of XMPP domains is empty' if msg != '': ud.debug(ud.LISTENER, ud.INFO, "plucs: %s" % msg) if oldval != newval: changed = True listener.setuid(0) ud.debug(ud.LISTENER, ud.INFO, "plucs: setting xmpp domains to '%s'" % newval) try: univention.config_registry.handler_set( ['xmpp/domains=%s' % newval]) finally: listener.unsetuid()
def initialize(): """Initialize the module once on first start or after clean.""" ud.debug(ud.LISTENER, ud.INFO, 'plucs: initialized')
global changed if not changed: ud.debug(ud.LISTENER, ud.INFO, "plucs: nothing changed, not restarting daemon.") return changed = False ucr = univention.config_registry.ConfigRegistry() ucr.load() if ucr.is_true("plucs/autostart", False): if ucr.is_true('plucs/restart/listener', False): ud.debug(ud.LISTENER, ud.INFO, 'PLUCS: Restarting server') try: listener.run('/usr/sbin/invoke-rc.d', ['invoke-rc.d', 'plucs', 'restart'], uid=0) except Exception, e: ud.debug(ud.ADMIN, ud.WARN, 'The restart of the PLUCS server failed: %s' % str(e)) else: ud.debug( ud.ADMIN, ud.INFO, 'PLUCS: the automatic restart of the PLUCS server by the listener is disabled. Set plucs/restart/listener to true to enable this option.' ) else: ud.debug( ud.LISTENER, ud.INFO, 'plucs: autostart disabled in config_registry - not started.')
def handler(dn, new, old): """Handle UDM extension modules""" if new: ocs = new.get('objectClass', []) univentionUCSVersionStart = new.get('univentionUCSVersionStart', [None])[0] univentionUCSVersionEnd = new.get('univentionUCSVersionEnd', [None])[0] current_UCS_version = "%s-%s" % (listener.configRegistry.get('version/version'), listener.configRegistry.get('version/patchlevel')) if univentionUCSVersionStart and UCS_Version(current_UCS_version) < UCS_Version(univentionUCSVersionStart): ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s requires at least UCR version %s.' % (name, new['cn'][0], univentionUCSVersionStart)) new = None elif univentionUCSVersionEnd and UCS_Version(current_UCS_version) > UCS_Version(univentionUCSVersionEnd): ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s specifies compatibility only up to and including UCR version %s.' % (name, new['cn'][0], univentionUCSVersionEnd)) new = None elif old: ocs = old.get('objectClass', []) if 'univentionUDMModule' in ocs: objectclass = 'univentionUDMModule' udm_module_name = 'settings/udm_module' target_subdir = 'univention/admin/handlers' elif 'univentionUDMHook' in ocs: objectclass = 'univentionUDMHook' udm_module_name = 'settings/udm_hook' target_subdir = 'univention/admin/hooks.d' elif 'univentionUDMSyntax' in ocs: objectclass = 'univentionUDMSyntax' udm_module_name = 'settings/udm_syntax' target_subdir = 'univention/admin/syntax.d' else: ud.debug(ud.LISTENER, ud.ERROR, '%s: Undetermined error: unknown objectclass: %s.' % (name, ocs)) old_relative_filename = None if old: old_relative_filename = old.get('%sFilename' % objectclass)[0] if new: new_version = new.get('univentionOwnedByPackageVersion', [None])[0] if not new_version: return new_pkgname = new.get('univentionOwnedByPackage', [None])[0] if not new_pkgname: return if old: # check for trivial changes diff_keys = [key for key in new.keys() if new.get(key) != old.get(key) and key not in ('entryCSN', 'modifyTimestamp', 'modifiersName')] if diff_keys == ['%sActive' % objectclass] and new.get('%sActive' % objectclass)[0] == 'TRUE': ud.debug(ud.LISTENER, ud.INFO, '%s: %s: activation status changed.' % (name, new['cn'][0])) return elif diff_keys == ['univentionAppIdentifier']: ud.debug(ud.LISTENER, ud.INFO, '%s: %s: App identifier changed.' % (name, new['cn'][0])) return if new_pkgname == old.get('univentionOwnedByPackage', [None])[0]: old_version = old.get('univentionOwnedByPackageVersion', ['0'])[0] rc = apt.apt_pkg.version_compare(new_version, old_version) if not rc > -1: ud.debug(ud.LISTENER, ud.WARN, '%s: New version is lower than version of old object (%s), skipping update.' % (name, old_version)) return # ok, basic checks passed, handle the data try: new_object_data = bz2.decompress(new.get('%sData' % objectclass)[0]) except TypeError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error uncompressing data of object %s.' % (name, dn)) return new_relative_filename = new.get('%sFilename' % objectclass)[0] listener.setuid(0) try: if old_relative_filename and old_relative_filename != new_relative_filename: remove_python_file(objectclass, target_subdir, old_relative_filename) if not install_python_file(objectclass, target_subdir, new_relative_filename, new_object_data): return install_messagecatalog(dn, new, objectclass) if objectclass == 'univentionUDMModule': install_umcregistration(dn, new) install_umcicons(dn, new) finally: listener.unsetuid() elif old: # ok, basic checks passed, handle the change listener.setuid(0) try: remove_python_file(objectclass, target_subdir, old_relative_filename) remove_messagecatalog(dn, old, objectclass) if objectclass == 'univentionUDMModule': remove_umcicons(dn, old) remove_umcregistration(dn, old) finally: listener.unsetuid() # Kill running univention-cli-server and mark new extension object active listener.setuid(0) try: if new: if not listener.configRegistry.get('server/role') == 'domaincontroller_master': # Only set active flag on Master return try: lo, ldap_position = udm_uldap.getAdminConnection() udm_modules.update() udm_module = udm_modules.get(udm_module_name) udm_modules.init(lo, ldap_position, udm_module) try: udm_object = udm_module.object(None, lo, ldap_position, dn) udm_object.open() udm_object['active'] = True udm_object.modify() except udm_errors.ldapError as e: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error modifying %s: %s.' % (name, dn, e)) except udm_errors.noObject as e: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error modifying %s: %s.' % (name, dn, e)) except udm_errors.ldapError as e: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error accessing UDM: %s' % (name, e)) finally: listener.unsetuid()
def handler(self, dn, new, old, name=None): """Handle LDAP schema extensions on Master and Backup""" if not listener.configRegistry.get('server/role') in ('domaincontroller_master', 'domaincontroller_backup'): return if new: new_version = new.get('univentionOwnedByPackageVersion', [None])[0] if not new_version: return new_pkgname = new.get('univentionOwnedByPackage', [None])[0] if not new_pkgname: return if old: # check for trivial changes diff_keys = [key for key in new.keys() if new.get(key) != old.get(key) and key not in ('entryCSN', 'modifyTimestamp', 'modifiersName')] if diff_keys == ['univentionLDAPSchemaActive'] and new.get('univentionLDAPSchemaActive') == ['TRUE']: ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: activation status changed.' % (name, new['cn'][0])) return elif diff_keys == ['univentionAppIdentifier']: ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: App identifier changed.' % (name, new['cn'][0])) return ud.debug(ud.LISTENER, ud.INFO, '%s: extension %s: changed attributes: %s' % (name, new['cn'][0], diff_keys)) if new_pkgname == old.get('univentionOwnedByPackage', [None])[0]: old_version = old.get('univentionOwnedByPackageVersion', ['0'])[0] rc = apt.apt_pkg.version_compare(new_version, old_version) if not rc > -1: ud.debug(ud.LISTENER, ud.WARN, '%s: New version is lower than version of old object (%s), skipping update.' % (name, old_version)) return try: new_object_data = bz2.decompress(new.get('univentionLDAPSchemaData')[0]) except TypeError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error uncompressing data of object %s.' % (name, dn)) return new_filename = os.path.join(self.basedir, new.get('univentionLDAPSchemaFilename')[0]) listener.setuid(0) try: backup_filename = None if old: old_filename = os.path.join(self.basedir, old.get('univentionLDAPSchemaFilename')[0]) if os.path.exists(old_filename): backup_fd, backup_filename = tempfile.mkstemp() ud.debug(ud.LISTENER, ud.INFO, '%s: Moving old file %s to %s.' % (name, old_filename, backup_filename)) try: shutil.move(old_filename, backup_filename) except IOError: ud.debug(ud.LISTENER, ud.WARN, '%s: Error renaming old file %s, removing it.' % (name, old_filename)) os.unlink(old_filename) # no choice backup_filename = None os.close(backup_fd) if not os.path.isdir(self.basedir): if os.path.exists(self.basedir): ud.debug(ud.LISTENER, ud.WARN, '%s: Directory name %s occupied, renaming blocking file.' % (name, self.basedir)) shutil.move(self.basedir, "%s.bak" % self.basedir) ud.debug(ud.LISTENER, ud.INFO, '%s: Create directory %s.' % (name, self.basedir)) os.makedirs(self.basedir, 0o755) # Create new extension file try: ud.debug(ud.LISTENER, ud.INFO, '%s: Writing new extension file %s.' % (name, new_filename)) with open(new_filename, 'w') as f: f.write(new_object_data) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error writing file %s.' % (name, new_filename)) return ucr = ConfigRegistry() ucr.load() ucr_handlers = configHandlers() ucr_handlers.load() ucr_handlers.update() ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) # validate # Slapschema doesn't fail on schema errors, errors are printed to stdout (Bug #45571) p = subprocess.Popen(['/usr/sbin/slapschema', ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) stdout, stderr = p.communicate() if p.returncode != 0 or stdout: ud.debug(ud.LISTENER, ud.ERROR, '%s: validation failed:\n%s.' % (name, stdout)) # Revert changes ud.debug(ud.LISTENER, ud.ERROR, '%s: Removing new file %s.' % (name, new_filename)) os.unlink(new_filename) if backup_filename: ud.debug(ud.LISTENER, ud.ERROR, '%s: Restoring previous file %s.' % (name, old_filename)) try: shutil.move(backup_filename, old_filename) os.close(backup_fd) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error reverting to old file %s.' % (name, old_filename)) # Commit and exit ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) return ud.debug(ud.LISTENER, ud.INFO, '%s: validation successful.' % (name,)) # cleanup backup if backup_filename: ud.debug(ud.LISTENER, ud.INFO, '%s: Removing backup of old file %s.' % (name, backup_filename)) os.unlink(backup_filename) os.close(backup_fd) self._todo_list.append(dn) self._do_reload = True finally: listener.unsetuid() elif old: old_filename = os.path.join(self.basedir, old.get('univentionLDAPSchemaFilename')[0]) if os.path.exists(old_filename): listener.setuid(0) try: backup_fd, backup_filename = tempfile.mkstemp() ud.debug(ud.LISTENER, ud.INFO, '%s: Moving old file %s to %s.' % (name, old_filename, backup_filename)) try: shutil.move(old_filename, backup_filename) except IOError: ud.debug(ud.LISTENER, ud.WARN, '%s: Error renaming old file %s, leaving it untouched.' % (name, old_filename)) os.close(backup_fd) return ucr = ConfigRegistry() ucr.load() ucr_handlers = configHandlers() ucr_handlers.load() ucr_handlers.update() ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) # Slapschema doesn't fail on schema errors, errors are printed to stdout (Bug #45571) p = subprocess.Popen(['/usr/sbin/slapschema', ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) stdout, stderr = p.communicate() if p.returncode != 0 or stdout: ud.debug(ud.LISTENER, ud.WARN, '%s: validation fails without %s:\n%s.' % (name, old_filename, stdout)) ud.debug(ud.LISTENER, ud.WARN, '%s: Restoring %s.' % (name, old_filename)) # Revert changes try: with open(backup_filename, 'r') as original: file_data = original.read() with open(old_filename, 'w') as target_file: target_file.write("### %s: Leftover of removed settings/ldapschema\n" % (datetime.datetime.now(), ) + file_data) os.unlink(backup_filename) os.close(backup_fd) except IOError: ud.debug(ud.LISTENER, ud.ERROR, '%s: Error reverting removal of %s.' % (name, old_filename)) # Commit and exit ucr_handlers.commit(ucr, ['/etc/ldap/slapd.conf']) return ud.debug(ud.LISTENER, ud.INFO, '%s: validation successful, removing backup of old file %s.' % (name, backup_filename)) os.unlink(backup_filename) os.close(backup_fd) self._todo_list.append(dn) self._do_reload = True finally: listener.unsetuid() return
def layout(module_name, object=None): """return layout of properties""" module = get(module_name) defining_layout = None if object: ud.debug(ud.ADMIN, ud.ALL, 'modules.py layout:: got an definied object') if object and hasattr(object, 'layout'): # for dynamic modules like users/self ud.debug(ud.ADMIN, ud.ALL, 'modules.py layout:: layout is defined by the object') defining_layout = object.layout elif hasattr(module, 'layout'): defining_layout = module.layout ud.debug(ud.ADMIN, ud.ALL, 'modules.py layout:: layout is defined by the module') if defining_layout: if object and hasattr(object, 'options'): layout = [] for tab in defining_layout: empty = True fields = [] for line in tab.layout: nline = [] for row in line: single = False nrow = [] if isinstance(row, basestring): single = True row = [row] for field in row: prop = module.property_descriptions[field] nrow.append(field) if not prop.options or [ opt for opt in prop.options if opt in object.options ]: if not prop.license or [ license for license in prop.license if license in object.lo.licensetypes ]: empty = False if nrow: if single: nrow = nrow[0] nline.append(nrow) if nline: fields.append(nline) if fields and not empty: ntab = copy.deepcopy(tab) ntab.layout = fields layout.append(ntab) ud.debug( ud.ADMIN, ud.ALL, 'modules.py layout:: return layout decreased by given options') return layout else: ud.debug(ud.ADMIN, ud.ALL, 'modules.py layout:: return defining_layout.') return defining_layout else: return []
def handler(dn, new, old, command): # type: (str, Optional[Dict[str, List[bytes]]], Optional[Dict[str, List[bytes]]], str) -> None if os.path.exists(FETCHMAIL_OLD_PICKLE): with open(FETCHMAIL_OLD_PICKLE, 'r') as fd: p = pickle.Unpickler(fd) old = p.load() os.unlink(FETCHMAIL_OLD_PICKLE) if command == 'r': with open(FETCHMAIL_OLD_PICKLE, 'w+') as fd: os.chmod(FETCHMAIL_OLD_PICKLE, 0o600) p = pickle.Pickler(fd) old = p.dump(old) p.clear_memo() flist = load_rc(fn_fetchmailrc) if old and not new and not command == 'r': # object has been deleted ==> remove entry from rc file flist = objdelete(flist, old) write_rc(flist, fn_fetchmailrc) elif old and new and details_complete(old) and not details_complete(new): # data is now incomplete ==> remove entry from rc file flist = objdelete(flist, old) write_rc(flist, fn_fetchmailrc) elif new and details_complete(new): # obj has been created or modified passwd = None if old: # old exists ==> object has been modified ==> get old password and remove object entry from rc file passwd = get_pw_from_rc(flist, old['uid'][0].decode('UTF-8')) flist = objdelete(flist, old) if not details_complete(new, incl_password=True): if only_password_reset(old, new): ud.debug(ud.LISTENER, ud.INFO, 'fetchmail: password has been reset - nothing to do') # only password has been reset ==> nothing to do return # new obj does not contain password if passwd: # passwd has been set in old ==> use old password ud.debug(ud.LISTENER, ud.INFO, 'fetchmail: using old password') objappend(flist, new, passwd) write_rc(flist, fn_fetchmailrc) else: ud.debug( ud.LISTENER, ud.ERROR, 'fetchmail: user "%s": no password set in old and new' % new['uid'][0]) else: # new obj contains password ==> use new password objappend(flist, new) write_rc(flist, fn_fetchmailrc) ud.debug(ud.LISTENER, ud.INFO, 'fetchmail: using new password') configRegistry = univention.config_registry.ConfigRegistry() configRegistry.load() listener.setuid(0) try: lo = univention.uldap.getMachineConnection() modlist = [('univentionFetchmailPasswd', new['univentionFetchmailPasswd'][0], b"")] lo.modify(dn, modlist) ud.debug(ud.LISTENER, ud.INFO, 'fetchmail: reset password successfully') except Exception as exc: ud.debug( ud.LISTENER, ud.ERROR, 'fetchmail: cannot reset password in LDAP (%s): %s' % (dn, exc)) finally: listener.unsetuid()
def get(module, co, lo, position, dn='', attr=None, superordinate=None, attributes=None): # type: (univention.admin.modules.UdmModule, univention.admin.uldap.config, univention.admin.uldap.access, univention.admin.uldap.position, str, Dict[str, List[Any]], Any, Any) -> univention.admin.handlers.simpleLdap """ Return object of module while trying to create objects of superordinate modules as well. :param module: |UDM| handler. :param co: |UDM| configuation object. :param lo: |LDAP| connection. :param position: |UDM| position instance. """ # module was deleted if not module: return None if not superordinate: superordinate = get_superordinate(module, co, lo, dn or position.getDn()) if dn: try: obj = univention.admin.modules.lookup(module.module, co, lo, base=dn, superordinate=superordinate, scope='base', unique=True, required=True)[0] obj.position.setDn(position.getDn() if position else dn) return obj except (ldap.NO_SUCH_OBJECT, univention.admin.uexceptions.noObject): if not lo.get(dn): raise univention.admin.uexceptions.noObject(dn) ud.debug( ud.ADMIN, ud.ERROR, 'univention.admin.objects.get(): The object %s is not a %s. Ignoring this error.' % ( dn, module.module, )) return module.object(co, lo, position, dn, superordinate=superordinate, attributes=attributes) # raise univention.admin.uexceptions.wrongObjectType('The object %s is not a %s.' % (dn, module.module,)) return module.object(co, lo, position, dn, superordinate=superordinate, attributes=attributes)
def handler(dn, new, old, command=''): # type: (str, Optional[Dict[str, List[str]]], Optional[Dict[str, List[str]]], str) -> None """ Handle changes to 'dn'. :param dn: Distinguished name. :param new: Current LDAP attribute values. :param old: Previous LDAP attribute values. :param command: LDAp transaction type. """ if configRegistry['server/role'] != 'domaincontroller_master': return setuid(0) try: global _delay if _delay: (old_dn, old) = _delay if 'a' != command or old['entryUUID'] != new['entryUUID']: ud.debug(ud.LISTENER, ud.WARN, 'CERTIFICATE: Non-consecutive move %s -> %s', old_dn, dn) (old_dn, old) = (None, None) _delay = None old_cn = old['cn'][0].decode('UTF-8') if old else None new_cn = new['cn'][0].decode('UTF-8') if new else None if new and not old: # changeType: add create_certificate(new_cn, domain(new)) if wildcard_certificate(new): create_certificate('*.%s' % new_cn, domain(new)) elif old and not new: # changeType: delete if 'r' == command: _delay = (dn, old) else: remove_certificate(old_cn, domainname=domain(old)) remove_certificate('*.%s' % old_cn, domainname=domain(old)) elif old and new: # changeType: modify old_domain = domain(old) new_domain = domain(new) if new_domain != old_domain: remove_certificate(old_cn, old_domain) create_certificate(new_cn, new_domain) remove_certificate('*.%s' % old_cn, old_domain) if wildcard_certificate(new): create_certificate('*.%s' % new_cn, new_domain) else: if wildcard_certificate(new) and not wildcard_certificate(old): create_certificate('*.%s' % new_cn, domain(new)) if not wildcard_certificate(new) and wildcard_certificate(old): remove_certificate('*.%s' % old_cn, domainname=domain(old)) if new: # Reset permissions fqdn = "%s.%s" % (new_cn, domain(new)) certpath = os.path.join(SSLDIR, fqdn) fix_permissions(certpath, dn, new) if wildcard_certificate(new): fqdn = "*.%s.%s" % (new_cn, domain(new)) certpath = os.path.join(SSLDIR, fqdn) fix_permissions(certpath, dn, new) finally: unsetuid()
def init(lo, position, module, template_object=None, force_reload=False): # X-type: (univention.admin.uldap.access, univention.admin.uldap.position, UdmModule, univention.admin.handlers.simpleLdap, bool) -> None """ Initialize |UDM| handler module. :param lo: |LDAP| connection. :param position: |UDM| position instance. :param module: |UDM| handler module. :param template_object: Reference to a instance, from which the default values are used. :param force_reload: With `True` force Python to reload the module from the file system. """ # you better do a reload if init is called a second time # especially because update_extended_attributes # called twice will have side-effects if force_reload: imp.reload(module) # reset property descriptions to defaults if possible if hasattr(module, 'default_property_descriptions'): module.property_descriptions = copy.deepcopy(module.default_property_descriptions) # ud.debug(ud.ADMIN, ud.INFO, 'modules_init: reset default descriptions') # overwrite property descriptions univention.admin.ucr_overwrite_properties(module, lo) # check for properties with the syntax class LDAP_Search for pname, prop in module.property_descriptions.items(): if prop.syntax.name == 'LDAP_Search': prop.syntax._load(lo) if prop.syntax.viewonly: module.mapping.unregister(pname, False) elif univention.admin.syntax.is_syntax(prop.syntax, univention.admin.syntax.complex) and hasattr(prop.syntax, 'subsyntaxes'): for text, subsyn in prop.syntax.subsyntaxes: if subsyn.name == 'LDAP_Search': subsyn._load(lo) # add new properties update_extended_options(lo, module, position) update_extended_attributes(lo, module, position) # get defaults from template if template_object: ud.debug(ud.ADMIN, ud.INFO, 'modules_init: got template object %s' % template_object.dn) template_object.open() # add template ext. attr. defaults if hasattr(template_object, 'property_descriptions'): for property_name, property in template_object.property_descriptions.items(): if not (property_name == "name" or property_name == "description"): default = property.base_default if default and property_name in module.property_descriptions: if property.multivalue: if module.property_descriptions[property_name].multivalue: module.property_descriptions[property_name].base_default = [] for i in range(0, len(default)): module.property_descriptions[property_name].base_default.append(default[i]) else: module.property_descriptions[property_name].base_default = default ud.debug(ud.ADMIN, ud.INFO, "modules.init: added template default (%s) to property %s" % (property.base_default, property_name)) # add template defaults for key in template_object.keys(): if not (key == "name" or key == "description"): # these keys are part of the template itself if key == '_options': if template_object[key] != [''] and template_object[key] != []: for option in module.options.keys(): module.options[option].default = option in template_object[key] else: for option in module.options.keys(): module.options[option].default = True else: if template_object.descriptions[key].multivalue: if module.property_descriptions[key].multivalue: module.property_descriptions[key].base_default = [] for i in range(0, len(template_object[key])): module.property_descriptions[key].base_default.append(template_object[key][i]) else: ud.debug(ud.ADMIN, ud.INFO, 'modules.init: template and object values not both multivalue !!') else: module.property_descriptions[key].base_default = template_object[key] module.property_descriptions[key].templates.append(template_object) ud.debug(ud.ADMIN, ud.INFO, 'modules_init: module.property_description after template: %s' % module.property_descriptions) else: ud.debug(ud.ADMIN, ud.INFO, 'modules_init: got no template') # re-build layout if there any overwrites defined univention.admin.ucr_overwrite_module_layout(module) # some choices depend on extended_options/attributes univention.admin.syntax.update_choices() module.initialized = 1
def _modify_object_from_old_and_new(l, dn, old, new): ml = modlist(old, new) if ml: ud.debug(ud.LISTENER, ud.ALL, 'replication: modify: %s' % dn) l.modify_s(dn, ml)
def open(self): univention.admin.handlers.simpleLdap.open(self) self.updateLastUsedValue = True try: caching_timeout = int( configRegistry.get( 'directory/manager/web/modules/groups/group/caching/uniqueMember/timeout', '300')) self.cache_uniqueMember.set_timeout(caching_timeout) except: pass if 'samba' in self.options: sid = self.oldattr.get('sambaSID', [''])[0] pos = sid.rfind('-') self.info['sambaRID'] = sid[pos + 1:] if self.exists(): self['memberOf'] = self.lo.searchDn(filter=filter_format( '(&(objectClass=posixGroup)(uniqueMember=%s))', [self.dn])) time_start = time.time() self['users'] = [] self['hosts'] = [] self['nestedGroup'] = [] for i in self.oldattr.get('uniqueMember', []): if cache_uniqueMember.is_valid(i): membertype = cache_uniqueMember.get(i).get('type') if membertype == 'user': self['users'].append(i) elif membertype == 'group': self['nestedGroup'].append(i) elif membertype == 'host': self['hosts'].append(i) elif i.startswith('uid='): self['users'].append(i) cache_uniqueMember.set(i, {'type': 'user'}) else: result = self.lo.getAttr(i, 'objectClass') if result: if 'univentionGroup' in result: self['nestedGroup'].append(i) cache_uniqueMember.set(i, {'type': 'group'}) elif 'univentionHost' in result: self['hosts'].append(i) cache_uniqueMember.set(i, {'type': 'host'}) else: self['users'].append(i) else: # removing following line breaks deletion of computers from groups self['users'].append(i) time_end = time.time() ud.debug( ud.ADMIN, ud.INFO, 'groups/group: open(): member check duration: %1.2fs' % (time_end - time_start)) self['allowedEmailUsers'] = self.oldattr.get( 'univentionAllowedEmailUsers', []) self['allowedEmailGroups'] = self.oldattr.get( 'univentionAllowedEmailGroups', []) self.save()
def update_extended_attributes(lo, module, position): # X-type: (univention.admin.uldap.access, UdmModule, univention.admin.uldap.position) -> None """ Load extended attribute from |LDAP| and modify |UDM| handler. """ # add list of tabnames created by extended attributes if not hasattr(module, 'extended_attribute_tabnames'): module.extended_attribute_tabnames = [] # append UDM extended attributes properties4tabs = {} # type: Dict[str, List[EA_Layout]] overwriteTabList = [] # type: List[str] module.extended_udm_attributes = [] # type: List[univention.admin.extended_attribute] module_filter = filter_format('(univentionUDMPropertyModule=%s)', [name(module)]) if name(module) == 'settings/usertemplate': module_filter = '(|(univentionUDMPropertyModule=users/user)%s)' % (module_filter,) for dn, attrs in lo.search(base=position.getDomainConfigBase(), filter='(&(objectClass=univentionUDMProperty)%s(univentionUDMPropertyVersion=2))' % (module_filter,)): # get CLI name pname = attrs['univentionUDMPropertyCLIName'][0] object_class = attrs.get('univentionUDMPropertyObjectClass', [])[0] if name(module) == 'settings/usertemplate' and object_class == 'univentionMail' and 'settings/usertemplate' not in attrs.get('univentionUDMPropertyModule', []): continue # since "mail" is a default option, creating a usertemplate with any mail attribute would raise Object class violation: object class 'univentionMail' requires attribute 'uid' # get syntax propertySyntaxString = attrs.get('univentionUDMPropertySyntax', [''])[0] if propertySyntaxString and hasattr(univention.admin.syntax, propertySyntaxString): propertySyntax = getattr(univention.admin.syntax, propertySyntaxString) else: if lo.search(filter=filter_format(univention.admin.syntax.LDAP_Search.FILTER_PATTERN, [propertySyntaxString])): propertySyntax = univention.admin.syntax.LDAP_Search(propertySyntaxString) else: propertySyntax = univention.admin.syntax.string() # get hooks propertyHookString = attrs.get('univentionUDMPropertyHook', [''])[0] propertyHook = None if propertyHookString and hasattr(univention.admin.hook, propertyHookString): propertyHook = getattr(univention.admin.hook, propertyHookString)() register_ldap_connection = getattr(propertyHook, 'hook_ldap_connection', None) if register_ldap_connection: register_ldap_connection(lo, position) # get default value propertyDefault = attrs.get('univentionUDMPropertyDefault', [None]) # value may change try: mayChange = int(attrs.get('univentionUDMPropertyValueMayChange', ['0'])[0]) except: ud.debug(ud.ADMIN, ud.ERROR, 'modules update_extended_attributes: ERROR: processing univentionUDMPropertyValueMayChange threw exception - assuming mayChange=0') mayChange = 0 # value is editable (only via hooks or direkt module.info[] access) editable = attrs.get('univentionUDMPropertyValueNotEditable', ['0'])[0] not in ['1', 'TRUE'] copyable = attrs.get('univentionUDMPropertyCopyable', ['0'])[0] not in ['1', 'TRUE'] # value is required valueRequired = (attrs.get('univentionUDMPropertyValueRequired', ['0'])[0].upper() in ['1', 'TRUE']) # value not available for searching try: doNotSearch = int(attrs.get('univentionUDMPropertyDoNotSearch', ['0'])[0]) except: ud.debug(ud.ADMIN, ud.ERROR, 'modules update_extended_attributes: ERROR: processing univentionUDMPropertyDoNotSearch threw exception - assuming doNotSearch=0') doNotSearch = 0 # check if CA is multivalue property if attrs.get('univentionUDMPropertyMultivalue', [''])[0] == '1': multivalue = 1 map_method = None unmap_method = None else: multivalue = 0 map_method = univention.admin.mapping.ListToString unmap_method = None if propertySyntaxString == 'boolean': map_method = univention.admin.mapping.BooleanListToString unmap_method = univention.admin.mapping.BooleanUnMap # single value ==> use only first value propertyDefault = propertyDefault[0] # Show this attribute in UDM/UMC? if attrs.get('univentionUDMPropertyLayoutDisable', [''])[0] == '1': layoutDisabled = True else: layoutDisabled = False # get current language lang = locale.getlocale(locale.LC_MESSAGES)[0] ud.debug(ud.ADMIN, ud.INFO, 'modules update_extended_attributes: LANG = %s' % str(lang)) # get descriptions shortdesc = _get_translation(lang, attrs, 'univentionUDMPropertyTranslationShortDescription;entry-%s', 'univentionUDMPropertyShortDescription') longdesc = _get_translation(lang, attrs, 'univentionUDMPropertyTranslationLongDescription;entry-%s', 'univentionUDMPropertyLongDescription') # create property fullWidth = (attrs.get('univentionUDMPropertyLayoutFullWidth', ['0'])[0].upper() in ['1', 'TRUE']) module.property_descriptions[pname] = univention.admin.property( short_description=shortdesc, long_description=longdesc, syntax=propertySyntax, multivalue=multivalue, options=attrs.get('univentionUDMPropertyOptions', []), required=valueRequired, may_change=mayChange, dontsearch=doNotSearch, identifies=False, default=propertyDefault, editable=editable, copyable=copyable, size='Two' if fullWidth else None, ) # add LDAP mapping if attrs['univentionUDMPropertyLdapMapping'][0].lower() != 'objectClass'.lower(): module.mapping.register(pname, attrs['univentionUDMPropertyLdapMapping'][0], unmap_method, map_method) else: module.mapping.register(pname, attrs['univentionUDMPropertyLdapMapping'][0], univention.admin.mapping.nothing, univention.admin.mapping.nothing) if hasattr(module, 'layout'): tabname = _get_translation(lang, attrs, 'univentionUDMPropertyTranslationTabName;entry-%s', 'univentionUDMPropertyLayoutTabName', _('Custom')) overwriteTab = (attrs.get('univentionUDMPropertyLayoutOverwriteTab', ['0'])[0].upper() in ['1', 'TRUE']) # in the first generation of extended attributes of version 2 # this field was a position defining the attribute to # overwrite. now it is the name of the attribute to overwrite overwriteProp = attrs.get('univentionUDMPropertyLayoutOverwritePosition', [''])[0] if overwriteProp == '0': overwriteProp = None deleteObjectClass = (attrs.get('univentionUDMPropertyDeleteObjectClass', ['0'])[0].upper() in ['1', 'TRUE']) tabAdvanced = (attrs.get('univentionUDMPropertyLayoutTabAdvanced', ['0'])[0].upper() in ['1', 'TRUE']) groupname = _get_translation(lang, attrs, 'univentionUDMPropertyTranslationGroupName;entry-%s', 'univentionUDMPropertyLayoutGroupName') try: groupPosition = int(attrs.get('univentionUDMPropertyLayoutGroupPosition', ['-1'])[0]) except TypeError: groupPosition = 0 ud.debug(ud.ADMIN, ud.INFO, 'update_extended_attributes: extended attribute (LDAP): %s' % str(attrs)) # only one is possible ==> overwriteTab wins if overwriteTab and overwriteProp: overwriteProp = None # add tab name to list if missing if tabname not in properties4tabs and not layoutDisabled: properties4tabs[tabname] = [] ud.debug(ud.ADMIN, ud.INFO, 'modules update_extended_attributes: custom fields init for tab %s' % tabname) # remember tab for purging if required if overwriteTab and tabname not in overwriteTabList and not layoutDisabled: overwriteTabList.append(tabname) if not layoutDisabled: # get position on tab # -1 == append on top priority = attrs.get('univentionUDMPropertyLayoutPosition', ['-1'])[0] try: priority = int(priority) if priority < 1: priority = -1 except ValueError: ud.debug(ud.ADMIN, ud.WARN, 'modules update_extended_attributes: custom field for tab %s: failed to convert tabNumber to int' % tabname) priority = -1 if priority == -1 and properties4tabs[tabname]: priority = max([-1, min((ea_layout.position for ea_layout in properties4tabs[tabname])) - 1]) properties4tabs[tabname].append(EA_Layout( name=pname, tabName=tabname, position=priority, advanced=tabAdvanced, overwrite=overwriteProp, fullWidth=fullWidth, groupName=groupname, groupPosition=groupPosition, is_app_tab=any(option in [key for (key, value) in getattr(module, 'options', {}).items() if value.is_app_option] for option in attrs.get('univentionUDMPropertyOptions', [])), )) else: for tab in getattr(module, 'layout', []): tab.remove(pname) module.extended_udm_attributes.append(univention.admin.extended_attribute( name=pname, objClass=object_class, ldapMapping=attrs['univentionUDMPropertyLdapMapping'][0], deleteObjClass=deleteObjectClass, syntax=propertySyntaxString, hook=propertyHook )) # overwrite tabs that have been added by UDM extended attributes for tab in module.extended_attribute_tabnames: if tab not in overwriteTabList: overwriteTabList.append(tab) if properties4tabs: # remove layout of tabs that have been marked for replacement for tab in module.layout: if tab.label in overwriteTabList: tab.layout = [] for tabname, priofields in properties4tabs.items(): priofields = sorted(priofields) currentTab = None # get existing fields if tab has not been overwritten for tab in module.layout: if tab.label == tabname: # found tab in layout currentTab = tab # tab found ==> leave loop break else: # tab not found in current layout, so add it currentTab = Tab(tabname, tabname, advanced=True) module.layout.append(currentTab) # remember tabs that have been added by UDM extended attributes if tabname not in module.extended_attribute_tabnames: module.extended_attribute_tabnames.append(tabname) currentTab.is_app_tab = any(x.is_app_tab for x in priofields) # check if tab is empty ==> overwritePosition is impossible freshTab = len(currentTab.layout) == 0 for ea_layout in priofields: if currentTab.advanced and not ea_layout.advanced: currentTab.advanced = False # if groupName is set check if it exists, otherwise create it if ea_layout.groupName: for item in currentTab.layout: if isinstance(item, ILayoutElement) and item.label == ea_layout.groupName: break else: # group does not exist grp = Group(ea_layout.groupName) if ea_layout.groupPosition > 0: currentTab.layout.insert(ea_layout.groupPosition - 1, grp) else: currentTab.layout.append(grp) # - existing property shall be overwritten AND # - tab is not new and has not been cleaned before AND # - position >= 1 (top left position is defined as 1) AND # - old property with given position exists if currentTab.exists(ea_layout.name): continue elif ea_layout.overwrite and not freshTab: # we want to overwrite an existing property # in the global fields ... if not ea_layout.groupName: replaced, layout = currentTab.replace(ea_layout.overwrite, ea_layout.name, recursive=True) if not replaced: # the property was not found so we'll append it currentTab.layout.append(ea_layout.name) else: for item in currentTab.layout: if isinstance(item, ILayoutElement) and item.label == ea_layout.groupName: replaced, layout = item.replace(ea_layout.overwrite, ea_layout.name) if not replaced: # the property was not found so we'll append it item.layout.append(ea_layout.name) else: if not ea_layout.groupName: currentTab.insert(ea_layout.position, ea_layout.name) else: for item in currentTab.layout: if isinstance(item, ILayoutElement) and item.label == ea_layout.groupName: item.insert(ea_layout.position, ea_layout.name) break # check for properties with the syntax class LDAP_Search for pname, prop in module.property_descriptions.items(): if prop.syntax.name == 'LDAP_Search': prop.syntax._load(lo) if prop.syntax.viewonly: module.mapping.unregister(pname, False) elif univention.admin.syntax.is_syntax(prop.syntax, univention.admin.syntax.complex) and hasattr(prop.syntax, 'subsyntaxes'): for text, subsyn in prop.syntax.subsyntaxes: if subsyn.name == 'LDAP_Search': subsyn._load(lo)
def handler(dn, new, old): # type: (str, dict, dict) -> None change_affects_this_host = False need_to_reload_samba = False need_to_reload_cups = False printer_is_group = False samba_force_printername = listener.configRegistry.is_true( 'samba/force_printername', True) global reload_samba_in_postrun reload_samba_in_postrun = True changes = [] if old: if filter_match(old): if old.get('univentionPrinterSambaName'): old_sharename = old['univentionPrinterSambaName'][0].decode( 'UTF-8') else: old_sharename = old['cn'][0].decode('UTF-8') old_filename = _join_basedir_filename( '/etc/samba/printers.conf.d/', old_sharename) samba_force_printername = testparm_is_true(old_filename, old_sharename, 'force printername') if b'univentionPrinterGroup' in old.get('objectClass', ()): printer_is_group = True if new: if b'univentionPrinterGroup' in new.get('objectClass', ()): printer_is_group = True modified_uri = '' for n in new.keys(): if new.get(n, []) != old.get(n, []): changes.append(n) if n == 'univentionPrinterURI': modified_uri = new['univentionPrinterURI'][0].decode('ASCII') for o in old.keys(): if o not in changes and new.get(o, []) != old.get(o, []): changes.append(o) if o == 'univentionPrinterURI' and not modified_uri: modified_uri = old['univentionPrinterURI'][0].decode('ASCII') options = { 'univentionPrinterURI': '-v', 'univentionPrinterLocation': '-L', 'description': '-D', 'univentionPrinterModel': '-m' } if (filter_match(new) or filter_match(old)): change_affects_this_host = True reload_samba_in_postrun = True # default, if it isn't done earlier if filter_match(old): if 'cn' in changes or not filter_match(new): # Deletions done via UCR-Variables printer_name = old['cn'][0].decode('UTF-8') listener.configRegistry.load() printer_list = listener.configRegistry.get( 'cups/restrictedprinters', '').split() printer_is_restricted = printer_name in printer_list if printer_is_restricted and not listener.configRegistry.is_false( 'cups/automaticrestrict', False): printer_list.remove(printer_name) keyval = 'cups/restrictedprinters=%s' % ' '.join(printer_list) listener.setuid(0) try: univention.config_registry.handler_set([keyval]) finally: listener.unsetuid() # Deletions done via lpadmin lpadmin(['-x', old['cn'][0].decode('UTF-8')]) need_to_reload_samba = True # Deletions done via editing the Samba config if old.get('univentionPrinterSambaName'): filename = _join_basedir_filename( '/etc/samba/printers.conf.d/', old['univentionPrinterSambaName'][0].decode('UTF-8')) listener.setuid(0) try: if os.path.exists(filename): os.unlink(filename) finally: listener.unsetuid() filename = _join_basedir_filename('/etc/samba/printers.conf.d/', old['cn'][0].decode('UTF-8')) listener.setuid(0) try: if os.path.exists(filename): os.unlink(filename) finally: listener.unsetuid() if filter_match(new): # Modifications done via UCR-Variables printer_name = new['cn'][0].decode('UTF-8') listener.configRegistry.load() printer_list = listener.configRegistry.get('cups/restrictedprinters', '').split() printer_is_restricted = printer_name in printer_list restrict_printer = (new.get( 'univentionPrinterACLUsers', []) or new.get( 'univentionPrinterACLGroups', [])) and new['univentionPrinterACLtype'][0] != b'allow all' update_restricted_printers = False if printer_is_restricted and not restrict_printer: printer_list.remove(printer_name) update_restricted_printers = True elif not printer_is_restricted and restrict_printer: printer_list.append(printer_name) update_restricted_printers = True if update_restricted_printers and not listener.configRegistry.is_false( 'cups/automaticrestrict', False): keyval = 'cups/restrictedprinters=%s' % ' '.join(printer_list) listener.setuid(0) try: univention.config_registry.handler_set([keyval]) finally: listener.unsetuid() need_to_reload_cups = True # Modifications done via lpadmin args = [] # lpadmin args # description = new.get('univentionPrinterSambaName', [b''])[0].decode('UTF-8') if new.get('univentionPrinterACLtype'): if new['univentionPrinterACLtype'][0] == b'allow all': args += ['-u', 'allow:all', '-o', 'auth-info-required=none'] elif new.get('univentionPrinterACLUsers') or new.get( 'univentionPrinterACLGroups'): args.append('-u') argument = "%s:" % new['univentionPrinterACLtype'][0].decode( 'ASCII') for userDn in new.get('univentionPrinterACLUsers', ()): argument += '%s,' % (_rdn(userDn.decode('UTF-8')), ) for groupDn in new.get('univentionPrinterACLGroups', ()): argument += '@%s,' % (_rdn(groupDn.decode('UTF-8')), ) args.append(argument.rstrip(',')) else: args += ['-o', 'auth-info-required=none'] # Add/Modify Printergroup if printer_is_group: #add = [] #if old: # Diff old <==> new # rem = old['univentionPrinterGroupMember'] # for el in new['univentionPrinterGroupMember']: # if el not in old['univentionPrinterGroupMember']: # add.append(el) # else: # rem.remove(el) #else: # Create new group # add = new['univentionPrinterGroupMember'] lpadmin(args) # Add/Modify Printer else: args.append('-p') args.append(new['cn'][0].decode('UTF-8')) for a in changes: if a == 'univentionPrinterURI': continue if a == 'univentionPrinterSpoolHost' and 'univentionPrinterModel' not in changes: model = new.get('univentionPrinterModel', EMPTY)[0].decode('ASCII') if model in ['None', 'smb']: model = 'raw' args += [options['univentionPrinterModel'], model] if a not in options: continue if a == 'univentionPrinterModel': model = new.get(a, EMPTY)[0].decode('ASCII') if model in ['None', 'smb']: model = 'raw' args += [options[a], model] else: args += [options[a], new.get(a, EMPTY)[0].decode('UTF-8')] args += [options['univentionPrinterURI'], modified_uri] args += ['-E'] # insert printer lpadmin(args) need_to_reload_samba = True # Modifications done via editing Samba config printername = new['cn'][0].decode('UTF-8') cups_printername = new['cn'][0].decode('UTF-8') if new.get('univentionPrinterSambaName'): printername = new['univentionPrinterSambaName'][0].decode( 'UTF-8') filename = _join_basedir_filename('/etc/samba/printers.conf.d/', printername) if not _validate_smb_share_name(printername): ud.debug( ud.LISTENER, ud.ERROR, "Invalid printer share name: %r. Ignoring!" % (printername, )) return def _quote(arg): if ' ' in arg: arg = '"%s"' % (arg.replace('"', '\\"'), ) return arg.replace('\n', '') user_and_groups = [ _quote(_rdn(_dn.decode('UTF-8'))) for _dn in new.get('univentionPrinterACLUsers', ()) ] user_and_groups.extend( _quote("@" + _rdn(_dn.decode('UTF-8'))) for _dn in new.get('univentionPrinterACLGroups', ())) perm = ' '.join(user_and_groups) # samba permissions listener.setuid(0) try: with open(filename, 'w') as fp: fp.write('[%s]\n' % (printername, )) fp.write('printer name = %s\n' % (cups_printername, )) fp.write('path = /tmp\n') fp.write('guest ok = yes\n') fp.write('printable = yes\n') if samba_force_printername: fp.write('force printername = yes\n') if perm: if new['univentionPrinterACLtype'][0] == b'allow': fp.write('valid users = %s\n' % perm) if new['univentionPrinterACLtype'][0] == b'deny': fp.write('invalid users = %s\n' % perm) os.chmod(filename, 0o755) os.chown(filename, 0, 0) finally: listener.unsetuid() if change_affects_this_host: listener.setuid(0) try: with open('/etc/samba/printers.conf.temp', 'w') as fp: for f in os.listdir('/etc/samba/printers.conf.d'): fp.write('include = %s\n' % os.path.join('/etc/samba/printers.conf.d', f)) os.rename('/etc/samba/printers.conf.temp', '/etc/samba/printers.conf') finally: listener.unsetuid() reload_printer_restrictions() if need_to_reload_cups: reload_cups_daemon() if need_to_reload_samba: reload_smbd() time.sleep(3) reload_smbd()
object['lockedTime'] = lock_timestamp object.modify() finally: object.descriptions['locked'].editable, object.descriptions[ 'locked'].may_change, object.descriptions[ 'lockedTime'].editable, object.descriptions[ 'lockedTime'].may_change = states if __name__ == '__main__': """Usage: python -m univention.lib.account lock --dn "$user_dn" --lock-time "$(date --utc '+%Y%m%d%H%M%SZ')" """ parser = argparse.ArgumentParser() subparsers = parser.add_subparsers() subparser = subparsers.add_parser('lock', help='Locks a user account') subparser.add_argument('--dn', required=True, help='The DN of the user account to be locked.') subparser.add_argument('--lock-time', required=True, help='The time when the user account was locked.') args = parser.parse_args() initialize_debug() ud1.debug( ud1.ADMIN, ud1.PROCESS, "univention.lib.account.lock was called for %s (%s)" % (args.dn, args.lock_time)) lock(args.dn, args.lock_time)
def write_configuration_file(dn, new, filename): if new.get('serviceProviderMetadata') and new['serviceProviderMetadata'][0]: metadata = new['serviceProviderMetadata'][0] try: root = xml.etree.ElementTree.fromstring(metadata) entityid = root.get('entityID') except xml.etree.ElementTree.ParseError as exc: ud.debug(ud.LISTENER, ud.ERROR, 'Parsing metadata failed: %s' % (exc,)) return False else: metadata = None entityid = new.get('SAMLServiceProviderIdentifier')[0] if new.get('rawsimplesamlSPconfig') and new['rawsimplesamlSPconfig'][0]: rawsimplesamlSPconfig = new['rawsimplesamlSPconfig'][0] else: rawsimplesamlSPconfig = None fd = open(filename, 'w') if rawsimplesamlSPconfig: fd.write(rawsimplesamlSPconfig) else: fd.write("<?php\n") fd.flush() if metadata: with NamedTemporaryFile() as temp: temp.write(raw_metadata_generator) temp.flush() process = Popen(['/usr/bin/php', temp.name, entityid], stdout=fd, stderr=PIPE, stdin=PIPE) stdout, stderr = process.communicate(metadata) if process.returncode != 0: ud.debug(ud.LISTENER, ud.ERROR, 'Failed to create %s: %s' % (filename, stderr,)) fd.write("$further = array(\n") else: fd.write('$metadata[%s] = array(\n' % php_string(entityid)) fd.write(" 'AssertionConsumerService' => %s,\n" % php_array(new.get('AssertionConsumerService'))) if new.get('singleLogoutService'): fd.write(" 'SingleLogoutService' => %s,\n" % php_array(new.get('singleLogoutService'))) if new.get('NameIDFormat'): fd.write(" 'NameIDFormat' => %s,\n" % php_string(new.get('NameIDFormat')[0])) if new.get('simplesamlNameIDAttribute'): fd.write(" 'simplesaml.nameidattribute' => %s,\n" % php_string(new.get('simplesamlNameIDAttribute')[0])) if new.get('simplesamlAttributes'): fd.write(" 'simplesaml.attributes' => %s,\n" % php_bool(new.get('simplesamlAttributes')[0])) if new.get('simplesamlAttributes') and new.get('simplesamlAttributes')[0] == "TRUE": simplesamlLDAPattributes = list(new.get('simplesamlLDAPattributes', [])) if new.get('simplesamlNameIDAttribute') and new.get('simplesamlNameIDAttribute')[0] not in simplesamlLDAPattributes: simplesamlLDAPattributes.append(new.get('simplesamlNameIDAttribute')[0]) fd.write(" 'attributes' => %s,\n" % php_array(simplesamlLDAPattributes)) if new.get('attributesNameFormat'): fd.write(" 'attributes.NameFormat' => %s,\n" % php_string(new.get('attributesNameFormat')[0])) if new.get('serviceproviderdescription'): fd.write(" 'description' => %s,\n" % php_string(new.get('serviceproviderdescription')[0])) if new.get('serviceProviderOrganizationName'): fd.write(" 'OrganizationName' => %s,\n" % php_string(new.get('serviceProviderOrganizationName')[0])) if new.get('privacypolicyURL'): fd.write(" 'privacypolicy' => %s,\n" % php_string(new.get('privacypolicyURL')[0])) fd.write(" 'authproc' => array(\n") if not metadata: # TODO: make it configurable # make sure that only users that are enabled to use this service provider are allowed fd.write(" 10 => array(\n") fd.write(" 'class' => 'authorize:Authorize',\n") fd.write(" 'regex' => FALSE,\n") fd.write(" 'enabledServiceProviderIdentifier' => %s,\n" % php_array([dn])) fd.write(" )\n") else: fd.write(" 100 => array('class' => 'core:AttributeMap', 'name2oid'),\n") fd.write(" ),\n") fd.write(");\n") if metadata: fd.write("$metadata[%s] = array_merge($metadata[%s], $further);" % (php_string(entityid), php_string(entityid))) fd.close() process = Popen(['/usr/bin/php', '-lf', filename], stderr=PIPE, stdout=PIPE) stdout, stderr = process.communicate() if process.returncode: ud.debug(ud.LISTENER, ud.ERROR, 'broken PHP syntax(%d) in %s: %s%s' % (process.returncode, filename, stderr, stdout)) try: with open(filename) as fd: ud.debug(ud.LISTENER, ud.ERROR, 'repr(%r)' % (fd.read(),)) os.unlink(filename) except IOError: pass
def remove_pymodules_links(objectclass, target_subdir, target_filename): """Remove pymodules parts: pyc, pyo, and file itself. Clean up directories in target_filename if empty.""" # input validation relative_filename = os.path.join(target_subdir, target_filename) if not relative_filename: ud.debug(ud.LISTENER, ud.ERROR, '%s: No python file to remove.' % (name,)) return False if relative_filename.startswith('/'): ud.debug(ud.LISTENER, ud.ERROR, '%s: Module path must not be absolute: %s.' % (name, relative_filename)) return False # trivial checks passed, go for it target_filename_parts = os.path.splitext(target_filename) if len(target_filename_parts) > 1 and target_filename_parts[-1] == ".py": pysupport_filename = ".".join(target_filename_parts[:-1]) else: pysupport_filename = target_filename pysupport_filename = '%s_%s.public' % (objectclass, pysupport_filename.replace('/', '_')) pysupport_filename = os.path.join(PYSUPPORT_DIR, pysupport_filename) if os.path.isfile(pysupport_filename): try: os.unlink(pysupport_filename) ud.debug(ud.LISTENER, ud.INFO, '%s: %s removed.' % (name, pysupport_filename)) except OSError as e: ud.debug(ud.LISTENER, ud.ERROR, '%s: Removal of %s failed: %s.' % (name, pysupport_filename, e)) try: p = subprocess.Popen(['/usr/sbin/update-python-modules', '-p'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = p.communicate() except OSError as e: ud.debug(ud.LISTENER, ud.ERROR, '%s: update-python-modules -p failed: %s.' % (name, e)) if p.returncode == 0: ud.debug(ud.LISTENER, ud.INFO, '%s: symlinks to %s removed.' % (name, relative_filename)) return True ud.debug(ud.LISTENER, ud.ERROR, '%s: update-python-modules -p failed: %s.' % (name, stderr)) return False
def remove_pyshared_file(target_subdir, target_filename): """Remove pyshared parts of public python module file""" # input validation relative_filename = os.path.join(target_subdir, target_filename) if not relative_filename: ud.debug(ud.LISTENER, ud.ERROR, '%s: No python file to remove.' % (name,)) return False if relative_filename.startswith('/'): ud.debug(ud.LISTENER, ud.ERROR, '%s: Module path must not be absolute: %s.' % (name, relative_filename)) return False # trivial checks passed, go for it filename = os.path.join(PYSHARED_DIR, relative_filename) if os.path.isfile(filename): # Only remove the file if it was not shipped as part of a debian package. p = subprocess.Popen(['dpkg', '-S', filename], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) p.wait() if p.returncode == 0: # ok, we should not remove this file # but at least check if the __init__.py file should be cleaned up. cleanup_python_moduledir would not do it since $filename is sill there. target_path = os.path.dirname(filename) skipfiles = (os.path.basename(filename), '__init__.py') for entry in os.listdir(target_path): if entry not in skipfiles: return python_init_filename = os.path.join(target_path, '__init__.py') if os.path.exists(python_init_filename): if os.path.getsize(python_init_filename) != 0: return # Only remove the file if it was not shipped as part of a debian package. p = subprocess.Popen(['dpkg', '-S', python_init_filename], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) p.wait() if p.returncode != 0: try: os.unlink(python_init_filename) ud.debug(ud.LISTENER, ud.INFO, '%s: %s removed.' % (name, python_init_filename)) except OSError as e: ud.debug(ud.LISTENER, ud.ERROR, '%s: Removal of %s failed: %s.' % (name, python_init_filename, e)) # return, nothing more to do in this case return else: try: os.unlink(filename) ud.debug(ud.LISTENER, ud.INFO, '%s: %s removed.' % (name, filename)) except OSError as e: ud.debug(ud.LISTENER, ud.ERROR, '%s: Removal of %s failed: %s.' % (name, filename, e)) try: cleanup_python_moduledir(PYSHARED_DIR, target_subdir, os.path.dirname(target_filename)) except moduleRemovalFailed as e: ud.debug(ud.LISTENER, ud.ERROR, '%s: %s' % (name, e)) return False
def _ldap_modlist(self): # we get a list of modifications to be done (called 'ml' down below) # this lists looks like this: # [('univentionMailHomeServer', [u'ugs-master.hosts.invalid'], u'ugs-master.hosts.invalid'), ('univentionMailUserQuota', u'100', u'101')] # we can modify those entries to conform to the LDAP schema ml = univention.admin.handlers.simpleLdap._ldap_modlist(self) if self.hasChanged( 'mailPrimaryAddress') and self['mailPrimaryAddress']: if not any(x[0] == 'mailPrimaryAddress' for x in self.alloc): value = 'univentioninternalpostuser+shared/%s@%s' % ( self['name'].lower(), self['mailDomain'].lower()) ml.append(('univentionMailSharedFolderDeliveryAddress', self.oldattr.get( 'univentionMailSharedFolderDeliveryAddress', []), [value.encode('UTF-8')])) address = '%s@%s' % (self['name'], self['mailDomain']) if self['mailPrimaryAddress'] != address: try: self.request_lock('mailPrimaryAddress', self['mailPrimaryAddress']) except univention.admin.uexceptions.noLock: raise univention.admin.uexceptions.mailAddressUsed( self['mailPrimaryAddress']) if not self['mailPrimaryAddress']: ml.append( ('univentionMailSharedFolderDeliveryAddress', self.oldattr.get('univentionMailSharedFolderDeliveryAddress', []), [])) rewrite_acl = False new_acls_tmp = [] for attr in ['sharedFolderUserACL', 'sharedFolderGroupACL']: ud.debug(ud.ADMIN, ud.INFO, 'ACLs: %s' % str(self[attr])) if self.hasChanged(attr): rewrite_acl = True # re-use regular expressions from syntax definitions if attr == 'sharedFolderUserACL': _sre = univention.admin.syntax.UserMailAddress.regex else: _sre = univention.admin.syntax.GroupName.regex for acl in self[attr]: if acl == '': continue if _sre.match(acl[0]): new_acls_tmp.append(' '.join(acl)) else: for acl in self[attr]: if acl == '': continue new_acls_tmp.append(' '.join(acl)) if rewrite_acl: for (a, b, c) in ml: if a in ['sharedFolderUserACL', 'sharedFolderGroupACL']: ml.remove((a, b, c)) new_acls_tmp = [x.encode('UTF-8') for x in new_acls_tmp] ml.append( ('univentionMailACL', self.oldattr.get('univentionMailACL', []), new_acls_tmp)) return ml
def initialize(): """Initialize the module once on first start or after clean.""" ud.debug(ud.LISTENER, ud.INFO, 'CERTIFICATE: Initialize')
def emit(self, record): msg = self.format(record) if isinstance(msg, unicode): msg = msg.encode("utf-8") udebug_level = self.LOGGING_TO_UDEBUG[record.levelname] ud.debug(self._udebug_facility, udebug_level, msg)