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 Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
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
.destructor
= pkix_pl_LdapResponse_Destroy
;
308 entry
.equalsFunction
= pkix_pl_LdapResponse_Equals
;
309 entry
.hashcodeFunction
= pkix_pl_LdapResponse_Hashcode
;
310 entry
.toStringFunction
= NULL
;
311 entry
.comparator
= NULL
;
312 entry
.duplicateFunction
= pkix_duplicateImmutable
;
314 systemClasses
[PKIX_LDAPRESPONSE_TYPE
] = entry
;
316 PKIX_RETURN(LDAPRESPONSE
);
319 /* --Public-Functions------------------------------------------------------- */
322 * FUNCTION: pkix_pl_LdapResponse_Create
325 * This function creates an LdapResponse for the LDAPMessageType provided in
326 * "responseType" and a buffer capacity provided by "totalLength". It copies
327 * into its buffer either "totalLength" or "bytesAvailable" bytes, whichever
328 * is less, from the buffer pointed to by "partialData", storing the number of
329 * bytes copied at "pBytesConsumed" and storing the address of the LdapResponse
330 * at "pLdapResponse".
332 * If a message is complete in a single I/O buffer, the LdapResponse will be
333 * complete when this function returns. If the message carries over into
334 * additional buffers, their contents will be added to the LdapResponse by
335 * susequent calls to pkix_pl_LdapResponse_Append.
339 * The value of the message type (LDAP_SEARCHRESPONSEENTRY_TYPE or
340 * LDAP_SEARCHRESPONSERESULT_TYPE) for the LdapResponse being created
342 * The UInt32 value for the total length of the encoded message to be
343 * stored in the LdapResponse
345 * The UInt32 value for the number of bytes of data available in the
348 * The address from which data is to be copied.
350 * The address at which is stored the UInt32 number of bytes taken from the
351 * current buffer. If this number is less than "bytesAvailable", then bytes
352 * remain in the buffer for the next LdapResponse. Must be non-NULL.
354 * The address where the created LdapResponse is stored. Must be non-NULL.
356 * Platform-specific context pointer.
358 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
360 * Returns NULL if the function succeeds.
361 * Returns an LdapResponse Error if the function fails in a non-fatal way.
362 * Returns a Fatal Error if the function fails in an unrecoverable way.
365 pkix_pl_LdapResponse_Create(
366 LDAPMessageType responseType
,
367 PKIX_UInt32 totalLength
,
368 PKIX_UInt32 bytesAvailable
,
370 PKIX_UInt32
*pBytesConsumed
,
371 PKIX_PL_LdapResponse
**pLdapResponse
,
374 PKIX_UInt32 bytesConsumed
= 0;
375 PKIX_PL_LdapResponse
*ldapResponse
= NULL
;
378 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_Create");
379 PKIX_NULLCHECK_ONE(pLdapResponse
);
381 if (bytesAvailable
<= totalLength
) {
382 bytesConsumed
= bytesAvailable
;
384 bytesConsumed
= totalLength
;
387 /* create a PKIX_PL_LdapResponse object */
388 PKIX_CHECK(PKIX_PL_Object_Alloc
389 (PKIX_LDAPRESPONSE_TYPE
,
390 sizeof (PKIX_PL_LdapResponse
),
391 (PKIX_PL_Object
**)&ldapResponse
,
393 PKIX_COULDNOTCREATEOBJECT
);
395 ldapResponse
->decoded
.protocolOp
.selector
= responseType
;
396 ldapResponse
->totalLength
= totalLength
;
397 ldapResponse
->partialLength
= bytesConsumed
;
399 if (totalLength
!= 0){
400 /* Alloc space for array */
401 PKIX_NULLCHECK_ONE(partialData
);
403 PKIX_CHECK(PKIX_PL_Malloc
412 (data
, partialData
, bytesConsumed
));
415 ldapResponse
->derEncoded
.type
= siBuffer
;
416 ldapResponse
->derEncoded
.data
= data
;
417 ldapResponse
->derEncoded
.len
= totalLength
;
418 *pBytesConsumed
= bytesConsumed
;
419 *pLdapResponse
= ldapResponse
;
423 if (PKIX_ERROR_RECEIVED
){
424 PKIX_DECREF(ldapResponse
);
427 PKIX_RETURN(LDAPRESPONSE
);
431 * FUNCTION: pkix_pl_LdapResponse_Append
434 * This function updates the LdapResponse pointed to by "response" with up to
435 * "incrLength" from the buffer pointer to by "incrData", storing the number of
436 * bytes copied at "pBytesConsumed".
440 * The address of the LdapResponse being updated. Must be non-zero.
442 * The UInt32 value for the number of bytes of data available in the
445 * The address from which data is to be copied.
447 * The address at which is stored the UInt32 number of bytes taken from the
448 * current buffer. If this number is less than "incrLength", then bytes
449 * remain in the buffer for the next LdapResponse. Must be non-NULL.
451 * Platform-specific context pointer.
453 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
455 * Returns NULL if the function succeeds.
456 * Returns an LdapResponse Error if the function fails in a non-fatal way.
457 * Returns a Fatal Error if the function fails in an unrecoverable way.
460 pkix_pl_LdapResponse_Append(
461 PKIX_PL_LdapResponse
*response
,
462 PKIX_UInt32 incrLength
,
464 PKIX_UInt32
*pBytesConsumed
,
467 PKIX_UInt32 newPartialLength
= 0;
468 PKIX_UInt32 bytesConsumed
= 0;
471 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_Append");
472 PKIX_NULLCHECK_TWO(response
, pBytesConsumed
);
474 if (incrLength
> 0) {
476 /* Calculate how many bytes we have room for. */
478 response
->totalLength
- response
->partialLength
;
480 if (bytesConsumed
> incrLength
) {
481 bytesConsumed
= incrLength
;
484 newPartialLength
= response
->partialLength
+ bytesConsumed
;
486 PKIX_NULLCHECK_ONE(incrData
);
488 dest
= &(((char *)response
->derEncoded
.data
)[
489 response
->partialLength
]);
494 (dest
, incrData
, bytesConsumed
));
496 response
->partialLength
= newPartialLength
;
499 *pBytesConsumed
= bytesConsumed
;
501 PKIX_RETURN(LDAPRESPONSE
);
505 * FUNCTION: pkix_pl_LdapResponse_IsComplete
508 * This function determines whether the LdapResponse pointed to by "response"
509 * contains all the data called for by the "totalLength" parameter provided
510 * when it was created, storing PKIX_TRUE at "pIsComplete" if so, and
511 * PKIX_FALSE otherwise.
515 * The address of the LdapResponse being evaluaTED. Must be non-zero.
517 * The UInt32 value for the number of bytes of data available in the
520 * The address from which data is to be copied.
522 * The address at which is stored the Boolean indication of whether the
523 * LdapResponse is complete. Must be non-NULL.
525 * Platform-specific context pointer.
527 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
529 * Returns NULL if the function succeeds.
530 * Returns an LdapResponse Error if the function fails in a non-fatal way.
531 * Returns a Fatal Error if the function fails in an unrecoverable way.
534 pkix_pl_LdapResponse_IsComplete(
535 PKIX_PL_LdapResponse
*response
,
536 PKIX_Boolean
*pIsComplete
,
539 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_IsComplete");
540 PKIX_NULLCHECK_TWO(response
, pIsComplete
);
542 if (response
->totalLength
== response
->partialLength
) {
543 *pIsComplete
= PKIX_TRUE
;
545 *pIsComplete
= PKIX_FALSE
;
548 PKIX_RETURN(LDAPRESPONSE
);
552 * FUNCTION: pkix_pl_LdapResponse_Decode
555 * This function decodes the DER data contained in the LdapResponse pointed to
556 * by "response", using the arena pointed to by "arena", and storing at
557 * "pStatus" SECSuccess if the decoding was successful and SECFailure
558 * otherwise. The decoded message is stored in an element of "response".
562 * The address of the PRArenaPool to be used in the decoding. Must be
565 * The address of the LdapResponse whose DER data is to be decoded. Must
568 * The address at which is stored the status from the decoding, SECSuccess
569 * if successful, SECFailure otherwise. Must be non-NULL.
571 * Platform-specific context pointer.
573 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
575 * Returns NULL if the function succeeds.
576 * Returns an LdapResponse Error if the function fails in a non-fatal way.
577 * Returns a Fatal Error if the function fails in an unrecoverable way.
580 pkix_pl_LdapResponse_Decode(
582 PKIX_PL_LdapResponse
*response
,
587 SECStatus rv
= SECFailure
;
589 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_Decode");
590 PKIX_NULLCHECK_THREE(arena
, response
, pStatus
);
592 if (response
->totalLength
!= response
->partialLength
) {
593 PKIX_ERROR(PKIX_ATTEMPTTODECODEANINCOMPLETERESPONSE
);
596 msg
= &(response
->decoded
);
599 (LDAPRESPONSE
, PORT_Memset
, (msg
, 0, sizeof (LDAPMessage
)));
601 PKIX_PL_NSSCALLRV(LDAPRESPONSE
, rv
, SEC_ASN1DecodeItem
,
602 (NULL
, msg
, PKIX_PL_LDAPMessageTemplate
, &(response
->derEncoded
)));
607 PKIX_RETURN(LDAPRESPONSE
);
611 * FUNCTION: pkix_pl_LdapResponse_GetMessage
614 * This function obtains the decoded message from the LdapResponse pointed to
615 * by "response", storing the result at "pMessage".
619 * The address of the LdapResponse whose decoded message is to be
620 * retrieved. Must be non-NULL.
622 * The address at which is stored the address of the decoded message. Must
625 * Platform-specific context pointer.
627 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
629 * Returns NULL if the function succeeds.
630 * Returns a Fatal Error if the function fails in an unrecoverable way.
633 pkix_pl_LdapResponse_GetMessage(
634 PKIX_PL_LdapResponse
*response
,
635 LDAPMessage
**pMessage
,
638 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_GetMessage");
639 PKIX_NULLCHECK_TWO(response
, pMessage
);
641 *pMessage
= &response
->decoded
;
643 PKIX_RETURN(LDAPRESPONSE
);
647 * FUNCTION: pkix_pl_LdapResponse_GetCapacity
650 * This function obtains from the LdapResponse pointed to by "response" the
651 * number of bytes remaining to be read, based on the totalLength that was
652 * provided to LdapResponse_Create and the data subsequently provided to
653 * LdapResponse_Append, storing the result at "pMessage".
657 * The address of the LdapResponse whose remaining capacity is to be
658 * retrieved. Must be non-NULL.
660 * The address at which is stored the address of the decoded message. Must
663 * Platform-specific context pointer.
665 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
667 * Returns NULL if the function succeeds.
668 * Returns an LdapResponse Error if the function fails in a non-fatal way.
669 * Returns a Fatal Error if the function fails in an unrecoverable way.
672 pkix_pl_LdapResponse_GetCapacity(
673 PKIX_PL_LdapResponse
*response
,
674 PKIX_UInt32
*pCapacity
,
677 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_GetCapacity");
678 PKIX_NULLCHECK_TWO(response
, pCapacity
);
680 *pCapacity
= response
->totalLength
- response
->partialLength
;
682 PKIX_RETURN(LDAPRESPONSE
);
686 * FUNCTION: pkix_pl_LdapResponse_GetMessageType
689 * This function obtains the message type from the LdapResponse pointed to
690 * by "response", storing the result at "pMessageType".
694 * The address of the LdapResponse whose message type is to be
695 * retrieved. Must be non-NULL.
697 * The address at which is stored the type of the response message. Must
700 * Platform-specific context pointer.
702 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
704 * Returns NULL if the function succeeds.
705 * Returns a Fatal Error if the function fails in an unrecoverable way.
708 pkix_pl_LdapResponse_GetMessageType(
709 PKIX_PL_LdapResponse
*response
,
710 LDAPMessageType
*pMessageType
,
713 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_GetMessageType");
714 PKIX_NULLCHECK_TWO(response
, pMessageType
);
716 *pMessageType
= response
->decoded
.protocolOp
.selector
;
718 PKIX_RETURN(LDAPRESPONSE
);
722 * FUNCTION: pkix_pl_LdapResponse_GetResultCode
725 * This function obtains the result code from the LdapResponse pointed to
726 * by "response", storing the result at "pResultCode".
730 * The address of the LdapResponse whose result code is to be
731 * retrieved. Must be non-NULL.
733 * The address at which is stored the address of the decoded message. Must
736 * Platform-specific context pointer.
738 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
740 * Returns NULL if the function succeeds.
741 * Returns an LdapResponse Error if the function fails in a non-fatal way.
742 * Returns a Fatal Error if the function fails in an unrecoverable way.
745 pkix_pl_LdapResponse_GetResultCode(
746 PKIX_PL_LdapResponse
*response
,
747 LDAPResultCode
*pResultCode
,
750 LDAPMessageType messageType
= 0;
751 LDAPSearchResponseResult
*resultMsg
= NULL
;
753 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_GetResultCode");
754 PKIX_NULLCHECK_TWO(response
, pResultCode
);
756 messageType
= response
->decoded
.protocolOp
.selector
;
758 if (messageType
!= LDAP_SEARCHRESPONSERESULT_TYPE
) {
759 PKIX_ERROR(PKIX_GETRESULTCODECALLEDFORNONRESULTMESSAGE
);
762 resultMsg
= &response
->decoded
.protocolOp
.op
.searchResponseResultMsg
;
764 *pResultCode
= *(char *)(resultMsg
->resultCode
.data
);
768 PKIX_RETURN(LDAPRESPONSE
);
772 * FUNCTION: pkix_pl_LdapResponse_GetAttributes
775 * This function obtains the attributes from the LdapResponse pointed to
776 * by "response", storing the result at "pAttributes".
780 * The address of the LdapResponse whose decoded message is to be
781 * retrieved. Must be non-NULL.
783 * The address at which is stored the attributes of the message. Must be
786 * Platform-specific context pointer.
788 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
790 * Returns NULL if the function succeeds.
791 * Returns an LdapResponse Error if the function fails in a non-fatal way.
792 * Returns a Fatal Error if the function fails in an unrecoverable way.
795 pkix_pl_LdapResponse_GetAttributes(
796 PKIX_PL_LdapResponse
*response
,
797 LDAPSearchResponseAttr
***pAttributes
,
800 LDAPMessageType messageType
= 0;
802 PKIX_ENTER(LDAPRESPONSE
, "PKIX_PL_LdapResponse_GetResultCode");
803 PKIX_NULLCHECK_TWO(response
, pAttributes
);
805 messageType
= response
->decoded
.protocolOp
.selector
;
807 if (messageType
!= LDAP_SEARCHRESPONSEENTRY_TYPE
) {
808 PKIX_ERROR(PKIX_GETATTRIBUTESCALLEDFORNONENTRYMESSAGE
);
811 *pAttributes
= response
->
812 decoded
.protocolOp
.op
.searchResponseEntryMsg
.attributes
;
816 PKIX_RETURN(LDAPRESPONSE
);