Source code

Revision control

Copy as Markdown

Other Tools

/* 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);
}