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_ldaprequest.c
6  *
7  */
8 
9 #include "pkix_pl_ldaprequest.h"
10 
11 /* --Private-LdapRequest-Functions------------------------------------- */
12 
13 /* Note: lengths do not include the NULL terminator */
14 static const char caAttr[] = "caCertificate;binary";
15 static unsigned int caAttrLen = sizeof(caAttr) - 1;
16 static const char uAttr[] = "userCertificate;binary";
17 static unsigned int uAttrLen = sizeof(uAttr) - 1;
18 static const char ccpAttr[] = "crossCertificatePair;binary";
19 static unsigned int ccpAttrLen = sizeof(ccpAttr) - 1;
20 static const char crlAttr[] = "certificateRevocationList;binary";
21 static unsigned int crlAttrLen = sizeof(crlAttr) - 1;
22 static const char arlAttr[] = "authorityRevocationList;binary";
23 static unsigned int arlAttrLen = sizeof(arlAttr) - 1;
24 
25 /*
26  * XXX If this function were moved into pkix_pl_ldapcertstore.c then all of
27  * LdapRequest and LdapResponse could be considered part of the LDAP client.
28  * But the constants, above, would have to be copied as well, and they are
29  * also needed in pkix_pl_LdapRequest_EncodeAttrs. So there would have to be
30  * two copies.
31  */
32 
33 /*
34  * FUNCTION: pkix_pl_LdapRequest_AttrTypeToBit
35  * DESCRIPTION:
36  *
37  *  This function creates an attribute mask bit corresponding to the SECItem
38  *  pointed to by "attrType", storing the result at "pAttrBit". The comparison
39  *  is case-insensitive. If "attrType" does not match any of the known types,
40  *  zero is stored at "pAttrBit".
41  *
42  * PARAMETERS
43  *  "attrType"
44  *      The address of the SECItem whose string contents are to be compared to
45  *      the various known attribute types. Must be non-NULL.
46  *  "pAttrBit"
47  *      The address where the result is stored. Must be 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 an LdapRequest Error if the function fails in a non-fatal way.
55  *  Returns a Fatal Error if the function fails in an unrecoverable way.
56  */
57 PKIX_Error *
pkix_pl_LdapRequest_AttrTypeToBit(SECItem * attrType,LdapAttrMask * pAttrBit,void * plContext)58 pkix_pl_LdapRequest_AttrTypeToBit(
59         SECItem *attrType,
60         LdapAttrMask *pAttrBit,
61         void *plContext)
62 {
63         LdapAttrMask attrBit = 0;
64         unsigned int attrLen = 0;
65         const char *s = NULL;
66 
67         PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrTypeToBit");
68         PKIX_NULLCHECK_TWO(attrType, pAttrBit);
69 
70         s = (const char *)attrType->data;
71         attrLen = attrType->len;
72 
73         /*
74          * Taking note of the fact that all of the comparand strings are
75          * different lengths, we do a slight optimization. If a string
76          * length matches but the string does not match, we skip comparing
77          * to the other strings. If new strings are added to the comparand
78          * list, and any are of equal length, be careful to change the
79          * grouping of tests accordingly.
80          */
81         if (attrLen == caAttrLen) {
82                 if (PORT_Strncasecmp(caAttr, s, attrLen) == 0) {
83                         attrBit = LDAPATTR_CACERT;
84                 }
85         } else if (attrLen == uAttrLen) {
86                 if (PORT_Strncasecmp(uAttr, s, attrLen) == 0) {
87                         attrBit = LDAPATTR_USERCERT;
88                 }
89         } else if (attrLen == ccpAttrLen) {
90                 if (PORT_Strncasecmp(ccpAttr, s, attrLen) == 0) {
91                         attrBit = LDAPATTR_CROSSPAIRCERT;
92                 }
93         } else if (attrLen == crlAttrLen) {
94                 if (PORT_Strncasecmp(crlAttr, s, attrLen) == 0) {
95                         attrBit = LDAPATTR_CERTREVLIST;
96                 }
97         } else if (attrLen == arlAttrLen) {
98                 if (PORT_Strncasecmp(arlAttr, s, attrLen) == 0) {
99                         attrBit = LDAPATTR_AUTHREVLIST;
100                 }
101         }
102 
103         *pAttrBit = attrBit;
104 
105         PKIX_RETURN(LDAPREQUEST);
106 }
107 
108 /*
109  * FUNCTION: pkix_pl_LdapRequest_AttrStringToBit
110  * DESCRIPTION:
111  *
112  *  This function creates an attribute mask bit corresponding to the null-
113  *  terminated string pointed to by "attrString", storing the result at
114  *  "pAttrBit". The comparison is case-insensitive. If "attrString" does not
115  *  match any of the known types, zero is stored at "pAttrBit".
116  *
117  * PARAMETERS
118  *  "attrString"
119  *      The address of the null-terminated string whose contents are to be compared to
120  *      the various known attribute types. Must be non-NULL.
121  *  "pAttrBit"
122  *      The address where the result is stored. Must be non-NULL.
123  *  "plContext"
124  *      Platform-specific context pointer.
125  * THREAD SAFETY:
126  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
127  * RETURNS:
128  *  Returns NULL if the function succeeds.
129  *  Returns an LdapRequest Error if the function fails in a non-fatal way.
130  *  Returns a Fatal Error if the function fails in an unrecoverable way.
131  */
132 PKIX_Error *
pkix_pl_LdapRequest_AttrStringToBit(char * attrString,LdapAttrMask * pAttrBit,void * plContext)133 pkix_pl_LdapRequest_AttrStringToBit(
134         char *attrString,
135         LdapAttrMask *pAttrBit,
136         void *plContext)
137 {
138         LdapAttrMask attrBit = 0;
139         unsigned int attrLen = 0;
140 
141         PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrStringToBit");
142         PKIX_NULLCHECK_TWO(attrString, pAttrBit);
143 
144         attrLen = PL_strlen(attrString);
145 
146         /*
147          * Taking note of the fact that all of the comparand strings are
148          * different lengths, we do a slight optimization. If a string
149          * length matches but the string does not match, we skip comparing
150          * to the other strings. If new strings are added to the comparand
151          * list, and any are of equal length, be careful to change the
152          * grouping of tests accordingly.
153          */
154         if (attrLen == caAttrLen) {
155                 if (PORT_Strncasecmp(caAttr, attrString, attrLen) == 0) {
156                         attrBit = LDAPATTR_CACERT;
157                 }
158         } else if (attrLen == uAttrLen) {
159                 if (PORT_Strncasecmp(uAttr, attrString, attrLen) == 0) {
160                         attrBit = LDAPATTR_USERCERT;
161                 }
162         } else if (attrLen == ccpAttrLen) {
163                 if (PORT_Strncasecmp(ccpAttr, attrString, attrLen) == 0) {
164                         attrBit = LDAPATTR_CROSSPAIRCERT;
165                 }
166         } else if (attrLen == crlAttrLen) {
167                 if (PORT_Strncasecmp(crlAttr, attrString, attrLen) == 0) {
168                         attrBit = LDAPATTR_CERTREVLIST;
169                 }
170         } else if (attrLen == arlAttrLen) {
171                 if (PORT_Strncasecmp(arlAttr, attrString, attrLen) == 0) {
172                         attrBit = LDAPATTR_AUTHREVLIST;
173                 }
174         }
175 
176         *pAttrBit = attrBit;
177 
178         PKIX_RETURN(LDAPREQUEST);
179 }
180 
181 /*
182  * FUNCTION: pkix_pl_LdapRequest_EncodeAttrs
183  * DESCRIPTION:
184  *
185  *  This function obtains the attribute mask bits from the LdapRequest pointed
186  *  to by "request", creates the corresponding array of AttributeTypes for the
187  *  encoding of the SearchRequest message.
188  *
189  * PARAMETERS
190  *  "request"
191  *      The address of the LdapRequest whose attributes are to be encoded. Must
192  *      be non-NULL.
193  *  "plContext"
194  *      Platform-specific context pointer.
195  * THREAD SAFETY:
196  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
197  * RETURNS:
198  *  Returns NULL if the function succeeds.
199  *  Returns an LdapRequest Error if the function fails in a non-fatal way.
200  *  Returns a Fatal Error if the function fails in an unrecoverable way.
201  */
202 static PKIX_Error *
pkix_pl_LdapRequest_EncodeAttrs(PKIX_PL_LdapRequest * request,void * plContext)203 pkix_pl_LdapRequest_EncodeAttrs(
204         PKIX_PL_LdapRequest *request,
205         void *plContext)
206 {
207         SECItem **attrArray = NULL;
208         PKIX_UInt32 attrIndex = 0;
209         LdapAttrMask attrBits;
210 
211         PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_EncodeAttrs");
212         PKIX_NULLCHECK_ONE(request);
213 
214         /* construct "attrs" according to bits in request->attrBits */
215         attrBits = request->attrBits;
216         attrArray = request->attrArray;
217         if ((attrBits & LDAPATTR_CACERT) == LDAPATTR_CACERT) {
218                 attrArray[attrIndex] = &(request->attributes[attrIndex]);
219                 request->attributes[attrIndex].type = siAsciiString;
220                 request->attributes[attrIndex].data = (unsigned char *)caAttr;
221                 request->attributes[attrIndex].len = caAttrLen;
222                 attrIndex++;
223         }
224         if ((attrBits & LDAPATTR_USERCERT) == LDAPATTR_USERCERT) {
225                 attrArray[attrIndex] = &(request->attributes[attrIndex]);
226                 request->attributes[attrIndex].type = siAsciiString;
227                 request->attributes[attrIndex].data = (unsigned char *)uAttr;
228                 request->attributes[attrIndex].len = uAttrLen;
229                 attrIndex++;
230         }
231         if ((attrBits & LDAPATTR_CROSSPAIRCERT) == LDAPATTR_CROSSPAIRCERT) {
232                 attrArray[attrIndex] = &(request->attributes[attrIndex]);
233                 request->attributes[attrIndex].type = siAsciiString;
234                 request->attributes[attrIndex].data = (unsigned char *)ccpAttr;
235                 request->attributes[attrIndex].len = ccpAttrLen;
236                 attrIndex++;
237         }
238         if ((attrBits & LDAPATTR_CERTREVLIST) == LDAPATTR_CERTREVLIST) {
239                 attrArray[attrIndex] = &(request->attributes[attrIndex]);
240                 request->attributes[attrIndex].type = siAsciiString;
241                 request->attributes[attrIndex].data = (unsigned char *)crlAttr;
242                 request->attributes[attrIndex].len = crlAttrLen;
243                 attrIndex++;
244         }
245         if ((attrBits & LDAPATTR_AUTHREVLIST) == LDAPATTR_AUTHREVLIST) {
246                 attrArray[attrIndex] = &(request->attributes[attrIndex]);
247                 request->attributes[attrIndex].type = siAsciiString;
248                 request->attributes[attrIndex].data = (unsigned char *)arlAttr;
249                 request->attributes[attrIndex].len = arlAttrLen;
250                 attrIndex++;
251         }
252         attrArray[attrIndex] = (SECItem *)NULL;
253 
254         PKIX_RETURN(LDAPREQUEST);
255 }
256 
257 /*
258  * FUNCTION: pkix_pl_LdapRequest_Destroy
259  * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
260  */
261 static PKIX_Error *
pkix_pl_LdapRequest_Destroy(PKIX_PL_Object * object,void * plContext)262 pkix_pl_LdapRequest_Destroy(
263         PKIX_PL_Object *object,
264         void *plContext)
265 {
266         PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Destroy");
267         PKIX_NULLCHECK_ONE(object);
268 
269         PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext),
270                     PKIX_OBJECTNOTLDAPREQUEST);
271 
272         /*
273          * All dynamic fields in an LDAPRequest are allocated
274          * in an arena, and will be freed when the arena is destroyed.
275          */
276 
277 cleanup:
278 
279         PKIX_RETURN(LDAPREQUEST);
280 }
281 
282 /*
283  * FUNCTION: pkix_pl_LdapRequest_Hashcode
284  * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
285  */
286 static PKIX_Error *
pkix_pl_LdapRequest_Hashcode(PKIX_PL_Object * object,PKIX_UInt32 * pHashcode,void * plContext)287 pkix_pl_LdapRequest_Hashcode(
288         PKIX_PL_Object *object,
289         PKIX_UInt32 *pHashcode,
290         void *plContext)
291 {
292         PKIX_UInt32 dataLen = 0;
293         PKIX_UInt32 dindex = 0;
294         PKIX_UInt32 sizeOfLength = 0;
295         PKIX_UInt32 idLen = 0;
296         const unsigned char *msgBuf = NULL;
297         PKIX_PL_LdapRequest *ldapRq = NULL;
298 
299         PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Hashcode");
300         PKIX_NULLCHECK_TWO(object, pHashcode);
301 
302         PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext),
303                     PKIX_OBJECTNOTLDAPREQUEST);
304 
305         ldapRq = (PKIX_PL_LdapRequest *)object;
306 
307         *pHashcode = 0;
308 
309         /*
310          * Two requests that differ only in msgnum are a match! Therefore,
311          * start hashcoding beyond the encoded messageID field.
312          */
313         if (ldapRq->encoded) {
314                 msgBuf = (const unsigned char *)ldapRq->encoded->data;
315                 /* Is message length short form (one octet) or long form? */
316                 if ((msgBuf[1] & 0x80) != 0) {
317                         sizeOfLength = msgBuf[1] & 0x7F;
318                         for (dindex = 0; dindex < sizeOfLength; dindex++) {
319                                 dataLen = (dataLen << 8) + msgBuf[dindex + 2];
320                         }
321                 } else {
322                         dataLen = msgBuf[1];
323                 }
324 
325                 /* How many bytes for the messageID? (Assume short form) */
326                 idLen = msgBuf[dindex + 3] + 2;
327                 dindex += idLen;
328                 dataLen -= idLen;
329                 msgBuf = &msgBuf[dindex + 2];
330 
331                 PKIX_CHECK(pkix_hash(msgBuf, dataLen, pHashcode, plContext),
332                         PKIX_HASHFAILED);
333         }
334 
335 cleanup:
336 
337         PKIX_RETURN(LDAPREQUEST);
338 
339 }
340 
341 /*
342  * FUNCTION: pkix_pl_LdapRequest_Equals
343  * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
344  */
345 static PKIX_Error *
pkix_pl_LdapRequest_Equals(PKIX_PL_Object * firstObj,PKIX_PL_Object * secondObj,PKIX_Boolean * pResult,void * plContext)346 pkix_pl_LdapRequest_Equals(
347         PKIX_PL_Object *firstObj,
348         PKIX_PL_Object *secondObj,
349         PKIX_Boolean *pResult,
350         void *plContext)
351 {
352         PKIX_PL_LdapRequest *firstReq = NULL;
353         PKIX_PL_LdapRequest *secondReq = NULL;
354         PKIX_UInt32 secondType = 0;
355         PKIX_UInt32 firstLen = 0;
356         const unsigned char *firstData = NULL;
357         const unsigned char *secondData = NULL;
358         PKIX_UInt32 sizeOfLength = 0;
359         PKIX_UInt32 dindex = 0;
360         PKIX_UInt32 i = 0;
361 
362         PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Equals");
363         PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
364 
365         /* test that firstObj is a LdapRequest */
366         PKIX_CHECK(pkix_CheckType(firstObj, PKIX_LDAPREQUEST_TYPE, plContext),
367                     PKIX_FIRSTOBJARGUMENTNOTLDAPREQUEST);
368 
369         /*
370          * Since we know firstObj is a LdapRequest, if both references are
371          * identical, they must be equal
372          */
373         if (firstObj == secondObj){
374                 *pResult = PKIX_TRUE;
375                 goto cleanup;
376         }
377 
378         /*
379          * If secondObj isn't a LdapRequest, we don't throw an error.
380          * We simply return a Boolean result of FALSE
381          */
382         *pResult = PKIX_FALSE;
383         PKIX_CHECK(PKIX_PL_Object_GetType
384                     (secondObj, &secondType, plContext),
385                     PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
386         if (secondType != PKIX_LDAPREQUEST_TYPE) {
387                 goto cleanup;
388         }
389 
390         firstReq = (PKIX_PL_LdapRequest *)firstObj;
391         secondReq = (PKIX_PL_LdapRequest *)secondObj;
392 
393         /* If either lacks an encoded string, they cannot be compared */
394         if (!(firstReq->encoded) || !(secondReq->encoded)) {
395                 goto cleanup;
396         }
397 
398         if (firstReq->encoded->len != secondReq->encoded->len) {
399                 goto cleanup;
400         }
401 
402         firstData = (const unsigned char *)firstReq->encoded->data;
403         secondData = (const unsigned char *)secondReq->encoded->data;
404 
405         /*
406          * Two requests that differ only in msgnum are equal! Therefore,
407          * start the byte comparison beyond the encoded messageID field.
408          */
409 
410         /* Is message length short form (one octet) or long form? */
411         if ((firstData[1] & 0x80) != 0) {
412                 sizeOfLength = firstData[1] & 0x7F;
413                 for (dindex = 0; dindex < sizeOfLength; dindex++) {
414                         firstLen = (firstLen << 8) + firstData[dindex + 2];
415                 }
416         } else {
417                 firstLen = firstData[1];
418         }
419 
420         /* How many bytes for the messageID? (Assume short form) */
421         i = firstData[dindex + 3] + 2;
422         dindex += i;
423         firstLen -= i;
424         firstData = &firstData[dindex + 2];
425 
426         /*
427          * In theory, we have to calculate where the second message data
428          * begins by checking its length encodings. But if these messages
429          * are equal, we can re-use the calculation we already did. If they
430          * are not equal, the byte comparisons will surely fail.
431          */
432 
433         secondData = &secondData[dindex + 2];
434 
435         for (i = 0; i < firstLen; i++) {
436                 if (firstData[i] != secondData[i]) {
437                         goto cleanup;
438                 }
439         }
440 
441         *pResult = PKIX_TRUE;
442 
443 cleanup:
444 
445         PKIX_RETURN(LDAPREQUEST);
446 }
447 
448 /*
449  * FUNCTION: pkix_pl_LdapRequest_RegisterSelf
450  * DESCRIPTION:
451  *  Registers PKIX_LDAPREQUEST_TYPE and its related functions with
452  *  systemClasses[]
453  * PARAMETERS:
454  *  "plContext"
455  *      Platform-specific context pointer.
456  * THREAD SAFETY:
457  *  Not Thread Safe - for performance and complexity reasons
458  *
459  *  Since this function is only called by PKIX_PL_Initialize, which should
460  *  only be called once, it is acceptable that this function is not
461  *  thread-safe.
462  */
463 PKIX_Error *
pkix_pl_LdapRequest_RegisterSelf(void * plContext)464 pkix_pl_LdapRequest_RegisterSelf(void *plContext)
465 {
466         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
467         pkix_ClassTable_Entry entry;
468 
469         PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_RegisterSelf");
470 
471         entry.description = "LdapRequest";
472         entry.objCounter = 0;
473         entry.typeObjectSize = sizeof(PKIX_PL_LdapRequest);
474         entry.destructor = pkix_pl_LdapRequest_Destroy;
475         entry.equalsFunction = pkix_pl_LdapRequest_Equals;
476         entry.hashcodeFunction = pkix_pl_LdapRequest_Hashcode;
477         entry.toStringFunction = NULL;
478         entry.comparator = NULL;
479         entry.duplicateFunction = pkix_duplicateImmutable;
480 
481         systemClasses[PKIX_LDAPREQUEST_TYPE] = entry;
482 
483         PKIX_RETURN(LDAPREQUEST);
484 }
485 
486 /* --Public-Functions------------------------------------------------------- */
487 
488 /*
489  * FUNCTION: pkix_pl_LdapRequest_Create
490  * DESCRIPTION:
491  *
492  *  This function creates an LdapRequest using the PLArenaPool pointed to by
493  *  "arena", a message number whose value is "msgnum", a base object pointed to
494  *  by "issuerDN", a scope whose value is "scope", a derefAliases flag whose
495  *  value is "derefAliases", a sizeLimit whose value is "sizeLimit", a timeLimit
496  *  whose value is "timeLimit", an attrsOnly flag whose value is "attrsOnly", a
497  *  filter whose value is "filter", and attribute bits whose value is
498  *  "attrBits"; storing the result at "pRequestMsg".
499  *
500  *  See pkix_pl_ldaptemplates.c (and below) for the ASN.1 representation of
501  *  message components, and see pkix_pl_ldapt.h for data types.
502  *
503  * PARAMETERS
504  *  "arena"
505  *      The address of the PLArenaPool to be used in the encoding. Must be
506  *      non-NULL.
507  *  "msgnum"
508  *      The UInt32 message number to be used for the messageID component of the
509  *      LDAP message exchange.
510  *  "issuerDN"
511  *      The address of the string to be used for the baseObject component of the
512  *      LDAP SearchRequest message. Must be non-NULL.
513  *  "scope"
514  *      The (enumerated) ScopeType to be used for the scope component of the
515  *      LDAP SearchRequest message
516  *  "derefAliases"
517  *      The (enumerated) DerefType to be used for the derefAliases component of
518  *      the LDAP SearchRequest message
519  *  "sizeLimit"
520  *      The UInt32 value to be used for the sizeLimit component of the LDAP
521  *      SearchRequest message
522  *  "timeLimit"
523  *      The UInt32 value to be used for the timeLimit component of the LDAP
524  *      SearchRequest message
525  *  "attrsOnly"
526  *      The Boolean value to be used for the attrsOnly component of the LDAP
527  *      SearchRequest message
528  *  "filter"
529  *      The filter to be used for the filter component of the LDAP
530  *      SearchRequest message
531  *  "attrBits"
532  *      The LdapAttrMask bits indicating the attributes to be included in the
533  *      attributes sequence of the LDAP SearchRequest message
534  *  "pRequestMsg"
535  *      The address at which the address of the LdapRequest is stored. Must
536  *      be non-NULL.
537  *  "plContext"
538  *      Platform-specific context pointer.
539  * THREAD SAFETY:
540  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
541  * RETURNS:
542  *  Returns NULL if the function succeeds.
543  *  Returns an LdapRequest Error if the function fails in a non-fatal way.
544  *  Returns a Fatal Error if the function fails in an unrecoverable way.
545  */
546 /*
547  * SearchRequest ::=
548  *      [APPLICATION 3] SEQUENCE {
549  *              baseObject      LDAPDN,
550  *              scope           ENUMERATED {
551  *                                      baseObject              (0),
552  *                                      singleLevel             (1),
553  *                                      wholeSubtree            (2)
554  *                              },
555  *              derefAliases    ENUMERATED {
556  *                                      neverDerefAliases       (0),
557  *                                      derefInSearching        (1),
558  *                                      derefFindingBaseObj     (2),
559  *                                      alwaysDerefAliases      (3)
560  *                              },
561  *              sizeLimit       INTEGER (0 .. MAXINT),
562  *                              -- value of 0 implies no sizeLimit
563  *              timeLimit       INTEGER (0 .. MAXINT),
564  *                              -- value of 0 implies no timeLimit
565  *              attrsOnly       BOOLEAN,
566  *                              -- TRUE, if only attributes (without values)
567  *                              -- to be returned
568  *              filter          Filter,
569  *              attributes      SEQUENCE OF AttributeType
570  *      }
571  *
572  * Filter ::=
573  *      CHOICE {
574  *              and             [0] SET OF Filter,
575  *              or              [1] SET OF Filter,
576  *              not             [2] Filter,
577  *              equalityMatch   [3] AttributeValueAssertion,
578  *              substrings      [4] SubstringFilter,
579  *              greaterOrEqual  [5] AttributeValueAssertion,
580  *              lessOrEqual     [6] AttributeValueAssertion,
581  *              present         [7] AttributeType,
582  *              approxMatch     [8] AttributeValueAssertion
583  *      }
584  *
585  * SubstringFilter ::=
586  *      SEQUENCE {
587  *              type            AttributeType,
588  *              SEQUENCE OF CHOICE {
589  *                      initial [0] LDAPString,
590  *                      any     [1] LDAPString,
591  *                      final   [2] LDAPString,
592  *              }
593  *      }
594  *
595  * AttributeValueAssertion ::=
596  *      SEQUENCE {
597  *              attributeType   AttributeType,
598  *              attributeValue  AttributeValue,
599  *      }
600  *
601  * AttributeValue ::= OCTET STRING
602  *
603  * AttributeType ::= LDAPString
604  *               -- text name of the attribute, or dotted
605  *               -- OID representation
606  *
607  * LDAPDN ::= LDAPString
608  *
609  * LDAPString ::= OCTET STRING
610  *
611  */
612 PKIX_Error *
pkix_pl_LdapRequest_Create(PLArenaPool * arena,PKIX_UInt32 msgnum,char * issuerDN,ScopeType scope,DerefType derefAliases,PKIX_UInt32 sizeLimit,PKIX_UInt32 timeLimit,char attrsOnly,LDAPFilter * filter,LdapAttrMask attrBits,PKIX_PL_LdapRequest ** pRequestMsg,void * plContext)613 pkix_pl_LdapRequest_Create(
614         PLArenaPool *arena,
615         PKIX_UInt32 msgnum,
616         char *issuerDN,
617         ScopeType scope,
618         DerefType derefAliases,
619         PKIX_UInt32 sizeLimit,
620         PKIX_UInt32 timeLimit,
621         char attrsOnly,
622         LDAPFilter *filter,
623         LdapAttrMask attrBits,
624         PKIX_PL_LdapRequest **pRequestMsg,
625         void *plContext)
626 {
627         LDAPMessage msg;
628         LDAPSearch *search;
629         PKIX_PL_LdapRequest *ldapRequest = NULL;
630         char scopeTypeAsChar;
631         char derefAliasesTypeAsChar;
632         SECItem *attrArray[MAX_LDAPATTRS + 1];
633 
634         PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Create");
635         PKIX_NULLCHECK_THREE(arena, issuerDN, pRequestMsg);
636 
637         /* create a PKIX_PL_LdapRequest object */
638         PKIX_CHECK(PKIX_PL_Object_Alloc
639                     (PKIX_LDAPREQUEST_TYPE,
640                     sizeof (PKIX_PL_LdapRequest),
641                     (PKIX_PL_Object **)&ldapRequest,
642                     plContext),
643                     PKIX_COULDNOTCREATEOBJECT);
644 
645         ldapRequest->arena = arena;
646         ldapRequest->msgnum = msgnum;
647         ldapRequest->issuerDN = issuerDN;
648         ldapRequest->scope = scope;
649         ldapRequest->derefAliases = derefAliases;
650         ldapRequest->sizeLimit = sizeLimit;
651         ldapRequest->timeLimit = timeLimit;
652         ldapRequest->attrsOnly = attrsOnly;
653         ldapRequest->filter = filter;
654         ldapRequest->attrBits = attrBits;
655 
656         ldapRequest->attrArray = attrArray;
657 
658         PKIX_CHECK(pkix_pl_LdapRequest_EncodeAttrs
659                 (ldapRequest, plContext),
660                 PKIX_LDAPREQUESTENCODEATTRSFAILED);
661 
662         PKIX_PL_NSSCALL
663                 (LDAPREQUEST, PORT_Memset, (&msg, 0, sizeof (LDAPMessage)));
664 
665         msg.messageID.type = siUnsignedInteger;
666         msg.messageID.data = (void*)&msgnum;
667         msg.messageID.len = sizeof (msgnum);
668 
669         msg.protocolOp.selector = LDAP_SEARCH_TYPE;
670 
671         search = &(msg.protocolOp.op.searchMsg);
672 
673         search->baseObject.type = siAsciiString;
674         search->baseObject.data = (void *)issuerDN;
675         search->baseObject.len = PL_strlen(issuerDN);
676         scopeTypeAsChar = (char)scope;
677         search->scope.type = siUnsignedInteger;
678         search->scope.data = (void *)&scopeTypeAsChar;
679         search->scope.len = sizeof (scopeTypeAsChar);
680         derefAliasesTypeAsChar = (char)derefAliases;
681         search->derefAliases.type = siUnsignedInteger;
682         search->derefAliases.data =
683                 (void *)&derefAliasesTypeAsChar;
684         search->derefAliases.len =
685                 sizeof (derefAliasesTypeAsChar);
686         search->sizeLimit.type = siUnsignedInteger;
687         search->sizeLimit.data = (void *)&sizeLimit;
688         search->sizeLimit.len = sizeof (PKIX_UInt32);
689         search->timeLimit.type = siUnsignedInteger;
690         search->timeLimit.data = (void *)&timeLimit;
691         search->timeLimit.len = sizeof (PKIX_UInt32);
692         search->attrsOnly.type = siBuffer;
693         search->attrsOnly.data = (void *)&attrsOnly;
694         search->attrsOnly.len = sizeof (attrsOnly);
695 
696         PKIX_PL_NSSCALL
697                 (LDAPREQUEST,
698                 PORT_Memcpy,
699                 (&search->filter, filter, sizeof (LDAPFilter)));
700 
701         search->attributes = attrArray;
702 
703         PKIX_PL_NSSCALLRV
704                 (LDAPREQUEST, ldapRequest->encoded, SEC_ASN1EncodeItem,
705                 (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate));
706 
707         if (!(ldapRequest->encoded)) {
708                 PKIX_ERROR(PKIX_FAILEDINENCODINGSEARCHREQUEST);
709         }
710 
711         *pRequestMsg = ldapRequest;
712 
713 cleanup:
714 
715         if (PKIX_ERROR_RECEIVED) {
716                 PKIX_DECREF(ldapRequest);
717         }
718 
719         PKIX_RETURN(LDAPREQUEST);
720 }
721 
722 /*
723  * FUNCTION: pkix_pl_LdapRequest_GetEncoded
724  * DESCRIPTION:
725  *
726  *  This function obtains the encoded message from the LdapRequest pointed to
727  *  by "request", storing the result at "pRequestBuf".
728  *
729  * PARAMETERS
730  *  "request"
731  *      The address of the LdapRequest whose encoded message is to be
732  *      retrieved. Must be non-NULL.
733  *  "pRequestBuf"
734  *      The address at which is stored the address of the encoded message. Must
735  *      be non-NULL.
736  *  "plContext"
737  *      Platform-specific context pointer.
738  * THREAD SAFETY:
739  *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
740  * RETURNS:
741  *  Returns NULL if the function succeeds.
742  *  Returns an LdapRequest Error if the function fails in a non-fatal way.
743  *  Returns a Fatal Error if the function fails in an unrecoverable way.
744  */
745 PKIX_Error *
pkix_pl_LdapRequest_GetEncoded(PKIX_PL_LdapRequest * request,SECItem ** pRequestBuf,void * plContext)746 pkix_pl_LdapRequest_GetEncoded(
747         PKIX_PL_LdapRequest *request,
748         SECItem **pRequestBuf,
749         void *plContext)
750 {
751         PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_GetEncoded");
752         PKIX_NULLCHECK_TWO(request, pRequestBuf);
753 
754         *pRequestBuf = request->encoded;
755 
756         PKIX_RETURN(LDAPREQUEST);
757 }
758