tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pkix_pl_ldaprequest.c (27485B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * pkix_pl_ldaprequest.c
      6 *
      7 */
      8 
      9 #include "pkix_pl_ldaprequest.h"
     10 
     11 /* --Private-LdapRequest-Functions------------------------------------- */
     12 
     13 /* Note: lengths do not include the NULL terminator */
     14 static const char caAttr[] = "caCertificate;binary";
     15 static unsigned int caAttrLen = sizeof(caAttr) - 1;
     16 static const char uAttr[] = "userCertificate;binary";
     17 static unsigned int uAttrLen = sizeof(uAttr) - 1;
     18 static const char ccpAttr[] = "crossCertificatePair;binary";
     19 static unsigned int ccpAttrLen = sizeof(ccpAttr) - 1;
     20 static const char crlAttr[] = "certificateRevocationList;binary";
     21 static unsigned int crlAttrLen = sizeof(crlAttr) - 1;
     22 static const char arlAttr[] = "authorityRevocationList;binary";
     23 static unsigned int arlAttrLen = sizeof(arlAttr) - 1;
     24 
     25 /*
     26 * XXX If this function were moved into pkix_pl_ldapcertstore.c then all of
     27 * LdapRequest and LdapResponse could be considered part of the LDAP client.
     28 * But the constants, above, would have to be copied as well, and they are
     29 * also needed in pkix_pl_LdapRequest_EncodeAttrs. So there would have to be
     30 * two copies.
     31 */
     32 
     33 /*
     34 * FUNCTION: pkix_pl_LdapRequest_AttrTypeToBit
     35 * DESCRIPTION:
     36 *
     37 *  This function creates an attribute mask bit corresponding to the SECItem
     38 *  pointed to by "attrType", storing the result at "pAttrBit". The comparison
     39 *  is case-insensitive. If "attrType" does not match any of the known types,
     40 *  zero is stored at "pAttrBit".
     41 *
     42 * PARAMETERS
     43 *  "attrType"
     44 *      The address of the SECItem whose string contents are to be compared to
     45 *      the various known attribute types. Must be non-NULL.
     46 *  "pAttrBit"
     47 *      The address where the result is stored. Must be non-NULL.
     48 *  "plContext"
     49 *      Platform-specific context pointer.
     50 * THREAD SAFETY:
     51 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
     52 * RETURNS:
     53 *  Returns NULL if the function succeeds.
     54 *  Returns an LdapRequest Error if the function fails in a non-fatal way.
     55 *  Returns a Fatal Error if the function fails in an unrecoverable way.
     56 */
     57 PKIX_Error *
     58 pkix_pl_LdapRequest_AttrTypeToBit(
     59        SECItem *attrType,
     60        LdapAttrMask *pAttrBit,
     61        void *plContext)
     62 {
     63        LdapAttrMask attrBit = 0;
     64        unsigned int attrLen = 0;
     65        const char *s = NULL;
     66 
     67        PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrTypeToBit");
     68        PKIX_NULLCHECK_TWO(attrType, pAttrBit);
     69 
     70        s = (const char *)attrType->data;
     71        attrLen = attrType->len;
     72 
     73        /*
     74         * Taking note of the fact that all of the comparand strings are
     75         * different lengths, we do a slight optimization. If a string
     76         * length matches but the string does not match, we skip comparing
     77         * to the other strings. If new strings are added to the comparand
     78         * list, and any are of equal length, be careful to change the
     79         * grouping of tests accordingly.
     80         */
     81        if (attrLen == caAttrLen) {
     82                if (PORT_Strncasecmp(caAttr, s, attrLen) == 0) {
     83                        attrBit = LDAPATTR_CACERT;
     84                }
     85        } else if (attrLen == uAttrLen) {
     86                if (PORT_Strncasecmp(uAttr, s, attrLen) == 0) {
     87                        attrBit = LDAPATTR_USERCERT;
     88                }
     89        } else if (attrLen == ccpAttrLen) {
     90                if (PORT_Strncasecmp(ccpAttr, s, attrLen) == 0) {
     91                        attrBit = LDAPATTR_CROSSPAIRCERT;
     92                }
     93        } else if (attrLen == crlAttrLen) {
     94                if (PORT_Strncasecmp(crlAttr, s, attrLen) == 0) {
     95                        attrBit = LDAPATTR_CERTREVLIST;
     96                }
     97        } else if (attrLen == arlAttrLen) {
     98                if (PORT_Strncasecmp(arlAttr, s, attrLen) == 0) {
     99                        attrBit = LDAPATTR_AUTHREVLIST;
    100                }
    101        }
    102 
    103        *pAttrBit = attrBit;
    104 
    105        PKIX_RETURN(LDAPREQUEST);
    106 }
    107 
    108 /*
    109 * FUNCTION: pkix_pl_LdapRequest_AttrStringToBit
    110 * DESCRIPTION:
    111 *
    112 *  This function creates an attribute mask bit corresponding to the null-
    113 *  terminated string pointed to by "attrString", storing the result at
    114 *  "pAttrBit". The comparison is case-insensitive. If "attrString" does not
    115 *  match any of the known types, zero is stored at "pAttrBit".
    116 *
    117 * PARAMETERS
    118 *  "attrString"
    119 *      The address of the null-terminated string whose contents are to be compared to
    120 *      the various known attribute types. Must be non-NULL.
    121 *  "pAttrBit"
    122 *      The address where the result is stored. Must be non-NULL.
    123 *  "plContext"
    124 *      Platform-specific context pointer.
    125 * THREAD SAFETY:
    126 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    127 * RETURNS:
    128 *  Returns NULL if the function succeeds.
    129 *  Returns an LdapRequest Error if the function fails in a non-fatal way.
    130 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    131 */
    132 PKIX_Error *
    133 pkix_pl_LdapRequest_AttrStringToBit(
    134        char *attrString,
    135        LdapAttrMask *pAttrBit,
    136        void *plContext)
    137 {
    138        LdapAttrMask attrBit = 0;
    139        unsigned int attrLen = 0;
    140 
    141        PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrStringToBit");
    142        PKIX_NULLCHECK_TWO(attrString, pAttrBit);
    143 
    144        attrLen = PL_strlen(attrString);
    145 
    146        /*
    147         * Taking note of the fact that all of the comparand strings are
    148         * different lengths, we do a slight optimization. If a string
    149         * length matches but the string does not match, we skip comparing
    150         * to the other strings. If new strings are added to the comparand
    151         * list, and any are of equal length, be careful to change the
    152         * grouping of tests accordingly.
    153         */
    154        if (attrLen == caAttrLen) {
    155                if (PORT_Strncasecmp(caAttr, attrString, attrLen) == 0) {
    156                        attrBit = LDAPATTR_CACERT;
    157                }
    158        } else if (attrLen == uAttrLen) {
    159                if (PORT_Strncasecmp(uAttr, attrString, attrLen) == 0) {
    160                        attrBit = LDAPATTR_USERCERT;
    161                }
    162        } else if (attrLen == ccpAttrLen) {
    163                if (PORT_Strncasecmp(ccpAttr, attrString, attrLen) == 0) {
    164                        attrBit = LDAPATTR_CROSSPAIRCERT;
    165                }
    166        } else if (attrLen == crlAttrLen) {
    167                if (PORT_Strncasecmp(crlAttr, attrString, attrLen) == 0) {
    168                        attrBit = LDAPATTR_CERTREVLIST;
    169                }
    170        } else if (attrLen == arlAttrLen) {
    171                if (PORT_Strncasecmp(arlAttr, attrString, attrLen) == 0) {
    172                        attrBit = LDAPATTR_AUTHREVLIST;
    173                }
    174        }
    175 
    176        *pAttrBit = attrBit;
    177 
    178        PKIX_RETURN(LDAPREQUEST);
    179 }
    180 
    181 /*
    182 * FUNCTION: pkix_pl_LdapRequest_EncodeAttrs
    183 * DESCRIPTION:
    184 *
    185 *  This function obtains the attribute mask bits from the LdapRequest pointed
    186 *  to by "request", creates the corresponding array of AttributeTypes for the
    187 *  encoding of the SearchRequest message.
    188 *
    189 * PARAMETERS
    190 *  "request"
    191 *      The address of the LdapRequest whose attributes are to be encoded. Must
    192 *      be non-NULL.
    193 *  "plContext"
    194 *      Platform-specific context pointer.
    195 * THREAD SAFETY:
    196 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    197 * RETURNS:
    198 *  Returns NULL if the function succeeds.
    199 *  Returns an LdapRequest Error if the function fails in a non-fatal way.
    200 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    201 */
    202 static PKIX_Error *
    203 pkix_pl_LdapRequest_EncodeAttrs(
    204        PKIX_PL_LdapRequest *request,
    205        void *plContext)
    206 {
    207        SECItem **attrArray = NULL;
    208        PKIX_UInt32 attrIndex = 0;
    209        LdapAttrMask attrBits;
    210 
    211        PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_EncodeAttrs");
    212        PKIX_NULLCHECK_ONE(request);
    213 
    214        /* construct "attrs" according to bits in request->attrBits */
    215        attrBits = request->attrBits;
    216        attrArray = request->attrArray;
    217        if ((attrBits & LDAPATTR_CACERT) == LDAPATTR_CACERT) {
    218                attrArray[attrIndex] = &(request->attributes[attrIndex]);
    219                request->attributes[attrIndex].type = siAsciiString;
    220                request->attributes[attrIndex].data = (unsigned char *)caAttr;
    221                request->attributes[attrIndex].len = caAttrLen;
    222                attrIndex++;
    223        }
    224        if ((attrBits & LDAPATTR_USERCERT) == LDAPATTR_USERCERT) {
    225                attrArray[attrIndex] = &(request->attributes[attrIndex]);
    226                request->attributes[attrIndex].type = siAsciiString;
    227                request->attributes[attrIndex].data = (unsigned char *)uAttr;
    228                request->attributes[attrIndex].len = uAttrLen;
    229                attrIndex++;
    230        }
    231        if ((attrBits & LDAPATTR_CROSSPAIRCERT) == LDAPATTR_CROSSPAIRCERT) {
    232                attrArray[attrIndex] = &(request->attributes[attrIndex]);
    233                request->attributes[attrIndex].type = siAsciiString;
    234                request->attributes[attrIndex].data = (unsigned char *)ccpAttr;
    235                request->attributes[attrIndex].len = ccpAttrLen;
    236                attrIndex++;
    237        }
    238        if ((attrBits & LDAPATTR_CERTREVLIST) == LDAPATTR_CERTREVLIST) {
    239                attrArray[attrIndex] = &(request->attributes[attrIndex]);
    240                request->attributes[attrIndex].type = siAsciiString;
    241                request->attributes[attrIndex].data = (unsigned char *)crlAttr;
    242                request->attributes[attrIndex].len = crlAttrLen;
    243                attrIndex++;
    244        }
    245        if ((attrBits & LDAPATTR_AUTHREVLIST) == LDAPATTR_AUTHREVLIST) {
    246                attrArray[attrIndex] = &(request->attributes[attrIndex]);
    247                request->attributes[attrIndex].type = siAsciiString;
    248                request->attributes[attrIndex].data = (unsigned char *)arlAttr;
    249                request->attributes[attrIndex].len = arlAttrLen;
    250                attrIndex++;
    251        }
    252        attrArray[attrIndex] = (SECItem *)NULL;
    253 
    254        PKIX_RETURN(LDAPREQUEST);
    255 }
    256 
    257 /*
    258 * FUNCTION: pkix_pl_LdapRequest_Destroy
    259 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
    260 */
    261 static PKIX_Error *
    262 pkix_pl_LdapRequest_Destroy(
    263        PKIX_PL_Object *object,
    264        void *plContext)
    265 {
    266        PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Destroy");
    267        PKIX_NULLCHECK_ONE(object);
    268 
    269        PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext),
    270                    PKIX_OBJECTNOTLDAPREQUEST);
    271 
    272        /*
    273         * All dynamic fields in an LDAPRequest are allocated
    274         * in an arena, and will be freed when the arena is destroyed.
    275         */
    276 
    277 cleanup:
    278 
    279        PKIX_RETURN(LDAPREQUEST);
    280 }
    281 
    282 /*
    283 * FUNCTION: pkix_pl_LdapRequest_Hashcode
    284 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
    285 */
    286 static PKIX_Error *
    287 pkix_pl_LdapRequest_Hashcode(
    288        PKIX_PL_Object *object,
    289        PKIX_UInt32 *pHashcode,
    290        void *plContext)
    291 {
    292        PKIX_UInt32 dataLen = 0;
    293        PKIX_UInt32 dindex = 0;
    294        PKIX_UInt32 sizeOfLength = 0;
    295        PKIX_UInt32 idLen = 0;
    296        const unsigned char *msgBuf = NULL;
    297        PKIX_PL_LdapRequest *ldapRq = NULL;
    298 
    299        PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Hashcode");
    300        PKIX_NULLCHECK_TWO(object, pHashcode);
    301 
    302        PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext),
    303                    PKIX_OBJECTNOTLDAPREQUEST);
    304 
    305        ldapRq = (PKIX_PL_LdapRequest *)object;
    306 
    307        *pHashcode = 0;
    308 
    309        /*
    310         * Two requests that differ only in msgnum are a match! Therefore,
    311         * start hashcoding beyond the encoded messageID field.
    312         */
    313        if (ldapRq->encoded) {
    314                msgBuf = (const unsigned char *)ldapRq->encoded->data;
    315                /* Is message length short form (one octet) or long form? */
    316                if ((msgBuf[1] & 0x80) != 0) {
    317                        sizeOfLength = msgBuf[1] & 0x7F;
    318                        for (dindex = 0; dindex < sizeOfLength; dindex++) {
    319                                dataLen = (dataLen << 8) + msgBuf[dindex + 2];
    320                        }
    321                } else {
    322                        dataLen = msgBuf[1];
    323                }
    324 
    325                /* How many bytes for the messageID? (Assume short form) */
    326                idLen = msgBuf[dindex + 3] + 2;
    327                dindex += idLen;
    328                dataLen -= idLen;
    329                msgBuf = &msgBuf[dindex + 2];
    330 
    331                PKIX_CHECK(pkix_hash(msgBuf, dataLen, pHashcode, plContext),
    332                        PKIX_HASHFAILED);
    333        }
    334 
    335 cleanup:
    336 
    337        PKIX_RETURN(LDAPREQUEST);
    338 
    339 }
    340 
    341 /*
    342 * FUNCTION: pkix_pl_LdapRequest_Equals
    343 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
    344 */
    345 static PKIX_Error *
    346 pkix_pl_LdapRequest_Equals(
    347        PKIX_PL_Object *firstObj,
    348        PKIX_PL_Object *secondObj,
    349        PKIX_Boolean *pResult,
    350        void *plContext)
    351 {
    352        PKIX_PL_LdapRequest *firstReq = NULL;
    353        PKIX_PL_LdapRequest *secondReq = NULL;
    354        PKIX_UInt32 secondType = 0;
    355        PKIX_UInt32 firstLen = 0;
    356        const unsigned char *firstData = NULL;
    357        const unsigned char *secondData = NULL;
    358        PKIX_UInt32 sizeOfLength = 0;
    359        PKIX_UInt32 dindex = 0;
    360        PKIX_UInt32 i = 0;
    361 
    362        PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Equals");
    363        PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
    364 
    365        /* test that firstObj is a LdapRequest */
    366        PKIX_CHECK(pkix_CheckType(firstObj, PKIX_LDAPREQUEST_TYPE, plContext),
    367                    PKIX_FIRSTOBJARGUMENTNOTLDAPREQUEST);
    368 
    369        /*
    370         * Since we know firstObj is a LdapRequest, if both references are
    371         * identical, they must be equal
    372         */
    373        if (firstObj == secondObj){
    374                *pResult = PKIX_TRUE;
    375                goto cleanup;
    376        }
    377 
    378        /*
    379         * If secondObj isn't a LdapRequest, we don't throw an error.
    380         * We simply return a Boolean result of FALSE
    381         */
    382        *pResult = PKIX_FALSE;
    383        PKIX_CHECK(PKIX_PL_Object_GetType
    384                    (secondObj, &secondType, plContext),
    385                    PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
    386        if (secondType != PKIX_LDAPREQUEST_TYPE) {
    387                goto cleanup;
    388        }
    389 
    390        firstReq = (PKIX_PL_LdapRequest *)firstObj;
    391        secondReq = (PKIX_PL_LdapRequest *)secondObj;
    392 
    393        /* If either lacks an encoded string, they cannot be compared */
    394        if (!(firstReq->encoded) || !(secondReq->encoded)) {
    395                goto cleanup;
    396        }
    397 
    398        if (firstReq->encoded->len != secondReq->encoded->len) {
    399                goto cleanup;
    400        }
    401 
    402        firstData = (const unsigned char *)firstReq->encoded->data;
    403        secondData = (const unsigned char *)secondReq->encoded->data;
    404 
    405        /*
    406         * Two requests that differ only in msgnum are equal! Therefore,
    407         * start the byte comparison beyond the encoded messageID field.
    408         */
    409 
    410        /* Is message length short form (one octet) or long form? */
    411        if ((firstData[1] & 0x80) != 0) {
    412                sizeOfLength = firstData[1] & 0x7F;
    413                for (dindex = 0; dindex < sizeOfLength; dindex++) {
    414                        firstLen = (firstLen << 8) + firstData[dindex + 2];
    415                }
    416        } else {
    417                firstLen = firstData[1];
    418        }
    419 
    420        /* How many bytes for the messageID? (Assume short form) */
    421        i = firstData[dindex + 3] + 2;
    422        dindex += i;
    423        firstLen -= i;
    424        firstData = &firstData[dindex + 2];
    425 
    426        /*
    427         * In theory, we have to calculate where the second message data
    428         * begins by checking its length encodings. But if these messages
    429         * are equal, we can re-use the calculation we already did. If they
    430         * are not equal, the byte comparisons will surely fail.
    431         */
    432 
    433        secondData = &secondData[dindex + 2];
    434        
    435        for (i = 0; i < firstLen; i++) {
    436                if (firstData[i] != secondData[i]) {
    437                        goto cleanup;
    438                }
    439        }
    440 
    441        *pResult = PKIX_TRUE;
    442 
    443 cleanup:
    444 
    445        PKIX_RETURN(LDAPREQUEST);
    446 }
    447 
    448 /*
    449 * FUNCTION: pkix_pl_LdapRequest_RegisterSelf
    450 * DESCRIPTION:
    451 *  Registers PKIX_LDAPREQUEST_TYPE and its related functions with
    452 *  systemClasses[]
    453 * PARAMETERS:
    454 *  "plContext"
    455 *      Platform-specific context pointer.
    456 * THREAD SAFETY:
    457 *  Not Thread Safe - for performance and complexity reasons
    458 *
    459 *  Since this function is only called by PKIX_PL_Initialize, which should
    460 *  only be called once, it is acceptable that this function is not
    461 *  thread-safe.
    462 */
    463 PKIX_Error *
    464 pkix_pl_LdapRequest_RegisterSelf(void *plContext)
    465 {
    466        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
    467        pkix_ClassTable_Entry entry;
    468 
    469        PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_RegisterSelf");
    470 
    471        entry.description = "LdapRequest";
    472        entry.objCounter = 0;
    473        entry.typeObjectSize = sizeof(PKIX_PL_LdapRequest);
    474        entry.destructor = pkix_pl_LdapRequest_Destroy;
    475        entry.equalsFunction = pkix_pl_LdapRequest_Equals;
    476        entry.hashcodeFunction = pkix_pl_LdapRequest_Hashcode;
    477        entry.toStringFunction = NULL;
    478        entry.comparator = NULL;
    479        entry.duplicateFunction = pkix_duplicateImmutable;
    480 
    481        systemClasses[PKIX_LDAPREQUEST_TYPE] = entry;
    482 
    483        PKIX_RETURN(LDAPREQUEST);
    484 }
    485 
    486 /* --Public-Functions------------------------------------------------------- */
    487 
    488 /*
    489 * FUNCTION: pkix_pl_LdapRequest_Create
    490 * DESCRIPTION:
    491 *
    492 *  This function creates an LdapRequest using the PLArenaPool pointed to by
    493 *  "arena", a message number whose value is "msgnum", a base object pointed to
    494 *  by "issuerDN", a scope whose value is "scope", a derefAliases flag whose
    495 *  value is "derefAliases", a sizeLimit whose value is "sizeLimit", a timeLimit
    496 *  whose value is "timeLimit", an attrsOnly flag whose value is "attrsOnly", a
    497 *  filter whose value is "filter", and attribute bits whose value is
    498 *  "attrBits"; storing the result at "pRequestMsg".
    499 *
    500 *  See pkix_pl_ldaptemplates.c (and below) for the ASN.1 representation of
    501 *  message components, and see pkix_pl_ldapt.h for data types.
    502 *
    503 * PARAMETERS
    504 *  "arena"
    505 *      The address of the PLArenaPool to be used in the encoding. Must be
    506 *      non-NULL.
    507 *  "msgnum"
    508 *      The UInt32 message number to be used for the messageID component of the
    509 *      LDAP message exchange.
    510 *  "issuerDN"
    511 *      The address of the string to be used for the baseObject component of the
    512 *      LDAP SearchRequest message. Must be non-NULL.
    513 *  "scope"
    514 *      The (enumerated) ScopeType to be used for the scope component of the
    515 *      LDAP SearchRequest message
    516 *  "derefAliases"
    517 *      The (enumerated) DerefType to be used for the derefAliases component of
    518 *      the LDAP SearchRequest message
    519 *  "sizeLimit"
    520 *      The UInt32 value to be used for the sizeLimit component of the LDAP
    521 *      SearchRequest message
    522 *  "timeLimit"
    523 *      The UInt32 value to be used for the timeLimit component of the LDAP
    524 *      SearchRequest message
    525 *  "attrsOnly"
    526 *      The Boolean value to be used for the attrsOnly component of the LDAP
    527 *      SearchRequest message
    528 *  "filter"
    529 *      The filter to be used for the filter component of the LDAP
    530 *      SearchRequest message
    531 *  "attrBits"
    532 *      The LdapAttrMask bits indicating the attributes to be included in the
    533 *      attributes sequence of the LDAP SearchRequest message
    534 *  "pRequestMsg"
    535 *      The address at which the address of the LdapRequest is stored. Must
    536 *      be non-NULL.
    537 *  "plContext"
    538 *      Platform-specific context pointer.
    539 * THREAD SAFETY:
    540 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    541 * RETURNS:
    542 *  Returns NULL if the function succeeds.
    543 *  Returns an LdapRequest Error if the function fails in a non-fatal way.
    544 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    545 */
    546 /*
    547 * SearchRequest ::=
    548 *      [APPLICATION 3] SEQUENCE {
    549 *              baseObject      LDAPDN,
    550 *              scope           ENUMERATED {
    551 *                                      baseObject              (0),
    552 *                                      singleLevel             (1),
    553 *                                      wholeSubtree            (2)
    554 *                              },
    555 *              derefAliases    ENUMERATED {
    556 *                                      neverDerefAliases       (0),
    557 *                                      derefInSearching        (1),
    558 *                                      derefFindingBaseObj     (2),
    559 *                                      alwaysDerefAliases      (3)
    560 *                              },
    561 *              sizeLimit       INTEGER (0 .. MAXINT),
    562 *                              -- value of 0 implies no sizeLimit
    563 *              timeLimit       INTEGER (0 .. MAXINT),
    564 *                              -- value of 0 implies no timeLimit
    565 *              attrsOnly       BOOLEAN,
    566 *                              -- TRUE, if only attributes (without values)
    567 *                              -- to be returned
    568 *              filter          Filter,
    569 *              attributes      SEQUENCE OF AttributeType
    570 *      }
    571 *
    572 * Filter ::=
    573 *      CHOICE {
    574 *              and             [0] SET OF Filter,
    575 *              or              [1] SET OF Filter,
    576 *              not             [2] Filter,
    577 *              equalityMatch   [3] AttributeValueAssertion,
    578 *              substrings      [4] SubstringFilter,
    579 *              greaterOrEqual  [5] AttributeValueAssertion,
    580 *              lessOrEqual     [6] AttributeValueAssertion,
    581 *              present         [7] AttributeType,
    582 *              approxMatch     [8] AttributeValueAssertion
    583 *      }
    584 *
    585 * SubstringFilter ::=
    586 *      SEQUENCE {
    587 *              type            AttributeType,
    588 *              SEQUENCE OF CHOICE {
    589 *                      initial [0] LDAPString,
    590 *                      any     [1] LDAPString,
    591 *                      final   [2] LDAPString,
    592 *              }
    593 *      }
    594 *
    595 * AttributeValueAssertion ::=
    596 *      SEQUENCE {
    597 *              attributeType   AttributeType,
    598 *              attributeValue  AttributeValue,
    599 *      }
    600 *
    601 * AttributeValue ::= OCTET STRING
    602 *
    603 * AttributeType ::= LDAPString
    604 *               -- text name of the attribute, or dotted
    605 *               -- OID representation
    606 *
    607 * LDAPDN ::= LDAPString
    608 *
    609 * LDAPString ::= OCTET STRING
    610 *
    611 */
    612 PKIX_Error *
    613 pkix_pl_LdapRequest_Create(
    614        PLArenaPool *arena,
    615        PKIX_UInt32 msgnum,
    616        char *issuerDN,
    617        ScopeType scope,
    618        DerefType derefAliases,
    619        PKIX_UInt32 sizeLimit,
    620        PKIX_UInt32 timeLimit,
    621        char attrsOnly,
    622        LDAPFilter *filter,
    623        LdapAttrMask attrBits,
    624        PKIX_PL_LdapRequest **pRequestMsg,
    625        void *plContext)
    626 {
    627        LDAPMessage msg;
    628        LDAPSearch *search;
    629        PKIX_PL_LdapRequest *ldapRequest = NULL;
    630        char scopeTypeAsChar;
    631        char derefAliasesTypeAsChar;
    632        SECItem *attrArray[MAX_LDAPATTRS + 1];
    633 
    634        PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Create");
    635        PKIX_NULLCHECK_THREE(arena, issuerDN, pRequestMsg);
    636 
    637        /* create a PKIX_PL_LdapRequest object */
    638        PKIX_CHECK(PKIX_PL_Object_Alloc
    639                    (PKIX_LDAPREQUEST_TYPE,
    640                    sizeof (PKIX_PL_LdapRequest),
    641                    (PKIX_PL_Object **)&ldapRequest,
    642                    plContext),
    643                    PKIX_COULDNOTCREATEOBJECT);
    644 
    645        ldapRequest->arena = arena;
    646        ldapRequest->msgnum = msgnum;
    647        ldapRequest->issuerDN = issuerDN;
    648        ldapRequest->scope = scope;
    649        ldapRequest->derefAliases = derefAliases;
    650        ldapRequest->sizeLimit = sizeLimit;
    651        ldapRequest->timeLimit = timeLimit;
    652        ldapRequest->attrsOnly = attrsOnly;
    653        ldapRequest->filter = filter;
    654        ldapRequest->attrBits = attrBits;
    655 
    656        ldapRequest->attrArray = attrArray;
    657 
    658        PKIX_CHECK(pkix_pl_LdapRequest_EncodeAttrs
    659                (ldapRequest, plContext),
    660                PKIX_LDAPREQUESTENCODEATTRSFAILED);
    661 
    662        PKIX_PL_NSSCALL
    663                (LDAPREQUEST, PORT_Memset, (&msg, 0, sizeof (LDAPMessage)));
    664 
    665        msg.messageID.type = siUnsignedInteger;
    666        msg.messageID.data = (void*)&msgnum;
    667        msg.messageID.len = sizeof (msgnum);
    668 
    669        msg.protocolOp.selector = LDAP_SEARCH_TYPE;
    670 
    671        search = &(msg.protocolOp.op.searchMsg);
    672 
    673        search->baseObject.type = siAsciiString;
    674        search->baseObject.data = (void *)issuerDN;
    675        search->baseObject.len = PL_strlen(issuerDN);
    676        scopeTypeAsChar = (char)scope;
    677        search->scope.type = siUnsignedInteger;
    678        search->scope.data = (void *)&scopeTypeAsChar;
    679        search->scope.len = sizeof (scopeTypeAsChar);
    680        derefAliasesTypeAsChar = (char)derefAliases;
    681        search->derefAliases.type = siUnsignedInteger;
    682        search->derefAliases.data =
    683                (void *)&derefAliasesTypeAsChar;
    684        search->derefAliases.len =
    685                sizeof (derefAliasesTypeAsChar);
    686        search->sizeLimit.type = siUnsignedInteger;
    687        search->sizeLimit.data = (void *)&sizeLimit;
    688        search->sizeLimit.len = sizeof (PKIX_UInt32);
    689        search->timeLimit.type = siUnsignedInteger;
    690        search->timeLimit.data = (void *)&timeLimit;
    691        search->timeLimit.len = sizeof (PKIX_UInt32);
    692        search->attrsOnly.type = siBuffer;
    693        search->attrsOnly.data = (void *)&attrsOnly;
    694        search->attrsOnly.len = sizeof (attrsOnly);
    695 
    696        PKIX_PL_NSSCALL
    697                (LDAPREQUEST,
    698                PORT_Memcpy,
    699                (&search->filter, filter, sizeof (LDAPFilter)));
    700 
    701        search->attributes = attrArray;
    702 
    703        PKIX_PL_NSSCALLRV
    704                (LDAPREQUEST, ldapRequest->encoded, SEC_ASN1EncodeItem,
    705                (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate));
    706 
    707        if (!(ldapRequest->encoded)) {
    708                PKIX_ERROR(PKIX_FAILEDINENCODINGSEARCHREQUEST);
    709        }
    710 
    711        *pRequestMsg = ldapRequest;
    712 
    713 cleanup:
    714 
    715        if (PKIX_ERROR_RECEIVED) {
    716                PKIX_DECREF(ldapRequest);
    717        }
    718 
    719        PKIX_RETURN(LDAPREQUEST);
    720 }
    721 
    722 /*
    723 * FUNCTION: pkix_pl_LdapRequest_GetEncoded
    724 * DESCRIPTION:
    725 *
    726 *  This function obtains the encoded message from the LdapRequest pointed to
    727 *  by "request", storing the result at "pRequestBuf".
    728 *
    729 * PARAMETERS
    730 *  "request"
    731 *      The address of the LdapRequest whose encoded message is to be
    732 *      retrieved. Must be non-NULL.
    733 *  "pRequestBuf"
    734 *      The address at which is stored the address of the encoded message. Must
    735 *      be non-NULL.
    736 *  "plContext"
    737 *      Platform-specific context pointer.
    738 * THREAD SAFETY:
    739 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    740 * RETURNS:
    741 *  Returns NULL if the function succeeds.
    742 *  Returns an LdapRequest Error if the function fails in a non-fatal way.
    743 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    744 */
    745 PKIX_Error *
    746 pkix_pl_LdapRequest_GetEncoded(
    747        PKIX_PL_LdapRequest *request,
    748        SECItem **pRequestBuf,
    749        void *plContext)
    750 {
    751        PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_GetEncoded");
    752        PKIX_NULLCHECK_TWO(request, pRequestBuf);
    753 
    754        *pRequestBuf = request->encoded;
    755 
    756        PKIX_RETURN(LDAPREQUEST);
    757 }