pkix_pl_ldapresponse.c (26342B)
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 }