diff -Nur xxxxxx-delete-deactivated.orig/conffiles/etc/cron.d/xxxxxx-delete-deactivated xxxxxx-delete-deactivated/conffiles/etc/cron.d/xxxxxx-delete-deactivated --- xxxxxx-delete-deactivated.orig/conffiles/etc/cron.d/xxxxxx-delete-deactivated 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/conffiles/etc/cron.d/xxxxxx-delete-deactivated 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,3 @@ +@%@UCRWARNING=# @%@ +MAILTO=@%@xxxxxx/delete/deactivated/mailaddress/schedule@%@ +0 3 * * * root /usr/sbin/xxxxxx-delete-deactivated --delete diff -Nur xxxxxx-delete-deactivated.orig/debian/changelog xxxxxx-delete-deactivated/debian/changelog --- xxxxxx-delete-deactivated.orig/debian/changelog 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/changelog 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,26 @@ +xxxxxx-delete-deactivated (1.0.3-1) unstable; urgency=low + + * remove home directory check (Ticket#: 2010090910014184) + + -- Janek Walkenhorst Wed, 14 Dec 2011 15:49:50 +0100 + +xxxxxx-delete-deactivated (1.0.2-1) unstable; urgency=low + + * do not overwrite logfiles (Ticket#: 2010090910014184) + + -- Janek Walkenhorst Wed, 14 Dec 2011 11:05:53 +0100 + +xxxxxx-delete-deactivated (1.0.1-1) unstable; urgency=low + + * update search filter (Ticket#: 2010090910014184) + * add encoding declaration to fix encoding warnings + * only do one LDAP search in xxxxxx-delete-deactivated + * add default values to URCV + + -- Janek Walkenhorst Tue, 13 Dec 2011 14:42:54 +0100 + +xxxxxx-delete-deactivated (1.0.0-2) unstable; urgency=low + + * Initial release. (Ticket#: 2010090910014184) + + -- Janek Walkenhorst Thu, 25 Aug 2011 10:14:30 +0200 diff -Nur xxxxxx-delete-deactivated.orig/debian/compat xxxxxx-delete-deactivated/debian/compat --- xxxxxx-delete-deactivated.orig/debian/compat 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/compat 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1 @@ +7 diff -Nur xxxxxx-delete-deactivated.orig/debian/control xxxxxx-delete-deactivated/debian/control --- xxxxxx-delete-deactivated.orig/debian/control 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/control 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,21 @@ +Source: xxxxxx-delete-deactivated +Section: univention +Priority: optional +Maintainer: Univention GmbH +Build-Depends: debhelper (>> 7.0.50~), univention-config-dev +Standards-Version: 3.5.5 + +Package: xxxxxx-delete-deactivated-master +Architecture: all +Description: Delete deactivated users + This package is to be installed only on the DC master computer. + +Package: xxxxxx-delete-deactivated-home +Architecture: all +Description: Delete home directories of deactivated users + This package is to be installed only on computers where the home directories should be deleted. + +Package: xxxxxx-delete-deactivated-mail +Architecture: all +Description: Delete email directories of deactivated users + This package is to be installed only on computers where the email directories should be deleted. diff -Nur xxxxxx-delete-deactivated.orig/debian/copyright xxxxxx-delete-deactivated/debian/copyright --- xxxxxx-delete-deactivated.orig/debian/copyright 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/copyright 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,27 @@ +Copyright 2011 Univention GmbH + +http://www.univention.de/ + +All rights reserved. + +The source code of the software contained in this package +as well as the source package itself are made available +under the terms of the GNU Affero General Public License version 3 +(GNU AGPL V3) as published by the Free Software Foundation. + +Binary versions of this package provided by Univention to you as +well as other copyrighted, protected or trademarked materials like +Logos, graphics, fonts, specific documentations and configurations, +cryptographic keys etc. are subject to a license agreement between +you and Univention and not subject to the GNU AGPL V3. + +In the case you use the software under the terms of the GNU AGPL V3, +the program is provided in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public +License with the Debian GNU/Linux or Univention distribution in file +/usr/share/common-licenses/AGPL-3; if not, see +. diff -Nur xxxxxx-delete-deactivated.orig/debian/rules xxxxxx-delete-deactivated/debian/rules --- xxxxxx-delete-deactivated.orig/debian/rules 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/rules 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,45 @@ +#!/usr/bin/make -f +# +# xxxxxx-delete-deactivated +# debian/rules file +# +# Copyright 2011 Univention GmbH +# +# http://www.univention.de/ +# +# All rights reserved. +# +# The source code of this program is made available +# under the terms of the GNU Affero General Public License version 3 +# (GNU AGPL V3) as published by the Free Software Foundation. +# +# Binary versions of this program provided by Univention to you as +# well as other copyrighted, protected or trademarked materials like +# Logos, graphics, fonts, specific documentations and configurations, +# cryptographic keys etc. are subject to a license agreement between +# you and Univention and not subject to the GNU AGPL V3. +# +# In the case you use this program under the terms of the GNU AGPL V3, +# the program is provided in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License with the Debian GNU/Linux or Univention distribution in file +# /usr/share/common-licenses/AGPL-3; if not, see +# . + +override_dh_auto_install: + dh_auto_install + univention-install-config-registry + univention-install-config-registry-info + +override_dh_clean: + dh_clean + rm -f debian/xxxxxx-delete-deactivated-master.conffiles + rm -f debian/xxxxxx-delete-deactivated-home.conffiles + rm -f debian/xxxxxx-delete-deactivated-mail.conffiles + +%: + dh $@ diff -Nur xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-home.install xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-home.install --- xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-home.install 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-home.install 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1 @@ +delete-deactivated-home.py usr/lib/univention-directory-listener/system diff -Nur xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-home.postinst xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-home.postinst --- xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-home.postinst 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-home.postinst 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,42 @@ +#!/bin/sh +# +# xxxxxx-delete-deactivated +# -home postinst +# +# Copyright 2011 Univention GmbH +# +# http://www.univention.de/ +# +# All rights reserved. +# +# The source code of this program is made available +# under the terms of the GNU Affero General Public License version 3 +# (GNU AGPL V3) as published by the Free Software Foundation. +# +# Binary versions of this program provided by Univention to you as +# well as other copyrighted, protected or trademarked materials like +# Logos, graphics, fonts, specific documentations and configurations, +# cryptographic keys etc. are subject to a license agreement between +# you and Univention and not subject to the GNU AGPL V3. +# +# In the case you use this program under the terms of the GNU AGPL V3, +# the program is provided in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License with the Debian GNU/Linux or Univention distribution in file +# /usr/share/common-licenses/AGPL-3; if not, see +# . + +#DEBHELPER# + +if [ "$1" = 'configure' ] +then + univention-config-registry set 'xxxxxx/delete/deactivated/home/logfile?/var/log/univention/xxxxxx-delete-deactivated-home.log' \ + 'xxxxxx/delete/deactivated/days?30' + invoke-rc.d univention-directory-listener crestart +fi + +exit 0 diff -Nur xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-home.univention-config-registry-variables xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-home.univention-config-registry-variables --- xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-home.univention-config-registry-variables 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-home.univention-config-registry-variables 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,23 @@ +[xxxxxx/delete/deactivated] +Description[de]=Aktiviert das automatische Löschen von deaktivierten Benutzern +Description[en]=Activates the automatic deletion of deactivated users. +Type=str +Categories=management-udm + +[xxxxxx/delete/deactivated/days] +Description[de]=Nach wie vielen Tagen deaktivierte Benutzer automatisch gelöscht werden. +Description[en]=After how many days deactivated users are automatically deleted. +Type=str +Categories=management-udm + +[xxxxxx/delete/deactivated/home] +Description[de]=Aktiviert das Löschen von Heimatverzeichnissen auf diesem Computer. +Description[en]=Activates the deletion of home directories on this computer. +Type=str +Categories=management-udm + +[xxxxxx/delete/deactivated/home/logfile] +Description[de]=Logdatei in der die gelöschten Heimatverzeichnisse protokolliert werden. +Description[en]=Log file to log deleted home directories in. +Type=str +Categories=management-udm diff -Nur xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-mail.install xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-mail.install --- xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-mail.install 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-mail.install 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1 @@ +delete-deactivated-mail.py usr/lib/univention-directory-listener/system diff -Nur xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-mail.postinst xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-mail.postinst --- xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-mail.postinst 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-mail.postinst 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,42 @@ +#!/bin/sh +# +# xxxxxx-delete-deactivated +# -mail postinst +# +# Copyright 2011 Univention GmbH +# +# http://www.univention.de/ +# +# All rights reserved. +# +# The source code of this program is made available +# under the terms of the GNU Affero General Public License version 3 +# (GNU AGPL V3) as published by the Free Software Foundation. +# +# Binary versions of this program provided by Univention to you as +# well as other copyrighted, protected or trademarked materials like +# Logos, graphics, fonts, specific documentations and configurations, +# cryptographic keys etc. are subject to a license agreement between +# you and Univention and not subject to the GNU AGPL V3. +# +# In the case you use this program under the terms of the GNU AGPL V3, +# the program is provided in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License with the Debian GNU/Linux or Univention distribution in file +# /usr/share/common-licenses/AGPL-3; if not, see +# . + +#DEBHELPER# + +if [ "$1" = 'configure' ] +then + univention-config-registry set 'xxxxxx/delete/deactivated/mail/logfile?/var/log/univention/xxxxxx-delete-deactivated-mail.log' \ + 'xxxxxx/delete/deactivated/days?30' + invoke-rc.d univention-directory-listener crestart +fi + +exit 0 diff -Nur xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-mail.univention-config-registry-variables xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-mail.univention-config-registry-variables --- xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-mail.univention-config-registry-variables 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-mail.univention-config-registry-variables 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,23 @@ +[xxxxxx/delete/deactivated] +Description[de]=Aktiviert das automatische Löschen von deaktivierten Benutzern +Description[en]=Activates the automatic deletion of deactivated users. +Type=str +Categories=management-udm + +[xxxxxx/delete/deactivated/days] +Description[de]=Nach wie vielen Tagen deaktivierte Benutzer automatisch gelöscht werden. +Description[en]=After how many days deactivated users are automatically deleted. +Type=str +Categories=management-udm + +[xxxxxx/delete/deactivated/mail] +Description[de]=Aktiviert das Löschen von E-Mail-Verzeichnissen auf diesem Computer. +Description[en]=Activates the deletion of email directories on this computer. +Type=str +Categories=management-udm + +[xxxxxx/delete/deactivated/mail/logfile] +Description[de]=Logdatei in der die gelöschten Mailboxen protokolliert werden. +Description[en]=Log file to log deleted mailboxes in. +Type=str +Categories=management-udm diff -Nur xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-master.install xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-master.install --- xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-master.install 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-master.install 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,2 @@ +delete-deactivated-master.py usr/lib/univention-directory-listener/system +xxxxxx-delete-deactivated usr/sbin diff -Nur xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-master.postinst xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-master.postinst --- xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-master.postinst 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-master.postinst 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,46 @@ +#!/bin/sh +# +# xxxxxx-delete-deactivated +# -master postinst +# +# Copyright 2011 Univention GmbH +# +# http://www.univention.de/ +# +# All rights reserved. +# +# The source code of this program is made available +# under the terms of the GNU Affero General Public License version 3 +# (GNU AGPL V3) as published by the Free Software Foundation. +# +# Binary versions of this program provided by Univention to you as +# well as other copyrighted, protected or trademarked materials like +# Logos, graphics, fonts, specific documentations and configurations, +# cryptographic keys etc. are subject to a license agreement between +# you and Univention and not subject to the GNU AGPL V3. +# +# In the case you use this program under the terms of the GNU AGPL V3, +# the program is provided in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License with the Debian GNU/Linux or Univention distribution in file +# /usr/share/common-licenses/AGPL-3; if not, see +# . + +#DEBHELPER# + +if [ "$1" = 'configure' ] +then + ldap_base="$(univention-config-registry get ldap/base)" + univention-config-registry set 'xxxxxx/delete/deactivated/logfile?/var/log/univention/xxxxxx-delete-deactivated.log' \ + 'xxxxxx/delete/deactivated/days?30' \ + 'xxxxxx/delete/deactivated/mailaddress/schedule?root' \ + 'xxxxxx/delete/deactivated/mailaddress/error?root' \ + 'xxxxxx/delete/deactivated/blacklist?uid=join-backup,cn=users,'"$ldap_base"'|uid=join-slave,cn=users,'"$ldap_base"'|uid=spam,cn=users,'"$ldap_base"'|uid=Administrator,cn=users,'"$ldap_base" + invoke-rc.d univention-directory-listener crestart +fi + +exit 0 diff -Nur xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-master.univention-config-registry xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-master.univention-config-registry --- xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-master.univention-config-registry 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-master.univention-config-registry 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,3 @@ +Type: file +File: etc/cron.d/xxxxxx-delete-deactivated +Variables: xxxxxx/delete/deactivated/mailaddress/schedule diff -Nur xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-master.univention-config-registry-variables xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-master.univention-config-registry-variables --- xxxxxx-delete-deactivated.orig/debian/xxxxxx-delete-deactivated-master.univention-config-registry-variables 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/debian/xxxxxx-delete-deactivated-master.univention-config-registry-variables 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,35 @@ +[xxxxxx/delete/deactivated] +Description[de]=Aktiviert das automatische Löschen von deaktivierten Benutzern +Description[en]=Activates the automatic deletion of deactivated users. +Type=str +Categories=management-udm + +[xxxxxx/delete/deactivated/days] +Description[de]=Nach wie vielen Tagen deaktivierte Benutzer automatisch gelöscht werden. +Description[en]=After how many days deactivated users are automatically deleted. +Type=str +Categories=management-udm + +[xxxxxx/delete/deactivated/mailaddress/schedule] +Description[de]=E-Mail Adresse an die eine Übersicht der zu löschenden Benutzer geschickt wird. +Description[en]=Email address to recieve an overview of the users which are going to be deleted. +Type=str +Categories=management-udm + +[xxxxxx/delete/deactivated/mailaddress/error] +Description[de]=E-Mail Adresse an die Fehlermeldungen versendet werden. +Description[en]=Email address to recieve error messages. +Type=str +Categories=management-udm + +[xxxxxx/delete/deactivated/logfile] +Description[de]=Protokolldatei in der die gelöschten Benutzer protokolliert werden. +Description[en]=Logfile to log deleted users in. +Type=str +Categories=management-udm + +[xxxxxx/delete/deactivated/blacklist] +Description[de]=Liste der Benutzer, die nicht automatisch gelöscht werden sollen, wenn sie deaktiviert werden (Einträge sind DNs mit | getrennt) +Description[en]=List of users which should not be deleted automatically if deactivated (Entries are DNs separated with |) +Type=str +Categories=management-udm diff -Nur xxxxxx-delete-deactivated.orig/delete-deactivated-home.py xxxxxx-delete-deactivated/delete-deactivated-home.py --- xxxxxx-delete-deactivated.orig/delete-deactivated-home.py 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/delete-deactivated-home.py 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +# xxxxxx-delete-deactivated-home +# listener plugin to delete home directories +# +# Copyright 2011 Univention GmbH +# +# http://www.univention.de/ +# +# All rights reserved. +# +# The source code of this program is made available +# under the terms of the GNU Affero General Public License version 3 +# (GNU AGPL V3) as published by the Free Software Foundation. +# +# Binary versions of this program provided by Univention to you as +# well as other copyrighted, protected or trademarked materials like +# Logos, graphics, fonts, specific documentations and configurations, +# cryptographic keys etc. are subject to a license agreement between +# you and Univention and not subject to the GNU AGPL V3. +# +# In the case you use this program under the terms of the GNU AGPL V3, +# the program is provided in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License with the Debian GNU/Linux or Univention distribution in file +# /usr/share/common-licenses/AGPL-3; if not, see +# . + +name = 'delete-deactivated-home' +description = 'deletes the home directory of automatically deleted users' +filter = '(objectClass=posixAccount)' +attributes = ['uid'] +modrdn = '1' + +import listener +import univention.debug +import datetime +import time + +UCRV_ACTIVATED = 'xxxxxx/delete/deactivated' +UCRV_ACTIVATED_HOME = 'xxxxxx/delete/deactivated/home' +UCRV_DAYS = 'xxxxxx/delete/deactivated/days' +UCRV_LOGFILE_HOME = 'xxxxxx/delete/deactivated/home/logfile' + +def userIsDeactivated(user): + if not user.get('krb5KDCFlags', []) == ['254']: + return False + if not user.get('shadowExpire', []) == ['1']: + return False + if not user.get('sambaAcctFlags', []) in (['[UD ]'], ['[ULD ]'], ): + return False + return True + +def encodeTimestamp(timestamp): + return (timestamp - datetime.timedelta(10000)).strftime('%Y%m%d%H%M%SZ') + +def decodeTimestamp(text): + return datetime.date(*time.strptime(text, '%Y%m%d%H%M%SZ')[:3]) + datetime.timedelta(10000) + +def now(): + return datetime.date(*time.gmtime()[:3]) + +def userHasDeactivationTimestamp(user): + return user.get('krb5ValidEnd') and decodeTimestamp(user['krb5ValidEnd'][0]) <= now() + +def userHasExpired(user, expiryAfterDays): + if not expiryAfterDays: + return False + return decodeTimestamp(user['krb5ValidEnd'][0]) + datetime.timedelta(expiryAfterDays) <= now() + +def logfile(message): + if UCRV_LOGFILE_HOME not in listener.baseConfig: + return + listener.setuid(0) + try: + log = open(listener.baseConfig[UCRV_LOGFILE_HOME], 'a') + log.write(message + '\n') + log.close() + finally: + listener.unsetuid() + +def deleteHome(dn, user): + if not 'homeDirectory' in user: + univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, "[delete-deactivated-home] 'homeDirectory' not in user %r" % (dn, )) + return + logfile('Deleting %r for %r' % (user['homeDirectory'][0], dn, )) + listener.run('/usr/bin/find', ['find', user['homeDirectory'][0], '-delete', ], 0, False) + +def handler(dn, new, old, command): + if listener.baseConfig.get(UCRV_ACTIVATED, '').lower() not in ('yes', 'true', '1', 'enable', 'enabled', 'on'): + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-home] disabled via UCRV " + UCRV_ACTIVATED) + return + if listener.baseConfig.get(UCRV_ACTIVATED_HOME, '').lower() not in ('yes', 'true', '1', 'enable', 'enabled', 'on'): + univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, "[delete-deactivated-home] disabled via UCRV " + UCRV_ACTIVATED_HOME) + return + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-home] command == %r" % (command, )) + if command == 'm': # object modified + pass # don't care + elif command == 'd': # object deleted + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-home] userHasDeactivationTimestamp(old) == %r" % (userHasDeactivationTimestamp(old), )) + if userHasDeactivationTimestamp(old): # correctly (==automatically) deleted + expiryAfterDays = None + try: + expiryAfterDays = max(0, int(listener.baseConfig.get(UCRV_DAYS))) + except (TypeError, ValueError, ): + pass + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-home] userHasExpired(old, %r) == %r" % (expiryAfterDays, userHasExpired(old, expiryAfterDays), )) + if userHasExpired(old, expiryAfterDays): + deleteHome(dn, old) + else: + univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, "[delete-deactivated-home] user %r deleted before expiry" % (dn, )) + else: # incorrectly (==manually) deleted + pass # don't care (the listener on master whines about wrong deletion) + elif command == 'r': # object "deleted" for rename + pass # don't care + elif command == 'a': # object added || object "added" for rename (last was 'r') + pass # don't care + elif command == 'n': # initial/resync + pass # don't care + else: + univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, "[delete-deactivated-home] command == %r is unknown!" % (command, )) + +def postrun(): + pass + +def clean(): + pass + +def initialize(): + pass diff -Nur xxxxxx-delete-deactivated.orig/delete-deactivated-mail.py xxxxxx-delete-deactivated/delete-deactivated-mail.py --- xxxxxx-delete-deactivated.orig/delete-deactivated-mail.py 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/delete-deactivated-mail.py 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +# xxxxxx-delete-deactivated +# listener plugin to delete home directories +# +# Copyright 2011 Univention GmbH +# +# http://www.univention.de/ +# +# All rights reserved. +# +# The source code of this program is made available +# under the terms of the GNU Affero General Public License version 3 +# (GNU AGPL V3) as published by the Free Software Foundation. +# +# Binary versions of this program provided by Univention to you as +# well as other copyrighted, protected or trademarked materials like +# Logos, graphics, fonts, specific documentations and configurations, +# cryptographic keys etc. are subject to a license agreement between +# you and Univention and not subject to the GNU AGPL V3. +# +# In the case you use this program under the terms of the GNU AGPL V3, +# the program is provided in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License with the Debian GNU/Linux or Univention distribution in file +# /usr/share/common-licenses/AGPL-3; if not, see +# . + +name = 'delete-deactivated-mail' +description = 'deletes the mail of automatically deleted users' +filter = '(objectClass=posixAccount)' +attributes = ['uid'] +modrdn = '1' + +import listener +import univention.debug +import datetime +import time + +UCRV_ACTIVATED = 'xxxxxx/delete/deactivated' +UCRV_ACTIVATED_MAIL = 'xxxxxx/delete/deactivated/mail' +UCRV_DAYS = 'xxxxxx/delete/deactivated/days' +UCRV_LOGFILE_MAIL = 'xxxxxx/delete/deactivated/mail/logfile' + +def userIsDeactivated(user): + if not user.get('krb5KDCFlags', []) == ['254']: + return False + if not user.get('shadowExpire', []) == ['1']: + return False + if not user.get('sambaAcctFlags', []) in (['[UD ]'], ['[ULD ]'], ): + return False + return True + +def encodeTimestamp(timestamp): + return (timestamp - datetime.timedelta(10000)).strftime('%Y%m%d%H%M%SZ') + +def decodeTimestamp(text): + return datetime.date(*time.strptime(text, '%Y%m%d%H%M%SZ')[:3]) + datetime.timedelta(10000) + +def now(): + return datetime.date(*time.gmtime()[:3]) + +def userHasDeactivationTimestamp(user): + return user.get('krb5ValidEnd') and decodeTimestamp(user['krb5ValidEnd'][0]) <= now() + +def userHasExpired(user, expiryAfterDays): + if not expiryAfterDays: + return False + return decodeTimestamp(user['krb5ValidEnd'][0]) + datetime.timedelta(expiryAfterDays) <= now() + +def logfile(message): + if UCRV_LOGFILE_MAIL not in listener.baseConfig: + return + listener.setuid(0) + try: + log = open(listener.baseConfig[UCRV_LOGFILE_MAIL], 'a') + log.write(message + '\n') + log.close() + finally: + listener.unsetuid() + +def deleteMail(dn, user): + if not 'mailPrimaryAddress' in user: + univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, "[delete-deactivated-mail] 'mailPrimaryAddress' not in user %r" % (dn, )) + return + logfile('Deleting %r for %r' % (user['mailPrimaryAddress'][0], dn, )) + listener.run('/usr/sbin/univention-cyrus-mailbox-delete', ['univention-cyrus-mailbox-delete', '--user', user['mailPrimaryAddress'][0], ], 0, False) + +def handler(dn, new, old, command): + if listener.baseConfig.get(UCRV_ACTIVATED, '').lower() not in ('yes', 'true', '1', 'enable', 'enabled', 'on'): + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-mail] disabled via UCRV " + UCRV_ACTIVATED) + return + if listener.baseConfig.get(UCRV_ACTIVATED_MAIL, '').lower() not in ('yes', 'true', '1', 'enable', 'enabled', 'on'): + univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, "[delete-deactivated-mail] disabled via UCRV " + UCRV_ACTIVATED_MAIL) + return + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-mail] command == %r" % (command, )) + if command == 'm': # object modified + pass # don't care + elif command == 'd': # object deleted + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-mail] userHasDeactivationTimestamp(old) == %r" % (userHasDeactivationTimestamp(old), )) + if userHasDeactivationTimestamp(old): # correctly (==automatically) deleted + expiryAfterDays = None + try: + expiryAfterDays = max(0, int(listener.baseConfig.get(UCRV_DAYS))) + except (TypeError, ValueError, ): + pass + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-mail] userHasExpired(old, %r) == %r" % (expiryAfterDays, userHasExpired(old, expiryAfterDays), )) + if userHasExpired(old, expiryAfterDays): + deleteMail(dn, old) + else: + univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, "[delete-deactivated-mail] user %r deleted before expiry" % (dn, )) + else: # incorrectly (==manually) deleted + pass # don't care (the listener on master whines about wrong deletion) + elif command == 'r': # object "deleted" for rename + pass # don't care + elif command == 'a': # object added || object "added" for rename (last was 'r') + pass # don't care + elif command == 'n': # initial/resync + pass # don't care + else: + univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, "[delete-deactivated-mail] command == %r is unknown!" % (command, )) + +def postrun(): + pass + +def clean(): + pass + +def initialize(): + pass diff -Nur xxxxxx-delete-deactivated.orig/delete-deactivated-master.py xxxxxx-delete-deactivated/delete-deactivated-master.py --- xxxxxx-delete-deactivated.orig/delete-deactivated-master.py 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/delete-deactivated-master.py 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,195 @@ +# -*- coding: utf-8 -*- +# xxxxxx-delete-deactivated +# listener plugin to delete home directories +# +# Copyright 2011 Univention GmbH +# +# http://www.univention.de/ +# +# All rights reserved. +# +# The source code of this program is made available +# under the terms of the GNU Affero General Public License version 3 +# (GNU AGPL V3) as published by the Free Software Foundation. +# +# Binary versions of this program provided by Univention to you as +# well as other copyrighted, protected or trademarked materials like +# Logos, graphics, fonts, specific documentations and configurations, +# cryptographic keys etc. are subject to a license agreement between +# you and Univention and not subject to the GNU AGPL V3. +# +# In the case you use this program under the terms of the GNU AGPL V3, +# the program is provided in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License with the Debian GNU/Linux or Univention distribution in file +# /usr/share/common-licenses/AGPL-3; if not, see +# . + +name = 'delete-deactivated-master' +description = 'Stores the timestamp when a user is deactivated' +filter = '(&(|(&(objectClass=posixAccount)(objectClass=shadowAccount))(objectClass=univentionMail)(objectClass=sambaSamAccount)(objectClass=simpleSecurityObject)(&(objectClass=person)(objectClass=organizationalPerson)(objectClass=inetOrgPerson)))(!(uidNumber=0))(!(uid=*$)))' +attributes = ['krb5KDCFlags', 'shadowExpire', 'sambaAcctFlags'] +modrdn = '1' + +import listener +import univention.debug +import univention.uldap +import datetime +import time + +UCRV_ACTIVATED = 'xxxxxx/delete/deactivated' +UCRV_BLACKLIST = 'xxxxxx/delete/deactivated/blacklist' +UCRV_DAYS = 'xxxxxx/delete/deactivated/days' +UCRV_MAIL_ERROR = 'xxxxxx/delete/deactivated/mailaddress/error' + +def userIsDeactivated(user): + if not user.get('krb5KDCFlags', []) == ['254']: + return False + if not user.get('shadowExpire', []) == ['1']: + return False + if not user.get('sambaAcctFlags', []) in (['[UD ]'], ['[ULD ]'], ): + return False + return True + +def encodeTimestamp(timestamp): + return (timestamp - datetime.timedelta(10000)).strftime('%Y%m%d%H%M%SZ') + +def decodeTimestamp(text): + return datetime.date(*time.strptime(text, '%Y%m%d%H%M%SZ')[:3]) + datetime.timedelta(10000) + +def now(): + return datetime.date(*time.gmtime()[:3]) + +def userHasDeactivationTimestamp(user): + return user.get('krb5ValidEnd') and decodeTimestamp(user['krb5ValidEnd'][0]) <= now() + +def userHasExpired(user, expiryAfterDays): + if not expiryAfterDays: + return False + return decodeTimestamp(user['krb5ValidEnd'][0]) + datetime.timedelta(expiryAfterDays) <= now() + +import email.MIMEText +import smtplib +def errorMail(message, user): + textMessage = 'Hallo,\n\nxxxxxx-delete-deactivated meldet folgendes Problem:\n' + textMessage+= message.strip() + '\n' + textMessage+= '\n\nDie Attribute des Benutzers waren:\n{\n' + for (key, value, ) in user.items(): + textMessage+= '%r: %r,' % (key, value, ) + textMessage+= '}\n' + mailMessage = email.MIMEText.MIMEText(message, 'plain', 'utf-8') + mailMessage['Subject'] = message + mailMessage['To'] = listener.baseConfig.get(UCRV_MAIL_ERROR, 'root') + mailMessage['From'] = 'root@' + listener.baseConfig.get('hostname', 'localhost') + s = smtplib.SMTP('localhost') + s.sendmail(mailMessage['From'], [mailMessage['To']], mailMessage.as_string()) + s.quit() + +def userIsBlacklisted(dn): + if UCRV_BLACKLIST not in listener.baseConfig: + return False + blacklist = listener.baseConfig[UCRV_BLACKLIST].split('|') + return dn in blacklist + +def handler(dn, new, old, command): + if listener.baseConfig.get(UCRV_ACTIVATED, '').lower() not in ('yes', 'true', '1', 'enable', 'enabled', 'on'): + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-master] disabled via UCRV " + UCRV_ACTIVATED) + return + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-master] command == %r" % (command, )) + if userIsBlacklisted(dn): + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-master] ignoring blacklisted %r" % (dn, )) + return + if command == 'm': # object modified + if old and new: # modification + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-master] userIsDeactivated(old) == %s userIsDeactivated(new) == %s" % (userIsDeactivated(old), userIsDeactivated(new), )) + if not userIsDeactivated(old) and userIsDeactivated(new): # activated → deactivated + postrun.actions.append( ('deactivated', dn, ) ) + if userIsDeactivated(old) and not userIsDeactivated(new): # deactivated → activated + postrun.actions.append( ( 'activated', dn, ) ) + else: + univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, "[delete-deactivated-master] command == 'm' and not (old and new)! old=%r new=%r" % (old, new, )) + elif command == 'd': # object deleted + if userHasDeactivationTimestamp(old): # deleted correctly (==automatically) + expiryAfterDays = None + try: + expiryAfterDays = max(0, int(listener.baseConfig.get(UCRV_DAYS))) + except (TypeError, ValueError, ): + pass + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-master] userHasExpired(old, %r) == %r" % (expiryAfterDays, userHasExpired(old, expiryAfterDays), )) + if userHasExpired(old, expiryAfterDays): + pass # don't care (the other listeners process automatic user deletion) + else: + univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, "[delete-deactivated-master] user %r deleted before expiry" % (dn, )) + errorMail('Benutzer %r wurde vor Ablauf gelöscht' % (dn, ), old) + else: # deleted incorrectly (==manually) + univention.debug.debug(univention.debug.LISTENER, univention.debug.WARN, "[delete-deactivated-master] user %r deleted incorrectly" % (dn, )) + errorMail('Benutzer %r wurde manuell gelöscht' % (dn, ), old) + elif command == 'r': # object "deleted" for rename + pass # don't care + elif command == 'a': # object added || object "added" for rename (last was 'r') + pass # don't care + elif command == 'n': # initial/resync + pass # don't care + else: + univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, "[delete-deactivated-master] command == %r is unknown!" % (command, )) + +def postrun(): + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, "[delete-deactivated-master] postrun.actions == %r" % (postrun.actions, )) + actions = {} + for (action, dn, ) in postrun.actions: + actions[dn] = action + postrun.actions = [] + for (dn, action, ) in actions.items(): + if not ldap_info['lo']: + ldap_reconnect() + if action == 'deactivated': + changes = [('krb5ValidEnd', ldap_info['lo'].getAttr(dn, 'krb5ValidEnd'), [encodeTimestamp(now())], ), + ('shadowExpire', ldap_info['lo'].getAttr(dn, 'shadowExpire'), ['1'], )] + elif action == 'activated': + changes = [('krb5ValidEnd', ldap_info['lo'].getAttr(dn, 'krb5ValidEnd'), [], ), + ('shadowExpire', ldap_info['lo'].getAttr(dn, 'shadowExpire'), [], )] + if ldap_info['lo']: + ldap_info['lo'].modify(dn, changes) + else: + univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, "[delete-deactivated-master] ldap_info['lo'] is %r! Could not set timestamp for %r" % (ldap_info['lo'], dn, )) +postrun.actions = [] + +def clean(): + pass + +def initialize(): + pass + +ldap_info = {} +def ldap_reconnect(): + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, '[delete-deactivated-master] ldap reconnect triggered') + if 'ldapserver' in ldap_info and 'basedn' in ldap_info and 'binddn' in ldap_info and 'bindpw' in ldap_info: + try: + ldap_info['lo'] = univention.uldap.access(host = ldap_info['ldapserver'], + base = ldap_info['basedn'], + binddn = ldap_info['binddn'], + bindpw = ldap_info['bindpw'], + start_tls = 2) + except ValueError, ex: + univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, '[delete-deactivated-master] ldap reconnect failed: %s' % str(ex)) + ldap_info['lo'] = None + else: + if ldap_info['lo'] == None: + univention.debug.debug(univention.debug.LISTENER, univention.debug.ERROR, '[delete-deactivated-master] ldap reconnect failed') + +def setdata(key, value): + if key == 'bindpw': + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, '[delete-deactivated-master] listener passed key="%s" value=""' % key) + else: + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, '[delete-deactivated-master] listener passed key="%s" value="%s"' % (key, value)) + if key in [ 'ldapserver', 'basedn', 'binddn', 'bindpw' ]: + ldap_info[ key ] = value + else: + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, '[delete-deactivated-master] listener passed unknown data (key="%s" value="%s")' % (key, value)) + if key == 'ldapserver': + univention.debug.debug(univention.debug.LISTENER, univention.debug.INFO, '[delete-deactivated-master] ldap server changed to %s' % value) + ldap_reconnect() diff -Nur xxxxxx-delete-deactivated.orig/README xxxxxx-delete-deactivated/README --- xxxxxx-delete-deactivated.orig/README 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/README 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,46 @@ +Allgemein: + Benutzer werden nicht mehr gelöscht, sondern deaktiviert (Benutzer-Konto → Konto-Deaktiviertung → Alle deaktiviert). + Wird ein Benutzer deaktiviert speichert ein listener-Modul nach kurzer Zeit das Datum des deaktivierens (aka Heute) in dem Konto-Ablaufdatum (Wert = Deaktivierungszeitpunkt - 10000 Tage) + Ein cron-job löscht täglich alle Benutzer die länger als xxxxxx/delete/deactivated/days deaktiviert waren und schreibt dies in eine Protokolldatei. + Listener-Skripte auf den Systemen auf denen home/mail gelöscht werden sollen erkennen das Löschen, prüfen ob der Benutzer nach Ablauf gelöscht wurde, und löschen dann das entsprechende /home oder die mailbox + + xxxxxx/delete/deactivated/days muss auf allen Systemen, auf denen eines der Pakete installiert ist, gleich gesetzt sein. + + Der Listener muss neu gestartet werden, damit die Änderungen an UCR-Variablen übernommen werden! + +Paket xxxxxx-delete-deactivated-master: + Wird auf dem Master installiert + Enthält ein Listener-Skript, das für deaktivierte Benutzer das Konto-Ablaufdatum setzt + Sofern xxxxxx/delete/deactivated=yes + Fehlbedienungen (Benutzer manuell gelöscht) werden per E-Mail an xxxxxx/delete/deactivated/mailaddress/error gesendet + Sofern der Benutzer nicht in der xxxxxx/delete/deactivated/blacklist steht + Enthält /usr/sbin/xxxxxx-delete-deactivated + Löscht abgelaufene Benutzer, sofern + xxxxxx/delete/deactivated=yes + xxxxxx/delete/deactivated/days >= 1 + Kann auch manuell aufgerufen werden, ohne --force werden die Benutzer nicht gelöscht. + Protokolliert gelöschte Benutzer in xxxxxx/delete/deactivated/logfile + Enthält cron-job der täglich xxxxxx-delete-deactivated aufruft + Ausgaben gehen per E-Mail an xxxxxx/delete/deactivated/mailaddress/schedule + +Paket xxxxxx-delete-deactivated-home: + Wird dort installiert wo /home gelöscht werden soll + Enthält ein Listener-Skript, das für gelöschte Benutzer das /home löscht, sofern + sie nach dem Ablauf (also automatisch) gelöscht wurden, + xxxxxx/delete/deactivated=yes + xxxxxx/delete/deactivated/home=yes + (Warnt (in der listener.log) wenn diese Variable nicht gesetzt ist - dann sollte das Paket auch nicht installiert sein) + xxxxxx/delete/deactivated/days >= 1 + Das Home-Verzeichnis == /home/$USER ist + (Ansonsten wird ein Fehler in die listener.log eingetragen) + Protokolliert gelöschte Heimatverzeichnisse in xxxxxx/delete/deactivated/home/logfile + +Paket xxxxxx-delete-deactivated-mail: + Wird dort installiert wo Mailboxen gelöscht werden sollen + Enthält ein Listener-Skript, das für gelöschte Benutzer die Mailbox löscht, sofern + sie nach dem Ablauf (also automatisch) gelöscht wurden, + xxxxxx/delete/deactivated=yes + xxxxxx/delete/deactivated/mail=yes + (Warnt (in der listener.log) wenn diese Variable nicht gesetzt ist - dann sollte das Paket auch nicht installiert sein) + xxxxxx/delete/deactivated/days >= 1 + Protokolliert gelöschte Mailboxen in xxxxxx/delete/deactivated/mail/logfile diff -Nur xxxxxx-delete-deactivated.orig/xxxxxx-delete-deactivated xxxxxx-delete-deactivated/xxxxxx-delete-deactivated --- xxxxxx-delete-deactivated.orig/xxxxxx-delete-deactivated 1970-01-01 01:00:00.000000000 +0100 +++ xxxxxx-delete-deactivated/xxxxxx-delete-deactivated 2012-01-03 08:15:36.000000000 +0100 @@ -0,0 +1,133 @@ +#!/usr/bin/python2.4 +# -*- coding: utf-8 -*- +# +# xxxxxx-delete-deactivated +# summarize and delete deactivated users +# +# Copyright 2011 Univention GmbH +# +# http://www.univention.de/ +# +# All rights reserved. +# +# The source code of this program is made available +# under the terms of the GNU Affero General Public License version 3 +# (GNU AGPL V3) as published by the Free Software Foundation. +# +# Binary versions of this program provided by Univention to you as +# well as other copyrighted, protected or trademarked materials like +# Logos, graphics, fonts, specific documentations and configurations, +# cryptographic keys etc. are subject to a license agreement between +# you and Univention and not subject to the GNU AGPL V3. +# +# In the case you use this program under the terms of the GNU AGPL V3, +# the program is provided in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public +# License with the Debian GNU/Linux or Univention distribution in file +# /usr/share/common-licenses/AGPL-3; if not, see +# . +import univention.config_registry +import univention.uldap +import subprocess +import sys +import datetime +import time +import optparse + +UCRV_ACTIVATED = 'xxxxxx/delete/deactivated' +UCRV_DAYS = 'xxxxxx/delete/deactivated/days' +UCRV_LOGFILE = 'xxxxxx/delete/deactivated/logfile' +LDAP_SEARCHFILTER = '(&(|(&(objectClass=posixAccount)(objectClass=shadowAccount))(objectClass=univentionMail)(objectClass=sambaSamAccount)(objectClass=simpleSecurityObject)(&(objectClass=person)(objectClass=organizationalPerson)(objectClass=inetOrgPerson)))(!(uidNumber=0))(!(uid=*$)))' + +def userIsDeactivated(user): + if not user.get('krb5KDCFlags', []) == ['254']: + return False + if not user.get('shadowExpire', []) == ['1']: + return False + if not user.get('sambaAcctFlags', []) in (['[UD ]'], ['[ULD ]'], ): + return False + return True + +def encodeTimestamp(timestamp): + return (timestamp - datetime.timedelta(10000)).strftime('%Y%m%d%H%M%SZ') + +def decodeTimestamp(text): + return datetime.date(*time.strptime(text, '%Y%m%d%H%M%SZ')[:3]) + datetime.timedelta(10000) + +def now(): + return datetime.date(*time.gmtime()[:3]) + +def userHasDeactivationTimestamp(user): + return user.get('krb5ValidEnd') and decodeTimestamp(user['krb5ValidEnd'][0]) <= now() + +def userHasExpired(user, expiryAfterDays): + if not expiryAfterDays: + return False + return decodeTimestamp(user['krb5ValidEnd'][0]) + datetime.timedelta(expiryAfterDays) <= now() + +def deleteExpiredUsers(searchResults, expiryAfterDays, logFile): + errorsOccurred = False + for (dn, user, ) in searchResults: + if userHasDeactivationTimestamp(user): + if userHasExpired(user, expiryAfterDays): + logFile.write('deleting %r\n' % dn) + if not subprocess.call( ('/usr/sbin/univention-directory-manager', 'users/user', 'remove', '--dn', dn, ) ) == 0: + errorsOccurred = True + return not errorsOccurred + +def buildDeletionSchedule(searchResults, expiryAfterDays): + if not expiryAfterDays: + print 'ACHTUNG: ' + UCRV_DAYS + ' ist ungültig, daher werden keine automatischen Löschungen durchgeführt!' + return + schedule = [] + for (dn, user, ) in searchResults: + if userHasDeactivationTimestamp(user): + expiryIn = (datetime.timedelta(expiryAfterDays) - (now() - decodeTimestamp(user['krb5ValidEnd'][0]))).days + schedule.append( (expiryIn, dn, ) ) + schedule.sort() + print 'Die folgenden Benutzer werden gelöscht:' + foundDelete = False + for (expiryIn, dn, ) in schedule: + if expiryIn <= 0: + foundDelete = True + print ' %s' % (dn, ) + if not foundDelete: + print ' -keine-' + print + print 'Die folgenden Benutzer sind für die Löschung in den nächsten Tagen vorgesehen:' + found = False + for (expiryIn, dn, ) in sorted(schedule): + if expiryIn > 0: + found = True + print '%3d %s' % (expiryIn, dn, ) + if not found: + print ' -keine-' + if foundDelete: + print + print 'Detailierte Informationen zum Löschvorgang:' + +if __name__ == "__main__": + parser = optparse.OptionParser() + parser.add_option('-d', '--delete', dest='delete', action='store_true', default=False, help='actually delete users') + (options, args, ) = parser.parse_args() + uldap = univention.uldap.getAdminConnection() + ucr = univention.config_registry.ConfigRegistry() + ucr.load() + expiryAfterDays = None + if ucr.get(UCRV_ACTIVATED, '').lower() not in ('yes', 'true', '1', 'enable', 'enabled', 'on'): + sys.exit() + try: + expiryAfterDays = max(0, int(ucr.get(UCRV_DAYS))) + except (TypeError, ValueError, ): + pass + if UCRV_LOGFILE in ucr: + logFile = open(ucr[UCRV_LOGFILE], 'a') + searchResults = uldap.search(filter=LDAP_SEARCHFILTER) + buildDeletionSchedule(searchResults, expiryAfterDays) + if options.delete: + if not deleteExpiredUsers(searchResults, expiryAfterDays, logFile): + sys.exit(1)