Example #1
0
	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()
Example #2
0
	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 )
Example #3
0
	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
Example #4
0
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) )
Example #5
0
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()
Example #7
0
 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()
Example #8
0
 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")
Example #9
0
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)
Example #10
0
	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)
Example #11
0
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
Example #12
0
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
Example #13
0
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
Example #14
0
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()
Example #15
0
 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,
     )
Example #16
0
File: bind.py Project: B-Rich/smart
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,))
Example #17
0
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)))
Example #18
0
	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
Example #19
0
File: nic.py Project: B-Rich/smart
	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' )
Example #20
0
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)) )
Example #21
0
File: nic.py Project: B-Rich/smart
	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 )
Example #22
0
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)))
Example #23
0
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()
Example #24
0
File: nic.py Project: B-Rich/smart
	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 )
Example #25
0
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)))
Example #26
0
	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 )
Example #27
0
	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 )
Example #28
0
	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()
Example #29
0
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),)])
Example #30
0
	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()
Example #31
0
	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)
Example #35
0
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:
Example #39
0
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
Example #40
0
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()
Example #41
0
def initialize():
    """Initialize the module once on first start or after clean."""
    ud.debug(ud.LISTENER, ud.INFO, 'plucs: initialized')
Example #42
0
    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()
Example #44
0
	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
Example #45
0
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 []
Example #46
0
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
Example #50
0
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()
Example #54
0
            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
Example #58
0
    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
Example #59
0
def initialize():
    """Initialize the module once on first start or after clean."""
    ud.debug(ud.LISTENER, ud.INFO, 'CERTIFICATE: Initialize')
Example #60
0
 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)