def check_domain(self, username, password, ad_server_address, mode):
        ad_domain_info = {}
        try:
            if mode == 'admember':
                admember.check_server_role()
            ad_domain_info = admember.lookup_adds_dc(ad_server_address)

            ad_server_ip = ad_domain_info['DC IP']
            if mode == 'admember':
                admember.check_domain(ad_domain_info)
            admember.check_connection(ad_domain_info, username, password)
            admember.check_ad_account(ad_domain_info, username, password)
        except admember.invalidUCSServerRole as exc:  # check_server_role()
            MODULE.warn('Failure: %s' % exc)
            raise UMC_Error(
                _('The AD member mode can only be configured on a DC master server.'
                  ))
        except admember.failedADConnect as exc:  # lookup_adds_dc()
            MODULE.warn('Failure: %s' % exc)
            raise UMC_Error(
                _('Could not connect to AD Server %s. Please verify that the specified address is correct. (%s)'
                  ) % (ad_server_address, 'check_domain: %s' % (exc, )))
        except admember.domainnameMismatch as exc:  # check_domain()
            MODULE.warn('Failure: %s' % exc)
            raise UMC_Error(
                _('The domain name of the AD Server (%(ad_domain)s) does not match the local UCS domain name (%(ucs_domain)s). For the AD member mode, it is necessary to setup a UCS system with the same domain name as the AD Server.'
                  ) % {
                      'ad_domain': ad_domain_info.get("Domain"),
                      'ucs_domain': ucr['domainname']
                  })
        except admember.connectionFailed as exc:  # check_connection()
            MODULE.warn('Failure: %s' % exc)
            raise UMC_Error(
                _('Could not connect to AD Server %s. Please verify that username and password are correct. (Details:\n%s)'
                  ) % (ad_domain_info.get('DC DNS Name'), exc))
        except admember.notDomainAdminInAD as exc:  # check_ad_account()
            MODULE.warn('Failure: %s' % exc)
            raise UMC_Error(
                _('The given user is not member of the Domain Admins group in Active Directory. This is a requirement for the Active Directory domain join.'
                  ))

        # final info dict that is returned... replace spaces in the keys with '_'
        MODULE.info('Preparing info dict...')
        info = dict([(key.replace(' ', '_'), value)
                     for key, value in ad_domain_info.iteritems()])
        info['ssl_supported'] = admember.server_supports_ssl(ad_server_ip)
        # try to get binddn
        info['LDAP_BindDN'] = get_ad_binddn_from_name(info['LDAP_Base'],
                                                      ad_server_ip, username,
                                                      password)
        MODULE.info(str(info))
        return info
Example #2
0
	def _enable_ssl_and_test_connection(self, certificate_fname=None):
		with ucr_rollback(ucr, ['connector/ad/ldap/ssl', 'connector/ad/ldap/certificate']):
			if certificate_fname:
				univention.config_registry.handler_set([u'connector/ad/ldap/certificate=%s' % certificate_fname])
			server = ucr.get('connector/ad/ldap/host')
			if server:
				success = False
				if admember.server_supports_ssl(server):
					admember.enable_ssl()
					try:
						success = test_connection()
					except ADNotAvailable:
						success = False
				if not success:
					raise UMC_Error(_('Could not establish an encrypted connection. Either "%r" is not reachable or does not support encryption.') % server)
			else:
				MODULE.warn('connector is not configured yet, cannot test connection')
