7

I am using ldap module of python to connect to ldap server. I am able to query the database but I dont know how to retrieve the fields present in the database, so that I can notify the user in advance to quering the database, telling him that the field he is trying to access is not in the database.

For example if the fields present are just

cn
memberOf

and if the user tries to query the database with filter

cn and memberOf and notcontained

I should be able to know that the notcontained attribute is not in the dabase schema.

How can I accomplish this.

Thanks.

ashokadhikari
  • 1,182
  • 3
  • 15
  • 29

4 Answers4

9

You need to read the schema of your ldap server.

This code may work for you, as tempalte

#!/usr/bin/env python
#coding:utf-8
# Author:  peter --<pjl@hpc.com.py>
# Purpose: Tareas comunes a utilizar con respecto a schemas ldap
# Created: 01/05/12
import ldap
import ldap.schema



########################################################################
class SchemasIPA(object):

    __ldaps = ldap.schema

    #----------------------------------------------------------------------
    def __init__(self, url):
        """Constructor"""
        ldap._trace_level = 0
        ldap.set_option(ldap.OPT_DEBUG_LEVEL,0)
        subschemasubentry_dn, self.schema = ldap.schema.urlfetch(url,ldap._trace_level)
        self.oc_tree = self.schema.tree(ldap.schema.ObjectClass)        
        self.at_tree = self.schema.tree(ldap.schema.AttributeType)        

    def getobjectclasses(self):
        """
        trae la listas de objectclasses de un servidor dado
        """
        allobjc = {}
        for a in self.oc_tree.keys():
            objc = self.schema.get_obj(ldap.schema.ObjectClass, a)

            if objc != None:
                allobjc[objc.oid] = (objc.names, objc.must, objc.may, objc.sup, objc.obsolete)

        return allobjc

    def getatributes(self):
        """
        trae la lista de atributos de un servidor dado
        """
        allatt= {}
        o = []
        for a in self.at_tree.keys():
            att = self.schema.get_obj(ldap.schema.AttributeType, a)

            if att != None:
                allatt[att.oid] = (att.names, att.syntax, att.syntax_len, att.desc, att.collective, att.equality, att.single_value)

        return allatt

    def getvalidoid(self, objects):
        """
        retorno un valor oid libre valida para la creacion de esquemas y atributos
        el proceso valido es pedirle a la iana un oid valido, pero se tarda mas de un mes
        los oid a utilizar son valores predefinidos al momento de la instalacion del servidor ldap
        """
        pass

if __name__ == '__main__':
    sch = SchemasIPA('ldap://localhost')
    #at = sch.getatributes()
    ob = sch.getobjectclasses()

    for a, b in ob.iteritems():
        print a
        print b[0]

Then you can wrapper this class like this

#a file contained the above class
import schemas

olschemas = schemas.SchemasIPA(url='ldap://192.168.1.81')

#here are, some magic :)
pa = olschemas.schema.get_obj(olschemas._SchemasIPA__ldaps.ObjectClass, 'posixaccount')
pa.must #going to print all the attributes that can't be null's
pa.may #going to print all the attributes that are optional's
Pjl
  • 1,752
  • 18
  • 21
  • 1
    Finally managed to get `python-ldap` to tell me about all the available objectClasses in the schema using this code, thank you! – Lukas Graf Oct 29 '13 at 08:50
  • 1
    How to bind? otherwise getting this error - ldap.OPERATIONS_ERROR: {'info': '000004DC: LdapErr: DSID-0C090A22, comment: In order to perform this operation a successful bind must be completed on the connection., data 0, v3839', 'desc': 'Operations error'} – Pankaj Goyal Oct 02 '18 at 20:56
  • @PankajGoyal You need first to initialize the connection to the server, then depends of the server (AD, Opendaldap|389directoryserver), you bind with the .bind method. Of theses 3 the only complicated going's to be AD, because if enforce to connect with a valida certificated. I give an answer to this question in https://stackoverflow.com/questions/13636117/python-ldap-and-microsoft-active-directory-connect-and-delete-user/16557927#16557927, hope its help you – Pjl May 15 '20 at 15:44
3

The Root DSE and possible base DN of the schema

Assuming that the LDAP client only cares what attributes are defined in the schema (see extensibleObject below), to determine if an attribute is defined in the server schema, retrieve the schema. In many directory servers, the base DN (or base object) for the schema is defined in the attribute subSchemaSubEntry which might be present in the root DSE. For more information about the root DSE, see LDAP: The Root DSE. To retrieve the contents of the root DSE, transmit a search request to the server consisting of a base object of '' and a search scope of base, and a requested attribute list consisting of * and +.

extensibleObject

Note that the presence of the objectClass extensibleObject allows LDAP clients to add any attribute name and value they require, much like a FORTRAN garbage common block, that is, attributes could be present in an entry but not defined in the schema.

subSchemaSubEntry not present

If the subSchemaSubEntry attribute is not present, contact the server administrators and ask for information regarding retrieving the schema and for sufficient access rights to do so.

subSchemaSubEntry present

If the subSchemaSubEntry attribute is present, read the schema by transmitting a search request to the server using the value of the subSchemaSubEntry attribute as the base object, a search scope of one and a requested attribute list consistent of * and +. The attribute type definitions and objectClass definitions are contained in the schema.

Terry Gardner
  • 10,957
  • 2
  • 28
  • 38
2

I am using ldap module of python to connect to ldap server. I am able to query the database but I dont know how to retrieve the fields present in the database, so that I can notify the user in advance to quering the database, telling him that the field he is trying to access is not in the database.

A simple solution would be to search and then print a list of the keys from the result.

import ldap

# connect to your ldap server

some_dn = '...' # Your base dn
some_lookup = '...' # your lookup attr

result = conn.search_s(some_dn,ldap.SCOPE_SUBTREE,some_lookup)
result[0][1].keys()

For example, against my AD server it returns the following:

['mailNickname',
 'publicDelegatesBL',
 'logonCount',
 'cn',
 'countryCode',
 'dSCorePropagationData',
 'objectClass',
 # ... many many more
'telephoneNumber',
'physicalDeliveryOfficeName',
'name',
'memberOf',
'codePage',
'userAccountControl',
'msExchMDBRulesQuota',
'lastLogon',
'protocolSettings',
'uSNChanged',
'sn',
'msExchVersion',
'mDBUseDefaults',
'givenName',
'msExchMailboxGuid',
'lastLogoff']
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
  • 1
    Thanks. But Even if some result[0][1] entry doesnt have the memberOf attribute set, does the above code show the memberOf attribute, in the assumption memberOf attribute is set only in some of the entries (and not necessarily the first) – ashokadhikari Jul 11 '12 at 07:21
-1

I'm not trying to explain the whole step to connect to AD. Just explaining how you can view all the fields/attributes you have in your AD.

import ldap

#create the conn connection to your AD before. This depends on your AD and your company.

conn.search_s('dc=#Your_directory_details', '(&(objectclass=#type_defined_in_your_directory)(#accountname_used_inyour_directory='+ username +'))' ,attributes['*']) conn.entries[0]