pkix_pl_ldaprequest.c (27485B)
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_ldaprequest.c 6 * 7 */ 8 9 #include "pkix_pl_ldaprequest.h" 10 11 /* --Private-LdapRequest-Functions------------------------------------- */ 12 13 /* Note: lengths do not include the NULL terminator */ 14 static const char caAttr[] = "caCertificate;binary"; 15 static unsigned int caAttrLen = sizeof(caAttr) - 1; 16 static const char uAttr[] = "userCertificate;binary"; 17 static unsigned int uAttrLen = sizeof(uAttr) - 1; 18 static const char ccpAttr[] = "crossCertificatePair;binary"; 19 static unsigned int ccpAttrLen = sizeof(ccpAttr) - 1; 20 static const char crlAttr[] = "certificateRevocationList;binary"; 21 static unsigned int crlAttrLen = sizeof(crlAttr) - 1; 22 static const char arlAttr[] = "authorityRevocationList;binary"; 23 static unsigned int arlAttrLen = sizeof(arlAttr) - 1; 24 25 /* 26 * XXX If this function were moved into pkix_pl_ldapcertstore.c then all of 27 * LdapRequest and LdapResponse could be considered part of the LDAP client. 28 * But the constants, above, would have to be copied as well, and they are 29 * also needed in pkix_pl_LdapRequest_EncodeAttrs. So there would have to be 30 * two copies. 31 */ 32 33 /* 34 * FUNCTION: pkix_pl_LdapRequest_AttrTypeToBit 35 * DESCRIPTION: 36 * 37 * This function creates an attribute mask bit corresponding to the SECItem 38 * pointed to by "attrType", storing the result at "pAttrBit". The comparison 39 * is case-insensitive. If "attrType" does not match any of the known types, 40 * zero is stored at "pAttrBit". 41 * 42 * PARAMETERS 43 * "attrType" 44 * The address of the SECItem whose string contents are to be compared to 45 * the various known attribute types. Must be non-NULL. 46 * "pAttrBit" 47 * The address where the result is stored. Must be non-NULL. 48 * "plContext" 49 * Platform-specific context pointer. 50 * THREAD SAFETY: 51 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 52 * RETURNS: 53 * Returns NULL if the function succeeds. 54 * Returns an LdapRequest Error if the function fails in a non-fatal way. 55 * Returns a Fatal Error if the function fails in an unrecoverable way. 56 */ 57 PKIX_Error * 58 pkix_pl_LdapRequest_AttrTypeToBit( 59 SECItem *attrType, 60 LdapAttrMask *pAttrBit, 61 void *plContext) 62 { 63 LdapAttrMask attrBit = 0; 64 unsigned int attrLen = 0; 65 const char *s = NULL; 66 67 PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrTypeToBit"); 68 PKIX_NULLCHECK_TWO(attrType, pAttrBit); 69 70 s = (const char *)attrType->data; 71 attrLen = attrType->len; 72 73 /* 74 * Taking note of the fact that all of the comparand strings are 75 * different lengths, we do a slight optimization. If a string 76 * length matches but the string does not match, we skip comparing 77 * to the other strings. If new strings are added to the comparand 78 * list, and any are of equal length, be careful to change the 79 * grouping of tests accordingly. 80 */ 81 if (attrLen == caAttrLen) { 82 if (PORT_Strncasecmp(caAttr, s, attrLen) == 0) { 83 attrBit = LDAPATTR_CACERT; 84 } 85 } else if (attrLen == uAttrLen) { 86 if (PORT_Strncasecmp(uAttr, s, attrLen) == 0) { 87 attrBit = LDAPATTR_USERCERT; 88 } 89 } else if (attrLen == ccpAttrLen) { 90 if (PORT_Strncasecmp(ccpAttr, s, attrLen) == 0) { 91 attrBit = LDAPATTR_CROSSPAIRCERT; 92 } 93 } else if (attrLen == crlAttrLen) { 94 if (PORT_Strncasecmp(crlAttr, s, attrLen) == 0) { 95 attrBit = LDAPATTR_CERTREVLIST; 96 } 97 } else if (attrLen == arlAttrLen) { 98 if (PORT_Strncasecmp(arlAttr, s, attrLen) == 0) { 99 attrBit = LDAPATTR_AUTHREVLIST; 100 } 101 } 102 103 *pAttrBit = attrBit; 104 105 PKIX_RETURN(LDAPREQUEST); 106 } 107 108 /* 109 * FUNCTION: pkix_pl_LdapRequest_AttrStringToBit 110 * DESCRIPTION: 111 * 112 * This function creates an attribute mask bit corresponding to the null- 113 * terminated string pointed to by "attrString", storing the result at 114 * "pAttrBit". The comparison is case-insensitive. If "attrString" does not 115 * match any of the known types, zero is stored at "pAttrBit". 116 * 117 * PARAMETERS 118 * "attrString" 119 * The address of the null-terminated string whose contents are to be compared to 120 * the various known attribute types. Must be non-NULL. 121 * "pAttrBit" 122 * The address where the result is stored. Must be non-NULL. 123 * "plContext" 124 * Platform-specific context pointer. 125 * THREAD SAFETY: 126 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 127 * RETURNS: 128 * Returns NULL if the function succeeds. 129 * Returns an LdapRequest Error if the function fails in a non-fatal way. 130 * Returns a Fatal Error if the function fails in an unrecoverable way. 131 */ 132 PKIX_Error * 133 pkix_pl_LdapRequest_AttrStringToBit( 134 char *attrString, 135 LdapAttrMask *pAttrBit, 136 void *plContext) 137 { 138 LdapAttrMask attrBit = 0; 139 unsigned int attrLen = 0; 140 141 PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_AttrStringToBit"); 142 PKIX_NULLCHECK_TWO(attrString, pAttrBit); 143 144 attrLen = PL_strlen(attrString); 145 146 /* 147 * Taking note of the fact that all of the comparand strings are 148 * different lengths, we do a slight optimization. If a string 149 * length matches but the string does not match, we skip comparing 150 * to the other strings. If new strings are added to the comparand 151 * list, and any are of equal length, be careful to change the 152 * grouping of tests accordingly. 153 */ 154 if (attrLen == caAttrLen) { 155 if (PORT_Strncasecmp(caAttr, attrString, attrLen) == 0) { 156 attrBit = LDAPATTR_CACERT; 157 } 158 } else if (attrLen == uAttrLen) { 159 if (PORT_Strncasecmp(uAttr, attrString, attrLen) == 0) { 160 attrBit = LDAPATTR_USERCERT; 161 } 162 } else if (attrLen == ccpAttrLen) { 163 if (PORT_Strncasecmp(ccpAttr, attrString, attrLen) == 0) { 164 attrBit = LDAPATTR_CROSSPAIRCERT; 165 } 166 } else if (attrLen == crlAttrLen) { 167 if (PORT_Strncasecmp(crlAttr, attrString, attrLen) == 0) { 168 attrBit = LDAPATTR_CERTREVLIST; 169 } 170 } else if (attrLen == arlAttrLen) { 171 if (PORT_Strncasecmp(arlAttr, attrString, attrLen) == 0) { 172 attrBit = LDAPATTR_AUTHREVLIST; 173 } 174 } 175 176 *pAttrBit = attrBit; 177 178 PKIX_RETURN(LDAPREQUEST); 179 } 180 181 /* 182 * FUNCTION: pkix_pl_LdapRequest_EncodeAttrs 183 * DESCRIPTION: 184 * 185 * This function obtains the attribute mask bits from the LdapRequest pointed 186 * to by "request", creates the corresponding array of AttributeTypes for the 187 * encoding of the SearchRequest message. 188 * 189 * PARAMETERS 190 * "request" 191 * The address of the LdapRequest whose attributes are to be encoded. Must 192 * be non-NULL. 193 * "plContext" 194 * Platform-specific context pointer. 195 * THREAD SAFETY: 196 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 197 * RETURNS: 198 * Returns NULL if the function succeeds. 199 * Returns an LdapRequest Error if the function fails in a non-fatal way. 200 * Returns a Fatal Error if the function fails in an unrecoverable way. 201 */ 202 static PKIX_Error * 203 pkix_pl_LdapRequest_EncodeAttrs( 204 PKIX_PL_LdapRequest *request, 205 void *plContext) 206 { 207 SECItem **attrArray = NULL; 208 PKIX_UInt32 attrIndex = 0; 209 LdapAttrMask attrBits; 210 211 PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_EncodeAttrs"); 212 PKIX_NULLCHECK_ONE(request); 213 214 /* construct "attrs" according to bits in request->attrBits */ 215 attrBits = request->attrBits; 216 attrArray = request->attrArray; 217 if ((attrBits & LDAPATTR_CACERT) == LDAPATTR_CACERT) { 218 attrArray[attrIndex] = &(request->attributes[attrIndex]); 219 request->attributes[attrIndex].type = siAsciiString; 220 request->attributes[attrIndex].data = (unsigned char *)caAttr; 221 request->attributes[attrIndex].len = caAttrLen; 222 attrIndex++; 223 } 224 if ((attrBits & LDAPATTR_USERCERT) == LDAPATTR_USERCERT) { 225 attrArray[attrIndex] = &(request->attributes[attrIndex]); 226 request->attributes[attrIndex].type = siAsciiString; 227 request->attributes[attrIndex].data = (unsigned char *)uAttr; 228 request->attributes[attrIndex].len = uAttrLen; 229 attrIndex++; 230 } 231 if ((attrBits & LDAPATTR_CROSSPAIRCERT) == LDAPATTR_CROSSPAIRCERT) { 232 attrArray[attrIndex] = &(request->attributes[attrIndex]); 233 request->attributes[attrIndex].type = siAsciiString; 234 request->attributes[attrIndex].data = (unsigned char *)ccpAttr; 235 request->attributes[attrIndex].len = ccpAttrLen; 236 attrIndex++; 237 } 238 if ((attrBits & LDAPATTR_CERTREVLIST) == LDAPATTR_CERTREVLIST) { 239 attrArray[attrIndex] = &(request->attributes[attrIndex]); 240 request->attributes[attrIndex].type = siAsciiString; 241 request->attributes[attrIndex].data = (unsigned char *)crlAttr; 242 request->attributes[attrIndex].len = crlAttrLen; 243 attrIndex++; 244 } 245 if ((attrBits & LDAPATTR_AUTHREVLIST) == LDAPATTR_AUTHREVLIST) { 246 attrArray[attrIndex] = &(request->attributes[attrIndex]); 247 request->attributes[attrIndex].type = siAsciiString; 248 request->attributes[attrIndex].data = (unsigned char *)arlAttr; 249 request->attributes[attrIndex].len = arlAttrLen; 250 attrIndex++; 251 } 252 attrArray[attrIndex] = (SECItem *)NULL; 253 254 PKIX_RETURN(LDAPREQUEST); 255 } 256 257 /* 258 * FUNCTION: pkix_pl_LdapRequest_Destroy 259 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) 260 */ 261 static PKIX_Error * 262 pkix_pl_LdapRequest_Destroy( 263 PKIX_PL_Object *object, 264 void *plContext) 265 { 266 PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Destroy"); 267 PKIX_NULLCHECK_ONE(object); 268 269 PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext), 270 PKIX_OBJECTNOTLDAPREQUEST); 271 272 /* 273 * All dynamic fields in an LDAPRequest are allocated 274 * in an arena, and will be freed when the arena is destroyed. 275 */ 276 277 cleanup: 278 279 PKIX_RETURN(LDAPREQUEST); 280 } 281 282 /* 283 * FUNCTION: pkix_pl_LdapRequest_Hashcode 284 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) 285 */ 286 static PKIX_Error * 287 pkix_pl_LdapRequest_Hashcode( 288 PKIX_PL_Object *object, 289 PKIX_UInt32 *pHashcode, 290 void *plContext) 291 { 292 PKIX_UInt32 dataLen = 0; 293 PKIX_UInt32 dindex = 0; 294 PKIX_UInt32 sizeOfLength = 0; 295 PKIX_UInt32 idLen = 0; 296 const unsigned char *msgBuf = NULL; 297 PKIX_PL_LdapRequest *ldapRq = NULL; 298 299 PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Hashcode"); 300 PKIX_NULLCHECK_TWO(object, pHashcode); 301 302 PKIX_CHECK(pkix_CheckType(object, PKIX_LDAPREQUEST_TYPE, plContext), 303 PKIX_OBJECTNOTLDAPREQUEST); 304 305 ldapRq = (PKIX_PL_LdapRequest *)object; 306 307 *pHashcode = 0; 308 309 /* 310 * Two requests that differ only in msgnum are a match! Therefore, 311 * start hashcoding beyond the encoded messageID field. 312 */ 313 if (ldapRq->encoded) { 314 msgBuf = (const unsigned char *)ldapRq->encoded->data; 315 /* Is message length short form (one octet) or long form? */ 316 if ((msgBuf[1] & 0x80) != 0) { 317 sizeOfLength = msgBuf[1] & 0x7F; 318 for (dindex = 0; dindex < sizeOfLength; dindex++) { 319 dataLen = (dataLen << 8) + msgBuf[dindex + 2]; 320 } 321 } else { 322 dataLen = msgBuf[1]; 323 } 324 325 /* How many bytes for the messageID? (Assume short form) */ 326 idLen = msgBuf[dindex + 3] + 2; 327 dindex += idLen; 328 dataLen -= idLen; 329 msgBuf = &msgBuf[dindex + 2]; 330 331 PKIX_CHECK(pkix_hash(msgBuf, dataLen, pHashcode, plContext), 332 PKIX_HASHFAILED); 333 } 334 335 cleanup: 336 337 PKIX_RETURN(LDAPREQUEST); 338 339 } 340 341 /* 342 * FUNCTION: pkix_pl_LdapRequest_Equals 343 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) 344 */ 345 static PKIX_Error * 346 pkix_pl_LdapRequest_Equals( 347 PKIX_PL_Object *firstObj, 348 PKIX_PL_Object *secondObj, 349 PKIX_Boolean *pResult, 350 void *plContext) 351 { 352 PKIX_PL_LdapRequest *firstReq = NULL; 353 PKIX_PL_LdapRequest *secondReq = NULL; 354 PKIX_UInt32 secondType = 0; 355 PKIX_UInt32 firstLen = 0; 356 const unsigned char *firstData = NULL; 357 const unsigned char *secondData = NULL; 358 PKIX_UInt32 sizeOfLength = 0; 359 PKIX_UInt32 dindex = 0; 360 PKIX_UInt32 i = 0; 361 362 PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Equals"); 363 PKIX_NULLCHECK_THREE(firstObj, secondObj, pResult); 364 365 /* test that firstObj is a LdapRequest */ 366 PKIX_CHECK(pkix_CheckType(firstObj, PKIX_LDAPREQUEST_TYPE, plContext), 367 PKIX_FIRSTOBJARGUMENTNOTLDAPREQUEST); 368 369 /* 370 * Since we know firstObj is a LdapRequest, if both references are 371 * identical, they must be equal 372 */ 373 if (firstObj == secondObj){ 374 *pResult = PKIX_TRUE; 375 goto cleanup; 376 } 377 378 /* 379 * If secondObj isn't a LdapRequest, we don't throw an error. 380 * We simply return a Boolean result of FALSE 381 */ 382 *pResult = PKIX_FALSE; 383 PKIX_CHECK(PKIX_PL_Object_GetType 384 (secondObj, &secondType, plContext), 385 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); 386 if (secondType != PKIX_LDAPREQUEST_TYPE) { 387 goto cleanup; 388 } 389 390 firstReq = (PKIX_PL_LdapRequest *)firstObj; 391 secondReq = (PKIX_PL_LdapRequest *)secondObj; 392 393 /* If either lacks an encoded string, they cannot be compared */ 394 if (!(firstReq->encoded) || !(secondReq->encoded)) { 395 goto cleanup; 396 } 397 398 if (firstReq->encoded->len != secondReq->encoded->len) { 399 goto cleanup; 400 } 401 402 firstData = (const unsigned char *)firstReq->encoded->data; 403 secondData = (const unsigned char *)secondReq->encoded->data; 404 405 /* 406 * Two requests that differ only in msgnum are equal! Therefore, 407 * start the byte comparison beyond the encoded messageID field. 408 */ 409 410 /* Is message length short form (one octet) or long form? */ 411 if ((firstData[1] & 0x80) != 0) { 412 sizeOfLength = firstData[1] & 0x7F; 413 for (dindex = 0; dindex < sizeOfLength; dindex++) { 414 firstLen = (firstLen << 8) + firstData[dindex + 2]; 415 } 416 } else { 417 firstLen = firstData[1]; 418 } 419 420 /* How many bytes for the messageID? (Assume short form) */ 421 i = firstData[dindex + 3] + 2; 422 dindex += i; 423 firstLen -= i; 424 firstData = &firstData[dindex + 2]; 425 426 /* 427 * In theory, we have to calculate where the second message data 428 * begins by checking its length encodings. But if these messages 429 * are equal, we can re-use the calculation we already did. If they 430 * are not equal, the byte comparisons will surely fail. 431 */ 432 433 secondData = &secondData[dindex + 2]; 434 435 for (i = 0; i < firstLen; i++) { 436 if (firstData[i] != secondData[i]) { 437 goto cleanup; 438 } 439 } 440 441 *pResult = PKIX_TRUE; 442 443 cleanup: 444 445 PKIX_RETURN(LDAPREQUEST); 446 } 447 448 /* 449 * FUNCTION: pkix_pl_LdapRequest_RegisterSelf 450 * DESCRIPTION: 451 * Registers PKIX_LDAPREQUEST_TYPE and its related functions with 452 * systemClasses[] 453 * PARAMETERS: 454 * "plContext" 455 * Platform-specific context pointer. 456 * THREAD SAFETY: 457 * Not Thread Safe - for performance and complexity reasons 458 * 459 * Since this function is only called by PKIX_PL_Initialize, which should 460 * only be called once, it is acceptable that this function is not 461 * thread-safe. 462 */ 463 PKIX_Error * 464 pkix_pl_LdapRequest_RegisterSelf(void *plContext) 465 { 466 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; 467 pkix_ClassTable_Entry entry; 468 469 PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_RegisterSelf"); 470 471 entry.description = "LdapRequest"; 472 entry.objCounter = 0; 473 entry.typeObjectSize = sizeof(PKIX_PL_LdapRequest); 474 entry.destructor = pkix_pl_LdapRequest_Destroy; 475 entry.equalsFunction = pkix_pl_LdapRequest_Equals; 476 entry.hashcodeFunction = pkix_pl_LdapRequest_Hashcode; 477 entry.toStringFunction = NULL; 478 entry.comparator = NULL; 479 entry.duplicateFunction = pkix_duplicateImmutable; 480 481 systemClasses[PKIX_LDAPREQUEST_TYPE] = entry; 482 483 PKIX_RETURN(LDAPREQUEST); 484 } 485 486 /* --Public-Functions------------------------------------------------------- */ 487 488 /* 489 * FUNCTION: pkix_pl_LdapRequest_Create 490 * DESCRIPTION: 491 * 492 * This function creates an LdapRequest using the PLArenaPool pointed to by 493 * "arena", a message number whose value is "msgnum", a base object pointed to 494 * by "issuerDN", a scope whose value is "scope", a derefAliases flag whose 495 * value is "derefAliases", a sizeLimit whose value is "sizeLimit", a timeLimit 496 * whose value is "timeLimit", an attrsOnly flag whose value is "attrsOnly", a 497 * filter whose value is "filter", and attribute bits whose value is 498 * "attrBits"; storing the result at "pRequestMsg". 499 * 500 * See pkix_pl_ldaptemplates.c (and below) for the ASN.1 representation of 501 * message components, and see pkix_pl_ldapt.h for data types. 502 * 503 * PARAMETERS 504 * "arena" 505 * The address of the PLArenaPool to be used in the encoding. Must be 506 * non-NULL. 507 * "msgnum" 508 * The UInt32 message number to be used for the messageID component of the 509 * LDAP message exchange. 510 * "issuerDN" 511 * The address of the string to be used for the baseObject component of the 512 * LDAP SearchRequest message. Must be non-NULL. 513 * "scope" 514 * The (enumerated) ScopeType to be used for the scope component of the 515 * LDAP SearchRequest message 516 * "derefAliases" 517 * The (enumerated) DerefType to be used for the derefAliases component of 518 * the LDAP SearchRequest message 519 * "sizeLimit" 520 * The UInt32 value to be used for the sizeLimit component of the LDAP 521 * SearchRequest message 522 * "timeLimit" 523 * The UInt32 value to be used for the timeLimit component of the LDAP 524 * SearchRequest message 525 * "attrsOnly" 526 * The Boolean value to be used for the attrsOnly component of the LDAP 527 * SearchRequest message 528 * "filter" 529 * The filter to be used for the filter component of the LDAP 530 * SearchRequest message 531 * "attrBits" 532 * The LdapAttrMask bits indicating the attributes to be included in the 533 * attributes sequence of the LDAP SearchRequest message 534 * "pRequestMsg" 535 * The address at which the address of the LdapRequest is stored. Must 536 * be non-NULL. 537 * "plContext" 538 * Platform-specific context pointer. 539 * THREAD SAFETY: 540 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 541 * RETURNS: 542 * Returns NULL if the function succeeds. 543 * Returns an LdapRequest Error if the function fails in a non-fatal way. 544 * Returns a Fatal Error if the function fails in an unrecoverable way. 545 */ 546 /* 547 * SearchRequest ::= 548 * [APPLICATION 3] SEQUENCE { 549 * baseObject LDAPDN, 550 * scope ENUMERATED { 551 * baseObject (0), 552 * singleLevel (1), 553 * wholeSubtree (2) 554 * }, 555 * derefAliases ENUMERATED { 556 * neverDerefAliases (0), 557 * derefInSearching (1), 558 * derefFindingBaseObj (2), 559 * alwaysDerefAliases (3) 560 * }, 561 * sizeLimit INTEGER (0 .. MAXINT), 562 * -- value of 0 implies no sizeLimit 563 * timeLimit INTEGER (0 .. MAXINT), 564 * -- value of 0 implies no timeLimit 565 * attrsOnly BOOLEAN, 566 * -- TRUE, if only attributes (without values) 567 * -- to be returned 568 * filter Filter, 569 * attributes SEQUENCE OF AttributeType 570 * } 571 * 572 * Filter ::= 573 * CHOICE { 574 * and [0] SET OF Filter, 575 * or [1] SET OF Filter, 576 * not [2] Filter, 577 * equalityMatch [3] AttributeValueAssertion, 578 * substrings [4] SubstringFilter, 579 * greaterOrEqual [5] AttributeValueAssertion, 580 * lessOrEqual [6] AttributeValueAssertion, 581 * present [7] AttributeType, 582 * approxMatch [8] AttributeValueAssertion 583 * } 584 * 585 * SubstringFilter ::= 586 * SEQUENCE { 587 * type AttributeType, 588 * SEQUENCE OF CHOICE { 589 * initial [0] LDAPString, 590 * any [1] LDAPString, 591 * final [2] LDAPString, 592 * } 593 * } 594 * 595 * AttributeValueAssertion ::= 596 * SEQUENCE { 597 * attributeType AttributeType, 598 * attributeValue AttributeValue, 599 * } 600 * 601 * AttributeValue ::= OCTET STRING 602 * 603 * AttributeType ::= LDAPString 604 * -- text name of the attribute, or dotted 605 * -- OID representation 606 * 607 * LDAPDN ::= LDAPString 608 * 609 * LDAPString ::= OCTET STRING 610 * 611 */ 612 PKIX_Error * 613 pkix_pl_LdapRequest_Create( 614 PLArenaPool *arena, 615 PKIX_UInt32 msgnum, 616 char *issuerDN, 617 ScopeType scope, 618 DerefType derefAliases, 619 PKIX_UInt32 sizeLimit, 620 PKIX_UInt32 timeLimit, 621 char attrsOnly, 622 LDAPFilter *filter, 623 LdapAttrMask attrBits, 624 PKIX_PL_LdapRequest **pRequestMsg, 625 void *plContext) 626 { 627 LDAPMessage msg; 628 LDAPSearch *search; 629 PKIX_PL_LdapRequest *ldapRequest = NULL; 630 char scopeTypeAsChar; 631 char derefAliasesTypeAsChar; 632 SECItem *attrArray[MAX_LDAPATTRS + 1]; 633 634 PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_Create"); 635 PKIX_NULLCHECK_THREE(arena, issuerDN, pRequestMsg); 636 637 /* create a PKIX_PL_LdapRequest object */ 638 PKIX_CHECK(PKIX_PL_Object_Alloc 639 (PKIX_LDAPREQUEST_TYPE, 640 sizeof (PKIX_PL_LdapRequest), 641 (PKIX_PL_Object **)&ldapRequest, 642 plContext), 643 PKIX_COULDNOTCREATEOBJECT); 644 645 ldapRequest->arena = arena; 646 ldapRequest->msgnum = msgnum; 647 ldapRequest->issuerDN = issuerDN; 648 ldapRequest->scope = scope; 649 ldapRequest->derefAliases = derefAliases; 650 ldapRequest->sizeLimit = sizeLimit; 651 ldapRequest->timeLimit = timeLimit; 652 ldapRequest->attrsOnly = attrsOnly; 653 ldapRequest->filter = filter; 654 ldapRequest->attrBits = attrBits; 655 656 ldapRequest->attrArray = attrArray; 657 658 PKIX_CHECK(pkix_pl_LdapRequest_EncodeAttrs 659 (ldapRequest, plContext), 660 PKIX_LDAPREQUESTENCODEATTRSFAILED); 661 662 PKIX_PL_NSSCALL 663 (LDAPREQUEST, PORT_Memset, (&msg, 0, sizeof (LDAPMessage))); 664 665 msg.messageID.type = siUnsignedInteger; 666 msg.messageID.data = (void*)&msgnum; 667 msg.messageID.len = sizeof (msgnum); 668 669 msg.protocolOp.selector = LDAP_SEARCH_TYPE; 670 671 search = &(msg.protocolOp.op.searchMsg); 672 673 search->baseObject.type = siAsciiString; 674 search->baseObject.data = (void *)issuerDN; 675 search->baseObject.len = PL_strlen(issuerDN); 676 scopeTypeAsChar = (char)scope; 677 search->scope.type = siUnsignedInteger; 678 search->scope.data = (void *)&scopeTypeAsChar; 679 search->scope.len = sizeof (scopeTypeAsChar); 680 derefAliasesTypeAsChar = (char)derefAliases; 681 search->derefAliases.type = siUnsignedInteger; 682 search->derefAliases.data = 683 (void *)&derefAliasesTypeAsChar; 684 search->derefAliases.len = 685 sizeof (derefAliasesTypeAsChar); 686 search->sizeLimit.type = siUnsignedInteger; 687 search->sizeLimit.data = (void *)&sizeLimit; 688 search->sizeLimit.len = sizeof (PKIX_UInt32); 689 search->timeLimit.type = siUnsignedInteger; 690 search->timeLimit.data = (void *)&timeLimit; 691 search->timeLimit.len = sizeof (PKIX_UInt32); 692 search->attrsOnly.type = siBuffer; 693 search->attrsOnly.data = (void *)&attrsOnly; 694 search->attrsOnly.len = sizeof (attrsOnly); 695 696 PKIX_PL_NSSCALL 697 (LDAPREQUEST, 698 PORT_Memcpy, 699 (&search->filter, filter, sizeof (LDAPFilter))); 700 701 search->attributes = attrArray; 702 703 PKIX_PL_NSSCALLRV 704 (LDAPREQUEST, ldapRequest->encoded, SEC_ASN1EncodeItem, 705 (arena, NULL, (void *)&msg, PKIX_PL_LDAPMessageTemplate)); 706 707 if (!(ldapRequest->encoded)) { 708 PKIX_ERROR(PKIX_FAILEDINENCODINGSEARCHREQUEST); 709 } 710 711 *pRequestMsg = ldapRequest; 712 713 cleanup: 714 715 if (PKIX_ERROR_RECEIVED) { 716 PKIX_DECREF(ldapRequest); 717 } 718 719 PKIX_RETURN(LDAPREQUEST); 720 } 721 722 /* 723 * FUNCTION: pkix_pl_LdapRequest_GetEncoded 724 * DESCRIPTION: 725 * 726 * This function obtains the encoded message from the LdapRequest pointed to 727 * by "request", storing the result at "pRequestBuf". 728 * 729 * PARAMETERS 730 * "request" 731 * The address of the LdapRequest whose encoded message is to be 732 * retrieved. Must be non-NULL. 733 * "pRequestBuf" 734 * The address at which is stored the address of the encoded message. Must 735 * be non-NULL. 736 * "plContext" 737 * Platform-specific context pointer. 738 * THREAD SAFETY: 739 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) 740 * RETURNS: 741 * Returns NULL if the function succeeds. 742 * Returns an LdapRequest Error if the function fails in a non-fatal way. 743 * Returns a Fatal Error if the function fails in an unrecoverable way. 744 */ 745 PKIX_Error * 746 pkix_pl_LdapRequest_GetEncoded( 747 PKIX_PL_LdapRequest *request, 748 SECItem **pRequestBuf, 749 void *plContext) 750 { 751 PKIX_ENTER(LDAPREQUEST, "pkix_pl_LdapRequest_GetEncoded"); 752 PKIX_NULLCHECK_TWO(request, pRequestBuf); 753 754 *pRequestBuf = request->encoded; 755 756 PKIX_RETURN(LDAPREQUEST); 757 }