#!/usr/bin/python2.6
# -*- coding: utf-8 -*-
#
# Univention S4 Connector
#  Upgrade script for NTSecurityDescriptor attributes
#
# Copyright 2013-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 subprocess
import sys
import string
import ldap
from optparse import OptionParser
import univention.config_registry
import univention.admin.uldap
import univention.admin.uexceptions

def _connect_ucs(configRegistry, binddn, bindpwd):
	''' Connect to OpenLDAP '''

	if binddn and bindpwd:
		bindpw = bindpwd
	else:
		bindpw_file = configRegistry.get('connector/ldap/bindpw', '/etc/ldap.secret')
		binddn = configRegistry.get('connector/ldap/binddn', 'cn=admin,'+configRegistry['ldap/base'])
		bindpw=open(bindpw_file).read()
		if bindpw[-1] == '\n':
			bindpw=bindpw[0:-1]

	host = configRegistry.get('connector/ldap/server', configRegistry.get('ldap/master'))

	try:
		port = int(configRegistry.get('connector/ldap/port', configRegistry.get('ldap/master/port')))
	except:
		port = 7389

	lo = univention.admin.uldap.access(host=host, port=port, base=configRegistry['ldap/base'], binddn=binddn, bindpw=bindpw, start_tls=2, follow_referral=True)

	return lo


def search_s4():
	''' Search all S4 GPO objects with NTSecurityDescriptor attribute and return a
		dictonary with dn as key and NTSecurityDescriptor as result.
	'''

	p1 = subprocess.Popen(['ldbsearch -H /var/lib/samba/private/sam.ldb "(&(objectClass=groupPolicyContainer)(NTSecurityDescriptor=*))" dn NTSecurityDescriptor | ldapsearch-wrapper'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
	(stdout,stderr) = p1.communicate()

	if p1.returncode != 0:
		print stderr
		sys.exit(p1.returncode)

	result = {}
	dn=None

	for line in stdout.split('\n'):
		line=line.strip()
		if line.startswith('dn: '):
			dn=line[4:]
		if line.startswith('nTSecurityDescriptor: '):
			nTSecurityDescriptor=line[len('nTSecurityDescriptor: '):]
			result[dn] = nTSecurityDescriptor
			dn=None

	return result



def write_to_ucs(configRegistry,  s4_result, binddn, bindpwd):
	''' Write the result from search_s4 to UCS LDAP '''

	lo = _connect_ucs(configRegistry, binddn, bindpwd)

	s4_ldap_base = configRegistry.get('connector/s4/ldap/base' ).lower()
	ucs_ldap_base = configRegistry.get('ldap/base').lower()
	for s4_dn in s4_result.keys():
		ucs_dn = s4_dn.lower().replace(s4_ldap_base, ucs_ldap_base)
		ml = []
		try:
			for dn, attributes in lo.search(base=ucs_dn, scope=ldap.SCOPE_BASE):
				ml.append( ('msNTSecurityDescriptor', attributes.get('msNTSecurityDescriptor'), s4_result[s4_dn]) )
			if ml:
				print 'Set msNTSecurityDescriptor for UCS object (%s)' % (ucs_dn)
				lo.modify(ucs_dn, ml)
		except univention.admin.uexceptions.noObject:
			pass
		except:
			print 'Failed to set msNTSecurityDescriptor for UCS object (%s)' % (ucs_dn)
	pass


if __name__ == '__main__':

	parser = OptionParser(usage='msGPOSecurityDescriptor.py (--write2ucs|--write2samba4)')
	parser.add_option("--write2ucs", dest="write2ucs", action="store_true", help="Write NTSecurityDescriptor from Samba 4 to UCS", default=False)
	parser.add_option("--binddn", dest="binddn", action="store", help="Binddn for UCS LDAP connection")
	parser.add_option("--bindpwd", dest="bindpwd", action="store", help="Password for UCS LDAP connection")
	(options, args) = parser.parse_args()

	configRegistry = univention.config_registry.ConfigRegistry()
	configRegistry.load()

	if options.write2ucs:
		result = search_s4()
		write_to_ucs(configRegistry, result, options.binddn, options.bindpwd)
	else:
		parser.print_help()
		sys.exit(1)

	sys.exit(0)

