2  * dotMacTool.cpp - .mac TP exerciser 
   5 #include <Security/Security.h> 
   6 #include <Security/SecKeyPriv.h> 
   7 #include <security_cdsa_utils/cuCdsaUtils.h> 
   8 #include <security_cdsa_utils/cuFileIo.h> 
   9 #include <security_cdsa_utils/cuPem.h> 
  13 //#include <security_dotmac_tp/dotMacTp.h> 
  15 #include <security_cdsa_utils/cuPrintCert.h> 
  17 #include "keyPicker.h" 
  18 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h> 
  20 #define USER_DEFAULT            "dmitchtest@mac.com" 
  21 #define PWD_DEF                         "123456" 
  23 static void usage(char **argv
) 
  25         printf("usage: %s op [options]\n", argv
[0]); 
  27         printf("    g                generate identity cert\n"); 
  28         printf("    G                generate email signing cert\n"); 
  29         printf("    e                generate email encrypting cert\n"); 
  30         printf("    l                lookup cert (requires -f)\n"); 
  31         printf("    L                lookup identity cert (via -u)\n"); 
  32         printf("    M                lookup email signing cert (via -u)\n"); 
  33         printf("    N                lookup encrypting cert (via -u)\n"); 
  35         printf("   -g                Generate keypair\n"); 
  36         printf("   -p                pick key pair from existing\n"); 
  37         printf("   -u username       Default = %s\n", USER_DEFAULT
); 
  38         printf("   -Z password       Specify password immediately\n"); 
  39         printf("   -z                Use default password %s\n", PWD_DEF
); 
  40         printf("   -k keychain       Source/destination of keys and certs\n"); 
  41         printf("   -c filename       Write CSR to filename\n"); 
  42         printf("   -C filename       Use existing CSR (no keygen)\n"); 
  43         printf("   -f refIdFile      RefId file for cert lookup\n"); 
  44         printf("   -n                Do NOT post the CSR to the .mac server\n"); 
  45         printf("   -H hostname       Alternate .mac server host name (default %s)\n", 
  46                                         DOT_MAC_SIGN_HOST_NAME
); 
  47         printf("   -o outFile        Write output cert or refId (if any) to outFile\n"); 
  48         printf("   -r                Renew (default is new)\n"); 
  49         printf("   -M                Pause for MallocDebug\n"); 
  50         printf("   -q                Quiet\n"); 
  51         printf("   -v                Verbose\n"); 
  52         printf("   -h                Usage\n"); 
  56 static CSSM_VERSION vers 
= {2, 0}; 
  58 static CSSM_API_MEMORY_FUNCS memFuncs 