Example #3
0
	def adconnector_save(self, request):
		"""Saves the Active Directory connection configuration

		options:
			Host_IP: IP address of the AD server
			LDAP_Host: hostname of the AD server
			LDAP_Base: LDAP base of the AD server
			LDAP_BindDN: LDAP DN to use for authentication
			KerberosDomain: kerberos domain
			PollSleep: time in seconds between polls
			RetryRejected: how many time to retry a synchronisation
			MappingSyncMode: synchronisation mode
			MappingGroupLanguage: language of the AD server

		return: { 'success' : (True|False), 'message' : <details> }
		"""

		for umckey, ucrkey, default in Instance.OPTION_MAPPING:
			val = request.options.get(umckey, default)
			if val:
				if isinstance(val, bool):
					val = 'yes' if val else 'no'
				MODULE.info('Setting %s=%s' % (ucrkey, val))
				univention.config_registry.handler_set([u'%s=%s' % (ucrkey, val)])

		ucr.load()
		if ucr.get('connector/ad/ldap/ldaps'):
			MODULE.info('Unsetting connector/ad/ldap/ldaps')
			univention.config_registry.handler_unset([u'connector/ad/ldap/ldaps'])
		if ucr.get('connector/ad/ldap/port') == '636':
			MODULE.info('Setting ldap port to 389')
			univention.config_registry.handler_set([u'connector/ad/ldap/port=389'])

		if not request.options.get('LDAP_Password') in (None, '', DO_NOT_CHANGE_PWD):
			fn = ucr.get('connector/ad/ldap/bindpw', FN_BINDPW)
			try:
				with open(fn, 'w') as fd:
					fd.write(request.options.get('LDAP_Password'))
				os.chmod(fn, 0o600)
				os.chown(fn, 0, 0)
				univention.config_registry.handler_set([u'connector/ad/ldap/bindpw=%s' % fn])
			except Exception as e:
				MODULE.info('Saving bind password failed (filename=%(fn)s ; exception=%(exception)s)' % {'fn': fn, 'exception': str(e.__class__)})
				self.finished(request.id, {'success': False, 'message': _('Saving bind password failed (filename=%(fn)s ; exception=%(exception)s)') % {'fn': fn, 'exception': str(e.__class__)}})
				return

		ssldir = '/etc/univention/ssl/%s' % request.options.get('LDAP_Host')
		if not os.path.exists(ssldir):
			self._create_certificate(request)
			return

		# enter a static host entry such that the AD server's FQDN can be resolved
		univention.config_registry.handler_set([u'hosts/static/%(Host_IP)s=%(LDAP_Host)s' % request.options])

		# check for SSL support on AD side
		if admember.server_supports_ssl(server=request.options.get('LDAP_Host')):
			MODULE.process('Enabling SSL...')
			admember.enable_ssl()
		else:
			MODULE.warn('SSL is not supported')
			admember.disable_ssl()

		# UCR variables are set, and now we can try to guess the language of
		# the AD domain
		ad_lang = guess_ad_domain_language()
		univention.config_registry.handler_set([u'connector/ad/mapping/group/language=%s' % ad_lang])

		self.finished(request.id, {'success': True, 'message': _('Active Directory connection settings have been saved.')})
