OLD | NEW |
| (Empty) |
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_ldapresponse.c | |
6 * | |
7 */ | |
8 | |
9 #include <fcntl.h> | |
10 #include "pkix_pl_ldapresponse.h" | |
11 | |
12 /* --Private-LdapResponse-Functions------------------------------------- */ | |
13 | |
14 /* | |
15 * FUNCTION: pkix_pl_LdapResponse_Destroy | |
16 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
17 */ | |
18 static PKIX_Error * | |
19 pkix_pl_LdapResponse_Destroy( | |
20 PKIX_PL_Object *object, | |
21 void *plContext) | |
22 { | |
23 PKIX_PL_LdapResponse *ldapRsp = NULL; | |
24 LDAPMessage *m = NULL; | |
25 LDAPSearchResponseEntry *entry = NULL; | |
26 LDAPSearchResponseResult *result = NULL; | |
27 LDAPSearchResponseAttr **attributes = NULL; | |
28 LDAPSearchResponseAttr *attr = NULL; | |
29 SECItem **valp = NULL; | |
30 SECItem *val = NULL; | |
31 | |
32 PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Destroy"); | |
33 PKIX_NULLCHECK_ONE(object); | |
34 | |
35 PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPRESPONSE_TYPE, plContext), | |
36 PKIX_OBJECTNOTLDAPRESPONSE); | |
37 | |
38 ldapRsp = (PKIX_PL_LdapResponse *)object; | |
39 | |
40 m = &ldapRsp->decoded; | |
41 | |
42 if (m->messageID.data != NULL) { | |
43 PR_Free(m->messageID.data); | |
44 } | |
45 | |
46 if (m->protocolOp.selector == | |
47 LDAP_SEARCHRESPONSEENTRY_TYPE) { | |
48 entry = &m->protocolOp.op.searchResponseEntryMsg; | |
49 if (entry->objectName.data != NULL) { | |
50 PR_Free(entry->objectName.data); | |
51 } | |
52 if (entry->attributes != NULL) { | |
53 for (attributes = entry->attributes; | |
54 *attributes != NULL; | |
55 attributes++) { | |
56 attr = *attributes; | |
57 PR_Free(attr->attrType.data); | |
58 for (valp = attr->val; *valp != NULL; valp++) { | |
59 val = *valp; | |
60 if (val->data != NULL) { | |
61 PR_Free(val->data); | |
62 } | |
63 PR_Free(val); | |
64 } | |
65 PR_Free(attr->val); | |
66 PR_Free(attr); | |
67 } | |
68 PR_Free(entry->attributes); | |
69 } | |
70 } else if (m->protocolOp.selector == | |
71 LDAP_SEARCHRESPONSERESULT_TYPE) { | |
72 result = &m->protocolOp.op.searchResponseResultMsg; | |
73 if (result->resultCode.data != NULL) { | |
74 PR_Free(result->resultCode.data); | |
75 } | |
76 } | |
77 | |
78 PKIX_FREE(ldapRsp->derEncoded.data); | |
79 | |
80 cleanup: | |
81 | |
82 PKIX_RETURN(LDAPRESPONSE); | |
83 } | |
84 | |
85 /* | |
86 * FUNCTION: pkix_pl_LdapResponse_Hashcode | |
87 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) | |
88 */ | |
89 static PKIX_Error * | |
90 pkix_pl_LdapResponse_Hashcode( | |
91 PKIX_PL_Object *object, | |
92 PKIX_UInt32 *pHashcode, | |
93 void *plContext) | |
94 { | |
95 PKIX_UInt32 dataLen = 0; | |
96 PKIX_UInt32 dindex = 0; | |
97 PKIX_UInt32 sizeOfLength = 0; | |
98 PKIX_UInt32 idLen = 0; | |
99 const unsigned char *msgBuf = NULL; | |
100 PKIX_PL_LdapResponse *ldapRsp = NULL; | |
101 | |
102 PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Hashcode"); | |
103 PKIX_NULLCHECK_TWO(object, pHashcode); | |
104 | |
105 PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPRESPONSE_TYPE, plContext), | |
106 PKIX_OBJECTNOTLDAPRESPONSE); | |
107 | |
108 ldapRsp = (PKIX_PL_LdapResponse *)object; | |
109 | |
110 *pHashcode = 0; | |
111 | |
112 /* | |
113 * Two responses that differ only in msgnum are a match! Therefore, | |
114 * start hashcoding beyond the encoded messageID field. | |
115 */ | |
116 if (ldapRsp->derEncoded.data) { | |
117 msgBuf = (const unsigned char *)ldapRsp->derEncoded.data; | |
118 /* Is message length short form (one octet) or long form? */ | |
119 if ((msgBuf[1] & 0x80) != 0) { | |
120 sizeOfLength = msgBuf[1] & 0x7F; | |
121 for (dindex = 0; dindex < sizeOfLength; dindex++) { | |
122 dataLen = (dataLen << 8) + msgBuf[dindex + 2]; | |
123 } | |
124 } else { | |
125 dataLen = msgBuf[1]; | |
126 } | |
127 | |
128 /* How many bytes for the messageID? (Assume short form) */ | |
129 idLen = msgBuf[dindex + 3] + 2; | |
130 dindex += idLen; | |
131 dataLen -= idLen; | |
132 msgBuf = &msgBuf[dindex + 2]; | |
133 | |
134 PKIX_CHECK(pkix_hash(msgBuf, dataLen, pHashcode, plContext), | |
135 PKIX_HASHFAILED); | |
136 } | |
137 | |
138 cleanup: | |
139 | |
140 PKIX_RETURN(LDAPRESPONSE); | |
141 | |
142 } | |
143 | |
144 /* | |
145 * FUNCTION: pkix_pl_LdapResponse_Equals | |
146 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) | |
147 */ | |
148 static PKIX_Error * | |
149 pkix_pl_LdapResponse_Equals( | |
150 PKIX_PL_Object *firstObj, | |
151 PKIX_PL_Object *secondObj, | |
152 PKIX_Boolean *pResult, | |
153 void *plContext) | |
154 { | |
155 PKIX_PL_LdapResponse *rsp1 = NULL; | |
156 PKIX_PL_LdapResponse *rsp2 = NULL; | |
157 PKIX_UInt32 secondType = 0; | |
158 PKIX_UInt32 firstLen = 0; | |
159 const unsigned char *firstData = NULL; | |
160 const unsigned char *secondData = NULL; | |
161 PKIX_UInt32 sizeOfLength = 0; | |
162 PKIX_UInt32 dindex = 0; | |
163 PKIX_UInt32 i = 0; | |
164 | |
165 PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Equals"); | |
166 PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult); | |
167 | |
168 /* test that firstObj is a LdapResponse */ | |
169 PKIX_CHECK(pkix_CheckType(firstObj, PKIX_LDAPRESPONSE_TYPE, plContext), | |
170 PKIX_FIRSTOBJARGUMENTNOTLDAPRESPONSE); | |
171 | |
172 /* | |
173 * Since we know firstObj is a LdapResponse, if both references are | |
174 * identical, they must be equal | |
175 */ | |
176 if (firstObj == secondObj){ | |
177 *pResult = PKIX_TRUE; | |
178 goto cleanup; | |
179 } | |
180 | |
181 /* | |
182 * If secondObj isn't a LdapResponse, we don't throw an error. | |
183 * We simply return a Boolean result of FALSE | |
184 */ | |
185 *pResult = PKIX_FALSE; | |
186 PKIX_CHECK(PKIX_PL_Object_GetType(secondObj, &secondType, plContext), | |
187 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); | |
188 if (secondType != PKIX_LDAPRESPONSE_TYPE) { | |
189 goto cleanup; | |
190 } | |
191 | |
192 rsp1 = (PKIX_PL_LdapResponse *)firstObj; | |
193 rsp2 = (PKIX_PL_LdapResponse *)secondObj; | |
194 | |
195 /* If either lacks an encoded string, they cannot be compared */ | |
196 if (!(rsp1->derEncoded.data) || !(rsp2->derEncoded.data)) { | |
197 goto cleanup; | |
198 } | |
199 | |
200 if (rsp1->derEncoded.len != rsp2->derEncoded.len) { | |
201 goto cleanup; | |
202 } | |
203 | |
204 firstData = (const unsigned char *)rsp1->derEncoded.data; | |
205 secondData = (const unsigned char *)rsp2->derEncoded.data; | |
206 | |
207 /* | |
208 * Two responses that differ only in msgnum are equal! Therefore, | |
209 * start the byte comparison beyond the encoded messageID field. | |
210 */ | |
211 | |
212 /* Is message length short form (one octet) or long form? */ | |
213 if ((firstData[1] & 0x80) != 0) { | |
214 sizeOfLength = firstData[1] & 0x7F; | |
215 for (dindex = 0; dindex < sizeOfLength; dindex++) { | |
216 firstLen = (firstLen << 8) + firstData[dindex + 2]; | |
217 } | |
218 } else { | |
219 firstLen = firstData[1]; | |
220 } | |
221 | |
222 /* How many bytes for the messageID? (Assume short form) */ | |
223 i = firstData[dindex + 3] + 2; | |
224 dindex += i; | |
225 firstLen -= i; | |
226 firstData = &firstData[dindex + 2]; | |
227 | |
228 /* | |
229 * In theory, we have to calculate where the second message data | |
230 * begins by checking its length encodings. But if these messages | |
231 * are equal, we can re-use the calculation we already did. If they | |
232 * are not equal, the byte comparisons will surely fail. | |
233 */ | |
234 | |
235 secondData = &secondData[dindex + 2]; | |
236 | |
237 for (i = 0; i < firstLen; i++) { | |
238 if (firstData[i] != secondData[i]) { | |
239 goto cleanup; | |
240 } | |
241 } | |
242 | |
243 *pResult = PKIX_TRUE; | |
244 | |
245 cleanup: | |
246 | |
247 PKIX_RETURN(LDAPRESPONSE); | |
248 } | |
249 | |
250 /* | |
251 * FUNCTION: pkix_pl_LdapResponse_RegisterSelf | |
252 * DESCRIPTION: | |
253 * Registers PKIX_LDAPRESPONSE_TYPE and its related functions with | |
254 * systemClasses[] | |
255 * PARAMETERS: | |
256 * "plContext" | |
257 * Platform-specific context pointer. | |
258 * THREAD SAFETY: | |
259 * Not Thread Safe - for performance and complexity reasons | |
260 * | |
261 * Since this function is only called by PKIX_PL_Initialize, which should | |
262 * only be called once, it is acceptable that this function is not | |
263 * thread-safe. | |
264 */ | |
265 PKIX_Error * | |
266 pkix_pl_LdapResponse_RegisterSelf(void *plContext) | |
267 { | |
268 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
269 pkix_ClassTable_Entry entry; | |
270 | |
271 PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_RegisterSelf"); | |
272 | |
273 entry.description = "LdapResponse"; | |
274 entry.objCounter = 0; | |
275 entry.typeObjectSize = sizeof(PKIX_PL_LdapResponse); | |
276 entry.destructor = pkix_pl_LdapResponse_Destroy; | |
277 entry.equalsFunction = pkix_pl_LdapResponse_Equals; | |
278 entry.hashcodeFunction = pkix_pl_LdapResponse_Hashcode; | |
279 entry.toStringFunction = NULL; | |
280 entry.comparator = NULL; | |
281 entry.duplicateFunction = pkix_duplicateImmutable; | |
282 | |
283 systemClasses[PKIX_LDAPRESPONSE_TYPE] = entry; | |
284 | |
285 PKIX_RETURN(LDAPRESPONSE); | |
286 } | |
287 | |
288 /* --Public-Functions------------------------------------------------------- */ | |
289 | |
290 /* | |
291 * FUNCTION: pkix_pl_LdapResponse_Create | |
292 * DESCRIPTION: | |
293 * | |
294 * This function creates an LdapResponse for the LDAPMessageType provided in | |
295 * "responseType" and a buffer capacity provided by "totalLength". It copies | |
296 * into its buffer either "totalLength" or "bytesAvailable" bytes, whichever | |
297 * is less, from the buffer pointed to by "partialData", storing the number of | |
298 * bytes copied at "pBytesConsumed" and storing the address of the LdapResponse | |
299 * at "pLdapResponse". | |
300 * | |
301 * If a message is complete in a single I/O buffer, the LdapResponse will be | |
302 * complete when this function returns. If the message carries over into | |
303 * additional buffers, their contents will be added to the LdapResponse by | |
304 * susequent calls to pkix_pl_LdapResponse_Append. | |
305 * | |
306 * PARAMETERS | |
307 * "responseType" | |
308 * The value of the message type (LDAP_SEARCHRESPONSEENTRY_TYPE or | |
309 * LDAP_SEARCHRESPONSERESULT_TYPE) for the LdapResponse being created | |
310 * "totalLength" | |
311 * The UInt32 value for the total length of the encoded message to be | |
312 * stored in the LdapResponse | |
313 * "bytesAvailable" | |
314 * The UInt32 value for the number of bytes of data available in the | |
315 * current buffer. | |
316 * "partialData" | |
317 * The address from which data is to be copied. | |
318 * "pBytesConsumed" | |
319 * The address at which is stored the UInt32 number of bytes taken from the | |
320 * current buffer. If this number is less than "bytesAvailable", then bytes | |
321 * remain in the buffer for the next LdapResponse. Must be non-NULL. | |
322 * "pLdapResponse" | |
323 * The address where the created LdapResponse is stored. Must be non-NULL. | |
324 * "plContext" | |
325 * Platform-specific context pointer. | |
326 * THREAD SAFETY: | |
327 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
328 * RETURNS: | |
329 * Returns NULL if the function succeeds. | |
330 * Returns an LdapResponse Error if the function fails in a non-fatal way. | |
331 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
332 */ | |
333 PKIX_Error * | |
334 pkix_pl_LdapResponse_Create( | |
335 LDAPMessageType responseType, | |
336 PKIX_UInt32 totalLength, | |
337 PKIX_UInt32 bytesAvailable, | |
338 void *partialData, | |
339 PKIX_UInt32 *pBytesConsumed, | |
340 PKIX_PL_LdapResponse **pLdapResponse, | |
341 void *plContext) | |
342 { | |
343 PKIX_UInt32 bytesConsumed = 0; | |
344 PKIX_PL_LdapResponse *ldapResponse = NULL; | |
345 void *data = NULL; | |
346 | |
347 PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Create"); | |
348 PKIX_NULLCHECK_ONE(pLdapResponse); | |
349 | |
350 if (bytesAvailable <= totalLength) { | |
351 bytesConsumed = bytesAvailable; | |
352 } else { | |
353 bytesConsumed = totalLength; | |
354 } | |
355 | |
356 /* create a PKIX_PL_LdapResponse object */ | |
357 PKIX_CHECK(PKIX_PL_Object_Alloc | |
358 (PKIX_LDAPRESPONSE_TYPE, | |
359 sizeof (PKIX_PL_LdapResponse), | |
360 (PKIX_PL_Object **)&ldapResponse, | |
361 plContext), | |
362 PKIX_COULDNOTCREATEOBJECT); | |
363 | |
364 ldapResponse->decoded.protocolOp.selector = responseType; | |
365 ldapResponse->totalLength = totalLength; | |
366 ldapResponse->partialLength = bytesConsumed; | |
367 | |
368 if (totalLength != 0){ | |
369 /* Alloc space for array */ | |
370 PKIX_NULLCHECK_ONE(partialData); | |
371 | |
372 PKIX_CHECK(PKIX_PL_Malloc | |
373 (totalLength, | |
374 &data, | |
375 plContext), | |
376 PKIX_MALLOCFAILED); | |
377 | |
378 PKIX_PL_NSSCALL | |
379 (LDAPRESPONSE, | |
380 PORT_Memcpy, | |
381 (data, partialData, bytesConsumed)); | |
382 } | |
383 | |
384 ldapResponse->derEncoded.type = siBuffer; | |
385 ldapResponse->derEncoded.data = data; | |
386 ldapResponse->derEncoded.len = totalLength; | |
387 *pBytesConsumed = bytesConsumed; | |
388 *pLdapResponse = ldapResponse; | |
389 | |
390 cleanup: | |
391 | |
392 if (PKIX_ERROR_RECEIVED){ | |
393 PKIX_DECREF(ldapResponse); | |
394 } | |
395 | |
396 PKIX_RETURN(LDAPRESPONSE); | |
397 } | |
398 | |
399 /* | |
400 * FUNCTION: pkix_pl_LdapResponse_Append | |
401 * DESCRIPTION: | |
402 * | |
403 * This function updates the LdapResponse pointed to by "response" with up to | |
404 * "incrLength" from the buffer pointer to by "incrData", storing the number of | |
405 * bytes copied at "pBytesConsumed". | |
406 * | |
407 * PARAMETERS | |
408 * "response" | |
409 * The address of the LdapResponse being updated. Must be non-zero. | |
410 * "incrLength" | |
411 * The UInt32 value for the number of bytes of data available in the | |
412 * current buffer. | |
413 * "incrData" | |
414 * The address from which data is to be copied. | |
415 * "pBytesConsumed" | |
416 * The address at which is stored the UInt32 number of bytes taken from the | |
417 * current buffer. If this number is less than "incrLength", then bytes | |
418 * remain in the buffer for the next LdapResponse. Must be non-NULL. | |
419 * "plContext" | |
420 * Platform-specific context pointer. | |
421 * THREAD SAFETY: | |
422 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
423 * RETURNS: | |
424 * Returns NULL if the function succeeds. | |
425 * Returns an LdapResponse Error if the function fails in a non-fatal way. | |
426 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
427 */ | |
428 PKIX_Error * | |
429 pkix_pl_LdapResponse_Append( | |
430 PKIX_PL_LdapResponse *response, | |
431 PKIX_UInt32 incrLength, | |
432 void *incrData, | |
433 PKIX_UInt32 *pBytesConsumed, | |
434 void *plContext) | |
435 { | |
436 PKIX_UInt32 newPartialLength = 0; | |
437 PKIX_UInt32 bytesConsumed = 0; | |
438 void *dest = NULL; | |
439 | |
440 PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Append"); | |
441 PKIX_NULLCHECK_TWO(response, pBytesConsumed); | |
442 | |
443 if (incrLength > 0) { | |
444 | |
445 /* Calculate how many bytes we have room for. */ | |
446 bytesConsumed = | |
447 response->totalLength - response->partialLength; | |
448 | |
449 if (bytesConsumed > incrLength) { | |
450 bytesConsumed = incrLength; | |
451 } | |
452 | |
453 newPartialLength = response->partialLength + bytesConsumed; | |
454 | |
455 PKIX_NULLCHECK_ONE(incrData); | |
456 | |
457 dest = &(((char *)response->derEncoded.data)[ | |
458 response->partialLength]); | |
459 | |
460 PKIX_PL_NSSCALL | |
461 (LDAPRESPONSE, | |
462 PORT_Memcpy, | |
463 (dest, incrData, bytesConsumed)); | |
464 | |
465 response->partialLength = newPartialLength; | |
466 } | |
467 | |
468 *pBytesConsumed = bytesConsumed; | |
469 | |
470 PKIX_RETURN(LDAPRESPONSE); | |
471 } | |
472 | |
473 /* | |
474 * FUNCTION: pkix_pl_LdapResponse_IsComplete | |
475 * DESCRIPTION: | |
476 * | |
477 * This function determines whether the LdapResponse pointed to by "response" | |
478 * contains all the data called for by the "totalLength" parameter provided | |
479 * when it was created, storing PKIX_TRUE at "pIsComplete" if so, and | |
480 * PKIX_FALSE otherwise. | |
481 * | |
482 * PARAMETERS | |
483 * "response" | |
484 * The address of the LdapResponse being evaluaTED. Must be non-zero. | |
485 * "incrLength" | |
486 * The UInt32 value for the number of bytes of data available in the | |
487 * current buffer. | |
488 * "incrData" | |
489 * The address from which data is to be copied. | |
490 * "pIsComplete" | |
491 * The address at which is stored the Boolean indication of whether the | |
492 * LdapResponse is complete. Must be non-NULL. | |
493 * "plContext" | |
494 * Platform-specific context pointer. | |
495 * THREAD SAFETY: | |
496 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
497 * RETURNS: | |
498 * Returns NULL if the function succeeds. | |
499 * Returns an LdapResponse Error if the function fails in a non-fatal way. | |
500 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
501 */ | |
502 PKIX_Error * | |
503 pkix_pl_LdapResponse_IsComplete( | |
504 PKIX_PL_LdapResponse *response, | |
505 PKIX_Boolean *pIsComplete, | |
506 void *plContext) | |
507 { | |
508 PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_IsComplete"); | |
509 PKIX_NULLCHECK_TWO(response, pIsComplete); | |
510 | |
511 if (response->totalLength == response->partialLength) { | |
512 *pIsComplete = PKIX_TRUE; | |
513 } else { | |
514 *pIsComplete = PKIX_FALSE; | |
515 } | |
516 | |
517 PKIX_RETURN(LDAPRESPONSE); | |
518 } | |
519 | |
520 /* | |
521 * FUNCTION: pkix_pl_LdapResponse_Decode | |
522 * DESCRIPTION: | |
523 * | |
524 * This function decodes the DER data contained in the LdapResponse pointed to | |
525 * by "response", using the arena pointed to by "arena", and storing at | |
526 * "pStatus" SECSuccess if the decoding was successful and SECFailure | |
527 * otherwise. The decoded message is stored in an element of "response". | |
528 * | |
529 * PARAMETERS | |
530 * "arena" | |
531 * The address of the PLArenaPool to be used in the decoding. Must be | |
532 * non-NULL. | |
533 * "response" | |
534 * The address of the LdapResponse whose DER data is to be decoded. Must | |
535 * be non-NULL. | |
536 * "pStatus" | |
537 * The address at which is stored the status from the decoding, SECSuccess | |
538 * if successful, SECFailure otherwise. Must be non-NULL. | |
539 * "plContext" | |
540 * Platform-specific context pointer. | |
541 * THREAD SAFETY: | |
542 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
543 * RETURNS: | |
544 * Returns NULL if the function succeeds. | |
545 * Returns an LdapResponse Error if the function fails in a non-fatal way. | |
546 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
547 */ | |
548 PKIX_Error * | |
549 pkix_pl_LdapResponse_Decode( | |
550 PLArenaPool *arena, | |
551 PKIX_PL_LdapResponse *response, | |
552 SECStatus *pStatus, | |
553 void *plContext) | |
554 { | |
555 LDAPMessage *msg; | |
556 SECStatus rv = SECFailure; | |
557 | |
558 PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Decode"); | |
559 PKIX_NULLCHECK_THREE(arena, response, pStatus); | |
560 | |
561 if (response->totalLength != response->partialLength) { | |
562 PKIX_ERROR(PKIX_ATTEMPTTODECODEANINCOMPLETERESPONSE); | |
563 } | |
564 | |
565 msg = &(response->decoded); | |
566 | |
567 PKIX_PL_NSSCALL | |
568 (LDAPRESPONSE, PORT_Memset, (msg, 0, sizeof (LDAPMessage))); | |
569 | |
570 PKIX_PL_NSSCALLRV(LDAPRESPONSE, rv, SEC_ASN1DecodeItem, | |
571 (NULL, msg, PKIX_PL_LDAPMessageTemplate, &(response->derEncoded))); | |
572 | |
573 *pStatus = rv; | |
574 cleanup: | |
575 | |
576 PKIX_RETURN(LDAPRESPONSE); | |
577 } | |
578 | |
579 /* | |
580 * FUNCTION: pkix_pl_LdapResponse_GetMessage | |
581 * DESCRIPTION: | |
582 * | |
583 * This function obtains the decoded message from the LdapResponse pointed to | |
584 * by "response", storing the result at "pMessage". | |
585 * | |
586 * PARAMETERS | |
587 * "response" | |
588 * The address of the LdapResponse whose decoded message is to be | |
589 * retrieved. Must be non-NULL. | |
590 * "pMessage" | |
591 * The address at which is stored the address of the decoded message. Must | |
592 * be non-NULL. | |
593 * "plContext" | |
594 * Platform-specific context pointer. | |
595 * THREAD SAFETY: | |
596 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
597 * RETURNS: | |
598 * Returns NULL if the function succeeds. | |
599 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
600 */ | |
601 PKIX_Error * | |
602 pkix_pl_LdapResponse_GetMessage( | |
603 PKIX_PL_LdapResponse *response, | |
604 LDAPMessage **pMessage, | |
605 void *plContext) | |
606 { | |
607 PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetMessage"); | |
608 PKIX_NULLCHECK_TWO(response, pMessage); | |
609 | |
610 *pMessage = &response->decoded; | |
611 | |
612 PKIX_RETURN(LDAPRESPONSE); | |
613 } | |
614 | |
615 /* | |
616 * FUNCTION: pkix_pl_LdapResponse_GetCapacity | |
617 * DESCRIPTION: | |
618 * | |
619 * This function obtains from the LdapResponse pointed to by "response" the | |
620 * number of bytes remaining to be read, based on the totalLength that was | |
621 * provided to LdapResponse_Create and the data subsequently provided to | |
622 * LdapResponse_Append, storing the result at "pMessage". | |
623 * | |
624 * PARAMETERS | |
625 * "response" | |
626 * The address of the LdapResponse whose remaining capacity is to be | |
627 * retrieved. Must be non-NULL. | |
628 * "pCapacity" | |
629 * The address at which is stored the address of the decoded message. Must | |
630 * be non-NULL. | |
631 * "plContext" | |
632 * Platform-specific context pointer. | |
633 * THREAD SAFETY: | |
634 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
635 * RETURNS: | |
636 * Returns NULL if the function succeeds. | |
637 * Returns an LdapResponse Error if the function fails in a non-fatal way. | |
638 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
639 */ | |
640 PKIX_Error * | |
641 pkix_pl_LdapResponse_GetCapacity( | |
642 PKIX_PL_LdapResponse *response, | |
643 PKIX_UInt32 *pCapacity, | |
644 void *plContext) | |
645 { | |
646 PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetCapacity"); | |
647 PKIX_NULLCHECK_TWO(response, pCapacity); | |
648 | |
649 *pCapacity = response->totalLength - response->partialLength; | |
650 | |
651 PKIX_RETURN(LDAPRESPONSE); | |
652 } | |
653 | |
654 /* | |
655 * FUNCTION: pkix_pl_LdapResponse_GetMessageType | |
656 * DESCRIPTION: | |
657 * | |
658 * This function obtains the message type from the LdapResponse pointed to | |
659 * by "response", storing the result at "pMessageType". | |
660 * | |
661 * PARAMETERS | |
662 * "response" | |
663 * The address of the LdapResponse whose message type is to be | |
664 * retrieved. Must be non-NULL. | |
665 * "pMessageType" | |
666 * The address at which is stored the type of the response message. Must | |
667 * be non-NULL. | |
668 * "plContext" | |
669 * Platform-specific context pointer. | |
670 * THREAD SAFETY: | |
671 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
672 * RETURNS: | |
673 * Returns NULL if the function succeeds. | |
674 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
675 */ | |
676 PKIX_Error * | |
677 pkix_pl_LdapResponse_GetMessageType( | |
678 PKIX_PL_LdapResponse *response, | |
679 LDAPMessageType *pMessageType, | |
680 void *plContext) | |
681 { | |
682 PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetMessageType"); | |
683 PKIX_NULLCHECK_TWO(response, pMessageType); | |
684 | |
685 *pMessageType = response->decoded.protocolOp.selector; | |
686 | |
687 PKIX_RETURN(LDAPRESPONSE); | |
688 } | |
689 | |
690 /* | |
691 * FUNCTION: pkix_pl_LdapResponse_GetResultCode | |
692 * DESCRIPTION: | |
693 * | |
694 * This function obtains the result code from the LdapResponse pointed to | |
695 * by "response", storing the result at "pResultCode". | |
696 * | |
697 * PARAMETERS | |
698 * "response" | |
699 * The address of the LdapResponse whose result code is to be | |
700 * retrieved. Must be non-NULL. | |
701 * "pResultCode" | |
702 * The address at which is stored the address of the decoded message. Must | |
703 * be non-NULL. | |
704 * "plContext" | |
705 * Platform-specific context pointer. | |
706 * THREAD SAFETY: | |
707 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
708 * RETURNS: | |
709 * Returns NULL if the function succeeds. | |
710 * Returns an LdapResponse Error if the function fails in a non-fatal way. | |
711 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
712 */ | |
713 PKIX_Error * | |
714 pkix_pl_LdapResponse_GetResultCode( | |
715 PKIX_PL_LdapResponse *response, | |
716 LDAPResultCode *pResultCode, | |
717 void *plContext) | |
718 { | |
719 LDAPMessageType messageType = 0; | |
720 LDAPSearchResponseResult *resultMsg = NULL; | |
721 | |
722 PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetResultCode"); | |
723 PKIX_NULLCHECK_TWO(response, pResultCode); | |
724 | |
725 messageType = response->decoded.protocolOp.selector; | |
726 | |
727 if (messageType != LDAP_SEARCHRESPONSERESULT_TYPE) { | |
728 PKIX_ERROR(PKIX_GETRESULTCODECALLEDFORNONRESULTMESSAGE); | |
729 } | |
730 | |
731 resultMsg = &response->decoded.protocolOp.op.searchResponseResultMsg; | |
732 | |
733 *pResultCode = *(resultMsg->resultCode.data); | |
734 | |
735 cleanup: | |
736 | |
737 PKIX_RETURN(LDAPRESPONSE); | |
738 } | |
739 | |
740 /* | |
741 * FUNCTION: pkix_pl_LdapResponse_GetAttributes | |
742 * DESCRIPTION: | |
743 * | |
744 * This function obtains the attributes from the LdapResponse pointed to | |
745 * by "response", storing the result at "pAttributes". | |
746 * | |
747 * PARAMETERS | |
748 * "response" | |
749 * The address of the LdapResponse whose decoded message is to be | |
750 * retrieved. Must be non-NULL. | |
751 * "pAttributes" | |
752 * The address at which is stored the attributes of the message. Must be | |
753 * non-NULL. | |
754 * "plContext" | |
755 * Platform-specific context pointer. | |
756 * THREAD SAFETY: | |
757 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
758 * RETURNS: | |
759 * Returns NULL if the function succeeds. | |
760 * Returns an LdapResponse Error if the function fails in a non-fatal way. | |
761 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
762 */ | |
763 PKIX_Error * | |
764 pkix_pl_LdapResponse_GetAttributes( | |
765 PKIX_PL_LdapResponse *response, | |
766 LDAPSearchResponseAttr ***pAttributes, | |
767 void *plContext) | |
768 { | |
769 LDAPMessageType messageType = 0; | |
770 | |
771 PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetResultCode"); | |
772 PKIX_NULLCHECK_TWO(response, pAttributes); | |
773 | |
774 messageType = response->decoded.protocolOp.selector; | |
775 | |
776 if (messageType != LDAP_SEARCHRESPONSEENTRY_TYPE) { | |
777 PKIX_ERROR(PKIX_GETATTRIBUTESCALLEDFORNONENTRYMESSAGE); | |
778 } | |
779 | |
780 *pAttributes = response-> | |
781 decoded.protocolOp.op.searchResponseEntryMsg.attributes; | |
782 | |
783 cleanup: | |
784 | |
785 PKIX_RETURN(LDAPRESPONSE); | |
786 } | |
OLD | NEW |