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 *
pkix_pl_LdapDefaultClient_MakeBind(PLArenaPool * arena,PKIX_Int32 versionData,LDAPBindAPI * bindAPI,PKIX_UInt32 msgNum,SECItem ** pBindMsg,void * plContext)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 *
pkix_pl_LdapDefaultClient_MakeUnbind(PLArenaPool * arena,PKIX_UInt32 msgNum,SECItem ** pUnbindMsg,void * plContext)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 *
pkix_pl_LdapDefaultClient_MakeAbandon(PLArenaPool * arena,PKIX_UInt32 msgNum,SECItem ** pAbandonMsg,void * plContext)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 *
pkix_pl_LdapDefaultClient_DecodeBindResponse(PLArenaPool * arena,SECItem * src,LDAPMessage * pBindResponse,SECStatus * pStatus,void * plContext)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 *
pkix_pl_LdapDefaultClient_VerifyBindResponse(PKIX_PL_LdapDefaultClient * client,PKIX_UInt32 bufLen,void * plContext)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 *
pkix_pl_LdapDefaultClient_RecvCheckComplete(PKIX_PL_LdapDefaultClient * client,PKIX_UInt32 bytesProcessed,PKIX_Boolean * pKeepGoing,void * plContext)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 *
pkix_pl_LdapDefaultClient_CreateHelper(PKIX_PL_Socket * socket,LDAPBindAPI * bindAPI,PKIX_PL_LdapDefaultClient ** pClient,void * plContext)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 *
PKIX_PL_LdapDefaultClient_Create(PRNetAddr * sockaddr,PRIntervalTime timeout,LDAPBindAPI * bindAPI,PKIX_PL_LdapDefaultClient ** pClient,void * plContext)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 *
PKIX_PL_LdapDefaultClient_CreateByName(char * hostname,PRIntervalTime timeout,LDAPBindAPI * bindAPI,PKIX_PL_LdapDefaultClient ** pClient,void * plContext)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 *
pkix_pl_LdapDefaultClient_Destroy(PKIX_PL_Object * object,void * plContext)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 *
pkix_pl_LdapDefaultClient_Hashcode(PKIX_PL_Object * object,PKIX_UInt32 * pHashcode,void * plContext)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 *
pkix_pl_LdapDefaultClient_Equals(PKIX_PL_Object * firstObject,PKIX_PL_Object * secondObject,PKIX_Int32 * pResult,void * plContext)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 *
pkix_pl_LdapDefaultClient_RegisterSelf(void * plContext)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 *
pkix_pl_LdapDefaultClient_GetPollDesc(PKIX_PL_LdapDefaultClient * context,PRPollDesc ** pPollDesc,void * plContext)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 *
pkix_pl_LdapDefaultClient_ConnectContinue(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,void * plContext)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 *
pkix_pl_LdapDefaultClient_Bind(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,void * plContext)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  */
pkix_pl_LdapDefaultClient_BindContinue(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,void * plContext)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 *
pkix_pl_LdapDefaultClient_BindResponse(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,void * plContext)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 *
pkix_pl_LdapDefaultClient_BindResponseContinue(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,void * plContext)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 *
pkix_pl_LdapDefaultClient_Send(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,PKIX_UInt32 * pBytesTransferred,void * plContext)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 *
pkix_pl_LdapDefaultClient_SendContinue(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,PKIX_UInt32 * pBytesTransferred,void * plContext)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 *
pkix_pl_LdapDefaultClient_Recv(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,void * plContext)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 *
pkix_pl_LdapDefaultClient_RecvContinue(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,void * plContext)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 *
pkix_pl_LdapDefaultClient_AbandonContinue(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,void * plContext)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 *
pkix_pl_LdapDefaultClient_RecvInitial(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,void * plContext)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 *
pkix_pl_LdapDefaultClient_RecvNonInitial(PKIX_PL_LdapDefaultClient * client,PKIX_Boolean * pKeepGoing,void * plContext)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 *
pkix_pl_LdapDefaultClient_Dispatch(PKIX_PL_LdapDefaultClient * client,void * plContext)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 *
pkix_pl_LdapDefaultClient_MakeAndFilter(PLArenaPool * arena,LDAPNameComponent ** nameComponents,LDAPFilter ** pFilter,void * plContext)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 *
pkix_pl_LdapDefaultClient_InitiateRequest(PKIX_PL_LdapClient * genericClient,LDAPRequestParams * requestParams,void ** pPollDesc,PKIX_List ** pResponse,void * plContext)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 *
pkix_pl_LdapDefaultClient_ResumeRequest(PKIX_PL_LdapClient * genericClient,void ** pPollDesc,PKIX_List ** pResponse,void * plContext)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 *
PKIX_PL_LdapDefaultClient_AbandonRequest(PKIX_PL_LdapDefaultClient * client,void * plContext)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 }
2495