From: Chris R. <chr...@me...> - 2001-01-29 18:03:18
Attachments:
ldap-schema.diffs
|
I think the schema method of the Net::LDAP class is fairly broken. It isn't documented, either :-) Here's my take on the existing behaviour: schema ( [ dn => DN ] ) DN is an optional distinguished name. If not present, the method will use a random DN from the Root DSE's subschemaSubentry attribute. If this attribute is not present, the method will try <cn=schema>. It then tries to do a base object search of that DN with a filter of (objectClass=*). However, this is useless if you specify the DN, because the schema object can only be constructed if the search requests some operational attributes. This is also useless if you don't specify the DN and there is a subschemaSubentry attribute in the root DSE, because the filter is wrong (see RFC 2251 section 3.2.2, last para.) It's probably also useless in the <cn=schema> case, though that case seems to be a band-aid for broken versions of a particular server (Netscape?) and so all bets are probably off on that one's behaviour ;-) So the code's kind of trying to do two different things (reading a subentry and reading an entry) and failing at both. Here's what I think this code should do. schema ( [ dn => DN ] ) If a DN is passed, return a Net::LDAP::Schema object using the subschema retrieved from the objectClasses and attributeTypes operational attributes from that entry (specifically entry, *not* subentry.) If a DN is not specified, return a Net::LDAP::Schema object using the objectClasses and attributeTypes held in the subentry (again, specifically subentry, *not* entry) referenced by one of the values from the Root DSE's subschemaSubentry attribute. If the Root DSE doesn't contain a subschemaSubentry attribute, try using the DN of <cn=schema> for compatibility with some broken directory servers. I'm attaching some diffs against Net::LDAP 0.20 which implements this behaviour. The line offsets are probably a bit out too because I've been experimenting with some other local changes. Sigh. Anyway, sorry it isn't against a clean 0.22, but the guts of the change are: In schema() add a $filter variable and set it depending on the existence of $arg{'dn'}; In schema() set the attrs array when reading the subschema to include the necessary operational attributes; In root_dse() set the attrs array when reading the Root DSE to include all the standard (RFC 2251) operational attributes. I suppose I must get around to installing 0.22 at some point :-) Cheers, Chris |
From: Kurt D. Z. <Ku...@Op...> - 2001-01-29 18:55:32
|
My suggestion is to have three routines: subschema( targetDN ) which reads the subschema contained in the entry (or subentry) named by the DN. This would do a base search of the DN with the filter (objectClass=subschema) and specifically request the return of attribute types describing the schema elements. subschemasubentry( targetDN ) which returns the DN contained as a value of the subschemaSubentry attribute type within the entry (or subentry) named by the DN. Would return error if multiple values of subschemasubentry exist (subschemasubentry is a single valued attributed type). schema( DN ) [named this for historical purposes] which is a basically a shortcut for subschema( subschemasubentry( targetDN ) ) Note this would return an error if the root DSE subschemasubentry contained multiple values. This is a FEATURE as the user needs to select the correct one manually to obtain the appropriate schema. Kurt At 06:02 PM 1/29/01 +0000, Chris Ridd wrote: >I think the schema method of the Net::LDAP class is fairly broken. It isn't >documented, either :-) > >Here's my take on the existing behaviour: > >schema ( [ dn => DN ] ) > >DN is an optional distinguished name. If not present, the method will use a >random DN from the Root DSE's subschemaSubentry attribute. If this >attribute is not present, the method will try <cn=schema>. > >It then tries to do a base object search of that DN with a filter of >(objectClass=*). > >However, this is useless if you specify the DN, because the schema object >can only be constructed if the search requests some operational attributes. > >This is also useless if you don't specify the DN and there is a >subschemaSubentry attribute in the root DSE, because the filter is wrong >(see RFC 2251 section 3.2.2, last para.) > >It's probably also useless in the <cn=schema> case, though that case seems >to be a band-aid for broken versions of a particular server (Netscape?) and >so all bets are probably off on that one's behaviour ;-) > >So the code's kind of trying to do two different things (reading a subentry >and reading an entry) and failing at both. > >Here's what I think this code should do. > >schema ( [ dn => DN ] ) > > If a DN is passed, return a Net::LDAP::Schema object using the subschema >retrieved from the objectClasses and attributeTypes operational attributes >from that entry (specifically entry, *not* subentry.) > > If a DN is not specified, return a Net::LDAP::Schema object using the >objectClasses and attributeTypes held in the subentry (again, specifically >subentry, *not* entry) referenced by one of the values from the Root DSE's >subschemaSubentry attribute. If the Root DSE doesn't contain a >subschemaSubentry attribute, try using the DN of <cn=schema> for >compatibility with some broken directory servers. > >I'm attaching some diffs against Net::LDAP 0.20 which implements this >behaviour. The line offsets are probably a bit out too because I've been >experimenting with some other local changes. Sigh. Anyway, sorry it isn't >against a clean 0.22, but the guts of the change are: > >In schema() add a $filter variable and set it depending on the existence of >$arg{'dn'}; > >In schema() set the attrs array when reading the subschema to include the >necessary operational attributes; > >In root_dse() set the attrs array when reading the Root DSE to include all >the standard (RFC 2251) operational attributes. > >I suppose I must get around to installing 0.22 at some point :-) > >Cheers, > >Chris |
From: Kurt D. Z. <Ku...@Op...> - 2001-01-29 19:19:14
|
Edited for clarity: At 10:54 AM 1/29/01 -0800, Kurt D. Zeilenga wrote: >My suggestion is to have three routines: > >subschema( targetDN ) which reads the subschema contained in the >entry (or subentry) named by the targetDN. This would do a base >search of the targetDN with the filter (objectClass=subschema) and >specifically request the return of attribute types describing >the schema elements. > >subschemasubentry( targetDN ) which returns the DN contained >as a value of the subschemaSubentry attribute type within >the entry (or subentry) named by the targetDN. Would return error >if multiple values of subschemasubentry exist (subschemasubentry >is a single valued attributed type). > >schema( DN ) [named this for historical purposes] which is >a basically a shortcut for > subschema( subschemasubentry( targetDN ) ) > >Note this would return an error if the root DSE subschemasubentry >contained multiple values. This is a FEATURE as the user needs >to select the correct one manually to obtain the appropriate >schema. > >Kurt > > >At 06:02 PM 1/29/01 +0000, Chris Ridd wrote: >>I think the schema method of the Net::LDAP class is fairly broken. It isn't >>documented, either :-) >> >>Here's my take on the existing behaviour: >> >>schema ( [ dn => DN ] ) >> >>DN is an optional distinguished name. If not present, the method will use a >>random DN from the Root DSE's subschemaSubentry attribute. If this >>attribute is not present, the method will try <cn=schema>. >> >>It then tries to do a base object search of that DN with a filter of >>(objectClass=*). >> >>However, this is useless if you specify the DN, because the schema object >>can only be constructed if the search requests some operational attributes. >> >>This is also useless if you don't specify the DN and there is a >>subschemaSubentry attribute in the root DSE, because the filter is wrong >>(see RFC 2251 section 3.2.2, last para.) >> >>It's probably also useless in the <cn=schema> case, though that case seems >>to be a band-aid for broken versions of a particular server (Netscape?) and >>so all bets are probably off on that one's behaviour ;-) >> >>So the code's kind of trying to do two different things (reading a subentry >>and reading an entry) and failing at both. >> >>Here's what I think this code should do. >> >>schema ( [ dn => DN ] ) >> >> If a DN is passed, return a Net::LDAP::Schema object using the subschema >>retrieved from the objectClasses and attributeTypes operational attributes >>from that entry (specifically entry, *not* subentry.) >> >> If a DN is not specified, return a Net::LDAP::Schema object using the >>objectClasses and attributeTypes held in the subentry (again, specifically >>subentry, *not* entry) referenced by one of the values from the Root DSE's >>subschemaSubentry attribute. If the Root DSE doesn't contain a >>subschemaSubentry attribute, try using the DN of <cn=schema> for >>compatibility with some broken directory servers. >> >>I'm attaching some diffs against Net::LDAP 0.20 which implements this >>behaviour. The line offsets are probably a bit out too because I've been >>experimenting with some other local changes. Sigh. Anyway, sorry it isn't >>against a clean 0.22, but the guts of the change are: >> >>In schema() add a $filter variable and set it depending on the existence of >>$arg{'dn'}; >> >>In schema() set the attrs array when reading the subschema to include the >>necessary operational attributes; >> >>In root_dse() set the attrs array when reading the Root DSE to include all >>the standard (RFC 2251) operational attributes. >> >>I suppose I must get around to installing 0.22 at some point :-) >> >>Cheers, >> >>Chris |
From: Chris R. <chr...@me...> - 2001-01-30 10:29:13
Attachments:
ldap-schema.diffs
|
"Kurt D. Zeilenga" <Ku...@Op...> wrote: > Edited for clarity: > > At 10:54 AM 1/29/01 -0800, Kurt D. Zeilenga wrote: >> My suggestion is to have three routines: >> >> subschema( targetDN ) which reads the subschema contained in the >> entry (or subentry) named by the targetDN. This would do a base >> search of the targetDN with the filter (objectClass=subschema) and >> specifically request the return of attribute types describing >> the schema elements. >> >> subschemasubentry( targetDN ) which returns the DN contained >> as a value of the subschemaSubentry attribute type within >> the entry (or subentry) named by the targetDN. Would return error >> if multiple values of subschemasubentry exist (subschemasubentry >> is a single valued attributed type). >> >> schema( DN ) [named this for historical purposes] which is >> a basically a shortcut for >> subschema( subschemasubentry( targetDN ) ) >> >> Note this would return an error if the root DSE subschemasubentry >> contained multiple values. This is a FEATURE as the user needs >> to select the correct one manually to obtain the appropriate >> schema. >> >> Kurt Thanks for the comments. In fact, my change of yesterday is incorrect because it accidentally used the X.500 subschema operational attributes instead of the LDAP ones. (In X.500 attributeTypes and objectClasses etc are operational attributes on every entry.) Your suggested API looks sensible. It permits caching of schema objects, which is a Good Thing as they're reasonably expensive to keep transferring from the directory and parsing in the client. They're also fairly large objects to have to keep creating :-) Here's a revised patch. It implements a cache which appeared to work in my test. I'm not entirely certain what the desired semantics of the old subschema() method were (this was probably apparent from my previous message :-), so have left that method alone. The cache is keyed on subentry DN, and includes a timestamp which is either the subentry's modifyTimestamp (if it has one) or createTimestamp (if it has one). It needs migrating to the 0.22 API, but that's fairly trivial. There's a minor problem because the code 'knows' what attributes the Net::LDAP::Schema class requires, but that's fixable too. Cheers, Chris |
From: Clif H. <cl...@di...> - 2001-01-31 01:53:39
|
> > I think the schema method of the Net::LDAP class is fairly broken. It isn't > documented, either :-) I agreed it is not documented, we can fix that. > > Here's my take on the existing behaviour: > > schema ( [ dn => DN ] ) > > DN is an optional distinguished name. If not present, the method will use a > random DN from the Root DSE's subschemaSubentry attribute. If this > attribute is not present, the method will try <cn=schema>. > > It then tries to do a base object search of that DN with a filter of > (objectClass=*). > > However, this is useless if you specify the DN, because the schema object > can only be constructed if the search requests some operational attributes. > > This is also useless if you don't specify the DN and there is a > subschemaSubentry attribute in the root DSE, because the filter is wrong > (see RFC 2251 section 3.2.2, last para.) > > It's probably also useless in the <cn=schema> case, though that case seems > to be a band-aid for broken versions of a particular server (Netscape?) and > so all bets are probably off on that one's behaviour ;-) I am going to have to take issue with the above paragraph, I am using .22. I have used this on my x.500 servers, thru the ldap interface, works fine. I have used this on my Netscape LDAP servers, works fine. I am 99% sure that I have used this on my Exchange servers and that it worked fine. This is one gross schema! I know I have tried this on a MS Active Directory but I do not remember if it worked correctly. IMO if cn=schema is broken, it has the strange habit of returning correct data. > > So the code's kind of trying to do two different things (reading a subentry > and reading an entry) and failing at both. > > Here's what I think this code should do. > > schema ( [ dn => DN ] ) > > If a DN is passed, return a Net::LDAP::Schema object using the subschema > retrieved from the objectClasses and attributeTypes operational attributes > from that entry (specifically entry, *not* subentry.) > > If a DN is not specified, return a Net::LDAP::Schema object using the > objectClasses and attributeTypes held in the subentry (again, specifically > subentry, *not* entry) referenced by one of the values from the Root DSE's > subschemaSubentry attribute. If the Root DSE doesn't contain a > subschemaSubentry attribute, try using the DN of <cn=schema> for > compatibility with some broken directory servers. > I believe the RFC states MAY contain a subschemaSubentry attribute. > I'm attaching some diffs against Net::LDAP 0.20 which implements this > behaviour. The line offsets are probably a bit out too because I've been > experimenting with some other local changes. Sigh. Anyway, sorry it isn't > against a clean 0.22, but the guts of the change are: > > In schema() add a $filter variable and set it depending on the existence of > $arg{'dn'}; > > In schema() set the attrs array when reading the subschema to include the > necessary operational attributes; > > In root_dse() set the attrs array when reading the Root DSE to include all > the standard (RFC 2251) operational attributes. > > I suppose I must get around to installing 0.22 at some point :-) > > Cheers, > > Chris Later, Clif Harden c-h...@ti... |
From: Chris R. <chr...@me...> - 2001-01-31 12:34:01
|
Clif Harden <cl...@di...> wrote: > IMO if cn=schema is broken, it has the strange habit of returning correct > data. I think it is very much a quick hack for a specific server. There's nothing in *any* RFC requiring subschema to be stored at <cn=schema>. Perhaps some other servers are trying to be compatible with the first server that used <cn=schema>. I insist (!) that it is a fluke that it works for you :-) > I believe the RFC states MAY contain a subschemaSubentry attribute. Well, section 3.4 of RFC 2251 says "If the server masters directory entries under one or more schema rules, there may be any number of values of the subschemaSubentry attribute in the root DSE.". Since you can't have an attribute with zero values, I would read this as saying the attribute may have more than one value. But this is arguable. (Also note the direct conflict between this part of 2251 and 2252 section 5.1.5, the former says the attribute called subschemaSubentry is multi-valued, and the latter where it says the subschemaSubentry is single-valued. Both interpretations make sense in their own context, but unfortunately the RFC editors chose the same name for both attributes.) It definitely isn't the best way to locate any subschema held on a server. Cheers, Chris |
From: Kurt D. Z. <Ku...@Op...> - 2001-01-31 15:25:54
|
It is widely known that the Root DSE subschema mechanism described in RFC 2251 is seriously broken. This approach should be avoided. (I suspect this approach to be eliminated from the specification). If you want discover the subschema controlling a particular entry, obtain the subschema from the DN contained in that entry's subschemaSubentry attribute. If adding an entry, fetch the schema controlling the entry's parent to be. This approach should work on all LDAPv3 servers implementing subschema discovery. I note that the IETF LDAPbis WG is working on a revision of the LDAPv3 specification. I encourage all those interested in producing an LDAPv3 Draft Standard to get involved. http://www.ietf.org/html.charters/ldapbis-charter.html |
From: Clif H. <cl...@di...> - 2001-01-31 16:18:08
|
> > It is widely known that the Root DSE subschema mechanism described > in RFC 2251 is seriously broken. This approach should be avoided. > (I suspect this approach to be eliminated from the specification). > > If you want discover the subschema controlling a particular > entry, obtain the subschema from the DN contained in that entry's > subschemaSubentry attribute. If adding an entry, fetch the schema This is where part of the problem lies, according to RFC 2251 3.2.1 subschemaSubentry is a MAY contain attribute. Many directory servers do not use subschemaSubentry, whether this is right or wrong engineering practice does not matter because it is legal according to the RFC. Maybe someone should work with the IETF to make subschemaSubentry a MUST contain attribute. Personally I think it should be a MUST contain attribute. > controlling the entry's parent to be. This approach should work on > all LDAPv3 servers implementing subschema discovery. > > I note that the IETF LDAPbis WG is working on a revision of > the LDAPv3 specification. I encourage all those interested > in producing an LDAPv3 Draft Standard to get involved. > http://www.ietf.org/html.charters/ldapbis-charter.html > > Regards, Clif Harden c-h...@ti... |
From: Chris R. <chr...@me...> - 2001-01-31 16:40:19
|
Clif Harden <cl...@di...> wrote: >> >> It is widely known that the Root DSE subschema mechanism described >> in RFC 2251 is seriously broken. This approach should be avoided. >> (I suspect this approach to be eliminated from the specification). >> >> If you want discover the subschema controlling a particular >> entry, obtain the subschema from the DN contained in that entry's >> subschemaSubentry attribute. If adding an entry, fetch the schema > > > This is where part of the problem lies, according to RFC 2251 > 3.2.1 subschemaSubentry is a MAY contain attribute. Many directory > servers do not use subschemaSubentry, whether this is right or wrong > engineering practice does not matter because it is legal according > to the RFC. > > Maybe someone should work with the IETF to make subschemaSubentry a > MUST contain attribute. Personally I think it should be a MUST contain > attribute. (To clarify for those who don't have RFC 2251 open whilst reading this thread, that section defines the operational attributes on each entry, *not* the attributes in the root DSE.) Yeah it should probably be a MUST, but clients must never expect to be able to read it because there might be access controls in place which prevent this. Cheers, Chris |
From: Clif H. <cl...@di...> - 2001-01-31 17:15:22
|
> > Clif Harden <cl...@di...> wrote: > >> > >> It is widely known that the Root DSE subschema mechanism described > >> in RFC 2251 is seriously broken. This approach should be avoided. > >> (I suspect this approach to be eliminated from the specification). > >> > >> If you want discover the subschema controlling a particular > >> entry, obtain the subschema from the DN contained in that entry's > >> subschemaSubentry attribute. If adding an entry, fetch the schema > > > > > > This is where part of the problem lies, according to RFC 2251 > > 3.2.1 subschemaSubentry is a MAY contain attribute. Many directory > > servers do not use subschemaSubentry, whether this is right or wrong > > engineering practice does not matter because it is legal according > > to the RFC. > > > > Maybe someone should work with the IETF to make subschemaSubentry a > > MUST contain attribute. Personally I think it should be a MUST contain > > attribute. > > (To clarify for those who don't have RFC 2251 open whilst reading this > thread, that section defines the operational attributes on each entry, > *not* the attributes in the root DSE.) Due to Kurt's use of "particular entry" I took this to mean any entry in the DIT besides the rootDSE. > > Yeah it should probably be a MUST, but clients must never expect to be able > to read it because there might be access controls in place which prevent > this. Very true statement about access controls, we put access controls on our operational attributes. > > Cheers, > > Chris > Later, Clif Harden c-h...@ti... |
From: Chris R. <chr...@me...> - 2001-01-31 17:22:01
|
Clif Harden <cl...@di...> wrote: > Due to Kurt's use of "particular entry" I took this to mean any > entry in the DIT besides the rootDSE. It's all very confusing :-) Cheers, Chris |
From: Jim H. <ha...@us...> - 2001-01-31 16:50:21
|
I would like to see the dump method for entries made smarter about binary values of attributes. Right now, it just dumps them as regular characters which messes up terminal emulators if the wrong values come across. the ldapsearch command on Solaris shows a value of NOT ASCII for them, which is much friendlier. --Jim Harle |
From: Clif H. <cl...@di...> - 2001-01-31 17:26:26
|
> > I would like to see the dump method for entries made smarter about binary > values of attributes. Right now, it just dumps them as regular characters > which messes up terminal emulators if the wrong values come across. the > ldapsearch command on Solaris shows a value of NOT ASCII for them, which > is much friendlier. > > --Jim Harle > What I do with the binary attributes is base64 encode them before dumping them to a the screen or file. This fixes the problem of crashing terminal emulators. Later, Clif Harden |
From: Chris R. <chr...@me...> - 2001-01-31 17:44:37
|
Jim Harle <ha...@us...> wrote: > I would like to see the dump method for entries made smarter about binary > values of attributes. Right now, it just dumps them as regular characters > which messes up terminal emulators if the wrong values come across. the > ldapsearch command on Solaris shows a value of NOT ASCII for them, which > is much friendlier. Net::LDAP does not use the schema information in any way at present. This is both good (lean and mean and it doesn't mess around with stuff) and bad (sometimes confusing behaviour.) So it currently cannot tell what is a 'binary' attribute. I guess by binary attribute you mean 'human-readable', as per the table in section 4.3.2 of RFC 2252, and not just those attributes with binary AttributeDescriptions. Or do you just mean 'printable using the current display device'? I have some diffs which are probably broken ATM which changes this. But it also changes the existing value API. IIRC I changed it so that the $ldap object gets a useSchema() method, which takes a Net::LDAP::Schema argument. When this is used, the new value API gets switched in. The new value API is roughly this: Net::LDAP::Entry->get() returns an instance of Net::LDAP::Attribute. Net::LDAP::Attribute->type() returns the attribute type (name) Net::LDAP::Attribute->values() returns an array of Net::LDAP::Value objects. Net::LDAP::Value->string() returns undef for an attribute which is not human-readable, or the string if it is Net::LDAP::Value->octets() always returns the raw bytes received from the server Net::LDAP::Value->description() returns the AttributeDescription eg "binary" It's all fairly logical IMO, but it involves several extra method calls when accessing values which could be a bad thing from a performance point of view. There about a million (slight exaggeration, actually 116 :-) subclasses of Net::LDAP::Value implementing syntax handlers for all the known syntaxes. These syntax handlers can do things like 'explode' their values into pieces, which is useful for values of DN syntax for instance. They also know about values with "binary" AttributeDescriptions. Is it worth persevering with these schema changes? It provides you with your desired semantics in a clean way, and it doesn't lose the current means of accessing the 'raw' data, which I find an attractive feature of Net::LDAP. (Though it does this with a different interface, natch.) I've got bogged down in the syntax handlers, incidentally. They're seriously boring to write and there are a lot of them. Cheers, Chris |
From: Jim H. <ha...@us...> - 2001-01-31 17:59:00
|
Thanks for requesting clarification of my language. To be more precise, I would like to see Net::LDAP::Entry->dump() (or possible a variant like asciidump() ) recognize attibute values have any bytes whose values are outside the range 32-127 base 10. For such attributes it would display something like "NOT ASCII" as ldapsearch does or "(NOT PRINTABLE)" or something similar. I am not looking for a change in the API, only what is displayed. --Jim Harle On Wed, 31 Jan 2001, Chris Ridd wrote: > Jim Harle <ha...@us...> wrote: > > I would like to see the dump method for entries made smarter about binary > > values of attributes. Right now, it just dumps them as regular characters > > which messes up terminal emulators if the wrong values come across. the > > ldapsearch command on Solaris shows a value of NOT ASCII for them, which > > is much friendlier. > > Net::LDAP does not use the schema information in any way at present. This > is both good (lean and mean and it doesn't mess around with stuff) and bad > (sometimes confusing behaviour.) > > So it currently cannot tell what is a 'binary' attribute. I guess by binary > attribute you mean 'human-readable', as per the table in section 4.3.2 of > RFC 2252, and not just those attributes with binary AttributeDescriptions. > Or do you just mean 'printable using the current display device'? > > I have some diffs which are probably broken ATM which changes this. But it > also changes the existing value API. > > IIRC I changed it so that the $ldap object gets a useSchema() method, which > takes a Net::LDAP::Schema argument. When this is used, the new value API > gets switched in. > > The new value API is roughly this: > > Net::LDAP::Entry->get() returns an instance of Net::LDAP::Attribute. > Net::LDAP::Attribute->type() returns the attribute type (name) > Net::LDAP::Attribute->values() returns an array of Net::LDAP::Value objects. > Net::LDAP::Value->string() returns undef for an attribute which is not > human-readable, or the string if it is > Net::LDAP::Value->octets() always returns the raw bytes received from the > server > Net::LDAP::Value->description() returns the AttributeDescription eg "binary" > > It's all fairly logical IMO, but it involves several extra method calls > when accessing values which could be a bad thing from a performance point > of view. > > There about a million (slight exaggeration, actually 116 :-) subclasses of > Net::LDAP::Value implementing syntax handlers for all the known syntaxes. > These syntax handlers can do things like 'explode' their values into > pieces, which is useful for values of DN syntax for instance. They also > know about values with "binary" AttributeDescriptions. > > Is it worth persevering with these schema changes? It provides you with > your desired semantics in a clean way, and it doesn't lose the current > means of accessing the 'raw' data, which I find an attractive feature of > Net::LDAP. (Though it does this with a different interface, natch.) > > I've got bogged down in the syntax handlers, incidentally. They're > seriously boring to write and there are a lot of them. > > Cheers, > > Chris > > |
From: Kurt D. Z. <Ku...@Op...> - 2001-01-31 18:03:41
|
I'd suggest that the dump method produce LDIF and make use of the base64 form as appropriate (non-printable characters, leading/trailing spaces, etc.). Producing LDIF requires no knowledge of schema. Kurt At 05:43 PM 1/31/01 +0000, Chris Ridd wrote: >Jim Harle <ha...@us...> wrote: >> I would like to see the dump method for entries made smarter about binary >> values of attributes. Right now, it just dumps them as regular characters >> which messes up terminal emulators if the wrong values come across. the >> ldapsearch command on Solaris shows a value of NOT ASCII for them, which >> is much friendlier. > >Net::LDAP does not use the schema information in any way at present. This >is both good (lean and mean and it doesn't mess around with stuff) and bad >(sometimes confusing behaviour.) > >So it currently cannot tell what is a 'binary' attribute. I guess by binary >attribute you mean 'human-readable', as per the table in section 4.3.2 of >RFC 2252, and not just those attributes with binary AttributeDescriptions. >Or do you just mean 'printable using the current display device'? > >I have some diffs which are probably broken ATM which changes this. But it >also changes the existing value API. > >IIRC I changed it so that the $ldap object gets a useSchema() method, which >takes a Net::LDAP::Schema argument. When this is used, the new value API >gets switched in. > >The new value API is roughly this: > >Net::LDAP::Entry->get() returns an instance of Net::LDAP::Attribute. >Net::LDAP::Attribute->type() returns the attribute type (name) >Net::LDAP::Attribute->values() returns an array of Net::LDAP::Value objects. >Net::LDAP::Value->string() returns undef for an attribute which is not >human-readable, or the string if it is >Net::LDAP::Value->octets() always returns the raw bytes received from the >server >Net::LDAP::Value->description() returns the AttributeDescription eg "binary" > >It's all fairly logical IMO, but it involves several extra method calls >when accessing values which could be a bad thing from a performance point >of view. > >There about a million (slight exaggeration, actually 116 :-) subclasses of >Net::LDAP::Value implementing syntax handlers for all the known syntaxes. >These syntax handlers can do things like 'explode' their values into >pieces, which is useful for values of DN syntax for instance. They also >know about values with "binary" AttributeDescriptions. > >Is it worth persevering with these schema changes? It provides you with >your desired semantics in a clean way, and it doesn't lose the current >means of accessing the 'raw' data, which I find an attractive feature of >Net::LDAP. (Though it does this with a different interface, natch.) > >I've got bogged down in the syntax handlers, incidentally. They're >seriously boring to write and there are a lot of them. > >Cheers, > >Chris |
From: Chris R. <chr...@me...> - 2001-01-31 18:08:20
|
"Kurt D. Zeilenga" <Ku...@Op...> wrote: > I'd suggest that the dump method produce LDIF and make use of the > base64 form as appropriate (non-printable characters, leading/trailing > spaces, etc.). Producing LDIF requires no knowledge of schema. > > Kurt There already are LDIF modules in Net::LDAP. Cheers, Chris |
From: Chris R. <chr...@me...> - 2001-01-31 18:13:33
|
"Kurt D. Zeilenga" <Ku...@Op...> wrote: > Producing LDIF requires no knowledge of schema. It does if you have entries obtained via LDAPv2, because you won't know which values need to be converted to UTF-8, which of course LDIF requires. Cheers, Chris |
From: Kurt D. Z. <Ku...@Op...> - 2001-01-31 18:47:26
|
At 06:13 PM 1/31/01 +0000, Chris Ridd wrote: >"Kurt D. Zeilenga" <Ku...@Op...> wrote: >> Producing LDIF requires no knowledge of schema. > >It does if you have entries obtained via LDAPv2, because you won't know >which values need to be converted to UTF-8, which of course LDIF requires. An LDIF engine requires no knowledge of schema. Valid LDIFv1 (for LDAPv2 and LDAPv3) can be produce solely by examining the values to be represented and then to present those values in one of the allowed forms as demonstrated by net::LDAP LDIF's module. I personally think the entry dump method should just use the LDIF module... Kurt |
From: Chris R. <chr...@me...> - 2001-02-01 11:23:03
|
"Kurt D. Zeilenga" <Ku...@Op...> wrote: > At 06:13 PM 1/31/01 +0000, Chris Ridd wrote: >> "Kurt D. Zeilenga" <Ku...@Op...> wrote: >>> Producing LDIF requires no knowledge of schema. >> >> It does if you have entries obtained via LDAPv2, because you won't know >> which values need to be converted to UTF-8, which of course LDIF >> requires. > > An LDIF engine requires no knowledge of schema. Valid LDIFv1 (for > LDAPv2 and LDAPv3) can be produce solely by examining the values > to be represented and then to present those values in one of the > allowed forms as demonstrated by net::LDAP LDIF's module. I might be wrong, but I can't see how you can render an LDAPv2 attribute called say 'foo' with a value containing an arbitrary string of octets, into LDIF. If foo is a DirectoryString (or DN or RDN), then the value *must* be UTF-8 (point 7 in the "Notes" section of RFC 2849). But you don't know it's a DirectoryString/DN/RDN, and if you guessed it was you'd then have to guess the character set it was encoded in. Given that most LDAPv2 servers get this completely wrong (no T.61 support), this is a problem. If they use T.61 correctly then I agree this conversion is possible. [Aside: there aren't any freely available T.61 <-> anything-else converters are there?] If foo isn't a DirectoryString or DN or RDN, then I think you can get away with 'foo:: <base64 value>'. So at the very least I think you need to know enough schema to know that attributes are DirectoryStrings/DNs/RDNs or not, and then have enough faith in the server's notion of LDAPv2 character sets. Or have I got this wrong? > I personally think the entry dump method should just use > the LDIF module... Hey, we agree on something! :-) > Kurt > Cheers, Chris |
From: Kurt D. Z. <Ku...@Op...> - 2001-02-01 14:42:33
|
At 11:22 AM 2/1/01 +0000, Chris Ridd wrote: >Or have I got this wrong? Yes. A value presented in LDIF MUST have the same value when extracted from LDIF. Values should not be altered by LDIF engines on input or output. LDIF engines encode values, they don't alter values (hence no syntax information is needed). If the value is presentable directly, without any alteration, as a SAFE-STRING form (regardless of the values actual syntax), then it may be presented using this form. Otherwise the value is presented in base64 form. Note: In regards to DNs, the LDIF comment only applies to the "dn:". Please note that both versions of the protocol restricts LDAPDN to a subsets of UTF-8. In particular, LDAPv2 restricts LDAPDN values to IA5 (RFC 1777, Section 4, top of page 4). Kurt |
From: Chris R. <chr...@me...> - 2001-02-01 15:48:52
|
"Kurt D. Zeilenga" <Ku...@Op...> wrote: > At 11:22 AM 2/1/01 +0000, Chris Ridd wrote: >> Or have I got this wrong? > > Yes. A value presented in LDIF MUST have the same value when > extracted from LDIF. Values should not be altered by LDIF > engines on input or output. LDIF engines encode values, they > don't alter values (hence no syntax information is needed). The 7th "Note" says different: "7. Distinguished names, relative distinguished names, and attribute values of DirectoryString syntax must be valid UTF-8 strings. Implementations that read LDIF may interpret files in which these entities are stored in some other character set encoding, but implementations must not generate LDIF content which does not contain valid UTF-8 data." Note the must not in the last part. > If the value is presentable directly, without any alteration, > as a SAFE-STRING form (regardless of the values actual syntax), > then it may be presented using this form. Otherwise the > value is presented in base64 form. value-spec = ":" ( FILL 0*1(SAFE-STRING) / ":" FILL (BASE64-STRING) / "<" FILL url) ; See notes 7 and 8, below Hm, I think you're saying that the second form of value-spec doesn't have to be legal UTF-8 once base64-decoded. That makes sense, as that's how you'd normally include things like jpegPhotos. I guess this also means that an LDIF file saved using an LDAPv2 entry can only then be *safely* loaded back over an LDAPv2 connection? That would be because there are valid LDAPv2 strings that actually use T.61, but are also valid UTF-8 byte sequences for *different* characters. Hence the comment at the start of the second sentence of note 7 I suppose. > Note: In regards to DNs, the LDIF comment only applies to the > "dn:". Please note that both versions of the protocol restricts > LDAPDN to a subsets of UTF-8. In particular, LDAPv2 restricts I don't see where the RFC imposes *that* restriction. So I recant. You're right, however the LDIF reader has to pretty careful accepting LDIF files produced from LDAPv2 UAs. Cheers, Chris |
From: Kurt D. Z. <Ku...@Op...> - 2001-02-01 16:37:16
|
I believe that the RFC could stand some clarification. It's only LDIFv1, only a Proposed Standard. So that's to be expected. One thing I do note, that in the context of RFC 2849, LDAP is LDAPv3 [RFC2251]. LDIFv1 use with LDAPv2 can be (and probably should be) viewed as an unspecified extension. At 03:48 PM 2/1/01 +0000, Chris Ridd wrote: >I guess this also means that an LDIF file saved using an LDAPv2 entry can >only then be *safely* loaded back over an LDAPv2 connection? Yes, LDIF does not address protocol version differences. LDAPv2 is LDAPv2, LDAPv3 is LDAPv3, mixing is dangerous. I wrote an I-D detailing some of the version differences you might be interested in reading draft-zeilenga-ldapbis-vd-00.txt [which I mean to revise shortly]. I should add something about LDIF issues to this I-D... >> Note: In regards to DNs, the LDIF comment only applies to the >> "dn:". Please note that both versions of the protocol restricts >> LDAPDN to a subsets of UTF-8. In particular, LDAPv2 restricts > >I don't see where the RFC imposes *that* restriction. Most folks miss this one, but... The LDAPString is a notational convenience to indicate that, although strings of LDAPString type encode as OCTET STRING types, the legal character set in such strings is limited to the IA5 character set. LDAPDN ::= LDAPString Many implementations are quite liberal in what they accept... >So I recant. You're right, however the LDIF reader has to pretty careful >accepting LDIF files produced from LDAPv2 UAs. By reader, I assume you mean "a human reader" and not an LDIF parser. An LDIF parser should have be stupid, a human dealing with applications using different protocols needs to quite smart (or quite dumb :-). Kurt |
From: Graham B. <gb...@po...> - 2001-01-31 20:47:13
|
On Wed, Jan 31, 2001 at 05:43:52PM -0000, Chris Ridd wrote: > Jim Harle <ha...@us...> wrote: > > I would like to see the dump method for entries made smarter about binary > > values of attributes. Right now, it just dumps them as regular characters > > which messes up terminal emulators if the wrong values come across. the > > ldapsearch command on Solaris shows a value of NOT ASCII for them, which > > is much friendlier. > > Net::LDAP does not use the schema information in any way at present. This > is both good (lean and mean and it doesn't mess around with stuff) and bad > (sometimes confusing behaviour.) > > So it currently cannot tell what is a 'binary' attribute. I guess by binary > attribute you mean 'human-readable', as per the table in section 4.3.2 of > RFC 2252, and not just those attributes with binary AttributeDescriptions. > Or do you just mean 'printable using the current display device'? > > I have some diffs which are probably broken ATM which changes this. But it > also changes the existing value API. > > IIRC I changed it so that the $ldap object gets a useSchema() method, which > takes a Net::LDAP::Schema argument. When this is used, the new value API > gets switched in. > > The new value API is roughly this: > > Net::LDAP::Entry->get() returns an instance of Net::LDAP::Attribute. > Net::LDAP::Attribute->type() returns the attribute type (name) > Net::LDAP::Attribute->values() returns an array of Net::LDAP::Value objects. > Net::LDAP::Value->string() returns undef for an attribute which is not > human-readable, or the string if it is > Net::LDAP::Value->octets() always returns the raw bytes received from the > server > Net::LDAP::Value->description() returns the AttributeDescription eg "binary" > > It's all fairly logical IMO, but it involves several extra method calls > when accessing values which could be a bad thing from a performance point > of view. This all sounds good. If it can truly be made optional, or just done via additional methods to the existing ones, then we should add it to CVS > There about a million (slight exaggeration, actually 116 :-) subclasses of > Net::LDAP::Value implementing syntax handlers for all the known syntaxes. > These syntax handlers can do things like 'explode' their values into > pieces, which is useful for values of DN syntax for instance. They also > know about values with "binary" AttributeDescriptions. > > Is it worth persevering with these schema changes? It provides you with > your desired semantics in a clean way, and it doesn't lose the current > means of accessing the 'raw' data, which I find an attractive feature of > Net::LDAP. (Though it does this with a different interface, natch.) I think it is certainly worth considering, can you post the code somewhere so others can see it and discuss it. If its not too big post it to the list, otherwise send me a tar file and I will place it on the sourceforge FTP server > I've got bogged down in the syntax handlers, incidentally. They're > seriously boring to write and there are a lot of them. I can only imagine. Graham. |
From: Graham B. <gb...@po...> - 2001-01-31 20:41:00
|
The dump method on an entry was added a long time ago as a temporary measure as at that time Net::LDAP::LDIF did not exist. Either we need to get people to call Net::LDAP::LDIF(*STDERR)->write($entry) or the dump method should be changed to do that. Graham. On Wed, Jan 31, 2001 at 11:50:17AM -0500, Jim Harle wrote: > I would like to see the dump method for entries made smarter about binary > values of attributes. Right now, it just dumps them as regular characters > which messes up terminal emulators if the wrong values come across. the > ldapsearch command on Solaris shows a value of NOT ASCII for them, which > is much friendlier. > > --Jim Harle > > > > |