コード例 #1
0
ファイル: uldap.py プロジェクト: bopopescu/smart-1
    def _handle_referral(self, exception):
        # Following referral
        e = exception.args[0]
        info = e.get('info')
        ldap_url = info[info.find('ldap'):]
        if isLDAPUrl(ldap_url):
            conn_str = LDAPUrl(ldap_url).initializeUrl()

            lo_ref = ldap.initialize(conn_str)

            if self.ca_certfile:
                lo_ref.set_option(ldap.OPT_X_TLS_CACERTFILE, self.ca_certfile)

            if self.start_tls == 1:
                try:
                    lo_ref.start_tls_s()
                except:
                    univention.debug.debug(univention.debug.LDAP,
                                           univention.debug.WARN,
                                           'Could not start TLS')
            elif self.start_tls == 2:
                lo_ref.start_tls_s()

            lo_ref.simple_bind_s(self.binddn, self.__encode_pwd(self.bindpw))
            return lo_ref

        else:
            raise ldap.CONNECT_ERROR, 'Bad referral "%s"' % str(e)
コード例 #2
0
ファイル: engine.py プロジェクト: clebergnu/ldapalchemy
    def __init__(self, url, **kwargs):
        if not ldapurl.isLDAPUrl(url):
            #
            # assume a hostname or ip address
            #
            url = 'ldap://%s' % url

        self.url = url
        self._initialize()

        self._username = ''
        self._password = ''

        #
        # Process kwargs
        # 
        for key in ('user', 'username', 'binddn'):
            if kwargs.has_key(key):
                self._username = kwargs[key]
                break

        for key in ('passwd', 'password', 'bindpw'):
            if kwargs.has_key(key):
                self._password = kwargs[key]
                break

        self._bind()
コード例 #3
0
ファイル: uldap.py プロジェクト: kielfriedt/smart
    def _handle_referral(self, exception):
        # Following referral
        e = exception.args[0]
        info = e.get("info")
        ldap_url = info[info.find("ldap") :]
        if isLDAPUrl(ldap_url):
            conn_str = LDAPUrl(ldap_url).initializeUrl()

            lo_ref = ldap.initialize(conn_str)

            if self.ca_certfile:
                lo_ref.set_option(ldap.OPT_X_TLS_CACERTFILE, self.ca_certfile)

            if self.start_tls == 1:
                try:
                    lo_ref.start_tls_s()
                except:
                    univention.debug.debug(univention.debug.LDAP, univention.debug.WARN, "Could not start TLS")
            elif self.start_tls == 2:
                lo_ref.start_tls_s()

            lo_ref.simple_bind_s(self.binddn, self.__encode_pwd(self.bindpw))
            return lo_ref

        else:
            raise ldap.CONNECT_ERROR, 'Bad referral "%s"' % str(e)
コード例 #4
0
	def _handle_referral(self, exception):
		univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'Following LDAP referral')
		exc = exception.args[0]
		info = exc.get('info')
		ldap_url = info[info.find('ldap'):]
		if isLDAPUrl(ldap_url):
			conn_str = LDAPUrl(ldap_url).initializeUrl()

			lo_ref = ldap.ldapobject.ReconnectLDAPObject(conn_str, trace_stack_limit=None)

			if self.ca_certfile:
				lo_ref.set_option(ldap.OPT_X_TLS_CACERTFILE, self.ca_certfile)

			if self.start_tls == 1:
				try:
					lo_ref.start_tls_s()
				except:
					univention.debug.debug(univention.debug.LDAP, univention.debug.WARN, 'Could not start TLS')
			elif self.start_tls == 2:
				lo_ref.start_tls_s()

			lo_ref.simple_bind_s(self.binddn, self.__encode_pwd(self.bindpw))
			return lo_ref

		else:
			raise ldap.CONNECT_ERROR('Bad referral "%s"' % (exc,))
コード例 #5
0
	def doLogin(self, server=None,username=None,password=None,suffix=None,remember=True,_dc=None):
		if not username or not password:
			return "{'failure':1,'info':'Missing username or password'}"
		
		if logged_in():
			do_redirect('/index')
		
		if username == "admin":
			username = "******"
		elif not "=" in username:
			username="******" % (username, suffix)
		
		use_SSL=0
		
		if ldapurl.isLDAPUrl(server):
			u = ldapurl.LDAPUrl(server)
			if u.urlscheme == "ldaps": use_SSL=1
			server = u.hostport
			
		if ":" in server:
			server,port = server.split(":")
			port = int(port)
		else:
			if use_SSL:
				port = 636
			else:
				port = 389

		if use_SSL:
			return """{failure:1,'info':"Unfortunately SSL is not supported at the moment"}"""
		try:
			l = ldap.open(server,port)
		except ldap.LDAPError, e:
			err = parse_ldap_error(e)
			return """{failure:1,'info':"%s"}""" % (err)
