From be2a8e8cc8afcfa6bc5ac08efb4689c43bb94aaf Mon Sep 17 00:00:00 2001 From: Quanah Gibson-Mount <quanah@openldap.org> Date: Mon, 10 Nov 2008 22:55:48 +0000 Subject: [PATCH] ITS#5784 --- CHANGES | 1 + clients/tools/common.c | 43 ++ .../draft-masarati-ldap-whatfailed-xx.txt | 672 ++++++++++++++++++ doc/drafts/draft-masarati-ldap-whatfailed.xml | 240 +++++++ include/ldap.h | 2 + servers/slapd/backend.c | 6 + servers/slapd/controls.c | 203 +++++- servers/slapd/proto-slap.h | 7 + servers/slapd/slap.h | 9 + 9 files changed, 1166 insertions(+), 17 deletions(-) create mode 100644 doc/drafts/draft-masarati-ldap-whatfailed-xx.txt create mode 100644 doc/drafts/draft-masarati-ldap-whatfailed.xml diff --git a/CHANGES b/CHANGES index daa2c0449c..c91d6c1219 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,7 @@ OpenLDAP 2.4.13 Engineering Fixed slapd statslog printing of released entry (ITS#5775) Added slapd support for certificateListExactMatch (ITS#5700) Fixed slapd syncrepl MOD of attrs with no EQ rule (ITS#5781) + Added slapd What failed? control (ITS#5784) Fixed slapd-bdb/hdb invalid db crash (ITS#5698) Added slapd-bdb/hdb dbpagesize keyword Added slapd-bdb/hdb checksum keyword diff --git a/clients/tools/common.c b/clients/tools/common.c index 58d5e6bf49..cda39c9f8c 100644 --- a/clients/tools/common.c +++ b/clients/tools/common.c @@ -138,6 +138,9 @@ static int print_sss( LDAP *ld, LDAPControl *ctrl ); #ifdef LDAP_CONTROL_X_DEREF static int print_deref( LDAP *ld, LDAPControl *ctrl ); #endif +#ifdef LDAP_CONTROL_X_WHATFAILED +static int print_whatfailed( LDAP *ld, LDAPControl *ctrl ); +#endif static struct tool_ctrls_t { const char *oid; @@ -153,6 +156,9 @@ static struct tool_ctrls_t { { LDAP_CONTROL_SORTRESPONSE, TOOL_SEARCH, print_sss }, #ifdef LDAP_CONTROL_X_DEREF { LDAP_CONTROL_X_DEREF, TOOL_SEARCH, print_deref }, +#endif +#ifdef LDAP_CONTROL_X_WHATFAILED + { LDAP_CONTROL_X_WHATFAILED, TOOL_ALL, print_whatfailed }, #endif { NULL, 0, NULL } }; @@ -1966,6 +1972,43 @@ done:; } #endif +#ifdef LDAP_CONTROL_X_WHATFAILED +static int +print_whatfailed( LDAP *ld, LDAPControl *ctrl ) +{ + BerElement *ber; + ber_tag_t tag; + ber_len_t siz; + BerVarray bva = NULL; + + /* Create a BerElement from the berval returned in the control. */ + ber = ber_init( &ctrl->ldctl_value ); + + if ( ber == NULL ) { + return LDAP_NO_MEMORY; + } + + siz = sizeof(struct berval); + tag = ber_scanf( ber, "[M]", &bva, &siz, 0 ); + if ( tag != LBER_ERROR ) { + int i; + + tool_write_ldif( LDIF_PUT_COMMENT, " what failed:", NULL, 0 ); + + for ( i = 0; bva[i].bv_val != NULL; i++ ) { + tool_write_ldif( LDIF_PUT_COMMENT, NULL, bva[i].bv_val, bva[i].bv_len ); + } + + ldap_memfree( bva ); + } + + ber_free( ber, 1 ); + + + return 0; +} +#endif + #ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST static int print_ppolicy( LDAP *ld, LDAPControl *ctrl ) diff --git a/doc/drafts/draft-masarati-ldap-whatfailed-xx.txt b/doc/drafts/draft-masarati-ldap-whatfailed-xx.txt new file mode 100644 index 0000000000..a98c341077 --- /dev/null +++ b/doc/drafts/draft-masarati-ldap-whatfailed-xx.txt @@ -0,0 +1,672 @@ + + + +Network Working Group P. Masarati +Internet-Draft Politecnico di Milano +Intended status: Standards Track October 2008 +Expires: April 4, 2009 + + + LDAP "What Failed?" Control + draft-masarati-ldap-whatfailed.txt + +Status of this Memo + + By submitting this Internet-Draft, each author represents that any + applicable patent or other IPR claims of which he or she is aware + have been or will be disclosed, and any of which he or she becomes + aware will be disclosed, in accordance with Section 6 of BCP 79. + + Internet-Drafts are working documents of the Internet Engineering + Task Force (IETF), its areas, and its working groups. Note that + other groups may also distribute working documents as Internet- + Drafts. + + Internet-Drafts are draft documents valid for a maximum of six months + and may be updated, replaced, or obsoleted by other documents at any + time. It is inappropriate to use Internet-Drafts as reference + material or to cite them other than as "work in progress." + + The list of current Internet-Drafts can be accessed at + http://www.ietf.org/ietf/1id-abstracts.txt. + + The list of Internet-Draft Shadow Directories can be accessed at + http://www.ietf.org/shadow.html. + + This Internet-Draft will expire on April 4, 2009. + + + + + + + + + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 1] + +Internet-Draft LDAP WHATFAILED October 2008 + + +Abstract + + This document describes the LDAP "What Failed?" control. This + control allows DUAs to request, in response to a failed operation + request, the object identifier of those extensions that caused the + operation to fail. + + +Table of Contents + + 1. Background and Intended Use . . . . . . . . . . . . . . . . . 3 + 2. LDAP "What Failed?" Control . . . . . . . . . . . . . . . . . 4 + 2.1. Control Semantics . . . . . . . . . . . . . . . . . . . . 4 + 2.2. Control Request . . . . . . . . . . . . . . . . . . . . . 4 + 2.3. Control Response . . . . . . . . . . . . . . . . . . . . . 5 + 3. Implementation Notes . . . . . . . . . . . . . . . . . . . . . 6 + 4. Security Considerations . . . . . . . . . . . . . . . . . . . 7 + 5. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 8 + 5.1. Object Identifier Registration . . . . . . . . . . . . . . 8 + 6. Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . 9 + 7. References . . . . . . . . . . . . . . . . . . . . . . . . . . 10 + 7.1. Normative References . . . . . . . . . . . . . . . . . . . 10 + 7.2. Informative References . . . . . . . . . . . . . . . . . . 10 + Author's Address . . . . . . . . . . . . . . . . . . . . . . . . . 11 + Intellectual Property and Copyright Statements . . . . . . . . . . 12 + + + + + + + + + + + + + + + + + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 2] + +Internet-Draft LDAP WHATFAILED October 2008 + + +1. Background and Intended Use + + The LDAP Protocol [RFC4510] is extensible. Extensions include + controls, extended requests and extensions related to other aspects + of the protocol, for example those described in [RFC4526], [RFC4529] + and more. + + Operations may fail for different reasons. The resultCode may help + in determining the reason of a failure. The (optional) + diagnosticsMessage fields of a LDAPResponse could also be of help. + However, according to [RFC4511], implementations MUST NOT rely on the + returned values, which are simply intended to be presented as are to + human users. + + In case of failure related to the inability to process a control + marked as critical in a request, the specific resultCode + unavailableCriticalExtension is returned. In case of failure related + to an unrecognized extendedReq, the generic resultCode protocolError + is returned. Failures related to handling other extensions may + result in other generic resultCode values. + + As a consequence, DUAs may be unable to exactly determine what + extension, if any, caused a failure. The "What Failed?" control + represents a means for the DSA to inform DUAs about what specific + extensions, if any, caused an error notified by the DSA. + + The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", + "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this + document are to be interpreted as described in [RFC2119]. + + + + + + + + + + + + + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 3] + +Internet-Draft LDAP WHATFAILED October 2008 + + +2. LDAP "What Failed?" Control + +2.1. Control Semantics + + The presence of the "What Failed?" LDAP control in a LDAP request + indicates that the DUA, in case of error, wishes to receive detailed + information about what extension, if any, caused the error. + + The criticality of the control in the request SHOULD be FALSE. + According to the semantics of the criticality field as indicated in + [RFC4511], this ensures that in case the control is not recognized by + the DSA, it does not cause itself an error. + + The presence of this control in a request does not guarantee that the + DSA will return detailed information about what extensions caused an + error. Considering the requirement on the criticality of the + control, the DSA MAY simply choose to ignore the control. The DSA + MAY hide information about failure in handling an extension to + prevent disclosure of other information. The DSA MAY choose to + notify an error as soon as it is detected, instead of proceed + checking its ability to handle any other extension present in a + request. + + Implementations may choose to check the validity of extensions, + including controls, as soon as they are parsed. As a consequence, a + critical control might result in an error before thw "What Failed?" + control request is parsed. Implementations SHOULD check anyway the + presence of this control, unless they detect that the remaining part + of the request is malformed. Clients SHOULD NOT rely on any specific + ordering of controls handling when requesting the "What Failed?" + control. + + Servers implementing this technical specification SHOULD publish the + object identifier whatFailed-oid (IANA assigned; see Section 5) as a + value of the 'supportedControl' attribute [RFC4512] in their root + DSE. + +2.2. Control Request + + The controlType is whatFailed-oid (IANA assigned; see Section 5); the + controlValue MUST be absent; the criticality SHOULD be FALSE. + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 4] + +Internet-Draft LDAP WHATFAILED October 2008 + + +2.3. Control Response + + The controlType is whatFailed-oid (IANA assigned; see Section 5); the + controlValue is: + + controlValue ::= SET OF oid LDAPOID + + If the set of extension OID is empty, the control is omitted from the + response. The criticality MUST be FALSE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 5] + +Internet-Draft LDAP WHATFAILED October 2008 + + +3. Implementation Notes + + The "What Failed?" LDAP Control is implemented in OpenLDAP software + using the temporary OID 1.3.6.1.4.1.4203.666.5.17 under OpenLDAP's + experimental OID arc. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 6] + +Internet-Draft LDAP WHATFAILED October 2008 + + +4. Security Considerations + + Implementations MUST take measures to prevent the disclosure of + sensible information whenever this may result from disclosing what + extension caused an error. This can consist in excluding the OID of + specific extensions from the controlValue in the response, or in + entirely omitting the control in the response. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 7] + +Internet-Draft LDAP WHATFAILED October 2008 + + +5. IANA Considerations + +5.1. Object Identifier Registration + + It is requested that IANA register upon Standards Action an LDAP + Object Identifier for use in this technical specification. + + Subject: Request for LDAP OID Registration + Person & email address to contact for further information: + Pierangelo Masarati <ando@OpenLDAP.org> + Specification: (I-D) + Author/Change Controller: IESG + Comments: + Identifies the LDAP "What Failed?" Control request + and response + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 8] + +Internet-Draft LDAP WHATFAILED October 2008 + + +6. Acknowledgments + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 9] + +Internet-Draft LDAP WHATFAILED October 2008 + + +7. References + +7.1. Normative References + + [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate + Requirement Levels", BCP 14, RFC 2119, March 1997. + + [RFC4510] Zeilenga, K., "Lightweight Directory Access Protocol + (LDAP): Technical Specification Road Map", RFC 4510, + June 2006. + + [RFC4511] Sermersheim, J., "Lightweight Directory Access Protocol + (LDAP): The Protocol", RFC 4511, June 2006. + + [RFC4512] Zeilenga, K., "Lightweight Directory Access Protocol + (LDAP): Directory Information Models", RFC 4512, + June 2006. + +7.2. Informative References + + [RFC4526] Zeilenga, K., "Lightweight Directory Access Protocol + (LDAP) Absolute True and False Filters", RFC 4526, + June 2006. + + [RFC4529] Zeilenga, K., "Requesting Attributes by Object Class in + the Lightweight Directory Access Protocol", RFC 4529, + June 2006. + + + + + + + + + + + + + + + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 10] + +Internet-Draft LDAP WHATFAILED October 2008 + + +Author's Address + + Pierangelo Masarati + Politecnico di Milano + Dipartimento di Ingegneria Aerospaziale + via La Masa 34 + Milano 20156 + IT + + Phone: +39 02 2399 8309 + Fax: +39 02 2399 8334 + Email: ando@OpenLDAP.org + URI: http://www.aero.polimi.it/masarati/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 11] + +Internet-Draft LDAP WHATFAILED October 2008 + + +Full Copyright Statement + + Copyright (C) The IETF Trust (2008). + + This document is subject to the rights, licenses and restrictions + contained in BCP 78, and except as set forth therein, the authors + retain all their rights. + + This document and the information contained herein are provided on an + "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS + OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND + THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF + THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED + WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + + +Intellectual Property + + The IETF takes no position regarding the validity or scope of any + Intellectual Property Rights or other rights that might be claimed to + pertain to the implementation or use of the technology described in + this document or the extent to which any license under such rights + might or might not be available; nor does it represent that it has + made any independent effort to identify any such rights. Information + on the procedures with respect to rights in RFC documents can be + found in BCP 78 and BCP 79. + + Copies of IPR disclosures made to the IETF Secretariat and any + assurances of licenses to be made available, or the result of an + attempt made to obtain a general license or permission for the use of + such proprietary rights by implementers or users of this + specification can be obtained from the IETF on-line IPR repository at + http://www.ietf.org/ipr. + + The IETF invites any interested party to bring to its attention any + copyrights, patents or patent applications, or other proprietary + rights that may cover technology that may be required to implement + this standard. Please address the information to the IETF at + ietf-ipr@ietf.org. + + + + + + + + + + + +Masarati Expires April 4, 2009 [Page 12] + diff --git a/doc/drafts/draft-masarati-ldap-whatfailed.xml b/doc/drafts/draft-masarati-ldap-whatfailed.xml new file mode 100644 index 0000000000..1d8ce5e470 --- /dev/null +++ b/doc/drafts/draft-masarati-ldap-whatfailed.xml @@ -0,0 +1,240 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [ + <!ENTITY rfc2119 PUBLIC '' + 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml'> + <!ENTITY rfc4510 PUBLIC '' + 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.4510.xml'> + <!ENTITY rfc4511 PUBLIC '' + 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.4511.xml'> + <!ENTITY rfc4512 PUBLIC '' + 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.4512.xml'> + <!ENTITY rfc4526 PUBLIC '' + 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.4526.xml'> + <!ENTITY rfc4529 PUBLIC '' + 'http://xml.resource.org/public/rfc/bibxml/reference.RFC.4529.xml'> +]> + +<!-- $OpenLDAP$ --> + +<rfc category="std" ipr="full3978" docName="draft-masarati-ldap-whatfailed.txt"> + +<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?> + +<?rfc toc="yes" ?> +<?rfc symrefs="yes" ?> +<?rfc sortrefs="yes"?> +<?rfc iprnotified="no" ?> +<?rfc strict="yes" ?> + + <front> + <title abbrev='LDAP WHATFAILED'>LDAP "What Failed?" Control</title> + <author initials='P.' surname="Masarati" fullname='Pierangelo Masarati'> + <organization abbrev='Politecnico di Milano'> + Politecnico di Milano + </organization> + <address> + <postal> + <street>Dipartimento di Ingegneria Aerospaziale</street> + <street>via La Masa 34</street> + <city>Milano</city> + <code>20156</code> + <country>IT</country> + </postal> + <phone>+39 02 2399 8309</phone> + <facsimile>+39 02 2399 8334</facsimile> + <email>ando@OpenLDAP.org</email> + <uri>http://www.aero.polimi.it/masarati/</uri> + </address> + </author> + <!--date/--> + <date month='October' year='2008' /> + <abstract> + <t> +This document describes the LDAP "What Failed?" control. +This control allows DUAs to request, in response to a failed operation +request, the object identifier of those extensions that caused +the operation to fail. + </t> + </abstract> + </front> + + <middle> + <section title="Background and Intended Use"> + <t> +The LDAP Protocol <xref target="RFC4510" /> is extensible. +Extensions include controls, extended requests and extensions related +to other aspects of the protocol, for example those described in +<xref target="RFC4526" />, <xref target="RFC4529" /> and more. + </t> + + <t> +Operations may fail for different reasons. +The resultCode may help in determining the reason of a failure. +The (optional) diagnosticsMessage fields of a LDAPResponse +could also be of help. +However, according to <xref target="RFC4511" />, +implementations MUST NOT rely on the returned values, +which are simply intended to be presented as are to human users. + </t> + + <t> +In case of failure related to the inability to process a control +marked as critical in a request, the specific resultCode +unavailableCriticalExtension is returned. +In case of failure related to an unrecognized extendedReq, the generic +resultCode protocolError is returned. +Failures related to handling other extensions may result +in other generic resultCode values. + </t> + + <t> +As a consequence, DUAs may be unable to exactly determine +what extension, if any, caused a failure. +The "What Failed?" control represents a means for the DSA to inform +DUAs about what specific extensions, if any, caused an error notified +by the DSA. + </t> + + <t> +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", +"SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", +and "OPTIONAL" in this document are to be interpreted as +described in <xref target="RFC2119" />. + </t> + </section> + + <section title='LDAP "What Failed?" Control'> + <section title="Control Semantics"> + <t> +The presence of the "What Failed?" LDAP control in a LDAP request +indicates that the DUA, in case of error, wishes to receive detailed +information about what extension, if any, caused the error. + </t> + + <t> +The criticality of the control in the request SHOULD be FALSE. +According to the semantics of the criticality field as indicated +in <xref target="RFC4511" />, this ensures that in case the control +is not recognized by the DSA, it does not cause itself an error. + </t> + + <t> +The presence of this control in a request does not guarantee that the DSA +will return detailed information about what extensions caused an error. +Considering the requirement on the criticality of the control, +the DSA MAY simply choose to ignore the control. +The DSA MAY hide information about failure in handling an extension +to prevent disclosure of other information. +The DSA MAY choose to notify an error as soon as it is detected, +instead of proceed checking its ability to handle any other extension +present in a request. + </t> + + <t> +Implementations may choose to check the validity of extensions, +including controls, as soon as they are parsed. +As a consequence, a critical control might result in an error +before thw "What Failed?" control request is parsed. +Implementations SHOULD check anyway the presence of this control, +unless they detect that the remaining part of the request +is malformed. +Clients SHOULD NOT rely on any specific ordering of controls handling +when requesting the "What Failed?" control. + </t> + + <t> +Servers implementing this technical specification SHOULD publish +the object identifier whatFailed-oid (IANA assigned; +see <xref target="iana_considerations" />) as a value +of the 'supportedControl' attribute <xref target="RFC4512" /> +in their root DSE. + </t> + </section> + + <section title="Control Request"> + <t> +The controlType is whatFailed-oid (IANA assigned; +see <xref target="iana_considerations" />); +the controlValue MUST be absent; +the criticality SHOULD be FALSE. + </t> + </section> + + <section title="Control Response"> + <figure> + <preamble> +The controlType is whatFailed-oid (IANA assigned; +see <xref target="iana_considerations" />); +the controlValue is: + </preamble> + <artwork> + controlValue ::= SET OF oid LDAPOID + </artwork> + <postamble> +If the set of extension OID is empty, the control is omitted +from the response. +The criticality MUST be FALSE. + </postamble> + </figure> + </section> + </section> + + <section title="Implementation Notes"> + <t> +The "What Failed?" LDAP Control is implemented in OpenLDAP software +using the temporary OID 1.3.6.1.4.1.4203.666.5.17 under OpenLDAP's +experimental OID arc. + </t> + </section> + + <section title="Security Considerations"> + <t> +Implementations MUST take measures to prevent the disclosure +of sensible information whenever this may result from disclosing +what extension caused an error. +This can consist in excluding the OID of specific extensions from +the controlValue in the response, or in entirely omitting the control +in the response. + </t> + </section> + + <section anchor="iana_considerations" title="IANA Considerations"> + <section title="Object Identifier Registration"> + <figure> + <preamble> +It is requested that IANA register upon Standards Action an LDAP +Object Identifier for use in this technical specification. + </preamble> + <artwork> + Subject: Request for LDAP OID Registration + Person & email address to contact for further information: + Pierangelo Masarati <ando@OpenLDAP.org> + Specification: (I-D) + Author/Change Controller: IESG + Comments: + Identifies the LDAP "What Failed?" Control request + and response + </artwork> + </figure> + </section> + </section> + + <section title="Acknowledgments"> + </section> + </middle> + + <back> + <references title='Normative References'> + &rfc2119; + &rfc4510; + &rfc4511; + &rfc4512; + </references> + <references title='Informative References'> + &rfc4526; + &rfc4529; + </references> + </back> + +</rfc> diff --git a/include/ldap.h b/include/ldap.h index 99c2474723..59dd2e4539 100644 --- a/include/ldap.h +++ b/include/ldap.h @@ -323,6 +323,8 @@ typedef struct ldapcontrol { LDAP_CONTROL_X_SESSION_TRACKING ".3" /* Dereference Control (work in progress) */ #define LDAP_CONTROL_X_DEREF "1.3.6.1.4.1.4203.666.5.16" +/* "What Failed?" Control (work in progress) */ +#define LDAP_CONTROL_X_WHATFAILED "1.3.6.1.4.1.4203.666.5.17" #endif /* LDAP_DEVEL */ /* various expired works */ diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c index db3f299b61..ccbc938da5 100644 --- a/servers/slapd/backend.c +++ b/servers/slapd/backend.c @@ -946,6 +946,12 @@ backend_check_controls( case LDAP_COMPARE_FALSE: if ( !op->o_bd->be_ctrls[cid] && (*ctrls)->ldctl_iscritical ) { +#ifdef SLAP_CONTROL_X_WHATFAILED + if ( get_whatFailed( op ) ) { + char *oids[ 2 ] = { (*ctrls)->ldctl_oid, NULL }; + slap_ctrl_whatFailed_add( op, rs, oids ); + } +#endif /* RFC 4511 allows unavailableCriticalExtension to be * returned when the server is unwilling to perform * an operation extended by a recognized critical diff --git a/servers/slapd/controls.c b/servers/slapd/controls.c index f2efdd1696..496524f10a 100644 --- a/servers/slapd/controls.c +++ b/servers/slapd/controls.c @@ -48,6 +48,9 @@ static SLAP_CTRL_PARSE_FN parseValuesReturnFilter; #ifdef SLAP_CONTROL_X_SESSION_TRACKING static SLAP_CTRL_PARSE_FN parseSessionTracking; #endif +#ifdef SLAP_CONTROL_X_WHATFAILED +static SLAP_CTRL_PARSE_FN parseWhatFailed; +#endif #undef sc_mask /* avoid conflict with Irix 6.5 <sys/signal.h> */ @@ -217,6 +220,14 @@ static struct slap_control control_defs[] = { session_tracking_extops, NULL, parseSessionTracking, LDAP_SLIST_ENTRY_INITIALIZER(next) }, #endif +#ifdef SLAP_CONTROL_X_WHATFAILED + { LDAP_CONTROL_X_WHATFAILED, + (int)offsetof(struct slap_control_ids, sc_whatFailed), + SLAP_CTRL_GLOBAL|SLAP_CTRL_ACCESS|SLAP_CTRL_HIDE, + NULL, NULL, + parseWhatFailed, LDAP_SLIST_ENTRY_INITIALIZER(next) }, +#endif + { NULL, 0, 0, NULL, 0, NULL, LDAP_SLIST_ENTRY_INITIALIZER(next) } }; @@ -536,6 +547,7 @@ int slap_parse_ctrl( const char **text ) { struct slap_control *sc; + int rc = LDAP_SUCCESS; sc = find_ctrl( control->ldctl_oid ); if( sc != NULL ) { @@ -591,31 +603,29 @@ int slap_parse_ctrl( if (( sc->sc_mask & tagmask ) == tagmask ) { /* available extension */ - int rc; + if ( sc->sc_parse ) { + rc = sc->sc_parse( op, rs, control ); + assert( rc != LDAP_UNAVAILABLE_CRITICAL_EXTENSION ); - if( !sc->sc_parse ) { + } else if ( control->ldctl_iscritical ) { *text = "not yet implemented"; - return LDAP_OTHER; + rc = LDAP_OTHER; } - rc = sc->sc_parse( op, rs, control ); - if ( rc ) { - assert( rc != LDAP_UNAVAILABLE_CRITICAL_EXTENSION ); - return rc; - } - } else if( control->ldctl_iscritical ) { + } else if ( control->ldctl_iscritical ) { /* unavailable CRITICAL control */ *text = "critical extension is unavailable"; - return LDAP_UNAVAILABLE_CRITICAL_EXTENSION; + rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; } - } else if( control->ldctl_iscritical ) { + + } else if ( control->ldctl_iscritical ) { /* unrecognized CRITICAL control */ *text = "critical extension is not recognized"; - return LDAP_UNAVAILABLE_CRITICAL_EXTENSION; + rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; } - return LDAP_SUCCESS; + return rc; } int get_ctrls( @@ -629,6 +639,15 @@ int get_ctrls( char *opaque; BerElement *ber = op->o_ber; struct berval bv; +#ifdef SLAP_CONTROL_X_WHATFAILED + /* NOTE: right now, slapd checks the validity of each control + * while parsing. As a consequence, it can only detect one + * cause of failure at a time. This results in returning + * exactly one OID with the whatFailed control, or no control + * at all. + */ + char *failed_oid = NULL; +#endif len = ber_pvt_ber_remaining(ber); @@ -769,6 +788,9 @@ int get_ctrls( rs->sr_err = slap_parse_ctrl( op, rs, c, &rs->sr_text ); if ( rs->sr_err != LDAP_SUCCESS ) { +#ifdef SLAP_CONTROL_X_WHATFAILED + failed_oid = c->ldctl_oid; +#endif goto return_results; } } @@ -784,6 +806,69 @@ return_results: send_ldap_disconnect( op, rs ); rs->sr_err = SLAPD_DISCONNECT; } else { +#ifdef SLAP_CONTROL_X_WHATFAILED + /* might have not been parsed yet? */ + if ( failed_oid != NULL ) { + if ( !get_whatFailed( op ) ) { + /* look it up */ + + /* step through each remaining element */ + for ( ; tag != LBER_ERROR; tag = ber_next_element( ber, &len, opaque ) ) + { + LDAPControl c = { 0 }; + + tag = ber_scanf( ber, "{m" /*}*/, &bv ); + c.ldctl_oid = bv.bv_val; + + if ( tag == LBER_ERROR ) { + slap_free_ctrls( op, op->o_ctrls ); + op->o_ctrls = NULL; + break; + + } else if ( c.ldctl_oid == NULL ) { + slap_free_ctrls( op, op->o_ctrls ); + op->o_ctrls = NULL; + break; + } + + tag = ber_peek_tag( ber, &len ); + if ( tag == LBER_BOOLEAN ) { + ber_int_t crit; + tag = ber_scanf( ber, "b", &crit ); + if( tag == LBER_ERROR ) { + slap_free_ctrls( op, op->o_ctrls ); + op->o_ctrls = NULL; + break; + } + + tag = ber_peek_tag( ber, &len ); + } + + if ( tag == LBER_OCTETSTRING ) { + tag = ber_scanf( ber, "m", &c.ldctl_value ); + + if( tag == LBER_ERROR ) { + slap_free_ctrls( op, op->o_ctrls ); + op->o_ctrls = NULL; + break; + } + } + + if ( strcmp( c.ldctl_oid, LDAP_CONTROL_X_WHATFAILED ) == 0 ) { + const char *text; + slap_parse_ctrl( op, rs, &c, &text ); + break; + } + } + } + + if ( get_whatFailed( op ) ) { + char *oids[ 2 ] = { failed_oid, NULL }; + slap_ctrl_whatFailed_add( op, rs, oids ); + } + } +#endif + send_ldap_result( op, rs ); } } @@ -1112,11 +1197,11 @@ static int parsePagedResults ( If the page size is greater than or equal to the sizeLimit value, the server should ignore the control as the request can be satisfied in a single page. - + * NOTE: this assumes that the op->ors_slimit be set * before the controls are parsed. */ - + if ( op->ors_slimit > 0 && size >= op->ors_slimit ) { op->o_pagedresults = SLAP_CONTROL_IGNORED; @@ -1192,7 +1277,7 @@ static int parseAssert ( rs->sr_text = "assert control: internal error"; return LDAP_OTHER; } - + rs->sr_err = get_filter( op, ber, (Filter **)&(op->o_assertion), &rs->sr_text); (void) ber_free( ber, 1 ); @@ -1377,7 +1462,7 @@ static int parseValuesReturnFilter ( rs->sr_text = "internal error"; return LDAP_OTHER; } - + rs->sr_err = get_vrFilter( op, ber, (ValuesReturnFilter **)&(op->o_vrFilter), &rs->sr_text); @@ -1865,3 +1950,87 @@ slap_ctrl_session_tracking_request_add( Operation *op, SlapReply *rs, LDAPContro return slap_ctrl_session_tracking_add( op, rs, &ip, &name, &id, ctrl ); } #endif + +#ifdef SLAP_CONTROL_X_WHATFAILED +static int parseWhatFailed( + Operation *op, + SlapReply *rs, + LDAPControl *ctrl ) +{ + if ( op->o_whatFailed != SLAP_CONTROL_NONE ) { + rs->sr_text = "\"WHat Failed?\" control specified multiple times"; + return LDAP_PROTOCOL_ERROR; + } + + if ( !BER_BVISNULL( &ctrl->ldctl_value )) { + rs->sr_text = "\"What Failed?\" control value not absent"; + return LDAP_PROTOCOL_ERROR; + } + + op->o_whatFailed = ctrl->ldctl_iscritical + ? SLAP_CONTROL_CRITICAL + : SLAP_CONTROL_NONCRITICAL; + + return LDAP_SUCCESS; +} + +int +slap_ctrl_whatFailed_add( + Operation *op, + SlapReply *rs, + char **oids ) +{ + BerElementBuffer berbuf; + BerElement *ber = (BerElement *) &berbuf; + LDAPControl **ctrls = NULL; + struct berval ctrlval; + int i, rc = LDAP_SUCCESS; + + ber_init2( ber, NULL, LBER_USE_DER ); + ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx ); + ber_printf( ber, "[" /*]*/ ); + for ( i = 0; oids[ i ] != NULL; i++ ) { + ber_printf( ber, "s", oids[ i ] ); + } + ber_printf( ber, /*[*/ "]" ); + + if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) { + rc = LDAP_OTHER; + goto done; + } + + i = 0; + if ( rs->sr_ctrls != NULL ) { + for ( ; rs->sr_ctrls[ i ] != NULL; i++ ) { + if ( strcmp( rs->sr_ctrls[ i ]->ldctl_oid, LDAP_CONTROL_X_WHATFAILED ) != 0 ) { + /* TODO: add */ + assert( 0 ); + } + } + } + + ctrls = op->o_tmprealloc( rs->sr_ctrls, + sizeof(LDAPControl *)*( i + 2 ) + + sizeof(LDAPControl) + + ctrlval.bv_len + 1, + op->o_tmpmemctx ); + if ( ctrls == NULL ) { + rc = LDAP_OTHER; + goto done; + } + ctrls[ i + 1 ] = NULL; + ctrls[ i ] = (LDAPControl *)&ctrls[ i + 2 ]; + ctrls[ i ]->ldctl_oid = LDAP_CONTROL_X_WHATFAILED; + ctrls[ i ]->ldctl_iscritical = 0; + ctrls[ i ]->ldctl_value.bv_val = (char *)&ctrls[ i ][ 1 ]; + AC_MEMCPY( ctrls[ i ]->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len + 1 ); + ctrls[ i ]->ldctl_value.bv_len = ctrlval.bv_len; + + ber_free_buf( ber ); + + rs->sr_ctrls = ctrls; + +done:; + return rc; +} +#endif diff --git a/servers/slapd/proto-slap.h b/servers/slapd/proto-slap.h index 42aa39fe5a..3999334aa3 100644 --- a/servers/slapd/proto-slap.h +++ b/servers/slapd/proto-slap.h @@ -660,6 +660,13 @@ LDAP_SLAPD_F (int) slap_ctrl_session_tracking_request_add LDAP_P(( Operation *op, SlapReply *rs, LDAPControl *ctrl )); #endif /* SLAP_CONTROL_X_SESSION_TRACKING */ +#ifdef SLAP_CONTROL_X_WHATFAILED +LDAP_SLAPD_F (int) +slap_ctrl_whatFailed_add LDAP_P(( + Operation *op, + SlapReply *rs, + char **oids )); +#endif /* SLAP_CONTROL_X_WHATFAILED */ /* * config.c diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h index 50039b2369..d9cdccf5bd 100644 --- a/servers/slapd/slap.h +++ b/servers/slapd/slap.h @@ -64,6 +64,7 @@ LDAP_BEGIN_DECL #define LDAP_SYNC_TIMESTAMP #define SLAP_CONTROL_X_SORTEDRESULTS #define SLAP_CONTROL_X_SESSION_TRACKING +#define SLAP_CONTROL_X_WHATFAILED #define SLAP_CONFIG_DELETE #endif @@ -2404,6 +2405,9 @@ struct slap_control_ids { int sc_sessionTracking; #endif int sc_valuesReturnFilter; +#ifdef SLAP_CONTROL_X_WHATFAILED + int sc_whatFailed; +#endif }; /* @@ -2673,6 +2677,11 @@ struct Operation { #define get_sessionTracking(op) ((int)(op)->o_session_tracking) #endif +#ifdef SLAP_CONTROL_X_WHATFAILED +#define o_whatFailed o_ctrlflag[slap_cids.sc_whatFailed] +#define get_whatFailed(op) _SCM((op)->o_whatFailed) +#endif + #define o_sync o_ctrlflag[slap_cids.sc_LDAPsync] AuthorizationInformation o_authz; -- GitLab