]>
Commit | Line | Data |
---|---|---|
d8f41ccd A |
1 | /* |
2 | * dotMacTool.cpp - .mac TP exerciser | |
3 | */ | |
4 | ||
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> | |
10 | #include <stdlib.h> | |
11 | #include <stdio.h> | |
12 | #include <unistd.h> | |
13 | //#include <security_dotmac_tp/dotMacTp.h> | |
14 | #include <dotMacTp.h> | |
15 | #include <security_cdsa_utils/cuPrintCert.h> | |
16 | ||
17 | #include "keyPicker.h" | |
18 | #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h> | |
19 | ||
20 | #define USER_DEFAULT "dmitchtest@mac.com" | |
21 | #define PWD_DEF "123456" | |
22 | ||
23 | static void usage(char **argv) | |
24 | { | |
25 | printf("usage: %s op [options]\n", argv[0]); | |
26 | printf("Op:\n"); | |
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"); | |
34 | printf("Options:\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"); | |
53 | exit(1); | |
54 | } | |
55 | ||
56 | static CSSM_VERSION vers = {2, 0}; | |
57 | ||
58 | static CSSM_API_MEMORY_FUNCS memFuncs = { | |
59 | cuAppMalloc, | |
60 | cuAppFree, | |
61 | cuAppRealloc, | |
62 | cuAppCalloc, | |
63 | NULL | |
64 | }; | |
65 | ||
66 | static CSSM_TP_HANDLE dotMacStartup() | |
67 | { | |
68 | CSSM_TP_HANDLE tpHand; | |
69 | CSSM_RETURN crtn; | |
70 | ||
71 | if(cuCssmStartup() == CSSM_FALSE) { | |
72 | return 0; | |
73 | } | |
74 | crtn = CSSM_ModuleLoad(&gGuidAppleDotMacTP, | |
75 | CSSM_KEY_HIERARCHY_NONE, | |
76 | NULL, // eventHandler | |
77 | NULL); // AppNotifyCallbackCtx | |
78 | if(crtn) { | |
79 | cuPrintError("CSSM_ModuleLoad(DotMacTP)", crtn); | |
80 | return 0; | |
81 | } | |
82 | crtn = CSSM_ModuleAttach (&gGuidAppleDotMacTP, | |
83 | &vers, | |
84 | &memFuncs, // memFuncs | |
85 | 0, // SubserviceID | |
86 | CSSM_SERVICE_TP, // SubserviceFlags | |
87 | 0, // AttachFlags | |
88 | CSSM_KEY_HIERARCHY_NONE, | |
89 | NULL, // FunctionTable | |
90 | 0, // NumFuncTable | |
91 | NULL, // reserved | |
92 | &tpHand); | |
93 | if(crtn) { | |
94 | cuPrintError("CSSM_ModuleAttach(DotMacTP)", crtn); | |
95 | return 0; | |
96 | } | |
97 | else { | |
98 | return tpHand; | |
99 | } | |
100 | } | |
101 | ||
102 | /* print text, safely */ | |
103 | static void snDumpText( | |
104 | const unsigned char *rcvBuf, | |
105 | unsigned len) | |
106 | { | |
107 | char *cp = (char *)rcvBuf; | |
108 | unsigned i; | |
109 | char c; | |
110 | ||
111 | for(i=0; i<len; i++) { | |
112 | c = *cp++; | |
113 | if(c == '\0') { | |
114 | break; | |
115 | } | |
116 | switch(c) { | |
117 | case '\n': | |
118 | printf("\\n\n"); // graphic and liternal newline | |
119 | break; | |
120 | case '\r': | |
121 | printf("\\r\n"); | |
122 | break; | |
123 | default: | |
124 | if(isprint(c) && (c != '\n')) { | |
125 | printf("%c", c); | |
126 | } | |
127 | else { | |
128 | printf("<%02X>", ((unsigned)c) & 0xff); | |
129 | } | |
130 | break; | |
131 | } | |
132 | ||
133 | } | |
134 | } | |
135 | ||
136 | static OSStatus genKeyPair( | |
137 | SecKeychainRef kcRef, // NULL means the default list | |
138 | SecKeyRef *pubKey, // RETURNED | |
139 | SecKeyRef *privKey) // RETURNED | |
140 | { | |
141 | OSStatus ortn; | |
142 | ||
143 | ortn = SecKeyCreatePair(kcRef, | |
144 | DOT_MAC_KEY_ALG, | |
145 | DOT_MAC_KEY_SIZE, | |
146 | 0, // context handle | |
147 | /* public key usage and attrs */ | |
148 | CSSM_KEYUSE_ANY, | |
149 | CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE, | |
150 | /* private key usage and attrs */ | |
151 | CSSM_KEYUSE_ANY, | |
152 | CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_EXTRACTABLE | | |
153 | CSSM_KEYATTR_SENSITIVE, | |
154 | NULL, // initial access | |
155 | pubKey, | |
156 | privKey); | |
157 | if(ortn) { | |
158 | cssmPerror("SecKeyCreatePair", ortn); | |
159 | } | |
160 | return ortn; | |
161 | } | |
162 | ||
163 | /* Lookup via ReferenceID, obtained from CSSM_TP_SubmitCredRequest() */ | |
164 | OSStatus doLookupViaRefId( | |
165 | CSSM_TP_HANDLE tpHand, | |
166 | unsigned char *refId, | |
167 | unsigned refIdLen, | |
168 | char *outFile, | |
169 | bool verbose) | |
170 | { | |
171 | CSSM_DATA refIdData = { refIdLen, refId }; | |
172 | sint32 EstimatedTime; | |
173 | CSSM_BOOL ConfirmationRequired; | |
174 | CSSM_TP_RESULT_SET_PTR resultSet = NULL; | |
175 | CSSM_RETURN crtn; | |
176 | ||
177 | crtn = CSSM_TP_RetrieveCredResult(tpHand, &refIdData, NULL, | |
178 | &EstimatedTime, &ConfirmationRequired, &resultSet); | |
179 | if(crtn) { | |
180 | cssmPerror("CSSM_TP_RetrieveCredResult", crtn); | |
181 | return crtn; | |
182 | } | |
183 | if(resultSet == NULL) { | |
184 | printf("***CSSM_TP_RetrieveCredResult OK, but no result set\n"); | |
185 | return -1; | |
186 | } | |
187 | if(resultSet->NumberOfResults != 1) { | |
188 | printf("***CSSM_TP_RetrieveCredResult OK, NumberOfResults (%u)\n", | |
189 | (unsigned)resultSet->NumberOfResults); | |
190 | return -1; | |
191 | } | |
192 | if(resultSet->Results == NULL) { | |
193 | printf("***CSSM_TP_RetrieveCredResult OK, but empty result set\n"); | |
194 | return -1; | |
195 | } | |
196 | CSSM_DATA_PTR certData = (CSSM_DATA_PTR)resultSet->Results; | |
197 | ||
198 | printf("...cert retrieval complete\n"); | |
199 | if(outFile) { | |
200 | if(!writeFile(outFile, certData->Data, certData->Length)) { | |
201 | printf("...%lu bytes of cert data written to %s\n", | |
202 | certData->Length, outFile); | |
203 | } | |
204 | else { | |
205 | printf("***Error writing cert to %s\n", outFile); | |
206 | crtn = ioErr; | |
207 | } | |
208 | } | |
209 | else if(verbose) { | |
210 | unsigned char *der; | |
211 | unsigned derLen; | |
212 | if(pemDecode(certData->Data, certData->Length, &der, &derLen)) { | |
213 | printf("***Error PEM decoding returned cert\n"); | |
214 | } | |
215 | else { | |
216 | printCert(der, derLen, CSSM_FALSE); | |
217 | free(der); | |
218 | } | |
219 | } | |
220 | return noErr; | |
221 | } | |
222 | ||
223 | /* | |
224 | * Lookup via user name, a greatly simplified form of CSSM_TP_SubmitCredRequest() | |
225 | */ | |
226 | OSStatus doLookupViaUserName( | |
227 | CSSM_TP_HANDLE tpHand, | |
228 | const CSSM_OID *opOid, | |
229 | const char *userName, | |
230 | const char *hostName, // optional | |
231 | char *outFile, | |
232 | bool verbose) | |
233 | { | |
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}; | |
241 | sint32 estTime; | |
242 | CSSM_TP_CALLERAUTH_CONTEXT callerAuth; | |
243 | ||
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; | |
254 | }; | |
255 | ||
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; | |
265 | ||
266 | CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest (tpHand, | |
267 | tpAuthPtr, | |
268 | CSSM_TP_AUTHORITY_REQUEST_CERTLOOKUP, | |
269 | &reqSet, // const CSSM_TP_REQUEST_SET *RequestInput, | |
270 | &callerAuth, | |
271 | &estTime, // sint32 *EstimatedTime, | |
272 | &certData); // CSSM_DATA_PTR ReferenceIdentifier | |
273 | ||
274 | if(crtn) { | |
275 | cssmPerror("CSSM_TP_SubmitCredRequest(lookup)", crtn); | |
276 | return crtn; | |
277 | } | |
278 | ||
279 | printf("...cert lookup complete\n"); | |
280 | if(outFile) { | |
281 | if(!writeFile(outFile, certData.Data, certData.Length)) { | |
282 | printf("...%lu bytes of cert data written to %s\n", | |
283 | certData.Length, outFile); | |
284 | } | |
285 | else { | |
286 | printf("***Error writing cert to %s\n", outFile); | |
287 | crtn = ioErr; | |
288 | } | |
289 | } | |
290 | if(verbose) { | |
291 | /* This one returns the cert in DER format, we might revisit that */ | |
292 | printCert(certData.Data, certData.Length, CSSM_FALSE); | |
293 | } | |
294 | return crtn; | |
295 | } | |
296 | ||
297 | #define FULL_EMAIL_ADDRESS 1 | |
298 | ||
299 | int main(int argc, char **argv) | |
300 | { | |
301 | CSSM_RETURN crtn; | |
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; | |
309 | char pwdBuf[1000]; | |
310 | CSSM_TP_CALLERAUTH_CONTEXT callerAuth; | |
311 | sint32 estTime; | |
312 | CSSM_DATA refId = {0, NULL}; | |
313 | OSStatus ortn; | |
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; | |
320 | ||
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; | |
334 | bool quiet = false; | |
335 | bool verbose = false; | |
336 | bool lookupViaRefId = false; | |
337 | bool lookupViaUserName = false; | |
338 | char *refIdFile = NULL; | |
339 | bool doPause = false; | |
340 | ||
341 | if(argc < 2) { | |
342 | usage(argv); | |
343 | } | |
344 | switch(argv[1][0]) { | |
345 | case 'L': | |
346 | lookupViaUserName = true; | |
347 | /* drop thru */ | |
348 | case 'g': | |
349 | opOid = &CSSMOID_DOTMAC_CERT_REQ_IDENTITY; | |
350 | break; | |
351 | ||
352 | case 'M': | |
353 | lookupViaUserName = true; | |
354 | /* drop thru */ | |
355 | case 'G': | |
356 | opOid = &CSSMOID_DOTMAC_CERT_REQ_EMAIL_SIGN; | |
357 | break; | |
358 | ||
359 | case 'N': | |
360 | lookupViaUserName = true; | |
361 | /* drop thru */ | |
362 | case 'e': | |
363 | opOid = &CSSMOID_DOTMAC_CERT_REQ_EMAIL_ENCRYPT; | |
364 | break; | |
365 | ||
366 | case 'l': | |
367 | lookupViaRefId = true; | |
368 | break; | |
369 | default: | |
370 | usage(argv); | |
371 | } | |
372 | ||
373 | extern char *optarg; | |
374 | extern int optind; | |
375 | optind = 2; | |
376 | int arg; | |
377 | while ((arg = getopt(argc, argv, "gpk:c:u:Z:H:nzrC:o:hf:Mqv")) != -1) { | |
378 | switch (arg) { | |
379 | case 'g': | |
380 | genKeys = true; | |
381 | break; | |
382 | case 'p': | |
383 | pickKeys = true; | |
384 | break; | |
385 | case 'u': | |
386 | userName = optarg; | |
387 | break; | |
388 | case 'Z': | |
389 | password = optarg; | |
390 | break; | |
391 | case 'z': | |
392 | password = (char *)PWD_DEF; | |
393 | break; | |
394 | case 'k': | |
395 | keychainName = optarg; | |
396 | break; | |
397 | case 'c': | |
398 | csrOutName = optarg; | |
399 | break; | |
400 | case 'C': | |
401 | csrInName = optarg; | |
402 | break; | |
403 | case 'H': | |
404 | hostName = optarg; | |
405 | break; | |
406 | case 'n': | |
407 | doNotPost = true; | |
408 | break; | |
409 | case 'r': | |
410 | doRenew = true; | |
411 | break; | |
412 | case 'o': | |
413 | outFile = optarg; | |
414 | break; | |
415 | case 'f': | |
416 | refIdFile = optarg; | |
417 | break; | |
418 | case 'M': | |
419 | doPause = true; | |
420 | break; | |
421 | case 'v': | |
422 | verbose = true; | |
423 | break; | |
424 | case 'q': | |
425 | quiet = true; | |
426 | break; | |
427 | case 'h': | |
428 | usage(argv); | |
429 | } | |
430 | } | |
431 | ||
432 | if(doPause) { | |
433 | fpurge(stdin); | |
434 | printf("Pausing for MallocDebug attach; CR to continue: "); | |
435 | getchar(); | |
436 | } | |
437 | ||
438 | CSSM_TP_HANDLE tpHand = dotMacStartup(); | |
439 | if(tpHand == 0) { | |
440 | printf("Error attaching to the .mac TP. Check your MDS file.\n"); | |
441 | exit(1); | |
442 | } | |
443 | ||
444 | if(lookupViaRefId) { | |
445 | if(refIdFile == NULL) { | |
446 | printf("I need a refIdFile to do a lookup.\n"); | |
447 | usage(argv); | |
448 | } | |
449 | unsigned char *refId; | |
450 | unsigned refIdLen; | |
451 | int irtn = readFile(refIdFile, &refId, &refIdLen); | |
452 | if(irtn) { | |
453 | printf("***Error reading refId from %s. Aborting.\n", refIdFile); | |
454 | exit(1); | |
455 | } | |
456 | ortn = doLookupViaRefId(tpHand, refId, refIdLen, outFile, verbose); | |
457 | free(refId); | |
458 | goto done; | |
459 | } | |
460 | if(lookupViaUserName) { | |
461 | ortn = doLookupViaUserName(tpHand, opOid, userName, hostName, outFile, verbose); | |
462 | goto done; | |
463 | } | |
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"); | |
467 | exit(1); | |
468 | } | |
469 | ||
470 | memset(&certReq, 0, sizeof(certReq)); | |
471 | ||
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); | |
477 | if(ortn) { | |
478 | cssmPerror("SecKeychainOpen", ortn); | |
479 | exit(1); | |
480 | } | |
481 | ||
482 | /* make sure it's there since a successful SecKeychainOpen proves nothing */ | |
483 | SecKeychainStatus kcStat; | |
484 | ortn = SecKeychainGetStatus(kcRef, &kcStat); | |
485 | if(ortn) { | |
486 | cssmPerror("SecKeychainGetStatus", ortn); | |
487 | goto done; | |
488 | } | |
489 | } | |
490 | ||
491 | if(password == NULL) { | |
492 | const char *pwdp = getpass("Enter .mac password: "); | |
493 | if(pwdp == NULL) { | |
494 | printf("Aboerting.\n"); | |
495 | ortn = paramErr; | |
496 | goto done; | |
497 | } | |
498 | memmove(pwdBuf, pwdp, strlen(pwdp) + 1); | |
499 | password = pwdBuf; | |
500 | } | |
501 | certReq.password.Data = (uint8 *)password; | |
502 | certReq.password.Length = strlen(password); | |
503 | certReq.userName.Data = (uint8 *)userName; | |
504 | certReq.userName.Length = strlen(userName); | |
505 | ||
506 | if(csrInName) { | |
507 | unsigned len; | |
508 | if(readFile(csrInName, &certReq.csr.Data, &len)) { | |
509 | printf("***Error reading CSR from %s. Aborting.\n", csrInName); | |
510 | exit(1); | |
511 | } | |
512 | certReq.csr.Length = len; | |
513 | certReq.flags |= CSSM_DOTMAC_TP_EXIST_CSR; | |
514 | } | |
515 | else { | |
516 | /* | |
517 | * All the stuff the TP needs to actually generate a CSR. | |
518 | * | |
519 | * Get a key pair, somehow. | |
520 | */ | |
521 | if(genKeys) { | |
522 | ortn = genKeyPair(kcRef, &pubKeyRef, &privKeyRef); | |
523 | } | |
524 | else { | |
525 | ortn = keyPicker(kcRef, &pubKeyRef, &privKeyRef); | |
526 | } | |
527 | if(ortn) { | |
528 | printf("Can't proceed without a keypair. Aborting.\n"); | |
529 | exit(1); | |
530 | } | |
531 | ortn = SecKeyGetCSSMKey(pubKeyRef, &pubKey); | |
532 | if(ortn) { | |
533 | cssmPerror("SecKeyGetCSSMKey", ortn); | |
534 | goto done; | |
535 | } | |
536 | ortn = SecKeyGetCSSMKey(privKeyRef, &privKey); | |
537 | if(ortn) { | |
538 | cssmPerror("SecKeyGetCSSMKey", ortn); | |
539 | goto done; | |
540 | } | |
541 | ortn = SecKeyGetCSPHandle(privKeyRef, &cspHand); | |
542 | if(ortn) { | |
543 | cssmPerror("SecKeyGetCSPHandle", ortn); | |
544 | goto done; | |
545 | } | |
546 | ||
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 | |
552 | { | |
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); | |
558 | } | |
559 | #else | |
560 | tvp.value.Data = (uint8 *)userName; | |
561 | tvp.value.Length = strlen(userName); | |
562 | #endif | |
563 | } | |
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; | |
572 | }; | |
573 | ||
574 | certReq.version = CSSM_DOT_MAC_TP_REQ_VERSION; | |
575 | if(!csrInName) { | |
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; | |
582 | } | |
583 | if(doNotPost) { | |
584 | certReq.flags |= CSSM_DOTMAC_TP_DO_NOT_POST; | |
585 | } | |
586 | if(csrOutName != NULL) { | |
587 | certReq.flags |= CSSM_DOTMAC_TP_RETURN_CSR; | |
588 | } | |
589 | if(doRenew) { | |
590 | certReq.flags |= CSSM_DOTMAC_TP_SIGN_RENEW; | |
591 | } | |
592 | ||
593 | reqSet.NumberOfRequests = 1; | |
594 | reqSet.Requests = &certReq; | |
595 | ||
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; | |
602 | if(!csrInName) { | |
603 | ortn = SecKeyGetCredentials(privKeyRef, | |
604 | CSSM_ACL_AUTHORIZATION_SIGN, | |
605 | kSecCredentialTypeDefault, | |
606 | const_cast<const CSSM_ACCESS_CREDENTIALS **>(&callerAuth.CallerCredentials)); | |
607 | if(ortn) { | |
608 | cssmPerror("SecKeyGetCredentials", crtn); | |
609 | goto done; | |
610 | } | |
611 | } | |
612 | ||
613 | crtn = CSSM_TP_SubmitCredRequest (tpHand, | |
614 | tpAuthPtr, | |
615 | CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, // CSSM_TP_AUTHORITY_REQUEST_TYPE | |
616 | &reqSet, // const CSSM_TP_REQUEST_SET *RequestInput, | |
617 | &callerAuth, | |
618 | &estTime, // sint32 *EstimatedTime, | |
619 | &refId); // CSSM_DATA_PTR ReferenceIdentifier | |
620 | switch(crtn) { | |
621 | case CSSM_OK: | |
622 | case CSSMERR_APPLE_DOTMAC_REQ_QUEUED: | |
623 | { | |
624 | /* | |
625 | * refId should be a cert or RefId | |
626 | */ | |
627 | const char *itemType = "Cert"; | |
628 | const char *statStr = "OK"; | |
629 | if(crtn != CSSM_OK) { | |
630 | itemType = "RefId"; | |
631 | statStr = "Cert"; | |
632 | } | |
633 | if((refId.Data == NULL) || (refId.Length == 0)) { | |
634 | printf("CSSM_TP_SubmitCredRequest returned %s but no data\n", statStr); | |
635 | break; | |
636 | } | |
637 | if(crtn == CSSM_OK) { | |
638 | printf("...cert acquisition complete\n"); | |
639 | } | |
640 | else { | |
641 | printf("...Cert request QUEUED\n"); | |
642 | } | |
643 | if(outFile) { | |
644 | if(!writeFile(outFile, refId.Data, refId.Length)) { | |
645 | if(!quiet) { | |
646 | printf("...%lu bytes of %s written to %s\n", | |
647 | refId.Length, itemType, outFile); | |
648 | } | |
649 | } | |
650 | else { | |
651 | printf("***Error writing %s to %s\n", itemType, outFile); | |
652 | crtn = ioErr; | |
653 | } | |
654 | } | |
655 | else if(verbose) { | |
656 | if(crtn == CSSM_OK) { | |
657 | unsigned char *der; | |
658 | unsigned derLen; | |
659 | if(pemDecode(refId.Data, refId.Length, &der, &derLen)) { | |
660 | printf("***Error PEM decoding returned cert\n"); | |
661 | } | |
662 | else { | |
663 | printCert(der, derLen, CSSM_FALSE); | |
664 | free(der); | |
665 | } | |
666 | } | |
667 | else { | |
668 | printf("RefId data:\n"); | |
669 | snDumpText(refId.Data, refId.Length); | |
670 | } | |
671 | } | |
672 | break; | |
673 | } | |
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"); | |
677 | break; | |
678 | } | |
679 | printf("...cert acquisition : REDIRECTED to: "); | |
680 | snDumpText(refId.Data, refId.Length); | |
681 | printf("\n"); | |
682 | break; | |
683 | default: | |
684 | cssmPerror("CSSM_TP_SubmitCredRequest", crtn); | |
685 | break; | |
686 | } | |
687 | if(csrOutName) { | |
688 | if((certReq.csr.Data == NULL) || (certReq.csr.Length == 0)) { | |
689 | printf("***Asked for CSR but didn't get one\n"); | |
690 | ortn = paramErr; | |
691 | goto done; | |
692 | } | |
693 | if(writeFile(csrOutName, certReq.csr.Data, certReq.csr.Length)) { | |
694 | printf("***Error writing CSR to %s.\n", csrOutName); | |
695 | } | |
696 | else { | |
697 | printf("...%lu bytes written as CSR to %s\n", certReq.csr.Length, csrOutName); | |
698 | } | |
699 | } | |
700 | done: | |
701 | /* cleanup */ | |
702 | CSSM_ModuleDetach(tpHand); | |
703 | if(certReq.clHand) { | |
704 | CSSM_ModuleDetach(certReq.clHand); | |
705 | } | |
706 | if(kcRef) { | |
707 | CFRelease(kcRef); | |
708 | } | |
709 | if(csrInName) { | |
710 | free(certReq.csr.Data); | |
711 | } | |
712 | if(privKeyRef) { | |
713 | CFRelease(privKeyRef); | |
714 | } | |
715 | if(pubKeyRef) { | |
716 | CFRelease(pubKeyRef); | |
717 | } | |
718 | if(refId.Data) { | |
719 | cuAppFree(refId.Data, NULL); | |
720 | } | |
721 | if(doPause) { | |
722 | fpurge(stdin); | |
723 | printf("Pausing for MallocDebug measurement; CR to continue: "); | |
724 | getchar(); | |
725 | } | |
726 | ||
727 | return ortn; | |
728 | } |