コード例 #6
0
    def _ldap_bind(self):
        """
        Set LDAP binding
        """

        #ldap.set_option(ldap.OPT_DEBUG_LEVEL, 4095)

        if self.auth_type == 'gssapi' :
            if not ldap.SASL_AVAIL:
                raise AnsibleLookupError("Cannot use auth=gssapi when SASL is not configured with the local LDAP install")
            # if self.username or self.password:
            #     raise AnsibleError("Explicit credentials are not supported when auth_type='gssapi'. Call kinit outside of Ansible")
        elif self.auth_type == 'simple' and not (self.username and  self.password):
            raise AnsibleError("The username and password values are required when auth_type=simple")
        else:
            if self.username and self.password:
                pass
                # self.auth_type = 'simple'
            if ldap.SASL_AVAIL:
                self.auth_type == 'gssapi'
            else:
                raise AnsibleError("Invalid auth_type value '%s': expecting either 'gssapi', or 'simple'" % self.auth_type)
        
        if ldapurl.isLDAPUrl(self.domain):
            ldap_url = ldapurl.LDAPUrl(ldapUrl=self.domain)
        else:
            self.port = self.port if self.port else 389 if self.scheme == 'ldap' else 636
            ldap_url = ldapurl.LDAPUrl(hostport="%s:%d" % (self.domain, self.port), urlscheme=self.scheme)             
        
        if self.validate_certs is False :
            ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_ALLOW) 
        
        if not ldap.TLS_AVAIL and conn_url.urlscheme == 'ldaps':
            raise AnsibleLookupError("Cannot use TLS as the local LDAP installed has not been configured to support it")
        
        conn_url = ldap_url.initializeUrl()
        #self.ldap_session = MyLDAPObject(conn_url, trace_level=3)  # higher trace levels
        self.ldap_session = MyLDAPObject(conn_url)
        self.ldap_session.page_size = 900
        self.ldap_session.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
        self.ldap_session.set_option(ldap.OPT_REFERRALS, 0)
 
        if self.auth_type == 'simple':
            try:
                self.ldap_session.bind_s(self.username, self.password, ldap.AUTH_SIMPLE)
            except ldap.LDAPError as err:
                raise AnsibleError("Failed to simple bind against LDAP host '%s': %s " % (conn_url, to_native(err)))
        else:
            cmd = ['kinit', self.username]
            error_code = subprocess.run(cmd, input=self.password.encode(), stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode
            if error_code > 0:
                raise AnsibleError("kinit failure")
            try:
                self.ldap_session.sasl_gssapi_bind_s()
            except ldap.AUTH_UNKNOWN as err:
                # The SASL GSSAPI binding is not installed, e.g. cyrus-sasl-gssapi. Give a better error message than what python-ldap provides
                raise AnsibleError("Failed to do a sasl bind against LDAP host '%s', the GSSAPI mech is not installed: %s" % (conn_url, to_native(err)))
            except ldap.LDAPError as err:
                raise AnsibleError("Failed to do a sasl bind against LDAP host '%s': %s" % (conn_url, to_native(err)))                
コード例 #7
0
 def test_isLDAPUrl(self):
     for ldap_url, expected in self.is_ldap_url_tests.items():
         result = ldapurl.isLDAPUrl(ldap_url)
         self.assertEqual(
             result, expected,
             'isLDAPUrl("%s") returns %d instead of %d.' % (
                 ldap_url, result, expected,
             )
         )
コード例 #8
0
 def run(self):
     start = time.time()
     self.logger.debug("starting thread to download {0}".format(self.crl))
     try:
         crlraw = None
         end = 0 # should be ok as a starting value, since it's 2016
         # LDAP
         if( ldapurl.isLDAPUrl( self.crl ) ):
             url_parts = ldapurl.LDAPUrl( self.crl )
             connectionstring = "{0}://{1}".format(url_parts.urlscheme, url_parts.hostport)
             
             try:
                 l = ldap.initialize(connectionstring)
                 try:
                     l.bind_s('','') #anonymous bind
                     scope = url_parts.scope if url_parts.scope != None else 0
                     if url_parts.filterstr == None:
                         res = l.search_s(url_parts.dn, scope, attrlist=url_parts.attrs)
                     else:
                         res = l.search_s(url_parts.dn, scope, url_parts.filterstr, attrlist=url_parts.attrs)
                     
                     for item in res:
                         for key in item[1]:
                             for crlraw in item[1][key]:
                                 self.output_queue.put((self.crl, crlraw))
                                 end = time.time()
                                 self.logger.debug("downloading {0} finished, took {1} seconds".format(self.crl, (end - start)))
                                 self.log_queue.put((self.crl, (end-start)))
                 except ldap.LDAPError, e:
                         if type(e.message) == dict:
                             for (k, v) in e.message.iteritems():
                                 self.logger.warn("%s: %s" % (k, v) )
                         else:
                             self.logger.warn(e)
                         end = time.time()
                         self.log_queue.put((self.crl, "LDAPError: {1} (after {0} seconds)".format((end-start), e)))
             finally:
                 try:
                     l.unbind()
                 except Error:
                     pass
         # HTTP(S)
         else:
             crlraw = urllib2.urlopen(self.crl).read()
             self.output_queue.put((self.crl, crlraw))
             end = time.time()
             self.logger.debug("downloading {0} finished, took {1} seconds".format(self.crl, (end - start)))
             self.log_queue.put((self.crl, (end-start)))
         if(end - start > 30):
             self.logger.warn("{0} was hella slow, took {1} seconds".format(self.crl, (end - start)))
     except Exception as e:
         end = time.time()
         self.logger.warn("Exception when downloading {0}: {1}".format(self.crl, str(e)))
         self.log_queue.put((self.crl, "EXCEPTION {1} (after {0} seconds)".format((end-start), e)))
     finally:
         self.semaphore.release()
コード例 #9
0
ファイル: LdapChecker.py プロジェクト: hmpf/nav
    def execute(self):
        args = self.args
        # we can connect in 2 ways. By hostname/ip (and portnumber)
        # or by ldap-uri
        if "url" in args and ldapurl.isLDAPUrl(args["url"]):
            conn = ldap.initialize(args["url"])
        else:
            ip, port = self.get_address()
            conn = ldap.initialize("ldap://%s:%s" % (ip, port))
        try:
            username = args.get("username", "")
            password = args.get("password", "")
            conn.simple_bind(username, password)

            try:
                self._set_version(args, conn)
            except ValueError:
                return Event.DOWN, "unsupported protocol version"

            base = args.get("base", "dc=example,dc=org")
            if base == "cn=monitor":
                my_res = conn.search_st(base,
                                        ldap.SCOPE_BASE,
                                        timeout=self.timeout)
                versionstr = str(my_res[0][-1]['description'][0])
                self.version = versionstr
                return Event.UP, versionstr
            scope = args.get("scope", "SUBTREE").upper()
            if scope == "BASE":
                scope = ldap.SCOPE_BASE
            elif scope == "ONELEVEL":
                scope = ldap.SCOPE_ONELEVEL
            else:
                scope = ldap.SCOPE_SUBTREE
            filtr = args.get("filter", "objectClass=*")
            try:
                conn.search_ext_s(base,
                                  scope,
                                  filterstr=filtr,
                                  timeout=self.timeout)
                # pylint: disable=W0703
            except Exception as err:
                return (
                    Event.DOWN,
                    "Failed ldapSearch on %s for %s: %s" %
                    (self.get_address(), filtr, str(err)),
                )
        finally:
            try:
                conn.unbind()
            except Exception:
                pass

        return Event.UP, "Ok"
コード例 #10
0
def main():
    """ Process user's arguments """
    # Setup logging
    logging.basicConfig(format='%(message)s', level=logging.INFO)

    menu = menu_handler()
    args = menu[0]
    # Invoke sub-commands in argparse
    ldap_ls = menu[1].choices['ls']
    ldap_search = menu[1].choices['search']
    ldap_modify = menu[1].choices['modify']
    ldap_delete = menu[1].choices['delete']
    ldap_bulk = menu[1].choices['bulk']

    # Validate LDAP server URL
    if not ldapurl.isLDAPUrl(args.SERVER):
        logging.critical("\nERROR: %s has an invalid URL format!\n",
                         args.SERVER)
        exit(1)

    try:
        if args.action == "ls":
            ldap_session = start_ldap_session(args.SERVER, args.BINDDN)
            ldap_ls.set_defaults(
                func=ldap_action_ls(ldap_session, args.basedn))
        elif args.action == "search":
            ldap_session = start_ldap_session(args.SERVER, args.BINDDN)
            ldap_search.set_defaults(func=ldap_action_search(ldap_session, \
                args.basedn, args.ldap_filter))
        elif args.action == "modify":
            ldap_session = start_ldap_session(args.SERVER, args.BINDDN)
            ldap_modify.set_defaults(func=ldap_action_modify(ldap_session, \
                args.modify_dn, args.target_attr, args.new_value, \
                args.modifymode))
        elif args.action == "delete":
            ldap_session = start_ldap_session(args.SERVER, args.BINDDN)
            ldap_delete.set_defaults(func=ldap_action_delete(ldap_session, \
                args.delete_dn))
        elif args.action == "bulk":
            ldap_session = start_ldap_session(args.SERVER, args.BINDDN)
            ldap_bulk.set_defaults(func=ldap_action_bulk(ldap_session, \
                args))
        else:
            logging.critical(
                "You need to provide at least one action to perform!")
            exit(0)
    except (KeyboardInterrupt, ldap.SERVER_DOWN, ldap.UNWILLING_TO_PERFORM, \
            ldap.INVALID_CREDENTIALS, ldap.INVALID_DN_SYNTAX, \
        ldap.NO_SUCH_OBJECT) as e:
        exit(e)
コード例 #11
0
ファイル: logindialog.py プロジェクト: clebergnu/ldapalchemy
    def __input_connection_uri(self):
        '''
        Asks for the connection uri
        '''
        uri = raw_input('Enter LDAP server URI [%s]: ' \
                        % self.config.connection_uri)

        if not uri:
            return self.config.connection_uri

        if not ldapurl.isLDAPUrl(uri):
            raise LDAPInvalidURI
            
        return uri
コード例 #12
0
    def _handle_referral(self, exception):
        """ Handle a referral specified in the passed-in exception
        """
        payload = exception.args[0]
        info = payload.get('info')
        ldap_url = info[info.find('ldap'):]

        if ldapurl.isLDAPUrl(ldap_url):
            conn_str = ldapurl.LDAPUrl(ldap_url).initializeUrl()
            conn = self._connect(conn_str)
            conn.simple_bind_s(self._encode_incoming(self.bind_dn),
                               self._encode_incoming(self.bind_pwd))
            return conn
        else:
            raise ldap.CONNECT_ERROR('Bad referral "%s"' % str(exception))
コード例 #13
0
 def test_isLDAPUrl(self):
     for ldap_url, expected in self.is_ldap_url_tests.items():
         result = ldapurl.isLDAPUrl(ldap_url)
         self.assertEqual(
             result, expected,
             'isLDAPUrl("%s") returns %d instead of %d.' % (
                 ldap_url,
                 result,
                 expected,
             ))
         if expected:
             LDAPUrl(ldapUrl=ldap_url)
         else:
             with self.assertRaises(ValueError):
                 LDAPUrl(ldapUrl=ldap_url)
コード例 #14
0
    def _handle_referral(self, exception):
        """ Handle a referral specified in the passed-in exception 
        """
        payload = exception.args[0]
        info = payload.get('info')
        ldap_url = info[info.find('ldap'):]

        if ldapurl.isLDAPUrl(ldap_url):
            conn_str = ldapurl.LDAPUrl(ldap_url).initializeUrl()
            conn = self._connect(conn_str)
            conn.simple_bind_s(self._encode_incoming(self.bind_dn),
                               self._encode_incoming(self.bind_pwd))
            return conn
        else:
            raise ldap.CONNECT_ERROR, 'Bad referral "%s"' % str(exception)
コード例 #15
0
def ldap_setup_url(module, hostname, encryption=None):

    prefix = 'ldap'
    port = 389

    if encryption == 'SSL':
        prefix = 'ldaps'
        port = 636

    server = _setup_url(prefix, port, hostname)

    if ldapurl.isLDAPUrl(server):
        return server
    else:
        fail_msg = "Invalid ldap uri for: {}".format(server)
        module.fail_json(msg=fail_msg)
コード例 #16
0
def ldap_setup_url(module, hostname, encryption=None):

    prefix = 'ldap'
    port = 389

    if encryption == 'SSL':
        prefix = 'ldaps'
        port = 636

    server = _setup_url(prefix, port, hostname)

    if ldapurl.isLDAPUrl(server):
        return server
    else:
        fail_msg = "Invalid ldap uri for: {}".format(server)
        module.fail_json(msg=fail_msg)
コード例 #17
0
def main():
    """ LDAP session and logging setup """
    try:
        # Setup logging
        logging.basicConfig(stream=stdout,
                            format='%(message)s',
                            level=logging.INFO)
        # Setup arguments for LDAP session
        menu = menu_handler()
        BASEDN = menu.BASEDN
        PAGE_SIZE = menu.sizelimit
        SEARCH_FILTER = menu.filter
        ATTRS_LIST = menu.ATTRIBUTES.split(',')
        ldap_user = menu.userdn
        writetocsv = bool(menu.writetocsv)

        # Validate LDAP server URL
        if not ldapurl.isLDAPUrl(menu.SERVER):
            logging.critical("\nERROR: %s has an invalid URL format!\n",
                             menu.SERVER)
            exit(1)

        if menu.userdn:
            # Set ldap_auth=True when LDAP authentication is chosen!
            LDAP_SESSION = start_session(menu.SERVER,
                                         ldap_user,
                                         ldap_auth=True)
        else:
            # Anonymous query is performed!.
            LDAP_SESSION = start_session(menu.SERVER,
                                         ldap_user,
                                         ldap_auth=False)
        ldap_data = ldap_paging(PAGE_SIZE, BASEDN, SEARCH_FILTER, ATTRS_LIST,
                                LDAP_SESSION)
        retrieved_ldap_attrs = process_ldap_data(ldap_data, ATTRS_LIST,
                                                 writetocsv)
        if writetocsv:
            csv_file = menu.writetocsv
            write_to_csv(csv_file, retrieved_ldap_attrs)
            csv_headers = ';'.join(ATTRS_LIST) + '\n'
            write_csv_headers(csv_file, csv_headers)
            logging.info("\nResults have been written to CSV file: %s !\n",
                         csv_file)
    except (KeyboardInterrupt, SERVER_DOWN, UNWILLING_TO_PERFORM, \
            INVALID_CREDENTIALS, SIZELIMIT_EXCEEDED) as e:
        exit(e)
コード例 #18
0
ファイル: LdapChecker.py プロジェクト: alexanderfefelov/nav
    def execute(self):
        args = self.getArgs()
        # we can connect in 2 ways. By hostname/ip (and portnumber)
        # or by ldap-uri
        if "url" in args and ldapurl.isLDAPUrl(args["url"]):
            conn = ldap.initialize(args["url"])
        else:
            ip, port = self.getAddress()
            conn = ldap.initialize("ldap://%s:%s" % (ip, port))
        username = args.get("username", "")
        password = args.get("password", "")
        conn.simple_bind(username, password)

        try:
            self._set_version(args, conn)
        except ValueError:
            return Event.DOWN, "unsupported protocol version"

        base = args.get("base", "dc=example,dc=org")
        if base == "cn=monitor":
            my_res = conn.search_st(base, ldap.SCOPE_BASE,
                                    timeout=self.getTimeout())
            versionstr = str(my_res[0][-1]['description'][0])
            self.setVersion(versionstr)
            return Event.UP, versionstr
        scope = args.get("scope", "SUBTREE").upper()
        if scope == "BASE":
            scope = ldap.SCOPE_BASE
        elif scope == "ONELEVEL":
            scope = ldap.SCOPE_ONELEVEL
        else:
            scope = ldap.SCOPE_SUBTREE
        filtr = args.get("filter", "objectClass=*")
        try:
            conn.search_ext_s(base, scope, filterstr=filtr,
                              timeout=self.getTimeout())
            # pylint: disable=W0703
        except Exception as err:
            return (Event.DOWN,
                    "Failed ldapSearch on %s for %s: %s" % (
                        self.getAddress(), filtr, str(err)))

        conn.unbind()

        return Event.UP, "Ok"
コード例 #19
0
    def _handle_referral(self, exception):
        # type: (ldap.REFERRAL) -> ldap.ldapobject.ReconnectLDAPObject
        """
		Follow LDAP rederral.

		:param exception ldap.REFERRAL: The LDAP referral exception.
		:returns: LDAP connection object for the referred LDAP server.
		:rtype: ldap.ldapobject.ReconnectLDAPObject
		"""
        univention.debug.debug(univention.debug.LDAP, univention.debug.INFO,
                               'Following LDAP referral')
        exc = exception.args[0]
        info = exc.get('info')
        ldap_url = info[info.find('ldap'):]
        if isLDAPUrl(ldap_url):
            conn_str = LDAPUrl(ldap_url).initializeUrl()

            # FIXME?: this upgrades a access(reconnect=False) connection to a reconnect=True connection
            lo_ref = ldap.ldapobject.ReconnectLDAPObject(
                conn_str, trace_stack_limit=None)

            if self.ca_certfile:
                lo_ref.set_option(ldap.OPT_X_TLS_CACERTFILE, self.ca_certfile)

            if self.start_tls == 1:
                try:
                    lo_ref.start_tls_s()
                except:
                    univention.debug.debug(univention.debug.LDAP,
                                           univention.debug.WARN,
                                           'Could not start TLS')
            elif self.start_tls == 2:
                lo_ref.start_tls_s()

            lo_ref.simple_bind_s(self.binddn, self.__encode_pwd(self.bindpw))
            return lo_ref

        else:
            raise ldap.CONNECT_ERROR('Bad referral "%s"' % (exc, ))
コード例 #20
0
    def handle_referral(self, exception):
        """ Handle a referral specified in a exception """
        payload = exception.args[0]
        info = payload.get('info')
        ldap_url = info[info.find('ldap'):]

        if isLDAPUrl(ldap_url):
            conn_str = LDAPUrl(ldap_url).initializeUrl()

            if self.binduid_usage == 1:
                user_dn = self.bind_dn
                user_pwd = self.bind_pwd
            else:
                user = getSecurityManager().getUser()
                try:
                    user_dn = user.getUserDN()
                    user_pwd = user._getPassword()
                except AttributeError:  # User object is not a LDAPUser
                    user_dn = user_pwd = ''

            return self._connect(conn_str, user_dn, user_pwd)

        else:
            raise ldap.CONNECT_ERROR, 'Bad referral "%s"' % str(exception)
コード例 #21
0
    def run(self, terms, variables=None, **kwargs):
        if not HAS_LDAP:
            msg = missing_required_lib("python-ldap", url="https://pypi.org/project/python-ldap/")
            msg += ". Import Error: %s" % LDAP_IMP_ERR
            raise AnsibleLookupError(msg)

        # Load the variables and direct args into the lookup options
        self.set_options(var_options=variables, direct=kwargs)
        domain = self.get_option('domain')
        port = self.get_option('port')
        scheme = self.get_option('scheme')
        start_tls = self.get_option('start_tls')
        validate_certs = self.get_option('validate_certs')
        cacert_file = self.get_option('ca_cert')
        search_base = self.get_option('search_base')
        username = self.get_option('username')
        password = self.get_option('password')
        auth = self.get_option('auth')
        allow_plaintext = self.get_option('allow_plaintext')

        # Validate and set input values
        # https://www.openldap.org/lists/openldap-software/200202/msg00456.html
        validate_certs_map = {
            'never': ldap.OPT_X_TLS_NEVER,
            'allow': ldap.OPT_X_TLS_ALLOW,
            'try': ldap.OPT_X_TLS_TRY,
            'demand': ldap.OPT_X_TLS_DEMAND,  # Same as OPT_X_TLS_HARD
        }
        validate_certs_value = validate_certs_map.get(validate_certs, None)
        if validate_certs_value is None:
            valid_keys = list(validate_certs_map.keys())
            valid_keys.sort()
            raise AnsibleLookupError("Invalid validate_certs value '%s': valid values are '%s'"
                                     % (validate_certs, "', '".join(valid_keys)))

        if auth not in ['gssapi', 'simple']:
            raise AnsibleLookupError("Invalid auth value '%s': expecting either 'gssapi', or 'simple'" % auth)
        elif auth == 'gssapi':
            if not ldap.SASL_AVAIL:
                raise AnsibleLookupError("Cannot use auth=gssapi when SASL is not configured with the local LDAP "
                                         "install")
            if username or password:
                raise AnsibleLookupError("Explicit credentials are not supported when auth='gssapi'. Call kinit "
                                         "outside of Ansible")
        elif auth == 'simple' and not (username and password):
            raise AnsibleLookupError("The username and password values are required when auth=simple")

        if ldapurl.isLDAPUrl(domain):
            ldap_url = ldapurl.LDAPUrl(ldapUrl=domain)
        else:
            port = port if port else 389 if scheme == 'ldap' else 636
            ldap_url = ldapurl.LDAPUrl(hostport="%s:%d" % (domain, port), urlscheme=scheme)

        # We have encryption if using LDAPS, or StartTLS is used, or we auth with SASL/GSSAPI
        encrypted = ldap_url.urlscheme == 'ldaps' or start_tls or auth == 'gssapi'
        if not encrypted and not allow_plaintext:
            raise AnsibleLookupError("Current configuration will result in plaintext traffic exposing credentials. "
                                     "Set auth=gssapi, scheme=ldaps, start_tls=True, or allow_plaintext=True to "
                                     "continue")

        if ldap_url.urlscheme == 'ldaps' or start_tls:
            # We cannot use conn.set_option as OPT_X_TLS_NEWCTX (required to use the new context) is not supported on
            # older distros like EL7. Setting it on the ldap object works instead
            if not ldap.TLS_AVAIL:
                raise AnsibleLookupError("Cannot use TLS as the local LDAP installed has not been configured to support it")

            ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, validate_certs_value)
            if cacert_file:
                cacert_path = os.path.expanduser(os.path.expandvars(cacert_file))
                if not os.path.exists(to_bytes(cacert_path)):
                    raise AnsibleLookupError("The cacert_file specified '%s' does not exist" % to_native(cacert_path))

                try:
                    # While this is a path, python-ldap expects a str/unicode and not bytes
                    ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, to_text(cacert_path))
                except ValueError:
                    # https://keathmilligan.net/python-ldap-and-macos/
                    raise AnsibleLookupError("Failed to set path to cacert file, this is a known issue with older "
                                             "OpenLDAP libraries on the host. Update OpenLDAP and reinstall "
                                             "python-ldap to continue")

        conn_url = ldap_url.initializeUrl()
        conn = ldap.initialize(conn_url, bytes_mode=False)
        conn.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
        conn.set_option(ldap.OPT_REFERRALS, 0)  # Allow us to search from the base

        # Make sure we run StartTLS before doing the bind to protect the credentials
        if start_tls:
            try:
                conn.start_tls_s()
            except ldap.LDAPError as err:
                raise AnsibleLookupError("Failed to send StartTLS to LDAP host '%s': %s"
                                         % (conn_url, to_native(err)))

        if auth == 'simple':
            try:
                conn.bind_s(to_text(username), to_text(password))
            except ldap.LDAPError as err:
                raise AnsibleLookupError("Failed to simple bind against LDAP host '%s': %s"
                                         % (conn_url, to_native(err)))
        else:
            try:
                conn.sasl_gssapi_bind_s()
            except ldap.AUTH_UNKNOWN as err:
                # The SASL GSSAPI binding is not installed, e.g. cyrus-sasl-gssapi. Give a better error message than
                # what python-ldap provides
                raise AnsibleLookupError("Failed to do a sasl bind against LDAP host '%s', the GSSAPI mech is not "
                                         "installed: %s" % (conn_url, to_native(err)))
            except ldap.LDAPError as err:
                raise AnsibleLookupError("Failed to do a sasl bind against LDAP host '%s': %s"
                                         % (conn_url, to_native(err)))

        try:
            if not search_base:
                root_dse = conn.read_rootdse_s()
                search_base = root_dse['defaultNamingContext'][0]

            ret = []
            # TODO: change method to search for all servers in 1 request instead of multiple requests
            for server in terms:
                ret.append(get_laps_password(conn, server, search_base))
        finally:
            conn.unbind_s()

        return ret
