1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
14 * The Original Code is the PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
22 * Sun Microsystems, Inc.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * pkix_pl_ldapresponse.c
43 #include "pkix_pl_ldapresponse.h"
45 /* --Private-LdapResponse-Functions------------------------------------- */
48 * FUNCTION: pkix_pl_LdapResponse_Destroy
49 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
52 pkix_pl_LdapResponse_Destroy(
53 PKIX_PL_Object
*object
,
56 PKIX_PL_LdapResponse
*ldapRsp
= NULL
;
57 LDAPMessage
*m
= NULL
;
58 LDAPSearchResponseEntry
*entry
= NULL
;
59 LDAPSearchResponseResult
*result
= NULL
;
60 LDAPSearchResponseAttr
**attributes
= NULL
;
61 LDAPSearchResponseAttr
*attr
= NULL
;
62 SECItem
**valp
= NULL
;
65 PKIX_ENTER(LDAPRESPONSE
, "pkix_pl_LdapResponse_Destroy");
66 PKIX_NULLCHECK_ONE(object
);
68 PKIX_CHECK(pkix_CheckType(object
, PKIX_LDAPRESPONSE_TYPE
, plContext
),
69 PKIX_OBJECTNOTLDAPRESPONSE
);
71 ldapRsp
= (PKIX_PL_LdapResponse
*)object
;
73 m
= &ldapRsp
->decoded
;
75 if (m
->messageID
.data
!= NULL
) {
76 PR_Free(m
->messageID
.data
);
79 if (m
->protocolOp
.selector
==
80 LDAP_SEARCHRESPONSEENTRY_TYPE
) {
81 entry
= &m
->protocolOp
.op
.searchResponseEntryMsg
;
82 if (entry
->objectName
.data
!= NULL
) {
83 PR_Free(entry
->objectName
.data
);
85 if (entry
->attributes
!= NULL
) {
86 for (attributes
= entry
->attributes
;
90 PR_Free(attr
->attrType
.data
);
91 for (valp
= attr
->val
; *valp
!= NULL
; valp
++) {
93 if (val
->data
!= NULL
) {
101 PR_Free(entry
->attributes
);
103 } else if (m
->protocolOp
.selector
==
104 LDAP_SEARCHRESPONSERESULT_TYPE
) {
105 result
= &m
->protocolOp
.op
.searchResponseResultMsg
;
106 if (result
->resultCode
.data
!= NULL
) {
107 PR_Free(result
->resultCode
.data
);
111 PKIX_FREE(ldapRsp
->derEncoded
.data
);
115 PKIX_RETURN(LDAPRESPONSE
);
119 * FUNCTION: pkix_pl_LdapResponse_Hashcode
120 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
123 pkix_pl_LdapResponse_Hashcode(
124 PKIX_PL_Object
*object
,
125 PKIX_UInt32
*pHashcode
,
128 PKIX_UInt32 dataLen
= 0;
129 PKIX_UInt32 dindex
= 0;
130 PKIX_UInt32 sizeOfLength
= 0;
131 PKIX_UInt32 idLen
= 0;
132 const unsigned char *msgBuf
= NULL
;
133 PKIX_PL_LdapResponse
*ldapRsp
= NULL
;
135 PKIX_ENTER(LDAPRESPONSE
, "pkix_pl_LdapResponse_Hashcode");
136 PKIX_NULLCHECK_TWO(object
, pHashcode
);
138 PKIX_CHECK(pkix_CheckType(object
, PKIX_LDAPRESPONSE_TYPE
, plContext
),
139 PKIX_OBJECTNOTLDAPRESPONSE
);
141 ldapRsp
= (PKIX_PL_LdapResponse
*)object
;
146 * Two responses that differ only in msgnum are a match! Therefore,
147 * start hashcoding beyond the encoded messageID field.
149 if (ldapRsp
->derEncoded
.data
) {
150 msgBuf
= (const unsigned char *)ldapRsp
->derEncoded
.data
;
151 /* Is message length short form (one octet) or long form? */
152 if ((msgBuf
[1] & 0x80) != 0) {
153 sizeOfLength
= msgBuf
[1] & 0x7F;
154 for (dindex
= 0; dindex
< sizeOfLength
; dindex
++) {
155 dataLen
= (dataLen
<< 8) + msgBuf
[dindex
+ 2];
161 /* How many bytes for the messageID? (Assume short form) */
162 idLen
= msgBuf
[dindex
+ 3] + 2;
165 msgBuf
= &msgBuf
[dindex
+ 2];
167 PKIX_CHECK(pkix_hash(msgBuf
, dataLen
, pHashcode
, plContext
),
173 PKIX_RETURN(LDAPRESPONSE
);
178 * FUNCTION: pkix_pl_LdapResponse_Equals
179 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
182 pkix_pl_LdapResponse_Equals(
183 PKIX_PL_Object
*firstObj
,
184 PKIX_PL_Object
*secondObj
,
185 PKIX_Boolean
*pResult
,
188 PKIX_PL_LdapResponse
*rsp1
= NULL
;
189 PKIX_PL_LdapResponse
*rsp2
= NULL
;
190 PKIX_UInt32 secondType
= 0;
191 PKIX_UInt32 firstLen
= 0;
192 const unsigned char *firstData
= NULL
;
193 const unsigned char *secondData
= NULL
;
194 PKIX_UInt32 sizeOfLength
= 0;
195 PKIX_UInt32 dindex
= 0;
198 PKIX_ENTER(LDAPRESPONSE
, "pkix_pl_LdapResponse_Equals");
199 PKIX_NULLCHECK_THREE(firstObj
, secondObj
, pResult
);
201 /* test that firstObj is a LdapResponse */
202 PKIX_CHECK(pkix_CheckType(firstObj
, PKIX_LDAPRESPONSE_TYPE
, plContext
),
203 PKIX_FIRSTOBJARGUMENTNOTLDAPRESPONSE
);
206 * Since we know firstObj is a LdapResponse, if both references are
207 * identical, they must be equal
209 if (firstObj
== secondObj
){
210 *pResult
= PKIX_TRUE
;
215 * If secondObj isn't a LdapResponse, we don't throw an error.
216 * We simply return a Boolean result of FALSE
218 *pResult
= PKIX_FALSE
;
219 PKIX_CHECK(PKIX_PL_Object_GetType(secondObj
, &secondType
, plContext
),
220 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT
);
221 if (secondType
!= PKIX_LDAPRESPONSE_TYPE
) {
225 rsp1
= (PKIX_PL_LdapResponse
*)firstObj
;
226 rsp2
= (PKIX_PL_LdapResponse
*)secondObj
;
228 /* If either lacks an encoded string, they cannot be compared */
229 if (!(rsp1
->derEncoded
.data
) || !(rsp2
->derEncoded
.data
)) {
233 if (rsp1
->derEncoded
.len
!= rsp2
->derEncoded
.len
) {
237 firstData
= (const unsigned char *)rsp1
->derEncoded
.data
;
238 secondData
= (const unsigned char *)rsp2
->derEncoded
.data
;
241 * Two responses that differ only in msgnum are equal! Therefore,
242 * start the byte comparison beyond the encoded messageID field.
245 /* Is message length short form (one octet) or long form? */
246 if ((firstData
[1] & 0x80) != 0) {
247 sizeOfLength
= firstData
[1] & 0x7F;
248 for (dindex
= 0; dindex
< sizeOfLength
; dindex
++) {
249 firstLen
= (firstLen
<< 8) + firstData
[dindex
+ 2];
252 firstLen
= firstData
[1];
255 /* How many bytes for the messageID? (Assume short form) */
256 i
= firstData
[dindex
+ 3] + 2;
259 firstData
= &firstData
[dindex
+ 2];
262 * In theory, we have to calculate where the second message data
263 * begins by checking its length encodings. But if these messages
264 * are equal, we can re-use the calculation we already did. If they
265 * are not equal, the byte comparisons will surely fail.
268 secondData
= &secondData
[dindex
+ 2];
270 for (i
= 0; i
< firstLen
; i
++) {
271 if (firstData
[i
] != secondData
[i
]) {
276 *pResult
= PKIX_TRUE
;
280 PKIX_RETURN(LDAPRESPONSE
);
284 * FUNCTION: pkix_pl_LdapResponse_RegisterSelf
286 * Registers PKIX_LDAPRESPONSE_TYPE and its related functions with
290 * Platform-specific context pointer.
292 * Not Thread Safe - for performance and complexity reasons
294 * Since this function is only called by PKIX_PL_Initialize, which should
295 * only be called once, it is acceptable that this function is not
299 pkix_pl_LdapResponse_RegisterSelf(void *plContext
)
301 extern pkix_ClassTable_Entry systemClasses
[PKIX_NUMTYPES
];
302 pkix_ClassTable_Entry entry
;
304 PKIX_ENTER(LDAPRESPONSE
, "pkix_pl_LdapResponse_RegisterSelf");
306 entry
.description
= "LdapResponse";
307 entry
.objCounter
= 0;
308 entry
.typeObjectSize
= sizeof(PKIX_PL_LdapResponse
);
309 entry
.destructor
= pkix_pl_LdapResponse_Destroy
;
310 entry
.equalsFunction
= pkix_pl_LdapResponse_Equals
;
311 entry
.hashcodeFunction
= pkix_pl_LdapResponse_Hashcode
;
312 entry
.toStringFunction
= NULL
;
313 entry
.comparator
= NULL
;
314 entry
.duplicateFunction
= pkix_duplicateImmutable
;
316 systemClasses
[PKIX_LDAPRESPONSE_TYPE
] = entry
;
318 PKIX_RETURN(LDAPRESPONSE
);
321 /* --Public-Functions------------------------------------------------------- */
324 * FUNCTION: pkix_pl_LdapResponse_Create
327 * This function creates an LdapResponse for the LDAPMessageType provided in
328 * "responseType" and a buffer capacity provided by "totalLength". It copies
329 * into its buffer either "totalLength" or "bytesAvailable" bytes, whichever
330 * is less, from the buffer pointed to by "partialData", storing the number of
331 * bytes copied at "pBytesConsumed" and storing the address of the LdapResponse
332 * at "pLdapResponse".
334 * If a message is complete in a single I/O buffer, the LdapResponse will be
335 * complete when this function returns. If the message carries over into
336 * additional buffers, their contents will be added to the LdapResponse by
337 * susequent calls to pkix_pl_LdapResponse_Append.
341 * The value of the message type (LDAP_SEARCHRESPONSEENTRY_TYPE or
342 * LDAP_SEARCHRESPONSERESULT_TYPE) for the LdapResponse being created
344 * The UInt32 value for the total length of the encoded message to be
345 * stored in the LdapResponse
347 * The UInt32 value for the number of bytes of data available in the
350 * The address from which data is to be copied.
352 * The address at which is stored the UInt32 number of bytes taken from the
353 * current buffer. If this number is less than "bytesAvailable", then bytes
354 * remain in the buffer for the next LdapResponse. Must be non-NULL.
356 * The address where the created LdapResponse is stored. Must be non-NULL.
358 * Platform-specific context pointer.
360 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
362 * Returns NULL if the function succeeds.
363 * Returns an LdapResponse Error if the function fails in a non-fatal way.
364 * Returns a Fatal Error if the function fails in an unrecoverable way.
367 pkix_pl_LdapResponse_Create(
368 LDAPMessageType responseType
,
369 PKIX_UInt32 totalLength
,
370 PKIX_UInt32 bytesAvailable
,
372 PKIX_UInt32
*pBytesConsumed
,
373 PKIX_PL_LdapResponse
**pLdapResponse
,
376 PKIX_UInt32 bytesConsumed
= 0;
377 PKIX_PL_LdapResponse
*ldapResponse
= NULL
;
380 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_Create");
381 PKIX_NULLCHECK_ONE(pLdapResponse
);
383 if (bytesAvailable
<= totalLength
) {
384 bytesConsumed
= bytesAvailable
;
386 bytesConsumed
= totalLength
;
389 /* create a PKIX_PL_LdapResponse object */
390 PKIX_CHECK(PKIX_PL_Object_Alloc
391 (PKIX_LDAPRESPONSE_TYPE
,
392 sizeof (PKIX_PL_LdapResponse
),
393 (PKIX_PL_Object
**)&ldapResponse
,
395 PKIX_COULDNOTCREATEOBJECT
);
397 ldapResponse
->decoded
.protocolOp
.selector
= responseType
;
398 ldapResponse
->totalLength
= totalLength
;
399 ldapResponse
->partialLength
= bytesConsumed
;
401 if (totalLength
!= 0){
402 /* Alloc space for array */
403 PKIX_NULLCHECK_ONE(partialData
);
405 PKIX_CHECK(PKIX_PL_Malloc
414 (data
, partialData
, bytesConsumed
));
417 ldapResponse
->derEncoded
.type
= siBuffer
;
418 ldapResponse
->derEncoded
.data
= data
;
419 ldapResponse
->derEncoded
.len
= totalLength
;
420 *pBytesConsumed
= bytesConsumed
;
421 *pLdapResponse
= ldapResponse
;
425 if (PKIX_ERROR_RECEIVED
){
426 PKIX_DECREF(ldapResponse
);
429 PKIX_RETURN(LDAPRESPONSE
);
433 * FUNCTION: pkix_pl_LdapResponse_Append
436 * This function updates the LdapResponse pointed to by "response" with up to
437 * "incrLength" from the buffer pointer to by "incrData", storing the number of
438 * bytes copied at "pBytesConsumed".
442 * The address of the LdapResponse being updated. Must be non-zero.
444 * The UInt32 value for the number of bytes of data available in the
447 * The address from which data is to be copied.
449 * The address at which is stored the UInt32 number of bytes taken from the
450 * current buffer. If this number is less than "incrLength", then bytes
451 * remain in the buffer for the next LdapResponse. Must be non-NULL.
453 * Platform-specific context pointer.
455 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
457 * Returns NULL if the function succeeds.
458 * Returns an LdapResponse Error if the function fails in a non-fatal way.
459 * Returns a Fatal Error if the function fails in an unrecoverable way.
462 pkix_pl_LdapResponse_Append(
463 PKIX_PL_LdapResponse
*response
,
464 PKIX_UInt32 incrLength
,
466 PKIX_UInt32
*pBytesConsumed
,
469 PKIX_UInt32 newPartialLength
= 0;
470 PKIX_UInt32 bytesConsumed
= 0;
473 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_Append");
474 PKIX_NULLCHECK_TWO(response
, pBytesConsumed
);
476 if (incrLength
> 0) {
478 /* Calculate how many bytes we have room for. */
480 response
->totalLength
- response
->partialLength
;
482 if (bytesConsumed
> incrLength
) {
483 bytesConsumed
= incrLength
;
486 newPartialLength
= response
->partialLength
+ bytesConsumed
;
488 PKIX_NULLCHECK_ONE(incrData
);
490 dest
= &(((char *)response
->derEncoded
.data
)[
491 response
->partialLength
]);
496 (dest
, incrData
, bytesConsumed
));
498 response
->partialLength
= newPartialLength
;
501 *pBytesConsumed
= bytesConsumed
;
503 PKIX_RETURN(LDAPRESPONSE
);
507 * FUNCTION: pkix_pl_LdapResponse_IsComplete
510 * This function determines whether the LdapResponse pointed to by "response"
511 * contains all the data called for by the "totalLength" parameter provided
512 * when it was created, storing PKIX_TRUE at "pIsComplete" if so, and
513 * PKIX_FALSE otherwise.
517 * The address of the LdapResponse being evaluaTED. Must be non-zero.
519 * The UInt32 value for the number of bytes of data available in the
522 * The address from which data is to be copied.
524 * The address at which is stored the Boolean indication of whether the
525 * LdapResponse is complete. Must be non-NULL.
527 * Platform-specific context pointer.
529 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
531 * Returns NULL if the function succeeds.
532 * Returns an LdapResponse Error if the function fails in a non-fatal way.
533 * Returns a Fatal Error if the function fails in an unrecoverable way.
536 pkix_pl_LdapResponse_IsComplete(
537 PKIX_PL_LdapResponse
*response
,
538 PKIX_Boolean
*pIsComplete
,
541 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_IsComplete");
542 PKIX_NULLCHECK_TWO(response
, pIsComplete
);
544 if (response
->totalLength
== response
->partialLength
) {
545 *pIsComplete
= PKIX_TRUE
;
547 *pIsComplete
= PKIX_FALSE
;
550 PKIX_RETURN(LDAPRESPONSE
);
554 * FUNCTION: pkix_pl_LdapResponse_Decode
557 * This function decodes the DER data contained in the LdapResponse pointed to
558 * by "response", using the arena pointed to by "arena", and storing at
559 * "pStatus" SECSuccess if the decoding was successful and SECFailure
560 * otherwise. The decoded message is stored in an element of "response".
564 * The address of the PRArenaPool to be used in the decoding. Must be
567 * The address of the LdapResponse whose DER data is to be decoded. Must
570 * The address at which is stored the status from the decoding, SECSuccess
571 * if successful, SECFailure otherwise. Must be non-NULL.
573 * Platform-specific context pointer.
575 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
577 * Returns NULL if the function succeeds.
578 * Returns an LdapResponse Error if the function fails in a non-fatal way.
579 * Returns a Fatal Error if the function fails in an unrecoverable way.
582 pkix_pl_LdapResponse_Decode(
584 PKIX_PL_LdapResponse
*response
,
589 SECStatus rv
= SECFailure
;
591 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_Decode");
592 PKIX_NULLCHECK_THREE(arena
, response
, pStatus
);
594 if (response
->totalLength
!= response
->partialLength
) {
595 PKIX_ERROR(PKIX_ATTEMPTTODECODEANINCOMPLETERESPONSE
);
598 msg
= &(response
->decoded
);
601 (LDAPRESPONSE
, PORT_Memset
, (msg
, 0, sizeof (LDAPMessage
)));
603 PKIX_PL_NSSCALLRV(LDAPRESPONSE
, rv
, SEC_ASN1DecodeItem
,
604 (NULL
, msg
, PKIX_PL_LDAPMessageTemplate
, &(response
->derEncoded
)));
609 PKIX_RETURN(LDAPRESPONSE
);
613 * FUNCTION: pkix_pl_LdapResponse_GetMessage
616 * This function obtains the decoded message from the LdapResponse pointed to
617 * by "response", storing the result at "pMessage".
621 * The address of the LdapResponse whose decoded message is to be
622 * retrieved. Must be non-NULL.
624 * The address at which is stored the address of the decoded message. Must
627 * Platform-specific context pointer.
629 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
631 * Returns NULL if the function succeeds.
632 * Returns a Fatal Error if the function fails in an unrecoverable way.
635 pkix_pl_LdapResponse_GetMessage(
636 PKIX_PL_LdapResponse
*response
,
637 LDAPMessage
**pMessage
,
640 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_GetMessage");
641 PKIX_NULLCHECK_TWO(response
, pMessage
);
643 *pMessage
= &response
->decoded
;
645 PKIX_RETURN(LDAPRESPONSE
);
649 * FUNCTION: pkix_pl_LdapResponse_GetCapacity
652 * This function obtains from the LdapResponse pointed to by "response" the
653 * number of bytes remaining to be read, based on the totalLength that was
654 * provided to LdapResponse_Create and the data subsequently provided to
655 * LdapResponse_Append, storing the result at "pMessage".
659 * The address of the LdapResponse whose remaining capacity is to be
660 * retrieved. Must be non-NULL.
662 * The address at which is stored the address of the decoded message. Must
665 * Platform-specific context pointer.
667 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
669 * Returns NULL if the function succeeds.
670 * Returns an LdapResponse Error if the function fails in a non-fatal way.
671 * Returns a Fatal Error if the function fails in an unrecoverable way.
674 pkix_pl_LdapResponse_GetCapacity(
675 PKIX_PL_LdapResponse
*response
,
676 PKIX_UInt32
*pCapacity
,
679 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_GetCapacity");
680 PKIX_NULLCHECK_TWO(response
, pCapacity
);
682 *pCapacity
= response
->totalLength
- response
->partialLength
;
684 PKIX_RETURN(LDAPRESPONSE
);
688 * FUNCTION: pkix_pl_LdapResponse_GetMessageType
691 * This function obtains the message type from the LdapResponse pointed to
692 * by "response", storing the result at "pMessageType".
696 * The address of the LdapResponse whose message type is to be
697 * retrieved. Must be non-NULL.
699 * The address at which is stored the type of the response message. Must
702 * Platform-specific context pointer.
704 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
706 * Returns NULL if the function succeeds.
707 * Returns a Fatal Error if the function fails in an unrecoverable way.
710 pkix_pl_LdapResponse_GetMessageType(
711 PKIX_PL_LdapResponse
*response
,
712 LDAPMessageType
*pMessageType
,
715 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_GetMessageType");
716 PKIX_NULLCHECK_TWO(response
, pMessageType
);
718 *pMessageType
= response
->decoded
.protocolOp
.selector
;
720 PKIX_RETURN(LDAPRESPONSE
);
724 * FUNCTION: pkix_pl_LdapResponse_GetResultCode
727 * This function obtains the result code from the LdapResponse pointed to
728 * by "response", storing the result at "pResultCode".
732 * The address of the LdapResponse whose result code is to be
733 * retrieved. Must be non-NULL.
735 * The address at which is stored the address of the decoded message. Must
738 * Platform-specific context pointer.
740 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
742 * Returns NULL if the function succeeds.
743 * Returns an LdapResponse Error if the function fails in a non-fatal way.
744 * Returns a Fatal Error if the function fails in an unrecoverable way.
747 pkix_pl_LdapResponse_GetResultCode(
748 PKIX_PL_LdapResponse
*response
,
749 LDAPResultCode
*pResultCode
,
752 LDAPMessageType messageType
= 0;
753 LDAPSearchResponseResult
*resultMsg
= NULL
;
755 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_GetResultCode");
756 PKIX_NULLCHECK_TWO(response
, pResultCode
);
758 messageType
= response
->decoded
.protocolOp
.selector
;
760 if (messageType
!= LDAP_SEARCHRESPONSERESULT_TYPE
) {
761 PKIX_ERROR(PKIX_GETRESULTCODECALLEDFORNONRESULTMESSAGE
);
764 resultMsg
= &response
->decoded
.protocolOp
.op
.searchResponseResultMsg
;
766 *pResultCode
= *(char *)(resultMsg
->resultCode
.data
);
770 PKIX_RETURN(LDAPRESPONSE
);
774 * FUNCTION: pkix_pl_LdapResponse_GetAttributes
777 * This function obtains the attributes from the LdapResponse pointed to
778 * by "response", storing the result at "pAttributes".
782 * The address of the LdapResponse whose decoded message is to be
783 * retrieved. Must be non-NULL.
785 * The address at which is stored the attributes of the message. Must be
788 * Platform-specific context pointer.
790 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
792 * Returns NULL if the function succeeds.
793 * Returns an LdapResponse Error if the function fails in a non-fatal way.
794 * Returns a Fatal Error if the function fails in an unrecoverable way.
797 pkix_pl_LdapResponse_GetAttributes(
798 PKIX_PL_LdapResponse
*response
,
799 LDAPSearchResponseAttr
***pAttributes
,
802 LDAPMessageType messageType
= 0;
804 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_GetResultCode");
805 PKIX_NULLCHECK_TWO(response
, pAttributes
);
807 messageType
= response
->decoded
.protocolOp
.selector
;
809 if (messageType
!= LDAP_SEARCHRESPONSEENTRY_TYPE
) {
810 PKIX_ERROR(PKIX_GETATTRIBUTESCALLEDFORNONENTRYMESSAGE
);
813 *pAttributes
= response
->
814 decoded
.protocolOp
.op
.searchResponseEntryMsg
.attributes
;
818 PKIX_RETURN(LDAPRESPONSE
);