server/sources/ldapfeed.py
changeset 9462 375fc1868b11
parent 9461 fc3b8798737c
child 9468 39b7a91a3f4c
equal deleted inserted replaced
9461:fc3b8798737c 9462:375fc1868b11
    45 # map ldap protocol to their standard port
    45 # map ldap protocol to their standard port
    46 PROTO_PORT = {'ldap': 389,
    46 PROTO_PORT = {'ldap': 389,
    47               'ldaps': 636,
    47               'ldaps': 636,
    48               'ldapi': None,
    48               'ldapi': None,
    49               }
    49               }
    50 
       
    51 
       
    52 class ConnectionWrapper(object):
       
    53     def __init__(self, cnx=None):
       
    54         self.cnx = cnx
       
    55     def commit(self):
       
    56         pass
       
    57     def rollback(self):
       
    58         pass
       
    59     def cursor(self):
       
    60         return None # no actual cursor support
       
    61     def close(self):
       
    62         if hasattr(self.cnx, 'close'):
       
    63             self.cnx.close()
       
    64 
    50 
    65 
    51 
    66 class LDAPFeedSource(datafeed.DataFeedSource):
    52 class LDAPFeedSource(datafeed.DataFeedSource):
    67     """LDAP feed source: unlike ldapuser source, this source is copy based and
    53     """LDAP feed source: unlike ldapuser source, this source is copy based and
    68     will import ldap content (beside passwords for authentication) into the
    54     will import ldap content (beside passwords for authentication) into the
   231         protocol, hostport = self.urls[0].split('://')
   217         protocol, hostport = self.urls[0].split('://')
   232         if protocol != 'ldapi' and not ':' in hostport:
   218         if protocol != 'ldapi' and not ':' in hostport:
   233             hostport = '%s:%s' % (hostport, PROTO_PORT[protocol])
   219             hostport = '%s:%s' % (hostport, PROTO_PORT[protocol])
   234         return protocol, hostport
   220         return protocol, hostport
   235 
   221 
   236     def get_connection(self):
       
   237         """open and return a connection to the source"""
       
   238         if self._conn is None:
       
   239             try:
       
   240                 self._connect()
       
   241             except Exception:
       
   242                 self.exception('unable to connect to ldap')
       
   243         return ConnectionWrapper(self._conn)
       
   244 
       
   245     def authenticate(self, session, login, password=None, **kwargs):
   222     def authenticate(self, session, login, password=None, **kwargs):
   246         """return CWUser eid for the given login/password if this account is
   223         """return CWUser eid for the given login/password if this account is
   247         defined in this source, else raise `AuthenticationError`
   224         defined in this source, else raise `AuthenticationError`
   248 
   225 
   249         two queries are needed since passwords are stored crypted, so we have
   226         two queries are needed since passwords are stored crypted, so we have
   303            pass
   280            pass
   304         #conn.set_option(ldap.OPT_NETWORK_TIMEOUT, conn_timeout)
   281         #conn.set_option(ldap.OPT_NETWORK_TIMEOUT, conn_timeout)
   305         #conn.timeout = op_timeout
   282         #conn.timeout = op_timeout
   306         # Now bind with the credentials given. Let exceptions propagate out.
   283         # Now bind with the credentials given. Let exceptions propagate out.
   307         if user is None:
   284         if user is None:
   308             # no user specified, we want to initialize the 'data' connection,
       
   309             assert self._conn is None
       
   310             self._conn = conn
       
   311             # XXX always use simple bind for data connection
   285             # XXX always use simple bind for data connection
   312             if not self.cnx_dn:
   286             if not self.cnx_dn:
   313                 conn.simple_bind_s(self.cnx_dn, self.cnx_pwd)
   287                 conn.simple_bind_s(self.cnx_dn, self.cnx_pwd)
   314             else:
   288             else:
   315                 self._authenticate(conn, {'dn': self.cnx_dn}, self.cnx_pwd)
   289                 self._authenticate(conn, {'dn': self.cnx_dn}, self.cnx_pwd)
   343     def _search(self, session, base, scope,
   317     def _search(self, session, base, scope,
   344                 searchstr='(objectClass=*)', attrs=()):
   318                 searchstr='(objectClass=*)', attrs=()):
   345         """make an ldap query"""
   319         """make an ldap query"""
   346         self.debug('ldap search %s %s %s %s %s', self.uri, base, scope,
   320         self.debug('ldap search %s %s %s %s %s', self.uri, base, scope,
   347                    searchstr, list(attrs))
   321                    searchstr, list(attrs))
   348         # XXX for now, we do not have connections set support for LDAP, so
   322         if self._conn is None:
   349         # this is always self._conn
   323             self._conn = self._connect()
   350         cnx = self.get_connection().cnx #session.cnxset.connection(self.uri).cnx
   324         cnx = self._conn
   351         if cnx is None:
       
   352             # cant connect to server
       
   353             msg = session._("can't connect to source %s, some data may be missing")
       
   354             session.set_shared_data('sources_error', msg % self.uri, txdata=True)
       
   355             return []
       
   356         try:
   325         try:
   357             res = cnx.search_s(base, scope, searchstr, attrs)
   326             res = cnx.search_s(base, scope, searchstr, attrs)
   358         except ldap.PARTIAL_RESULTS:
   327         except ldap.PARTIAL_RESULTS:
   359             res = cnx.result(all=0)[1]
   328             res = cnx.result(all=0)[1]
   360         except ldap.NO_SUCH_OBJECT:
   329         except ldap.NO_SUCH_OBJECT: