1/* 2 * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25/* 26 * DotMacCredRequest.cpp - public session functions for Submit/Retrieve cred result 27 */ 28 29#include "AppleDotMacTPSession.h" 30#include "dotMacTpDebug.h" 31#include "dotMacTpUtils.h" 32#include "dotMacTpRpcGlue.h" 33#include "dotMacTp.h" 34#include <security_asn1/nssUtils.h> 35#include <security_asn1/SecNssCoder.h> 36#include <Security/oidsalg.h> 37#include <security_cdsa_utils/cuPem.h> 38#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h> 39 40void AppleDotMacTPSession::RetrieveCredResult( 41 const CssmData &ReferenceIdentifier, 42 const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthCredentials, 43 sint32 &EstimatedTime, 44 CSSM_BOOL &ConfirmationRequired, 45 CSSM_TP_RESULT_SET_PTR &RetrieveOutput) 46{ 47 /* 48 * The only input we use is the RefId, which we created in SubmitCredRequest() 49 * in the case of a CSSMERR_APPLE_DOTMAC_REQ_QUEUED status. 50 */ 51 if((ReferenceIdentifier.Data == NULL) || (ReferenceIdentifier.Length == 0)) { 52 dotMacErrorLog("RetrieveCredResult: NULL ReferenceIdentifier\n"); 53 CssmError::throwMe(CSSMERR_TP_INVALID_IDENTIFIER); 54 } 55 if(CallerAuthCredentials != NULL) { 56 dotMacErrorLog("RetrieveCredResult: CallerAuthCredentials not used\n"); 57 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER); 58 } 59 60 /* 61 * Decode the RefId to get the fields we need to fetch the cert. 62 */ 63 SecNssCoder coder; 64 CSSM_DATA userName; 65 CSSM_DATA domain; 66 DotMacCertTypeTag certType; 67 OSStatus ortn = dotMacDecodeRefId(coder, ReferenceIdentifier, userName, domain, &certType); 68 if(ortn) { 69 dotMacErrorLog("RetrieveCredResult: Invalid RefID\n"); 70 CssmError::throwMe(CSSMERR_TP_INVALID_IDENTIFIER); 71 } 72 73 /* Fetch the cert. */ 74 CSSM_DATA certData = {0, NULL}; 75 CSSM_RETURN crtn; 76 crtn = dotMacTpCertFetch(userName, domain, certType, *this, certData); 77 if(crtn) { 78 /* FIXME error handling here, including no data */ 79 CssmError::throwMe(crtn); 80 } 81 82 ConfirmationRequired = CSSM_FALSE; 83 EstimatedTime = 0; 84 85 /* Return cert data as the single Results in CSSM_TP_RESULT_SET. */ 86 if(certData.Length == 0) { 87 /* The spec says this is OK, it just means that no cert is available yet */ 88 dotMacErrorLog("RetrieveCredResult: no data after successful GET\n"); 89 CssmError::throwMe(CSSMERR_TP_CERT_NOT_VALID_YET); 90 } 91 92 RetrieveOutput = (CSSM_TP_RESULT_SET_PTR)malloc(sizeof(CSSM_TP_RESULT_SET)); 93 CSSM_DATA *resultData = (CSSM_DATA *)malloc(sizeof(CSSM_DATA)); 94 *resultData = certData; 95 RetrieveOutput->NumberOfResults = 1; 96 RetrieveOutput->Results = resultData; 97} 98 99/* 100 * All archive requests (store, fetch, list, remove) go through here. 101 * All are synchronous (i.e., no RetrieveCredResult is needed). 102 */ 103void AppleDotMacTPSession::SubmitArchiveRequest( 104 DotMacArchiveType archiveType, // OID preparsed 105 const CSSM_DATA &hostName, // required 106 CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType, 107 const CSSM_TP_REQUEST_SET &RequestInput, 108 const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext, 109 sint32 &EstimatedTime, 110 CssmData &ReferenceIdentifier) 111{ 112 CSSM_APPLE_DOTMAC_TP_ARCHIVE_REQUEST *archReq = 113 (CSSM_APPLE_DOTMAC_TP_ARCHIVE_REQUEST *)RequestInput.Requests; 114 const CSSM_DATA *pfxIn = NULL; 115 CSSM_DATA *pfxOut = NULL; 116 const CSSM_DATA *archiveName = NULL; 117 const CSSM_DATA *timeString = NULL; 118 uint32 version; 119 120 if((archReq == NULL) || 121 (archReq->userName.Data == NULL) || 122 (archReq->password.Data == NULL)) { 123 dotMacErrorLog("SubmitArchiveRequest: bad username/pwd\n"); 124 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); 125 } 126 127 /* Version and cert type - infer certType if v. 1 */ 128 version = archReq->version; 129 const CSSM_DATA *serialNumber = NULL; 130 DotMacArchive_v2 **archives_v2 = NULL; 131 DotMacArchive **archives_v1 = NULL; 132 DotMacCertTypeTag certTypeTag; 133 if(version >= CSSM_DOT_MAC_TP_ARCHIVE_REQ_VERSION_v2) { 134 certTypeTag = archReq->certTypeTag; 135 archives_v2 = &archReq->archives_v2; 136 serialNumber = &archReq->serialNumber; 137 } 138 else { 139 /* backwards compatibility */ 140 certTypeTag = CSSM_DOT_MAC_TYPE_ICHAT; 141 archives_v1 = &archReq->archives; 142 } 143 144 /* further verification per request type */ 145 bool badInputs = false; 146 switch(archiveType) { 147 case DMAT_List: 148 /* nothing further needed */ 149 break; 150 case DMAT_Store: 151 if((archReq->archiveName.Data == NULL) || 152 (archReq->timeString.Data == NULL) || 153 (archReq->pfx.Data == NULL)) { 154 badInputs = true; 155 } 156 pfxIn = &archReq->pfx; 157 archiveName = &archReq->archiveName; 158 timeString = &archReq->timeString; 159 break; 160 case DMAT_Fetch: 161 pfxOut = &archReq->pfx; 162 /* and drop thru */ 163 case DMAT_Remove: 164 if(archReq->archiveName.Data == NULL) { 165 badInputs = true; 166 } 167 archiveName = &archReq->archiveName; 168 break; 169 default: 170 assert(0); 171 CssmError::throwMe(internalComponentErr); 172 } 173 if(badInputs) { 174 dotMacErrorLog("SubmitArchiveRequest: bad per-method inputs\n"); 175 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); 176 } 177 178 CSSM_RETURN crtn; 179 180 crtn = dotMacPostArchiveReq(version, certTypeTag, 181 archiveType, 182 archReq->userName, archReq->password, hostName, // all required 183 archiveName, pfxIn, timeString, serialNumber, pfxOut, 184 &archReq->numArchives, archives_v1, archives_v2, 185 *this); 186 if(crtn) { 187 CssmError::throwMe(crtn); 188 } 189} 190 191typedef enum { 192 CRO_Sign, 193 CRO_Archive, 194 CRO_Lookup 195} CredReqOp; 196 197/* 198 * This is the primary entry point to initiate all operations performed 199 * by this module. 200 */ 201void AppleDotMacTPSession::SubmitCredRequest( 202 const CSSM_TP_AUTHORITY_ID *PreferredAuthority, // optional 203 CSSM_TP_AUTHORITY_REQUEST_TYPE RequestType, 204 const CSSM_TP_REQUEST_SET &RequestInput, 205 const CSSM_TP_CALLERAUTH_CONTEXT *CallerAuthContext, 206 sint32 &EstimatedTime, 207 CssmData &ReferenceIdentifier) 208{ 209 CSSM_DATA hostName = { strlen(DOT_MAC_SIGN_HOST_NAME), (uint8 *)DOT_MAC_SIGN_HOST_NAME }; 210 CSSM_DATA domainName = { strlen(DOT_MAC_DOMAIN), (uint8 *)DOT_MAC_DOMAIN }; 211 CSSM_DATA fullName = { 0, NULL }; 212 CSSM_DATA *altHost = NULL; 213 214 CredReqOp op = CRO_Sign; 215 switch(RequestType) { 216 case CSSM_TP_AUTHORITY_REQUEST_CERTISSUE: 217 break; 218 case CSSM_TP_AUTHORITY_REQUEST_CERTLOOKUP: 219 op = CRO_Lookup; 220 hostName.Length = strlen(DOT_MAC_LOOKUP_HOST_NAME); 221 hostName.Data = (uint8 *)DOT_MAC_LOOKUP_HOST_NAME; 222 break; 223 default: 224 CssmError::throwMe(CSSMERR_TP_UNSUPPORTED_SERVICE); 225 } 226 227 /* default host, overridable via PreferredAuthority or username specification */ 228 CssmAutoData fullHostName(Allocator::standard()); 229 fullHostName.malloc(hostName.Length + 1 + domainName.Length); 230 fullName = fullHostName.get(); 231 memmove(fullName.Data, hostName.Data, hostName.Length); 232 memmove(fullName.Data + hostName.Length, ".", 1); 233 memmove(fullName.Data + hostName.Length + 1, domainName.Data, domainName.Length); 234 235 /* qualify inputs */ 236 if(PreferredAuthority) { 237 /* only valid option: host name */ 238 if(PreferredAuthority->AuthorityCert != NULL) { 239 dotMacErrorLog("SubmitCredRequest: AuthorityCert illegal\n"); 240 CssmError::throwMe(CSSMERR_TP_INVALID_AUTHORITY); 241 } 242 if(PreferredAuthority->AuthorityLocation == NULL) { 243 dotMacErrorLog("SubmitCredRequest: AuthorityLocation invalid\n"); 244 CssmError::throwMe(CSSMERR_TP_INVALID_AUTHORITY); 245 } 246 if(PreferredAuthority->AuthorityLocation->AddressType != CSSM_ADDR_NAME) { 247 dotMacErrorLog("SubmitCredRequest: AddressType invalid\n"); 248 CssmError::throwMe(CSSMERR_TP_INVALID_AUTHORITY); 249 } 250 fullName = PreferredAuthority->AuthorityLocation->Address; 251 if(fullName.Data == NULL) { 252 dotMacErrorLog("SubmitCredRequest: Address invalid\n"); 253 CssmError::throwMe(CSSMERR_TP_INVALID_AUTHORITY); 254 } 255 /* for archive only (it has a different default) */ 256 altHost = &fullName; 257 dotMacTokenizeHostName(fullName, hostName, domainName); 258 } 259 260 if(CallerAuthContext == NULL) { 261 CssmError::throwMe(CSSMERR_TP_INVALID_CALLERAUTH_CONTEXT_POINTER); 262 } 263 if((RequestInput.NumberOfRequests != 1) || 264 (RequestInput.Requests == NULL)) { 265 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); 266 } 267 const CSSM_TP_POLICYINFO *tpPolicy = &CallerAuthContext->Policy; 268 if((tpPolicy->NumberOfPolicyIds != 1) || (tpPolicy->PolicyIds == NULL)) { 269 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS); 270 } 271 272 DotMacCertTypeTag certType = CSSM_DOT_MAC_TYPE_UNSPECIFIED; 273 DotMacArchiveType archiveType = DMAT_List; 274 CSSM_DATA csr = {0, NULL}; 275 276 /* 277 * Map policy to op and (if op is CRO_Sign) cert type. 278 * For CRO_Archive ops, certType is in CSSM_APPLE_DOTMAC_TP_ARCHIVE_REQUEST. 279 */ 280 const CSSM_OID *oid = &tpPolicy->PolicyIds->FieldOid; 281 if(nssCompareCssmData(oid, &CSSMOID_DOTMAC_CERT_REQ_IDENTITY)) { 282 certType = CSSM_DOT_MAC_TYPE_ICHAT; 283 } 284 else if(nssCompareCssmData(oid, &CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN)) { 285 certType = CSSM_DOT_MAC_TYPE_EMAIL_SIGNING; 286 } 287 else if(nssCompareCssmData(oid, &CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT)) { 288 certType = CSSM_DOT_MAC_TYPE_EMAIL_ENCRYPT; 289 } 290 else if(nssCompareCssmData(oid, &CSSMOID_DOTMAC_CERT_REQ_SHARED_SERVICES)) { 291 certType = CSSM_DOT_MAC_TYPE_SHARED_SERVICES; 292 } 293 /* Archive ops: certType is in CSSM_APPLE_DOTMAC_TP_ARCHIVE_REQUEST */ 294 else if(nssCompareCssmData(oid, &CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_LIST)) { 295 op = CRO_Archive; 296 archiveType = DMAT_List; 297 } 298 else if(nssCompareCssmData(oid, &CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_STORE)) { 299 op = CRO_Archive; 300 archiveType = DMAT_Store; 301 } 302 else if(nssCompareCssmData(oid, &CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_FETCH)) { 303 op = CRO_Archive; 304 archiveType = DMAT_Fetch; 305 } 306 else if(nssCompareCssmData(oid, &CSSMOID_DOTMAC_CERT_REQ_ARCHIVE_REMOVE)) { 307 op = CRO_Archive; 308 archiveType = DMAT_Remove; 309 } 310 else { 311 CssmError::throwMe(CSSMERR_TP_INVALID_POLICY_IDENTIFIERS); 312 } 313 314 switch(op) { 315 case CRO_Archive: 316 { 317 CSSM_APPLE_DOTMAC_TP_ARCHIVE_REQUEST *archReq = 318 (CSSM_APPLE_DOTMAC_TP_ARCHIVE_REQUEST *)RequestInput.Requests; 319 if(!archReq || !archReq->userName.Data || !archReq->userName.Length) { 320 dotMacErrorLog("SubmitCredRequest(Archive): bad username\n"); 321 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); 322 } 323 if (!altHost) { 324 CSSM_DATA archReqDomain = domainName; 325 dotMacTokenizeUserName(archReq->userName, archReq->userName, archReqDomain); 326 if (archReqDomain.Length && archReqDomain.Data) { 327 domainName = archReqDomain; 328 fullHostName.reset(); 329 fullHostName.malloc(hostName.Length + 1 + domainName.Length); 330 fullName = fullHostName.get(); 331 memmove(fullName.Data, hostName.Data, hostName.Length); 332 memmove(fullName.Data + hostName.Length, ".", 1); 333 memmove(fullName.Data + hostName.Length + 1, domainName.Data, domainName.Length); 334 } 335 } 336 SubmitArchiveRequest(archiveType, fullName, RequestType, 337 RequestInput, CallerAuthContext, EstimatedTime, ReferenceIdentifier); 338 return; 339 } 340 case CRO_Lookup: 341 { 342 CSSM_APPLE_DOTMAC_TP_CERT_REQUEST *certReq = 343 (CSSM_APPLE_DOTMAC_TP_CERT_REQUEST *)RequestInput.Requests; 344 if(!certReq || !certReq->userName.Data || !certReq->userName.Length) { 345 dotMacErrorLog("SubmitCredRequest(Lookup): bad username\n"); 346 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); 347 } 348 if (!altHost) { 349 CSSM_DATA certReqDomain = domainName; 350 dotMacTokenizeUserName(certReq->userName, certReq->userName, certReqDomain); 351 if (certReqDomain.Length && certReqDomain.Data) { 352 domainName = certReqDomain; 353 fullHostName.reset(); 354 fullHostName.malloc(hostName.Length + 1 + domainName.Length); 355 fullName = fullHostName.get(); 356 memmove(fullName.Data, hostName.Data, hostName.Length); 357 memmove(fullName.Data + hostName.Length, ".", 1); 358 memmove(fullName.Data + hostName.Length + 1, domainName.Data, domainName.Length); 359 } 360 } 361 362 if(certReq->flags & CSSM_DOTMAC_TP_IS_REQ_PENDING) { 363 /* 364 * We're just asking the server if there is a request pending 365 * for this user 366 */ 367 if(certReq->password.Data == NULL) { 368 dotMacErrorLog("TP_IS_REQ_PENDING: no passphrase\n"); 369 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); 370 } 371 CSSM_RETURN crtn = dotMacPostReqPendingPing(certType, 372 certReq->userName, 373 certReq->password, 374 fullName); 375 /* this RPC does not have a "success" return */ 376 assert(crtn != CSSM_OK); 377 if(crtn) { 378 CssmError::throwMe(crtn); 379 } 380 } 381 else { 382 /* 383 * Note this is a path which apps could use to have us do a standard 384 * cert fetch via HTTP, without any "pending request" state, but 385 * currently (9/20/06) no code in the system uses this. The only 386 * time CertificateRequest (in libsecurity_keychain) does a 387 * CSSM_TP_AUTHORITY_REQUEST_CERTLOOKUP op is when it's doing 388 * a CSSM_DOTMAC_TP_IS_REQ_PENDING poll op, which is handled just 389 * above this block. 390 */ 391 CSSM_RETURN crtn = dotMacTpCertFetch(certReq->userName, domainName, 392 certType, *this, ReferenceIdentifier); 393 if(crtn) { 394 dotMacErrorLog("SubmitCredRequest(Lookup): error on fetch\n"); 395 CssmError::throwMe(crtn); 396 } 397 } 398 return; 399 } 400 case CRO_Sign: 401 /* proceed to main body */ 402 break; 403 } 404 405 /* op = CRO_Sign */ 406 407 CSSM_APPLE_DOTMAC_TP_CERT_REQUEST *certReq = 408 (CSSM_APPLE_DOTMAC_TP_CERT_REQUEST *)RequestInput.Requests; 409 if((certReq->userName.Data == NULL) || 410 (certReq->password.Data == NULL)) { 411 dotMacErrorLog("SubmitCredRequest: bad username/pwd\n"); 412 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); 413 } 414 if(!(certReq->flags & CSSM_DOTMAC_TP_EXIST_CSR)) { 415 /* Generating a CSR requires even more... */ 416 if((certReq->cspHand == 0) || 417 (certReq->clHand == 0) || 418 (certReq->numTypeValuePairs == 0) || 419 (certReq->typeValuePairs == NULL) || 420 (certReq->publicKey == NULL) || 421 (certReq->privateKey == NULL)) { 422 dotMacErrorLog("SubmitCredRequest: bad CSR generating params\n"); 423 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); 424 } 425 } 426 else if(certReq->csr.Data == NULL) { 427 /* using existing CSR */ 428 dotMacErrorLog("SubmitCredRequest: bad incoming CSR\n"); 429 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); 430 } 431 432 /* local vars prior to goto */ 433 SecNssCoder coder; 434 CSSM_X509_NAME x509Name; 435 const CSSM_KEY *pubKey = certReq->publicKey; 436 const CSSM_KEY *actPubKey = NULL; 437 CSSM_BOOL freeRawKey = CSSM_FALSE; 438 CSSM_KEY rawPubKey; 439 unsigned char *pemCsr = NULL; 440 unsigned pemCsrLen; 441 CSSM_RETURN crtn = CSSM_OK; 442 CSSM_CC_HANDLE sigHand = 0; 443 CSSM_DATA_PTR csrPtr = NULL; 444 445 if(certReq->flags & CSSM_DOTMAC_TP_EXIST_CSR) { 446 /* Skip the CSR gen */ 447 csr = certReq->csr; 448 goto doPost; 449 } 450 451 /*** 452 *** Create a PEM-encoded PKCS12 CSR using the CL handle provided. 453 ***/ 454 455 /* Build an X509Name for the CL */ 456 dotMacTpbuildX509Name(coder, certReq->numTypeValuePairs, certReq->typeValuePairs, 457 x509Name); 458 459 /* convert possible ref key to raw; CL requires this */ 460 461 switch(pubKey->KeyHeader.BlobType) { 462 case CSSM_KEYBLOB_RAW: 463 actPubKey = pubKey; 464 break; 465 case CSSM_KEYBLOB_REFERENCE: 466 dotMacRefKeyToRaw(certReq->cspHand, pubKey, &rawPubKey); 467 actPubKey = &rawPubKey; 468 freeRawKey = CSSM_TRUE; 469 break; 470 default: 471 dotMacErrorLog("SubmitCredRequest: bad key blob type (%u)", 472 (unsigned)pubKey->KeyHeader.BlobType); 473 CssmError::throwMe(CSSMERR_TP_INVALID_REQUEST_INPUTS); 474 } 475 /* subsequent errors to errOut: */ 476 477 /* cook up a CL-passthrough-specific request */ 478 CSSM_APPLE_CL_CSR_REQUEST clReq; 479 memset(&clReq, 0, sizeof(clReq)); 480 clReq.subjectNameX509 = &x509Name; 481 clReq.signatureAlg = DOT_MAC_CSR_SIGNATURE_ALGID; 482 clReq.signatureOid = DOT_MAC_CSR_SIGNATURE_ALGOID; 483 clReq.cspHand = certReq->cspHand; 484 clReq.subjectPublicKey = actPubKey; 485 clReq.subjectPrivateKey = certReq->privateKey; 486 487 /* A crypto handle to pass to the CL */ 488 crtn = CSSM_CSP_CreateSignatureContext(certReq->cspHand, 489 clReq.signatureAlg, 490 (CallerAuthContext ? CallerAuthContext->CallerCredentials : NULL), 491 certReq->privateKey, 492 &sigHand); 493 if(crtn) { 494 dotMacErrorLog("CSSM_CSP_CreateSignatureContext returned %ld", (long)crtn); 495 goto errOut; 496 } 497 498 /* down to the CL to do the actual work */ 499 crtn = CSSM_CL_PassThrough(certReq->clHand, 500 sigHand, 501 CSSM_APPLEX509CL_OBTAIN_CSR, 502 &clReq, 503 (void **)&csrPtr); 504 if(crtn) { 505 dotMacErrorLog("CSSM_CL_PassThrough returned %ld", (long)crtn); 506 goto errOut; 507 } 508 if(csrPtr == NULL) { 509 dotMacErrorLog("SubmitCredRequest: CL returned NULL CSR\n"); 510 crtn = internalComponentErr; 511 goto errOut; 512 } 513 514 /* base64 encode */ 515 if(pemEncode(csrPtr->Data, csrPtr->Length, &pemCsr, &pemCsrLen, 516 "CERTIFICATE REQUEST")) { 517 dotMacErrorLog("***Error on PEM encode of CSR\n"); 518 crtn = memFullErr; 519 goto errOut; 520 } 521 522 if(certReq->flags & CSSM_DOTMAC_TP_RETURN_CSR) { 523 /* caller wants a copy of the CSR */ 524 certReq->csr.Data = (uint8 *)malloc(pemCsrLen); 525 memmove(certReq->csr.Data, pemCsr, pemCsrLen); 526 certReq->csr.Length = pemCsrLen; 527 } 528 csr.Data = pemCsr; 529 csr.Length = pemCsrLen; 530 531doPost: 532 if(!(certReq->flags & CSSM_DOTMAC_TP_DO_NOT_POST)) { 533 534 /* do the net request */ 535 CSSM_DATA resultBody; 536 if (!altHost) { 537 CSSM_DATA certReqDomain = domainName; 538 dotMacTokenizeUserName(certReq->userName, certReq->userName, certReqDomain); 539 if (certReqDomain.Length && certReqDomain.Data) { 540 domainName = certReqDomain; 541 fullHostName.reset(); 542 fullHostName.malloc(hostName.Length + 1 + domainName.Length); 543 fullName = fullHostName.get(); 544 memmove(fullName.Data, hostName.Data, hostName.Length); 545 memmove(fullName.Data + hostName.Length, ".", 1); 546 memmove(fullName.Data + hostName.Length + 1, domainName.Data, domainName.Length); 547 } 548 } 549 550 crtn = dotMacPostCertReq(certType, 551 certReq->userName, 552 certReq->password, 553 fullName, 554 certReq->flags & CSSM_DOTMAC_TP_SIGN_RENEW ? true : false, 555 csr, 556 coder, 557 EstimatedTime, 558 resultBody); 559 switch(crtn) { 560 /* Some cases return data to caller */ 561 case noErr: /* resultBody = PEM-encoded cert */ 562 case CSSMERR_APPLE_DOTMAC_REQ_REDIRECT: /* resultBody = URL */ 563 case CSSMERR_APPLE_DOTMAC_REQ_QUEUED: /* resultBody = opaque data we'll use later */ 564 if(resultBody.Data != NULL) { 565 ReferenceIdentifier.Data = (uint8 *)malloc(resultBody.Length); 566 ReferenceIdentifier.Length = resultBody.Length; 567 memmove(ReferenceIdentifier.Data, resultBody.Data, resultBody.Length); 568 569 /* skip trailing NULL - it's just ASCII data */ 570 if(resultBody.Data[resultBody.Length-1] == '\0') { 571 ReferenceIdentifier.Length--; 572 } 573 } 574 else { 575 dotMacErrorLog("***SubmitCredReq: expected RefId.Data, got none\n"); 576 } 577 break; 578 default: 579 break; 580 } 581 } 582 583errOut: 584 /* free local resources */ 585 if(sigHand) { 586 CSSM_DeleteContext(sigHand); 587 } 588 if(freeRawKey) { 589 CSSM_FreeKey(certReq->cspHand, NULL, &rawPubKey, CSSM_FALSE); 590 } 591 if(pemCsr) { 592 free(pemCsr); 593 } 594 if(crtn) { 595 CssmError::throwMe(crtn); 596 } 597 598} 599