|
From: Hans A. <Han...@Ph...> - 2002-04-03 12:57:04
|
I have finished a first version of schema support for python-ldap.
There are four simple wrapper for the functions str2objectclass(),
str2attributetype(), str2matchingrule(), and str2syntax() in the _ldap
module (and thus in the ldap module --- I guess it would be a good idea
to del() them from the ldap module in the ldap/__init__.py file...).
These functions should not be used directly, since they are (probably)
not thread safe.
There exists a new module ldap.schema, which proviedes the following
functions/classes:
* Thread safe wrappers for the four C functions (str2xyz), which return
lists of entries which correspond to the C data types (defined in
ldap_schema.h). For thread safety, they simply use the _ldap_call()
function (Michael, is this a good idea?).
* Four simple classes (attributeType, objectClass, ldapSyntax,
matchingRule). Their constructors take a string description
of the schema, pass it to the wrapper functions and fill in the
object attributes. See RFC2252 for details.
* The class rootDSESchema (looking for a better name...), which takes
an initialize()'d and simple_bind_s()'ed ldap object. The constructor
queries the rootDSE and fills the attributeTypes, objectClasses,
ldapSyntaxes, and matchingRules which are known by the ldap server
into 8 dictionaries: for each of the four classes, there is one
dictionary which takes the oid's as keys (these are those funny
"1.2.3.4" things, which are supposed to be unique), and one
dictionary takes the names as keys. The latter is necessary, since
for example, in objectClasses, the allowed or required attributes are
referred to by name rather than by oid. The names of the
dictionaries are:
objectClasses
objectClassesByName
attributeTypes
attributeTypesByName
ldapSyntaxes
ldapSyntaxesByName
matchingRules
matchingRulesByName
I've attached four files (a patch for setup.py, and the newly created
files Modules/schema.c, Modules/schema.h, Lib/ldap/schema.py).
Any comments? Does the user interface make sense? Could someone please
try it with a _server_ different from OpenLDAP 2? As long as untested,
I would say that it is only compatible with OpenLDAP --- there was some
try/error involved in the RootDSE search...
Hans
--
Han...@Ph...
|
|
From: <mi...@st...> - 2002-04-03 14:37:57
|
Hans Aschauer wrote:
> I have finished a first version of schema support for python-ldap.
Great!
> * Thread safe wrappers for the four C functions (str2xyz), which return
> lists of entries which correspond to the C data types (defined in
> ldap_schema.h). For thread safety, they simply use the _ldap_call()
> function (Michael, is this a good idea?).
I don't know if it's good idea. But it was the best idea I came up with. So
it's the right way to do it.
> * Four simple classes (attributeType, objectClass, ldapSyntax,
> matchingRule). Their constructors take a string description
> of the schema, pass it to the wrapper functions and fill in the
> object attributes. See RFC2252 for details.
Ok.
> * The class rootDSESchema (looking for a better name...), which takes
> an initialize()'d and simple_bind_s()'ed ldap object.
You should not do initialize() and simple_bind_s() because it could be a
waste of resource and the root DSE and/or schema could be subject of access
control. The application is responsible to make the connection and set up
the right bind context => simply let the application pass in a instance of
ldap.LDAPObject and solely do the search_s() calls within your class.
> The constructor
> queries the rootDSE and fills the attributeTypes, objectClasses,
> ldapSyntaxes, and matchingRules which are known by the ldap server
> into 8 dictionaries: for each of the four classes, there is one
> dictionary which takes the oid's as keys (these are those funny
> "1.2.3.4" things, which are supposed to be unique), and one
> dictionary takes the names as keys. The latter is necessary, since
> for example, in objectClasses, the allowed or required attributes are
> referred to by name rather than by oid.
I'd like to have a single OID registry since OIDs are really unique. There
are no collisions. Simply map the OID in string notation to the schema
element instance with a single dictionary. The reverse mapping can also be
done by a single dictionary. I don't think that people are using the same
names for attribute types and object classes.
> there was some
> try/error involved in the RootDSE search...
He, he.
BTW: Theoretically the sub schema sub entry can be different in each part of
the DIT. Therefore an application has to query the subschemaSubentry
attribute each time it uses the schema somewhere. Schema can be cached if
the DN in subschemaSubentry attribute is the same. Maybe the OID registry
could be a nested dictionary...
Taken from web2ldap's module ldapsession (lines wrapped!):
def getSubschemaEntryDN(self,dn):
"""Get DN of subschemaSubentry for dn"""
# Search for DN of subschemaSubentry
search_result = self.readEntry(dn,['subschemaSubentry'])
if search_result:
entry = search_result[0][1]
return
entry.get('subschemaSubentry',entry.get('subschemaSubentry',[None]))[0]
else:
return None
Ciao, Michael.
|
|
From: Hans A. <Han...@Ph...> - 2002-04-03 17:42:48
|
On Wednesday, 3. April 2002 16:37, you wrote: > Hans Aschauer wrote: > > (defined in ldap_schema.h). For thread safety, they simply use the > > _ldap_call() function (Michael, is this a good idea?). > > I don't know if it's good idea. But it was the best idea I came up > with. So it's the right way to do it. :-) [...] > > * The class rootDSESchema (looking for a better name...), which > > takes an initialize()'d and simple_bind_s()'ed ldap object. > > You should not do initialize() and simple_bind_s() because it could > be a waste of resource and the root DSE and/or schema could be > subject of access control. The application is responsible to make > the connection and set up the right bind context => simply let the > application pass in a instance of ldap.LDAPObject and solely do the > search_s() calls within your class. Ooops, that was exactly what I meant. Just pass an initialized and boud ldap object. > > The constructor > > queries the rootDSE and fills the attributeTypes, objectClasses, > > ldapSyntaxes, and matchingRules which are known by the ldap > > server into 8 dictionaries: for each of the four classes, there is > > one dictionary which takes the oid's as keys (these are those > > funny "1.2.3.4" things, which are supposed to be unique), and one > > dictionary takes the names as keys. The latter is necessary, since > > for example, in objectClasses, the allowed or required attributes > > are referred to by name rather than by oid. > > I'd like to have a single OID registry since OIDs are really unique. > There are no collisions. Simply map the OID in string notation to the > schema element instance with a single dictionary. The reverse mapping > can also be done by a single dictionary. I don't think that people > are using the same names for attribute types and object classes. You are right, this will really simplify things... [...] > BTW: Theoretically the sub schema sub entry can be different in each > part of the DIT. Therefore an application has to query the > subschemaSubentry attribute each time it uses the schema somewhere. > Schema can be cached if the DN in subschemaSubentry attribute is the > same. Maybe the OID registry could be a nested dictionary... You write of this possibility as a theoretical one. Do you know of any ldap server that implements this? Hmm, if I think about it, this is really usful as soon as referrals are being used. Are there other real-world situations where you (or someone else) have seen this? Maybe one should not automatically query the schema entries for every branch of the DIT, but only at "important" branches. If there exists no schema description at the desired level of the tree, the closest one is aquired (in Zopista speach) by climbing down the tree toward its root. It would then be up to the application writer (or some clever logics) to determine which branch is considered important. Would something like this make sense? -- Han...@Ph... |
|
From: <mi...@st...> - 2002-04-03 20:03:12
|
Hans Aschauer wrote: > On Wednesday, 3. April 2002 16:37, you wrote: > >>Hans Aschauer wrote: > >> > * The class rootDSESchema (looking for a better name...), which >> > takes an initialize()'d and simple_bind_s()'ed ldap object. >> >> [..] simply let the >>application pass in a instance of ldap.LDAPObject and solely do the >>search_s() calls within your class. > > Ooops, that was exactly what I meant. Just pass an initialized and boud > ldap object. Sorry, misread your phrase. >>BTW: Theoretically the sub schema sub entry can be different in each >>part of the DIT. > > You write of this possibility as a theoretical one. Do you know of any > ldap server that implements this? No I don't know one. Hmm, I have to check database configuration in Netscape and iPlanet DS again. But applications have to be prepared for it. > Maybe one should not automatically query the schema entries for every > branch of the DIT, but only at "important" branches. Now the really exciting questions is how you distinguish the "important" branches. ;-) IMHO efficient applications should request the DN of the sub schema sub entry by requesting attribute subschemaSubentry of current DN each and every time. If that points to a sub schema sub entry already parsed the cached schema instance can be used. > If there exists no > schema description at the desired level of the tree, the closest one is > aquired (in Zopista speach) by climbing down the tree toward its root. I'm pretty sure there are situations where tree climbing does not work. Don't try to be clever. Most times it does not work out. Anyway we should review RFC 2251, section 3.2.2 for that more closely. BTW: There could be also these attributes in sub schema sub entry: matchingRuleUse, dITStructureRules, dITContentRules and nameForms. I know OpenLDAP 2 server does not implement any of these. Does the schema parser in OpenLDAP 2 libs handle any of these? Ciao, Michael. |
|
From: Hans A. <Han...@Ph...> - 2002-04-04 08:38:07
|
On Wednesday, 3. April 2002 20:48, Michael Ströder wrote: > Hans Aschauer wrote: > > On Wednesday, 3. April 2002 16:37, you wrote: [about doing clever things in climbing down trees] > I'm pretty sure there are situations where tree climbing does not > work. Don't try to be clever. Most times it does not work out. Anyway > we should review RFC 2251, section 3.2.2 for that more closely. Ok, I went back to RFC 2251. That's how I understand it (please correct me when I'm wrong): Sec. 3.4: We can query the RootDSE for the subschemaSubentry attribute, which tells us which "subschema entries (or subentries) [are] known by this server": [aschauer@pygar]$ldapsearch -LLL -x -b "" -s base "(objectclass=*)" \ subschemaSubentry dn: subschemaSubentry: cn=Subschema Sec. 3.2.2: The result conforms to this section: "cn: this attribute MUST be used to form the RDN of the subschema entry". One thing I missed up to now: "Clients MUST only retrieve attributes from a subschema entry by requesting a base object search of the entry, where the search filter is '(objectClass=subschema)'" (up to now I used '(objectClass=*)'). Let's try it: [aschauer@pygar]$ldapsearch -LLL -x -b "cn=Subschema" -s base \ "(objectclass=subschema)" objectclasses | less Works! So, as far as I understand it, we should first query the rootDSE for the subschema (sub)entries, and use the results as search bases for querying the schema information. > BTW: There could be also these attributes in sub schema sub entry: > matchingRuleUse, dITStructureRules, dITContentRules and nameForms. > I know OpenLDAP 2 server does not implement any of these. Does the > schema parser in OpenLDAP 2 libs handle any of these? Nope. I just looked at the source, and the parsers seem to be kind of hard-coded. No generic BNF parser. But then, that's exactly how I would write such a parser ;-) So long, Hans -- Han...@Ph... |
|
From: <mi...@st...> - 2002-04-04 21:56:26
|
Hans Aschauer wrote:
>
> Ok, I went back to RFC 2251. That's how I understand it (please correct
> me when I'm wrong):
>
> Sec. 3.4:
> We can query the RootDSE for the subschemaSubentry attribute, which
> tells us which "subschema entries (or subentries) [are] known by this
> server":
>
> [aschauer@pygar]$ldapsearch -LLL -x -b "" -s base "(objectclass=*)" \
> subschemaSubentry
> dn:
> subschemaSubentry: cn=Subschema
Hmm, BTW it does not clarify how a client should deal with a multi-valued
subschemaSubentry attribute. Should schemas be used exclusive-or or joined.
That's another interesting topic to be discussed in IETF ldap-bis WG.
> So, as far as I understand it, we should first query the rootDSE for
> the subschema (sub)entries, and use the results as search bases for
> querying the schema information.
Take also a look at section 3.2.1.:
--------------- snip -----------------
3.2.1. Attributes of Entries
[..]
Entries MAY contain, among others, the following operational
attributes, defined in [5]. These attributes are maintained
automatically by the server and are not modifiable by clients:
[..]
- subschemaSubentry: the Distinguished Name of the subschema entry
(or subentry) which controls the schema for this entry.
--------------- snip -----------------
So my conclusion is that an application should first try to query
operational attribute subschemaSubentry for a particular entry and fall-back
to the subschemaSubentry attribute in the root DSE to find out the location
of sub schema sub entry in the DIT. Puh...
I guess I will start a discussion about that on the ldap-bis list.
Ciao, Michael.
|
|
From: Hans A. <Han...@Ph...> - 2002-04-05 13:20:34
|
On Thursday, 4. April 2002 23:51, Michael Ströder wrote:
> Hmm, BTW it does not clarify how a client should deal with a
> multi-valued subschemaSubentry attribute. Should schemas be used
> exclusive-or or joined. That's another interesting topic to be
> discussed in IETF ldap-bis WG.
As I understand it, this issue has been addressed in
draft-ietf-ldapbis-protocol-02.txt:
"""
B.8 Section 3.4
- Reworded text surrounding subschemaSubentry to reflect that it is
a single-valued attribute that holds the schema for the root DSE.
Also noted that if the server masters entries that use differing
schema, each entry's subschemaSubentry attribute must be
interrogated. This may change as further fine-tuning is done to
the data model.
"""
[...]
> So my conclusion is that an application should first try to query
> operational attribute subschemaSubentry for a particular entry and
> fall-back to the subschemaSubentry attribute in the root DSE to find
> out the location of sub schema sub entry in the DIT. Puh...
According to the draft, we should probably query the root DSE only if
we are interested in the schema controlling the root DSE itself (which
most applications are not, as I think). On the other hand, the RFC text
is somwhat misleading (especially where it is changed by the draft),
and I don't know how implementors of server software interpreted the
text...
Anyway, back to the python specific things :-)
* If we implement per-entry schema information, caching is mandatory.
And it can be easily done, since we we can create a mapping
"subschema-entry RDN" => "schema information" (by doing it this way
we would not need nested trees, and for servers which have only one
subschema entry, one saves a lot of memory).
To be specific, for my OpenLDAP installation, this mapping would look
like {'cn=Subschema': <class ldap.schema.rootDSESchema at xyz>} ---
only one entry. Of course, the name of the class
ldap.schema.rootDSESchema has to be changed... How about "schema"?
* How should this cache be accessed? Logically, it belongs to the ldap
connection (or to the ldap server, but there is not such python
class, is it?). However, I don't know if it is too high-level to make
it an attribute of the LDAPObject class.
So long,
Hans
--
Han...@Ph...
|
|
From: <mi...@st...> - 2002-04-16 08:01:40
|
Hans Aschauer wrote: > I have finished a first version of schema support for python-ldap. I tried your attachments. But to me it seems that there is lacking something. The build went fine but the functions do not appear in extension module _ldap. Maybe you also modified functions.c? Please re-send most recent version of your schema support and SASL patches. Ciao, Michael. |
|
From: Joe L. <jl...@op...> - 2002-04-19 17:27:08
|
Now that some of this has been commited, any interest in making another -pr= e release? On 4/15/02 10:59 PM, "Michael Str=F6der" <mi...@st...> wrote: > Hans Aschauer wrote: >> I have finished a first version of schema support for python-ldap. >=20 > I tried your attachments. But to me it seems that there is lacking > something. The build went fine but the functions do not appear in extensi= on > module _ldap. >=20 > Maybe you also modified functions.c? >=20 > Please re-send most recent version of your schema support and SASL patche= s. >=20 > Ciao, Michael. >=20 >=20 > _______________________________________________ > Python-LDAP-dev mailing list > Pyt...@li... > https://lists.sourceforge.net/lists/listinfo/python-ldap-dev |
|
From: <mi...@st...> - 2002-04-19 17:43:46
|
Joe Little wrote: > Now that some of this has been commited, any interest in making another -pre > release? Far too early to ask for a pre-release. Ciao, Michael. |