コード例 #22
0
#! /usr/bin/env python2
import sys
import ldap, ldapurl
import time

url = sys.argv[1]

start = time.time()
if( ldapurl.isLDAPUrl( url ) ):
    url_parts = ldapurl.LDAPUrl( url )
    connectionstring = "{0}://{1}".format(url_parts.urlscheme, url_parts.hostport)
    
    try:
        l = ldap.initialize(connectionstring)
        try:
            l.bind_s('','') #anonymous bind
            scope = url_parts.scope if url_parts.scope != None else 0
            if url_parts.filterstr == None:
                res = l.search_s(url_parts.dn, scope, attrlist=url_parts.attrs)
            else:
                res = l.search_s(url_parts.dn, scope, url_parts.filterstr, attrlist=url_parts.attrs)
            
            for item in res:
                for key in item[1]:
                    for crlraw in item[1][key]:
                        print("got crlraw!")
        except ldap.LDAPError, e:
                if type(e.message) == dict:
                    for (k, v) in e.message.iteritems():
                       print("%s: %sn" % (k, v) )
                else:
コード例 #23
0
    def run(self):
        start = time.time()
        self.logger.debug("starting thread to download {0}".format(self.crl))
        try:
            crlraw = None
            end = 0  # should be ok as a starting value, since it's 2016
            # LDAP
            if (ldapurl.isLDAPUrl(self.crl)):
                url_parts = ldapurl.LDAPUrl(self.crl)
                connectionstring = "{0}://{1}".format(url_parts.urlscheme,
                                                      url_parts.hostport)

                try:
                    l = ldap.initialize(connectionstring)
                    try:
                        l.bind_s('', '')  #anonymous bind
                        scope = url_parts.scope if url_parts.scope != None else 0
                        if url_parts.filterstr == None:
                            res = l.search_s(url_parts.dn,
                                             scope,
                                             attrlist=url_parts.attrs)
                        else:
                            res = l.search_s(url_parts.dn,
                                             scope,
                                             url_parts.filterstr,
                                             attrlist=url_parts.attrs)

                        for item in res:
                            for key in item[1]:
                                for crlraw in item[1][key]:
                                    self.output_queue.put((self.crl, crlraw))
                                    end = time.time()
                                    self.logger.debug(
                                        "downloading {0} finished, took {1} seconds"
                                        .format(self.crl, (end - start)))
                                    self.log_queue.put(
                                        (self.crl, (end - start)))
                    except ldap.LDAPError, e:
                        if type(e.message) == dict:
                            for (k, v) in e.message.iteritems():
                                self.logger.warn("%s: %s" % (k, v))
                        else:
                            self.logger.warn(e)
                        end = time.time()
                        self.log_queue.put(
                            (self.crl,
                             "LDAPError: {1} (after {0} seconds)".format(
                                 (end - start), e)))
                finally:
                    try:
                        l.unbind()
                    except Error:
                        pass
            # HTTP(S)
            else:
                crlraw = urllib2.urlopen(self.crl).read()
                self.output_queue.put((self.crl, crlraw))
                end = time.time()
                self.logger.debug(
                    "downloading {0} finished, took {1} seconds".format(
                        self.crl, (end - start)))
                self.log_queue.put((self.crl, (end - start)))
            if (end - start > 30):
                self.logger.warn("{0} was hella slow, took {1} seconds".format(
                    self.crl, (end - start)))
        except Exception as e:
            end = time.time()
            self.logger.warn("Exception when downloading {0}: {1}".format(
                self.crl, str(e)))
            self.log_queue.put(
                (self.crl, "EXCEPTION {1} (after {0} seconds)".format(
                    (end - start), e)))
        finally:
            self.semaphore.release()
