#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
#
# Univention AD Connector
#  List all rejected objects
#
# Copyright 2004-2014 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
# <http://www.gnu.org/licenses/>.


import sys, string, os, time, signal, shutil

import ldap, traceback
import univention
import univention.connector
import univention.connector.ad

import univention.config_registry

CONFIGBASENAME="connector"

def usage():
    print ""
    print "This is univention-connector-list-rejected"
    print ""
    print "Univention-connector-list-rejected tries to summarize the objects which are rejected due to sync failures"
    print ""
    print "Usage:"
    print "univention-connector-list-rejected [-c configbase]"
    print ""
    print "The default configbase is \"connector\"."


if len(sys.argv) > 1:
	if sys.argv[1] in ['-h', '--help', '-?']:
		usage()
		sys.exit(0)
	if sys.argv[1] == '-c':
		if len(sys.argv) != 3:
			print "ERROR: option \"-c\" needs an argument!"
			usage()
			sys.exit(1)
		else:
			CONFIGBASENAME = sys.argv[2]
			print "use configbase %s" % CONFIGBASENAME
	

sys.path=['/etc/univention/%s/ad/'%CONFIGBASENAME]+sys.path
import mapping

def main():
	configRegistry=univention.config_registry.ConfigRegistry()
	configRegistry.load()

	if not configRegistry.has_key('%s/ad/ldap/host' % CONFIGBASENAME):
		print '%s/ad/ldap/host not set' % CONFIGBASENAME
		sys.exit(1)
	if not configRegistry.has_key('%s/ad/ldap/port' % CONFIGBASENAME):
		print '%s/ad/ldap/port not set' % CONFIGBASENAME
		sys.exit(1)
	if not configRegistry.has_key('%s/ad/ldap/base' % CONFIGBASENAME):
		print '%s/ad/ldap/base not set' % CONFIGBASENAME
		sys.exit(1)
	if not configRegistry.has_key('%s/ad/ldap/binddn' % CONFIGBASENAME):
		print '%s/ad/ldap/binddn not set' % CONFIGBASENAME
		sys.exit(1)
	if not configRegistry.has_key('%s/ad/ldap/bindpw' % CONFIGBASENAME):
		print '%s/ad/ldap/bindpw not set' % CONFIGBASENAME
		sys.exit(1)

	ca_file = configRegistry.get('%s/ad/ldap/certificate' % CONFIGBASENAME)

	if configRegistry.is_true('%s/ad/ldap/ssl' % CONFIGBASENAME, True):

		if ca_file:
			# create a new CAcert file, which contains the UCS CA and the AD CA,
			# see Bug #17768 for details
			#  https://forge.univention.org/bugzilla/show_bug.cgi?id=17768
			new_ca_filename = '/var/cache/univention-ad-connector/CAcert-%s.pem' % CONFIGBASENAME
			if not os.path.exists(new_ca_filename):
				new_ca = open(new_ca_filename, 'w')

				ca = open('/etc/univention/ssl/ucsCA/CAcert.pem', 'r')
				new_ca.write(string.join(ca.readlines(),''))
				ca.close()

				ca = open(configRegistry['%s/ad/ldap/certificate' % CONFIGBASENAME])
				new_ca.write(string.join(ca.readlines(),''))
				ca.close()

				new_ca.close()
			
			ldap.set_option( ldap.OPT_X_TLS_CACERTFILE, new_ca_filename )
		else:
			ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)

	if not configRegistry.has_key('%s/ad/listener/dir' % CONFIGBASENAME):
		print '%s/ad/listener/dir not set' % CONFIGBASENAME
		sys.exit(1)

	if not configRegistry.has_key('%s/ad/retryrejected' % CONFIGBASENAME):
		baseconfig_retry_rejected=10
	else:
		baseconfig_retry_rejected=configRegistry['%s/ad/retryrejected' % CONFIGBASENAME]

	ad_ldap_bindpw=open(configRegistry['%s/ad/ldap/bindpw' % CONFIGBASENAME]).read()
	if ad_ldap_bindpw[-1] == '\n':
		ad_ldap_bindpw=ad_ldap_bindpw[0:-1]
	
	poll_sleep=int(configRegistry['%s/ad/poll/sleep' % CONFIGBASENAME])


	#try:
	ad=univention.connector.ad.ad( CONFIGBASENAME,
				       mapping.ad_mapping,
				       configRegistry,
				       configRegistry['%s/ad/ldap/host' % CONFIGBASENAME],
				       configRegistry['%s/ad/ldap/port' % CONFIGBASENAME],
				       configRegistry['%s/ad/ldap/base' % CONFIGBASENAME],
				       configRegistry['%s/ad/ldap/binddn' % CONFIGBASENAME],
				       ad_ldap_bindpw,
				       configRegistry['%s/ad/ldap/certificate' % CONFIGBASENAME],
				       configRegistry['%s/ad/listener/dir' % CONFIGBASENAME],
				       False)
	#except:
	#	print "Failed to read Connector-Config. This may happen if the connector is running."		
	#	sys.exit(1)

	found_rejected = False
	i=1
	print "\n\tUCS rejected\n"
	for filename,dn in ad.list_rejected_ucs():
		found_rejected = True
		print "%5d:   UCS DN: %s" % (i, univention.connector.ad.encode_attrib(dn).encode('latin'))
		ad_dn = univention.connector.ad.encode_attrib(ad.get_dn_by_ucs(dn)).encode('latin')
		if ad_dn:
			print "          AD DN: %s" % ad_dn
		else:
			print "          AD DN: <not found>"
		print "         Filename: %s\n" % filename
		i+=1

	i=1
	print "\nAD rejected\n"
	for id,dn in ad.list_rejected():
		found_rejected = True
		print "%5d:    AD DN: %s" % (i,univention.connector.ad.encode_attrib(dn).encode('latin'))
		ucs_dn = univention.connector.ad.encode_attrib(ad.get_dn_by_con(dn)).encode('latin')
		if ucs_dn:
			print "         UCS DN: %s" % ucs_dn
		else:
			print "         UCS DN: <not found>"
		i+=1

	if not found_rejected:
		print "\nThere may be no rejected DNs if the connector is in progress, to be\nsure stop the connector before running this script.\n"

	print "\n\tlast synced USN: %s" % ad.get_lastUSN()	

if __name__ == "__main__":
	main()

