Mercurial > trustbridge > nss-cmake-static
diff nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldaprequest.c Mon Jul 28 10:47:06 2014 +0200 @@ -0,0 +1,761 @@ +/* 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_PL_LdapRequest *ldapRq = NULL; + + PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Destroy"); + PKIX_NULLCHECK_ONE(object); + + PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext), + PKIX_OBJECTNOTLDAPREQUEST); + + ldapRq = (PKIX_PL_LdapRequest *)object; + + /* + * 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); +}