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