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