I see some inconsistency and possibly some misunderstanding (probably mostly at my side) on controls and criticality. This has been discussed many times, but probably slapd did not converge yet.
The specs (RFC4511) say that controls CAN be critical or non-critical. Implementations (DSAs) MAY or MAY NOT recognize controls. I see many cases; some of them are trivial, but other are not.
Let's consider a matrix, where columns represent criticality (FALSE, TRUE) and rows represent implementation (FALSE, TRUE).
implemented \ criticality | FALSE | TRUE | ----------------------------+--------+--------+ FALSE | F,F | F,T | ----------------------------+--------+--------+ TRUE | T,F | T,T | ----------------------------+--------+--------+
The specs state that if a control is not implemented, criticality determines whether the control is ignored (crit == FALSE) or the operation fails (crit == TRUE). If the control is implemented, then criticality determines whether, in case the control cannot be applied, whether the control is ignored (crit == FALSE) or the operation fails (crit == TRUE).
It should be clear that the criticality field is already overloaded: in the first case the implementation does not know the control, while in the second case it knows the control so much that it can determine whether or not it can be applied.
Let's now add a third, fuzzy dimension: control semantics. In fact, in many specs, the control semantics tries to bend the meaning of criticality towards common sense.
The specs say that all four combinations F,F; F,T; T,F; T,T are perfectly legitimate, and describe how a DSA MUST behave in all cases (or CAN, when an arbitrary behavior is legitimate).
Let me start with intuitive considerations: there are cases in which some of the four possible behaviors should (lowercase "should") not be allowed by common sense. However, this seems to violate a strict interpretation of the specs. I'll bring examples shortly. But in any case, I believe slapd should behave:
1) consistently
2) biased towards security
Examples:
a) RFC4370, proxied authorization control, states that "Clients MUST include the criticality flag and MUST set it to TRUE. Servers MUST reject any request containing a Proxy Authorization Control without a criticality flag or with the flag set to FALSE with a protocolError error." and explains why: "These requirements protect clients from submitting a request that is executed with an unintended authorization identity." This is just common sense, and is part of the control's semantics, but it disagrees with RFC4511, which is normative.
Currently, slapd does not follow this common sense advice, and allows non-critical proxied authorization requests. Please note the first "MUST" (for the DUA) and the second "MUST" (for the DSA; this is in violation of RFC4511).
b) <draft-zeilenga-ldap-dontusecopy-04> (a work in progress) states that "The criticality MUST be TRUE. There is no corresponding response control." This again is common sense, since if the control is not recognized, the operation's semantics would be totally different, as (out of sync) copies could be used instead of the original data, which is the purpose of the control. Please note the "MUST" (uppercase; for the DUA).
Currently, slapd follows the advice of this work in progress, but it'll probably need to be changed in order to be published as an RFC, because as it is now it does not comply with RFC4511 (see ITS#5785).
Note that RFC4511 provides a sentence, about what controls specifications are to provide, that sounds a little bit ambiguous: "[...] direction as to what value the sender should provide for the criticality field (note: the semantics of the criticality field are defined above should not be altered by the control's specification)".
In the end, the responsibility for getting into trouble is all placed on the DUA; the specs "are to" (lowercase, no "MUST") provide what the sender "should" (lowercase, no "SHOULD") provide for the criticality field.
I believe that this is absolutely correct, but as a DSA implementor, and not only a DUA implementor, I also believe that it is the responsibility of the DSA to make sure its integrity and security is not compromised by a poorly behaving DUA. I recommend we take two actions:
1) make sure slapd behaves consistently in all those cases, no matter whether we choose to follow the letter of RFC4511 or to tend towards the security and integrity side
2) act in direction of a modification of RFC4511 that somehow allows the semantics of a control to override those of the criticality field. I believe the criticality field is a mandatory mechanism to promote interoperability when it comes to extensions. However, there are cases where either interoperability exists or doesn't. In those cases, we cannot simply delegate security and integrity to the DUA, as the DSA is responsible of both in the end.
I believe the main consequence of allowing the DSA to reject (as something closely related to a protocol violation) a control whose criticality does not conform with that control's specification in terms of semantics would be that in the case of criticality set to FALSE two implementations would behave differently depending on whether that control is implemented or not. But this degree of arbitrarity does not differ much from that implicitly allowed by clients when they set criticality to FALSE.
Sending dontUseCopy with FALSE is an error. RFC4511 says we should return possibly outdated data in response. Receiving an error in response to an error, instead of incorrect data because the control was ignored, seems more appropriate. Not per se, but rather because it brings less harm than it could by behaving according to RFC4511.
This is my 2c (well, reading back, it looks like more than just 2 :)
p.
In short,
if the control is critical, the server cannot ignore it. It must either make use of it as prescribed or fail. if the control is non-critical, the server can choose to ignore it. However, it should only do so before making use of it as prescribed.
Some controls specifications are simply broken. No part of the 'making use of the control' should depend on the value of criticality.
-- Kurt
On Nov 1, 2008, at 9:08 AM, Pierangelo Masarati wrote:
I see some inconsistency and possibly some misunderstanding (probably mostly at my side) on controls and criticality. This has been discussed many times, but probably slapd did not converge yet.
The specs (RFC4511) say that controls CAN be critical or non-critical. Implementations (DSAs) MAY or MAY NOT recognize controls. I see many cases; some of them are trivial, but other are not.
Let's consider a matrix, where columns represent criticality (FALSE, TRUE) and rows represent implementation (FALSE, TRUE).
implemented \ criticality | FALSE | TRUE | ----------------------------+--------+--------+ FALSE | F,F | F,T | ----------------------------+--------+--------+ TRUE | T,F | T,T | ----------------------------+--------+--------+
The specs state that if a control is not implemented, criticality determines whether the control is ignored (crit == FALSE) or the operation fails (crit == TRUE). If the control is implemented, then criticality determines whether, in case the control cannot be applied, whether the control is ignored (crit == FALSE) or the operation fails (crit == TRUE).
It should be clear that the criticality field is already overloaded: in the first case the implementation does not know the control, while in the second case it knows the control so much that it can determine whether or not it can be applied.
Let's now add a third, fuzzy dimension: control semantics. In fact, in many specs, the control semantics tries to bend the meaning of criticality towards common sense.
The specs say that all four combinations F,F; F,T; T,F; T,T are perfectly legitimate, and describe how a DSA MUST behave in all cases (or CAN, when an arbitrary behavior is legitimate).
Let me start with intuitive considerations: there are cases in which some of the four possible behaviors should (lowercase "should") not be allowed by common sense. However, this seems to violate a strict interpretation of the specs. I'll bring examples shortly. But in any case, I believe slapd should behave:
consistently
biased towards security
Examples:
a) RFC4370, proxied authorization control, states that "Clients MUST include the criticality flag and MUST set it to TRUE. Servers MUST reject any request containing a Proxy Authorization Control without a criticality flag or with the flag set to FALSE with a protocolError error." and explains why: "These requirements protect clients from submitting a request that is executed with an unintended authorization identity." This is just common sense, and is part of the control's semantics, but it disagrees with RFC4511, which is normative.
Currently, slapd does not follow this common sense advice, and allows non-critical proxied authorization requests. Please note the first "MUST" (for the DUA) and the second "MUST" (for the DSA; this is in violation of RFC4511).
b) <draft-zeilenga-ldap-dontusecopy-04> (a work in progress) states that "The criticality MUST be TRUE. There is no corresponding response control." This again is common sense, since if the control is not recognized, the operation's semantics would be totally different, as (out of sync) copies could be used instead of the original data, which is the purpose of the control. Please note the "MUST" (uppercase; for the DUA).
Currently, slapd follows the advice of this work in progress, but it'll probably need to be changed in order to be published as an RFC, because as it is now it does not comply with RFC4511 (see ITS#5785).
Note that RFC4511 provides a sentence, about what controls specifications are to provide, that sounds a little bit ambiguous: "[...] direction as to what value the sender should provide for the criticality field (note: the semantics of the criticality field are defined above should not be altered by the control's specification)".
In the end, the responsibility for getting into trouble is all placed on the DUA; the specs "are to" (lowercase, no "MUST") provide what the sender "should" (lowercase, no "SHOULD") provide for the criticality field.
I believe that this is absolutely correct, but as a DSA implementor, and not only a DUA implementor, I also believe that it is the responsibility of the DSA to make sure its integrity and security is not compromised by a poorly behaving DUA. I recommend we take two actions:
- make sure slapd behaves consistently in all those cases, no matter
whether we choose to follow the letter of RFC4511 or to tend towards the security and integrity side
- act in direction of a modification of RFC4511 that somehow allows
the semantics of a control to override those of the criticality field. I believe the criticality field is a mandatory mechanism to promote interoperability when it comes to extensions. However, there are cases where either interoperability exists or doesn't. In those cases, we cannot simply delegate security and integrity to the DUA, as the DSA is responsible of both in the end.
I believe the main consequence of allowing the DSA to reject (as something closely related to a protocol violation) a control whose criticality does not conform with that control's specification in terms of semantics would be that in the case of criticality set to FALSE two implementations would behave differently depending on whether that control is implemented or not. But this degree of arbitrarity does not differ much from that implicitly allowed by clients when they set criticality to FALSE.
Sending dontUseCopy with FALSE is an error. RFC4511 says we should return possibly outdated data in response. Receiving an error in response to an error, instead of incorrect data because the control was ignored, seems more appropriate. Not per se, but rather because it brings less harm than it could by behaving according to RFC4511.
This is my 2c (well, reading back, it looks like more than just 2 :)
p.
Kurt Zeilenga wrote:
In short,
if the control is critical, the server cannot ignore it. It must either make use of it as prescribed or fail. if the control is non-critical, the server can choose to ignore it. However, it should only do so before making use of it as prescribed.
Some controls specifications are simply broken. No part of the 'making use of the control' should depend on the value of criticality.
I'm not questioning this. I'm questioning the fact that the DSA allows a client to be happy with using a control with a criticality that could endanger the data integrity or security (and, all in all, violates the control's specs).
Also, I understand that rejecting an operation because it was performed with a non-critical control is in contrast with RFC4511. Handling of dontUseCopy needs to be fixed in slapd (see ITS#5785) for conformance with RFC4511, although this would allow slapd to process a control whose criticality setting is in violation of its specs.
I'm even more concerned about handling of RFC4370, which is now handled in full conformance of RFC4511, but I'd rather prefer that slapd rejects it if requested with criticality set to FALSE.
To me, slapd should reject those cases with protocolError.
p.
On Nov 2, 2008, at 11:00 AM, Pierangelo Masarati wrote:
Kurt Zeilenga wrote:
In short, if the control is critical, the server cannot ignore it. It must either make use of it as prescribed or fail. if the control is non-critical, the server can choose to ignore it. However, it should only do so before making use of it as prescribed. Some controls specifications are simply broken. No part of the 'making use of the control' should depend on the value of criticality.
I'm not questioning this. I'm questioning the fact that the DSA allows a client to be happy with using a control with a criticality that could endanger the data integrity or security (and, all in all, violates the control's specs).
Also, I understand that rejecting an operation because it was performed with a non-critical control is in contrast with RFC4511.
Absolutely not. In making use of the control, critical or not, the server can certainly return an error. Now RFC 4511 does allow for a server to, if it can, process the operation without the control. But the server certain cannot process a part the operation with the semantics implied by the operation and a part without.
Handling of dontUseCopy needs to be fixed in slapd (see ITS#5785) for conformance with RFC4511, although this would allow slapd to process a control whose criticality setting is in violation of its specs.
The server is not responsible for odd service if client fails to mark dontUseCopy critical.
I'm even more concerned about handling of RFC4370, which is now handled in full conformance of RFC4511, but I'd rather prefer that slapd rejects it if requested with criticality set to FALSE.
The server shouldn't even consider criticality in its processing until after deciding not to make use of a control, whether to fail due or ignore the control.
To me, slapd should reject those cases with protocolError.
This kind of breaks the separation between the controls criticality processing and control processing.
I tend to prefer 'be liberal in what you accept'. However, if I were to redesign LDAP from scratch, I'd remove the concept of a non- critical control in favor of requiring the client to fall-back. At present, most clients don't provide any fall-back. But I digress.
Kurt Zeilenga wrote:
On Nov 2, 2008, at 11:00 AM, Pierangelo Masarati wrote:
Kurt Zeilenga wrote:
In short, if the control is critical, the server cannot ignore it. It must either make use of it as prescribed or fail. if the control is non-critical, the server can choose to ignore it. However, it should only do so before making use of it as prescribed. Some controls specifications are simply broken. No part of the 'making use of the control' should depend on the value of criticality.
I'm not questioning this. I'm questioning the fact that the DSA allows a client to be happy with using a control with a criticality that could endanger the data integrity or security (and, all in all, violates the control's specs).
Also, I understand that rejecting an operation because it was performed with a non-critical control is in contrast with RFC4511.
Absolutely not. In making use of the control, critical or not, the server can certainly return an error. Now RFC 4511 does allow for a server to, if it can, process the operation without the control. But the server certain cannot process a part the operation with the semantics implied by the operation and a part without.
Handling of dontUseCopy needs to be fixed in slapd (see ITS#5785) for conformance with RFC4511, although this would allow slapd to process a control whose criticality setting is in violation of its specs.
The server is not responsible for odd service if client fails to mark dontUseCopy critical.
I'm even more concerned about handling of RFC4370, which is now handled in full conformance of RFC4511, but I'd rather prefer that slapd rejects it if requested with criticality set to FALSE.
The server shouldn't even consider criticality in its processing until after deciding not to make use of a control, whether to fail due or ignore the control.
To me, slapd should reject those cases with protocolError.
This kind of breaks the separation between the controls criticality processing and control processing.
Yes. But this is a consequence of the fact that some controls' specs seem to overload the criticality flag with some additional semantics.
I tend to prefer 'be liberal in what you accept'.
I'd agree (I do, in principle) but I'd limit liberality to data integrity and security.
p.
However, if I were to redesign LDAP from scratch, I'd remove the concept of a non-critical control in favor of requiring the client to fall-back. At present, most clients don't provide any fall-back. But I digress.
On Nov 2, 2008, at 11:28 AM, Pierangelo Masarati wrote:
Kurt Zeilenga wrote:
On Nov 2, 2008, at 11:00 AM, Pierangelo Masarati wrote:
Kurt Zeilenga wrote:
In short, if the control is critical, the server cannot ignore it. It must either make use of it as prescribed or fail. if the control is non-critical, the server can choose to ignore it. However, it should only do so before making use of it as prescribed. Some controls specifications are simply broken. No part of the 'making use of the control' should depend on the value of criticality.
I'm not questioning this. I'm questioning the fact that the DSA allows a client to be happy with using a control with a criticality that could endanger the data integrity or security (and, all in all, violates the control's specs).
Also, I understand that rejecting an operation because it was performed with a non-critical control is in contrast with RFC4511.
Absolutely not. In making use of the control, critical or not, the server can certainly return an error. Now RFC 4511 does allow for a server to, if it can, process the operation without the control. But the server certain cannot process a part the operation with the semantics implied by the operation and a part without.
Handling of dontUseCopy needs to be fixed in slapd (see ITS#5785) for conformance with RFC4511, although this would allow slapd to process a control whose criticality setting is in violation of its specs.
The server is not responsible for odd service if client fails to mark dontUseCopy critical.
I'm even more concerned about handling of RFC4370, which is now handled in full conformance of RFC4511, but I'd rather prefer that slapd rejects it if requested with criticality set to FALSE.
The server shouldn't even consider criticality in its processing until after deciding not to make use of a control, whether to fail due or ignore the control.
To me, slapd should reject those cases with protocolError.
This kind of breaks the separation between the controls criticality processing and control processing.
Yes. But this is a consequence of the fact that some controls' specs seem to overload the criticality flag with some additional semantics.
Though there are certainly one or two such specifications, a spec which simply says a client MUST specify mark a particular control as critical does not create such an overload. This is because a client MUST does not impart any requirement upon the server.
-- Kurt
Kurt Zeilenga wrote:
On Nov 2, 2008, at 11:28 AM, Pierangelo Masarati wrote:
Kurt Zeilenga wrote:
On Nov 2, 2008, at 11:00 AM, Pierangelo Masarati wrote:
Kurt Zeilenga wrote:
In short, if the control is critical, the server cannot ignore it. It must either make use of it as prescribed or fail. if the control is non-critical, the server can choose to ignore it. However, it should only do so before making use of it as prescribed. Some controls specifications are simply broken. No part of the 'making use of the control' should depend on the value of criticality.
I'm not questioning this. I'm questioning the fact that the DSA allows a client to be happy with using a control with a criticality that could endanger the data integrity or security (and, all in all, violates the control's specs).
Also, I understand that rejecting an operation because it was performed with a non-critical control is in contrast with RFC4511.
Absolutely not. In making use of the control, critical or not, the server can certainly return an error. Now RFC 4511 does allow for a server to, if it can, process the operation without the control. But the server certain cannot process a part the operation with the semantics implied by the operation and a part without.
Handling of dontUseCopy needs to be fixed in slapd (see ITS#5785) for conformance with RFC4511, although this would allow slapd to process a control whose criticality setting is in violation of its specs.
The server is not responsible for odd service if client fails to mark dontUseCopy critical.
I'm even more concerned about handling of RFC4370, which is now handled in full conformance of RFC4511, but I'd rather prefer that slapd rejects it if requested with criticality set to FALSE.
The server shouldn't even consider criticality in its processing until after deciding not to make use of a control, whether to fail due or ignore the control.
To me, slapd should reject those cases with protocolError.
This kind of breaks the separation between the controls criticality processing and control processing.
Yes. But this is a consequence of the fact that some controls' specs seem to overload the criticality flag with some additional semantics.
Though there are certainly one or two such specifications, a spec which simply says a client MUST specify mark a particular control as critical does not create such an overload. This is because a client MUST does not impart any requirement upon the server.
Well, in fact the overloading occurs when the server's implementor wants to be too clever :)
Probably a good trade-off would be to add a config parameter that says: be strict about clients not using "critical" as specified, the default being the current behavior (except for dontUseCopy!). Could be "disallow" "proxiedauthz_non_critical", "dontusecopy_non_critical" and so on; "non_critical" would disallow all.
p.
Pierangelo Masarati writes:
Kurt Zeilenga wrote:
On Nov 2, 2008, at 11:00 AM, Pierangelo Masarati wrote:
Kurt Zeilenga wrote:
Some controls specifications are simply broken. No part of the 'making use of the control' should depend on the value of criticality.
Is this stated anywhere now? I seem to misremember those ldapbis discussions. E.g. this message http://www.openldap.org/lists/ietf-ldapbis/200403/msg00058.html where you say the control spec _can_ require a criticality and the server can check it. It's about this RFC 4511 statement, I think: "note: the semantics of the criticality field are defined above should not be altered by the control's specification" but I'm not sure how much that implies. Certainly it means the spec can't tell the server to e.g. ignore the criticality in a request and treat criticality as TRUE regardless.
It was not stated anywhere when those controls were written (to RFC 2251). On the contrary, RFC 2251 said control specs include: "whether the control is always noncritical, always critical, or critical at the client's option". So RFC 2251 was talking both about the criticality sent in the LDAPMessage and the one in the spec. RFC 4511 switched to the one in the message only, making the spec advisory.
In any case, when the control spec does say the result depends on criticality, the two correct options are to implement the control that way or to not implement the control at all.
The server shouldn't even consider criticality in its processing until after deciding not to make use of a control, whether to fail due or ignore the control.
Well, almost never. If a request contains several possibly-conflicting controls, "Controls with a criticality of FALSE may be ignored in order to arrive at a valid combination".
About client-provided criticality FALSE when spec says TRUE:
To me, slapd should reject those cases with protocolError.
This kind of breaks the separation between the controls criticality processing and control processing.
Yes. But this is a consequence of the fact that some controls' specs seem to overload the criticality flag with some additional semantics.
I tend to prefer 'be liberal in what you accept'.
I'd agree (I do, in principle) but I'd limit liberality to data integrity and security.
I would too. But that was a huuuge discussion which I'm still nervous about dipping my toes into again:-)
However, if I were to redesign LDAP from scratch, I'd remove the concept of a non-critical control in favor of requiring the client to fall-back. At present, most clients don't provide any fall-back. But I digress.
Another digression: If I were to redesign LDAP from scratch, I'd call it "X.500".