コード例 #24
0
def modify_dsrc(inst, log, args):
    """Modify the instance config
    """
    dsrc_file = f'{expanduser("~")}/.dsrc'

    if path.exists(dsrc_file):
        config = configparser.ConfigParser()
        config.read(dsrc_file)

        # Verify we have a section to modify
        instances = config.sections()
        if inst.serverid not in instances:
            raise ValueError(
                "There is no configuration section for this instance to modify!"
            )

        # Process and validate the args
        if args.uri is not None:
            if not isLDAPUrl(args.uri):
                raise ValueError("The uri is not a valid LDAP URL!")
            if args.uri.startswith("ldapi"):
                # We must use EXTERNAL saslmech for LDAPI
                args.saslmech = "EXTERNAL"
            if args.uri == '':
                del config[inst.serverid]['uri']
            else:
                config[inst.serverid]['uri'] = args.uri
        if args.basedn is not None:
            if not is_dn(args.basedn):
                raise ValueError("The basedn is not a valid DN!")
            if args.basedn == '':
                del config[inst.serverid]['basedn']
            else:
                config[inst.serverid]['basedn'] = args.basedn
        if args.binddn is not None:
            if not is_dn(args.binddn):
                raise ValueError("The binddn is not a valid DN!")
            if args.binddn == '':
                del config[inst.serverid]['binddn']
            else:
                config[inst.serverid]['binddn'] = args.binddn
        if args.saslmech is not None:
            if args.saslmech not in ['EXTERNAL', 'PLAIN']:
                raise ValueError("The saslmech must be EXTERNAL or PLAIN!")
            if args.saslmech == '':
                del config[inst.serverid]['saslmech']
            else:
                config[inst.serverid]['saslmech'] = args.saslmech
        if args.tls_cacertdir is not None:
            if not path.exists(args.tls_cacertdir):
                raise ValueError('--tls-cacertdir directory does not exist!')
            if args.tls_cacertdir == '':
                del config[inst.serverid]['tls_cacertdir']
            else:
                config[inst.serverid]['tls_cacertdir'] = args.tls_cacertdir
        if args.tls_cert is not None:
            if not path.exists(args.tls_cert):
                raise ValueError(
                    '--tls-cert does not point to an existing file!')
            if args.tls_cert == '':
                del config[inst.serverid]['tls_cert']
            else:
                config[inst.serverid]['tls_cert'] = args.tls_cert
        if args.tls_key is not None:
            if not path.exists(args.tls_key):
                raise ValueError(
                    '--tls-key does not point to an existing file!')
            if args.tls_key == '':
                del config[inst.serverid]['tls_key']
            else:
                config[inst.serverid]['tls_key'] = args.tls_key
        if args.tls_reqcert is not None:
            if args.tls_reqcert not in ['never', 'hard', 'allow']:
                raise ValueError(
                    '--tls-reqcert value is invalid (must be either "never", "allow", or "hard")!'
                )
            if args.tls_reqcert == '':
                del config[inst.serverid]['tls_reqcert']
            else:
                config[inst.serverid]['tls_reqcert'] = args.tls_reqcert
        if args.starttls:
            config[inst.serverid]['starttls'] = 'true'
        if args.cancel_starttls:
            config[inst.serverid]['starttls'] = 'false'
        if args.pwdfile is not None:
            if not path.exists(args.pwdfile):
                raise ValueError('--pwdfile does not exist!')
            if args.pwdfile == '':
                del config[inst.serverid]['pwdfile']
            else:
                config[inst.serverid]['pwdfile'] = args.pwdfile

        # Okay now rewrite the file
        with open(dsrc_file, 'w') as configfile:
            config.write(configfile)

        log.info(f'Successfully updated: {dsrc_file}')
    else:
        raise ValueError(f'There is no .dsrc file "{dsrc_file}" to update!')
