tor-browser

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

pkix_pl_ldapdefaultclient.c (87794B)


      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_ldapdefaultclient.c
      6 *
      7 * LDAPDefaultClient Function Definitions
      8 *
      9 */
     10 
     11 /* We can't decode the length of a message without at least this many bytes */
     12 #define MINIMUM_MSG_LENGTH 5
     13 
     14 #include "pkix_pl_ldapdefaultclient.h"
     15 
     16 /* --Private-LdapDefaultClient-Message-Building-Functions---------------- */
     17 
     18 /*
     19 * FUNCTION: pkix_pl_LdapDefaultClient_MakeBind
     20 * DESCRIPTION:
     21 *
     22 *  This function creates and encodes a Bind message, using the arena pointed
     23 *  to by "arena", the version number contained in "versionData", the
     24 *  LDAPBindAPI pointed to by "bindAPI", and the messageID contained in
     25 *  "msgNum", and stores a pointer to the encoded string at "pBindMsg".
     26 *
     27 *  See pkix_pl_ldaptemplates.c for the ASN.1 description of a Bind message.
     28 *
     29 *  This code is not used if the DefaultClient was created with a NULL pointer
     30 *  supplied for the LDAPBindAPI structure. (Bind and Unbind do not seem to be
     31 *  expected for anonymous Search requests.)
     32 *
     33 * PARAMETERS:
     34 *  "arena"
     35 *      The address of the PLArenaPool used in encoding the message. Must be
     36 *       non-NULL.
     37 *  "versionData"
     38 *      The Int32 containing the version number to be encoded in the Bind
     39 *      message.
     40 *  "bindAPI"
     41 *      The address of the LDAPBindAPI to be encoded in the Bind message. Must
     42 *      be non-NULL.
     43 *  "msgNum"
     44 *      The Int32 containing the MessageID to be encoded in the Bind message.
     45 *  "pBindMsg"
     46 *      The address at which the encoded Bind message will be stored. Must be
     47 *      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 a LdapDefaultClient Error if the function fails in a
     55 *      non-fatal way.
     56 *  Returns a Fatal Error if the function fails in an unrecoverable way.
     57 */
     58 static PKIX_Error *
     59 pkix_pl_LdapDefaultClient_MakeBind(
     60        PLArenaPool *arena,
     61        PKIX_Int32 versionData,
     62        LDAPBindAPI *bindAPI,
     63        PKIX_UInt32 msgNum,
     64        SECItem **pBindMsg,
     65        void *plContext)
     66 {
     67        LDAPMessage msg;
     68        char version = '\0';
     69        SECItem *encoded = NULL;
     70        PKIX_UInt32 len = 0;
     71 
     72        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeBind");
     73        PKIX_NULLCHECK_TWO(arena, pBindMsg);
     74 
     75        PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset,
     76                (&msg, 0, sizeof (LDAPMessage)));
     77 
     78        version = (char)versionData;
     79 
     80        msg.messageID.type = siUnsignedInteger;
     81        msg.messageID.data = (void*)&msgNum;
     82        msg.messageID.len = sizeof (msgNum);
     83 
     84        msg.protocolOp.selector = LDAP_BIND_TYPE;
     85 
     86        msg.protocolOp.op.bindMsg.version.type = siUnsignedInteger;
     87        msg.protocolOp.op.bindMsg.version.data = (void *)&version;
     88        msg.protocolOp.op.bindMsg.version.len = sizeof (char);
     89 
     90        /*
     91         * XXX At present we only know how to handle anonymous requests (no
     92         * authentication), and we are guessing how to do simple authentication.
     93         * This section will need to be revised and extended when other
     94         * authentication is needed.
     95         */
     96        if (bindAPI->selector == SIMPLE_AUTH) {
     97                msg.protocolOp.op.bindMsg.bindName.type = siAsciiString;
     98                msg.protocolOp.op.bindMsg.bindName.data =
     99                        (void *)bindAPI->chooser.simple.bindName;
    100                len = PL_strlen(bindAPI->chooser.simple.bindName);
    101                msg.protocolOp.op.bindMsg.bindName.len = len;
    102 
    103                msg.protocolOp.op.bindMsg.authentication.type = siAsciiString;
    104                msg.protocolOp.op.bindMsg.authentication.data =
    105                        (void *)bindAPI->chooser.simple.authentication;
    106                len = PL_strlen(bindAPI->chooser.simple.authentication);
    107                msg.protocolOp.op.bindMsg.authentication.len = len;
    108        }
    109 
    110        PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem,
    111                (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate));
    112        if (!encoded) {
    113                PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
    114        }
    115 
    116        *pBindMsg = encoded;
    117 cleanup:
    118 
    119        PKIX_RETURN(LDAPDEFAULTCLIENT);
    120 }
    121 
    122 /*
    123 * FUNCTION: pkix_pl_LdapDefaultClient_MakeUnbind
    124 * DESCRIPTION:
    125 *
    126 *  This function creates and encodes a Unbind message, using the arena pointed
    127 *  to by "arena" and the messageID contained in "msgNum", and stores a pointer
    128 *  to the encoded string at "pUnbindMsg".
    129 *
    130 *  See pkix_pl_ldaptemplates.c for the ASN.1 description of an Unbind message.
    131 *
    132 *  This code is not used if the DefaultClient was created with a NULL pointer
    133 *  supplied for the LDAPBindAPI structure. (Bind and Unbind do not seem to be
    134 *  expected for anonymous Search requests.)
    135 *
    136 * PARAMETERS:
    137 *  "arena"
    138 *      The address of the PLArenaPool used in encoding the message. Must be
    139 *       non-NULL.
    140 *  "msgNum"
    141 *      The Int32 containing the MessageID to be encoded in the Unbind message.
    142 *  "pUnbindMsg"
    143 *      The address at which the encoded Unbind message will be stored. Must
    144 *      be non-NULL.
    145 *  "plContext"
    146 *      Platform-specific context pointer.
    147 * THREAD SAFETY:
    148 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    149 * RETURNS:
    150 *  Returns NULL if the function succeeds.
    151 *  Returns a LdapDefaultClient Error if the function fails in a
    152 *      non-fatal way.
    153 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    154 */
    155 static PKIX_Error *
    156 pkix_pl_LdapDefaultClient_MakeUnbind(
    157        PLArenaPool *arena,
    158        PKIX_UInt32 msgNum,
    159        SECItem **pUnbindMsg,
    160        void *plContext)
    161 {
    162        LDAPMessage msg;
    163        SECItem *encoded = NULL;
    164 
    165        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeUnbind");
    166        PKIX_NULLCHECK_TWO(arena, pUnbindMsg);
    167 
    168        PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset,
    169                (&msg, 0, sizeof (LDAPMessage)));
    170 
    171        msg.messageID.type = siUnsignedInteger;
    172        msg.messageID.data = (void*)&msgNum;
    173        msg.messageID.len = sizeof (msgNum);
    174 
    175        msg.protocolOp.selector = LDAP_UNBIND_TYPE;
    176 
    177        msg.protocolOp.op.unbindMsg.dummy.type = siBuffer;
    178        msg.protocolOp.op.unbindMsg.dummy.data = NULL;
    179        msg.protocolOp.op.unbindMsg.dummy.len = 0;
    180 
    181        PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem,
    182                (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate));
    183        if (!encoded) {
    184                PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
    185        }
    186 
    187        *pUnbindMsg = encoded;
    188 cleanup:
    189 
    190        PKIX_RETURN(LDAPDEFAULTCLIENT);
    191 }
    192 
    193 /*
    194 * FUNCTION: pkix_pl_LdapDefaultClient_MakeAbandon
    195 * DESCRIPTION:
    196 *
    197 *  This function creates and encodes a Abandon message, using the arena pointed
    198 *  to by "arena" and the messageID contained in "msgNum", and stores a pointer
    199 *  to the encoded string at "pAbandonMsg".
    200 *
    201 *  See pkix_pl_ldaptemplates.c for the ASN.1 description of an Abandon message.
    202 *
    203 * PARAMETERS:
    204 *  "arena"
    205 *      The address of the PLArenaPool used in encoding the message. Must be
    206 *       non-NULL.
    207 *  "msgNum"
    208 *      The Int32 containing the MessageID to be encoded in the Abandon message.
    209 *  "pAbandonMsg"
    210 *      The address at which the encoded Abandon message will be stored. Must
    211 *      be non-NULL.
    212 *  "plContext"
    213 *      Platform-specific context pointer.
    214 * THREAD SAFETY:
    215 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    216 * RETURNS:
    217 *  Returns NULL if the function succeeds.
    218 *  Returns a LdapDefaultClient Error if the function fails in a
    219 *      non-fatal way.
    220 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    221 */
    222 static PKIX_Error *
    223 pkix_pl_LdapDefaultClient_MakeAbandon(
    224        PLArenaPool *arena,
    225        PKIX_UInt32 msgNum,
    226        SECItem **pAbandonMsg,
    227        void *plContext)
    228 {
    229        LDAPMessage msg;
    230        SECItem *encoded = NULL;
    231 
    232        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeAbandon");
    233        PKIX_NULLCHECK_TWO(arena, pAbandonMsg);
    234 
    235        PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset,
    236                (&msg, 0, sizeof (LDAPMessage)));
    237 
    238        msg.messageID.type = siUnsignedInteger;
    239        msg.messageID.data = (void*)&msgNum;
    240        msg.messageID.len = sizeof (msgNum);
    241 
    242        msg.protocolOp.selector = LDAP_ABANDONREQUEST_TYPE;
    243 
    244        msg.protocolOp.op.abandonRequestMsg.messageID.type = siBuffer;
    245        msg.protocolOp.op.abandonRequestMsg.messageID.data = (void*)&msgNum;
    246        msg.protocolOp.op.abandonRequestMsg.messageID.len = sizeof (msgNum);
    247 
    248        PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem,
    249                (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate));
    250        if (!encoded) {
    251                PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED);
    252        }
    253 
    254        *pAbandonMsg = encoded;
    255 cleanup:
    256 
    257        PKIX_RETURN(LDAPDEFAULTCLIENT);
    258 }
    259 
    260 /*
    261 * FUNCTION: pkix_pl_LdapDefaultClient_DecodeBindResponse
    262 * DESCRIPTION:
    263 *
    264 *  This function decodes the encoded data pointed to by "src", using the arena
    265 *  pointed to by "arena", storing the decoded LDAPMessage at "pBindResponse"
    266 *  and the decoding status at "pStatus".
    267 *
    268 * PARAMETERS:
    269 *  "arena"
    270 *      The address of the PLArenaPool to be used in decoding the message. Must
    271 *      be  non-NULL.
    272 *  "src"
    273 *      The address of the SECItem containing the DER- (or BER-)encoded string.
    274 *       Must be non-NULL.
    275 *  "pBindResponse"
    276 *      The address at which the LDAPMessage is stored, if the decoding is
    277 *      successful (the returned status is SECSuccess). Must be non-NULL.
    278 *  "pStatus"
    279 *      The address at which the decoding status is stored. Must be non-NULL.
    280 *  "plContext"
    281 *      Platform-specific context pointer.
    282 * THREAD SAFETY:
    283 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    284 * RETURNS:
    285 *  Returns NULL if the function succeeds.
    286 *  Returns a LdapDefaultClient Error if the function fails in a
    287 *      non-fatal way.
    288 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    289 */
    290 static PKIX_Error *
    291 pkix_pl_LdapDefaultClient_DecodeBindResponse(
    292        PLArenaPool *arena,
    293        SECItem *src,
    294        LDAPMessage *pBindResponse,
    295        SECStatus *pStatus,
    296        void *plContext)
    297 {
    298        SECStatus rv = SECFailure;
    299        LDAPMessage response;
    300 
    301        PKIX_ENTER
    302                (LDAPDEFAULTCLIENT,
    303                "pkix_pl_LdapDefaultClient_DecodeBindResponse");
    304        PKIX_NULLCHECK_FOUR(arena, src, pBindResponse, pStatus);
    305 
    306        PKIX_PL_NSSCALL
    307                (LDAPDEFAULTCLIENT,
    308                PORT_Memset,
    309                (&response, 0, sizeof (LDAPMessage)));
    310 
    311        PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, rv, SEC_ASN1DecodeItem,
    312            (arena, &response, PKIX_PL_LDAPMessageTemplate, src));
    313 
    314        if (rv == SECSuccess) {
    315                *pBindResponse = response;
    316        }
    317 
    318        *pStatus = rv;
    319 
    320        PKIX_RETURN(LDAPDEFAULTCLIENT);
    321 }
    322 
    323 /*
    324 * FUNCTION: pkix_pl_LdapDefaultClient_VerifyBindResponse
    325 * DESCRIPTION:
    326 *
    327 *  This function verifies that the contents of the message in the rcvbuf of
    328 *  the LdapDefaultClient object pointed to by "client",  and whose length is
    329 *  provided by "buflen", is a response to a successful Bind.
    330 *
    331 * PARAMETERS:
    332 *  "client"
    333 *      The address of the LdapDefaultClient object. Must be non-NULL.
    334 *  "buflen"
    335 *      The value of the number of bytes in the receive buffer.
    336 *  "plContext"
    337 *      Platform-specific context pointer.
    338 * THREAD SAFETY:
    339 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    340 * RETURNS:
    341 *  Returns NULL if the function succeeds.
    342 *  Returns a LdapDefaultClient Error if the function fails in a
    343 *      non-fatal way.
    344 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    345 */
    346 static PKIX_Error *
    347 pkix_pl_LdapDefaultClient_VerifyBindResponse(
    348        PKIX_PL_LdapDefaultClient *client,
    349        PKIX_UInt32 bufLen,
    350        void *plContext)
    351 {
    352        SECItem decode = {siBuffer, NULL, 0};
    353        SECStatus rv = SECFailure;
    354        LDAPMessage msg;
    355        LDAPBindResponse *ldapBindResponse = &msg.protocolOp.op.bindResponseMsg;
    356 
    357        ldapBindResponse->resultCode.data = NULL;
    358 
    359        PKIX_ENTER
    360                (LDAPDEFAULTCLIENT,
    361                "pkix_pl_LdapDefaultClient_VerifyBindResponse");
    362        PKIX_NULLCHECK_TWO(client, client->rcvBuf);
    363 
    364        decode.data = (unsigned char *)(client->rcvBuf);
    365        decode.len = bufLen;
    366 
    367        PKIX_CHECK(pkix_pl_LdapDefaultClient_DecodeBindResponse
    368                (client->arena, &decode, &msg, &rv, plContext),
    369                PKIX_LDAPDEFAULTCLIENTDECODEBINDRESPONSEFAILED);
    370 
    371        if (rv == SECSuccess) {
    372                if (*(ldapBindResponse->resultCode.data) == SUCCESS) {
    373                        client->connectStatus = BOUND;
    374                } else {
    375                        PKIX_ERROR(PKIX_BINDREJECTEDBYSERVER);
    376                }
    377        } else {
    378                PKIX_ERROR(PKIX_CANTDECODEBINDRESPONSEFROMSERVER);
    379        }
    380 
    381 cleanup:
    382 
    383        PKIX_RETURN(LDAPDEFAULTCLIENT);
    384 }
    385 
    386 /*
    387 * FUNCTION: pkix_pl_LdapDefaultClient_RecvCheckComplete
    388 * DESCRIPTION:
    389 *
    390 *  This function determines whether the current response in the
    391 *  LdapDefaultClient pointed to by "client" is complete, in the sense that all
    392 *  bytes required to satisfy the message length field in the encoding have been
    393 *  received. If so, the pointer to input data is updated to reflect the number
    394 *  of bytes consumed, provided by "bytesProcessed". The state machine flag
    395 *  pointed to by "pKeepGoing" is updated to indicate whether processing can
    396 *  continue without further input.
    397 *
    398 * PARAMETERS:
    399 *  "client"
    400 *      The address of the LdapDefaultClient object. Must be non-NULL.
    401 *  "bytesProcessed"
    402 *      The UInt32 value of the number of bytes consumed from the current
    403 *      buffer.
    404 *  "pKeepGoing"
    405 *      The address at which the Boolean state machine flag is stored to
    406 *      indicate whether processing can continue without further input.
    407 *      Must be non-NULL.
    408 *  "plContext"
    409 *      Platform-specific context pointer.
    410 * THREAD SAFETY:
    411 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    412 * RETURNS:
    413 *  Returns NULL if the function succeeds.
    414 *  Returns a LdapDefaultClient Error if the function fails in a
    415 *      non-fatal way.
    416 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    417 */
    418 static PKIX_Error *
    419 pkix_pl_LdapDefaultClient_RecvCheckComplete(
    420        PKIX_PL_LdapDefaultClient *client,
    421        PKIX_UInt32 bytesProcessed,
    422        PKIX_Boolean *pKeepGoing,
    423        void *plContext)
    424 {
    425        PKIX_Boolean complete = PKIX_FALSE;
    426        SECStatus rv = SECFailure;
    427        LDAPMessageType messageType = 0;
    428        LDAPResultCode resultCode = 0;
    429 
    430        PKIX_ENTER
    431                (LDAPDEFAULTCLIENT,
    432                "pkix_pl_LdapDefaultClient_RecvCheckComplete");
    433        PKIX_NULLCHECK_TWO(client, pKeepGoing);
    434 
    435        PKIX_CHECK(pkix_pl_LdapResponse_IsComplete
    436                (client->currentResponse, &complete, plContext),
    437                PKIX_LDAPRESPONSEISCOMPLETEFAILED);
    438 
    439        if (complete) {
    440                PKIX_CHECK(pkix_pl_LdapResponse_Decode
    441                       (client->arena, client->currentResponse, &rv, plContext),
    442                        PKIX_LDAPRESPONSEDECODEFAILED);
    443 
    444                if (rv != SECSuccess) {
    445                        PKIX_ERROR(PKIX_CANTDECODESEARCHRESPONSEFROMSERVER);
    446                }
    447 
    448                PKIX_CHECK(pkix_pl_LdapResponse_GetMessageType
    449                        (client->currentResponse, &messageType, plContext),
    450                        PKIX_LDAPRESPONSEGETMESSAGETYPEFAILED);
    451 
    452                if (messageType == LDAP_SEARCHRESPONSEENTRY_TYPE) {
    453 
    454                        if (client->entriesFound == NULL) {
    455                                PKIX_CHECK(PKIX_List_Create
    456                                    (&(client->entriesFound), plContext),
    457                                    PKIX_LISTCREATEFAILED);
    458                        }
    459 
    460                        PKIX_CHECK(PKIX_List_AppendItem
    461                                (client->entriesFound,
    462                                (PKIX_PL_Object *)client->currentResponse,
    463                                plContext),
    464                                PKIX_LISTAPPENDITEMFAILED);
    465 
    466                        PKIX_DECREF(client->currentResponse);
    467 
    468                        /* current receive buffer empty? */
    469                        if (client->currentBytesAvailable == 0) {
    470                                client->connectStatus = RECV;
    471                                *pKeepGoing = PKIX_TRUE;
    472                        } else {
    473                                client->connectStatus = RECV_INITIAL;
    474                                client->currentInPtr = &((char *)
    475                                    (client->currentInPtr))[bytesProcessed];
    476                                *pKeepGoing = PKIX_TRUE;
    477                        }
    478 
    479                } else if (messageType == LDAP_SEARCHRESPONSERESULT_TYPE) {
    480                        PKIX_CHECK(pkix_pl_LdapResponse_GetResultCode
    481                                (client->currentResponse,
    482                                &resultCode,
    483                                plContext),
    484                                PKIX_LDAPRESPONSEGETRESULTCODEFAILED);
    485 
    486                        if ((client->entriesFound == NULL) &&
    487                            ((resultCode == SUCCESS) ||
    488                            (resultCode == NOSUCHOBJECT))) {
    489                                PKIX_CHECK(PKIX_List_Create
    490                                    (&(client->entriesFound), plContext),
    491                                    PKIX_LISTCREATEFAILED);
    492                        } else if (resultCode == SUCCESS) {
    493                                PKIX_CHECK(PKIX_List_SetImmutable
    494                                    (client->entriesFound, plContext),
    495                                    PKIX_LISTSETIMMUTABLEFAILED);
    496                                PKIX_CHECK(PKIX_PL_HashTable_Add
    497                                    (client->cachePtr,
    498                                    (PKIX_PL_Object *)client->currentRequest,
    499                                    (PKIX_PL_Object *)client->entriesFound,
    500                                    plContext),
    501                                    PKIX_HASHTABLEADDFAILED);
    502                        } else {
    503                            PKIX_ERROR(PKIX_UNEXPECTEDRESULTCODEINRESPONSE);
    504                        }
    505 
    506                        client->connectStatus = BOUND;
    507                        *pKeepGoing = PKIX_FALSE;
    508                        PKIX_DECREF(client->currentResponse);
    509 
    510                } else {
    511                        PKIX_ERROR(PKIX_SEARCHRESPONSEPACKETOFUNKNOWNTYPE);
    512                }
    513        } else {
    514                client->connectStatus = RECV;
    515                *pKeepGoing = PKIX_TRUE;
    516        }
    517 
    518 cleanup:
    519        PKIX_RETURN(LDAPDEFAULTCLIENT);
    520 }
    521 
    522 /* --Private-LdapDefaultClient-Object-Functions------------------------- */
    523 
    524 static PKIX_Error *
    525 pkix_pl_LdapDefaultClient_InitiateRequest(
    526        PKIX_PL_LdapClient *client,
    527        LDAPRequestParams *requestParams,
    528        void **pPollDesc,
    529        PKIX_List **pResponse,
    530        void *plContext);
    531 
    532 static PKIX_Error *
    533 pkix_pl_LdapDefaultClient_ResumeRequest(
    534        PKIX_PL_LdapClient *client,
    535        void **pPollDesc,
    536        PKIX_List **pResponse,
    537        void *plContext);
    538 
    539 /*
    540 * FUNCTION: pkix_pl_LdapDefaultClient_CreateHelper
    541 * DESCRIPTION:
    542 *
    543 *  This function creates a new LdapDefaultClient using the Socket pointed to
    544 *  by "socket", the PRIntervalTime pointed to by "timeout", and the
    545 *  LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient".
    546 *
    547 *  A value of zero for "timeout" means the LDAPClient will use non-blocking
    548 *  I/O.
    549 *
    550 * PARAMETERS:
    551 *  "socket"
    552 *      Address of the Socket to be used for the client. Must be non-NULL.
    553 *  "bindAPI"
    554 *      The address of the LDAPBindAPI containing the Bind information to be
    555 *      encoded in the Bind message.
    556 *  "pClient"
    557 *      The address at which the created LdapDefaultClient is to be stored.
    558 *      Must be non-NULL.
    559 *  "plContext"
    560 *      Platform-specific context pointer.
    561 * THREAD SAFETY:
    562 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    563 * RETURNS:
    564 *  Returns NULL if the function succeeds.
    565 *  Returns a LdapDefaultClient Error if the function fails in
    566 *      a non-fatal way.
    567 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    568 */
    569 PKIX_Error *
    570 pkix_pl_LdapDefaultClient_CreateHelper(
    571        PKIX_PL_Socket *socket,
    572        LDAPBindAPI *bindAPI,
    573        PKIX_PL_LdapDefaultClient **pClient,
    574        void *plContext)
    575 {
    576        PKIX_PL_HashTable *ht;
    577        PKIX_PL_LdapDefaultClient *ldapDefaultClient = NULL;
    578        PKIX_PL_Socket_Callback *callbackList;
    579        PRFileDesc *fileDesc = NULL;
    580        PLArenaPool *arena = NULL;
    581 
    582        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_CreateHelper");
    583        PKIX_NULLCHECK_TWO(socket, pClient);
    584 
    585        PKIX_CHECK(PKIX_PL_Object_Alloc
    586                    (PKIX_LDAPDEFAULTCLIENT_TYPE,
    587                    sizeof (PKIX_PL_LdapDefaultClient),
    588                    (PKIX_PL_Object **)&ldapDefaultClient,
    589                    plContext),
    590                    PKIX_COULDNOTCREATELDAPDEFAULTCLIENTOBJECT);
    591 
    592        ldapDefaultClient->vtable.initiateFcn =
    593                pkix_pl_LdapDefaultClient_InitiateRequest;
    594        ldapDefaultClient->vtable.resumeFcn =
    595                pkix_pl_LdapDefaultClient_ResumeRequest;
    596 
    597        PKIX_CHECK(pkix_pl_Socket_GetPRFileDesc
    598                (socket, &fileDesc, plContext),
    599                PKIX_SOCKETGETPRFILEDESCFAILED);
    600 
    601        ldapDefaultClient->pollDesc.fd = fileDesc;
    602        ldapDefaultClient->pollDesc.in_flags = 0;
    603        ldapDefaultClient->pollDesc.out_flags = 0;
    604 
    605        ldapDefaultClient->bindAPI = bindAPI;
    606 
    607        PKIX_CHECK(PKIX_PL_HashTable_Create
    608                (LDAP_CACHEBUCKETS, 0, &ht, plContext),
    609                PKIX_HASHTABLECREATEFAILED);
    610 
    611        ldapDefaultClient->cachePtr = ht;
    612 
    613        PKIX_CHECK(pkix_pl_Socket_GetCallbackList
    614                (socket, &callbackList, plContext),
    615                PKIX_SOCKETGETCALLBACKLISTFAILED);
    616 
    617        ldapDefaultClient->callbackList = callbackList;
    618 
    619        PKIX_INCREF(socket);
    620        ldapDefaultClient->clientSocket = socket;
    621 
    622        ldapDefaultClient->messageID = 0;
    623 
    624        ldapDefaultClient->bindAPI = bindAPI;
    625 
    626        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    627        if (!arena) {
    628            PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
    629        }
    630        ldapDefaultClient->arena = arena;
    631 
    632        ldapDefaultClient->sendBuf = NULL;
    633        ldapDefaultClient->bytesToWrite = 0;
    634 
    635        PKIX_CHECK(PKIX_PL_Malloc
    636                (RCVBUFSIZE, &ldapDefaultClient->rcvBuf, plContext),
    637                PKIX_MALLOCFAILED);
    638        ldapDefaultClient->capacity = RCVBUFSIZE;
    639 
    640        ldapDefaultClient->bindMsg = NULL;
    641        ldapDefaultClient->bindMsgLen = 0;
    642 
    643        ldapDefaultClient->entriesFound = NULL;
    644        ldapDefaultClient->currentRequest = NULL;
    645        ldapDefaultClient->currentResponse = NULL;
    646 
    647        *pClient = ldapDefaultClient;
    648 
    649 cleanup:
    650 
    651        if (PKIX_ERROR_RECEIVED) {
    652                PKIX_DECREF(ldapDefaultClient);
    653        }
    654 
    655        PKIX_RETURN(LDAPDEFAULTCLIENT);
    656 }
    657 
    658 /*
    659 * FUNCTION: PKIX_PL_LdapDefaultClient_Create
    660 * DESCRIPTION:
    661 *
    662 *  This function creates a new LdapDefaultClient using the PRNetAddr pointed to
    663 *  by "sockaddr", the PRIntervalTime pointed to by "timeout", and the
    664 *  LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient".
    665 *
    666 *  A value of zero for "timeout" means the LDAPClient will use non-blocking
    667 *  I/O.
    668 *
    669 * PARAMETERS:
    670 *  "sockaddr"
    671 *      Address of the PRNetAddr to be used for the socket connection. Must be
    672 *      non-NULL.
    673 *  "timeout"
    674 *      The PRIntervalTime to be used in I/O requests for this client.
    675 *  "bindAPI"
    676 *      The address of the LDAPBindAPI containing the Bind information to be
    677 *      encoded in the Bind message.
    678 *  "pClient"
    679 *      The address at which the created LdapDefaultClient is to be stored.
    680 *      Must be non-NULL.
    681 *  "plContext"
    682 *      Platform-specific context pointer.
    683 * THREAD SAFETY:
    684 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    685 * RETURNS:
    686 *  Returns NULL if the function succeeds.
    687 *  Returns a LdapDefaultClient Error if the function fails in
    688 *      a non-fatal way.
    689 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    690 */
    691 PKIX_Error *
    692 PKIX_PL_LdapDefaultClient_Create(
    693        PRNetAddr *sockaddr,
    694        PRIntervalTime timeout,
    695        LDAPBindAPI *bindAPI,
    696        PKIX_PL_LdapDefaultClient **pClient,
    697        void *plContext)
    698 {
    699        PRErrorCode status = 0;
    700        PKIX_PL_Socket *socket = NULL;
    701        PKIX_PL_LdapDefaultClient *client = NULL;
    702 
    703        PKIX_ENTER(LDAPDEFAULTCLIENT, "PKIX_PL_LdapDefaultClient_Create");
    704        PKIX_NULLCHECK_TWO(sockaddr, pClient);
    705 
    706        PKIX_CHECK(pkix_pl_Socket_Create
    707                (PKIX_FALSE, timeout, sockaddr, &status, &socket, plContext),
    708                PKIX_SOCKETCREATEFAILED);
    709 
    710        PKIX_CHECK(pkix_pl_LdapDefaultClient_CreateHelper
    711                (socket, bindAPI, &client, plContext),
    712                PKIX_LDAPDEFAULTCLIENTCREATEHELPERFAILED);
    713 
    714        /* Did Socket_Create say the connection was made? */
    715        if (status == 0) {
    716                if (client->bindAPI != NULL) {
    717                        client->connectStatus = CONNECTED;
    718                } else {
    719                        client->connectStatus = BOUND;
    720                }
    721        } else {
    722                client->connectStatus = CONNECT_PENDING;
    723        }
    724 
    725        *pClient = client;
    726 
    727 cleanup:
    728        if (PKIX_ERROR_RECEIVED) {
    729                PKIX_DECREF(client);
    730        }
    731 
    732        PKIX_DECREF(socket);
    733 
    734        PKIX_RETURN(LDAPDEFAULTCLIENT);
    735 }
    736 
    737 /*
    738 * FUNCTION: PKIX_PL_LdapDefaultClient_CreateByName
    739 * DESCRIPTION:
    740 *
    741 *  This function creates a new LdapDefaultClient using the hostname pointed to
    742 *  by "hostname", the PRIntervalTime pointed to by "timeout", and the
    743 *  LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient".
    744 *
    745 *  A value of zero for "timeout" means the LDAPClient will use non-blocking
    746 *  I/O.
    747 *
    748 * PARAMETERS:
    749 *  "hostname"
    750 *      Address of the hostname to be used for the socket connection. Must be
    751 *      non-NULL.
    752 *  "timeout"
    753 *      The PRIntervalTime to be used in I/O requests for this client.
    754 *  "bindAPI"
    755 *      The address of the LDAPBindAPI containing the Bind information to be
    756 *      encoded in the Bind message.
    757 *  "pClient"
    758 *      The address at which the created LdapDefaultClient is to be stored.
    759 *      Must be non-NULL.
    760 *  "plContext"
    761 *      Platform-specific context pointer.
    762 * THREAD SAFETY:
    763 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
    764 * RETURNS:
    765 *  Returns NULL if the function succeeds.
    766 *  Returns a LdapDefaultClient Error if the function fails in
    767 *      a non-fatal way.
    768 *  Returns a Fatal Error if the function fails in an unrecoverable way.
    769 */
    770 PKIX_Error *
    771 PKIX_PL_LdapDefaultClient_CreateByName(
    772        char *hostname,
    773        PRIntervalTime timeout,
    774        LDAPBindAPI *bindAPI,
    775        PKIX_PL_LdapDefaultClient **pClient,
    776        void *plContext)
    777 {
    778        PRErrorCode status = 0;
    779        PKIX_PL_Socket *socket = NULL;
    780        PKIX_PL_LdapDefaultClient *client = NULL;
    781 
    782        PKIX_ENTER(LDAPDEFAULTCLIENT, "PKIX_PL_LdapDefaultClient_CreateByName");
    783        PKIX_NULLCHECK_TWO(hostname, pClient);
    784 
    785        PKIX_CHECK(pkix_pl_Socket_CreateByName
    786                (PKIX_FALSE, timeout, hostname, &status, &socket, plContext),
    787                PKIX_SOCKETCREATEBYNAMEFAILED);
    788 
    789        PKIX_CHECK(pkix_pl_LdapDefaultClient_CreateHelper
    790                (socket, bindAPI, &client, plContext),
    791                PKIX_LDAPDEFAULTCLIENTCREATEHELPERFAILED);
    792 
    793        /* Did Socket_Create say the connection was made? */
    794        if (status == 0) {
    795                if (client->bindAPI != NULL) {
    796                        client->connectStatus = CONNECTED;
    797                } else {
    798                        client->connectStatus = BOUND;
    799                }
    800        } else {
    801                client->connectStatus = CONNECT_PENDING;
    802        }
    803 
    804        *pClient = client;
    805 
    806 cleanup:
    807        if (PKIX_ERROR_RECEIVED) {
    808                PKIX_DECREF(client);
    809        }
    810 
    811        PKIX_DECREF(socket);
    812 
    813        PKIX_RETURN(LDAPDEFAULTCLIENT);
    814 }
    815 
    816 /*
    817 * FUNCTION: pkix_pl_LdapDefaultClient_Destroy
    818 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
    819 */
    820 static PKIX_Error *
    821 pkix_pl_LdapDefaultClient_Destroy(
    822        PKIX_PL_Object *object,
    823        void *plContext)
    824 {
    825        PKIX_Int32 bytesWritten = 0;
    826        PKIX_PL_LdapDefaultClient *client = NULL;
    827        PKIX_PL_Socket_Callback *callbackList = NULL;
    828        SECItem *encoded = NULL;
    829 
    830        PKIX_ENTER(LDAPDEFAULTCLIENT,
    831                    "pkix_pl_LdapDefaultClient_Destroy");
    832        PKIX_NULLCHECK_ONE(object);
    833 
    834        PKIX_CHECK(pkix_CheckType
    835                    (object, PKIX_LDAPDEFAULTCLIENT_TYPE, plContext),
    836                    PKIX_OBJECTNOTANLDAPDEFAULTCLIENT);
    837 
    838        client = (PKIX_PL_LdapDefaultClient *)object;
    839 
    840        switch (client->connectStatus) {
    841        case CONNECT_PENDING:
    842                break;
    843        case CONNECTED:
    844        case BIND_PENDING:
    845        case BIND_RESPONSE:
    846        case BIND_RESPONSE_PENDING:
    847        case BOUND:
    848        case SEND_PENDING:
    849        case RECV:
    850        case RECV_PENDING:
    851        case RECV_INITIAL:
    852        case RECV_NONINITIAL:
    853        case ABANDON_PENDING:
    854                if (client->bindAPI != NULL) {
    855                        PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeUnbind
    856                                (client->arena,
    857                                ++(client->messageID),
    858                                &encoded,
    859                                plContext),
    860                                PKIX_LDAPDEFAULTCLIENTMAKEUNBINDFAILED);
    861 
    862                        callbackList =
    863                                (PKIX_PL_Socket_Callback *)(client->callbackList);
    864                        PKIX_CHECK(callbackList->sendCallback
    865                                (client->clientSocket,
    866                                encoded->data,
    867                                encoded->len,
    868                                &bytesWritten,
    869                                plContext),
    870                                PKIX_SOCKETSENDFAILED);
    871                }
    872                break;
    873        default:
    874                PKIX_ERROR(PKIX_LDAPDEFAULTCLIENTINILLEGALSTATE);
    875        }
    876 
    877        PKIX_DECREF(client->cachePtr);
    878        PKIX_DECREF(client->clientSocket);
    879        PKIX_DECREF(client->entriesFound);
    880        PKIX_DECREF(client->currentRequest);
    881        PKIX_DECREF(client->currentResponse);
    882 
    883        PKIX_CHECK(PKIX_PL_Free
    884 	(client->rcvBuf, plContext), PKIX_FREEFAILED);
    885 
    886        PKIX_PL_NSSCALL
    887                (LDAPDEFAULTCLIENT,
    888                PORT_FreeArena,
    889                (client->arena, PR_FALSE));
    890 
    891 cleanup:
    892 
    893        PKIX_RETURN(LDAPDEFAULTCLIENT);
    894 }
    895 
    896 /*
    897 * FUNCTION: pkix_pl_LdapDefaultClient_Hashcode
    898 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
    899 */
    900 static PKIX_Error *
    901 pkix_pl_LdapDefaultClient_Hashcode(
    902        PKIX_PL_Object *object,
    903        PKIX_UInt32 *pHashcode,
    904        void *plContext)
    905 {
    906        PKIX_PL_LdapDefaultClient *ldapDefaultClient = NULL;
    907        PKIX_UInt32 tempHash = 0;
    908 
    909        PKIX_ENTER
    910                (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Hashcode");
    911        PKIX_NULLCHECK_TWO(object, pHashcode);
    912 
    913        PKIX_CHECK(pkix_CheckType
    914                (object, PKIX_LDAPDEFAULTCLIENT_TYPE, plContext),
    915                PKIX_OBJECTNOTANLDAPDEFAULTCLIENT);
    916 
    917        ldapDefaultClient = (PKIX_PL_LdapDefaultClient *)object;
    918 
    919        PKIX_CHECK(PKIX_PL_Object_Hashcode
    920                ((PKIX_PL_Object *)ldapDefaultClient->clientSocket,
    921                &tempHash,
    922                plContext),
    923                PKIX_SOCKETHASHCODEFAILED);
    924 
    925        if (ldapDefaultClient->bindAPI != NULL) {
    926                tempHash = (tempHash << 7) +
    927                        ldapDefaultClient->bindAPI->selector;
    928        }
    929 
    930        *pHashcode = tempHash;
    931 
    932 cleanup:
    933 
    934        PKIX_RETURN(LDAPDEFAULTCLIENT);
    935 }
    936 
    937 /*
    938 * FUNCTION: pkix_pl_LdapDefaultClient_Equals
    939 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
    940 */
    941 static PKIX_Error *
    942 pkix_pl_LdapDefaultClient_Equals(
    943        PKIX_PL_Object *firstObject,
    944        PKIX_PL_Object *secondObject,
    945        PKIX_Int32 *pResult,
    946        void *plContext)
    947 {
    948        PKIX_PL_LdapDefaultClient *firstClientContext = NULL;
    949        PKIX_PL_LdapDefaultClient *secondClientContext = NULL;
    950        PKIX_Int32 compare = 0;
    951 
    952        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Equals");
    953        PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult);
    954 
    955        *pResult = PKIX_FALSE;
    956 
    957        PKIX_CHECK(pkix_CheckTypes
    958                (firstObject,
    959                secondObject,
    960                PKIX_LDAPDEFAULTCLIENT_TYPE,
    961                plContext),
    962                PKIX_OBJECTNOTANLDAPDEFAULTCLIENT);
    963 
    964        firstClientContext = (PKIX_PL_LdapDefaultClient *)firstObject;
    965        secondClientContext = (PKIX_PL_LdapDefaultClient *)secondObject;
    966 
    967        if (firstClientContext == secondClientContext) {
    968                *pResult = PKIX_TRUE;
    969                goto cleanup;
    970        }
    971 
    972        PKIX_CHECK(PKIX_PL_Object_Equals
    973                ((PKIX_PL_Object *)firstClientContext->clientSocket,
    974                (PKIX_PL_Object *)secondClientContext->clientSocket,
    975                &compare,
    976                plContext),
    977                PKIX_SOCKETEQUALSFAILED);
    978 
    979        if (!compare) {
    980                goto cleanup;
    981        }
    982 
    983        if (PKIX_EXACTLY_ONE_NULL
    984                (firstClientContext->bindAPI, secondClientContext->bindAPI)) {
    985                goto cleanup;
    986        }
    987 
    988        if (firstClientContext->bindAPI) {
    989                if (firstClientContext->bindAPI->selector !=
    990                    secondClientContext->bindAPI->selector) {
    991                        goto cleanup;
    992                }
    993        }
    994 
    995        *pResult = PKIX_TRUE;
    996 
    997 cleanup:
    998 
    999        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1000 }
   1001 
   1002 /*
   1003 * FUNCTION: pkix_pl_LdapDefaultClient_RegisterSelf
   1004 *
   1005 * DESCRIPTION:
   1006 *  Registers PKIX_PL_LDAPDEFAULTCLIENT_TYPE and its related
   1007 *  functions with systemClasses[]
   1008 *
   1009 * THREAD SAFETY:
   1010 *  Not Thread Safe - for performance and complexity reasons
   1011 *
   1012 *  Since this function is only called by PKIX_PL_Initialize, which should
   1013 *  only be called once, it is acceptable that this function is not
   1014 *  thread-safe.
   1015 */
   1016 PKIX_Error *
   1017 pkix_pl_LdapDefaultClient_RegisterSelf(void *plContext)
   1018 {
   1019        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
   1020        pkix_ClassTable_Entry entry;
   1021 
   1022        PKIX_ENTER
   1023                (LDAPDEFAULTCLIENT,
   1024                "pkix_pl_LdapDefaultClient_RegisterSelf");
   1025 
   1026        entry.description = "LdapDefaultClient";
   1027        entry.objCounter = 0;
   1028        entry.typeObjectSize = sizeof(PKIX_PL_LdapDefaultClient);
   1029        entry.destructor = pkix_pl_LdapDefaultClient_Destroy;
   1030        entry.equalsFunction = pkix_pl_LdapDefaultClient_Equals;
   1031        entry.hashcodeFunction = pkix_pl_LdapDefaultClient_Hashcode;
   1032        entry.toStringFunction = NULL;
   1033        entry.comparator = NULL;
   1034        entry.duplicateFunction = NULL;
   1035 
   1036        systemClasses[PKIX_LDAPDEFAULTCLIENT_TYPE] = entry;
   1037 
   1038        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1039 }
   1040 
   1041 /*
   1042 * FUNCTION: pkix_pl_LdapDefaultClient_GetPollDesc
   1043 * DESCRIPTION:
   1044 *
   1045 *  This function retrieves the PRPollDesc from the LdapDefaultClient
   1046 *  pointed to by "context" and stores the address at "pPollDesc".
   1047 *
   1048 * PARAMETERS:
   1049 *  "context"
   1050 *      The LdapDefaultClient whose PRPollDesc is desired. Must be non-NULL.
   1051 *  "pPollDesc"
   1052 *      Address where PRPollDesc will be stored. Must be non-NULL.
   1053 *  "plContext"
   1054 *      Platform-specific context pointer.
   1055 * THREAD SAFETY:
   1056 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1057 * RETURNS:
   1058 *  Returns NULL if the function succeeds.
   1059 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1060 */
   1061 PKIX_Error *
   1062 pkix_pl_LdapDefaultClient_GetPollDesc(
   1063        PKIX_PL_LdapDefaultClient *context,
   1064        PRPollDesc **pPollDesc,
   1065        void *plContext)
   1066 {
   1067        PKIX_ENTER
   1068                (LDAPDEFAULTCLIENT,
   1069                "pkix_pl_LdapDefaultClient_GetPollDesc");
   1070        PKIX_NULLCHECK_TWO(context, pPollDesc);
   1071 
   1072        *pPollDesc = &(context->pollDesc);
   1073 
   1074        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1075 }
   1076 
   1077 /* --Private-Ldap-CertStore-I/O-Functions---------------------------- */
   1078 /*
   1079 * FUNCTION: pkix_pl_LdapDefaultClient_ConnectContinue
   1080 * DESCRIPTION:
   1081 *
   1082 *  This function determines whether a socket Connect initiated earlier for the
   1083 *  CertStore embodied in the LdapDefaultClient "client" has completed, and
   1084 *  stores in "pKeepGoing" a flag indicating whether processing can continue
   1085 *  without further input.
   1086 *
   1087 * PARAMETERS:
   1088 *  "client"
   1089 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1090 *  "pKeepGoing"
   1091 *      The address at which the Boolean state machine flag is stored to
   1092 *      indicate whether processing can continue without further input.
   1093 *      Must be non-NULL.
   1094 *  "plContext"
   1095 *      Platform-specific context pointer.
   1096 * THREAD SAFETY:
   1097 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1098 * RETURNS:
   1099 *  Returns NULL if the function succeeds.
   1100 *  Returns a LdapDefaultClient Error if the function fails in a
   1101 *      non-fatal way.
   1102 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1103 */
   1104 static PKIX_Error *
   1105 pkix_pl_LdapDefaultClient_ConnectContinue(
   1106        PKIX_PL_LdapDefaultClient *client,
   1107        PKIX_Boolean *pKeepGoing,
   1108        void *plContext)
   1109 {
   1110        PKIX_PL_Socket_Callback *callbackList;
   1111        PRErrorCode status;
   1112        PKIX_Boolean keepGoing = PKIX_FALSE;
   1113 
   1114        PKIX_ENTER
   1115                (LDAPDEFAULTCLIENT,
   1116                "pkix_pl_LdapDefaultClient_ConnectContinue");
   1117        PKIX_NULLCHECK_ONE(client);
   1118 
   1119        callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   1120 
   1121        PKIX_CHECK(callbackList->connectcontinueCallback
   1122                (client->clientSocket, &status, plContext),
   1123                PKIX_SOCKETCONNECTCONTINUEFAILED);
   1124 
   1125        if (status == 0) {
   1126                if (client->bindAPI != NULL) {
   1127                        client->connectStatus = CONNECTED;
   1128                } else {
   1129                        client->connectStatus = BOUND;
   1130                }
   1131                keepGoing = PKIX_FALSE;
   1132        } else if (status != PR_IN_PROGRESS_ERROR) {
   1133                PKIX_ERROR(PKIX_UNEXPECTEDERRORINESTABLISHINGCONNECTION);
   1134        }
   1135 
   1136        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1137                ((PKIX_PL_Object *)client, plContext),
   1138                PKIX_OBJECTINVALIDATECACHEFAILED);
   1139 
   1140        *pKeepGoing = keepGoing;
   1141 
   1142 cleanup:
   1143        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1144 }
   1145 
   1146 /*
   1147 * FUNCTION: pkix_pl_LdapDefaultClient_Bind
   1148 * DESCRIPTION:
   1149 *
   1150 *  This function creates and sends the LDAP-protocol Bind message for the
   1151 *  CertStore embodied in the LdapDefaultClient "client", and stores in
   1152 *  "pKeepGoing" a flag indicating whether processing can continue without
   1153 *  further input.
   1154 *
   1155 * PARAMETERS:
   1156 *  "client"
   1157 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1158 *  "pKeepGoing"
   1159 *      The address at which the Boolean state machine flag is stored to
   1160 *      indicate whether processing can continue without further input.
   1161 *      Must be non-NULL.
   1162 *  "plContext"
   1163 *      Platform-specific context pointer.
   1164 * THREAD SAFETY:
   1165 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1166 * RETURNS:
   1167 *  Returns NULL if the function succeeds.
   1168 *  Returns a LdapDefaultClient Error if the function fails in a
   1169 *      non-fatal way.
   1170 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1171 */
   1172 static PKIX_Error *
   1173 pkix_pl_LdapDefaultClient_Bind(
   1174        PKIX_PL_LdapDefaultClient *client,
   1175        PKIX_Boolean *pKeepGoing,
   1176        void *plContext)
   1177 {
   1178        SECItem *encoded = NULL;
   1179        PKIX_Int32 bytesWritten = 0;
   1180        PKIX_PL_Socket_Callback *callbackList;
   1181 
   1182        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Bind");
   1183        PKIX_NULLCHECK_ONE(client);
   1184 
   1185        /* if we have not yet constructed the BIND message, build it now */
   1186        if (!(client->bindMsg)) {
   1187                PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeBind
   1188                        (client->arena,
   1189                        3,
   1190                        client->bindAPI,
   1191                        client->messageID,
   1192                        &encoded,
   1193                        plContext),
   1194                        PKIX_LDAPDEFAULTCLIENTMAKEBINDFAILED);
   1195                client->bindMsg = encoded->data;
   1196                client->bindMsgLen = encoded->len;
   1197        }
   1198 
   1199        callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   1200 
   1201        PKIX_CHECK(callbackList->sendCallback
   1202                (client->clientSocket,
   1203                client->bindMsg,
   1204                client->bindMsgLen,
   1205                &bytesWritten,
   1206                plContext),
   1207                PKIX_SOCKETSENDFAILED);
   1208 
   1209        client->lastIO = PR_Now();
   1210 
   1211        if (bytesWritten < 0) {
   1212                client->connectStatus = BIND_PENDING;
   1213                *pKeepGoing = PKIX_FALSE;
   1214        } else {
   1215                client->connectStatus = BIND_RESPONSE;
   1216                *pKeepGoing = PKIX_TRUE;
   1217        }
   1218 
   1219        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1220                ((PKIX_PL_Object *)client, plContext),
   1221                PKIX_OBJECTINVALIDATECACHEFAILED);
   1222 
   1223 cleanup:
   1224        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1225 }
   1226 
   1227 /*
   1228 * FUNCTION: pkix_pl_LdapDefaultClient_BindContinue
   1229 * DESCRIPTION:
   1230 *
   1231 *  This function determines whether the LDAP-protocol Bind message for the
   1232 *  CertStore embodied in the LdapDefaultClient "client" has completed, and
   1233 *  stores in "pKeepGoing" a flag indicating whether processing can continue
   1234 *  without further input.
   1235 *
   1236 * PARAMETERS:
   1237 *  "client"
   1238 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1239 *  "pKeepGoing"
   1240 *      The address at which the Boolean state machine flag is stored to
   1241 *      indicate whether processing can continue without further input.
   1242 *      Must be non-NULL.
   1243 *  "plContext"
   1244 *      Platform-specific context pointer.
   1245 * THREAD SAFETY:
   1246 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1247 * RETURNS:
   1248 *  Returns NULL if the function succeeds.
   1249 *  Returns a LdapDefaultClient Error if the function fails in a
   1250 *      non-fatal way.
   1251 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1252 */
   1253 PKIX_Error *pkix_pl_LdapDefaultClient_BindContinue(
   1254        PKIX_PL_LdapDefaultClient *client,
   1255        PKIX_Boolean *pKeepGoing,
   1256        void *plContext)
   1257 {
   1258        PKIX_Int32 bytesWritten = 0;
   1259        PKIX_PL_Socket_Callback *callbackList = NULL;
   1260 
   1261        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_BindContinue");
   1262        PKIX_NULLCHECK_ONE(client);
   1263 
   1264        *pKeepGoing = PKIX_FALSE;
   1265 
   1266        callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   1267 
   1268        PKIX_CHECK(callbackList->pollCallback
   1269                (client->clientSocket, &bytesWritten, NULL, plContext),
   1270                PKIX_SOCKETPOLLFAILED);
   1271 
   1272        /*
   1273         * If the send completed we can proceed to try for the
   1274         * response. If the send did not complete we will have
   1275         * continue to poll.
   1276         */
   1277        if (bytesWritten >= 0) {
   1278 
   1279                client->connectStatus = BIND_RESPONSE;
   1280 
   1281                PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1282                        ((PKIX_PL_Object *)client, plContext),
   1283                        PKIX_OBJECTINVALIDATECACHEFAILED);
   1284 
   1285                *pKeepGoing = PKIX_TRUE;
   1286        }
   1287 
   1288 cleanup:
   1289        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1290 }
   1291 
   1292 /*
   1293 * FUNCTION: pkix_pl_LdapDefaultClient_BindResponse
   1294 * DESCRIPTION:
   1295 *
   1296 *  This function attempts to read the LDAP-protocol BindResponse message for
   1297 *  the CertStore embodied in the LdapDefaultClient "client", and stores in
   1298 *  "pKeepGoing" a flag indicating whether processing can continue without
   1299 *  further input.
   1300 *
   1301 *  If a BindResponse is received with a Result code of 0 (success), we
   1302 *  continue with the connection. If a non-zero Result code is received,
   1303 *  we throw an Error. Some more sophisticated handling of that condition
   1304 *  might be in order in the future.
   1305 *
   1306 * PARAMETERS:
   1307 *  "client"
   1308 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1309 *  "pKeepGoing"
   1310 *      The address at which the Boolean state machine flag is stored to
   1311 *      indicate whether processing can continue without further input.
   1312 *      Must be non-NULL.
   1313 *  "plContext"
   1314 *      Platform-specific context pointer.
   1315 * THREAD SAFETY:
   1316 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1317 * RETURNS:
   1318 *  Returns NULL if the function succeeds.
   1319 *  Returns a LdapDefaultClient Error if the function fails in a
   1320 *      non-fatal way.
   1321 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1322 */
   1323 static PKIX_Error *
   1324 pkix_pl_LdapDefaultClient_BindResponse(
   1325        PKIX_PL_LdapDefaultClient *client,
   1326        PKIX_Boolean *pKeepGoing,
   1327        void *plContext)
   1328 {
   1329        PKIX_Int32 bytesRead = 0;
   1330        PKIX_PL_Socket_Callback *callbackList = NULL;
   1331 
   1332        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_BindResponse");
   1333        PKIX_NULLCHECK_TWO(client, client->rcvBuf);
   1334 
   1335        callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   1336 
   1337        PKIX_CHECK(callbackList->recvCallback
   1338                (client->clientSocket,
   1339                client->rcvBuf,
   1340                client->capacity,
   1341                &bytesRead,
   1342                plContext),
   1343                PKIX_SOCKETRECVFAILED);
   1344 
   1345        client->lastIO = PR_Now();
   1346 
   1347        if (bytesRead > 0) {
   1348                PKIX_CHECK(pkix_pl_LdapDefaultClient_VerifyBindResponse
   1349                        (client, bytesRead, plContext),
   1350                        PKIX_LDAPDEFAULTCLIENTVERIFYBINDRESPONSEFAILED);
   1351                /*
   1352                 * XXX What should we do if failure? At present if
   1353                 * VerifyBindResponse throws an Error, we do too.
   1354                 */
   1355                client->connectStatus = BOUND;
   1356        } else {
   1357                client->connectStatus = BIND_RESPONSE_PENDING;
   1358        }
   1359 
   1360        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1361                ((PKIX_PL_Object *)client, plContext),
   1362                PKIX_OBJECTINVALIDATECACHEFAILED);
   1363 
   1364        *pKeepGoing = PKIX_TRUE;
   1365 
   1366 cleanup:
   1367        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1368 }
   1369 
   1370 /*
   1371 * FUNCTION: pkix_pl_LdapDefaultClient_BindResponseContinue
   1372 * DESCRIPTION:
   1373 *
   1374 *  This function determines whether the LDAP-protocol BindResponse message for
   1375 *  the CertStore embodied in the LdapDefaultClient "client" has completed, and
   1376 *  stores in "pKeepGoing" a flag indicating whether processing can continue
   1377 *  without further input.
   1378 *
   1379 * PARAMETERS:
   1380 *  "client"
   1381 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1382 *  "pKeepGoing"
   1383 *      The address at which the Boolean state machine flag is stored to
   1384 *      indicate whether processing can continue without further input.
   1385 *      Must be non-NULL.
   1386 *  "plContext"
   1387 *      Platform-specific context pointer.
   1388 * THREAD SAFETY:
   1389 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1390 * RETURNS:
   1391 *  Returns NULL if the function succeeds.
   1392 *  Returns a LdapDefaultClient Error if the function fails in a
   1393 *      non-fatal way.
   1394 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1395 */
   1396 static PKIX_Error *
   1397 pkix_pl_LdapDefaultClient_BindResponseContinue(
   1398        PKIX_PL_LdapDefaultClient *client,
   1399        PKIX_Boolean *pKeepGoing,
   1400        void *plContext)
   1401 {
   1402        PKIX_Int32 bytesRead = 0;
   1403        PKIX_PL_Socket_Callback *callbackList = NULL;
   1404 
   1405        PKIX_ENTER
   1406                (LDAPDEFAULTCLIENT,
   1407                "pkix_pl_LdapDefaultClient_BindResponseContinue");
   1408        PKIX_NULLCHECK_ONE(client);
   1409 
   1410        callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   1411 
   1412        PKIX_CHECK(callbackList->pollCallback
   1413                (client->clientSocket, NULL, &bytesRead, plContext),
   1414                PKIX_SOCKETPOLLFAILED);
   1415 
   1416        if (bytesRead > 0) {
   1417                PKIX_CHECK(pkix_pl_LdapDefaultClient_VerifyBindResponse
   1418                        (client, bytesRead, plContext),
   1419                        PKIX_LDAPDEFAULTCLIENTVERIFYBINDRESPONSEFAILED);
   1420                client->connectStatus = BOUND;
   1421 
   1422                PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1423                        ((PKIX_PL_Object *)client, plContext),
   1424                        PKIX_OBJECTINVALIDATECACHEFAILED);
   1425 
   1426                *pKeepGoing = PKIX_TRUE;
   1427        } else {
   1428                *pKeepGoing = PKIX_FALSE;
   1429        }
   1430 
   1431 cleanup:
   1432        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1433 }
   1434 
   1435 /*
   1436 * FUNCTION: pkix_pl_LdapDefaultClient_Send
   1437 * DESCRIPTION:
   1438 *
   1439 *  This function creates and sends an LDAP-protocol message for the
   1440 *  CertStore embodied in the LdapDefaultClient "client", and stores in
   1441 *  "pKeepGoing" a flag indicating whether processing can continue without
   1442 *  further input, and at "pBytesTransferred" the number of bytes sent.
   1443 *
   1444 *  If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use
   1445 *  and that transmission has not completed.
   1446 *
   1447 * PARAMETERS:
   1448 *  "client"
   1449 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1450 *  "pKeepGoing"
   1451 *      The address at which the Boolean state machine flag is stored to
   1452 *      indicate whether processing can continue without further input.
   1453 *      Must be non-NULL.
   1454 *  "pBytesTransferred"
   1455 *      The address at which the number of bytes sent is stored. Must be
   1456 *      non-NULL.
   1457 *  "plContext"
   1458 *      Platform-specific context pointer.
   1459 * THREAD SAFETY:
   1460 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1461 * RETURNS:
   1462 *  Returns NULL if the function succeeds.
   1463 *  Returns a LdapDefaultClient Error if the function fails in a
   1464 *      non-fatal way.
   1465 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1466 */
   1467 static PKIX_Error *
   1468 pkix_pl_LdapDefaultClient_Send(
   1469        PKIX_PL_LdapDefaultClient *client,
   1470        PKIX_Boolean *pKeepGoing,
   1471        PKIX_UInt32 *pBytesTransferred,
   1472        void *plContext)
   1473 {
   1474        PKIX_Int32 bytesWritten = 0;
   1475        PKIX_PL_Socket_Callback *callbackList = NULL;
   1476 
   1477        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Send");
   1478        PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred);
   1479 
   1480        *pKeepGoing = PKIX_FALSE;
   1481 
   1482        /* Do we have anything waiting to go? */
   1483        if (client->sendBuf) {
   1484                callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   1485 
   1486                PKIX_CHECK(callbackList->sendCallback
   1487                        (client->clientSocket,
   1488                        client->sendBuf,
   1489                        client->bytesToWrite,
   1490                        &bytesWritten,
   1491                        plContext),
   1492                        PKIX_SOCKETSENDFAILED);
   1493 
   1494                client->lastIO = PR_Now();
   1495 
   1496                /*
   1497                 * If the send completed we can proceed to try for the
   1498                 * response. If the send did not complete we will have
   1499                 * to poll for completion later.
   1500                 */
   1501                if (bytesWritten >= 0) {
   1502                        client->sendBuf = NULL;
   1503                        client->connectStatus = RECV;
   1504                        *pKeepGoing = PKIX_TRUE;
   1505 
   1506                } else {
   1507                        *pKeepGoing = PKIX_FALSE;
   1508                        client->connectStatus = SEND_PENDING;
   1509                }
   1510 
   1511        }
   1512 
   1513        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1514                ((PKIX_PL_Object *)client, plContext),
   1515                PKIX_OBJECTINVALIDATECACHEFAILED);
   1516 
   1517        *pBytesTransferred = bytesWritten;
   1518 
   1519 cleanup:
   1520        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1521 }
   1522 
   1523 /*
   1524 * FUNCTION: pkix_pl_LdapDefaultClient_SendContinue
   1525 * DESCRIPTION:
   1526 *
   1527 *  This function determines whether the sending of the LDAP-protocol message
   1528 *  for the CertStore embodied in the LdapDefaultClient "client" has completed,
   1529 *  and stores in "pKeepGoing" a flag indicating whether processing can continue
   1530 *  without further input, and at "pBytesTransferred" the number of bytes sent.
   1531 *
   1532 *  If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use
   1533 *  and that transmission has not completed.
   1534 *
   1535 * PARAMETERS:
   1536 *  "client"
   1537 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1538 *  "pKeepGoing"
   1539 *      The address at which the Boolean state machine flag is stored to
   1540 *      indicate whether processing can continue without further input.
   1541 *      Must be non-NULL.
   1542 *  "pBytesTransferred"
   1543 *      The address at which the number of bytes sent is stored. Must be
   1544 *      non-NULL.
   1545 *  "plContext"
   1546 *      Platform-specific context pointer.
   1547 * THREAD SAFETY:
   1548 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1549 * RETURNS:
   1550 *  Returns NULL if the function succeeds.
   1551 *  Returns a LdapDefaultClient Error if the function fails in a
   1552 *      non-fatal way.
   1553 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1554 */
   1555 static PKIX_Error *
   1556 pkix_pl_LdapDefaultClient_SendContinue(
   1557        PKIX_PL_LdapDefaultClient *client,
   1558        PKIX_Boolean *pKeepGoing,
   1559        PKIX_UInt32 *pBytesTransferred,
   1560        void *plContext)
   1561 {
   1562        PKIX_Int32 bytesWritten = 0;
   1563        PKIX_PL_Socket_Callback *callbackList = NULL;
   1564 
   1565        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_SendContinue");
   1566        PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred);
   1567 
   1568        *pKeepGoing = PKIX_FALSE;
   1569 
   1570        callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   1571 
   1572        PKIX_CHECK(callbackList->pollCallback
   1573                (client->clientSocket, &bytesWritten, NULL, plContext),
   1574                PKIX_SOCKETPOLLFAILED);
   1575 
   1576        /*
   1577         * If the send completed we can proceed to try for the
   1578         * response. If the send did not complete we will have
   1579         * continue to poll.
   1580         */
   1581        if (bytesWritten >= 0) {
   1582                client->sendBuf = NULL;
   1583                client->connectStatus = RECV;
   1584 
   1585                PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1586                        ((PKIX_PL_Object *)client, plContext),
   1587                        PKIX_OBJECTINVALIDATECACHEFAILED);
   1588 
   1589                *pKeepGoing = PKIX_TRUE;
   1590        }
   1591 
   1592        *pBytesTransferred = bytesWritten;
   1593 
   1594 cleanup:
   1595        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1596 }
   1597 
   1598 /*
   1599 * FUNCTION: pkix_pl_LdapDefaultClient_Recv
   1600 * DESCRIPTION:
   1601 *
   1602 *  This function receives an LDAP-protocol message for the CertStore embodied
   1603 *  in the LdapDefaultClient "client", and stores in "pKeepGoing" a flag
   1604 *  indicating whether processing can continue without further input.
   1605 *
   1606 * PARAMETERS:
   1607 *  "client"
   1608 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1609 *  "pKeepGoing"
   1610 *      The address at which the Boolean state machine flag is stored to
   1611 *      indicate whether processing can continue without further input.
   1612 *      Must be non-NULL.
   1613 *  "plContext"
   1614 *      Platform-specific context pointer.
   1615 * THREAD SAFETY:
   1616 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1617 * RETURNS:
   1618 *  Returns NULL if the function succeeds.
   1619 *  Returns a LdapDefaultClient Error if the function fails in a
   1620 *      non-fatal way.
   1621 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1622 */
   1623 static PKIX_Error *
   1624 pkix_pl_LdapDefaultClient_Recv(
   1625        PKIX_PL_LdapDefaultClient *client,
   1626        PKIX_Boolean *pKeepGoing,
   1627        void *plContext)
   1628 {
   1629        PKIX_Int32 bytesRead = 0;
   1630        PKIX_UInt32 bytesToRead = 0;
   1631        PKIX_PL_Socket_Callback *callbackList = NULL;
   1632 
   1633        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Recv");
   1634        PKIX_NULLCHECK_THREE(client, pKeepGoing, client->rcvBuf);
   1635 
   1636        callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   1637 
   1638        /*
   1639         * If we attempt to fill our buffer with every read, we increase
   1640         * the risk of an ugly situation: one or two bytes of a new message
   1641         * left over at the end of processing one message. With such a
   1642         * fragment, we can't decode a byte count and so won't know how much
   1643         * space to allocate for the next LdapResponse. We try to avoid that
   1644         * case by reading just enough to complete the current message, unless
   1645         * there will be at least MINIMUM_MSG_LENGTH bytes left over.
   1646         */
   1647        if (client->currentResponse) {
   1648                PKIX_CHECK(pkix_pl_LdapResponse_GetCapacity
   1649                        (client->currentResponse, &bytesToRead, plContext),
   1650                        PKIX_LDAPRESPONSEGETCAPACITYFAILED);
   1651                if ((bytesToRead > client->capacity) ||
   1652                    ((bytesToRead + MINIMUM_MSG_LENGTH) < client->capacity)) {
   1653                        bytesToRead = client->capacity;
   1654                }
   1655        } else {
   1656                bytesToRead = client->capacity;
   1657        }
   1658 
   1659        client->currentBytesAvailable = 0;
   1660 
   1661        PKIX_CHECK(callbackList->recvCallback
   1662                (client->clientSocket,
   1663                (void *)client->rcvBuf,
   1664                bytesToRead,
   1665                &bytesRead,
   1666                plContext),
   1667                PKIX_SOCKETRECVFAILED);
   1668 
   1669        client->currentInPtr = client->rcvBuf;
   1670        client->lastIO = PR_Now();
   1671 
   1672        if (bytesRead > 0) {
   1673                client->currentBytesAvailable = bytesRead;
   1674                client->connectStatus = RECV_INITIAL;
   1675                *pKeepGoing = PKIX_TRUE;
   1676        } else {
   1677                client->connectStatus = RECV_PENDING;
   1678                *pKeepGoing = PKIX_FALSE;
   1679        }
   1680 
   1681        PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1682                ((PKIX_PL_Object *)client, plContext),
   1683                PKIX_OBJECTINVALIDATECACHEFAILED);
   1684 
   1685 cleanup:
   1686        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1687 }
   1688 
   1689 /*
   1690 * FUNCTION: pkix_pl_LdapDefaultClient_RecvContinue
   1691 * DESCRIPTION:
   1692 *
   1693 *  This function determines whether the receiving of the LDAP-protocol message
   1694 *  for the CertStore embodied in the LdapDefaultClient "client" has completed,
   1695 *  and stores in "pKeepGoing" a flag indicating whether processing can continue
   1696 *  without further input.
   1697 *
   1698 * PARAMETERS:
   1699 *  "client"
   1700 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1701 *  "pKeepGoing"
   1702 *      The address at which the Boolean state machine flag is stored to
   1703 *      indicate whether processing can continue without further input.
   1704 *      Must be non-NULL.
   1705 *  "plContext"
   1706 *      Platform-specific context pointer.
   1707 * THREAD SAFETY:
   1708 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1709 * RETURNS:
   1710 *  Returns NULL if the function succeeds.
   1711 *  Returns a LdapDefaultClient Error if the function fails in a
   1712 *      non-fatal way.
   1713 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1714 */
   1715 static PKIX_Error *
   1716 pkix_pl_LdapDefaultClient_RecvContinue(
   1717        PKIX_PL_LdapDefaultClient *client,
   1718        PKIX_Boolean *pKeepGoing,
   1719        void *plContext)
   1720 {
   1721        PKIX_Int32 bytesRead = 0;
   1722        PKIX_PL_Socket_Callback *callbackList = NULL;
   1723 
   1724        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvContinue");
   1725        PKIX_NULLCHECK_TWO(client, pKeepGoing);
   1726 
   1727        callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   1728 
   1729        PKIX_CHECK(callbackList->pollCallback
   1730                (client->clientSocket, NULL, &bytesRead, plContext),
   1731                PKIX_SOCKETPOLLFAILED);
   1732 
   1733        if (bytesRead > 0) {
   1734                client->currentBytesAvailable += bytesRead;
   1735                client->connectStatus = RECV_INITIAL;
   1736                *pKeepGoing = PKIX_TRUE;
   1737 
   1738                PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1739                        ((PKIX_PL_Object *)client, plContext),
   1740                        PKIX_OBJECTINVALIDATECACHEFAILED);
   1741        } else {
   1742                *pKeepGoing = PKIX_FALSE;
   1743        }
   1744 
   1745 cleanup:
   1746        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1747 }
   1748 
   1749 /*
   1750 * FUNCTION: pkix_pl_LdapDefaultClient_AbandonContinue
   1751 * DESCRIPTION:
   1752 *
   1753 *  This function determines whether the abandon-message request of the
   1754 *  LDAP-protocol message for the CertStore embodied in the LdapDefaultClient
   1755 *  "client" has completed, and stores in "pKeepGoing" a flag indicating whether
   1756 *  processing can continue without further input.
   1757 *
   1758 * PARAMETERS:
   1759 *  "client"
   1760 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1761 *  "pKeepGoing"
   1762 *      The address at which the Boolean state machine flag is stored to
   1763 *      indicate whether processing can continue without further input.
   1764 *      Must be non-NULL.
   1765 *  "plContext"
   1766 *      Platform-specific context pointer.
   1767 * THREAD SAFETY:
   1768 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1769 * RETURNS:
   1770 *  Returns NULL if the function succeeds.
   1771 *  Returns a LdapDefaultClient Error if the function fails in a
   1772 *      non-fatal way.
   1773 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1774 */
   1775 static PKIX_Error *
   1776 pkix_pl_LdapDefaultClient_AbandonContinue(
   1777        PKIX_PL_LdapDefaultClient *client,
   1778        PKIX_Boolean *pKeepGoing,
   1779        void *plContext)
   1780 {
   1781        PKIX_Int32 bytesWritten = 0;
   1782        PKIX_PL_Socket_Callback *callbackList = NULL;
   1783 
   1784        PKIX_ENTER
   1785                (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_AbandonContinue");
   1786        PKIX_NULLCHECK_TWO(client, pKeepGoing);
   1787 
   1788        callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   1789 
   1790        PKIX_CHECK(callbackList->pollCallback
   1791                (client->clientSocket, &bytesWritten, NULL, plContext),
   1792                PKIX_SOCKETPOLLFAILED);
   1793 
   1794        if (bytesWritten > 0) {
   1795                client->connectStatus = BOUND;
   1796                *pKeepGoing = PKIX_TRUE;
   1797 
   1798                PKIX_CHECK(PKIX_PL_Object_InvalidateCache
   1799                        ((PKIX_PL_Object *)client, plContext),
   1800                        PKIX_OBJECTINVALIDATECACHEFAILED);
   1801        } else {
   1802                *pKeepGoing = PKIX_FALSE;
   1803        }
   1804 
   1805 cleanup:
   1806        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1807 }
   1808 
   1809 /*
   1810 * FUNCTION: pkix_pl_LdapDefaultClient_RecvInitial
   1811 * DESCRIPTION:
   1812 *
   1813 *  This function processes the contents of the first buffer of a received
   1814 *  LDAP-protocol message for the CertStore embodied in the LdapDefaultClient
   1815 *  "client", and stores in "pKeepGoing" a flag indicating whether processing can
   1816 *  continue without further input.
   1817 *
   1818 * PARAMETERS:
   1819 *  "client"
   1820 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1821 *  "pKeepGoing"
   1822 *      The address at which the Boolean state machine flag is stored to
   1823 *      indicate whether processing can continue without further input.
   1824 *      Must be non-NULL.
   1825 *  "plContext"
   1826 *      Platform-specific context pointer.
   1827 * THREAD SAFETY:
   1828 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1829 * RETURNS:
   1830 *  Returns NULL if the function succeeds.
   1831 *  Returns a LdapDefaultClient Error if the function fails in a
   1832 *      non-fatal way.
   1833 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1834 */
   1835 static PKIX_Error *
   1836 pkix_pl_LdapDefaultClient_RecvInitial(
   1837        PKIX_PL_LdapDefaultClient *client,
   1838        PKIX_Boolean *pKeepGoing,
   1839        void *plContext)
   1840 {
   1841        unsigned char *msgBuf = NULL;
   1842        unsigned char *to = NULL;
   1843        unsigned char *from = NULL;
   1844        PKIX_UInt32 dataIndex = 0;
   1845        PKIX_UInt32 messageIdLen = 0;
   1846        PKIX_UInt32 messageLength = 0;
   1847        PKIX_UInt32 sizeofLength = 0;
   1848        PKIX_UInt32 bytesProcessed = 0;
   1849        unsigned char messageChar = 0;
   1850        LDAPMessageType messageType = 0;
   1851        PKIX_Int32 bytesRead = 0;
   1852        PKIX_PL_Socket_Callback *callbackList = NULL;
   1853 
   1854        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvInitial");
   1855        PKIX_NULLCHECK_TWO(client, pKeepGoing);
   1856 
   1857        /*
   1858         * Is there an LDAPResponse in progress? I.e., have we
   1859         * already processed the tag and length at the beginning of
   1860         * the message?
   1861         */
   1862        if (client->currentResponse) {
   1863                client->connectStatus = RECV_NONINITIAL;
   1864                *pKeepGoing = PKIX_TRUE;
   1865                goto cleanup;
   1866        }
   1867        msgBuf = client->currentInPtr;
   1868 
   1869        /* Do we have enough of the message to decode the message length? */
   1870        if (client->currentBytesAvailable < MINIMUM_MSG_LENGTH) {
   1871                /*
   1872                 * No! Move these few bytes to the beginning of rcvBuf
   1873                 * and hang another read.
   1874                 */
   1875 
   1876                to = (unsigned char *)client->rcvBuf;
   1877                from = client->currentInPtr;
   1878                for (dataIndex = 0;
   1879                    dataIndex < client->currentBytesAvailable;
   1880                    dataIndex++) {
   1881                        *to++ = *from++;
   1882                }
   1883                callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   1884                PKIX_CHECK(callbackList->recvCallback
   1885                        (client->clientSocket,
   1886                        (void *)to,
   1887                        client->capacity - client->currentBytesAvailable,
   1888                        &bytesRead,
   1889                        plContext),
   1890                        PKIX_SOCKETRECVFAILED);
   1891 
   1892                client->currentInPtr = client->rcvBuf;
   1893                client->lastIO = PR_Now();
   1894 
   1895                if (bytesRead <= 0) {
   1896                        client->connectStatus = RECV_PENDING;
   1897                        *pKeepGoing = PKIX_FALSE;
   1898                        goto cleanup;
   1899                } else {
   1900                        client->currentBytesAvailable += bytesRead;
   1901                }
   1902        }
   1903 
   1904        /*
   1905         * We have to determine whether the response is an entry, with
   1906         * application-specific tag LDAP_SEARCHRESPONSEENTRY_TYPE, or a
   1907         * resultCode, with application tag LDAP_SEARCHRESPONSERESULT_TYPE.
   1908         * First, we have to figure out where to look for the tag.
   1909         */
   1910 
   1911        /* Is the message length short form (one octet) or long form? */
   1912        if ((msgBuf[1] & 0x80) != 0) {
   1913                sizeofLength = msgBuf[1] & 0x7F;
   1914                for (dataIndex = 0; dataIndex < sizeofLength; dataIndex++) {
   1915                        messageLength =
   1916                                (messageLength << 8) + msgBuf[dataIndex + 2];
   1917                }
   1918        } else {
   1919                messageLength = msgBuf[1];
   1920        }
   1921 
   1922        /* How many bytes did the messageID require? */
   1923        messageIdLen = msgBuf[dataIndex + 3];
   1924 
   1925        messageChar = msgBuf[dataIndex + messageIdLen + 4];
   1926 
   1927        /* Are we looking at an Entry message or a ResultCode message? */
   1928        if ((SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION |
   1929            LDAP_SEARCHRESPONSEENTRY_TYPE) == messageChar) {
   1930 
   1931                messageType = LDAP_SEARCHRESPONSEENTRY_TYPE;
   1932 
   1933        } else if ((SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION |
   1934            LDAP_SEARCHRESPONSERESULT_TYPE) == messageChar) {
   1935 
   1936                messageType = LDAP_SEARCHRESPONSERESULT_TYPE;
   1937 
   1938        } else {
   1939 
   1940                PKIX_ERROR(PKIX_SEARCHRESPONSEPACKETOFUNKNOWNTYPE);
   1941 
   1942        }
   1943 
   1944        /*
   1945         * messageLength is the length from (tag, length, value).
   1946         * We have to allocate space for the tag and length bits too.
   1947         */
   1948        PKIX_CHECK(pkix_pl_LdapResponse_Create
   1949                (messageType,
   1950                messageLength + dataIndex + 2,
   1951                client->currentBytesAvailable,
   1952                msgBuf,
   1953                &bytesProcessed,
   1954                &(client->currentResponse),
   1955                plContext),
   1956                PKIX_LDAPRESPONSECREATEFAILED);
   1957 
   1958        client->currentBytesAvailable -= bytesProcessed;
   1959 
   1960        PKIX_CHECK(pkix_pl_LdapDefaultClient_RecvCheckComplete
   1961                (client, bytesProcessed, pKeepGoing, plContext),
   1962                PKIX_LDAPDEFAULTCLIENTRECVCHECKCOMPLETEFAILED);
   1963 
   1964 cleanup:
   1965 
   1966        PKIX_RETURN(LDAPDEFAULTCLIENT);
   1967 }
   1968 
   1969 /*
   1970 * FUNCTION: pkix_pl_LdapDefaultClient_RecvNonInitial
   1971 * DESCRIPTION:
   1972 *
   1973 *  This function processes the contents of buffers, after the first, of a
   1974 *  received LDAP-protocol message for the CertStore embodied in the
   1975 *  LdapDefaultClient "client", and stores in "pKeepGoing" a flag indicating
   1976 *  whether processing can continue without further input.
   1977 *
   1978 * PARAMETERS:
   1979 *  "client"
   1980 *      The address of the LdapDefaultClient object. Must be non-NULL.
   1981 *  "pKeepGoing"
   1982 *      The address at which the Boolean state machine flag is stored to
   1983 *      indicate whether processing can continue without further input.
   1984 *      Must be non-NULL.
   1985 *  "plContext"
   1986 *      Platform-specific context pointer.
   1987 * THREAD SAFETY:
   1988 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   1989 * RETURNS:
   1990 *  Returns NULL if the function succeeds.
   1991 *  Returns a LdapDefaultClient Error if the function fails in a
   1992 *      non-fatal way.
   1993 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   1994 */
   1995 static PKIX_Error *
   1996 pkix_pl_LdapDefaultClient_RecvNonInitial(
   1997        PKIX_PL_LdapDefaultClient *client,
   1998        PKIX_Boolean *pKeepGoing,
   1999        void *plContext)
   2000 {
   2001 
   2002        PKIX_UInt32 bytesProcessed = 0;
   2003 
   2004        PKIX_ENTER
   2005                (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvNonInitial");
   2006        PKIX_NULLCHECK_TWO(client, pKeepGoing);
   2007 
   2008        PKIX_CHECK(pkix_pl_LdapResponse_Append
   2009                (client->currentResponse,
   2010                client->currentBytesAvailable,
   2011                client->currentInPtr,
   2012                &bytesProcessed,
   2013                plContext),
   2014                PKIX_LDAPRESPONSEAPPENDFAILED);
   2015 
   2016        client->currentBytesAvailable -= bytesProcessed;
   2017 
   2018        PKIX_CHECK(pkix_pl_LdapDefaultClient_RecvCheckComplete
   2019                (client, bytesProcessed, pKeepGoing, plContext),
   2020                PKIX_LDAPDEFAULTCLIENTRECVCHECKCOMPLETEFAILED);
   2021 
   2022 cleanup:
   2023 
   2024        PKIX_RETURN(LDAPDEFAULTCLIENT);
   2025 }
   2026 
   2027 /*
   2028 * FUNCTION: pkix_pl_LdapDefaultClient_Dispatch
   2029 * DESCRIPTION:
   2030 *
   2031 *  This function is the state machine dispatcher for the CertStore embodied in
   2032 *  the LdapDefaultClient pointed to by "client". Results are returned by
   2033 *  changes to various fields in the context.
   2034 *
   2035 * PARAMETERS:
   2036 *  "client"
   2037 *      The address of the LdapDefaultClient object. Must be non-NULL.
   2038 *  "plContext"
   2039 *      Platform-specific context pointer.
   2040 * THREAD SAFETY:
   2041 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   2042 * RETURNS:
   2043 *  Returns NULL if the function succeeds.
   2044 *  Returns a LdapDefaultClient Error if the function fails in a
   2045 *      non-fatal way.
   2046 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   2047 */
   2048 static PKIX_Error *
   2049 pkix_pl_LdapDefaultClient_Dispatch(
   2050        PKIX_PL_LdapDefaultClient *client,
   2051        void *plContext)
   2052 {
   2053        PKIX_UInt32 bytesTransferred = 0;
   2054        PKIX_Boolean keepGoing = PKIX_TRUE;
   2055 
   2056        PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Dispatch");
   2057        PKIX_NULLCHECK_ONE(client);
   2058 
   2059        while (keepGoing) {
   2060                switch (client->connectStatus) {
   2061                case CONNECT_PENDING:
   2062                        PKIX_CHECK
   2063                                (pkix_pl_LdapDefaultClient_ConnectContinue
   2064                                (client, &keepGoing, plContext),
   2065                                PKIX_LDAPDEFAULTCLIENTCONNECTCONTINUEFAILED);
   2066                        break;
   2067                case CONNECTED:
   2068                        PKIX_CHECK
   2069                                (pkix_pl_LdapDefaultClient_Bind
   2070                                (client, &keepGoing, plContext),
   2071                                PKIX_LDAPDEFAULTCLIENTBINDFAILED);
   2072                        break;
   2073                case BIND_PENDING:
   2074                        PKIX_CHECK
   2075                                (pkix_pl_LdapDefaultClient_BindContinue
   2076                                (client, &keepGoing, plContext),
   2077                                PKIX_LDAPDEFAULTCLIENTBINDCONTINUEFAILED);
   2078                        break;
   2079                case BIND_RESPONSE:
   2080                        PKIX_CHECK
   2081                                (pkix_pl_LdapDefaultClient_BindResponse
   2082                                (client, &keepGoing, plContext),
   2083                                PKIX_LDAPDEFAULTCLIENTBINDRESPONSEFAILED);
   2084                        break;
   2085                case BIND_RESPONSE_PENDING:
   2086                        PKIX_CHECK
   2087                                (pkix_pl_LdapDefaultClient_BindResponseContinue
   2088                                (client, &keepGoing, plContext),
   2089                                PKIX_LDAPDEFAULTCLIENTBINDRESPONSECONTINUEFAILED);
   2090                        break;
   2091                case BOUND:
   2092                        PKIX_CHECK
   2093                                (pkix_pl_LdapDefaultClient_Send
   2094                                (client, &keepGoing, &bytesTransferred, plContext),
   2095                                PKIX_LDAPDEFAULTCLIENTSENDFAILED);
   2096                        break;
   2097                case SEND_PENDING:
   2098                        PKIX_CHECK
   2099                                (pkix_pl_LdapDefaultClient_SendContinue
   2100                                (client, &keepGoing, &bytesTransferred, plContext),
   2101                                PKIX_LDAPDEFAULTCLIENTSENDCONTINUEFAILED);
   2102                        break;
   2103                case RECV:
   2104                        PKIX_CHECK
   2105                                (pkix_pl_LdapDefaultClient_Recv
   2106                                (client, &keepGoing, plContext),
   2107                                PKIX_LDAPDEFAULTCLIENTRECVFAILED);
   2108                        break;
   2109                case RECV_PENDING:
   2110                        PKIX_CHECK
   2111                                (pkix_pl_LdapDefaultClient_RecvContinue
   2112                                (client, &keepGoing, plContext),
   2113                                PKIX_LDAPDEFAULTCLIENTRECVCONTINUEFAILED);
   2114                        break;
   2115                case RECV_INITIAL:
   2116                        PKIX_CHECK
   2117                                (pkix_pl_LdapDefaultClient_RecvInitial
   2118                                (client, &keepGoing, plContext),
   2119                                PKIX_LDAPDEFAULTCLIENTRECVINITIALFAILED);
   2120                        break;
   2121                case RECV_NONINITIAL:
   2122                        PKIX_CHECK
   2123                                (pkix_pl_LdapDefaultClient_RecvNonInitial
   2124                                (client, &keepGoing, plContext),
   2125                                PKIX_LDAPDEFAULTCLIENTRECVNONINITIALFAILED);
   2126                        break;
   2127                case ABANDON_PENDING:
   2128                        PKIX_CHECK
   2129                                (pkix_pl_LdapDefaultClient_AbandonContinue
   2130                                (client, &keepGoing, plContext),
   2131                                PKIX_LDAPDEFAULTCLIENTABANDONCONTINUEFAILED);
   2132                        break;
   2133                default:
   2134                        PKIX_ERROR(PKIX_LDAPCERTSTOREINILLEGALSTATE);
   2135                }
   2136        }
   2137 
   2138 cleanup:
   2139 
   2140        PKIX_RETURN(LDAPDEFAULTCLIENT);
   2141 }
   2142 
   2143 /*
   2144 * FUNCTION: pkix_pl_LdapDefaultClient_MakeAndFilter
   2145 * DESCRIPTION:
   2146 *
   2147 *  This function allocates space from the arena pointed to by "arena" to
   2148 *  construct a filter that will match components of the X500Name pointed to by
   2149 *  XXX...
   2150 *
   2151 * PARAMETERS:
   2152 *  "arena"
   2153 *      The address of the PLArenaPool used in creating the filter. Must be
   2154 *       non-NULL.
   2155 *  "nameComponent"
   2156 *      The address of a NULL-terminated list of LDAPNameComponents
   2157 *      Must be non-NULL.
   2158 *  "pFilter"
   2159 *      The address at which the result is stored.
   2160 *  "plContext"
   2161 *      Platform-specific context pointer
   2162 * THREAD SAFETY:
   2163 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   2164 * RETURNS:
   2165 *  Returns NULL if the function succeeds.
   2166 *  Returns a CertStore Error if the function fails in a non-fatal way.
   2167 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   2168 */
   2169 static PKIX_Error *
   2170 pkix_pl_LdapDefaultClient_MakeAndFilter(
   2171        PLArenaPool *arena,
   2172        LDAPNameComponent **nameComponents,
   2173        LDAPFilter **pFilter,
   2174        void *plContext)
   2175 {
   2176        LDAPFilter **setOfFilter;
   2177        LDAPFilter *andFilter = NULL;
   2178        LDAPFilter *currentFilter = NULL;
   2179        PKIX_UInt32 componentsPresent = 0;
   2180        void *v = NULL;
   2181        unsigned char *component = NULL;
   2182        LDAPNameComponent **componentP = NULL;
   2183 
   2184        PKIX_ENTER(CERTSTORE, "pkix_pl_LdapDefaultClient_MakeAndFilter");
   2185        PKIX_NULLCHECK_THREE(arena, nameComponents, pFilter);
   2186 
   2187        /* count how many components we were provided */
   2188        for (componentP = nameComponents, componentsPresent = 0;
   2189                *(componentP++) != NULL;
   2190                componentsPresent++) {}
   2191 
   2192        /* Space for (componentsPresent + 1) pointers to LDAPFilter */
   2193        PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZAlloc,
   2194                (arena, (componentsPresent + 1)*sizeof(LDAPFilter *)));
   2195        setOfFilter = (LDAPFilter **)v;
   2196 
   2197        /* Space for AndFilter and <componentsPresent> EqualFilters */
   2198        PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZNewArray,
   2199                (arena, LDAPFilter, componentsPresent + 1));
   2200        setOfFilter[0] = (LDAPFilter *)v;
   2201 
   2202        /* Claim the first array element for the ANDFilter */
   2203        andFilter = setOfFilter[0];
   2204 
   2205        /* Set ANDFilter to point to the first EqualFilter pointer */
   2206        andFilter->selector = LDAP_ANDFILTER_TYPE;
   2207        andFilter->filter.andFilter.filters = setOfFilter;
   2208 
   2209        currentFilter = andFilter + 1;
   2210 
   2211        for (componentP = nameComponents, componentsPresent = 0;
   2212                *(componentP) != NULL; componentP++) {
   2213                setOfFilter[componentsPresent++] = currentFilter;
   2214                currentFilter->selector = LDAP_EQUALFILTER_TYPE;
   2215                component = (*componentP)->attrType;
   2216                currentFilter->filter.equalFilter.attrType.data = component;
   2217                currentFilter->filter.equalFilter.attrType.len = 
   2218                        PL_strlen((const char *)component);
   2219                component = (*componentP)->attrValue;
   2220                currentFilter->filter.equalFilter.attrValue.data = component;
   2221                currentFilter->filter.equalFilter.attrValue.len =
   2222                        PL_strlen((const char *)component);
   2223                currentFilter++;
   2224        }
   2225 
   2226        setOfFilter[componentsPresent] = NULL;
   2227 
   2228        *pFilter = andFilter;
   2229 
   2230        PKIX_RETURN(CERTSTORE);
   2231 
   2232 }
   2233 
   2234 /*
   2235 * FUNCTION: pkix_pl_LdapDefaultClient_InitiateRequest
   2236 * DESCRIPTION:
   2237 *
   2238 *
   2239 * PARAMETERS:
   2240 *  "client"
   2241 *      The address of the LdapDefaultClient object. Must be non-NULL.
   2242 *  "requestParams"
   2243 *      The address of an LdapClientParams object. Must be non-NULL.
   2244 *  "pPollDesc"
   2245 *      The location where the address of the PRPollDesc is stored, if the
   2246 *      client returns with I/O pending.
   2247 *  "pResponse"
   2248 *      The address where the List of LDAPResponses, or NULL for an
   2249 *      unfinished request, is stored. Must be non-NULL.
   2250 *  "plContext"
   2251 *      Platform-specific context pointer.
   2252 * THREAD SAFETY:
   2253 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   2254 * RETURNS:
   2255 *  Returns NULL if the function succeeds.
   2256 *  Returns a LdapDefaultClient Error if the function fails in a
   2257 *      non-fatal way.
   2258 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   2259 */
   2260 static PKIX_Error *
   2261 pkix_pl_LdapDefaultClient_InitiateRequest(
   2262        PKIX_PL_LdapClient *genericClient,
   2263        LDAPRequestParams *requestParams,
   2264        void **pPollDesc,
   2265        PKIX_List **pResponse,
   2266        void *plContext)
   2267 {
   2268        PKIX_List *searchResponseList = NULL;
   2269        SECItem *encoded = NULL;
   2270        LDAPFilter *filter = NULL;
   2271        PKIX_PL_LdapDefaultClient *client = 0;
   2272 
   2273        PKIX_ENTER
   2274                (LDAPDEFAULTCLIENT,
   2275                "pkix_pl_LdapDefaultClient_InitiateRequest");
   2276        PKIX_NULLCHECK_FOUR(genericClient, requestParams, pPollDesc, pResponse);
   2277 
   2278        PKIX_CHECK(pkix_CheckType
   2279                ((PKIX_PL_Object *)genericClient,
   2280                PKIX_LDAPDEFAULTCLIENT_TYPE,
   2281                plContext),
   2282                PKIX_GENERICCLIENTNOTANLDAPDEFAULTCLIENT);
   2283 
   2284        client = (PKIX_PL_LdapDefaultClient *)genericClient;
   2285 
   2286        PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeAndFilter
   2287                (client->arena, requestParams->nc, &filter, plContext),
   2288                PKIX_LDAPDEFAULTCLIENTMAKEANDFILTERFAILED);
   2289 
   2290        PKIX_CHECK(pkix_pl_LdapRequest_Create
   2291                (client->arena,
   2292                client->messageID++,
   2293                requestParams->baseObject,
   2294                requestParams->scope,
   2295                requestParams->derefAliases,
   2296                requestParams->sizeLimit,
   2297                requestParams->timeLimit,
   2298                PKIX_FALSE,    /* attrs only */
   2299                filter,
   2300                requestParams->attributes,
   2301                &client->currentRequest,
   2302                plContext),
   2303                PKIX_LDAPREQUESTCREATEFAILED);
   2304 
   2305        /* check hashtable for matching request */
   2306        PKIX_CHECK(PKIX_PL_HashTable_Lookup
   2307                (client->cachePtr,
   2308                (PKIX_PL_Object *)(client->currentRequest),
   2309                (PKIX_PL_Object **)&searchResponseList,
   2310                plContext),
   2311                PKIX_HASHTABLELOOKUPFAILED);
   2312 
   2313        if (searchResponseList != NULL) {
   2314                *pPollDesc = NULL;
   2315                *pResponse = searchResponseList;
   2316                PKIX_DECREF(client->currentRequest);
   2317                goto cleanup;
   2318        }
   2319 
   2320        /* It wasn't cached. We'll have to actually send it. */
   2321 
   2322        PKIX_CHECK(pkix_pl_LdapRequest_GetEncoded
   2323                (client->currentRequest, &encoded, plContext),
   2324                PKIX_LDAPREQUESTGETENCODEDFAILED);
   2325 
   2326        client->sendBuf = encoded->data;
   2327        client->bytesToWrite = encoded->len;
   2328 
   2329        PKIX_CHECK(pkix_pl_LdapDefaultClient_Dispatch(client, plContext),
   2330                PKIX_LDAPDEFAULTCLIENTDISPATCHFAILED);
   2331 
   2332        /*
   2333         * It's not enough that we may be done with a particular read.
   2334         * We're still processing the transaction until we've gotten the
   2335         * SearchResponseResult message and returned to the BOUND state.
   2336         * Otherwise we must still have a read pending, and must hold off
   2337         * on returning results.
   2338         */
   2339        if ((client->connectStatus == BOUND) &&
   2340     (client->entriesFound != NULL)) {
   2341                *pPollDesc = NULL;
   2342                *pResponse = client->entriesFound;
   2343                client->entriesFound = NULL;
   2344                PKIX_DECREF(client->currentRequest);
   2345        } else {
   2346                *pPollDesc = &client->pollDesc;
   2347                *pResponse = NULL;
   2348        }
   2349 
   2350 cleanup:
   2351 
   2352        PKIX_RETURN(LDAPDEFAULTCLIENT);
   2353 
   2354 }
   2355 
   2356 /*
   2357 * FUNCTION: pkix_pl_LdapDefaultClient_ResumeRequest
   2358 * DESCRIPTION:
   2359 *
   2360 *
   2361 * PARAMETERS:
   2362 *  "client"
   2363 *      The address of the LdapDefaultClient object. Must be non-NULL.
   2364 *  "pPollDesc"
   2365 *      The location where the address of the PRPollDesc is stored, if the
   2366 *      client returns with I/O pending.
   2367 *  "pResponse"
   2368 *      The address where the List of LDAPResponses, or NULL for an
   2369 *      unfinished request, is stored. Must be non-NULL.
   2370 *  "plContext"
   2371 *      Platform-specific context pointer.
   2372 * THREAD SAFETY:
   2373 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   2374 * RETURNS:
   2375 *  Returns NULL if the function succeeds.
   2376 *  Returns a LdapDefaultClient Error if the function fails in a
   2377 *      non-fatal way.
   2378 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   2379 */
   2380 static PKIX_Error *
   2381 pkix_pl_LdapDefaultClient_ResumeRequest(
   2382        PKIX_PL_LdapClient *genericClient,
   2383        void **pPollDesc,
   2384        PKIX_List **pResponse,
   2385        void *plContext)
   2386 {
   2387        PKIX_PL_LdapDefaultClient *client = 0;
   2388 
   2389        PKIX_ENTER
   2390                (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_ResumeRequest");
   2391        PKIX_NULLCHECK_THREE(genericClient, pPollDesc, pResponse);
   2392 
   2393        PKIX_CHECK(pkix_CheckType
   2394                ((PKIX_PL_Object *)genericClient,
   2395                PKIX_LDAPDEFAULTCLIENT_TYPE,
   2396                plContext),
   2397                PKIX_GENERICCLIENTNOTANLDAPDEFAULTCLIENT);
   2398 
   2399        client = (PKIX_PL_LdapDefaultClient *)genericClient;
   2400 
   2401        PKIX_CHECK(pkix_pl_LdapDefaultClient_Dispatch(client, plContext),
   2402                PKIX_LDAPDEFAULTCLIENTDISPATCHFAILED);
   2403 
   2404        /*
   2405         * It's not enough that we may be done with a particular read.
   2406         * We're still processing the transaction until we've gotten the
   2407         * SearchResponseResult message and returned to the BOUND state.
   2408         * Otherwise we must still have a read pending, and must hold off
   2409         * on returning results.
   2410         */
   2411        if ((client->connectStatus == BOUND) &&
   2412     (client->entriesFound != NULL)) {
   2413                *pPollDesc = NULL;
   2414                *pResponse = client->entriesFound;
   2415                client->entriesFound = NULL;
   2416                PKIX_DECREF(client->currentRequest);
   2417        } else {
   2418                *pPollDesc = &client->pollDesc;
   2419                *pResponse = NULL;
   2420        }
   2421 
   2422 cleanup:
   2423 
   2424        PKIX_RETURN(LDAPDEFAULTCLIENT);
   2425 
   2426 }
   2427 
   2428 /* --Public-LdapDefaultClient-Functions----------------------------------- */
   2429 
   2430 /*
   2431 * FUNCTION: PKIX_PL_LdapDefaultClient_AbandonRequest
   2432 * DESCRIPTION:
   2433 *
   2434 *  This function creates and sends an LDAP-protocol "Abandon" message to the 
   2435 *  server connected to the LdapDefaultClient pointed to by "client".
   2436 *
   2437 * PARAMETERS:
   2438 *  "client"
   2439 *      The LdapDefaultClient whose connection is to be abandoned. Must be
   2440 *      non-NULL.
   2441 *  "plContext"
   2442 *      Platform-specific context pointer.
   2443 * THREAD SAFETY:
   2444 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
   2445 * RETURNS:
   2446 *  Returns NULL if the function succeeds.
   2447 *  Returns a Fatal Error if the function fails in an unrecoverable way.
   2448 */
   2449 PKIX_Error *
   2450 PKIX_PL_LdapDefaultClient_AbandonRequest(
   2451        PKIX_PL_LdapDefaultClient *client,
   2452        void *plContext)
   2453 {
   2454        PKIX_Int32 bytesWritten = 0;
   2455        PKIX_PL_Socket_Callback *callbackList = NULL;
   2456        SECItem *encoded = NULL;
   2457 
   2458        PKIX_ENTER(CERTSTORE, "PKIX_PL_LdapDefaultClient_AbandonRequest");
   2459        PKIX_NULLCHECK_ONE(client);
   2460 
   2461        if (client->connectStatus == RECV_PENDING) {
   2462                PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeAbandon
   2463                        (client->arena,
   2464                        (client->messageID) - 1,
   2465                        &encoded,
   2466                        plContext),
   2467                        PKIX_LDAPDEFAULTCLIENTMAKEABANDONFAILED);
   2468 
   2469                callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList);
   2470                PKIX_CHECK(callbackList->sendCallback
   2471                        (client->clientSocket,
   2472                        encoded->data,
   2473                        encoded->len,
   2474                        &bytesWritten,
   2475                        plContext),
   2476                        PKIX_SOCKETSENDFAILED);
   2477 
   2478                if (bytesWritten < 0) {
   2479                        client->connectStatus = ABANDON_PENDING;
   2480                } else {
   2481                        client->connectStatus = BOUND;
   2482                }
   2483        }
   2484 
   2485        PKIX_DECREF(client->entriesFound);
   2486        PKIX_DECREF(client->currentRequest);
   2487        PKIX_DECREF(client->currentResponse);
   2488 
   2489 cleanup:
   2490 
   2491        PKIX_DECREF(client);
   2492 
   2493        PKIX_RETURN(CERTSTORE);
   2494 }