| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| /* |
| * pkix_pl_ldapdefaultclient.c |
| * |
| * LDAPDefaultClient Function Definitions |
| * |
| */ |
| |
| /* We can't decode the length of a message without at least this many bytes */ |
| #define MINIMUM_MSG_LENGTH 5 |
| |
| #include "pkix_pl_ldapdefaultclient.h" |
| |
| /* --Private-LdapDefaultClient-Message-Building-Functions---------------- */ |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_MakeBind |
| * DESCRIPTION: |
| * |
| * This function creates and encodes a Bind message, using the arena pointed |
| * to by "arena", the version number contained in "versionData", the |
| * LDAPBindAPI pointed to by "bindAPI", and the messageID contained in |
| * "msgNum", and stores a pointer to the encoded string at "pBindMsg". |
| * |
| * See pkix_pl_ldaptemplates.c for the ASN.1 description of a Bind message. |
| * |
| * This code is not used if the DefaultClient was created with a NULL pointer |
| * supplied for the LDAPBindAPI structure. (Bind and Unbind do not seem to be |
| * expected for anonymous Search requests.) |
| * |
| * PARAMETERS: |
| * "arena" |
| * The address of the PLArenaPool used in encoding the message. Must be |
| * non-NULL. |
| * "versionData" |
| * The Int32 containing the version number to be encoded in the Bind |
| * message. |
| * "bindAPI" |
| * The address of the LDAPBindAPI to be encoded in the Bind message. Must |
| * be non-NULL. |
| * "msgNum" |
| * The Int32 containing the MessageID to be encoded in the Bind message. |
| * "pBindMsg" |
| * The address at which the encoded Bind message will be stored. Must be |
| * non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_MakeBind( |
| PLArenaPool *arena, |
| PKIX_Int32 versionData, |
| LDAPBindAPI *bindAPI, |
| PKIX_UInt32 msgNum, |
| SECItem **pBindMsg, |
| void *plContext) |
| { |
| LDAPMessage msg; |
| char version = '\0'; |
| SECItem *encoded = NULL; |
| PKIX_UInt32 len = 0; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeBind"); |
| PKIX_NULLCHECK_TWO(arena, pBindMsg); |
| |
| PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset, |
| (&msg, 0, sizeof (LDAPMessage))); |
| |
| version = (char)versionData; |
| |
| msg.messageID.type = siUnsignedInteger; |
| msg.messageID.data = (void*)&msgNum; |
| msg.messageID.len = sizeof (msgNum); |
| |
| msg.protocolOp.selector = LDAP_BIND_TYPE; |
| |
| msg.protocolOp.op.bindMsg.version.type = siUnsignedInteger; |
| msg.protocolOp.op.bindMsg.version.data = (void *)&version; |
| msg.protocolOp.op.bindMsg.version.len = sizeof (char); |
| |
| /* |
| * XXX At present we only know how to handle anonymous requests (no |
| * authentication), and we are guessing how to do simple authentication. |
| * This section will need to be revised and extended when other |
| * authentication is needed. |
| */ |
| if (bindAPI->selector == SIMPLE_AUTH) { |
| msg.protocolOp.op.bindMsg.bindName.type = siAsciiString; |
| msg.protocolOp.op.bindMsg.bindName.data = |
| (void *)bindAPI->chooser.simple.bindName; |
| len = PL_strlen(bindAPI->chooser.simple.bindName); |
| msg.protocolOp.op.bindMsg.bindName.len = len; |
| |
| msg.protocolOp.op.bindMsg.authentication.type = siAsciiString; |
| msg.protocolOp.op.bindMsg.authentication.data = |
| (void *)bindAPI->chooser.simple.authentication; |
| len = PL_strlen(bindAPI->chooser.simple.authentication); |
| msg.protocolOp.op.bindMsg.authentication.len = len; |
| } |
| |
| PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem, |
| (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate)); |
| if (!encoded) { |
| PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); |
| } |
| |
| *pBindMsg = encoded; |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_MakeUnbind |
| * DESCRIPTION: |
| * |
| * This function creates and encodes a Unbind message, using the arena pointed |
| * to by "arena" and the messageID contained in "msgNum", and stores a pointer |
| * to the encoded string at "pUnbindMsg". |
| * |
| * See pkix_pl_ldaptemplates.c for the ASN.1 description of an Unbind message. |
| * |
| * This code is not used if the DefaultClient was created with a NULL pointer |
| * supplied for the LDAPBindAPI structure. (Bind and Unbind do not seem to be |
| * expected for anonymous Search requests.) |
| * |
| * PARAMETERS: |
| * "arena" |
| * The address of the PLArenaPool used in encoding the message. Must be |
| * non-NULL. |
| * "msgNum" |
| * The Int32 containing the MessageID to be encoded in the Unbind message. |
| * "pUnbindMsg" |
| * The address at which the encoded Unbind message will be stored. Must |
| * be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_MakeUnbind( |
| PLArenaPool *arena, |
| PKIX_UInt32 msgNum, |
| SECItem **pUnbindMsg, |
| void *plContext) |
| { |
| LDAPMessage msg; |
| SECItem *encoded = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeUnbind"); |
| PKIX_NULLCHECK_TWO(arena, pUnbindMsg); |
| |
| PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset, |
| (&msg, 0, sizeof (LDAPMessage))); |
| |
| msg.messageID.type = siUnsignedInteger; |
| msg.messageID.data = (void*)&msgNum; |
| msg.messageID.len = sizeof (msgNum); |
| |
| msg.protocolOp.selector = LDAP_UNBIND_TYPE; |
| |
| msg.protocolOp.op.unbindMsg.dummy.type = siBuffer; |
| msg.protocolOp.op.unbindMsg.dummy.data = NULL; |
| msg.protocolOp.op.unbindMsg.dummy.len = 0; |
| |
| PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem, |
| (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate)); |
| if (!encoded) { |
| PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); |
| } |
| |
| *pUnbindMsg = encoded; |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_MakeAbandon |
| * DESCRIPTION: |
| * |
| * This function creates and encodes a Abandon message, using the arena pointed |
| * to by "arena" and the messageID contained in "msgNum", and stores a pointer |
| * to the encoded string at "pAbandonMsg". |
| * |
| * See pkix_pl_ldaptemplates.c for the ASN.1 description of an Abandon message. |
| * |
| * PARAMETERS: |
| * "arena" |
| * The address of the PLArenaPool used in encoding the message. Must be |
| * non-NULL. |
| * "msgNum" |
| * The Int32 containing the MessageID to be encoded in the Abandon message. |
| * "pAbandonMsg" |
| * The address at which the encoded Abandon message will be stored. Must |
| * be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_MakeAbandon( |
| PLArenaPool *arena, |
| PKIX_UInt32 msgNum, |
| SECItem **pAbandonMsg, |
| void *plContext) |
| { |
| LDAPMessage msg; |
| SECItem *encoded = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_MakeAbandon"); |
| PKIX_NULLCHECK_TWO(arena, pAbandonMsg); |
| |
| PKIX_PL_NSSCALL(LDAPDEFAULTCLIENT, PORT_Memset, |
| (&msg, 0, sizeof (LDAPMessage))); |
| |
| msg.messageID.type = siUnsignedInteger; |
| msg.messageID.data = (void*)&msgNum; |
| msg.messageID.len = sizeof (msgNum); |
| |
| msg.protocolOp.selector = LDAP_ABANDONREQUEST_TYPE; |
| |
| msg.protocolOp.op.abandonRequestMsg.messageID.type = siBuffer; |
| msg.protocolOp.op.abandonRequestMsg.messageID.data = (void*)&msgNum; |
| msg.protocolOp.op.abandonRequestMsg.messageID.len = sizeof (msgNum); |
| |
| PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, encoded, SEC_ASN1EncodeItem, |
| (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate)); |
| if (!encoded) { |
| PKIX_ERROR(PKIX_SECASN1ENCODEITEMFAILED); |
| } |
| |
| *pAbandonMsg = encoded; |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_DecodeBindResponse |
| * DESCRIPTION: |
| * |
| * This function decodes the encoded data pointed to by "src", using the arena |
| * pointed to by "arena", storing the decoded LDAPMessage at "pBindResponse" |
| * and the decoding status at "pStatus". |
| * |
| * PARAMETERS: |
| * "arena" |
| * The address of the PLArenaPool to be used in decoding the message. Must |
| * be non-NULL. |
| * "src" |
| * The address of the SECItem containing the DER- (or BER-)encoded string. |
| * Must be non-NULL. |
| * "pBindResponse" |
| * The address at which the LDAPMessage is stored, if the decoding is |
| * successful (the returned status is SECSuccess). Must be non-NULL. |
| * "pStatus" |
| * The address at which the decoding status is stored. Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_DecodeBindResponse( |
| PLArenaPool *arena, |
| SECItem *src, |
| LDAPMessage *pBindResponse, |
| SECStatus *pStatus, |
| void *plContext) |
| { |
| SECStatus rv = SECFailure; |
| LDAPMessage response; |
| |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, |
| "pkix_pl_LdapDefaultClient_DecodeBindResponse"); |
| PKIX_NULLCHECK_FOUR(arena, src, pBindResponse, pStatus); |
| |
| PKIX_PL_NSSCALL |
| (LDAPDEFAULTCLIENT, |
| PORT_Memset, |
| (&response, 0, sizeof (LDAPMessage))); |
| |
| PKIX_PL_NSSCALLRV(LDAPDEFAULTCLIENT, rv, SEC_ASN1DecodeItem, |
| (arena, &response, PKIX_PL_LDAPMessageTemplate, src)); |
| |
| if (rv == SECSuccess) { |
| *pBindResponse = response; |
| } |
| |
| *pStatus = rv; |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_VerifyBindResponse |
| * DESCRIPTION: |
| * |
| * This function verifies that the contents of the message in the rcvbuf of |
| * the LdapDefaultClient object pointed to by "client", and whose length is |
| * provided by "buflen", is a response to a successful Bind. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "buflen" |
| * The value of the number of bytes in the receive buffer. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_VerifyBindResponse( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_UInt32 bufLen, |
| void *plContext) |
| { |
| SECItem decode = {siBuffer, NULL, 0}; |
| SECStatus rv = SECFailure; |
| LDAPMessage msg; |
| LDAPBindResponse *ldapBindResponse = &msg.protocolOp.op.bindResponseMsg; |
| |
| ldapBindResponse->resultCode.data = NULL; |
| |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, |
| "pkix_pl_LdapDefaultClient_VerifyBindResponse"); |
| PKIX_NULLCHECK_TWO(client, client->rcvBuf); |
| |
| decode.data = (unsigned char *)(client->rcvBuf); |
| decode.len = bufLen; |
| |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_DecodeBindResponse |
| (client->arena, &decode, &msg, &rv, plContext), |
| PKIX_LDAPDEFAULTCLIENTDECODEBINDRESPONSEFAILED); |
| |
| if (rv == SECSuccess) { |
| if (*(ldapBindResponse->resultCode.data) == SUCCESS) { |
| client->connectStatus = BOUND; |
| } else { |
| PKIX_ERROR(PKIX_BINDREJECTEDBYSERVER); |
| } |
| } else { |
| PKIX_ERROR(PKIX_CANTDECODEBINDRESPONSEFROMSERVER); |
| } |
| |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_RecvCheckComplete |
| * DESCRIPTION: |
| * |
| * This function determines whether the current response in the |
| * LdapDefaultClient pointed to by "client" is complete, in the sense that all |
| * bytes required to satisfy the message length field in the encoding have been |
| * received. If so, the pointer to input data is updated to reflect the number |
| * of bytes consumed, provided by "bytesProcessed". The state machine flag |
| * pointed to by "pKeepGoing" is updated to indicate whether processing can |
| * continue without further input. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "bytesProcessed" |
| * The UInt32 value of the number of bytes consumed from the current |
| * buffer. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_RecvCheckComplete( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_UInt32 bytesProcessed, |
| PKIX_Boolean *pKeepGoing, |
| void *plContext) |
| { |
| PKIX_Boolean complete = PKIX_FALSE; |
| SECStatus rv = SECFailure; |
| LDAPMessageType messageType = 0; |
| LDAPResultCode resultCode = 0; |
| |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, |
| "pkix_pl_LdapDefaultClient_RecvCheckComplete"); |
| PKIX_NULLCHECK_TWO(client, pKeepGoing); |
| |
| PKIX_CHECK(pkix_pl_LdapResponse_IsComplete |
| (client->currentResponse, &complete, plContext), |
| PKIX_LDAPRESPONSEISCOMPLETEFAILED); |
| |
| if (complete) { |
| PKIX_CHECK(pkix_pl_LdapResponse_Decode |
| (client->arena, client->currentResponse, &rv, plContext), |
| PKIX_LDAPRESPONSEDECODEFAILED); |
| |
| if (rv != SECSuccess) { |
| PKIX_ERROR(PKIX_CANTDECODESEARCHRESPONSEFROMSERVER); |
| } |
| |
| PKIX_CHECK(pkix_pl_LdapResponse_GetMessageType |
| (client->currentResponse, &messageType, plContext), |
| PKIX_LDAPRESPONSEGETMESSAGETYPEFAILED); |
| |
| if (messageType == LDAP_SEARCHRESPONSEENTRY_TYPE) { |
| |
| if (client->entriesFound == NULL) { |
| PKIX_CHECK(PKIX_List_Create |
| (&(client->entriesFound), plContext), |
| PKIX_LISTCREATEFAILED); |
| } |
| |
| PKIX_CHECK(PKIX_List_AppendItem |
| (client->entriesFound, |
| (PKIX_PL_Object *)client->currentResponse, |
| plContext), |
| PKIX_LISTAPPENDITEMFAILED); |
| |
| PKIX_DECREF(client->currentResponse); |
| |
| /* current receive buffer empty? */ |
| if (client->currentBytesAvailable == 0) { |
| client->connectStatus = RECV; |
| *pKeepGoing = PKIX_TRUE; |
| } else { |
| client->connectStatus = RECV_INITIAL; |
| client->currentInPtr = &((char *) |
| (client->currentInPtr))[bytesProcessed]; |
| *pKeepGoing = PKIX_TRUE; |
| } |
| |
| } else if (messageType == LDAP_SEARCHRESPONSERESULT_TYPE) { |
| PKIX_CHECK(pkix_pl_LdapResponse_GetResultCode |
| (client->currentResponse, |
| &resultCode, |
| plContext), |
| PKIX_LDAPRESPONSEGETRESULTCODEFAILED); |
| |
| if ((client->entriesFound == NULL) && |
| ((resultCode == SUCCESS) || |
| (resultCode == NOSUCHOBJECT))) { |
| PKIX_CHECK(PKIX_List_Create |
| (&(client->entriesFound), plContext), |
| PKIX_LISTCREATEFAILED); |
| } else if (resultCode == SUCCESS) { |
| PKIX_CHECK(PKIX_List_SetImmutable |
| (client->entriesFound, plContext), |
| PKIX_LISTSETIMMUTABLEFAILED); |
| PKIX_CHECK(PKIX_PL_HashTable_Add |
| (client->cachePtr, |
| (PKIX_PL_Object *)client->currentRequest, |
| (PKIX_PL_Object *)client->entriesFound, |
| plContext), |
| PKIX_HASHTABLEADDFAILED); |
| } else { |
| PKIX_ERROR(PKIX_UNEXPECTEDRESULTCODEINRESPONSE); |
| } |
| |
| client->connectStatus = BOUND; |
| *pKeepGoing = PKIX_FALSE; |
| PKIX_DECREF(client->currentResponse); |
| |
| } else { |
| PKIX_ERROR(PKIX_SEARCHRESPONSEPACKETOFUNKNOWNTYPE); |
| } |
| } else { |
| client->connectStatus = RECV; |
| *pKeepGoing = PKIX_TRUE; |
| } |
| |
| cleanup: |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* --Private-LdapDefaultClient-Object-Functions------------------------- */ |
| |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_InitiateRequest( |
| PKIX_PL_LdapClient *client, |
| LDAPRequestParams *requestParams, |
| void **pPollDesc, |
| PKIX_List **pResponse, |
| void *plContext); |
| |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_ResumeRequest( |
| PKIX_PL_LdapClient *client, |
| void **pPollDesc, |
| PKIX_List **pResponse, |
| void *plContext); |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_CreateHelper |
| * DESCRIPTION: |
| * |
| * This function creates a new LdapDefaultClient using the Socket pointed to |
| * by "socket", the PRIntervalTime pointed to by "timeout", and the |
| * LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient". |
| * |
| * A value of zero for "timeout" means the LDAPClient will use non-blocking |
| * I/O. |
| * |
| * PARAMETERS: |
| * "socket" |
| * Address of the Socket to be used for the client. Must be non-NULL. |
| * "bindAPI" |
| * The address of the LDAPBindAPI containing the Bind information to be |
| * encoded in the Bind message. |
| * "pClient" |
| * The address at which the created LdapDefaultClient is to be stored. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in |
| * a non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| PKIX_Error * |
| pkix_pl_LdapDefaultClient_CreateHelper( |
| PKIX_PL_Socket *socket, |
| LDAPBindAPI *bindAPI, |
| PKIX_PL_LdapDefaultClient **pClient, |
| void *plContext) |
| { |
| PKIX_PL_HashTable *ht; |
| PKIX_PL_LdapDefaultClient *ldapDefaultClient = NULL; |
| PKIX_PL_Socket_Callback *callbackList; |
| PRFileDesc *fileDesc = NULL; |
| PLArenaPool *arena = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_CreateHelper"); |
| PKIX_NULLCHECK_TWO(socket, pClient); |
| |
| PKIX_CHECK(PKIX_PL_Object_Alloc |
| (PKIX_LDAPDEFAULTCLIENT_TYPE, |
| sizeof (PKIX_PL_LdapDefaultClient), |
| (PKIX_PL_Object **)&ldapDefaultClient, |
| plContext), |
| PKIX_COULDNOTCREATELDAPDEFAULTCLIENTOBJECT); |
| |
| ldapDefaultClient->vtable.initiateFcn = |
| pkix_pl_LdapDefaultClient_InitiateRequest; |
| ldapDefaultClient->vtable.resumeFcn = |
| pkix_pl_LdapDefaultClient_ResumeRequest; |
| |
| PKIX_CHECK(pkix_pl_Socket_GetPRFileDesc |
| (socket, &fileDesc, plContext), |
| PKIX_SOCKETGETPRFILEDESCFAILED); |
| |
| ldapDefaultClient->pollDesc.fd = fileDesc; |
| ldapDefaultClient->pollDesc.in_flags = 0; |
| ldapDefaultClient->pollDesc.out_flags = 0; |
| |
| ldapDefaultClient->bindAPI = bindAPI; |
| |
| PKIX_CHECK(PKIX_PL_HashTable_Create |
| (LDAP_CACHEBUCKETS, 0, &ht, plContext), |
| PKIX_HASHTABLECREATEFAILED); |
| |
| ldapDefaultClient->cachePtr = ht; |
| |
| PKIX_CHECK(pkix_pl_Socket_GetCallbackList |
| (socket, &callbackList, plContext), |
| PKIX_SOCKETGETCALLBACKLISTFAILED); |
| |
| ldapDefaultClient->callbackList = callbackList; |
| |
| PKIX_INCREF(socket); |
| ldapDefaultClient->clientSocket = socket; |
| |
| ldapDefaultClient->messageID = 0; |
| |
| ldapDefaultClient->bindAPI = bindAPI; |
| |
| arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
| if (!arena) { |
| PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY); |
| } |
| ldapDefaultClient->arena = arena; |
| |
| ldapDefaultClient->sendBuf = NULL; |
| ldapDefaultClient->bytesToWrite = 0; |
| |
| PKIX_CHECK(PKIX_PL_Malloc |
| (RCVBUFSIZE, &ldapDefaultClient->rcvBuf, plContext), |
| PKIX_MALLOCFAILED); |
| ldapDefaultClient->capacity = RCVBUFSIZE; |
| |
| ldapDefaultClient->bindMsg = NULL; |
| ldapDefaultClient->bindMsgLen = 0; |
| |
| ldapDefaultClient->entriesFound = NULL; |
| ldapDefaultClient->currentRequest = NULL; |
| ldapDefaultClient->currentResponse = NULL; |
| |
| *pClient = ldapDefaultClient; |
| |
| cleanup: |
| |
| if (PKIX_ERROR_RECEIVED) { |
| PKIX_DECREF(ldapDefaultClient); |
| } |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: PKIX_PL_LdapDefaultClient_Create |
| * DESCRIPTION: |
| * |
| * This function creates a new LdapDefaultClient using the PRNetAddr pointed to |
| * by "sockaddr", the PRIntervalTime pointed to by "timeout", and the |
| * LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient". |
| * |
| * A value of zero for "timeout" means the LDAPClient will use non-blocking |
| * I/O. |
| * |
| * PARAMETERS: |
| * "sockaddr" |
| * Address of the PRNetAddr to be used for the socket connection. Must be |
| * non-NULL. |
| * "timeout" |
| * The PRIntervalTime to be used in I/O requests for this client. |
| * "bindAPI" |
| * The address of the LDAPBindAPI containing the Bind information to be |
| * encoded in the Bind message. |
| * "pClient" |
| * The address at which the created LdapDefaultClient is to be stored. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in |
| * a non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| PKIX_Error * |
| PKIX_PL_LdapDefaultClient_Create( |
| PRNetAddr *sockaddr, |
| PRIntervalTime timeout, |
| LDAPBindAPI *bindAPI, |
| PKIX_PL_LdapDefaultClient **pClient, |
| void *plContext) |
| { |
| PRErrorCode status = 0; |
| PKIX_PL_Socket *socket = NULL; |
| PKIX_PL_LdapDefaultClient *client = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "PKIX_PL_LdapDefaultClient_Create"); |
| PKIX_NULLCHECK_TWO(sockaddr, pClient); |
| |
| PKIX_CHECK(pkix_pl_Socket_Create |
| (PKIX_FALSE, timeout, sockaddr, &status, &socket, plContext), |
| PKIX_SOCKETCREATEFAILED); |
| |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_CreateHelper |
| (socket, bindAPI, &client, plContext), |
| PKIX_LDAPDEFAULTCLIENTCREATEHELPERFAILED); |
| |
| /* Did Socket_Create say the connection was made? */ |
| if (status == 0) { |
| if (client->bindAPI != NULL) { |
| client->connectStatus = CONNECTED; |
| } else { |
| client->connectStatus = BOUND; |
| } |
| } else { |
| client->connectStatus = CONNECT_PENDING; |
| } |
| |
| *pClient = client; |
| |
| cleanup: |
| if (PKIX_ERROR_RECEIVED) { |
| PKIX_DECREF(client); |
| } |
| |
| PKIX_DECREF(socket); |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: PKIX_PL_LdapDefaultClient_CreateByName |
| * DESCRIPTION: |
| * |
| * This function creates a new LdapDefaultClient using the hostname pointed to |
| * by "hostname", the PRIntervalTime pointed to by "timeout", and the |
| * LDAPBindAPI pointed to by "bindAPI", and stores the result at "pClient". |
| * |
| * A value of zero for "timeout" means the LDAPClient will use non-blocking |
| * I/O. |
| * |
| * PARAMETERS: |
| * "hostname" |
| * Address of the hostname to be used for the socket connection. Must be |
| * non-NULL. |
| * "timeout" |
| * The PRIntervalTime to be used in I/O requests for this client. |
| * "bindAPI" |
| * The address of the LDAPBindAPI containing the Bind information to be |
| * encoded in the Bind message. |
| * "pClient" |
| * The address at which the created LdapDefaultClient is to be stored. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in |
| * a non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| PKIX_Error * |
| PKIX_PL_LdapDefaultClient_CreateByName( |
| char *hostname, |
| PRIntervalTime timeout, |
| LDAPBindAPI *bindAPI, |
| PKIX_PL_LdapDefaultClient **pClient, |
| void *plContext) |
| { |
| PRErrorCode status = 0; |
| PKIX_PL_Socket *socket = NULL; |
| PKIX_PL_LdapDefaultClient *client = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "PKIX_PL_LdapDefaultClient_CreateByName"); |
| PKIX_NULLCHECK_TWO(hostname, pClient); |
| |
| PKIX_CHECK(pkix_pl_Socket_CreateByName |
| (PKIX_FALSE, timeout, hostname, &status, &socket, plContext), |
| PKIX_SOCKETCREATEBYNAMEFAILED); |
| |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_CreateHelper |
| (socket, bindAPI, &client, plContext), |
| PKIX_LDAPDEFAULTCLIENTCREATEHELPERFAILED); |
| |
| /* Did Socket_Create say the connection was made? */ |
| if (status == 0) { |
| if (client->bindAPI != NULL) { |
| client->connectStatus = CONNECTED; |
| } else { |
| client->connectStatus = BOUND; |
| } |
| } else { |
| client->connectStatus = CONNECT_PENDING; |
| } |
| |
| *pClient = client; |
| |
| cleanup: |
| if (PKIX_ERROR_RECEIVED) { |
| PKIX_DECREF(client); |
| } |
| |
| PKIX_DECREF(socket); |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_Destroy |
| * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_Destroy( |
| PKIX_PL_Object *object, |
| void *plContext) |
| { |
| PKIX_Int32 bytesWritten = 0; |
| PKIX_PL_LdapDefaultClient *client = NULL; |
| PKIX_PL_Socket_Callback *callbackList = NULL; |
| SECItem *encoded = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, |
| "pkix_pl_LdapDefaultClient_Destroy"); |
| PKIX_NULLCHECK_ONE(object); |
| |
| PKIX_CHECK(pkix_CheckType |
| (object, PKIX_LDAPDEFAULTCLIENT_TYPE, plContext), |
| PKIX_OBJECTNOTANLDAPDEFAULTCLIENT); |
| |
| client = (PKIX_PL_LdapDefaultClient *)object; |
| |
| switch (client->connectStatus) { |
| case CONNECT_PENDING: |
| break; |
| case CONNECTED: |
| case BIND_PENDING: |
| case BIND_RESPONSE: |
| case BIND_RESPONSE_PENDING: |
| case BOUND: |
| case SEND_PENDING: |
| case RECV: |
| case RECV_PENDING: |
| case RECV_INITIAL: |
| case RECV_NONINITIAL: |
| case ABANDON_PENDING: |
| if (client->bindAPI != NULL) { |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeUnbind |
| (client->arena, |
| ++(client->messageID), |
| &encoded, |
| plContext), |
| PKIX_LDAPDEFAULTCLIENTMAKEUNBINDFAILED); |
| |
| callbackList = |
| (PKIX_PL_Socket_Callback *)(client->callbackList); |
| PKIX_CHECK(callbackList->sendCallback |
| (client->clientSocket, |
| encoded->data, |
| encoded->len, |
| &bytesWritten, |
| plContext), |
| PKIX_SOCKETSENDFAILED); |
| } |
| break; |
| default: |
| PKIX_ERROR(PKIX_LDAPDEFAULTCLIENTINILLEGALSTATE); |
| } |
| |
| PKIX_DECREF(client->cachePtr); |
| PKIX_DECREF(client->clientSocket); |
| PKIX_DECREF(client->entriesFound); |
| PKIX_DECREF(client->currentRequest); |
| PKIX_DECREF(client->currentResponse); |
| |
| PKIX_CHECK(PKIX_PL_Free |
| (client->rcvBuf, plContext), PKIX_FREEFAILED); |
| |
| PKIX_PL_NSSCALL |
| (LDAPDEFAULTCLIENT, |
| PORT_FreeArena, |
| (client->arena, PR_FALSE)); |
| |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_Hashcode |
| * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_Hashcode( |
| PKIX_PL_Object *object, |
| PKIX_UInt32 *pHashcode, |
| void *plContext) |
| { |
| PKIX_PL_LdapDefaultClient *ldapDefaultClient = NULL; |
| PKIX_UInt32 tempHash = 0; |
| |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Hashcode"); |
| PKIX_NULLCHECK_TWO(object, pHashcode); |
| |
| PKIX_CHECK(pkix_CheckType |
| (object, PKIX_LDAPDEFAULTCLIENT_TYPE, plContext), |
| PKIX_OBJECTNOTANLDAPDEFAULTCLIENT); |
| |
| ldapDefaultClient = (PKIX_PL_LdapDefaultClient *)object; |
| |
| PKIX_CHECK(PKIX_PL_Object_Hashcode |
| ((PKIX_PL_Object *)ldapDefaultClient->clientSocket, |
| &tempHash, |
| plContext), |
| PKIX_SOCKETHASHCODEFAILED); |
| |
| if (ldapDefaultClient->bindAPI != NULL) { |
| tempHash = (tempHash << 7) + |
| ldapDefaultClient->bindAPI->selector; |
| } |
| |
| *pHashcode = tempHash; |
| |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_Equals |
| * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h) |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_Equals( |
| PKIX_PL_Object *firstObject, |
| PKIX_PL_Object *secondObject, |
| PKIX_Int32 *pResult, |
| void *plContext) |
| { |
| PKIX_PL_LdapDefaultClient *firstClientContext = NULL; |
| PKIX_PL_LdapDefaultClient *secondClientContext = NULL; |
| PKIX_Int32 compare = 0; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Equals"); |
| PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); |
| |
| *pResult = PKIX_FALSE; |
| |
| PKIX_CHECK(pkix_CheckTypes |
| (firstObject, |
| secondObject, |
| PKIX_LDAPDEFAULTCLIENT_TYPE, |
| plContext), |
| PKIX_OBJECTNOTANLDAPDEFAULTCLIENT); |
| |
| firstClientContext = (PKIX_PL_LdapDefaultClient *)firstObject; |
| secondClientContext = (PKIX_PL_LdapDefaultClient *)secondObject; |
| |
| if (firstClientContext == secondClientContext) { |
| *pResult = PKIX_TRUE; |
| goto cleanup; |
| } |
| |
| PKIX_CHECK(PKIX_PL_Object_Equals |
| ((PKIX_PL_Object *)firstClientContext->clientSocket, |
| (PKIX_PL_Object *)secondClientContext->clientSocket, |
| &compare, |
| plContext), |
| PKIX_SOCKETEQUALSFAILED); |
| |
| if (!compare) { |
| goto cleanup; |
| } |
| |
| if (PKIX_EXACTLY_ONE_NULL |
| (firstClientContext->bindAPI, secondClientContext->bindAPI)) { |
| goto cleanup; |
| } |
| |
| if (firstClientContext->bindAPI) { |
| if (firstClientContext->bindAPI->selector != |
| secondClientContext->bindAPI->selector) { |
| goto cleanup; |
| } |
| } |
| |
| *pResult = PKIX_TRUE; |
| |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_RegisterSelf |
| * |
| * DESCRIPTION: |
| * Registers PKIX_PL_LDAPDEFAULTCLIENT_TYPE and its related |
| * functions with systemClasses[] |
| * |
| * THREAD SAFETY: |
| * Not Thread Safe - for performance and complexity reasons |
| * |
| * Since this function is only called by PKIX_PL_Initialize, which should |
| * only be called once, it is acceptable that this function is not |
| * thread-safe. |
| */ |
| PKIX_Error * |
| pkix_pl_LdapDefaultClient_RegisterSelf(void *plContext) |
| { |
| extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; |
| pkix_ClassTable_Entry entry; |
| |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, |
| "pkix_pl_LdapDefaultClient_RegisterSelf"); |
| |
| entry.description = "LdapDefaultClient"; |
| entry.objCounter = 0; |
| entry.typeObjectSize = sizeof(PKIX_PL_LdapDefaultClient); |
| entry.destructor = pkix_pl_LdapDefaultClient_Destroy; |
| entry.equalsFunction = pkix_pl_LdapDefaultClient_Equals; |
| entry.hashcodeFunction = pkix_pl_LdapDefaultClient_Hashcode; |
| entry.toStringFunction = NULL; |
| entry.comparator = NULL; |
| entry.duplicateFunction = NULL; |
| |
| systemClasses[PKIX_LDAPDEFAULTCLIENT_TYPE] = entry; |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_GetPollDesc |
| * DESCRIPTION: |
| * |
| * This function retrieves the PRPollDesc from the LdapDefaultClient |
| * pointed to by "context" and stores the address at "pPollDesc". |
| * |
| * PARAMETERS: |
| * "context" |
| * The LdapDefaultClient whose PRPollDesc is desired. Must be non-NULL. |
| * "pPollDesc" |
| * Address where PRPollDesc will be stored. Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| PKIX_Error * |
| pkix_pl_LdapDefaultClient_GetPollDesc( |
| PKIX_PL_LdapDefaultClient *context, |
| PRPollDesc **pPollDesc, |
| void *plContext) |
| { |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, |
| "pkix_pl_LdapDefaultClient_GetPollDesc"); |
| PKIX_NULLCHECK_TWO(context, pPollDesc); |
| |
| *pPollDesc = &(context->pollDesc); |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* --Private-Ldap-CertStore-I/O-Functions---------------------------- */ |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_ConnectContinue |
| * DESCRIPTION: |
| * |
| * This function determines whether a socket Connect initiated earlier for the |
| * CertStore embodied in the LdapDefaultClient "client" has completed, and |
| * stores in "pKeepGoing" a flag indicating whether processing can continue |
| * without further input. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_ConnectContinue( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| void *plContext) |
| { |
| PKIX_PL_Socket_Callback *callbackList; |
| PRErrorCode status; |
| PKIX_Boolean keepGoing = PKIX_FALSE; |
| |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, |
| "pkix_pl_LdapDefaultClient_ConnectContinue"); |
| PKIX_NULLCHECK_ONE(client); |
| |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| |
| PKIX_CHECK(callbackList->connectcontinueCallback |
| (client->clientSocket, &status, plContext), |
| PKIX_SOCKETCONNECTCONTINUEFAILED); |
| |
| if (status == 0) { |
| if (client->bindAPI != NULL) { |
| client->connectStatus = CONNECTED; |
| } else { |
| client->connectStatus = BOUND; |
| } |
| keepGoing = PKIX_FALSE; |
| } else if (status != PR_IN_PROGRESS_ERROR) { |
| PKIX_ERROR(PKIX_UNEXPECTEDERRORINESTABLISHINGCONNECTION); |
| } |
| |
| PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
| ((PKIX_PL_Object *)client, plContext), |
| PKIX_OBJECTINVALIDATECACHEFAILED); |
| |
| *pKeepGoing = keepGoing; |
| |
| cleanup: |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_Bind |
| * DESCRIPTION: |
| * |
| * This function creates and sends the LDAP-protocol Bind message for the |
| * CertStore embodied in the LdapDefaultClient "client", and stores in |
| * "pKeepGoing" a flag indicating whether processing can continue without |
| * further input. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_Bind( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| void *plContext) |
| { |
| SECItem *encoded = NULL; |
| PKIX_Int32 bytesWritten = 0; |
| PKIX_PL_Socket_Callback *callbackList; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Bind"); |
| PKIX_NULLCHECK_ONE(client); |
| |
| /* if we have not yet constructed the BIND message, build it now */ |
| if (!(client->bindMsg)) { |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeBind |
| (client->arena, |
| 3, |
| client->bindAPI, |
| client->messageID, |
| &encoded, |
| plContext), |
| PKIX_LDAPDEFAULTCLIENTMAKEBINDFAILED); |
| client->bindMsg = encoded->data; |
| client->bindMsgLen = encoded->len; |
| } |
| |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| |
| PKIX_CHECK(callbackList->sendCallback |
| (client->clientSocket, |
| client->bindMsg, |
| client->bindMsgLen, |
| &bytesWritten, |
| plContext), |
| PKIX_SOCKETSENDFAILED); |
| |
| client->lastIO = PR_Now(); |
| |
| if (bytesWritten < 0) { |
| client->connectStatus = BIND_PENDING; |
| *pKeepGoing = PKIX_FALSE; |
| } else { |
| client->connectStatus = BIND_RESPONSE; |
| *pKeepGoing = PKIX_TRUE; |
| } |
| |
| PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
| ((PKIX_PL_Object *)client, plContext), |
| PKIX_OBJECTINVALIDATECACHEFAILED); |
| |
| cleanup: |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_BindContinue |
| * DESCRIPTION: |
| * |
| * This function determines whether the LDAP-protocol Bind message for the |
| * CertStore embodied in the LdapDefaultClient "client" has completed, and |
| * stores in "pKeepGoing" a flag indicating whether processing can continue |
| * without further input. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| PKIX_Error *pkix_pl_LdapDefaultClient_BindContinue( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| void *plContext) |
| { |
| PKIX_Int32 bytesWritten = 0; |
| PKIX_PL_Socket_Callback *callbackList = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_BindContinue"); |
| PKIX_NULLCHECK_ONE(client); |
| |
| *pKeepGoing = PKIX_FALSE; |
| |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| |
| PKIX_CHECK(callbackList->pollCallback |
| (client->clientSocket, &bytesWritten, NULL, plContext), |
| PKIX_SOCKETPOLLFAILED); |
| |
| /* |
| * If the send completed we can proceed to try for the |
| * response. If the send did not complete we will have |
| * continue to poll. |
| */ |
| if (bytesWritten >= 0) { |
| |
| client->connectStatus = BIND_RESPONSE; |
| |
| PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
| ((PKIX_PL_Object *)client, plContext), |
| PKIX_OBJECTINVALIDATECACHEFAILED); |
| |
| *pKeepGoing = PKIX_TRUE; |
| } |
| |
| cleanup: |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_BindResponse |
| * DESCRIPTION: |
| * |
| * This function attempts to read the LDAP-protocol BindResponse message for |
| * the CertStore embodied in the LdapDefaultClient "client", and stores in |
| * "pKeepGoing" a flag indicating whether processing can continue without |
| * further input. |
| * |
| * If a BindResponse is received with a Result code of 0 (success), we |
| * continue with the connection. If a non-zero Result code is received, |
| * we throw an Error. Some more sophisticated handling of that condition |
| * might be in order in the future. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_BindResponse( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| void *plContext) |
| { |
| PKIX_Int32 bytesRead = 0; |
| PKIX_PL_Socket_Callback *callbackList = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_BindResponse"); |
| PKIX_NULLCHECK_TWO(client, client->rcvBuf); |
| |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| |
| PKIX_CHECK(callbackList->recvCallback |
| (client->clientSocket, |
| client->rcvBuf, |
| client->capacity, |
| &bytesRead, |
| plContext), |
| PKIX_SOCKETRECVFAILED); |
| |
| client->lastIO = PR_Now(); |
| |
| if (bytesRead > 0) { |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_VerifyBindResponse |
| (client, bytesRead, plContext), |
| PKIX_LDAPDEFAULTCLIENTVERIFYBINDRESPONSEFAILED); |
| /* |
| * XXX What should we do if failure? At present if |
| * VerifyBindResponse throws an Error, we do too. |
| */ |
| client->connectStatus = BOUND; |
| } else { |
| client->connectStatus = BIND_RESPONSE_PENDING; |
| } |
| |
| PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
| ((PKIX_PL_Object *)client, plContext), |
| PKIX_OBJECTINVALIDATECACHEFAILED); |
| |
| *pKeepGoing = PKIX_TRUE; |
| |
| cleanup: |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_BindResponseContinue |
| * DESCRIPTION: |
| * |
| * This function determines whether the LDAP-protocol BindResponse message for |
| * the CertStore embodied in the LdapDefaultClient "client" has completed, and |
| * stores in "pKeepGoing" a flag indicating whether processing can continue |
| * without further input. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_BindResponseContinue( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| void *plContext) |
| { |
| PKIX_Int32 bytesRead = 0; |
| PKIX_PL_Socket_Callback *callbackList = NULL; |
| |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, |
| "pkix_pl_LdapDefaultClient_BindResponseContinue"); |
| PKIX_NULLCHECK_ONE(client); |
| |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| |
| PKIX_CHECK(callbackList->pollCallback |
| (client->clientSocket, NULL, &bytesRead, plContext), |
| PKIX_SOCKETPOLLFAILED); |
| |
| if (bytesRead > 0) { |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_VerifyBindResponse |
| (client, bytesRead, plContext), |
| PKIX_LDAPDEFAULTCLIENTVERIFYBINDRESPONSEFAILED); |
| client->connectStatus = BOUND; |
| |
| PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
| ((PKIX_PL_Object *)client, plContext), |
| PKIX_OBJECTINVALIDATECACHEFAILED); |
| |
| *pKeepGoing = PKIX_TRUE; |
| } else { |
| *pKeepGoing = PKIX_FALSE; |
| } |
| |
| cleanup: |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_Send |
| * DESCRIPTION: |
| * |
| * This function creates and sends an LDAP-protocol message for the |
| * CertStore embodied in the LdapDefaultClient "client", and stores in |
| * "pKeepGoing" a flag indicating whether processing can continue without |
| * further input, and at "pBytesTransferred" the number of bytes sent. |
| * |
| * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use |
| * and that transmission has not completed. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "pBytesTransferred" |
| * The address at which the number of bytes sent is stored. Must be |
| * non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_Send( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| PKIX_UInt32 *pBytesTransferred, |
| void *plContext) |
| { |
| PKIX_Int32 bytesWritten = 0; |
| PKIX_PL_Socket_Callback *callbackList = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Send"); |
| PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred); |
| |
| *pKeepGoing = PKIX_FALSE; |
| |
| /* Do we have anything waiting to go? */ |
| if (client->sendBuf) { |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| |
| PKIX_CHECK(callbackList->sendCallback |
| (client->clientSocket, |
| client->sendBuf, |
| client->bytesToWrite, |
| &bytesWritten, |
| plContext), |
| PKIX_SOCKETSENDFAILED); |
| |
| client->lastIO = PR_Now(); |
| |
| /* |
| * If the send completed we can proceed to try for the |
| * response. If the send did not complete we will have |
| * to poll for completion later. |
| */ |
| if (bytesWritten >= 0) { |
| client->sendBuf = NULL; |
| client->connectStatus = RECV; |
| *pKeepGoing = PKIX_TRUE; |
| |
| } else { |
| *pKeepGoing = PKIX_FALSE; |
| client->connectStatus = SEND_PENDING; |
| } |
| |
| } |
| |
| PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
| ((PKIX_PL_Object *)client, plContext), |
| PKIX_OBJECTINVALIDATECACHEFAILED); |
| |
| *pBytesTransferred = bytesWritten; |
| |
| cleanup: |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_SendContinue |
| * DESCRIPTION: |
| * |
| * This function determines whether the sending of the LDAP-protocol message |
| * for the CertStore embodied in the LdapDefaultClient "client" has completed, |
| * and stores in "pKeepGoing" a flag indicating whether processing can continue |
| * without further input, and at "pBytesTransferred" the number of bytes sent. |
| * |
| * If "pBytesTransferred" is zero, it indicates that non-blocking I/O is in use |
| * and that transmission has not completed. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "pBytesTransferred" |
| * The address at which the number of bytes sent is stored. Must be |
| * non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_SendContinue( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| PKIX_UInt32 *pBytesTransferred, |
| void *plContext) |
| { |
| PKIX_Int32 bytesWritten = 0; |
| PKIX_PL_Socket_Callback *callbackList = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_SendContinue"); |
| PKIX_NULLCHECK_THREE(client, pKeepGoing, pBytesTransferred); |
| |
| *pKeepGoing = PKIX_FALSE; |
| |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| |
| PKIX_CHECK(callbackList->pollCallback |
| (client->clientSocket, &bytesWritten, NULL, plContext), |
| PKIX_SOCKETPOLLFAILED); |
| |
| /* |
| * If the send completed we can proceed to try for the |
| * response. If the send did not complete we will have |
| * continue to poll. |
| */ |
| if (bytesWritten >= 0) { |
| client->sendBuf = NULL; |
| client->connectStatus = RECV; |
| |
| PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
| ((PKIX_PL_Object *)client, plContext), |
| PKIX_OBJECTINVALIDATECACHEFAILED); |
| |
| *pKeepGoing = PKIX_TRUE; |
| } |
| |
| *pBytesTransferred = bytesWritten; |
| |
| cleanup: |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_Recv |
| * DESCRIPTION: |
| * |
| * This function receives an LDAP-protocol message for the CertStore embodied |
| * in the LdapDefaultClient "client", and stores in "pKeepGoing" a flag |
| * indicating whether processing can continue without further input. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_Recv( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| void *plContext) |
| { |
| PKIX_Int32 bytesRead = 0; |
| PKIX_UInt32 bytesToRead = 0; |
| PKIX_PL_Socket_Callback *callbackList = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Recv"); |
| PKIX_NULLCHECK_THREE(client, pKeepGoing, client->rcvBuf); |
| |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| |
| /* |
| * If we attempt to fill our buffer with every read, we increase |
| * the risk of an ugly situation: one or two bytes of a new message |
| * left over at the end of processing one message. With such a |
| * fragment, we can't decode a byte count and so won't know how much |
| * space to allocate for the next LdapResponse. We try to avoid that |
| * case by reading just enough to complete the current message, unless |
| * there will be at least MINIMUM_MSG_LENGTH bytes left over. |
| */ |
| if (client->currentResponse) { |
| PKIX_CHECK(pkix_pl_LdapResponse_GetCapacity |
| (client->currentResponse, &bytesToRead, plContext), |
| PKIX_LDAPRESPONSEGETCAPACITYFAILED); |
| if ((bytesToRead > client->capacity) || |
| ((bytesToRead + MINIMUM_MSG_LENGTH) < client->capacity)) { |
| bytesToRead = client->capacity; |
| } |
| } else { |
| bytesToRead = client->capacity; |
| } |
| |
| client->currentBytesAvailable = 0; |
| |
| PKIX_CHECK(callbackList->recvCallback |
| (client->clientSocket, |
| (void *)client->rcvBuf, |
| bytesToRead, |
| &bytesRead, |
| plContext), |
| PKIX_SOCKETRECVFAILED); |
| |
| client->currentInPtr = client->rcvBuf; |
| client->lastIO = PR_Now(); |
| |
| if (bytesRead > 0) { |
| client->currentBytesAvailable = bytesRead; |
| client->connectStatus = RECV_INITIAL; |
| *pKeepGoing = PKIX_TRUE; |
| } else { |
| client->connectStatus = RECV_PENDING; |
| *pKeepGoing = PKIX_FALSE; |
| } |
| |
| PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
| ((PKIX_PL_Object *)client, plContext), |
| PKIX_OBJECTINVALIDATECACHEFAILED); |
| |
| cleanup: |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_RecvContinue |
| * DESCRIPTION: |
| * |
| * This function determines whether the receiving of the LDAP-protocol message |
| * for the CertStore embodied in the LdapDefaultClient "client" has completed, |
| * and stores in "pKeepGoing" a flag indicating whether processing can continue |
| * without further input. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_RecvContinue( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| void *plContext) |
| { |
| PKIX_Int32 bytesRead = 0; |
| PKIX_PL_Socket_Callback *callbackList = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvContinue"); |
| PKIX_NULLCHECK_TWO(client, pKeepGoing); |
| |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| |
| PKIX_CHECK(callbackList->pollCallback |
| (client->clientSocket, NULL, &bytesRead, plContext), |
| PKIX_SOCKETPOLLFAILED); |
| |
| if (bytesRead > 0) { |
| client->currentBytesAvailable += bytesRead; |
| client->connectStatus = RECV_INITIAL; |
| *pKeepGoing = PKIX_TRUE; |
| |
| PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
| ((PKIX_PL_Object *)client, plContext), |
| PKIX_OBJECTINVALIDATECACHEFAILED); |
| } else { |
| *pKeepGoing = PKIX_FALSE; |
| } |
| |
| cleanup: |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_AbandonContinue |
| * DESCRIPTION: |
| * |
| * This function determines whether the abandon-message request of the |
| * LDAP-protocol message for the CertStore embodied in the LdapDefaultClient |
| * "client" has completed, and stores in "pKeepGoing" a flag indicating whether |
| * processing can continue without further input. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_AbandonContinue( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| void *plContext) |
| { |
| PKIX_Int32 bytesWritten = 0; |
| PKIX_PL_Socket_Callback *callbackList = NULL; |
| |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_AbandonContinue"); |
| PKIX_NULLCHECK_TWO(client, pKeepGoing); |
| |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| |
| PKIX_CHECK(callbackList->pollCallback |
| (client->clientSocket, &bytesWritten, NULL, plContext), |
| PKIX_SOCKETPOLLFAILED); |
| |
| if (bytesWritten > 0) { |
| client->connectStatus = BOUND; |
| *pKeepGoing = PKIX_TRUE; |
| |
| PKIX_CHECK(PKIX_PL_Object_InvalidateCache |
| ((PKIX_PL_Object *)client, plContext), |
| PKIX_OBJECTINVALIDATECACHEFAILED); |
| } else { |
| *pKeepGoing = PKIX_FALSE; |
| } |
| |
| cleanup: |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_RecvInitial |
| * DESCRIPTION: |
| * |
| * This function processes the contents of the first buffer of a received |
| * LDAP-protocol message for the CertStore embodied in the LdapDefaultClient |
| * "client", and stores in "pKeepGoing" a flag indicating whether processing can |
| * continue without further input. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_RecvInitial( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| void *plContext) |
| { |
| unsigned char *msgBuf = NULL; |
| unsigned char *to = NULL; |
| unsigned char *from = NULL; |
| PKIX_UInt32 dataIndex = 0; |
| PKIX_UInt32 messageIdLen = 0; |
| PKIX_UInt32 messageLength = 0; |
| PKIX_UInt32 sizeofLength = 0; |
| PKIX_UInt32 bytesProcessed = 0; |
| unsigned char messageChar = 0; |
| LDAPMessageType messageType = 0; |
| PKIX_Int32 bytesRead = 0; |
| PKIX_PL_Socket_Callback *callbackList = NULL; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvInitial"); |
| PKIX_NULLCHECK_TWO(client, pKeepGoing); |
| |
| /* |
| * Is there an LDAPResponse in progress? I.e., have we |
| * already processed the tag and length at the beginning of |
| * the message? |
| */ |
| if (client->currentResponse) { |
| client->connectStatus = RECV_NONINITIAL; |
| *pKeepGoing = PKIX_TRUE; |
| goto cleanup; |
| } |
| msgBuf = client->currentInPtr; |
| |
| /* Do we have enough of the message to decode the message length? */ |
| if (client->currentBytesAvailable < MINIMUM_MSG_LENGTH) { |
| /* |
| * No! Move these few bytes to the beginning of rcvBuf |
| * and hang another read. |
| */ |
| |
| to = (unsigned char *)client->rcvBuf; |
| from = client->currentInPtr; |
| for (dataIndex = 0; |
| dataIndex < client->currentBytesAvailable; |
| dataIndex++) { |
| *to++ = *from++; |
| } |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| PKIX_CHECK(callbackList->recvCallback |
| (client->clientSocket, |
| (void *)to, |
| client->capacity - client->currentBytesAvailable, |
| &bytesRead, |
| plContext), |
| PKIX_SOCKETRECVFAILED); |
| |
| client->currentInPtr = client->rcvBuf; |
| client->lastIO = PR_Now(); |
| |
| if (bytesRead <= 0) { |
| client->connectStatus = RECV_PENDING; |
| *pKeepGoing = PKIX_FALSE; |
| goto cleanup; |
| } else { |
| client->currentBytesAvailable += bytesRead; |
| } |
| } |
| |
| /* |
| * We have to determine whether the response is an entry, with |
| * application-specific tag LDAP_SEARCHRESPONSEENTRY_TYPE, or a |
| * resultCode, with application tag LDAP_SEARCHRESPONSERESULT_TYPE. |
| * First, we have to figure out where to look for the tag. |
| */ |
| |
| /* Is the message length short form (one octet) or long form? */ |
| if ((msgBuf[1] & 0x80) != 0) { |
| sizeofLength = msgBuf[1] & 0x7F; |
| for (dataIndex = 0; dataIndex < sizeofLength; dataIndex++) { |
| messageLength = |
| (messageLength << 8) + msgBuf[dataIndex + 2]; |
| } |
| } else { |
| messageLength = msgBuf[1]; |
| } |
| |
| /* How many bytes did the messageID require? */ |
| messageIdLen = msgBuf[dataIndex + 3]; |
| |
| messageChar = msgBuf[dataIndex + messageIdLen + 4]; |
| |
| /* Are we looking at an Entry message or a ResultCode message? */ |
| if ((SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | |
| LDAP_SEARCHRESPONSEENTRY_TYPE) == messageChar) { |
| |
| messageType = LDAP_SEARCHRESPONSEENTRY_TYPE; |
| |
| } else if ((SEC_ASN1_CONSTRUCTED | SEC_ASN1_APPLICATION | |
| LDAP_SEARCHRESPONSERESULT_TYPE) == messageChar) { |
| |
| messageType = LDAP_SEARCHRESPONSERESULT_TYPE; |
| |
| } else { |
| |
| PKIX_ERROR(PKIX_SEARCHRESPONSEPACKETOFUNKNOWNTYPE); |
| |
| } |
| |
| /* |
| * messageLength is the length from (tag, length, value). |
| * We have to allocate space for the tag and length bits too. |
| */ |
| PKIX_CHECK(pkix_pl_LdapResponse_Create |
| (messageType, |
| messageLength + dataIndex + 2, |
| client->currentBytesAvailable, |
| msgBuf, |
| &bytesProcessed, |
| &(client->currentResponse), |
| plContext), |
| PKIX_LDAPRESPONSECREATEFAILED); |
| |
| client->currentBytesAvailable -= bytesProcessed; |
| |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_RecvCheckComplete |
| (client, bytesProcessed, pKeepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTRECVCHECKCOMPLETEFAILED); |
| |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_RecvNonInitial |
| * DESCRIPTION: |
| * |
| * This function processes the contents of buffers, after the first, of a |
| * received LDAP-protocol message for the CertStore embodied in the |
| * LdapDefaultClient "client", and stores in "pKeepGoing" a flag indicating |
| * whether processing can continue without further input. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pKeepGoing" |
| * The address at which the Boolean state machine flag is stored to |
| * indicate whether processing can continue without further input. |
| * Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_RecvNonInitial( |
| PKIX_PL_LdapDefaultClient *client, |
| PKIX_Boolean *pKeepGoing, |
| void *plContext) |
| { |
| |
| PKIX_UInt32 bytesProcessed = 0; |
| |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_RecvNonInitial"); |
| PKIX_NULLCHECK_TWO(client, pKeepGoing); |
| |
| PKIX_CHECK(pkix_pl_LdapResponse_Append |
| (client->currentResponse, |
| client->currentBytesAvailable, |
| client->currentInPtr, |
| &bytesProcessed, |
| plContext), |
| PKIX_LDAPRESPONSEAPPENDFAILED); |
| |
| client->currentBytesAvailable -= bytesProcessed; |
| |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_RecvCheckComplete |
| (client, bytesProcessed, pKeepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTRECVCHECKCOMPLETEFAILED); |
| |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_Dispatch |
| * DESCRIPTION: |
| * |
| * This function is the state machine dispatcher for the CertStore embodied in |
| * the LdapDefaultClient pointed to by "client". Results are returned by |
| * changes to various fields in the context. |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_Dispatch( |
| PKIX_PL_LdapDefaultClient *client, |
| void *plContext) |
| { |
| PKIX_UInt32 bytesTransferred = 0; |
| PKIX_Boolean keepGoing = PKIX_TRUE; |
| |
| PKIX_ENTER(LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_Dispatch"); |
| PKIX_NULLCHECK_ONE(client); |
| |
| while (keepGoing) { |
| switch (client->connectStatus) { |
| case CONNECT_PENDING: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_ConnectContinue |
| (client, &keepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTCONNECTCONTINUEFAILED); |
| break; |
| case CONNECTED: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_Bind |
| (client, &keepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTBINDFAILED); |
| break; |
| case BIND_PENDING: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_BindContinue |
| (client, &keepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTBINDCONTINUEFAILED); |
| break; |
| case BIND_RESPONSE: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_BindResponse |
| (client, &keepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTBINDRESPONSEFAILED); |
| break; |
| case BIND_RESPONSE_PENDING: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_BindResponseContinue |
| (client, &keepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTBINDRESPONSECONTINUEFAILED); |
| break; |
| case BOUND: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_Send |
| (client, &keepGoing, &bytesTransferred, plContext), |
| PKIX_LDAPDEFAULTCLIENTSENDFAILED); |
| break; |
| case SEND_PENDING: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_SendContinue |
| (client, &keepGoing, &bytesTransferred, plContext), |
| PKIX_LDAPDEFAULTCLIENTSENDCONTINUEFAILED); |
| break; |
| case RECV: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_Recv |
| (client, &keepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTRECVFAILED); |
| break; |
| case RECV_PENDING: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_RecvContinue |
| (client, &keepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTRECVCONTINUEFAILED); |
| break; |
| case RECV_INITIAL: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_RecvInitial |
| (client, &keepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTRECVINITIALFAILED); |
| break; |
| case RECV_NONINITIAL: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_RecvNonInitial |
| (client, &keepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTRECVNONINITIALFAILED); |
| break; |
| case ABANDON_PENDING: |
| PKIX_CHECK |
| (pkix_pl_LdapDefaultClient_AbandonContinue |
| (client, &keepGoing, plContext), |
| PKIX_LDAPDEFAULTCLIENTABANDONCONTINUEFAILED); |
| break; |
| default: |
| PKIX_ERROR(PKIX_LDAPCERTSTOREINILLEGALSTATE); |
| } |
| } |
| |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_MakeAndFilter |
| * DESCRIPTION: |
| * |
| * This function allocates space from the arena pointed to by "arena" to |
| * construct a filter that will match components of the X500Name pointed to by |
| * XXX... |
| * |
| * PARAMETERS: |
| * "arena" |
| * The address of the PLArenaPool used in creating the filter. Must be |
| * non-NULL. |
| * "nameComponent" |
| * The address of a NULL-terminated list of LDAPNameComponents |
| * Must be non-NULL. |
| * "pFilter" |
| * The address at which the result is stored. |
| * "plContext" |
| * Platform-specific context pointer |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a CertStore Error if the function fails in a non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_MakeAndFilter( |
| PLArenaPool *arena, |
| LDAPNameComponent **nameComponents, |
| LDAPFilter **pFilter, |
| void *plContext) |
| { |
| LDAPFilter **setOfFilter; |
| LDAPFilter *andFilter = NULL; |
| LDAPFilter *currentFilter = NULL; |
| PKIX_UInt32 componentsPresent = 0; |
| void *v = NULL; |
| unsigned char *component = NULL; |
| LDAPNameComponent **componentP = NULL; |
| |
| PKIX_ENTER(CERTSTORE, "pkix_pl_LdapDefaultClient_MakeAndFilter"); |
| PKIX_NULLCHECK_THREE(arena, nameComponents, pFilter); |
| |
| /* count how many components we were provided */ |
| for (componentP = nameComponents, componentsPresent = 0; |
| *(componentP++) != NULL; |
| componentsPresent++) {} |
| |
| /* Space for (componentsPresent + 1) pointers to LDAPFilter */ |
| PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZAlloc, |
| (arena, (componentsPresent + 1)*sizeof(LDAPFilter *))); |
| setOfFilter = (LDAPFilter **)v; |
| |
| /* Space for AndFilter and <componentsPresent> EqualFilters */ |
| PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZNewArray, |
| (arena, LDAPFilter, componentsPresent + 1)); |
| setOfFilter[0] = (LDAPFilter *)v; |
| |
| /* Claim the first array element for the ANDFilter */ |
| andFilter = setOfFilter[0]; |
| |
| /* Set ANDFilter to point to the first EqualFilter pointer */ |
| andFilter->selector = LDAP_ANDFILTER_TYPE; |
| andFilter->filter.andFilter.filters = setOfFilter; |
| |
| currentFilter = andFilter + 1; |
| |
| for (componentP = nameComponents, componentsPresent = 0; |
| *(componentP) != NULL; componentP++) { |
| setOfFilter[componentsPresent++] = currentFilter; |
| currentFilter->selector = LDAP_EQUALFILTER_TYPE; |
| component = (*componentP)->attrType; |
| currentFilter->filter.equalFilter.attrType.data = component; |
| currentFilter->filter.equalFilter.attrType.len = |
| PL_strlen((const char *)component); |
| component = (*componentP)->attrValue; |
| currentFilter->filter.equalFilter.attrValue.data = component; |
| currentFilter->filter.equalFilter.attrValue.len = |
| PL_strlen((const char *)component); |
| currentFilter++; |
| } |
| |
| setOfFilter[componentsPresent] = NULL; |
| |
| *pFilter = andFilter; |
| |
| PKIX_RETURN(CERTSTORE); |
| |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_InitiateRequest |
| * DESCRIPTION: |
| * |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "requestParams" |
| * The address of an LdapClientParams object. Must be non-NULL. |
| * "pPollDesc" |
| * The location where the address of the PRPollDesc is stored, if the |
| * client returns with I/O pending. |
| * "pResponse" |
| * The address where the List of LDAPResponses, or NULL for an |
| * unfinished request, is stored. Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_InitiateRequest( |
| PKIX_PL_LdapClient *genericClient, |
| LDAPRequestParams *requestParams, |
| void **pPollDesc, |
| PKIX_List **pResponse, |
| void *plContext) |
| { |
| PKIX_List *searchResponseList = NULL; |
| SECItem *encoded = NULL; |
| LDAPFilter *filter = NULL; |
| PKIX_PL_LdapDefaultClient *client = 0; |
| |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, |
| "pkix_pl_LdapDefaultClient_InitiateRequest"); |
| PKIX_NULLCHECK_FOUR(genericClient, requestParams, pPollDesc, pResponse); |
| |
| PKIX_CHECK(pkix_CheckType |
| ((PKIX_PL_Object *)genericClient, |
| PKIX_LDAPDEFAULTCLIENT_TYPE, |
| plContext), |
| PKIX_GENERICCLIENTNOTANLDAPDEFAULTCLIENT); |
| |
| client = (PKIX_PL_LdapDefaultClient *)genericClient; |
| |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeAndFilter |
| (client->arena, requestParams->nc, &filter, plContext), |
| PKIX_LDAPDEFAULTCLIENTMAKEANDFILTERFAILED); |
| |
| PKIX_CHECK(pkix_pl_LdapRequest_Create |
| (client->arena, |
| client->messageID++, |
| requestParams->baseObject, |
| requestParams->scope, |
| requestParams->derefAliases, |
| requestParams->sizeLimit, |
| requestParams->timeLimit, |
| PKIX_FALSE, /* attrs only */ |
| filter, |
| requestParams->attributes, |
| &client->currentRequest, |
| plContext), |
| PKIX_LDAPREQUESTCREATEFAILED); |
| |
| /* check hashtable for matching request */ |
| PKIX_CHECK(PKIX_PL_HashTable_Lookup |
| (client->cachePtr, |
| (PKIX_PL_Object *)(client->currentRequest), |
| (PKIX_PL_Object **)&searchResponseList, |
| plContext), |
| PKIX_HASHTABLELOOKUPFAILED); |
| |
| if (searchResponseList != NULL) { |
| *pPollDesc = NULL; |
| *pResponse = searchResponseList; |
| PKIX_DECREF(client->currentRequest); |
| goto cleanup; |
| } |
| |
| /* It wasn't cached. We'll have to actually send it. */ |
| |
| PKIX_CHECK(pkix_pl_LdapRequest_GetEncoded |
| (client->currentRequest, &encoded, plContext), |
| PKIX_LDAPREQUESTGETENCODEDFAILED); |
| |
| client->sendBuf = encoded->data; |
| client->bytesToWrite = encoded->len; |
| |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_Dispatch(client, plContext), |
| PKIX_LDAPDEFAULTCLIENTDISPATCHFAILED); |
| |
| /* |
| * It's not enough that we may be done with a particular read. |
| * We're still processing the transaction until we've gotten the |
| * SearchResponseResult message and returned to the BOUND state. |
| * Otherwise we must still have a read pending, and must hold off |
| * on returning results. |
| */ |
| if ((client->connectStatus == BOUND) && |
| (client->entriesFound != NULL)) { |
| *pPollDesc = NULL; |
| *pResponse = client->entriesFound; |
| client->entriesFound = NULL; |
| PKIX_DECREF(client->currentRequest); |
| } else { |
| *pPollDesc = &client->pollDesc; |
| *pResponse = NULL; |
| } |
| |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| |
| } |
| |
| /* |
| * FUNCTION: pkix_pl_LdapDefaultClient_ResumeRequest |
| * DESCRIPTION: |
| * |
| * |
| * PARAMETERS: |
| * "client" |
| * The address of the LdapDefaultClient object. Must be non-NULL. |
| * "pPollDesc" |
| * The location where the address of the PRPollDesc is stored, if the |
| * client returns with I/O pending. |
| * "pResponse" |
| * The address where the List of LDAPResponses, or NULL for an |
| * unfinished request, is stored. Must be non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a LdapDefaultClient Error if the function fails in a |
| * non-fatal way. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| static PKIX_Error * |
| pkix_pl_LdapDefaultClient_ResumeRequest( |
| PKIX_PL_LdapClient *genericClient, |
| void **pPollDesc, |
| PKIX_List **pResponse, |
| void *plContext) |
| { |
| PKIX_PL_LdapDefaultClient *client = 0; |
| |
| PKIX_ENTER |
| (LDAPDEFAULTCLIENT, "pkix_pl_LdapDefaultClient_ResumeRequest"); |
| PKIX_NULLCHECK_THREE(genericClient, pPollDesc, pResponse); |
| |
| PKIX_CHECK(pkix_CheckType |
| ((PKIX_PL_Object *)genericClient, |
| PKIX_LDAPDEFAULTCLIENT_TYPE, |
| plContext), |
| PKIX_GENERICCLIENTNOTANLDAPDEFAULTCLIENT); |
| |
| client = (PKIX_PL_LdapDefaultClient *)genericClient; |
| |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_Dispatch(client, plContext), |
| PKIX_LDAPDEFAULTCLIENTDISPATCHFAILED); |
| |
| /* |
| * It's not enough that we may be done with a particular read. |
| * We're still processing the transaction until we've gotten the |
| * SearchResponseResult message and returned to the BOUND state. |
| * Otherwise we must still have a read pending, and must hold off |
| * on returning results. |
| */ |
| if ((client->connectStatus == BOUND) && |
| (client->entriesFound != NULL)) { |
| *pPollDesc = NULL; |
| *pResponse = client->entriesFound; |
| client->entriesFound = NULL; |
| PKIX_DECREF(client->currentRequest); |
| } else { |
| *pPollDesc = &client->pollDesc; |
| *pResponse = NULL; |
| } |
| |
| cleanup: |
| |
| PKIX_RETURN(LDAPDEFAULTCLIENT); |
| |
| } |
| |
| /* --Public-LdapDefaultClient-Functions----------------------------------- */ |
| |
| /* |
| * FUNCTION: PKIX_PL_LdapDefaultClient_AbandonRequest |
| * DESCRIPTION: |
| * |
| * This function creates and sends an LDAP-protocol "Abandon" message to the |
| * server connected to the LdapDefaultClient pointed to by "client". |
| * |
| * PARAMETERS: |
| * "client" |
| * The LdapDefaultClient whose connection is to be abandoned. Must be |
| * non-NULL. |
| * "plContext" |
| * Platform-specific context pointer. |
| * THREAD SAFETY: |
| * Thread Safe (see Thread Safety Definitions in Programmer's Guide) |
| * RETURNS: |
| * Returns NULL if the function succeeds. |
| * Returns a Fatal Error if the function fails in an unrecoverable way. |
| */ |
| PKIX_Error * |
| PKIX_PL_LdapDefaultClient_AbandonRequest( |
| PKIX_PL_LdapDefaultClient *client, |
| void *plContext) |
| { |
| PKIX_Int32 bytesWritten = 0; |
| PKIX_PL_Socket_Callback *callbackList = NULL; |
| SECItem *encoded = NULL; |
| |
| PKIX_ENTER(CERTSTORE, "PKIX_PL_LdapDefaultClient_AbandonRequest"); |
| PKIX_NULLCHECK_ONE(client); |
| |
| if (client->connectStatus == RECV_PENDING) { |
| PKIX_CHECK(pkix_pl_LdapDefaultClient_MakeAbandon |
| (client->arena, |
| (client->messageID) - 1, |
| &encoded, |
| plContext), |
| PKIX_LDAPDEFAULTCLIENTMAKEABANDONFAILED); |
| |
| callbackList = (PKIX_PL_Socket_Callback *)(client->callbackList); |
| PKIX_CHECK(callbackList->sendCallback |
| (client->clientSocket, |
| encoded->data, |
| encoded->len, |
| &bytesWritten, |
| plContext), |
| PKIX_SOCKETSENDFAILED); |
| |
| if (bytesWritten < 0) { |
| client->connectStatus = ABANDON_PENDING; |
| } else { |
| client->connectStatus = BOUND; |
| } |
| } |
| |
| PKIX_DECREF(client->entriesFound); |
| PKIX_DECREF(client->currentRequest); |
| PKIX_DECREF(client->currentResponse); |
| |
| cleanup: |
| |
| PKIX_DECREF(client); |
| |
| PKIX_RETURN(CERTSTORE); |
| } |