class Instance(Base, ProgressMixin):
	OPTION_MAPPING = (
		('LDAP_Host', 'connector/ad/ldap/host', ''),
		('LDAP_Base', 'connector/ad/ldap/base', ''),
		('LDAP_BindDN', 'connector/ad/ldap/binddn', ''),
		('KerberosDomain', 'connector/ad/mapping/kerberosdomain', ''),
		('PollSleep', 'connector/ad/poll/sleep', 5),
		('RetryRejected', 'connector/ad/retryrejected', 10),
		('DebugLevel', 'connector/debug/level', 2),
		('DebugFunction', 'connector/debug/function', False),
		('MappingSyncMode', 'connector/ad/mapping/syncmode', 'sync'),
		('MappingGroupLanguage', 'connector/ad/mapping/group/language', 'de')
	)

	def init(self):
		self.__update_status()

	def state(self, request):
		"""Retrieve current status of the Active Directory connection configuration and the service

		options: {}

		return: { 'configured' : (True|False), 'certificate' : (True|False), 'running' : (True|False) }
		"""

		self.__update_status()
		self.finished(request.id, {
			'ssl_enabled': self.status_ssl,
			'password_sync_enabled': self.status_password_sync,
			'running': self.status_running,
			'certificate': self.status_certificate,
			'mode_admember': self.status_mode_admember,
			'mode_adconnector': self.status_mode_adconnector,
			'configured': self.status_mode_adconnector or self.status_mode_admember,
			'server_role': ucr.get('server/role'),
		})

	def load(self, request):
		"""Retrieve current status of the Active Directory connection configuration and the service

		options: {}

		return: { <all AD connector UCR variables> }
		"""

		result = {}
		for option, var, default in Instance.OPTION_MAPPING:
			result[option] = ucr.get(var, default)

		pwd_file = ucr.get('connector/ad/ldap/bindpw')
		result['passwordExists'] = bool(pwd_file and os.path.exists(pwd_file))

		self.finished(request.id, result)

	@sanitize(LDAP_Host=StringSanitizer(required=True))
	def adconnector_save(self, request):
		"""Saves the Active Directory connection configuration

		options:
			Host_IP: IP address of the AD server
			LDAP_Host: hostname of the AD server
			LDAP_Base: LDAP base of the AD server
			LDAP_BindDN: LDAP DN to use for authentication
			KerberosDomain: kerberos domain
			PollSleep: time in seconds between polls
			RetryRejected: how many time to retry a synchronisation
			MappingSyncMode: synchronisation mode
			MappingGroupLanguage: language of the AD server

		return: { 'success' : (True|False), 'message' : <details> }
		"""

		self.required_options(request, 'Host_IP')
		self.required_options(request, *[x[0] for x in Instance.OPTION_MAPPING if x[2] == ''])

		for umckey, ucrkey, default in Instance.OPTION_MAPPING:
			val = request.options.get(umckey, default)
			if val:
				if isinstance(val, bool):
					val = val and 'yes' or 'no'
				MODULE.info('Setting %s=%s' % (ucrkey, val))
				univention.config_registry.handler_set([u'%s=%s' % (ucrkey, val)])

		ucr.load()
		if ucr.get('connector/ad/ldap/ldaps'):
			MODULE.info('Unsetting connector/ad/ldap/ldaps')
			univention.config_registry.handler_unset([u'connector/ad/ldap/ldaps'])
		if ucr.get('connector/ad/ldap/port') == '636':
			MODULE.info('Setting ldap port to 389')
			univention.config_registry.handler_set([u'connector/ad/ldap/port=389'])

		if not request.options.get('LDAP_Password') in (None, '', DO_NOT_CHANGE_PWD):
			fn = ucr.get('connector/ad/ldap/bindpw', FN_BINDPW)
			try:
				fd = open(fn, 'w')
				fd.write(request.options.get('LDAP_Password'))
				fd.close()
				os.chmod(fn, 0600)
				os.chown(fn, 0, 0)
				univention.config_registry.handler_set([u'connector/ad/ldap/bindpw=%s' % fn])
			except Exception, e:
				MODULE.info('Saving bind password failed (filename=%(fn)s ; exception=%(exception)s)' % {'fn': fn, 'exception': str(e.__class__)})
				self.finished(request.id, {'success': False, 'message': _('Saving bind password failed (filename=%(fn)s ; exception=%(exception)s)') % {'fn': fn, 'exception': str(e.__class__)}})
				return

		ssldir = '/etc/univention/ssl/%s' % request.options.get('LDAP_Host')
		if not os.path.exists(ssldir):
			self._create_certificate(request)
			return

		# enter a static host entry such that the AD server's FQDN can be resolved
		univention.config_registry.handler_set([u'hosts/static/%(Host_IP)s=%(LDAP_Host)s' % request.options])

		# check for SSL support on AD side
		if admember.server_supports_ssl(server=request.options.get('LDAP_Host')):
			MODULE.process('Enabling SSL...')
			admember.enable_ssl()
		else:
			MODULE.warn('SSL is not supported')
			admember.disable_ssl()

		# UCR variables are set, and now we can try to guess the language of
		# the AD domain
		ad_lang = guess_ad_domain_language()
		univention.config_registry.handler_set([u'connector/ad/mapping/group/language=%s' % ad_lang])

		self.finished(request.id, {'success': True, 'message': _('Active Directory connection settings have been saved.')})