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: ");