summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c')
-rw-r--r--security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c757
1 files changed, 757 insertions, 0 deletions
diff --git a/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c
new file mode 100644
index 000000000..4546e339a
--- /dev/null
+++ b/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c
@@ -0,0 +1,757 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * pkix_pl_ldaprequest.c
+ *
+ */
+
+#include "pkix_pl_ldaprequest.h"
+
+/* --Private-LdapRequest-Functions------------------------------------- */
+
+/* Note: lengths do not include the NULL terminator */
+static const char caAttr[] = "caCertificate;binary";
+static unsigned int caAttrLen = sizeof(caAttr) - 1;
+static const char uAttr[] = "userCertificate;binary";
+static unsigned int uAttrLen = sizeof(uAttr) - 1;
+static const char ccpAttr[] = "crossCertificatePair;binary";
+static unsigned int ccpAttrLen = sizeof(ccpAttr) - 1;
+static const char crlAttr[] = "certificateRevocationList;binary";
+static unsigned int crlAttrLen = sizeof(crlAttr) - 1;
+static const char arlAttr[] = "authorityRevocationList;binary";
+static unsigned int arlAttrLen = sizeof(arlAttr) - 1;
+
+/*
+ * XXX If this function were moved into pkix_pl_ldapcertstore.c then all of
+ * LdapRequest and LdapResponse could be considered part of the LDAP client.
+ * But the constants, above, would have to be copied as well, and they are
+ * also needed in pkix_pl_LdapRequest_EncodeAttrs. So there would have to be
+ * two copies.
+ */
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_AttrTypeToBit
+ * DESCRIPTION:
+ *
+ * This function creates an attribute mask bit corresponding to the SECItem
+ * pointed to by "attrType", storing the result at "pAttrBit". The comparison
+ * is case-insensitive. If "attrType" does not match any of the known types,
+ * zero is stored at "pAttrBit".
+ *
+ * PARAMETERS
+ * "attrType"
+ * The address of the SECItem whose string contents are to be compared to
+ * the various known attribute types. Must be non-NULL.
+ * "pAttrBit"
+ * The address where the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapRequest_AttrTypeToBit(
+ SECItem *attrType,
+ LdapAttrMask *pAttrBit,
+ void *plContext)
+{
+ LdapAttrMask attrBit = 0;
+ unsigned int attrLen = 0;
+ const char *s = NULL;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrTypeToBit");
+ PKIX_NULLCHECK_TWO(attrType, pAttrBit);
+
+ s = (const char *)attrType->data;
+ attrLen = attrType->len;
+
+ /*
+ * Taking note of the fact that all of the comparand strings are
+ * different lengths, we do a slight optimization. If a string
+ * length matches but the string does not match, we skip comparing
+ * to the other strings. If new strings are added to the comparand
+ * list, and any are of equal length, be careful to change the
+ * grouping of tests accordingly.
+ */
+ if (attrLen == caAttrLen) {
+ if (PORT_Strncasecmp(caAttr, s, attrLen) == 0) {
+ attrBit = LDAPATTR_CACERT;
+ }
+ } else if (attrLen == uAttrLen) {
+ if (PORT_Strncasecmp(uAttr, s, attrLen) == 0) {
+ attrBit = LDAPATTR_USERCERT;
+ }
+ } else if (attrLen == ccpAttrLen) {
+ if (PORT_Strncasecmp(ccpAttr, s, attrLen) == 0) {
+ attrBit = LDAPATTR_CROSSPAIRCERT;
+ }
+ } else if (attrLen == crlAttrLen) {
+ if (PORT_Strncasecmp(crlAttr, s, attrLen) == 0) {
+ attrBit = LDAPATTR_CERTREVLIST;
+ }
+ } else if (attrLen == arlAttrLen) {
+ if (PORT_Strncasecmp(arlAttr, s, attrLen) == 0) {
+ attrBit = LDAPATTR_AUTHREVLIST;
+ }
+ }
+
+ *pAttrBit = attrBit;
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_AttrStringToBit
+ * DESCRIPTION:
+ *
+ * This function creates an attribute mask bit corresponding to the null-
+ * terminated string pointed to by "attrString", storing the result at
+ * "pAttrBit". The comparison is case-insensitive. If "attrString" does not
+ * match any of the known types, zero is stored at "pAttrBit".
+ *
+ * PARAMETERS
+ * "attrString"
+ * The address of the null-terminated string whose contents are to be compared to
+ * the various known attribute types. Must be non-NULL.
+ * "pAttrBit"
+ * The address where the result is stored. Must be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapRequest_AttrStringToBit(
+ char *attrString,
+ LdapAttrMask *pAttrBit,
+ void *plContext)
+{
+ LdapAttrMask attrBit = 0;
+ unsigned int attrLen = 0;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrStringToBit");
+ PKIX_NULLCHECK_TWO(attrString, pAttrBit);
+
+ attrLen = PL_strlen(attrString);
+
+ /*
+ * Taking note of the fact that all of the comparand strings are
+ * different lengths, we do a slight optimization. If a string
+ * length matches but the string does not match, we skip comparing
+ * to the other strings. If new strings are added to the comparand
+ * list, and any are of equal length, be careful to change the
+ * grouping of tests accordingly.
+ */
+ if (attrLen == caAttrLen) {
+ if (PORT_Strncasecmp(caAttr, attrString, attrLen) == 0) {
+ attrBit = LDAPATTR_CACERT;
+ }
+ } else if (attrLen == uAttrLen) {
+ if (PORT_Strncasecmp(uAttr, attrString, attrLen) == 0) {
+ attrBit = LDAPATTR_USERCERT;
+ }
+ } else if (attrLen == ccpAttrLen) {
+ if (PORT_Strncasecmp(ccpAttr, attrString, attrLen) == 0) {
+ attrBit = LDAPATTR_CROSSPAIRCERT;
+ }
+ } else if (attrLen == crlAttrLen) {
+ if (PORT_Strncasecmp(crlAttr, attrString, attrLen) == 0) {
+ attrBit = LDAPATTR_CERTREVLIST;
+ }
+ } else if (attrLen == arlAttrLen) {
+ if (PORT_Strncasecmp(arlAttr, attrString, attrLen) == 0) {
+ attrBit = LDAPATTR_AUTHREVLIST;
+ }
+ }
+
+ *pAttrBit = attrBit;
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_EncodeAttrs
+ * DESCRIPTION:
+ *
+ * This function obtains the attribute mask bits from the LdapRequest pointed
+ * to by "request", creates the corresponding array of AttributeTypes for the
+ * encoding of the SearchRequest message.
+ *
+ * PARAMETERS
+ * "request"
+ * The address of the LdapRequest whose attributes are to be encoded. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+static PKIX_Error *
+pkix_pl_LdapRequest_EncodeAttrs(
+ PKIX_PL_LdapRequest *request,
+ void *plContext)
+{
+ SECItem **attrArray = NULL;
+ PKIX_UInt32 attrIndex = 0;
+ LdapAttrMask attrBits;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_EncodeAttrs");
+ PKIX_NULLCHECK_ONE(request);
+
+ /* construct "attrs" according to bits in request->attrBits */
+ attrBits = request->attrBits;
+ attrArray = request->attrArray;
+ if ((attrBits & LDAPATTR_CACERT) == LDAPATTR_CACERT) {
+ attrArray[attrIndex] = &(request->attributes[attrIndex]);
+ request->attributes[attrIndex].type = siAsciiString;
+ request->attributes[attrIndex].data = (unsigned char *)caAttr;
+ request->attributes[attrIndex].len = caAttrLen;
+ attrIndex++;
+ }
+ if ((attrBits & LDAPATTR_USERCERT) == LDAPATTR_USERCERT) {
+ attrArray[attrIndex] = &(request->attributes[attrIndex]);
+ request->attributes[attrIndex].type = siAsciiString;
+ request->attributes[attrIndex].data = (unsigned char *)uAttr;
+ request->attributes[attrIndex].len = uAttrLen;
+ attrIndex++;
+ }
+ if ((attrBits & LDAPATTR_CROSSPAIRCERT) == LDAPATTR_CROSSPAIRCERT) {
+ attrArray[attrIndex] = &(request->attributes[attrIndex]);
+ request->attributes[attrIndex].type = siAsciiString;
+ request->attributes[attrIndex].data = (unsigned char *)ccpAttr;
+ request->attributes[attrIndex].len = ccpAttrLen;
+ attrIndex++;
+ }
+ if ((attrBits & LDAPATTR_CERTREVLIST) == LDAPATTR_CERTREVLIST) {
+ attrArray[attrIndex] = &(request->attributes[attrIndex]);
+ request->attributes[attrIndex].type = siAsciiString;
+ request->attributes[attrIndex].data = (unsigned char *)crlAttr;
+ request->attributes[attrIndex].len = crlAttrLen;
+ attrIndex++;
+ }
+ if ((attrBits & LDAPATTR_AUTHREVLIST) == LDAPATTR_AUTHREVLIST) {
+ attrArray[attrIndex] = &(request->attributes[attrIndex]);
+ request->attributes[attrIndex].type = siAsciiString;
+ request->attributes[attrIndex].data = (unsigned char *)arlAttr;
+ request->attributes[attrIndex].len = arlAttrLen;
+ attrIndex++;
+ }
+ attrArray[attrIndex] = (SECItem *)NULL;
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_Destroy
+ * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapRequest_Destroy(
+ PKIX_PL_Object *object,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Destroy");
+ PKIX_NULLCHECK_ONE(object);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext),
+ PKIX_OBJECTNOTLDAPREQUEST);
+
+ /*
+ * All dynamic fields in an LDAPRequest are allocated
+ * in an arena, and will be freed when the arena is destroyed.
+ */
+
+cleanup:
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_Hashcode
+ * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapRequest_Hashcode(
+ PKIX_PL_Object *object,
+ PKIX_UInt32 *pHashcode,
+ void *plContext)
+{
+ PKIX_UInt32 dataLen = 0;
+ PKIX_UInt32 dindex = 0;
+ PKIX_UInt32 sizeOfLength = 0;
+ PKIX_UInt32 idLen = 0;
+ const unsigned char *msgBuf = NULL;
+ PKIX_PL_LdapRequest *ldapRq = NULL;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Hashcode");
+ PKIX_NULLCHECK_TWO(object, pHashcode);
+
+ PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext),
+ PKIX_OBJECTNOTLDAPREQUEST);
+
+ ldapRq = (PKIX_PL_LdapRequest *)object;
+
+ *pHashcode = 0;
+
+ /*
+ * Two requests that differ only in msgnum are a match! Therefore,
+ * start hashcoding beyond the encoded messageID field.
+ */
+ if (ldapRq->encoded) {
+ msgBuf = (const unsigned char *)ldapRq->encoded->data;
+ /* Is message length short form (one octet) or long form? */
+ if ((msgBuf[1] & 0x80) != 0) {
+ sizeOfLength = msgBuf[1] & 0x7F;
+ for (dindex = 0; dindex < sizeOfLength; dindex++) {
+ dataLen = (dataLen << 8) + msgBuf[dindex + 2];
+ }
+ } else {
+ dataLen = msgBuf[1];
+ }
+
+ /* How many bytes for the messageID? (Assume short form) */
+ idLen = msgBuf[dindex + 3] + 2;
+ dindex += idLen;
+ dataLen -= idLen;
+ msgBuf = &msgBuf[dindex + 2];
+
+ PKIX_CHECK(pkix_hash(msgBuf, dataLen, pHashcode, plContext),
+ PKIX_HASHFAILED);
+ }
+
+cleanup:
+
+ PKIX_RETURN(LDAPREQUEST);
+
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_Equals
+ * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
+ */
+static PKIX_Error *
+pkix_pl_LdapRequest_Equals(
+ PKIX_PL_Object *firstObj,
+ PKIX_PL_Object *secondObj,
+ PKIX_Boolean *pResult,
+ void *plContext)
+{
+ PKIX_PL_LdapRequest *firstReq = NULL;
+ PKIX_PL_LdapRequest *secondReq = NULL;
+ PKIX_UInt32 secondType = 0;
+ PKIX_UInt32 firstLen = 0;
+ const unsigned char *firstData = NULL;
+ const unsigned char *secondData = NULL;
+ PKIX_UInt32 sizeOfLength = 0;
+ PKIX_UInt32 dindex = 0;
+ PKIX_UInt32 i = 0;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Equals");
+ PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
+
+ /* test that firstObj is a LdapRequest */
+ PKIX_CHECK(pkix_CheckType(firstObj, PKIX_LDAPREQUEST_TYPE, plContext),
+ PKIX_FIRSTOBJARGUMENTNOTLDAPREQUEST);
+
+ /*
+ * Since we know firstObj is a LdapRequest, if both references are
+ * identical, they must be equal
+ */
+ if (firstObj == secondObj){
+ *pResult = PKIX_TRUE;
+ goto cleanup;
+ }
+
+ /*
+ * If secondObj isn't a LdapRequest, we don't throw an error.
+ * We simply return a Boolean result of FALSE
+ */
+ *pResult = PKIX_FALSE;
+ PKIX_CHECK(PKIX_PL_Object_GetType
+ (secondObj, &secondType, plContext),
+ PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
+ if (secondType != PKIX_LDAPREQUEST_TYPE) {
+ goto cleanup;
+ }
+
+ firstReq = (PKIX_PL_LdapRequest *)firstObj;
+ secondReq = (PKIX_PL_LdapRequest *)secondObj;
+
+ /* If either lacks an encoded string, they cannot be compared */
+ if (!(firstReq->encoded) || !(secondReq->encoded)) {
+ goto cleanup;
+ }
+
+ if (firstReq->encoded->len != secondReq->encoded->len) {
+ goto cleanup;
+ }
+
+ firstData = (const unsigned char *)firstReq->encoded->data;
+ secondData = (const unsigned char *)secondReq->encoded->data;
+
+ /*
+ * Two requests that differ only in msgnum are equal! Therefore,
+ * start the byte comparison beyond the encoded messageID field.
+ */
+
+ /* Is message length short form (one octet) or long form? */
+ if ((firstData[1] & 0x80) != 0) {
+ sizeOfLength = firstData[1] & 0x7F;
+ for (dindex = 0; dindex < sizeOfLength; dindex++) {
+ firstLen = (firstLen << 8) + firstData[dindex + 2];
+ }
+ } else {
+ firstLen = firstData[1];
+ }
+
+ /* How many bytes for the messageID? (Assume short form) */
+ i = firstData[dindex + 3] + 2;
+ dindex += i;
+ firstLen -= i;
+ firstData = &firstData[dindex + 2];
+
+ /*
+ * In theory, we have to calculate where the second message data
+ * begins by checking its length encodings. But if these messages
+ * are equal, we can re-use the calculation we already did. If they
+ * are not equal, the byte comparisons will surely fail.
+ */
+
+ secondData = &secondData[dindex + 2];
+
+ for (i = 0; i < firstLen; i++) {
+ if (firstData[i] != secondData[i]) {
+ goto cleanup;
+ }
+ }
+
+ *pResult = PKIX_TRUE;
+
+cleanup:
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_RegisterSelf
+ * DESCRIPTION:
+ * Registers PKIX_LDAPREQUEST_TYPE and its related functions with
+ * systemClasses[]
+ * PARAMETERS:
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Not Thread Safe - for performance and complexity reasons
+ *
+ * Since this function is only called by PKIX_PL_Initialize, which should
+ * only be called once, it is acceptable that this function is not
+ * thread-safe.
+ */
+PKIX_Error *
+pkix_pl_LdapRequest_RegisterSelf(void *plContext)
+{
+ extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
+ pkix_ClassTable_Entry entry;
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_RegisterSelf");
+
+ entry.description = "LdapRequest";
+ entry.objCounter = 0;
+ entry.typeObjectSize = sizeof(PKIX_PL_LdapRequest);
+ entry.destructor = pkix_pl_LdapRequest_Destroy;
+ entry.equalsFunction = pkix_pl_LdapRequest_Equals;
+ entry.hashcodeFunction = pkix_pl_LdapRequest_Hashcode;
+ entry.toStringFunction = NULL;
+ entry.comparator = NULL;
+ entry.duplicateFunction = pkix_duplicateImmutable;
+
+ systemClasses[PKIX_LDAPREQUEST_TYPE] = entry;
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/* --Public-Functions------------------------------------------------------- */
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_Create
+ * DESCRIPTION:
+ *
+ * This function creates an LdapRequest using the PLArenaPool pointed to by
+ * "arena", a message number whose value is "msgnum", a base object pointed to
+ * by "issuerDN", a scope whose value is "scope", a derefAliases flag whose
+ * value is "derefAliases", a sizeLimit whose value is "sizeLimit", a timeLimit
+ * whose value is "timeLimit", an attrsOnly flag whose value is "attrsOnly", a
+ * filter whose value is "filter", and attribute bits whose value is
+ * "attrBits"; storing the result at "pRequestMsg".
+ *
+ * See pkix_pl_ldaptemplates.c (and below) for the ASN.1 representation of
+ * message components, and see pkix_pl_ldapt.h for data types.
+ *
+ * PARAMETERS
+ * "arena"
+ * The address of the PLArenaPool to be used in the encoding. Must be
+ * non-NULL.
+ * "msgnum"
+ * The UInt32 message number to be used for the messageID component of the
+ * LDAP message exchange.
+ * "issuerDN"
+ * The address of the string to be used for the baseObject component of the
+ * LDAP SearchRequest message. Must be non-NULL.
+ * "scope"
+ * The (enumerated) ScopeType to be used for the scope component of the
+ * LDAP SearchRequest message
+ * "derefAliases"
+ * The (enumerated) DerefType to be used for the derefAliases component of
+ * the LDAP SearchRequest message
+ * "sizeLimit"
+ * The UInt32 value to be used for the sizeLimit component of the LDAP
+ * SearchRequest message
+ * "timeLimit"
+ * The UInt32 value to be used for the timeLimit component of the LDAP
+ * SearchRequest message
+ * "attrsOnly"
+ * The Boolean value to be used for the attrsOnly component of the LDAP
+ * SearchRequest message
+ * "filter"
+ * The filter to be used for the filter component of the LDAP
+ * SearchRequest message
+ * "attrBits"
+ * The LdapAttrMask bits indicating the attributes to be included in the
+ * attributes sequence of the LDAP SearchRequest message
+ * "pRequestMsg"
+ * The address at which the address of the LdapRequest is stored. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+/*
+ * SearchRequest ::=
+ * [APPLICATION 3] SEQUENCE {
+ * baseObject LDAPDN,
+ * scope ENUMERATED {
+ * baseObject (0),
+ * singleLevel (1),
+ * wholeSubtree (2)
+ * },
+ * derefAliases ENUMERATED {
+ * neverDerefAliases (0),
+ * derefInSearching (1),
+ * derefFindingBaseObj (2),
+ * alwaysDerefAliases (3)
+ * },
+ * sizeLimit INTEGER (0 .. MAXINT),
+ * -- value of 0 implies no sizeLimit
+ * timeLimit INTEGER (0 .. MAXINT),
+ * -- value of 0 implies no timeLimit
+ * attrsOnly BOOLEAN,
+ * -- TRUE, if only attributes (without values)
+ * -- to be returned
+ * filter Filter,
+ * attributes SEQUENCE OF AttributeType
+ * }
+ *
+ * Filter ::=
+ * CHOICE {
+ * and [0] SET OF Filter,
+ * or [1] SET OF Filter,
+ * not [2] Filter,
+ * equalityMatch [3] AttributeValueAssertion,
+ * substrings [4] SubstringFilter,
+ * greaterOrEqual [5] AttributeValueAssertion,
+ * lessOrEqual [6] AttributeValueAssertion,
+ * present [7] AttributeType,
+ * approxMatch [8] AttributeValueAssertion
+ * }
+ *
+ * SubstringFilter ::=
+ * SEQUENCE {
+ * type AttributeType,
+ * SEQUENCE OF CHOICE {
+ * initial [0] LDAPString,
+ * any [1] LDAPString,
+ * final [2] LDAPString,
+ * }
+ * }
+ *
+ * AttributeValueAssertion ::=
+ * SEQUENCE {
+ * attributeType AttributeType,
+ * attributeValue AttributeValue,
+ * }
+ *
+ * AttributeValue ::= OCTET STRING
+ *
+ * AttributeType ::= LDAPString
+ * -- text name of the attribute, or dotted
+ * -- OID representation
+ *
+ * LDAPDN ::= LDAPString
+ *
+ * LDAPString ::= OCTET STRING
+ *
+ */
+PKIX_Error *
+pkix_pl_LdapRequest_Create(
+ PLArenaPool *arena,
+ PKIX_UInt32 msgnum,
+ char *issuerDN,
+ ScopeType scope,
+ DerefType derefAliases,
+ PKIX_UInt32 sizeLimit,
+ PKIX_UInt32 timeLimit,
+ char attrsOnly,
+ LDAPFilter *filter,
+ LdapAttrMask attrBits,
+ PKIX_PL_LdapRequest **pRequestMsg,
+ void *plContext)
+{
+ LDAPMessage msg;
+ LDAPSearch *search;
+ PKIX_PL_LdapRequest *ldapRequest = NULL;
+ char scopeTypeAsChar;
+ char derefAliasesTypeAsChar;
+ SECItem *attrArray[MAX_LDAPATTRS + 1];
+
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Create");
+ PKIX_NULLCHECK_THREE(arena, issuerDN, pRequestMsg);
+
+ /* create a PKIX_PL_LdapRequest object */
+ PKIX_CHECK(PKIX_PL_Object_Alloc
+ (PKIX_LDAPREQUEST_TYPE,
+ sizeof (PKIX_PL_LdapRequest),
+ (PKIX_PL_Object **)&ldapRequest,
+ plContext),
+ PKIX_COULDNOTCREATEOBJECT);
+
+ ldapRequest->arena = arena;
+ ldapRequest->msgnum = msgnum;
+ ldapRequest->issuerDN = issuerDN;
+ ldapRequest->scope = scope;
+ ldapRequest->derefAliases = derefAliases;
+ ldapRequest->sizeLimit = sizeLimit;
+ ldapRequest->timeLimit = timeLimit;
+ ldapRequest->attrsOnly = attrsOnly;
+ ldapRequest->filter = filter;
+ ldapRequest->attrBits = attrBits;
+
+ ldapRequest->attrArray = attrArray;
+
+ PKIX_CHECK(pkix_pl_LdapRequest_EncodeAttrs
+ (ldapRequest, plContext),
+ PKIX_LDAPREQUESTENCODEATTRSFAILED);
+
+ PKIX_PL_NSSCALL
+ (LDAPREQUEST, PORT_Memset, (&msg, 0, sizeof (LDAPMessage)));
+
+ msg.messageID.type = siUnsignedInteger;
+ msg.messageID.data = (void*)&msgnum;
+ msg.messageID.len = sizeof (msgnum);
+
+ msg.protocolOp.selector = LDAP_SEARCH_TYPE;
+
+ search = &(msg.protocolOp.op.searchMsg);
+
+ search->baseObject.type = siAsciiString;
+ search->baseObject.data = (void *)issuerDN;
+ search->baseObject.len = PL_strlen(issuerDN);
+ scopeTypeAsChar = (char)scope;
+ search->scope.type = siUnsignedInteger;
+ search->scope.data = (void *)&scopeTypeAsChar;
+ search->scope.len = sizeof (scopeTypeAsChar);
+ derefAliasesTypeAsChar = (char)derefAliases;
+ search->derefAliases.type = siUnsignedInteger;
+ search->derefAliases.data =
+ (void *)&derefAliasesTypeAsChar;
+ search->derefAliases.len =
+ sizeof (derefAliasesTypeAsChar);
+ search->sizeLimit.type = siUnsignedInteger;
+ search->sizeLimit.data = (void *)&sizeLimit;
+ search->sizeLimit.len = sizeof (PKIX_UInt32);
+ search->timeLimit.type = siUnsignedInteger;
+ search->timeLimit.data = (void *)&timeLimit;
+ search->timeLimit.len = sizeof (PKIX_UInt32);
+ search->attrsOnly.type = siBuffer;
+ search->attrsOnly.data = (void *)&attrsOnly;
+ search->attrsOnly.len = sizeof (attrsOnly);
+
+ PKIX_PL_NSSCALL
+ (LDAPREQUEST,
+ PORT_Memcpy,
+ (&search->filter, filter, sizeof (LDAPFilter)));
+
+ search->attributes = attrArray;
+
+ PKIX_PL_NSSCALLRV
+ (LDAPREQUEST, ldapRequest->encoded, SEC_ASN1EncodeItem,
+ (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate));
+
+ if (!(ldapRequest->encoded)) {
+ PKIX_ERROR(PKIX_FAILEDINENCODINGSEARCHREQUEST);
+ }
+
+ *pRequestMsg = ldapRequest;
+
+cleanup:
+
+ if (PKIX_ERROR_RECEIVED) {
+ PKIX_DECREF(ldapRequest);
+ }
+
+ PKIX_RETURN(LDAPREQUEST);
+}
+
+/*
+ * FUNCTION: pkix_pl_LdapRequest_GetEncoded
+ * DESCRIPTION:
+ *
+ * This function obtains the encoded message from the LdapRequest pointed to
+ * by "request", storing the result at "pRequestBuf".
+ *
+ * PARAMETERS
+ * "request"
+ * The address of the LdapRequest whose encoded message is to be
+ * retrieved. Must be non-NULL.
+ * "pRequestBuf"
+ * The address at which is stored the address of the encoded message. Must
+ * be non-NULL.
+ * "plContext"
+ * Platform-specific context pointer.
+ * THREAD SAFETY:
+ * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
+ * RETURNS:
+ * Returns NULL if the function succeeds.
+ * Returns an LdapRequest Error if the function fails in a non-fatal way.
+ * Returns a Fatal Error if the function fails in an unrecoverable way.
+ */
+PKIX_Error *
+pkix_pl_LdapRequest_GetEncoded(
+ PKIX_PL_LdapRequest *request,
+ SECItem **pRequestBuf,
+ void *plContext)
+{
+ PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_GetEncoded");
+ PKIX_NULLCHECK_TWO(request, pRequestBuf);
+
+ *pRequestBuf = request->encoded;
+
+ PKIX_RETURN(LDAPREQUEST);
+}