tor-browser

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

pkix_pl_ldapresponse.c (26342B)


      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_ldapresponse.c
      6 *
      7 */
      8 
      9 #include <fcntl.h>
     10 #include "pkix_pl_ldapresponse.h"
     11 
     12 /* --Private-LdapResponse-Functions------------------------------------- */
     13 
     14 /*
     15 * FUNCTION: pkix_pl_LdapResponse_Destroy
     16 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
     17 */
     18 static PKIX_Error *
     19 pkix_pl_LdapResponse_Destroy(
     20        PKIX_PL_Object *object,
     21        void *plContext)
     22 {
     23        PKIX_PL_LdapResponse *ldapRsp = NULL;
     24        LDAPMessage *m = NULL;
     25        LDAPSearchResponseEntry *entry = NULL;
     26        LDAPSearchResponseResult *result = NULL;
     27        LDAPSearchResponseAttr **attributes = NULL;
     28        LDAPSearchResponseAttr *attr = NULL;
     29        SECItem **valp = NULL;
     30        SECItem *val = NULL;
     31 
     32        PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Destroy");
     33        PKIX_NULLCHECK_ONE(object);
     34 
     35        PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPRESPONSE_TYPE, plContext),
     36                    PKIX_OBJECTNOTLDAPRESPONSE);
     37 
     38        ldapRsp = (PKIX_PL_LdapResponse *)object;
     39 
     40        m = &ldapRsp->decoded;
     41 
     42        if (m->messageID.data != NULL) {
     43                PR_Free(m->messageID.data);
     44        }
     45 
     46        if (m->protocolOp.selector ==
     47                LDAP_SEARCHRESPONSEENTRY_TYPE) {
     48                entry = &m->protocolOp.op.searchResponseEntryMsg;
     49                if (entry->objectName.data != NULL) {
     50                        PR_Free(entry->objectName.data);
     51                }
     52                if (entry->attributes != NULL) {
     53                        for (attributes = entry->attributes;
     54                                *attributes != NULL;
     55                                attributes++) {
     56                                attr = *attributes;
     57                                PR_Free(attr->attrType.data);
     58                                for (valp = attr->val; *valp != NULL; valp++) {
     59                                        val = *valp;
     60                                        if (val->data != NULL) {
     61                                                PR_Free(val->data);
     62                                        }
     63                                        PR_Free(val);
     64                                }
     65                                PR_Free(attr->val);
     66                                PR_Free(attr);
     67                        }
     68                        PR_Free(entry->attributes);
     69                }
     70        } else if (m->protocolOp.selector ==
     71                LDAP_SEARCHRESPONSERESULT_TYPE) {
     72                result = &m->protocolOp.op.searchResponseResultMsg;
     73                if (result->resultCode.data != NULL) {
     74                        PR_Free(result->resultCode.data);
     75                }
     76        }
     77 
     78        PKIX_FREE(ldapRsp->derEncoded.data);
     79 
     80 cleanup:
     81 
     82        PKIX_RETURN(LDAPRESPONSE);
     83 }
     84 
     85 /*
     86 * FUNCTION: pkix_pl_LdapResponse_Hashcode
     87 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
     88 */
     89 static PKIX_Error *
     90 pkix_pl_LdapResponse_Hashcode(
     91        PKIX_PL_Object *object,
     92        PKIX_UInt32 *pHashcode,
     93        void *plContext)
     94 {
     95        PKIX_UInt32 dataLen = 0;
     96        PKIX_UInt32 dindex = 0;
     97        PKIX_UInt32 sizeOfLength = 0;
     98        PKIX_UInt32 idLen = 0;
     99        const unsigned char *msgBuf = NULL;
    100        PKIX_PL_LdapResponse *ldapRsp = NULL;
    101 
    102        PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Hashcode");
    103        PKIX_NULLCHECK_TWO(object, pHashcode);
    104 
    105        PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPRESPONSE_TYPE, plContext),
    106                    PKIX_OBJECTNOTLDAPRESPONSE);
    107 
    108        ldapRsp = (PKIX_PL_LdapResponse *)object;
    109 
    110        *pHashcode = 0;
    111 
    112        /*
    113         * Two responses that differ only in msgnum are a match! Therefore,
    114         * start hashcoding beyond the encoded messageID field.
    115         */
    116        if (ldapRsp->derEncoded.data) {
    117                msgBuf = (const unsigned char *)ldapRsp->derEncoded.data;
    118                /* Is message length short form (one octet) or long form? */
    119                if ((msgBuf[1] & 0x80) != 0) {
    120                        sizeOfLength = msgBuf[1] & 0x7F;
    121                        for (dindex = 0; dindex < sizeOfLength; dindex++) {
    122                                dataLen = (dataLen << 8) + msgBuf[dindex + 2];
    123                        }
    124                } else {
    125                        dataLen = msgBuf[1];
    126                }
    127 
    128                /* How many bytes for the messageID? (Assume short form) */
    129                idLen = msgBuf[dindex + 3] + 2;
    130                dindex += idLen;
    131                dataLen -= idLen;
    132                msgBuf = &msgBuf[dindex + 2];
    133 
    134                PKIX_CHECK(pkix_hash(msgBuf, dataLen, pHashcode, plContext),
    135                        PKIX_HASHFAILED);
    136        }
    137 
    138 cleanup:
    139 
    140        PKIX_RETURN(LDAPRESPONSE);
    141 
    142 }
    143 
    144 /*
    145 * FUNCTION: pkix_pl_LdapResponse_Equals
    146 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
    147 */
    148 static PKIX_Error *
    149 pkix_pl_LdapResponse_Equals(
    150        PKIX_PL_Object *firstObj,
    151        PKIX_PL_Object *secondObj,
    152        PKIX_Boolean *pResult,
    153        void *plContext)
    154 {
    155        PKIX_PL_LdapResponse *rsp1 = NULL;
    156        PKIX_PL_LdapResponse *rsp2 = NULL;
    157        PKIX_UInt32 secondType = 0;
    158        PKIX_UInt32 firstLen = 0;
    159        const unsigned char *firstData = NULL;
    160        const unsigned char *secondData = NULL;
    161        PKIX_UInt32 sizeOfLength = 0;
    162        PKIX_UInt32 dindex = 0;
    163        PKIX_UInt32 i = 0;
    164 
    165        PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Equals");
    166        PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
    167 
    168        /* test that firstObj is a LdapResponse */
    169        PKIX_CHECK(pkix_CheckType(firstObj, PKIX_LDAPRESPONSE_TYPE, plContext),
    170                    PKIX_FIRSTOBJARGUMENTNOTLDAPRESPONSE);
    171 
    172        /*
    173         * Since we know firstObj is a LdapResponse, if both references are
    174         * identical, they must be equal
    175         */
    176        if (firstObj == secondObj){
    177                *pResult = PKIX_TRUE;
    178                goto cleanup;
    179        }
    180 
    181        /*
    182         * If secondObj isn't a LdapResponse, we don't throw an error.
    183         * We simply return a Boolean result of FALSE
    184         */
    185        *pResult = PKIX_FALSE;
    186        PKIX_CHECK(PKIX_PL_Object_GetType(secondObj, &secondType, plContext),
    187                PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
    188        if (secondType != PKIX_LDAPRESPONSE_TYPE) {
    189                goto cleanup;
    190        }
    191 
    192        rsp1 = (PKIX_PL_LdapResponse *)firstObj;
    193        rsp2 = (PKIX_PL_LdapResponse *)secondObj;
    194 
    195        /* If either lacks an encoded string, they cannot be compared */
    196        if (!(rsp1->derEncoded.data) || !(rsp2->derEncoded.data)) {
    197                goto cleanup;
    198        }
    199 
    200        if (rsp1->derEncoded.len != rsp2->derEncoded.len) {
    201                goto cleanup;
    202        }
    203 
    204        firstData = (const unsigned char *)rsp1->derEncoded.data;
    205        secondData = (const unsigned char *)rsp2->derEncoded.data;
    206 
    207        /*
    208         * Two responses that differ only in msgnum are equal! Therefore,
    209         * start the byte comparison beyond the encoded messageID field.
    210         */
    211 
    212        /* Is message length short form (one octet) or long form? */
    213        if ((firstData[1] & 0x80) != 0) {
    214                sizeOfLength = firstData[1] & 0x7F;
    215                for (dindex = 0; dindex < sizeOfLength; dindex++) {
    216                        firstLen = (firstLen << 8) + firstData[dindex + 2];
    217                }
    218        } else {
    219                firstLen = firstData[1];
    220        }
    221 
    222        /* How many bytes for the messageID? (Assume short form) */
    223        i = firstData[dindex + 3] + 2;
    224        dindex += i;
    225        firstLen -= i;
    226        firstData = &firstData[dindex + 2];
    227 
    228        /*
    229         * In theory, we have to calculate where the second message data
    230         * begins by checking its length encodings. But if these messages
    231         * are equal, we can re-use the calculation we already did. If they
    232         * are not equal, the byte comparisons will surely fail.
    233         */
    234 
    235        secondData = &secondData[dindex + 2];
    236        
    237        for (i = 0; i < firstLen; i++) {
    238                if (firstData[i] != secondData[i]) {
    239                        goto cleanup;
    240                }
    241        }
    242 
    243        *pResult = PKIX_TRUE;
    244 
    245 cleanup:
    246 
    247        PKIX_RETURN(LDAPRESPONSE);
    248 }
    249 
    250 /*
    251 * FUNCTION: pkix_pl_LdapResponse_RegisterSelf
    252 * DESCRIPTION:
    253 *  Registers PKIX_LDAPRESPONSE_TYPE and its related functions with
    254 *  systemClasses[]
    255 * PARAMETERS:
    256 *  "plContext"
    257 *      Platform-specific context pointer.
    258 * THREAD SAFETY:
    259 *  Not Thread Safe - for performance and complexity reasons
    260 *
    261 *  Since this function is only called by PKIX_PL_Initialize, which should
    262 *  only be called once, it is acceptable that this function is not
    263 *  thread-safe.
    264 */
    265 PKIX_Error *
    266 pkix_pl_LdapResponse_RegisterSelf(void *plContext)
    267 {
    268        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
    269        pkix_ClassTable_Entry entry;
    270 
    271        PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_RegisterSelf");
    272 
    273        entry.description = "LdapResponse";
    274        entry.objCounter = 0;
    275        entry.typeObjectSize = sizeof(PKIX_PL_LdapResponse);
    276        entry.destructor = pkix_pl_LdapResponse_Destroy;
    277        entry.equalsFunction = pkix_pl_LdapResponse_Equals;
    278        entry.hashcodeFunction = pkix_pl_LdapResponse_Hashcode;
    279        entry.toStringFunction = NULL;
    280        entry.comparator = NULL;
    281        entry.duplicateFunction = pkix_duplicateImmutable;
    282 
    283        systemClasses[PKIX_LDAPRESPONSE_TYPE] = entry;
    284 
    285        PKIX_RETURN(LDAPRESPONSE);
    286 }
    287 
    288 /* --Public-Functions------------------------------------------------------- */
    289 
    290 /*
    291 * FUNCTION: pkix_pl_LdapResponse_Create
    292 * DESCRIPTION:
    293 *
    294 *  This function creates an LdapResponse for the LDAPMessageType provided in
    295 *  "responseType" and a buffer capacity provided by "totalLength". It copies
    296 *  into its buffer either "totalLength" or "bytesAvailable" bytes, whichever
    297 *  is less, from the buffer pointed to by "partialData", storing the number of
    298 *  bytes copied at "pBytesConsumed" and storing the address of the LdapResponse
    299 *  at "pLdapResponse".
    300 *
    301 *  If a message is complete in a single I/O buffer, the LdapResponse will be
    302 *  complete when this function returns. If the message carries over into
    303 *  additional buffers, their contents will be added to the LdapResponse by
    304 *  susequent calls to pkix_pl_LdapResponse_Append.
    305 *
    306 * PARAMETERS
    307 *  "responseType"
    308 *      The value of the message type (LDAP_SEARCHRESPONSEENTRY_TYPE or
    309 *      LDAP_SEARCHRESPONSERESULT_TYPE) for the LdapResponse being created
    310 *  "totalLength"
    311 *      The UInt32 value for the total length of the encoded message to be
    312 *      stored in the LdapResponse
    313 *  "bytesAvailable"
    314 *      The UInt32 value for the number of bytes of data available in the
    315 *      current buffer.
    316 *  "partialData"
    317 *      The address from which data is to be copied.
    318 *  "pBytesConsumed"
    319 *      The address at which is stored the UInt32 number of bytes taken from the
    320 *      current buffer. If this number is less than "bytesAvailable", then bytes
    321 *      remain in the buffer for the next LdapResponse. Must be non-NULL.
    322 *  "pLdapResponse"
    323 *      The address where the created LdapResponse is stored. Must be non-NULL.
    324 *  "plContext"
    325 *      Platform-specific context pointer.
    326 * THREAD SAFETY:
    327 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    328 * RETURNS:
    329 *  Returns NULL if the function succeeds.
    330 *  Returns an LdapResponse Error if the function fails in a non-fatal way.
    331 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    332 */
    333 PKIX_Error *
    334 pkix_pl_LdapResponse_Create(
    335        LDAPMessageType responseType,
    336        PKIX_UInt32 totalLength,
    337        PKIX_UInt32 bytesAvailable,
    338        void *partialData,
    339        PKIX_UInt32 *pBytesConsumed,
    340        PKIX_PL_LdapResponse **pLdapResponse,
    341        void *plContext)
    342 {
    343        PKIX_UInt32 bytesConsumed = 0;
    344        PKIX_PL_LdapResponse *ldapResponse = NULL;
    345        void *data = NULL;
    346 
    347        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Create");
    348        PKIX_NULLCHECK_ONE(pLdapResponse);
    349 
    350        if (bytesAvailable <= totalLength) {
    351                bytesConsumed = bytesAvailable;
    352        } else {
    353                bytesConsumed = totalLength;
    354        }
    355 
    356        /* create a PKIX_PL_LdapResponse object */
    357        PKIX_CHECK(PKIX_PL_Object_Alloc
    358                    (PKIX_LDAPRESPONSE_TYPE,
    359                    sizeof (PKIX_PL_LdapResponse),
    360                    (PKIX_PL_Object **)&ldapResponse,
    361                    plContext),
    362                    PKIX_COULDNOTCREATEOBJECT);
    363 
    364        ldapResponse->decoded.protocolOp.selector = responseType;
    365        ldapResponse->totalLength = totalLength;
    366        ldapResponse->partialLength = bytesConsumed;
    367 
    368        if (totalLength != 0){
    369                /* Alloc space for array */
    370                PKIX_NULLCHECK_ONE(partialData);
    371 
    372                PKIX_CHECK(PKIX_PL_Malloc
    373                    (totalLength,
    374                    &data,
    375                    plContext),
    376                    PKIX_MALLOCFAILED);
    377 
    378                PKIX_PL_NSSCALL
    379                    (LDAPRESPONSE,
    380                    PORT_Memcpy,
    381                    (data, partialData, bytesConsumed));
    382        }
    383 
    384        ldapResponse->derEncoded.type = siBuffer;
    385        ldapResponse->derEncoded.data = data;
    386        ldapResponse->derEncoded.len = totalLength;
    387        *pBytesConsumed = bytesConsumed;
    388        *pLdapResponse = ldapResponse;
    389 
    390 cleanup:
    391 
    392        if (PKIX_ERROR_RECEIVED){
    393                PKIX_DECREF(ldapResponse);
    394        }
    395 
    396        PKIX_RETURN(LDAPRESPONSE);
    397 }
    398 
    399 /*
    400 * FUNCTION: pkix_pl_LdapResponse_Append
    401 * DESCRIPTION:
    402 *
    403 *  This function updates the LdapResponse pointed to by "response" with up to
    404 *  "incrLength" from the buffer pointer to by "incrData", storing the number of
    405 *  bytes copied at "pBytesConsumed".
    406 *
    407 * PARAMETERS
    408 *  "response"
    409 *      The address of the LdapResponse being updated. Must be non-zero.
    410 *  "incrLength"
    411 *      The UInt32 value for the number of bytes of data available in the
    412 *      current buffer.
    413 *  "incrData"
    414 *      The address from which data is to be copied.
    415 *  "pBytesConsumed"
    416 *      The address at which is stored the UInt32 number of bytes taken from the
    417 *      current buffer. If this number is less than "incrLength", then bytes
    418 *      remain in the buffer for the next LdapResponse. Must be non-NULL.
    419 *  "plContext"
    420 *      Platform-specific context pointer.
    421 * THREAD SAFETY:
    422 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    423 * RETURNS:
    424 *  Returns NULL if the function succeeds.
    425 *  Returns an LdapResponse Error if the function fails in a non-fatal way.
    426 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    427 */
    428 PKIX_Error *
    429 pkix_pl_LdapResponse_Append(
    430        PKIX_PL_LdapResponse *response,
    431        PKIX_UInt32 incrLength,
    432        void *incrData,
    433        PKIX_UInt32 *pBytesConsumed,
    434        void *plContext)
    435 {
    436        PKIX_UInt32 newPartialLength = 0;
    437        PKIX_UInt32 bytesConsumed = 0;
    438        void *dest = NULL;
    439 
    440        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Append");
    441        PKIX_NULLCHECK_TWO(response, pBytesConsumed);
    442 
    443        if (incrLength > 0) {
    444 
    445                /* Calculate how many bytes we have room for. */
    446                bytesConsumed =
    447                        response->totalLength - response->partialLength;
    448 
    449                if (bytesConsumed > incrLength) {
    450                        bytesConsumed = incrLength;
    451                }
    452 
    453                newPartialLength = response->partialLength + bytesConsumed;
    454 
    455                PKIX_NULLCHECK_ONE(incrData);
    456 
    457                dest = &(((char *)response->derEncoded.data)[
    458                        response->partialLength]);
    459 
    460                PKIX_PL_NSSCALL
    461                        (LDAPRESPONSE,
    462                        PORT_Memcpy,
    463                        (dest, incrData, bytesConsumed));
    464 
    465                response->partialLength = newPartialLength;
    466        }
    467 
    468        *pBytesConsumed = bytesConsumed;
    469 
    470        PKIX_RETURN(LDAPRESPONSE);
    471 }
    472 
    473 /*
    474 * FUNCTION: pkix_pl_LdapResponse_IsComplete
    475 * DESCRIPTION:
    476 *
    477 *  This function determines whether the LdapResponse pointed to by "response"
    478 *  contains all the data called for by the "totalLength" parameter provided
    479 *  when it was created, storing PKIX_TRUE at "pIsComplete" if so, and
    480 *  PKIX_FALSE otherwise.
    481 *
    482 * PARAMETERS
    483 *  "response"
    484 *      The address of the LdapResponse being evaluaTED. Must be non-zero.
    485 *  "incrLength"
    486 *      The UInt32 value for the number of bytes of data available in the
    487 *      current buffer.
    488 *  "incrData"
    489 *      The address from which data is to be copied.
    490 *  "pIsComplete"
    491 *      The address at which is stored the Boolean indication of whether the
    492 *      LdapResponse is complete. Must be non-NULL.
    493 *  "plContext"
    494 *      Platform-specific context pointer.
    495 * THREAD SAFETY:
    496 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    497 * RETURNS:
    498 *  Returns NULL if the function succeeds.
    499 *  Returns an LdapResponse Error if the function fails in a non-fatal way.
    500 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    501 */
    502 PKIX_Error *
    503 pkix_pl_LdapResponse_IsComplete(
    504        PKIX_PL_LdapResponse *response,
    505        PKIX_Boolean *pIsComplete,
    506        void *plContext)
    507 {
    508        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_IsComplete");
    509        PKIX_NULLCHECK_TWO(response, pIsComplete);
    510 
    511        if (response->totalLength == response->partialLength) {
    512                *pIsComplete = PKIX_TRUE;
    513        } else {
    514                *pIsComplete = PKIX_FALSE;
    515        }
    516 
    517        PKIX_RETURN(LDAPRESPONSE);
    518 }
    519 
    520 /*
    521 * FUNCTION: pkix_pl_LdapResponse_Decode
    522 * DESCRIPTION:
    523 *
    524 *  This function decodes the DER data contained in the LdapResponse pointed to
    525 *  by "response", using the arena pointed to by "arena", and storing at
    526 *  "pStatus" SECSuccess if the decoding was successful and SECFailure
    527 *  otherwise. The decoded message is stored in an element of "response".
    528 *
    529 * PARAMETERS
    530 *  "arena"
    531 *      The address of the PLArenaPool to be used in the decoding. Must be
    532 *      non-NULL.
    533 *  "response"
    534 *      The address of the LdapResponse whose DER data is to be decoded. Must
    535 *      be non-NULL.
    536 *  "pStatus"
    537 *      The address at which is stored the status from the decoding, SECSuccess
    538 *      if successful, SECFailure otherwise. Must be non-NULL.
    539 *  "plContext"
    540 *      Platform-specific context pointer.
    541 * THREAD SAFETY:
    542 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    543 * RETURNS:
    544 *  Returns NULL if the function succeeds.
    545 *  Returns an LdapResponse Error if the function fails in a non-fatal way.
    546 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    547 */
    548 PKIX_Error *
    549 pkix_pl_LdapResponse_Decode(
    550        PLArenaPool *arena,
    551        PKIX_PL_LdapResponse *response,
    552        SECStatus *pStatus,
    553        void *plContext)
    554 {
    555        LDAPMessage *msg;
    556        SECStatus rv = SECFailure;
    557 
    558        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Decode");
    559        PKIX_NULLCHECK_THREE(arena, response, pStatus);
    560 
    561        if (response->totalLength != response->partialLength) {
    562                PKIX_ERROR(PKIX_ATTEMPTTODECODEANINCOMPLETERESPONSE);
    563        }
    564 
    565        msg = &(response->decoded);
    566 
    567        PKIX_PL_NSSCALL
    568                (LDAPRESPONSE, PORT_Memset, (msg, 0, sizeof (LDAPMessage)));
    569 
    570        PKIX_PL_NSSCALLRV(LDAPRESPONSE, rv, SEC_ASN1DecodeItem,
    571            (NULL, msg, PKIX_PL_LDAPMessageTemplate, &(response->derEncoded)));
    572 
    573        *pStatus = rv;
    574 cleanup:
    575 
    576        PKIX_RETURN(LDAPRESPONSE);
    577 }
    578 
    579 /*
    580 * FUNCTION: pkix_pl_LdapResponse_GetMessage
    581 * DESCRIPTION:
    582 *
    583 *  This function obtains the decoded message from the LdapResponse pointed to
    584 *  by "response", storing the result at "pMessage".
    585 *
    586 * PARAMETERS
    587 *  "response"
    588 *      The address of the LdapResponse whose decoded message is to be
    589 *      retrieved. Must be non-NULL.
    590 *  "pMessage"
    591 *      The address at which is stored the address of the decoded message. Must
    592 *      be non-NULL.
    593 *  "plContext"
    594 *      Platform-specific context pointer.
    595 * THREAD SAFETY:
    596 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    597 * RETURNS:
    598 *  Returns NULL if the function succeeds.
    599 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    600 */
    601 PKIX_Error *
    602 pkix_pl_LdapResponse_GetMessage(
    603        PKIX_PL_LdapResponse *response,
    604        LDAPMessage **pMessage,
    605        void *plContext)
    606 {
    607        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetMessage");
    608        PKIX_NULLCHECK_TWO(response, pMessage);
    609 
    610        *pMessage = &response->decoded;
    611 
    612        PKIX_RETURN(LDAPRESPONSE);
    613 }
    614 
    615 /*
    616 * FUNCTION: pkix_pl_LdapResponse_GetCapacity
    617 * DESCRIPTION:
    618 *
    619 *  This function obtains from the LdapResponse pointed to by "response" the
    620 *  number of bytes remaining to be read, based on the totalLength that was
    621 *  provided to LdapResponse_Create and the data subsequently provided to
    622 *  LdapResponse_Append, storing the result at "pMessage".
    623 *
    624 * PARAMETERS
    625 *  "response"
    626 *      The address of the LdapResponse whose remaining capacity is to be
    627 *      retrieved. Must be non-NULL.
    628 *  "pCapacity"
    629 *      The address at which is stored the address of the decoded message. Must
    630 *      be non-NULL.
    631 *  "plContext"
    632 *      Platform-specific context pointer.
    633 * THREAD SAFETY:
    634 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    635 * RETURNS:
    636 *  Returns NULL if the function succeeds.
    637 *  Returns an LdapResponse Error if the function fails in a non-fatal way.
    638 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    639 */
    640 PKIX_Error *
    641 pkix_pl_LdapResponse_GetCapacity(
    642        PKIX_PL_LdapResponse *response,
    643        PKIX_UInt32 *pCapacity,
    644        void *plContext)
    645 {
    646        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetCapacity");
    647        PKIX_NULLCHECK_TWO(response, pCapacity);
    648 
    649        *pCapacity = response->totalLength - response->partialLength;
    650 
    651        PKIX_RETURN(LDAPRESPONSE);
    652 }
    653 
    654 /*
    655 * FUNCTION: pkix_pl_LdapResponse_GetMessageType
    656 * DESCRIPTION:
    657 *
    658 *  This function obtains the message type from the LdapResponse pointed to
    659 *  by "response", storing the result at "pMessageType".
    660 *
    661 * PARAMETERS
    662 *  "response"
    663 *      The address of the LdapResponse whose message type is to be
    664 *      retrieved. Must be non-NULL.
    665 *  "pMessageType" 
    666 *      The address at which is stored the type of the response message. Must
    667 *      be non-NULL.
    668 *  "plContext"
    669 *      Platform-specific context pointer.
    670 * THREAD SAFETY:
    671 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    672 * RETURNS:
    673 *  Returns NULL if the function succeeds.
    674 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    675 */
    676 PKIX_Error *
    677 pkix_pl_LdapResponse_GetMessageType(
    678        PKIX_PL_LdapResponse *response,
    679        LDAPMessageType *pMessageType,
    680        void *plContext)
    681 {
    682        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetMessageType");
    683        PKIX_NULLCHECK_TWO(response, pMessageType);
    684 
    685        *pMessageType = response->decoded.protocolOp.selector;
    686 
    687        PKIX_RETURN(LDAPRESPONSE);
    688 }
    689 
    690 /*
    691 * FUNCTION: pkix_pl_LdapResponse_GetResultCode
    692 * DESCRIPTION:
    693 *
    694 *  This function obtains the result code from the LdapResponse pointed to
    695 *  by "response", storing the result at "pResultCode".
    696 *
    697 * PARAMETERS
    698 *  "response"
    699 *      The address of the LdapResponse whose result code is to be
    700 *      retrieved. Must be non-NULL.
    701 *  "pResultCode"
    702 *      The address at which is stored the address of the decoded message. Must
    703 *      be non-NULL.
    704 *  "plContext"
    705 *      Platform-specific context pointer.
    706 * THREAD SAFETY:
    707 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    708 * RETURNS:
    709 *  Returns NULL if the function succeeds.
    710 *  Returns an LdapResponse Error if the function fails in a non-fatal way.
    711 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    712 */
    713 PKIX_Error *
    714 pkix_pl_LdapResponse_GetResultCode(
    715        PKIX_PL_LdapResponse *response,
    716        LDAPResultCode *pResultCode,
    717        void *plContext)
    718 {
    719        LDAPMessageType messageType = 0;
    720        LDAPSearchResponseResult *resultMsg = NULL;
    721 
    722        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetResultCode");
    723        PKIX_NULLCHECK_TWO(response, pResultCode);
    724 
    725        messageType = response->decoded.protocolOp.selector;
    726 
    727        if (messageType != LDAP_SEARCHRESPONSERESULT_TYPE) {
    728                PKIX_ERROR(PKIX_GETRESULTCODECALLEDFORNONRESULTMESSAGE);
    729        }
    730 
    731        resultMsg = &response->decoded.protocolOp.op.searchResponseResultMsg;
    732 
    733        *pResultCode = *(resultMsg->resultCode.data);
    734 
    735 cleanup:
    736 
    737        PKIX_RETURN(LDAPRESPONSE);
    738 }
    739 
    740 /*
    741 * FUNCTION: pkix_pl_LdapResponse_GetAttributes
    742 * DESCRIPTION:
    743 *
    744 *  This function obtains the attributes from the LdapResponse pointed to
    745 *  by "response", storing the result at "pAttributes".
    746 *
    747 * PARAMETERS
    748 *  "response"
    749 *      The address of the LdapResponse whose decoded message is to be
    750 *      retrieved. Must be non-NULL.
    751 *  "pAttributes"
    752 *      The address at which is stored the attributes of the message. Must be
    753 *      non-NULL.
    754 *  "plContext"
    755 *      Platform-specific context pointer.
    756 * THREAD SAFETY:
    757 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    758 * RETURNS:
    759 *  Returns NULL if the function succeeds.
    760 *  Returns an LdapResponse Error if the function fails in a non-fatal way.
    761 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    762 */
    763 PKIX_Error *
    764 pkix_pl_LdapResponse_GetAttributes(
    765        PKIX_PL_LdapResponse *response,
    766        LDAPSearchResponseAttr ***pAttributes,
    767        void *plContext)
    768 {
    769        LDAPMessageType messageType = 0;
    770 
    771        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetResultCode");
    772        PKIX_NULLCHECK_TWO(response, pAttributes);
    773 
    774        messageType = response->decoded.protocolOp.selector;
    775 
    776        if (messageType != LDAP_SEARCHRESPONSEENTRY_TYPE) {
    777                PKIX_ERROR(PKIX_GETATTRIBUTESCALLEDFORNONENTRYMESSAGE);
    778        }
    779 
    780        *pAttributes = response->
    781                decoded.protocolOp.op.searchResponseEntryMsg.attributes;
    782 
    783 cleanup:
    784 
    785        PKIX_RETURN(LDAPRESPONSE);
    786 }