= { 
  66 static CSSM_TP_HANDLE 
dotMacStartup() 
  68         CSSM_TP_HANDLE tpHand
; 
  71         if(cuCssmStartup() == CSSM_FALSE
) { 
  74         crtn 
= CSSM_ModuleLoad(&gGuidAppleDotMacTP
, 
  75                 CSSM_KEY_HIERARCHY_NONE
, 
  77                 NULL
);                  // AppNotifyCallbackCtx 
  79                 cuPrintError("CSSM_ModuleLoad(DotMacTP)", crtn
); 
  82         crtn 
= CSSM_ModuleAttach (&gGuidAppleDotMacTP
, 
  84                 &memFuncs
,                              // memFuncs 
  86                 CSSM_SERVICE_TP
,                // SubserviceFlags 
  88                 CSSM_KEY_HIERARCHY_NONE
, 
  89                 NULL
,                                   // FunctionTable 
  94                 cuPrintError("CSSM_ModuleAttach(DotMacTP)", crtn
); 
 102 /* print text, safely */ 
 103 static void snDumpText( 
 104         const unsigned char *rcvBuf
,  
 107         char *cp 
= (char *)rcvBuf
; 
 111         for(i
=0; i
<len
; i
++) { 
 118                                 printf("\\n\n");        // graphic and liternal newline 
 124                                 if(isprint(c
) && (c 
!= '\n')) { 
 128                                         printf("<%02X>", ((unsigned)c
) & 0xff); 
 136 static OSStatus 
genKeyPair( 
 137         SecKeychainRef  kcRef
,          // NULL means the default list 
 138         SecKeyRef               
*pubKey
,        // RETURNED 
 139         SecKeyRef               
*privKey
)   // RETURNED 
 143         ortn 
= SecKeyCreatePair(kcRef
, 
 147                 /* public key usage and attrs */ 
 149                 CSSM_KEYATTR_RETURN_REF 
| CSSM_KEYATTR_PERMANENT 
| CSSM_KEYATTR_EXTRACTABLE
, 
 150                 /* private key usage and attrs */ 
 152                 CSSM_KEYATTR_RETURN_REF 
| CSSM_KEYATTR_PERMANENT 
| CSSM_KEYATTR_EXTRACTABLE 
| 
 153                         CSSM_KEYATTR_SENSITIVE
, 
 154                 NULL
,                                   // initial access 
 158                 cssmPerror("SecKeyCreatePair", ortn
); 
 163 /* Lookup via ReferenceID, obtained from CSSM_TP_SubmitCredRequest() */ 
 164 OSStatus 
doLookupViaRefId( 
 165         CSSM_TP_HANDLE tpHand
,   
 166         unsigned char *refId
,  
 171         CSSM_DATA refIdData 
= { refIdLen
, refId 
}; 
 172         sint32 EstimatedTime
; 
 173         CSSM_BOOL ConfirmationRequired
; 
 174         CSSM_TP_RESULT_SET_PTR resultSet 
= NULL
; 
 177         crtn 
= CSSM_TP_RetrieveCredResult(tpHand
, &refIdData
, NULL
,  
 178                 &EstimatedTime
, &ConfirmationRequired
, &resultSet
); 
 180                 cssmPerror("CSSM_TP_RetrieveCredResult", crtn
); 
 183         if(resultSet 
== NULL
) { 
 184                 printf("***CSSM_TP_RetrieveCredResult OK, but no result set\n"); 
 187         if(resultSet
->NumberOfResults 
!= 1) { 
 188                 printf("***CSSM_TP_RetrieveCredResult OK, NumberOfResults (%u)\n", 
 189                         (unsigned)resultSet
->NumberOfResults
); 
 192         if(resultSet
->Results 
== NULL
) { 
 193                 printf("***CSSM_TP_RetrieveCredResult OK, but empty result set\n"); 
 196         CSSM_DATA_PTR certData 
= (CSSM_DATA_PTR
)resultSet
->Results
; 
 198         printf("...cert retrieval complete\n"); 
 200                 if(!writeFile(outFile
, certData
->Data
, certData
->Length
)) { 
 201                         printf("...%lu bytes of cert data written to %s\n",  
 202                                         certData
->Length
, outFile
); 
 205                         printf("***Error writing cert to %s\n", outFile
); 
 212                 if(pemDecode(certData
->Data
, certData
->Length
, &der
, &derLen
)) { 
 213                         printf("***Error PEM decoding returned cert\n"); 
 216                         printCert(der
, derLen
, CSSM_FALSE
); 
 224 * Lookup via user name, a greatly simplified form of CSSM_TP_SubmitCredRequest() 
 226 OSStatus 
doLookupViaUserName( 
 227         CSSM_TP_HANDLE tpHand
,   
 228         const CSSM_OID 
*opOid
, 
 229         const char *userName
,  
 230         const char *hostName
,           // optional  
 234         CSSM_APPLE_DOTMAC_TP_CERT_REQUEST       certReq
; 
 235         CSSM_TP_AUTHORITY_ID                            tpAuthority
; 
 236         CSSM_TP_AUTHORITY_ID                            
*tpAuthPtr 
= NULL
; 
 237         CSSM_NET_ADDRESS                                        tpNetAddrs
; 
 238         CSSM_TP_REQUEST_SET                                     reqSet
; 
 239         CSSM_FIELD                                                      policyField
; 
 240         CSSM_DATA                                                       certData 
= {0, NULL
}; 
 242         CSSM_TP_CALLERAUTH_CONTEXT                      callerAuth
; 
 244         memset(&certReq
, 0, sizeof(certReq
)); 
 245         certReq
.userName
.Data 
= (uint8 
*)userName
; 
 246         certReq
.userName
.Length 
= strlen(userName
); 
 247         if(hostName 
!= NULL
) { 
 248                 tpAuthority
.AuthorityCert 
= NULL
; 
 249                 tpAuthority
.AuthorityLocation 
= &tpNetAddrs
; 
 250                 tpNetAddrs
.AddressType 
= CSSM_ADDR_NAME
; 
 251                 tpNetAddrs
.Address
.Data 
= (uint8 
*)hostName
; 
 252                 tpNetAddrs
.Address
.Length 
= strlen(hostName
); 
 253                 tpAuthPtr 
= &tpAuthority
; 
 256         certReq
.version 
= CSSM_DOT_MAC_TP_REQ_VERSION
; 
 257         reqSet
.NumberOfRequests 
= 1; 
 258         reqSet
.Requests 
= &certReq
; 
 259         policyField
.FieldOid 
= *opOid
; 
 260         policyField
.FieldValue
.Data 
= NULL
; 
 261         policyField
.FieldValue
.Length 
= 0; 
 262         memset(&callerAuth
, 0, sizeof(callerAuth
)); 
 263         callerAuth
.Policy
.NumberOfPolicyIds 
= 1; 
 264         callerAuth
.Policy
.PolicyIds 
= &policyField
; 
 266         CSSM_RETURN crtn 
= CSSM_TP_SubmitCredRequest (tpHand
, 
 268                 CSSM_TP_AUTHORITY_REQUEST_CERTLOOKUP
,  
 269                 &reqSet
,        // const CSSM_TP_REQUEST_SET *RequestInput, 
 271                 &estTime
,   // sint32 *EstimatedTime, 
 272                 &certData
);     // CSSM_DATA_PTR ReferenceIdentifier 
 275                 cssmPerror("CSSM_TP_SubmitCredRequest(lookup)", crtn
); 
 279         printf("...cert lookup complete\n"); 
 281                 if(!writeFile(outFile
, certData
.Data
, certData
.Length
)) { 
 282                         printf("...%lu bytes of cert data written to %s\n",  
 283                                         certData
.Length
, outFile
); 
 286                         printf("***Error writing cert to %s\n", outFile
); 
 291                 /* This one returns the cert in DER format, we might revisit that */ 
 292                 printCert(certData
.Data
, certData
.Length
, CSSM_FALSE
); 
 297 #define FULL_EMAIL_ADDRESS      1 
 299 int main(int argc
, char **argv
) 
 302         CSSM_TP_AUTHORITY_ID                            tpAuthority
; 
 303         CSSM_TP_AUTHORITY_ID                            
*tpAuthPtr 
= NULL
; 
 304         CSSM_NET_ADDRESS                                        tpNetAddrs
; 
 305         CSSM_APPLE_DOTMAC_TP_CERT_REQUEST       certReq
; 
 306         CSSM_TP_REQUEST_SET                                     reqSet
; 
 307         CSSM_CSP_HANDLE                                         cspHand 
= 0; 
 308         CSSM_X509_TYPE_VALUE_PAIR                       tvp
; 
 310         CSSM_TP_CALLERAUTH_CONTEXT                      callerAuth
; 
 312         CSSM_DATA                                                       refId 
= {0, NULL
}; 
 314         SecKeyRef                                                       pubKeyRef 
= NULL
; 
 315         SecKeyRef                                                       privKeyRef 
= NULL
; 
 316         const CSSM_KEY                                          
*privKey 
= NULL
; 
 317         const CSSM_KEY                                          
*pubKey 
= NULL
; 
 318         SecKeychainRef                                          kcRef 
= NULL
; 
 319         CSSM_FIELD                                                      policyField
; 
 321         /* user-spec'd variables */ 
 322         bool genKeys 
= false; 
 323         bool pickKeys 
= false; 
 324         char *keychainName 
= NULL
; 
 325         char *csrOutName 
= NULL
; 
 326         char *csrInName 
= NULL
; 
 327         const char *userName 
= USER_DEFAULT
; 
 328         char *password 
= NULL
; 
 329         char *hostName 
= NULL
; 
 330         bool doNotPost 
= false; 
 331         bool doRenew 
= false; 
 332         const CSSM_OID 
*opOid 
= NULL
; 
 333         char *outFile 
= NULL
; 
 335         bool verbose 
= false; 
 336         bool lookupViaRefId 
= false; 
 337         bool lookupViaUserName 
= false; 
 338         char *refIdFile 
= NULL
; 
 339         bool doPause 
= false; 
 346                         lookupViaUserName 
= true; 
 349                         opOid 
= &CSSMOID_DOTMAC_CERT_REQ_IDENTITY
; 
 353                         lookupViaUserName 
= true; 
 356                         opOid 
= &CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN
; 
 360                         lookupViaUserName 
= true; 
 363                         opOid 
= &CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT
; 
 367                         lookupViaRefId 
= true; 
 377         while ((arg 
= getopt(argc
, argv
, "gpk:c:u:Z:H:nzrC:o:hf:Mqv")) != -1) { 
 392                                 password 
= (char *)PWD_DEF
; 
 395                                 keychainName 
= optarg
; 
 434                 printf("Pausing for MallocDebug attach; CR to continue: "); 
 438         CSSM_TP_HANDLE tpHand 
= dotMacStartup(); 
 440                 printf("Error attaching to the .mac TP. Check your MDS file.\n"); 
 445                 if(refIdFile 
== NULL
) { 
 446                         printf("I need a refIdFile to do a lookup.\n"); 
 449                 unsigned char *refId
; 
 451                 int irtn 
= readFile(refIdFile
, &refId
, &refIdLen
); 
 453                         printf("***Error reading refId from %s. Aborting.\n", refIdFile
); 
 456                 ortn 
= doLookupViaRefId(tpHand
, refId
, refIdLen
, outFile
, verbose
); 
 460         if(lookupViaUserName
) { 
 461                 ortn 
= doLookupViaUserName(tpHand
, opOid
, userName
, hostName
, outFile
, verbose
); 
 464         if(!pickKeys 
&& !genKeys 
&& (csrInName 
== NULL
)) { 
 465                 printf("***You must specify either the -p (pick keys) or -g (generate keys)" 
 466                         " arguments, or provide a CSR (-C).\n"); 
 470         memset(&certReq
, 0, sizeof(certReq
)); 
 472         /* all of the subsequest argument are superfluous for lookupViaUserName, except for  
 473          * the user name itself, which has a default */ 
 474         if(keychainName 
!= NULL
) { 
 475                 /* pick a keychain (optional) */ 
 476                 ortn 
= SecKeychainOpen(keychainName
, &kcRef
); 
 478                         cssmPerror("SecKeychainOpen", ortn
); 
 482                 /* make sure it's there since a successful SecKeychainOpen proves nothing */ 
 483                 SecKeychainStatus kcStat
; 
 484                 ortn 
= SecKeychainGetStatus(kcRef
, &kcStat
); 
 486                         cssmPerror("SecKeychainGetStatus", ortn
); 
 491         if(password 
== NULL
) { 
 492                 const char *pwdp 
= getpass("Enter .mac password: "); 
 494                         printf("Aboerting.\n"); 
 498                 memmove(pwdBuf
, pwdp
, strlen(pwdp
) + 1); 
 501         certReq
.password
.Data 
= (uint8 
*)password
; 
 502         certReq
.password
.Length 
= strlen(password
); 
 503         certReq
.userName
.Data 
= (uint8 
*)userName
; 
 504         certReq
.userName
.Length 
= strlen(userName
); 
 508                 if(readFile(csrInName
, &certReq
.csr
.Data
, &len
)) { 
 509                         printf("***Error reading CSR from %s. Aborting.\n", csrInName
); 
 512                 certReq
.csr
.Length 
= len
; 
 513                 certReq
.flags 
|= CSSM_DOTMAC_TP_EXIST_CSR
; 
 517                  * All the stuff the TP needs to actually generate a CSR. 
 519                  * Get a key pair, somehow. 
 522                         ortn 
= genKeyPair(kcRef
, &pubKeyRef
, &privKeyRef
); 
 525                         ortn 
= keyPicker(kcRef
, &pubKeyRef
, &privKeyRef
); 
 528                         printf("Can't proceed without a keypair. Aborting.\n"); 
 531                 ortn 
= SecKeyGetCSSMKey(pubKeyRef
, &pubKey
); 
 533                         cssmPerror("SecKeyGetCSSMKey", ortn
); 
 536                 ortn 
= SecKeyGetCSSMKey(privKeyRef
, &privKey
); 
 538                         cssmPerror("SecKeyGetCSSMKey", ortn
); 
 541                 ortn 
= SecKeyGetCSPHandle(privKeyRef
, &cspHand
); 
 543                         cssmPerror("SecKeyGetCSPHandle", ortn
); 
 547                 /* CSSM_X509_TYPE_VALUE_PAIR - one pair for now */ 
 548                 // tvp.type = CSSMOID_EmailAddress; 
 549                 tvp
.type 
= CSSMOID_CommonName
; 
 550                 tvp
.valueType 
= BER_TAG_PRINTABLE_STRING
; 
 551                 #if FULL_EMAIL_ADDRESS 
 553                         unsigned nameLen 
= strlen(userName
); 
 554                         tvp
.value
.Data 
= (uint8 
*)malloc(nameLen 
+ strlen("@mac.com") + 1); 
 555                         strcpy((char *)tvp
.value
.Data
, userName
); 
 556                         strcpy((char *)tvp
.value
.Data 
+ nameLen
, "@mac.com"); 
 557                         tvp
.value
.Length 
= strlen((char *)tvp
.value
.Data
); 
 560                 tvp
.value
.Data 
= (uint8 
*)userName
; 
 561                 tvp
.value
.Length 
= strlen(userName
); 
 564         /* set up args for CSSM_TP_SubmitCredRequest */ 
 565         if(hostName 
!= NULL
) { 
 566                 tpAuthority
.AuthorityCert 
= NULL
; 
 567                 tpAuthority
.AuthorityLocation 
= &tpNetAddrs
; 
 568                 tpNetAddrs
.AddressType 
= CSSM_ADDR_NAME
; 
 569                 tpNetAddrs
.Address
.Data 
= (uint8 
*)hostName
; 
 570                 tpNetAddrs
.Address
.Length 
= strlen(hostName
); 
 571                 tpAuthPtr 
= &tpAuthority
; 
 574         certReq
.version 
= CSSM_DOT_MAC_TP_REQ_VERSION
; 
 576                 certReq
.cspHand 
= cspHand
; 
 577                 certReq
.clHand 
= cuClStartup(); 
 578                 certReq
.numTypeValuePairs 
= 1; 
 579                 certReq
.typeValuePairs 
= &tvp
; 
 580                 certReq
.publicKey 
= (CSSM_KEY_PTR
)pubKey
; 
 581                 certReq
.privateKey 
= (CSSM_KEY_PTR
)privKey
; 
 584                 certReq
.flags 
|= CSSM_DOTMAC_TP_DO_NOT_POST
; 
 586         if(csrOutName 
!= NULL
) { 
 587                 certReq
.flags 
|= CSSM_DOTMAC_TP_RETURN_CSR
; 
 590                 certReq
.flags 
|= CSSM_DOTMAC_TP_SIGN_RENEW
; 
 593         reqSet
.NumberOfRequests 
= 1; 
 594         reqSet
.Requests 
= &certReq
; 
 596         policyField
.FieldOid 
= *opOid
; 
 597         policyField
.FieldValue
.Data 
= NULL
; 
 598         policyField
.FieldValue
.Length 
= 0; 
 599         memset(&callerAuth
, 0, sizeof(callerAuth
)); 
 600         callerAuth
.Policy
.NumberOfPolicyIds 
= 1; 
 601         callerAuth
.Policy
.PolicyIds 
= &policyField
; 
 603                 ortn 
= SecKeyGetCredentials(privKeyRef
, 
 604                         CSSM_ACL_AUTHORIZATION_SIGN
, 
 605                         kSecCredentialTypeDefault
, 
 606                         const_cast<const CSSM_ACCESS_CREDENTIALS 
**>(&callerAuth
.CallerCredentials
)); 
 608                         cssmPerror("SecKeyGetCredentials", crtn
); 
 613         crtn 
= CSSM_TP_SubmitCredRequest (tpHand
, 
 615                 CSSM_TP_AUTHORITY_REQUEST_CERTISSUE
,    // CSSM_TP_AUTHORITY_REQUEST_TYPE  
 616                 &reqSet
,        // const CSSM_TP_REQUEST_SET *RequestInput, 
 618                 &estTime
,   // sint32 *EstimatedTime, 
 619                 &refId
);        // CSSM_DATA_PTR ReferenceIdentifier 
 622                 case CSSMERR_APPLE_DOTMAC_REQ_QUEUED
: 
 625                          * refId should be a cert or RefId 
 627                         const char *itemType 
= "Cert"; 
 628                         const char *statStr 
= "OK"; 
 629                         if(crtn 
!= CSSM_OK
) { 
 633                         if((refId
.Data 
== NULL
) || (refId
.Length 
== 0)) { 
 634                                 printf("CSSM_TP_SubmitCredRequest returned %s but no data\n", statStr
); 
 637                         if(crtn 
== CSSM_OK
) { 
 638                                 printf("...cert acquisition complete\n"); 
 641                                 printf("...Cert request QUEUED\n"); 
 644                                 if(!writeFile(outFile
, refId
.Data
, refId
.Length
)) { 
 646                                                 printf("...%lu bytes of %s written to %s\n",  
 647                                                         refId
.Length
, itemType
, outFile
); 
 651                                         printf("***Error writing %s to %s\n", itemType
, outFile
); 
 656                                 if(crtn 
== CSSM_OK
) { 
 659                                         if(pemDecode(refId
.Data
, refId
.Length
, &der
, &derLen
)) { 
 660                                                 printf("***Error PEM decoding returned cert\n"); 
 663                                                 printCert(der
, derLen
, CSSM_FALSE
); 
 668                                         printf("RefId data:\n"); 
 669                                         snDumpText(refId
.Data
, refId
.Length
); 
 674                 case CSSMERR_APPLE_DOTMAC_REQ_REDIRECT
: 
 675                         if((refId
.Data 
== NULL
) || (refId
.Length 
== 0)) { 
 676                                 printf("CSSM_TP_SubmitCredRequest returned REDIRECT but no data\n"); 
 679                         printf("...cert acquisition : REDIRECTED to: "); 
 680                         snDumpText(refId
.Data
, refId
.Length
); 
 684                         cssmPerror("CSSM_TP_SubmitCredRequest", crtn
); 
 688                 if((certReq
.csr
.Data 
== NULL
) || (certReq
.csr
.Length 
== 0)) { 
 689                         printf("***Asked for CSR but didn't get one\n"); 
 693                 if(writeFile(csrOutName
, certReq
.csr
.Data
, certReq
.csr
.Length
)) { 
 694                         printf("***Error writing CSR to %s.\n", csrOutName
); 
 697                         printf("...%lu bytes written as CSR to %s\n", certReq
.csr
.Length
, csrOutName
); 
 702         CSSM_ModuleDetach(tpHand
); 
 704                 CSSM_ModuleDetach(certReq
.clHand
); 
 710                 free(certReq
.csr
.Data
); 
 713                 CFRelease(privKeyRef
); 
 716                 CFRelease(pubKeyRef
); 
 719                 cuAppFree(refId
.Data
, NULL
); 
 723                 printf("Pausing for MallocDebug measurement; CR to continue: ");