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_ldapcertstore.c
6  *
7  * LDAPCertStore 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_ldapcertstore.h"
15 
16 /* --Private-Ldap-CertStore-Database-Functions----------------------- */
17 
18 /*
19  * FUNCTION: pkix_pl_LdapCertStore_DecodeCrossCertPair
20  * DESCRIPTION:
21  *
22  *  This function decodes a DER-encoded CrossCertPair pointed to by
23  *  "responseList" and extracts and decodes the Certificates in that pair,
24  *  adding the resulting Certs, if the decoding was successful, to the List
25  *  (possibly empty) pointed to by "certList". If none of the objects
26  *  can be decoded into a Cert, the List is returned unchanged.
27  *
28  * PARAMETERS:
29  *  "derCCPItem"
30  *      The address of the SECItem containing the DER representation of the
31  *      CrossCertPair. Must be non-NULL.
32  *  "certList"
33  *      The address of the List to which the decoded Certs are added. May be
34  *      empty, but must be non-NULL.
35  *  "plContext"
36  *      Platform-specific context pointer.
37  * THREAD SAFETY:
38  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
39  * RETURNS:
40  *  Returns NULL if the function succeeds.
41  *  Returns a CertStore Error if the function fails in a non-fatal way.
42  *  Returns a Fatal Error if the function fails in an unrecoverable way.
43  */
44 PKIX_Error *
pkix_pl_LdapCertStore_DecodeCrossCertPair(SECItem * derCCPItem,PKIX_List * certList,void * plContext)45 pkix_pl_LdapCertStore_DecodeCrossCertPair(
46         SECItem *derCCPItem,
47         PKIX_List *certList,
48         void *plContext)
49 {
50         LDAPCertPair certPair = {{ siBuffer, NULL, 0 }, { siBuffer, NULL, 0 }};
51         SECStatus rv = SECFailure;
52 
53         PLArenaPool *tempArena = NULL;
54 
55         PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_DecodeCrossCertPair");
56         PKIX_NULLCHECK_TWO(derCCPItem, certList);
57 
58         tempArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
59         if (!tempArena) {
60             PKIX_ERROR(PKIX_OUTOFMEMORY);
61         }
62 
63         rv = SEC_ASN1DecodeItem(tempArena, &certPair, PKIX_PL_LDAPCrossCertPairTemplate,
64                                 derCCPItem);
65         if (rv != SECSuccess) {
66                 goto cleanup;
67         }
68 
69         if (certPair.forward.data != NULL) {
70 
71             PKIX_CHECK(
72                 pkix_pl_Cert_CreateToList(&certPair.forward, certList,
73                                           plContext),
74                 PKIX_CERTCREATETOLISTFAILED);
75         }
76 
77         if (certPair.reverse.data != NULL) {
78 
79             PKIX_CHECK(
80                 pkix_pl_Cert_CreateToList(&certPair.reverse, certList,
81                                           plContext),
82                 PKIX_CERTCREATETOLISTFAILED);
83         }
84 
85 cleanup:
86         if (tempArena) {
87             PORT_FreeArena(tempArena, PR_FALSE);
88         }
89 
90         PKIX_RETURN(CERTSTORE);
91 }
92 
93 /*
94  * FUNCTION: pkix_pl_LdapCertStore_BuildCertList
95  * DESCRIPTION:
96  *
97  *  This function takes a List of LdapResponse objects pointed to by
98  *  "responseList" and extracts and decodes the Certificates in those responses,
99  *  storing the List of those Certificates at "pCerts". If none of the objects
100  *  can be decoded into a Cert, the returned List is empty.
101  *
102  * PARAMETERS:
103  *  "responseList"
104  *      The address of the List of LdapResponses. Must be non-NULL.
105  *  "pCerts"
106  *      The address at which the result is stored. Must be non-NULL.
107  *  "plContext"
108  *      Platform-specific context pointer.
109  * THREAD SAFETY:
110  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
111  * RETURNS:
112  *  Returns NULL if the function succeeds.
113  *  Returns a CertStore Error if the function fails in a non-fatal way.
114  *  Returns a Fatal Error if the function fails in an unrecoverable way.
115  */
116 PKIX_Error *
pkix_pl_LdapCertStore_BuildCertList(PKIX_List * responseList,PKIX_List ** pCerts,void * plContext)117 pkix_pl_LdapCertStore_BuildCertList(
118         PKIX_List *responseList,
119         PKIX_List **pCerts,
120         void *plContext)
121 {
122         PKIX_UInt32 numResponses = 0;
123         PKIX_UInt32 respIx = 0;
124         LdapAttrMask attrBits = 0;
125         PKIX_PL_LdapResponse *response = NULL;
126         PKIX_List *certList = NULL;
127         LDAPMessage *message = NULL;
128         LDAPSearchResponseEntry *sre = NULL;
129         LDAPSearchResponseAttr **sreAttrArray = NULL;
130         LDAPSearchResponseAttr *sreAttr = NULL;
131         SECItem *attrType = NULL;
132         SECItem **attrVal = NULL;
133         SECItem *derCertItem = NULL;
134 
135 
136         PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_BuildCertList");
137         PKIX_NULLCHECK_TWO(responseList, pCerts);
138 
139         PKIX_CHECK(PKIX_List_Create(&certList, plContext),
140                 PKIX_LISTCREATEFAILED);
141 
142         /* extract certs from response */
143         PKIX_CHECK(PKIX_List_GetLength
144                 (responseList, &numResponses, plContext),
145                 PKIX_LISTGETLENGTHFAILED);
146 
147         for (respIx = 0; respIx < numResponses; respIx++) {
148                 PKIX_CHECK(PKIX_List_GetItem
149                         (responseList,
150                         respIx,
151                         (PKIX_PL_Object **)&response,
152                         plContext),
153                         PKIX_LISTGETITEMFAILED);
154 
155                 PKIX_CHECK(pkix_pl_LdapResponse_GetMessage
156                         (response, &message, plContext),
157                         PKIX_LDAPRESPONSEGETMESSAGEFAILED);
158 
159                 sre = &(message->protocolOp.op.searchResponseEntryMsg);
160                 sreAttrArray = sre->attributes;
161 
162                 /* Get next element of null-terminated array */
163                 sreAttr = *sreAttrArray++;
164                 while (sreAttr != NULL) {
165                     attrType = &(sreAttr->attrType);
166                     PKIX_CHECK(pkix_pl_LdapRequest_AttrTypeToBit
167                         (attrType, &attrBits, plContext),
168                         PKIX_LDAPREQUESTATTRTYPETOBITFAILED);
169                     /* Is this attrVal a Certificate? */
170                     if (((LDAPATTR_CACERT | LDAPATTR_USERCERT) &
171                             attrBits) == attrBits) {
172                         attrVal = sreAttr->val;
173                         derCertItem = *attrVal++;
174                         while (derCertItem != 0) {
175                             /* create a PKIX_PL_Cert from derCert */
176                             PKIX_CHECK(pkix_pl_Cert_CreateToList
177                                 (derCertItem, certList, plContext),
178                                 PKIX_CERTCREATETOLISTFAILED);
179                             derCertItem = *attrVal++;
180                         }
181                     } else if ((LDAPATTR_CROSSPAIRCERT & attrBits) == attrBits){
182                         /* Is this attrVal a CrossPairCertificate? */
183                         attrVal = sreAttr->val;
184                         derCertItem = *attrVal++;
185                         while (derCertItem != 0) {
186                             /* create PKIX_PL_Certs from derCert */
187                             PKIX_CHECK(pkix_pl_LdapCertStore_DecodeCrossCertPair
188                                 (derCertItem, certList, plContext),
189                                 PKIX_LDAPCERTSTOREDECODECROSSCERTPAIRFAILED);
190                             derCertItem = *attrVal++;
191                         }
192                     }
193                     sreAttr = *sreAttrArray++;
194                 }
195                 PKIX_DECREF(response);
196         }
197 
198         *pCerts = certList;
199 
200 cleanup:
201         if (PKIX_ERROR_RECEIVED) {
202                 PKIX_DECREF(certList);
203         }
204 
205         PKIX_DECREF(response);
206 
207         PKIX_RETURN(CERTSTORE);
208 }
209 
210 /*
211  * FUNCTION: pkix_pl_LdapCertStore_BuildCrlList
212  * DESCRIPTION:
213  *
214  *  This function takes a List of LdapResponse objects pointed to by
215  *  "responseList" and extracts and decodes the CRLs in those responses, storing
216  *  the List of those CRLs at "pCrls". If none of the objects can be decoded
217  *  into a CRL, the returned List is empty.
218  *
219  * PARAMETERS:
220  *  "responseList"
221  *      The address of the List of LdapResponses. Must be non-NULL.
222  *  "pCrls"
223  *      The address at which the result is stored. Must be non-NULL.
224  *  "plContext"
225  *      Platform-specific context pointer.
226  * THREAD SAFETY:
227  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
228  * RETURNS:
229  *  Returns NULL if the function succeeds.
230  *  Returns a CertStore Error if the function fails in a non-fatal way.
231  *  Returns a Fatal Error if the function fails in an unrecoverable way.
232  */
233 PKIX_Error *
pkix_pl_LdapCertStore_BuildCrlList(PKIX_List * responseList,PKIX_List ** pCrls,void * plContext)234 pkix_pl_LdapCertStore_BuildCrlList(
235         PKIX_List *responseList,
236         PKIX_List **pCrls,
237         void *plContext)
238 {
239         PKIX_UInt32 numResponses = 0;
240         PKIX_UInt32 respIx = 0;
241         LdapAttrMask attrBits = 0;
242         CERTSignedCrl *nssCrl = NULL;
243         PKIX_PL_LdapResponse *response = NULL;
244         PKIX_List *crlList = NULL;
245         PKIX_PL_CRL *crl = NULL;
246         LDAPMessage *message = NULL;
247         LDAPSearchResponseEntry *sre = NULL;
248         LDAPSearchResponseAttr **sreAttrArray = NULL;
249         LDAPSearchResponseAttr *sreAttr = NULL;
250         SECItem *attrType = NULL;
251         SECItem **attrVal = NULL;
252         SECItem *derCrlCopy = NULL;
253         SECItem *derCrlItem = NULL;
254 
255         PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_BuildCrlList");
256         PKIX_NULLCHECK_TWO(responseList, pCrls);
257 
258         PKIX_CHECK(PKIX_List_Create(&crlList, plContext),
259                 PKIX_LISTCREATEFAILED);
260 
261         /* extract crls from response */
262         PKIX_CHECK(PKIX_List_GetLength
263                 (responseList, &numResponses, plContext),
264                 PKIX_LISTGETLENGTHFAILED);
265 
266         for (respIx = 0; respIx < numResponses; respIx++) {
267                 PKIX_CHECK(PKIX_List_GetItem
268                         (responseList,
269                         respIx,
270                         (PKIX_PL_Object **)&response,
271                         plContext),
272                         PKIX_LISTGETITEMFAILED);
273 
274                 PKIX_CHECK(pkix_pl_LdapResponse_GetMessage
275                         (response, &message, plContext),
276                         PKIX_LDAPRESPONSEGETMESSAGEFAILED);
277 
278                 sre = &(message->protocolOp.op.searchResponseEntryMsg);
279                 sreAttrArray = sre->attributes;
280 
281                 /* Get next element of null-terminated array */
282                 sreAttr = *sreAttrArray++;
283                 while (sreAttr != NULL) {
284                     attrType = &(sreAttr->attrType);
285                     PKIX_CHECK(pkix_pl_LdapRequest_AttrTypeToBit
286                         (attrType, &attrBits, plContext),
287                         PKIX_LDAPREQUESTATTRTYPETOBITFAILED);
288                     /* Is this attrVal a Revocation List? */
289                     if (((LDAPATTR_CERTREVLIST | LDAPATTR_AUTHREVLIST) &
290                             attrBits) == attrBits) {
291                         attrVal = sreAttr->val;
292                         derCrlItem = *attrVal++;
293                         while (derCrlItem != 0) {
294                             /* create a PKIX_PL_Crl from derCrl */
295                             derCrlCopy = SECITEM_DupItem(derCrlItem);
296                             if (!derCrlCopy) {
297                                 PKIX_ERROR(PKIX_ALLOCERROR);
298                             }
299                             /* crl will be based on derCrlCopy, but wont
300                              * own the der. */
301                             nssCrl =
302                                 CERT_DecodeDERCrlWithFlags(NULL, derCrlCopy,
303                                                        SEC_CRL_TYPE,
304                                                        CRL_DECODE_DONT_COPY_DER |
305                                                        CRL_DECODE_SKIP_ENTRIES);
306                             if (!nssCrl) {
307                                 SECITEM_FreeItem(derCrlCopy, PKIX_TRUE);
308                                 continue;
309                             }
310                             /* pkix crl own the der. */
311                             PKIX_CHECK(
312                                 pkix_pl_CRL_CreateWithSignedCRL(nssCrl,
313                                        derCrlCopy, NULL, &crl, plContext),
314                                 PKIX_CRLCREATEWITHSIGNEDCRLFAILED);
315                             /* Left control over memory pointed by derCrlCopy and
316                              * nssCrl to pkix crl. */
317                             derCrlCopy = NULL;
318                             nssCrl = NULL;
319                             PKIX_CHECK(PKIX_List_AppendItem
320                                        (crlList, (PKIX_PL_Object *) crl, plContext),
321                                        PKIX_LISTAPPENDITEMFAILED);
322                             PKIX_DECREF(crl);
323                             derCrlItem = *attrVal++;
324                         }
325                         /* Clean up after PKIX_CHECK_ONLY_FATAL */
326                         pkixTempErrorReceived = PKIX_FALSE;
327                     }
328                     sreAttr = *sreAttrArray++;
329                 }
330                 PKIX_DECREF(response);
331         }
332 
333         *pCrls = crlList;
334         crlList = NULL;
335 cleanup:
336         if (derCrlCopy) {
337             SECITEM_FreeItem(derCrlCopy, PKIX_TRUE);
338         }
339         if (nssCrl) {
340             SEC_DestroyCrl(nssCrl);
341         }
342         PKIX_DECREF(crl);
343         PKIX_DECREF(crlList);
344         PKIX_DECREF(response);
345 
346         PKIX_RETURN(CERTSTORE);
347 }
348 
349 /*
350  * FUNCTION: pkix_pl_LdapCertStore_DestroyAVAList
351  * DESCRIPTION:
352  *
353  *  This function frees the space allocated for the components of the
354  *  equalFilters that make up the andFilter pointed to by "filter".
355  *
356  * PARAMETERS:
357  *  "requestParams"
358  *      The address of the andFilter whose components are to be freed. Must be
359  *      non-NULL.
360  *  "plContext"
361  *      Platform-specific context pointer
362  * THREAD SAFETY:
363  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
364  * RETURNS:
365  *  Returns NULL if the function succeeds.
366  *  Returns a CertStore Error if the function fails in a non-fatal way.
367  *  Returns a Fatal Error if the function fails in an unrecoverable way.
368  */
369 static PKIX_Error *
pkix_pl_LdapCertStore_DestroyAVAList(LDAPNameComponent ** nameComponents,void * plContext)370 pkix_pl_LdapCertStore_DestroyAVAList(
371         LDAPNameComponent **nameComponents,
372         void *plContext)
373 {
374         LDAPNameComponent **currentNC = NULL;
375         unsigned char *component = NULL;
376 
377         PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_DestroyAVAList");
378         PKIX_NULLCHECK_ONE(nameComponents);
379 
380         /* Set currentNC to point to first AVA pointer */
381         currentNC = nameComponents;
382 
383         while ((*currentNC) != NULL) {
384                 component = (*currentNC)->attrValue;
385                 if (component != NULL) {
386                         PORT_Free(component);
387                 }
388                 currentNC++;
389         }
390 
391         PKIX_RETURN(CERTSTORE);
392 }
393 
394 /*
395  * FUNCTION: pkix_pl_LdapCertStore_MakeNameAVAList
396  * DESCRIPTION:
397  *
398  *  This function allocates space from the arena pointed to by "arena" to
399  *  construct a filter that will match components of the X500Name pointed to
400  *  by "name", and stores the resulting filter at "pFilter".
401  *
402  *  "name" is checked for commonName and organizationName components (cn=,
403  *  and o=). The component strings are extracted using the family of
404  *  CERT_Get* functions, and each must be freed with PORT_Free.
405  *
406  *  It is not clear which components should be in a request, so, for now,
407  *  we stop adding components after we have found one.
408  *
409  * PARAMETERS:
410  *  "arena"
411  *      The address of the PLArenaPool used in creating the filter. Must be
412  *       non-NULL.
413  *  "name"
414  *      The address of the X500Name whose components define the desired
415  *      matches. Must be non-NULL.
416  *  "pList"
417  *      The address at which the result is stored.
418  *  "plContext"
419  *      Platform-specific context pointer
420  * THREAD SAFETY:
421  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
422  * RETURNS:
423  *  Returns NULL if the function succeeds.
424  *  Returns a CertStore Error if the function fails in a non-fatal way.
425  *  Returns a Fatal Error if the function fails in an unrecoverable way.
426  */
427 static PKIX_Error *
pkix_pl_LdapCertStore_MakeNameAVAList(PLArenaPool * arena,PKIX_PL_X500Name * subjectName,LDAPNameComponent *** pList,void * plContext)428 pkix_pl_LdapCertStore_MakeNameAVAList(
429         PLArenaPool *arena,
430         PKIX_PL_X500Name *subjectName,
431         LDAPNameComponent ***pList,
432         void *plContext)
433 {
434         LDAPNameComponent **setOfNameComponents;
435         LDAPNameComponent *currentNameComponent = NULL;
436         PKIX_UInt32 componentsPresent = 0;
437         void *v = NULL;
438         unsigned char *component = NULL;
439 
440         PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_MakeNameAVAList");
441         PKIX_NULLCHECK_THREE(arena, subjectName, pList);
442 
443         /* Increase this if additional components may be extracted */
444 #define MAX_NUM_COMPONENTS 3
445 
446         /* Space for (MAX_NUM_COMPONENTS + 1) pointers to LDAPNameComponents */
447         PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZAlloc,
448                 (arena, (MAX_NUM_COMPONENTS + 1)*sizeof(LDAPNameComponent *)));
449         setOfNameComponents = (LDAPNameComponent **)v;
450 
451         /* Space for MAX_NUM_COMPONENTS LDAPNameComponents */
452         PKIX_PL_NSSCALLRV(CERTSTORE, v, PORT_ArenaZNewArray,
453                 (arena, LDAPNameComponent, MAX_NUM_COMPONENTS));
454 
455         currentNameComponent = (LDAPNameComponent *)v;
456 
457         /* Try for commonName */
458         PKIX_CHECK(pkix_pl_X500Name_GetCommonName
459                 (subjectName, &component, plContext),
460                 PKIX_X500NAMEGETCOMMONNAMEFAILED);
461         if (component) {
462                 setOfNameComponents[componentsPresent] = currentNameComponent;
463                 currentNameComponent->attrType = (unsigned char *)"cn";
464                 currentNameComponent->attrValue = component;
465                 componentsPresent++;
466                 currentNameComponent++;
467         }
468 
469         /*
470          * The LDAP specification says we can send multiple name components
471          * in an "AND" filter, but the LDAP Servers don't seem to be able to
472          * handle such requests. So we'll quit after the cn component.
473          */
474 #if 0
475         /* Try for orgName */
476         PKIX_CHECK(pkix_pl_X500Name_GetOrgName
477                 (subjectName, &component, plContext),
478                 PKIX_X500NAMEGETORGNAMEFAILED);
479         if (component) {
480                 setOfNameComponents[componentsPresent] = currentNameComponent;
481                 currentNameComponent->attrType = (unsigned char *)"o";
482                 currentNameComponent->attrValue = component;
483                 componentsPresent++;
484                 currentNameComponent++;
485         }
486 
487         /* Try for countryName */
488         PKIX_CHECK(pkix_pl_X500Name_GetCountryName
489                 (subjectName, &component, plContext),
490                 PKIX_X500NAMEGETCOUNTRYNAMEFAILED);
491         if (component) {
492                 setOfNameComponents[componentsPresent] = currentNameComponent;
493                 currentNameComponent->attrType = (unsigned char *)"c";
494                 currentNameComponent->attrValue = component;
495                 componentsPresent++;
496                 currentNameComponent++;
497         }
498 #endif
499 
500         setOfNameComponents[componentsPresent] = NULL;
501 
502         *pList = setOfNameComponents;
503 
504 cleanup:
505 
506         PKIX_RETURN(CERTSTORE);
507 
508 }
509 
510 #if 0
511 /*
512  * FUNCTION: pkix_pl_LdapCertstore_ConvertCertResponses
513  * DESCRIPTION:
514  *
515  *  This function processes the List of LDAPResponses pointed to by "responses"
516  *  into a List of resulting Certs, storing the result at "pCerts". If there
517  *  are no responses converted successfully, a NULL may be stored.
518  *
519  * PARAMETERS:
520  *  "responses"
521  *      The LDAPResponses whose contents are to be converted. Must be non-NULL.
522  *  "pCerts"
523  *      Address at which the returned List is stored. Must be non-NULL.
524  *  "plContext"
525  *      Platform-specific context pointer.
526  * THREAD SAFETY:
527  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
528  * RETURNS:
529  *  Returns NULL if the function succeeds.
530  *  Returns a CertStore Error if the function fails in a non-fatal way
531  *  Returns a Fatal Error if the function fails in an unrecoverable way.
532  */
533 PKIX_Error *
534 pkix_pl_LdapCertStore_ConvertCertResponses(
535         PKIX_List *responses,
536         PKIX_List **pCerts,
537         void *plContext)
538 {
539         PKIX_List *unfiltered = NULL;
540 
541         PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_ConvertCertResponses");
542         PKIX_NULLCHECK_TWO(responses, pCerts);
543 
544         /*
545          * We have a List of LdapResponse objects that have to be
546          * turned into Certs.
547          */
548         PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
549                 (responses, &unfiltered, plContext),
550                 PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);
551 
552         *pCerts = unfiltered;
553 
554 cleanup:
555 
556         PKIX_RETURN(CERTSTORE);
557 }
558 #endif
559 
560 /*
561  * FUNCTION: pkix_pl_LdapCertStore_GetCert
562  *  (see description of PKIX_CertStore_CertCallback in pkix_certstore.h)
563  */
564 PKIX_Error *
pkix_pl_LdapCertStore_GetCert(PKIX_CertStore * store,PKIX_CertSelector * selector,PKIX_VerifyNode * verifyNode,void ** pNBIOContext,PKIX_List ** pCertList,void * plContext)565 pkix_pl_LdapCertStore_GetCert(
566         PKIX_CertStore *store,
567         PKIX_CertSelector *selector,
568         PKIX_VerifyNode *verifyNode,
569         void **pNBIOContext,
570         PKIX_List **pCertList,
571         void *plContext)
572 {
573         PLArenaPool *requestArena = NULL;
574         LDAPRequestParams requestParams;
575         void *pollDesc = NULL;
576         PKIX_Int32 minPathLen = 0;
577         PKIX_Boolean cacheFlag = PKIX_FALSE;
578         PKIX_ComCertSelParams *params = NULL;
579         PKIX_PL_LdapCertStoreContext *lcs = NULL;
580         PKIX_List *responses = NULL;
581         PKIX_List *unfilteredCerts = NULL;
582         PKIX_List *filteredCerts = NULL;
583         PKIX_PL_X500Name *subjectName = 0;
584 
585         PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCert");
586         PKIX_NULLCHECK_THREE(store, selector, pCertList);
587 
588         requestParams.baseObject = "c=US";
589         requestParams.scope = WHOLE_SUBTREE;
590         requestParams.derefAliases = NEVER_DEREF;
591         requestParams.sizeLimit = 0;
592         requestParams.timeLimit = 0;
593 
594         /* Prepare elements for request filter */
595 
596         /*
597          * Get a short-lived arena. We'll be done with this space once
598          * the request is encoded.
599          */
600         requestArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
601         if (!requestArena) {
602                 PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
603         }
604 
605         PKIX_CHECK(PKIX_CertSelector_GetCommonCertSelectorParams
606                 (selector, &params, plContext),
607                 PKIX_CERTSELECTORGETCOMCERTSELPARAMSFAILED);
608 
609         /*
610          * If we have the subject name for the desired subject,
611          * ask the server for Certs with that subject.
612          */
613         PKIX_CHECK(PKIX_ComCertSelParams_GetSubject
614                 (params, &subjectName, plContext),
615                 PKIX_COMCERTSELPARAMSGETSUBJECTFAILED);
616 
617         PKIX_CHECK(PKIX_ComCertSelParams_GetBasicConstraints
618                 (params, &minPathLen, plContext),
619                 PKIX_COMCERTSELPARAMSGETBASICCONSTRAINTSFAILED);
620 
621         if (subjectName) {
622                 PKIX_CHECK(pkix_pl_LdapCertStore_MakeNameAVAList
623                         (requestArena,
624                         subjectName,
625                         &(requestParams.nc),
626                         plContext),
627                         PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED);
628 
629                 if (*requestParams.nc == NULL) {
630                         /*
631                          * The subjectName may not include any components
632                          * that we know how to encode. We do not return
633                          * an error, because the caller did not necessarily
634                          * do anything wrong, but we return an empty List.
635                          */
636                         PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
637                                 (requestArena, PR_FALSE));
638 
639                         PKIX_CHECK(PKIX_List_Create(&filteredCerts, plContext),
640                                 PKIX_LISTCREATEFAILED);
641 
642                         PKIX_CHECK(PKIX_List_SetImmutable
643                                 (filteredCerts, plContext),
644                                 PKIX_LISTSETIMMUTABLEFAILED);
645 
646                         *pNBIOContext = NULL;
647                         *pCertList = filteredCerts;
648                         filteredCerts = NULL;
649                         goto cleanup;
650                 }
651         } else {
652                 PKIX_ERROR(PKIX_INSUFFICIENTCRITERIAFORCERTQUERY);
653         }
654 
655         /* Prepare attribute field of request */
656 
657         requestParams.attributes = 0;
658 
659         if (minPathLen < 0) {
660                 requestParams.attributes |= LDAPATTR_USERCERT;
661         }
662 
663         if (minPathLen > -2) {
664                 requestParams.attributes |=
665                         LDAPATTR_CACERT | LDAPATTR_CROSSPAIRCERT;
666         }
667 
668         /* All request fields are done */
669 
670         PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
671                 (store, (PKIX_PL_Object **)&lcs, plContext),
672                 PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
673 
674         PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
675                 ((PKIX_PL_LdapClient *)lcs,
676                 &requestParams,
677                 &pollDesc,
678                 &responses,
679                 plContext),
680                 PKIX_LDAPCLIENTINITIATEREQUESTFAILED);
681 
682         PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList
683                 (requestParams.nc, plContext),
684                 PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED);
685 
686         if (requestArena) {
687                 PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
688                         (requestArena, PR_FALSE));
689                 requestArena = NULL;
690         }
691 
692         if (pollDesc != NULL) {
693                 /* client is waiting for non-blocking I/O to complete */
694                 *pNBIOContext = (void *)pollDesc;
695                 *pCertList = NULL;
696                 goto cleanup;
697         }
698         /* LdapClient has given us a response! */
699 
700         if (responses) {
701                 PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
702                         (store, &cacheFlag, plContext),
703                         PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);
704 
705                 PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
706                         (responses, &unfilteredCerts, plContext),
707                         PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);
708 
709                 PKIX_CHECK(pkix_CertSelector_Select
710                         (selector, unfilteredCerts, &filteredCerts, plContext),
711                         PKIX_CERTSELECTORSELECTFAILED);
712         }
713 
714         *pNBIOContext = NULL;
715         *pCertList = filteredCerts;
716         filteredCerts = NULL;
717 
718 cleanup:
719 
720         PKIX_DECREF(params);
721         PKIX_DECREF(subjectName);
722         PKIX_DECREF(responses);
723         PKIX_DECREF(unfilteredCerts);
724         PKIX_DECREF(filteredCerts);
725         PKIX_DECREF(lcs);
726 
727         PKIX_RETURN(CERTSTORE);
728 }
729 
730 /*
731  * FUNCTION: pkix_pl_LdapCertStore_GetCertContinue
732  *  (see description of PKIX_CertStore_CertCallback in pkix_certstore.h)
733  */
734 PKIX_Error *
pkix_pl_LdapCertStore_GetCertContinue(PKIX_CertStore * store,PKIX_CertSelector * selector,PKIX_VerifyNode * verifyNode,void ** pNBIOContext,PKIX_List ** pCertList,void * plContext)735 pkix_pl_LdapCertStore_GetCertContinue(
736         PKIX_CertStore *store,
737         PKIX_CertSelector *selector,
738         PKIX_VerifyNode *verifyNode,
739         void **pNBIOContext,
740         PKIX_List **pCertList,
741         void *plContext)
742 {
743         PKIX_Boolean cacheFlag = PKIX_FALSE;
744         PKIX_PL_LdapCertStoreContext *lcs = NULL;
745         void *pollDesc = NULL;
746         PKIX_List *responses = NULL;
747         PKIX_List *unfilteredCerts = NULL;
748         PKIX_List *filteredCerts = NULL;
749 
750         PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCertContinue");
751         PKIX_NULLCHECK_THREE(store, selector, pCertList);
752 
753         PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
754                 (store, (PKIX_PL_Object **)&lcs, plContext),
755                 PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
756 
757         PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest
758                 ((PKIX_PL_LdapClient *)lcs, &pollDesc, &responses, plContext),
759                 PKIX_LDAPCLIENTRESUMEREQUESTFAILED);
760 
761         if (pollDesc != NULL) {
762                 /* client is waiting for non-blocking I/O to complete */
763                 *pNBIOContext = (void *)pollDesc;
764                 *pCertList = NULL;
765                 goto cleanup;
766         }
767         /* LdapClient has given us a response! */
768 
769         if (responses) {
770                 PKIX_CHECK(PKIX_CertStore_GetCertStoreCacheFlag
771                         (store, &cacheFlag, plContext),
772                         PKIX_CERTSTOREGETCERTSTORECACHEFLAGFAILED);
773 
774                 PKIX_CHECK(pkix_pl_LdapCertStore_BuildCertList
775                         (responses, &unfilteredCerts, plContext),
776                         PKIX_LDAPCERTSTOREBUILDCERTLISTFAILED);
777 
778                 PKIX_CHECK(pkix_CertSelector_Select
779                         (selector, unfilteredCerts, &filteredCerts, plContext),
780                         PKIX_CERTSELECTORSELECTFAILED);
781         }
782 
783         *pNBIOContext = NULL;
784         *pCertList = filteredCerts;
785 
786 cleanup:
787 
788         PKIX_DECREF(responses);
789         PKIX_DECREF(unfilteredCerts);
790         PKIX_DECREF(lcs);
791 
792         PKIX_RETURN(CERTSTORE);
793 }
794 
795 /*
796  * FUNCTION: pkix_pl_LdapCertStore_GetCRL
797  *  (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
798  */
799 PKIX_Error *
pkix_pl_LdapCertStore_GetCRL(PKIX_CertStore * store,PKIX_CRLSelector * selector,void ** pNBIOContext,PKIX_List ** pCrlList,void * plContext)800 pkix_pl_LdapCertStore_GetCRL(
801         PKIX_CertStore *store,
802         PKIX_CRLSelector *selector,
803         void **pNBIOContext,
804         PKIX_List **pCrlList,
805         void *plContext)
806 {
807         LDAPRequestParams requestParams;
808         void *pollDesc = NULL;
809         PLArenaPool *requestArena = NULL;
810         PKIX_UInt32 numNames = 0;
811         PKIX_UInt32 thisName = 0;
812         PKIX_PL_CRL *candidate = NULL;
813         PKIX_List *responses = NULL;
814         PKIX_List *issuerNames = NULL;
815         PKIX_List *filteredCRLs = NULL;
816         PKIX_List *unfilteredCRLs = NULL;
817         PKIX_PL_X500Name *issuer = NULL;
818         PKIX_PL_LdapCertStoreContext *lcs = NULL;
819         PKIX_ComCRLSelParams *params = NULL;
820 
821         PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCRL");
822         PKIX_NULLCHECK_THREE(store, selector, pCrlList);
823 
824         requestParams.baseObject = "c=US";
825         requestParams.scope = WHOLE_SUBTREE;
826         requestParams.derefAliases = NEVER_DEREF;
827         requestParams.sizeLimit = 0;
828         requestParams.timeLimit = 0;
829         requestParams.attributes = LDAPATTR_CERTREVLIST | LDAPATTR_AUTHREVLIST;
830         /* Prepare elements for request filter */
831 
832         /* XXX Place CRLDP code here. Handle the case when */
833         /* RFC 5280. Paragraph: 4.2.1.13: */
834         /* If the distributionPoint field contains a directoryName, the entry */
835         /* for that directoryName contains the current CRL for the associated */
836         /* reasons and the CRL is issued by the associated cRLIssuer.  The CRL */
837         /* may be stored in either the certificateRevocationList or */
838         /* authorityRevocationList attribute.  The CRL is to be obtained by the */
839         /* application from whatever directory server is locally configured. */
840         /* The protocol the application uses to access the directory (e.g., DAP */
841         /* or LDAP) is a local matter. */
842 
843 
844 
845         /*
846          * Get a short-lived arena. We'll be done with this space once
847          * the request is encoded.
848          */
849         PKIX_PL_NSSCALLRV
850             (CERTSTORE, requestArena, PORT_NewArena, (DER_DEFAULT_CHUNKSIZE));
851 
852         if (!requestArena) {
853                 PKIX_ERROR_FATAL(PKIX_OUTOFMEMORY);
854         }
855 
856         PKIX_CHECK(PKIX_CRLSelector_GetCommonCRLSelectorParams
857                 (selector, &params, plContext),
858                 PKIX_CRLSELECTORGETCOMCERTSELPARAMSFAILED);
859 
860         PKIX_CHECK(PKIX_ComCRLSelParams_GetIssuerNames
861                 (params, &issuerNames, plContext),
862                 PKIX_COMCRLSELPARAMSGETISSUERNAMESFAILED);
863 
864         /*
865          * The specification for PKIX_ComCRLSelParams_GetIssuerNames in
866          * pkix_crlsel.h says that if the criterion is not set we get a null
867          * pointer. If we get an empty List the criterion is impossible to
868          * meet ("must match at least one of the names in the List").
869          */
870         if (issuerNames) {
871 
872                 PKIX_CHECK(PKIX_List_GetLength
873                         (issuerNames, &numNames, plContext),
874                         PKIX_LISTGETLENGTHFAILED);
875 
876                 if (numNames > 0) {
877                         for (thisName = 0; thisName < numNames; thisName++) {
878                                 PKIX_CHECK(PKIX_List_GetItem
879                                 (issuerNames,
880                                 thisName,
881                                 (PKIX_PL_Object **)&issuer,
882                                 plContext),
883                                 PKIX_LISTGETITEMFAILED);
884 
885                                 PKIX_CHECK
886                                         (pkix_pl_LdapCertStore_MakeNameAVAList
887                                         (requestArena,
888                                         issuer,
889                                         &(requestParams.nc),
890                                         plContext),
891                                         PKIX_LDAPCERTSTOREMAKENAMEAVALISTFAILED);
892 
893                                 PKIX_DECREF(issuer);
894 
895                                 if (*requestParams.nc == NULL) {
896                                         /*
897                                          * The issuer may not include any
898                                          * components that we know how to
899                                          * encode. We do not return an error,
900                                          * because the caller did not
901                                          * necessarily do anything wrong, but
902                                          * we return an empty List.
903                                          */
904                                         PKIX_PL_NSSCALL
905                                                 (CERTSTORE, PORT_FreeArena,
906                                                 (requestArena, PR_FALSE));
907 
908                                         PKIX_CHECK(PKIX_List_Create
909                                                 (&filteredCRLs, plContext),
910                                                 PKIX_LISTCREATEFAILED);
911 
912                                         PKIX_CHECK(PKIX_List_SetImmutable
913                                                 (filteredCRLs, plContext),
914                                                PKIX_LISTSETIMMUTABLEFAILED);
915 
916                                         *pNBIOContext = NULL;
917                                         *pCrlList = filteredCRLs;
918                                         goto cleanup;
919                                 }
920 
921                                 /*
922                                  * LDAP Servers don't seem to be able to handle
923                                  * requests with more than more than one name.
924                                  */
925                                 break;
926                         }
927                 } else {
928                         PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY);
929                 }
930         } else {
931                 PKIX_ERROR(PKIX_IMPOSSIBLECRITERIONFORCRLQUERY);
932         }
933 
934         /* All request fields are done */
935 
936         PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
937                 (store, (PKIX_PL_Object **)&lcs, plContext),
938                 PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
939 
940         PKIX_CHECK(PKIX_PL_LdapClient_InitiateRequest
941                 ((PKIX_PL_LdapClient *)lcs,
942                 &requestParams,
943                 &pollDesc,
944                 &responses,
945                 plContext),
946                 PKIX_LDAPCLIENTINITIATEREQUESTFAILED);
947 
948         PKIX_CHECK(pkix_pl_LdapCertStore_DestroyAVAList
949                 (requestParams.nc, plContext),
950                 PKIX_LDAPCERTSTOREDESTROYAVALISTFAILED);
951 
952         if (requestArena) {
953                 PKIX_PL_NSSCALL(CERTSTORE, PORT_FreeArena,
954                         (requestArena, PR_FALSE));
955         }
956 
957         if (pollDesc != NULL) {
958                 /* client is waiting for non-blocking I/O to complete */
959                 *pNBIOContext = (void *)pollDesc;
960                 *pCrlList = NULL;
961                 goto cleanup;
962         }
963         /* client has finished! */
964 
965         if (responses) {
966 
967                 /*
968                  * We have a List of LdapResponse objects that still have to be
969                  * turned into Crls.
970                  */
971                 PKIX_CHECK(pkix_pl_LdapCertStore_BuildCrlList
972                         (responses, &unfilteredCRLs, plContext),
973                         PKIX_LDAPCERTSTOREBUILDCRLLISTFAILED);
974 
975                 PKIX_CHECK(pkix_CRLSelector_Select
976                         (selector, unfilteredCRLs, &filteredCRLs, plContext),
977                         PKIX_CRLSELECTORSELECTFAILED);
978 
979         }
980 
981         /* Don't throw away the list if one CRL was bad! */
982         pkixTempErrorReceived = PKIX_FALSE;
983 
984         *pNBIOContext = NULL;
985         *pCrlList = filteredCRLs;
986 
987 cleanup:
988 
989         if (PKIX_ERROR_RECEIVED) {
990                 PKIX_DECREF(filteredCRLs);
991         }
992 
993         PKIX_DECREF(params);
994         PKIX_DECREF(issuerNames);
995         PKIX_DECREF(issuer);
996         PKIX_DECREF(candidate);
997         PKIX_DECREF(responses);
998         PKIX_DECREF(unfilteredCRLs);
999         PKIX_DECREF(lcs);
1000 
1001         PKIX_RETURN(CERTSTORE);
1002 }
1003 
1004 /*
1005  * FUNCTION: pkix_pl_LdapCertStore_GetCRLContinue
1006  *  (see description of PKIX_CertStore_CRLCallback in pkix_certstore.h)
1007  */
1008 PKIX_Error *
pkix_pl_LdapCertStore_GetCRLContinue(PKIX_CertStore * store,PKIX_CRLSelector * selector,void ** pNBIOContext,PKIX_List ** pCrlList,void * plContext)1009 pkix_pl_LdapCertStore_GetCRLContinue(
1010         PKIX_CertStore *store,
1011         PKIX_CRLSelector *selector,
1012         void **pNBIOContext,
1013         PKIX_List **pCrlList,
1014         void *plContext)
1015 {
1016         void *nbio = NULL;
1017         PKIX_PL_CRL *candidate = NULL;
1018         PKIX_List *responses = NULL;
1019         PKIX_PL_LdapCertStoreContext *lcs = NULL;
1020         PKIX_List *filteredCRLs = NULL;
1021         PKIX_List *unfilteredCRLs = NULL;
1022 
1023         PKIX_ENTER(CERTSTORE, "pkix_pl_LdapCertStore_GetCRLContinue");
1024         PKIX_NULLCHECK_FOUR(store, selector, pNBIOContext, pCrlList);
1025 
1026         PKIX_CHECK(PKIX_CertStore_GetCertStoreContext
1027                 (store, (PKIX_PL_Object **)&lcs, plContext),
1028                 PKIX_CERTSTOREGETCERTSTORECONTEXTFAILED);
1029 
1030         PKIX_CHECK(PKIX_PL_LdapClient_ResumeRequest
1031                 ((PKIX_PL_LdapClient *)lcs, &nbio, &responses, plContext),
1032                 PKIX_LDAPCLIENTRESUMEREQUESTFAILED);
1033 
1034         if (nbio != NULL) {
1035                 /* client is waiting for non-blocking I/O to complete */
1036                 *pNBIOContext = (void *)nbio;
1037                 *pCrlList = NULL;
1038                 goto cleanup;
1039         }
1040         /* client has finished! */
1041 
1042         if (responses) {
1043 
1044                 /*
1045                  * We have a List of LdapResponse objects that still have to be
1046                  * turned into Crls.
1047                  */
1048                 PKIX_CHECK(pkix_pl_LdapCertStore_BuildCrlList
1049                         (responses, &unfilteredCRLs, plContext),
1050                         PKIX_LDAPCERTSTOREBUILDCRLLISTFAILED);
1051 
1052                 PKIX_CHECK(pkix_CRLSelector_Select
1053                         (selector, unfilteredCRLs, &filteredCRLs, plContext),
1054                         PKIX_CRLSELECTORSELECTFAILED);
1055 
1056                 PKIX_CHECK(PKIX_List_SetImmutable(filteredCRLs, plContext),
1057                         PKIX_LISTSETIMMUTABLEFAILED);
1058 
1059         }
1060 
1061         /* Don't throw away the list if one CRL was bad! */
1062         pkixTempErrorReceived = PKIX_FALSE;
1063 
1064         *pCrlList = filteredCRLs;
1065 
1066 cleanup:
1067         if (PKIX_ERROR_RECEIVED) {
1068                 PKIX_DECREF(filteredCRLs);
1069         }
1070 
1071         PKIX_DECREF(candidate);
1072         PKIX_DECREF(responses);
1073         PKIX_DECREF(unfilteredCRLs);
1074         PKIX_DECREF(lcs);
1075 
1076         PKIX_RETURN(CERTSTORE);
1077 }
1078 
1079 /* --Public-LdapCertStore-Functions----------------------------------- */
1080 
1081 /*
1082  * FUNCTION: PKIX_PL_LdapCertStore_Create
1083  * (see comments in pkix_samples_modules.h)
1084  */
1085 PKIX_Error *
PKIX_PL_LdapCertStore_Create(PKIX_PL_LdapClient * client,PKIX_CertStore ** pCertStore,void * plContext)1086 PKIX_PL_LdapCertStore_Create(
1087         PKIX_PL_LdapClient *client,
1088         PKIX_CertStore **pCertStore,
1089         void *plContext)
1090 {
1091         PKIX_CertStore *certStore = NULL;
1092 
1093         PKIX_ENTER(CERTSTORE, "PKIX_PL_LdapCertStore_Create");
1094         PKIX_NULLCHECK_TWO(client, pCertStore);
1095 
1096         PKIX_CHECK(PKIX_CertStore_Create
1097                 (pkix_pl_LdapCertStore_GetCert,
1098                 pkix_pl_LdapCertStore_GetCRL,
1099                 pkix_pl_LdapCertStore_GetCertContinue,
1100                 pkix_pl_LdapCertStore_GetCRLContinue,
1101                 NULL,       /* don't support trust */
1102                 NULL,      /* can not store crls */
1103                 NULL,      /* can not do revocation check */
1104                 (PKIX_PL_Object *)client,
1105                 PKIX_TRUE,  /* cache flag */
1106                 PKIX_FALSE, /* not local */
1107                 &certStore,
1108                 plContext),
1109                 PKIX_CERTSTORECREATEFAILED);
1110 
1111         *pCertStore = certStore;
1112 
1113 cleanup:
1114 
1115         PKIX_RETURN(CERTSTORE);
1116 }
1117