PageRenderTime 46ms CodeModel.GetById 16ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/libpkix/pkix_pl_nss/module/pkix_pl_ldapresponse.c

http://github.com/zpao/v8monkey
C | 819 lines | 369 code | 106 blank | 344 comment | 53 complexity | 70dab45468c44591dc597de30f31b35c MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  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/
  8 *
  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
 12 * License.
 13 *
 14 * The Original Code is the PKIX-C library.
 15 *
 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.
 20 *
 21 * Contributor(s):
 22 *   Sun Microsystems, Inc.
 23 *
 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.
 35 *
 36 * ***** END LICENSE BLOCK ***** */
 37/*
 38 * pkix_pl_ldapresponse.c
 39 *
 40 */
 41
 42#include <fcntl.h>
 43#include "pkix_pl_ldapresponse.h"
 44
 45/* --Private-LdapResponse-Functions------------------------------------- */
 46
 47/*
 48 * FUNCTION: pkix_pl_LdapResponse_Destroy
 49 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
 50 */
 51static PKIX_Error *
 52pkix_pl_LdapResponse_Destroy(
 53        PKIX_PL_Object *object,
 54        void *plContext)
 55{
 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;
 63        SECItem *val = NULL;
 64
 65        PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Destroy");
 66        PKIX_NULLCHECK_ONE(object);
 67
 68        PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPRESPONSE_TYPE, plContext),
 69                    PKIX_OBJECTNOTLDAPRESPONSE);
 70
 71        ldapRsp = (PKIX_PL_LdapResponse *)object;
 72
 73        m = &ldapRsp->decoded;
 74
 75        if (m->messageID.data != NULL) {
 76                PR_Free(m->messageID.data);
 77        }
 78
 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);
 84                }
 85                if (entry->attributes != NULL) {
 86                        for (attributes = entry->attributes;
 87                                *attributes != NULL;
 88                                attributes++) {
 89                                attr = *attributes;
 90                                PR_Free(attr->attrType.data);
 91                                for (valp = attr->val; *valp != NULL; valp++) {
 92                                        val = *valp;
 93                                        if (val->data != NULL) {
 94                                                PR_Free(val->data);
 95                                        }
 96                                        PR_Free(val);
 97                                }
 98                                PR_Free(attr->val);
 99                                PR_Free(attr);
100                        }
101                        PR_Free(entry->attributes);
102                }
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);
108                }
109        }
110
111        PKIX_FREE(ldapRsp->derEncoded.data);
112
113cleanup:
114
115        PKIX_RETURN(LDAPRESPONSE);
116}
117
118/*
119 * FUNCTION: pkix_pl_LdapResponse_Hashcode
120 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
121 */
122static PKIX_Error *
123pkix_pl_LdapResponse_Hashcode(
124        PKIX_PL_Object *object,
125        PKIX_UInt32 *pHashcode,
126        void *plContext)
127{
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;
134
135        PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Hashcode");
136        PKIX_NULLCHECK_TWO(object, pHashcode);
137
138        PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPRESPONSE_TYPE, plContext),
139                    PKIX_OBJECTNOTLDAPRESPONSE);
140
141        ldapRsp = (PKIX_PL_LdapResponse *)object;
142
143        *pHashcode = 0;
144
145        /*
146         * Two responses that differ only in msgnum are a match! Therefore,
147         * start hashcoding beyond the encoded messageID field.
148         */
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];
156                        }
157                } else {
158                        dataLen = msgBuf[1];
159                }
160
161                /* How many bytes for the messageID? (Assume short form) */
162                idLen = msgBuf[dindex + 3] + 2;
163                dindex += idLen;
164                dataLen -= idLen;
165                msgBuf = &msgBuf[dindex + 2];
166
167                PKIX_CHECK(pkix_hash(msgBuf, dataLen, pHashcode, plContext),
168                        PKIX_HASHFAILED);
169        }
170
171cleanup:
172
173        PKIX_RETURN(LDAPRESPONSE);
174
175}
176
177/*
178 * FUNCTION: pkix_pl_LdapResponse_Equals
179 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
180 */
181static PKIX_Error *
182pkix_pl_LdapResponse_Equals(
183        PKIX_PL_Object *firstObj,
184        PKIX_PL_Object *secondObj,
185        PKIX_Boolean *pResult,
186        void *plContext)
187{
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;
196        PKIX_UInt32 i = 0;
197
198        PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_Equals");
199        PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult);
200
201        /* test that firstObj is a LdapResponse */
202        PKIX_CHECK(pkix_CheckType(firstObj, PKIX_LDAPRESPONSE_TYPE, plContext),
203                    PKIX_FIRSTOBJARGUMENTNOTLDAPRESPONSE);
204
205        /*
206         * Since we know firstObj is a LdapResponse, if both references are
207         * identical, they must be equal
208         */
209        if (firstObj == secondObj){
210                *pResult = PKIX_TRUE;
211                goto cleanup;
212        }
213
214        /*
215         * If secondObj isn't a LdapResponse, we don't throw an error.
216         * We simply return a Boolean result of FALSE
217         */
218        *pResult = PKIX_FALSE;
219        PKIX_CHECK(PKIX_PL_Object_GetType(secondObj, &secondType, plContext),
220                PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
221        if (secondType != PKIX_LDAPRESPONSE_TYPE) {
222                goto cleanup;
223        }
224
225        rsp1 = (PKIX_PL_LdapResponse *)firstObj;
226        rsp2 = (PKIX_PL_LdapResponse *)secondObj;
227
228        /* If either lacks an encoded string, they cannot be compared */
229        if (!(rsp1->derEncoded.data) || !(rsp2->derEncoded.data)) {
230                goto cleanup;
231        }
232
233        if (rsp1->derEncoded.len != rsp2->derEncoded.len) {
234                goto cleanup;
235        }
236
237        firstData = (const unsigned char *)rsp1->derEncoded.data;
238        secondData = (const unsigned char *)rsp2->derEncoded.data;
239
240        /*
241         * Two responses that differ only in msgnum are equal! Therefore,
242         * start the byte comparison beyond the encoded messageID field.
243         */
244
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];
250                }
251        } else {
252                firstLen = firstData[1];
253        }
254
255        /* How many bytes for the messageID? (Assume short form) */
256        i = firstData[dindex + 3] + 2;
257        dindex += i;
258        firstLen -= i;
259        firstData = &firstData[dindex + 2];
260
261        /*
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.
266         */
267
268        secondData = &secondData[dindex + 2];
269        
270        for (i = 0; i < firstLen; i++) {
271                if (firstData[i] != secondData[i]) {
272                        goto cleanup;
273                }
274        }
275
276        *pResult = PKIX_TRUE;
277
278cleanup:
279
280        PKIX_RETURN(LDAPRESPONSE);
281}
282
283/*
284 * FUNCTION: pkix_pl_LdapResponse_RegisterSelf
285 * DESCRIPTION:
286 *  Registers PKIX_LDAPRESPONSE_TYPE and its related functions with
287 *  systemClasses[]
288 * PARAMETERS:
289 *  "plContext"
290 *      Platform-specific context pointer.
291 * THREAD SAFETY:
292 *  Not Thread Safe - for performance and complexity reasons
293 *
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
296 *  thread-safe.
297 */
298PKIX_Error *
299pkix_pl_LdapResponse_RegisterSelf(void *plContext)
300{
301        extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
302        pkix_ClassTable_Entry entry;
303
304        PKIX_ENTER(LDAPRESPONSE, "pkix_pl_LdapResponse_RegisterSelf");
305
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;
315
316        systemClasses[PKIX_LDAPRESPONSE_TYPE] = entry;
317
318        PKIX_RETURN(LDAPRESPONSE);
319}
320
321/* --Public-Functions------------------------------------------------------- */
322
323/*
324 * FUNCTION: pkix_pl_LdapResponse_Create
325 * DESCRIPTION:
326 *
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".
333 *
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.
338 *
339 * PARAMETERS
340 *  "responseType"
341 *      The value of the message type (LDAP_SEARCHRESPONSEENTRY_TYPE or
342 *      LDAP_SEARCHRESPONSERESULT_TYPE) for the LdapResponse being created
343 *  "totalLength"
344 *      The UInt32 value for the total length of the encoded message to be
345 *      stored in the LdapResponse
346 *  "bytesAvailable"
347 *      The UInt32 value for the number of bytes of data available in the
348 *      current buffer.
349 *  "partialData"
350 *      The address from which data is to be copied.
351 *  "pBytesConsumed"
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.
355 *  "pLdapResponse"
356 *      The address where the created LdapResponse is stored. Must be non-NULL.
357 *  "plContext"
358 *      Platform-specific context pointer.
359 * THREAD SAFETY:
360 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
361 * RETURNS:
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.
365 */
366PKIX_Error *
367pkix_pl_LdapResponse_Create(
368        LDAPMessageType responseType,
369        PKIX_UInt32 totalLength,
370        PKIX_UInt32 bytesAvailable,
371        void *partialData,
372        PKIX_UInt32 *pBytesConsumed,
373        PKIX_PL_LdapResponse **pLdapResponse,
374        void *plContext)
375{
376        PKIX_UInt32 bytesConsumed = 0;
377        PKIX_PL_LdapResponse *ldapResponse = NULL;
378        void *data = NULL;
379
380        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Create");
381        PKIX_NULLCHECK_ONE(pLdapResponse);
382
383        if (bytesAvailable <= totalLength) {
384                bytesConsumed = bytesAvailable;
385        } else {
386                bytesConsumed = totalLength;
387        }
388
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,
394                    plContext),
395                    PKIX_COULDNOTCREATEOBJECT);
396
397        ldapResponse->decoded.protocolOp.selector = responseType;
398        ldapResponse->totalLength = totalLength;
399        ldapResponse->partialLength = bytesConsumed;
400
401        if (totalLength != 0){
402                /* Alloc space for array */
403                PKIX_NULLCHECK_ONE(partialData);
404
405                PKIX_CHECK(PKIX_PL_Malloc
406                    (totalLength,
407                    &data,
408                    plContext),
409                    PKIX_MALLOCFAILED);
410
411                PKIX_PL_NSSCALL
412                    (LDAPRESPONSE,
413                    PORT_Memcpy,
414                    (data, partialData, bytesConsumed));
415        }
416
417        ldapResponse->derEncoded.type = siBuffer;
418        ldapResponse->derEncoded.data = data;
419        ldapResponse->derEncoded.len = totalLength;
420        *pBytesConsumed = bytesConsumed;
421        *pLdapResponse = ldapResponse;
422
423cleanup:
424
425        if (PKIX_ERROR_RECEIVED){
426                PKIX_DECREF(ldapResponse);
427        }
428
429        PKIX_RETURN(LDAPRESPONSE);
430}
431
432/*
433 * FUNCTION: pkix_pl_LdapResponse_Append
434 * DESCRIPTION:
435 *
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".
439 *
440 * PARAMETERS
441 *  "response"
442 *      The address of the LdapResponse being updated. Must be non-zero.
443 *  "incrLength"
444 *      The UInt32 value for the number of bytes of data available in the
445 *      current buffer.
446 *  "incrData"
447 *      The address from which data is to be copied.
448 *  "pBytesConsumed"
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.
452 *  "plContext"
453 *      Platform-specific context pointer.
454 * THREAD SAFETY:
455 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
456 * RETURNS:
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.
460 */
461PKIX_Error *
462pkix_pl_LdapResponse_Append(
463        PKIX_PL_LdapResponse *response,
464        PKIX_UInt32 incrLength,
465        void *incrData,
466        PKIX_UInt32 *pBytesConsumed,
467        void *plContext)
468{
469        PKIX_UInt32 newPartialLength = 0;
470        PKIX_UInt32 bytesConsumed = 0;
471        void *dest = NULL;
472
473        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Append");
474        PKIX_NULLCHECK_TWO(response, pBytesConsumed);
475
476        if (incrLength > 0) {
477
478                /* Calculate how many bytes we have room for. */
479                bytesConsumed =
480                        response->totalLength - response->partialLength;
481
482                if (bytesConsumed > incrLength) {
483                        bytesConsumed = incrLength;
484                }
485
486                newPartialLength = response->partialLength + bytesConsumed;
487
488                PKIX_NULLCHECK_ONE(incrData);
489
490                dest = &(((char *)response->derEncoded.data)[
491                        response->partialLength]);
492
493                PKIX_PL_NSSCALL
494                        (LDAPRESPONSE,
495                        PORT_Memcpy,
496                        (dest, incrData, bytesConsumed));
497
498                response->partialLength = newPartialLength;
499        }
500
501        *pBytesConsumed = bytesConsumed;
502
503        PKIX_RETURN(LDAPRESPONSE);
504}
505
506/*
507 * FUNCTION: pkix_pl_LdapResponse_IsComplete
508 * DESCRIPTION:
509 *
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.
514 *
515 * PARAMETERS
516 *  "response"
517 *      The address of the LdapResponse being evaluaTED. Must be non-zero.
518 *  "incrLength"
519 *      The UInt32 value for the number of bytes of data available in the
520 *      current buffer.
521 *  "incrData"
522 *      The address from which data is to be copied.
523 *  "pIsComplete"
524 *      The address at which is stored the Boolean indication of whether the
525 *      LdapResponse is complete. Must be non-NULL.
526 *  "plContext"
527 *      Platform-specific context pointer.
528 * THREAD SAFETY:
529 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
530 * RETURNS:
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.
534 */
535PKIX_Error *
536pkix_pl_LdapResponse_IsComplete(
537        PKIX_PL_LdapResponse *response,
538        PKIX_Boolean *pIsComplete,
539        void *plContext)
540{
541        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_IsComplete");
542        PKIX_NULLCHECK_TWO(response, pIsComplete);
543
544        if (response->totalLength == response->partialLength) {
545                *pIsComplete = PKIX_TRUE;
546        } else {
547                *pIsComplete = PKIX_FALSE;
548        }
549
550        PKIX_RETURN(LDAPRESPONSE);
551}
552
553/*
554 * FUNCTION: pkix_pl_LdapResponse_Decode
555 * DESCRIPTION:
556 *
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".
561 *
562 * PARAMETERS
563 *  "arena"
564 *      The address of the PRArenaPool to be used in the decoding. Must be
565 *      non-NULL.
566 *  "response"
567 *      The address of the LdapResponse whose DER data is to be decoded. Must
568 *      be non-NULL.
569 *  "pStatus"
570 *      The address at which is stored the status from the decoding, SECSuccess
571 *      if successful, SECFailure otherwise. Must be non-NULL.
572 *  "plContext"
573 *      Platform-specific context pointer.
574 * THREAD SAFETY:
575 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
576 * RETURNS:
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.
580 */
581PKIX_Error *
582pkix_pl_LdapResponse_Decode(
583        PRArenaPool *arena,
584        PKIX_PL_LdapResponse *response,
585        SECStatus *pStatus,
586        void *plContext)
587{
588        LDAPMessage *msg;
589        SECStatus rv = SECFailure;
590
591        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_Decode");
592        PKIX_NULLCHECK_THREE(arena, response, pStatus);
593
594        if (response->totalLength != response->partialLength) {
595                PKIX_ERROR(PKIX_ATTEMPTTODECODEANINCOMPLETERESPONSE);
596        }
597
598        msg = &(response->decoded);
599
600        PKIX_PL_NSSCALL
601                (LDAPRESPONSE, PORT_Memset, (msg, 0, sizeof (LDAPMessage)));
602
603        PKIX_PL_NSSCALLRV(LDAPRESPONSE, rv, SEC_ASN1DecodeItem,
604            (NULL, msg, PKIX_PL_LDAPMessageTemplate, &(response->derEncoded)));
605
606        *pStatus = rv;
607cleanup:
608
609        PKIX_RETURN(LDAPRESPONSE);
610}
611
612/*
613 * FUNCTION: pkix_pl_LdapResponse_GetMessage
614 * DESCRIPTION:
615 *
616 *  This function obtains the decoded message from the LdapResponse pointed to
617 *  by "response", storing the result at "pMessage".
618 *
619 * PARAMETERS
620 *  "response"
621 *      The address of the LdapResponse whose decoded message is to be
622 *      retrieved. Must be non-NULL.
623 *  "pMessage"
624 *      The address at which is stored the address of the decoded message. Must
625 *      be non-NULL.
626 *  "plContext"
627 *      Platform-specific context pointer.
628 * THREAD SAFETY:
629 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
630 * RETURNS:
631 *  Returns NULL if the function succeeds.
632 *  Returns a Fatal Error if the function fails in an unrecoverable way.
633 */
634PKIX_Error *
635pkix_pl_LdapResponse_GetMessage(
636        PKIX_PL_LdapResponse *response,
637        LDAPMessage **pMessage,
638        void *plContext)
639{
640        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetMessage");
641        PKIX_NULLCHECK_TWO(response, pMessage);
642
643        *pMessage = &response->decoded;
644
645        PKIX_RETURN(LDAPRESPONSE);
646}
647
648/*
649 * FUNCTION: pkix_pl_LdapResponse_GetCapacity
650 * DESCRIPTION:
651 *
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".
656 *
657 * PARAMETERS
658 *  "response"
659 *      The address of the LdapResponse whose remaining capacity is to be
660 *      retrieved. Must be non-NULL.
661 *  "pCapacity"
662 *      The address at which is stored the address of the decoded message. Must
663 *      be non-NULL.
664 *  "plContext"
665 *      Platform-specific context pointer.
666 * THREAD SAFETY:
667 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
668 * RETURNS:
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.
672 */
673PKIX_Error *
674pkix_pl_LdapResponse_GetCapacity(
675        PKIX_PL_LdapResponse *response,
676        PKIX_UInt32 *pCapacity,
677        void *plContext)
678{
679        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetCapacity");
680        PKIX_NULLCHECK_TWO(response, pCapacity);
681
682        *pCapacity = response->totalLength - response->partialLength;
683
684        PKIX_RETURN(LDAPRESPONSE);
685}
686
687/*
688 * FUNCTION: pkix_pl_LdapResponse_GetMessageType
689 * DESCRIPTION:
690 *
691 *  This function obtains the message type from the LdapResponse pointed to
692 *  by "response", storing the result at "pMessageType".
693 *
694 * PARAMETERS
695 *  "response"
696 *      The address of the LdapResponse whose message type is to be
697 *      retrieved. Must be non-NULL.
698 *  "pMessageType" 
699 *      The address at which is stored the type of the response message. Must
700 *      be non-NULL.
701 *  "plContext"
702 *      Platform-specific context pointer.
703 * THREAD SAFETY:
704 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
705 * RETURNS:
706 *  Returns NULL if the function succeeds.
707 *  Returns a Fatal Error if the function fails in an unrecoverable way.
708 */
709PKIX_Error *
710pkix_pl_LdapResponse_GetMessageType(
711        PKIX_PL_LdapResponse *response,
712        LDAPMessageType *pMessageType,
713        void *plContext)
714{
715        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetMessageType");
716        PKIX_NULLCHECK_TWO(response, pMessageType);
717
718        *pMessageType = response->decoded.protocolOp.selector;
719
720        PKIX_RETURN(LDAPRESPONSE);
721}
722
723/*
724 * FUNCTION: pkix_pl_LdapResponse_GetResultCode
725 * DESCRIPTION:
726 *
727 *  This function obtains the result code from the LdapResponse pointed to
728 *  by "response", storing the result at "pResultCode".
729 *
730 * PARAMETERS
731 *  "response"
732 *      The address of the LdapResponse whose result code is to be
733 *      retrieved. Must be non-NULL.
734 *  "pResultCode"
735 *      The address at which is stored the address of the decoded message. Must
736 *      be non-NULL.
737 *  "plContext"
738 *      Platform-specific context pointer.
739 * THREAD SAFETY:
740 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
741 * RETURNS:
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.
745 */
746PKIX_Error *
747pkix_pl_LdapResponse_GetResultCode(
748        PKIX_PL_LdapResponse *response,
749        LDAPResultCode *pResultCode,
750        void *plContext)
751{
752        LDAPMessageType messageType = 0;
753        LDAPSearchResponseResult *resultMsg = NULL;
754
755        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetResultCode");
756        PKIX_NULLCHECK_TWO(response, pResultCode);
757
758        messageType = response->decoded.protocolOp.selector;
759
760        if (messageType != LDAP_SEARCHRESPONSERESULT_TYPE) {
761                PKIX_ERROR(PKIX_GETRESULTCODECALLEDFORNONRESULTMESSAGE);
762        }
763
764        resultMsg = &response->decoded.protocolOp.op.searchResponseResultMsg;
765
766        *pResultCode = *(char *)(resultMsg->resultCode.data);
767
768cleanup:
769
770        PKIX_RETURN(LDAPRESPONSE);
771}
772
773/*
774 * FUNCTION: pkix_pl_LdapResponse_GetAttributes
775 * DESCRIPTION:
776 *
777 *  This function obtains the attributes from the LdapResponse pointed to
778 *  by "response", storing the result at "pAttributes".
779 *
780 * PARAMETERS
781 *  "response"
782 *      The address of the LdapResponse whose decoded message is to be
783 *      retrieved. Must be non-NULL.
784 *  "pAttributes"
785 *      The address at which is stored the attributes of the message. Must be
786 *      non-NULL.
787 *  "plContext"
788 *      Platform-specific context pointer.
789 * THREAD SAFETY:
790 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
791 * RETURNS:
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.
795 */
796PKIX_Error *
797pkix_pl_LdapResponse_GetAttributes(
798        PKIX_PL_LdapResponse *response,
799        LDAPSearchResponseAttr ***pAttributes,
800        void *plContext)
801{
802        LDAPMessageType messageType = 0;
803
804        PKIX_ENTER(LDAPRESPONSE, "PKIX_PL_LdapResponse_GetResultCode");
805        PKIX_NULLCHECK_TWO(response, pAttributes);
806
807        messageType = response->decoded.protocolOp.selector;
808
809        if (messageType != LDAP_SEARCHRESPONSEENTRY_TYPE) {
810                PKIX_ERROR(PKIX_GETATTRIBUTESCALLEDFORNONENTRYMESSAGE);
811        }
812
813        *pAttributes = response->
814                decoded.protocolOp.op.searchResponseEntryMsg.attributes;
815
816cleanup:
817
818        PKIX_RETURN(LDAPRESPONSE);
819}