コード例 #25
0
def create_dsrc(inst, log, args):
    """Create the .dsrc file

    [instance]
    uri = ldaps://hostname:port
    basedn = dc=example,dc=com
    binddn = uid=user,....
    saslmech = [EXTERNAL|PLAIN]
    tls_cacertdir = /path/to/cacertdir
    tls_cert = /path/to/user.crt
    tls_key = /path/to/user.key
    tls_reqcert = [never, hard, allow]
    starttls = [true, false]
    pwdfile = /path/to/file
    """

    dsrc_file = f'{expanduser("~")}/.dsrc'
    config = configparser.ConfigParser()
    config.read(dsrc_file)

    # Verify this section does not already exist
    instances = config.sections()
    if inst.serverid in instances:
        raise ValueError(
            "There is already a configuration section for this instance!")

    # Process and validate the args
    config[inst.serverid] = {}

    if args.uri is not None:
        if not isLDAPUrl(args.uri):
            raise ValueError("The uri is not a valid LDAP URL!")
        if args.uri.startswith("ldapi"):
            # We must use EXTERNAL saslmech for LDAPI
            args.saslmech = "EXTERNAL"
        config[inst.serverid]['uri'] = args.uri
    if args.basedn is not None:
        if not is_dn(args.basedn):
            raise ValueError("The basedn is not a valid DN!")
        config[inst.serverid]['basedn'] = args.basedn
    if args.binddn is not None:
        if not is_dn(args.binddn):
            raise ValueError("The binddn is not a valid DN!")
        config[inst.serverid]['binddn'] = args.binddn
    if args.saslmech is not None:
        if args.saslmech not in ['EXTERNAL', 'PLAIN']:
            raise ValueError("The saslmech must be EXTERNAL or PLAIN!")
        config[inst.serverid]['saslmech'] = args.saslmech
    if args.tls_cacertdir is not None:
        if not path.exists(args.tls_cacertdir):
            raise ValueError('--tls-cacertdir directory does not exist!')
        config[inst.serverid]['tls_cacertdir'] = args.tls_cacertdir
    if args.tls_cert is not None:
        if not path.exists(args.tls_cert):
            raise ValueError('--tls-cert does not point to an existing file!')
        config[inst.serverid]['tls_cert'] = args.tls_cert
    if args.tls_key is not None:
        if not path.exists(args.tls_key):
            raise ValueError('--tls-key does not point to an existing file!')
        config[inst.serverid]['tls_key'] = args.tls_key
    if args.tls_reqcert is not None:
        if args.tls_reqcert not in ['never', 'hard', 'allow']:
            raise ValueError(
                '--tls-reqcert value is invalid (must be either "never", "allow", or "hard")!'
            )
        config[inst.serverid]['tls_reqcert'] = args.tls_reqcert
    if args.starttls:
        config[inst.serverid]['starttls'] = 'true'
    if args.pwdfile is not None:
        if not path.exists(args.pwdfile):
            raise ValueError('--pwdfile does not exist!')
        config[inst.serverid]['pwdfile'] = args.pwdfile

    if len(config[inst.serverid]) == 0:
        # No args set
        raise ValueError(
            "You must set at least one argument for the new dsrc file!")

    # Print a preview of the config
    log.info(f'Updating "{dsrc_file}" with:\n')
    log.info(f'    [{inst.serverid}]')
    for k, v in config[inst.serverid].items():
        log.info(f'    {k} = {v}')

    # Perform confirmation?
    if not args.do_it:
        while 1:
            val = input(f'\nUpdate "{dsrc_file}" ? [yes]: ').rstrip().lower()
            if val == '' or val == 'y' or val == 'yes':
                break
            if val == 'n' or val == 'no':
                return

    # Now write the file
    with open(dsrc_file, 'w') as configfile:
        config.write(configfile)

    log.info(f'Successfully updated: {dsrc_file}')