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