1
2#include "sslAppUtils.h"
3#include "sslThreading.h"
4#include "identPicker.h"
5#include <utilLib/fileIo.h>
6#include <utilLib/common.h>
7#include <stdlib.h>
8#include <stdio.h>
9#include <sys/param.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
13#include <Security/AuthSession.h>		// for Sec errors
14#include <CoreFoundation/CFDate.h>
15
16/* Set true when PR-3074739 is merged to TOT */
17#define NEW_SSL_ERRS_3074739		1
18
19const char *sslGetCipherSuiteString(SSLCipherSuite cs)
20{
21	static char noSuite[40];
22
23	switch(cs) {
24		case SSL_NULL_WITH_NULL_NULL:
25			return "SSL_NULL_WITH_NULL_NULL";
26		case SSL_RSA_WITH_NULL_MD5:
27			return "SSL_RSA_WITH_NULL_MD5";
28		case SSL_RSA_WITH_NULL_SHA:
29			return "SSL_RSA_WITH_NULL_SHA";
30		case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
31			return "SSL_RSA_EXPORT_WITH_RC4_40_MD5";
32		case SSL_RSA_WITH_RC4_128_MD5:
33			return "SSL_RSA_WITH_RC4_128_MD5";
34		case SSL_RSA_WITH_RC4_128_SHA:
35			return "SSL_RSA_WITH_RC4_128_SHA";
36		case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
37			return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
38		case SSL_RSA_WITH_IDEA_CBC_SHA:
39			return "SSL_RSA_WITH_IDEA_CBC_SHA";
40		case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
41			return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA";
42		case SSL_RSA_WITH_DES_CBC_SHA:
43			return "SSL_RSA_WITH_DES_CBC_SHA";
44		case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
45			return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
46		case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
47			return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
48		case SSL_DH_DSS_WITH_DES_CBC_SHA:
49			return "SSL_DH_DSS_WITH_DES_CBC_SHA";
50		case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:
51			return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA";
52		case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
53			return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
54		case SSL_DH_RSA_WITH_DES_CBC_SHA:
55			return "SSL_DH_RSA_WITH_DES_CBC_SHA";
56		case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:
57			return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA";
58		case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
59			return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
60		case SSL_DHE_DSS_WITH_DES_CBC_SHA:
61			return "SSL_DHE_DSS_WITH_DES_CBC_SHA";
62		case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
63			return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
64		case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
65			return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
66		case SSL_DHE_RSA_WITH_DES_CBC_SHA:
67			return "SSL_DHE_RSA_WITH_DES_CBC_SHA";
68		case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
69			return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
70		case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
71			return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5";
72		case SSL_DH_anon_WITH_RC4_128_MD5:
73			return "SSL_DH_anon_WITH_RC4_128_MD5";
74		case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
75			return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
76		case SSL_DH_anon_WITH_DES_CBC_SHA:
77			return "SSL_DH_anon_WITH_DES_CBC_SHA";
78		case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
79			return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA";
80		case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
81			return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
82		case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
83			return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
84		case SSL_RSA_WITH_RC2_CBC_MD5:
85			return "SSL_RSA_WITH_RC2_CBC_MD5";
86		case SSL_RSA_WITH_IDEA_CBC_MD5:
87			return "SSL_RSA_WITH_IDEA_CBC_MD5";
88		case SSL_RSA_WITH_DES_CBC_MD5:
89			return "SSL_RSA_WITH_DES_CBC_MD5";
90		case SSL_RSA_WITH_3DES_EDE_CBC_MD5:
91			return "SSL_RSA_WITH_3DES_EDE_CBC_MD5";
92		case SSL_NO_SUCH_CIPHERSUITE:
93			return "SSL_NO_SUCH_CIPHERSUITE";
94		case TLS_RSA_WITH_AES_128_CBC_SHA:
95			return "TLS_RSA_WITH_AES_128_CBC_SHA";
96		case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
97			return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
98		case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
99			return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
100		case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
101			return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
102		case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
103			return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
104		case TLS_DH_anon_WITH_AES_128_CBC_SHA:
105			return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
106		case TLS_RSA_WITH_AES_256_CBC_SHA:
107			return "TLS_RSA_WITH_AES_256_CBC_SHA";
108		case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
109			return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
110		case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
111			return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
112		case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
113			return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
114		case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
115			return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
116		case TLS_DH_anon_WITH_AES_256_CBC_SHA:
117			return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
118
119		/* ECDSA */
120		case TLS_ECDH_ECDSA_WITH_NULL_SHA:
121			return "TLS_ECDH_ECDSA_WITH_NULL_SHA";
122		case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
123			return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
124		case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
125			return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
126		case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
127			return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
128		case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
129			return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
130		case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
131			return "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
132		case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
133			return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
134		case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
135			return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
136		case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
137			return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
138		case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
139			return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
140		case TLS_ECDH_RSA_WITH_NULL_SHA:
141			return "TLS_ECDH_RSA_WITH_NULL_SHA";
142		case TLS_ECDH_RSA_WITH_RC4_128_SHA:
143			return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
144		case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
145			return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
146		case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
147			return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
148		case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
149			return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
150		case TLS_ECDHE_RSA_WITH_NULL_SHA:
151			return "TLS_ECDHE_RSA_WITH_NULL_SHA";
152		case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
153			return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
154		case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
155			return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
156		case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
157			return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
158		case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
159			return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
160		case TLS_ECDH_anon_WITH_NULL_SHA:
161			return "TLS_ECDH_anon_WITH_NULL_SHA";
162		case TLS_ECDH_anon_WITH_RC4_128_SHA:
163			return "TLS_ECDH_anon_WITH_RC4_128_SHA";
164		case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
165			return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
166		case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
167			return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
168		case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
169			return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
170
171		default:
172			sprintf(noSuite, "Unknown (%d)", (unsigned)cs);
173			return noSuite;
174	}
175}
176
177/*
178 * Given a SSLProtocolVersion - typically from SSLGetProtocolVersion -
179 * return a string representation.
180 */
181const char *sslGetProtocolVersionString(SSLProtocol prot)
182{
183	static char noProt[20];
184
185	switch(prot) {
186		case kSSLProtocolUnknown:
187			return "kSSLProtocolUnknown";
188		case kSSLProtocol2:
189			return "kSSLProtocol2";
190		case kSSLProtocol3:
191			return "kSSLProtocol3";
192		case kSSLProtocol3Only:
193			return "kSSLProtocol3Only";
194		case kTLSProtocol1:
195			return "kTLSProtocol1";
196		case kTLSProtocol1Only:
197			return "kTLSProtocol1Only";
198		default:
199			sprintf(noProt, "Unknown (%d)", (unsigned)prot);
200			return noProt;
201	}
202}
203
204/*
205 * Return string representation of SecureTransport-related OSStatus.
206 */
207const char *sslGetSSLErrString(OSStatus err)
208{
209	static char noErrStr[20];
210
211	switch(err) {
212		case noErr:
213			return "noErr";
214		case memFullErr:
215			return "memFullErr";
216		case paramErr:
217			return "paramErr";
218		case unimpErr:
219			return "unimpErr";
220		case ioErr:
221			return "ioErr";
222		case badReqErr:
223			return "badReqErr";
224		case errSSLProtocol:
225			return "errSSLProtocol";
226		case errSSLNegotiation:
227			return "errSSLNegotiation";
228		case errSSLFatalAlert:
229			return "errSSLFatalAlert";
230		case errSSLWouldBlock:
231			return "errSSLWouldBlock";
232		case errSSLSessionNotFound:
233			return "errSSLSessionNotFound";
234		case errSSLClosedGraceful:
235			return "errSSLClosedGraceful";
236		case errSSLClosedAbort:
237			return "errSSLClosedAbort";
238   		case errSSLXCertChainInvalid:
239			return "errSSLXCertChainInvalid";
240		case errSSLBadCert:
241			return "errSSLBadCert";
242		case errSSLCrypto:
243			return "errSSLCrypto";
244		case errSSLInternal:
245			return "errSSLInternal";
246		case errSSLModuleAttach:
247			return "errSSLModuleAttach";
248		case errSSLUnknownRootCert:
249			return "errSSLUnknownRootCert";
250		case errSSLNoRootCert:
251			return "errSSLNoRootCert";
252		case errSSLCertExpired:
253			return "errSSLCertExpired";
254		case errSSLCertNotYetValid:
255			return "errSSLCertNotYetValid";
256		case errSSLClosedNoNotify:
257			return "errSSLClosedNoNotify";
258		case errSSLBufferOverflow:
259			return "errSSLBufferOverflow";
260		case errSSLBadCipherSuite:
261			return "errSSLBadCipherSuite";
262		/* TLS/Panther addenda */
263		case errSSLPeerUnexpectedMsg:
264			return "errSSLPeerUnexpectedMsg";
265		case errSSLPeerBadRecordMac:
266			return "errSSLPeerBadRecordMac";
267		case errSSLPeerDecryptionFail:
268			return "errSSLPeerDecryptionFail";
269		case errSSLPeerRecordOverflow:
270			return "errSSLPeerRecordOverflow";
271		case errSSLPeerDecompressFail:
272			return "errSSLPeerDecompressFail";
273		case errSSLPeerHandshakeFail:
274			return "errSSLPeerHandshakeFail";
275		case errSSLPeerBadCert:
276			return "errSSLPeerBadCert";
277		case errSSLPeerUnsupportedCert:
278			return "errSSLPeerUnsupportedCert";
279		case errSSLPeerCertRevoked:
280			return "errSSLPeerCertRevoked";
281		case errSSLPeerCertExpired:
282			return "errSSLPeerCertExpired";
283		case errSSLPeerCertUnknown:
284			return "errSSLPeerCertUnknown";
285		case errSSLIllegalParam:
286			return "errSSLIllegalParam";
287		case errSSLPeerUnknownCA:
288			return "errSSLPeerUnknownCA";
289		case errSSLPeerAccessDenied:
290			return "errSSLPeerAccessDenied";
291		case errSSLPeerDecodeError:
292			return "errSSLPeerDecodeError";
293		case errSSLPeerDecryptError:
294			return "errSSLPeerDecryptError";
295		case errSSLPeerExportRestriction:
296			return "errSSLPeerExportRestriction";
297		case errSSLPeerProtocolVersion:
298			return "errSSLPeerProtocolVersion";
299		case errSSLPeerInsufficientSecurity:
300			return "errSSLPeerInsufficientSecurity";
301		case errSSLPeerInternalError:
302			return "errSSLPeerInternalError";
303		case errSSLPeerUserCancelled:
304			return "errSSLPeerUserCancelled";
305		case errSSLPeerNoRenegotiation:
306			return "errSSLPeerNoRenegotiation";
307		case errSSLHostNameMismatch:
308			return "errSSLHostNameMismatch";
309		case errSSLConnectionRefused:
310			return "errSSLConnectionRefused";
311		case errSSLDecryptionFail:
312			return "errSSLDecryptionFail";
313		case errSSLBadRecordMac:
314			return "errSSLBadRecordMac";
315		case errSSLRecordOverflow:
316			return "errSSLRecordOverflow";
317		case errSSLBadConfiguration:
318			return "errSSLBadConfiguration";
319
320		/* some from the Sec layer */
321		case errSecNotAvailable:			return "errSecNotAvailable";
322		case errSecReadOnly:				return "errSecReadOnly";
323		case errSecAuthFailed:				return "errSecAuthFailed";
324		case errSecNoSuchKeychain:			return "errSecNoSuchKeychain";
325		case errSecInvalidKeychain:			return "errSecInvalidKeychain";
326		case errSecDuplicateItem:			return "errSecDuplicateItem";
327		case errSecItemNotFound:			return "errSecItemNotFound";
328		case errSecNoSuchAttr:				return "errSecNoSuchAttr";
329		case errSecInvalidItemRef:			return "errSecInvalidItemRef";
330		case errSecInvalidSearchRef:		return "errSecInvalidSearchRef";
331		case errSecNoSuchClass:				return "errSecNoSuchClass";
332		case errSecNoDefaultKeychain:		return "errSecNoDefaultKeychain";
333		case errSecWrongSecVersion:			return "errSecWrongSecVersion";
334		case errSessionInvalidId:			return "errSessionInvalidId";
335		case errSessionInvalidAttributes:	return "errSessionInvalidAttributes";
336		case errSessionAuthorizationDenied:	return "errSessionAuthorizationDenied";
337		case errSessionInternal:			return "errSessionInternal";
338		case errSessionInvalidFlags:		return "errSessionInvalidFlags";
339		case errSecInvalidTrustSettings:	return "errSecInvalidTrustSettings";
340		case errSecNoTrustSettings:			return "errSecNoTrustSettings";
341
342		default:
343			if(err < (CSSM_BASE_ERROR +
344			         (CSSM_ERRORCODE_MODULE_EXTENT * 8))) {
345				/* assume CSSM error */
346				return cssmErrToStr(err);
347			}
348			else {
349				sprintf(noErrStr, "Unknown (%d)", (unsigned)err);
350				return noErrStr;
351			}
352	}
353}
354
355void printSslErrStr(
356	const char 	*op,
357	OSStatus 	err)
358{
359	printf("*** %s: %s\n", op, sslGetSSLErrString(err));
360}
361
362const char *sslGetClientCertStateString(SSLClientCertificateState state)
363{
364	static char noState[20];
365
366	switch(state) {
367		case kSSLClientCertNone:
368			return "ClientCertNone";
369		case kSSLClientCertRequested:
370			return "CertRequested";
371		case kSSLClientCertSent:
372			return "ClientCertSent";
373		case kSSLClientCertRejected:
374			return "ClientCertRejected";
375		default:
376			sprintf(noState, "Unknown (%d)", (unsigned)state);
377			return noState;
378	}
379
380}
381
382const char *sslGetClientAuthTypeString(SSLClientAuthenticationType authType)
383{
384	static char noType[20];
385
386	switch(authType) {
387		case SSLClientAuthNone:
388			return "None";
389		case SSLClientAuth_RSASign:
390			return "RSASign";
391		case SSLClientAuth_DSSSign:
392			return "DSSSign";
393		case SSLClientAuth_RSAFixedDH:
394			return "RSAFixedDH";
395		case SSLClientAuth_DSS_FixedDH:
396			return "DSS_FixedDH";
397		case SSLClientAuth_ECDSASign:
398			return "ECDSASign";
399		case SSLClientAuth_RSAFixedECDH:
400			return "RSAFixedECDH";
401		case SSLClientAuth_ECDSAFixedECDH:
402			return "ECDSAFixedECDH";
403		default:
404			sprintf(noType, "Unknown (%d)", (unsigned)authType);
405			return noType;
406	}
407}
408
409/*
410 * Convert a keychain name (which may be NULL) into the CFArrayRef required
411 * by SSLSetCertificate. This is a bare-bones example of this operation,
412 * since it requires and assumes that there is exactly one SecIdentity
413 * in the keychain - i.e., there is exactly one matching cert/private key
414 * pair. A real world server would probably search a keychain for a SecIdentity
415 * matching some specific criteria.
416 */
417CFArrayRef getSslCerts(
418	const char			*kcName,				// may be NULL, i.e., use default
419	CSSM_BOOL			encryptOnly,
420	CSSM_BOOL			completeCertChain,
421	const char			*anchorFile,			// optional trusted anchor
422	SecKeychainRef		*pKcRef)				// RETURNED
423{
424	SecKeychainRef 		kcRef = nil;
425	OSStatus			ortn;
426
427	*pKcRef = nil;
428
429	/* pick a keychain */
430	if(kcName) {
431		ortn = SecKeychainOpen(kcName, &kcRef);
432		if(ortn) {
433			printf("SecKeychainOpen returned %d.\n", (int)ortn);
434			printf("Cannot open keychain at %s. Aborting.\n", kcName);
435			return NULL;
436		}
437	}
438	else {
439		/* use default keychain */
440		ortn = SecKeychainCopyDefault(&kcRef);
441		if(ortn) {
442			printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn);
443			return nil;
444		}
445	}
446	*pKcRef = kcRef;
447	return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain,
448		NULL,		// SSL policy
449		anchorFile);
450}
451
452/*
453 * Determine if specified SecCertificateRef is a self-signed cert.
454 * We do this by comparing the subject and issuerr names; no cryptographic
455 * verification is performed.
456 *
457 * Returns true if the cert appears to be a root.
458 */
459static bool isCertRefRoot(
460	SecCertificateRef certRef)
461{
462	/* just search for the two attrs we want */
463	UInt32 tags[2] = {kSecSubjectItemAttr, kSecIssuerItemAttr};
464	SecKeychainAttributeInfo attrInfo;
465	attrInfo.count = 2;
466	attrInfo.tag = tags;
467	attrInfo.format = NULL;
468	SecKeychainAttributeList *attrList = NULL;
469	SecKeychainAttribute *attr1 = NULL;
470	SecKeychainAttribute *attr2 = NULL;
471	bool brtn = false;
472
473	OSStatus ortn = SecKeychainItemCopyAttributesAndData(
474		(SecKeychainItemRef)certRef,
475		&attrInfo,
476		NULL,			// itemClass
477		&attrList,
478		NULL,			// length - don't need the data
479		NULL);			// outData
480	if(ortn) {
481		cssmPerror("SecKeychainItemCopyAttributesAndData", ortn);
482		/* may want to be a bit more robust here, but this should
483		 * never happen */
484		return false;
485	}
486	/* subsequent errors to errOut: */
487
488	if((attrList == NULL) || (attrList->count != 2)) {
489		printf("***Unexpected result fetching label attr\n");
490		goto errOut;
491	}
492
493	/* rootness is just byte-for-byte compare of the two names */
494	attr1 = &attrList->attr[0];
495	attr2 = &attrList->attr[1];
496	if(attr1->length == attr2->length) {
497		if(memcmp(attr1->data, attr2->data, attr1->length) == 0) {
498			brtn = true;
499		}
500	}
501errOut:
502	SecKeychainItemFreeAttributesAndData(attrList, NULL);
503	return brtn;
504}
505
506
507/*
508 * Given a SecIdentityRef, do our best to construct a complete, ordered, and
509 * verified cert chain, returning the result in a CFArrayRef. The result is
510 * suitable for use when calling SSLSetCertificate().
511 */
512OSStatus sslCompleteCertChain(
513	SecIdentityRef 		identity,
514	SecCertificateRef	trustedAnchor,	// optional additional trusted anchor
515	bool 				includeRoot, 	// include the root in outArray
516	const CSSM_OID		*vfyPolicy,		// optional - if NULL, use SSL
517	CFArrayRef			*outArray)		// created and RETURNED
518{
519	CFMutableArrayRef 			certArray;
520	SecTrustRef					secTrust = NULL;
521	SecPolicyRef				policy = NULL;
522	SecPolicySearchRef			policySearch = NULL;
523	SecTrustResultType			secTrustResult;
524	CSSM_TP_APPLE_EVIDENCE_INFO *dummyEv;			// not used
525	CFArrayRef					certChain = NULL;   // constructed chain
526	CFIndex 					numResCerts;
527
528	certArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
529	CFArrayAppendValue(certArray, identity);
530
531	/*
532	 * Case 1: identity is a root; we're done. Note that this case
533	 * overrides the includeRoot argument.
534	 */
535	SecCertificateRef certRef;
536	OSStatus ortn = SecIdentityCopyCertificate(identity, &certRef);
537	if(ortn) {
538		/* should never happen */
539		cssmPerror("SecIdentityCopyCertificate", ortn);
540		return ortn;
541	}
542	bool isRoot = isCertRefRoot(certRef);
543	if(isRoot) {
544		*outArray = certArray;
545		CFRelease(certRef);
546		return noErr;
547	}
548
549	/*
550	 * Now use SecTrust to get a complete cert chain, using all of the
551	 * user's keychains to look for intermediate certs.
552	 * NOTE this does NOT handle root certs which are not in the system
553	 * root cert DB. (The above case, where the identity is a root cert, does.)
554	 */
555	CFMutableArrayRef subjCerts = CFArrayCreateMutable(NULL, 1, &kCFTypeArrayCallBacks);
556	CFArraySetValueAtIndex(subjCerts, 0, certRef);
557
558	/* the array owns the subject cert ref now */
559	CFRelease(certRef);
560
561	/* Get a SecPolicyRef for SSL cert chain verification */
562	ortn = SecPolicySearchCreate(CSSM_CERT_X_509v3,
563		vfyPolicy ? vfyPolicy : &CSSMOID_APPLE_TP_SSL,
564		NULL,				// value
565		&policySearch);
566	if(ortn) {
567		cssmPerror("SecPolicySearchCreate", ortn);
568		goto errOut;
569	}
570	ortn = SecPolicySearchCopyNext(policySearch, &policy);
571	if(ortn) {
572		cssmPerror("SecPolicySearchCopyNext", ortn);
573		goto errOut;
574	}
575
576	/* build a SecTrustRef for specified policy and certs */
577	ortn = SecTrustCreateWithCertificates(subjCerts,
578		policy, &secTrust);
579	if(ortn) {
580		cssmPerror("SecTrustCreateWithCertificates", ortn);
581		goto errOut;
582	}
583
584	if(trustedAnchor) {
585		/*
586		 * Tell SecTrust to trust this one in addition to the current
587		 * trusted system-wide anchors.
588		 */
589		CFMutableArrayRef newAnchors;
590		CFArrayRef currAnchors;
591
592		ortn = SecTrustCopyAnchorCertificates(&currAnchors);
593		if(ortn) {
594			/* should never happen */
595			cssmPerror("SecTrustCopyAnchorCertificates", ortn);
596			goto errOut;
597		}
598		newAnchors = CFArrayCreateMutableCopy(NULL,
599			CFArrayGetCount(currAnchors) + 1,
600			currAnchors);
601		CFRelease(currAnchors);
602		CFArrayAppendValue(newAnchors, trustedAnchor);
603		ortn = SecTrustSetAnchorCertificates(secTrust, newAnchors);
604		CFRelease(newAnchors);
605		if(ortn) {
606			cssmPerror("SecTrustSetAnchorCertificates", ortn);
607			goto errOut;
608		}
609	}
610	/* evaluate: GO */
611	ortn = SecTrustEvaluate(secTrust, &secTrustResult);
612	if(ortn) {
613		cssmPerror("SecTrustEvaluate", ortn);
614		goto errOut;
615	}
616	switch(secTrustResult) {
617		case kSecTrustResultUnspecified:
618			/* cert chain valid, no special UserTrust assignments */
619		case kSecTrustResultProceed:
620			/* cert chain valid AND user explicitly trusts this */
621			break;
622		default:
623			/*
624			 * Cert chain construction failed.
625			 * Just go with the single subject cert we were given.
626			 */
627			printf("***Warning: could not construct completed cert chain\n");
628			ortn = noErr;
629			goto errOut;
630	}
631
632	/* get resulting constructed cert chain */
633	ortn = SecTrustGetResult(secTrust, &secTrustResult, &certChain, &dummyEv);
634	if(ortn) {
635		cssmPerror("SecTrustEvaluate", ortn);
636		goto errOut;
637	}
638
639	/*
640	 * Copy certs from constructed chain to our result array, skipping
641	 * the leaf (which is already there, as a SecIdentityRef) and possibly
642	 * a root.
643	 */
644	numResCerts = CFArrayGetCount(certChain);
645	if(numResCerts < 2) {
646		/*
647		 * Can't happen: if subject was a root, we'd already have returned.
648		 * If chain doesn't verify to a root, we'd have bailed after
649		 * SecTrustEvaluate().
650		 */
651		printf("***sslCompleteCertChain screwup: numResCerts %d\n",
652			(int)numResCerts);
653		ortn = noErr;
654		goto errOut;
655	}
656	if(!includeRoot) {
657		/* skip the last (root) cert) */
658		numResCerts--;
659	}
660	for(CFIndex dex=1; dex<numResCerts; dex++) {
661		certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certChain, dex);
662		CFArrayAppendValue(certArray, certRef);
663	}
664errOut:
665	/* clean up */
666	if(secTrust) {
667		CFRelease(secTrust);
668	}
669	if(subjCerts) {
670		CFRelease(subjCerts);
671	}
672	if(policy) {
673		CFRelease(policy);
674	}
675	if(policySearch) {
676		CFRelease(policySearch);
677	}
678	*outArray = certArray;
679	return ortn;
680}
681
682
683/*
684 * Given an open keychain, find a SecIdentityRef and munge it into
685 * a CFArrayRef required by SSLSetCertificate().
686 */
687CFArrayRef sslKcRefToCertArray(
688	SecKeychainRef		kcRef,
689	CSSM_BOOL			encryptOnly,
690	CSSM_BOOL			completeCertChain,
691	const CSSM_OID		*vfyPolicy,		// optional - if NULL, use SSL policy to complete
692	const char			*trustedAnchorFile)
693{
694	/* quick check to make sure the keychain exists */
695	SecKeychainStatus kcStat;
696	OSStatus ortn = SecKeychainGetStatus(kcRef, &kcStat);
697	if(ortn) {
698		printSslErrStr("SecKeychainGetStatus", ortn);
699		printf("Can not open keychain. Aborting.\n");
700		return nil;
701	}
702
703	/*
704	 * Search for "any" identity matching specified key use;
705	 * in this app, we expect there to be exactly one.
706	 */
707	SecIdentitySearchRef srchRef = nil;
708	ortn = SecIdentitySearchCreate(kcRef,
709		encryptOnly ? CSSM_KEYUSE_DECRYPT : CSSM_KEYUSE_SIGN,
710		&srchRef);
711	if(ortn) {
712		printf("SecIdentitySearchCreate returned %d.\n", (int)ortn);
713		printf("Cannot find signing key in keychain. Aborting.\n");
714		return nil;
715	}
716	SecIdentityRef identity = nil;
717	ortn = SecIdentitySearchCopyNext(srchRef, &identity);
718	if(ortn) {
719		printf("SecIdentitySearchCopyNext returned %d.\n", (int)ortn);
720		printf("Cannot find signing key in keychain. Aborting.\n");
721		return nil;
722	}
723	if(CFGetTypeID(identity) != SecIdentityGetTypeID()) {
724		printf("SecIdentitySearchCopyNext CFTypeID failure!\n");
725		return nil;
726	}
727
728	/*
729	 * Found one.
730	 */
731	if(completeCertChain) {
732		/*
733		 * Place it and the other certs needed to verify it -
734		 * up to but not including the root - in a CFArray.
735		 */
736		SecCertificateRef anchorCert = NULL;
737		if(trustedAnchorFile) {
738			ortn = sslReadAnchor(trustedAnchorFile, &anchorCert);
739			if(ortn) {
740				printf("***Error reading anchor file\n");
741			}
742		}
743		CFArrayRef ca;
744		ortn = sslCompleteCertChain(identity, anchorCert, false, vfyPolicy, &ca);
745		if(anchorCert) {
746			CFRelease(anchorCert);
747		}
748		return ca;
749	}
750	else {
751		/* simple case, just this one identity */
752		CFArrayRef ca = CFArrayCreate(NULL,
753			(const void **)&identity,
754			1,
755			NULL);
756		if(ca == nil) {
757			printf("CFArrayCreate error\n");
758		}
759		return ca;
760	}
761}
762
763OSStatus addTrustedSecCert(
764	SSLContextRef 		ctx,
765	SecCertificateRef 	secCert,
766	CSSM_BOOL 			replaceAnchors)
767{
768	OSStatus ortn;
769	CFMutableArrayRef array;
770
771	if(secCert == NULL) {
772		printf("***addTrustedSecCert screwup\n");
773		return paramErr;
774	}
775	array = CFArrayCreateMutable(kCFAllocatorDefault,
776		(CFIndex)1, &kCFTypeArrayCallBacks);
777	if(array == NULL) {
778		return memFullErr;
779	}
780	CFArrayAppendValue(array, secCert);
781	ortn = SSLSetTrustedRoots(ctx, array, replaceAnchors ? true : false);
782	if(ortn) {
783		printSslErrStr("SSLSetTrustedRoots", ortn);
784	}
785	CFRelease(array);
786	return ortn;
787}
788
789OSStatus sslReadAnchor(
790	const char 			*anchorFile,
791	SecCertificateRef 	*certRef)
792{
793	OSStatus ortn;
794	SecCertificateRef secCert;
795	unsigned char *certData;
796	unsigned certLen;
797	CSSM_DATA cert;
798	int rtn;
799
800	rtn = cspReadFile(anchorFile, &certData, &certLen);
801	if(rtn) {
802		printf("cspReadFile(%s) returned %d\n", anchorFile, rtn);
803		return -1;
804	}
805	cert.Data = certData;
806	cert.Length = certLen;
807	ortn = SecCertificateCreateFromData(&cert,
808			CSSM_CERT_X_509v3,
809			CSSM_CERT_ENCODING_DER,
810			&secCert);
811	free(certData);
812	if(ortn) {
813		printf("***SecCertificateCreateFromData returned %d\n", (int)ortn);
814		return ortn;
815	}
816	*certRef = secCert;
817	return noErr;
818}
819
820OSStatus sslAddTrustedRoot(
821	SSLContextRef 	ctx,
822	const char 		*anchorFile,
823	CSSM_BOOL 		replaceAnchors)
824{
825	OSStatus ortn;
826	SecCertificateRef secCert;
827
828	ortn = sslReadAnchor(anchorFile, &secCert);
829	if(ortn) {
830		printf("***Error (%ld) reading %s. SSLSetTrustedRoots skipped.\n",
831			(long)ortn, anchorFile);
832		return ortn;
833	}
834	return addTrustedSecCert(ctx, secCert, replaceAnchors);
835}
836
837#if 0
838/* Per 3537606 this is no longer necessary */
839/*
840 * Assume incoming identity contains a root (e.g., created by
841 * certtool) and add that cert to ST's trusted anchors. This
842 * enables ST's verify of the incoming chain to succeed without
843 * a kludgy "AllowAnyRoot" specification.
844 */
845OSStatus addIdentityAsTrustedRoot(
846	SSLContextRef 	ctx,
847	CFArrayRef		identArray)
848{
849	CFIndex numItems = CFArrayGetCount(identArray);
850	if(numItems == 0) {
851		printf("***addIdentityAsTrustedRoot: empty identArray\n");
852		return paramErr;
853	}
854
855	/* Root should be the last item - could be identity, could be cert */
856	CFTypeRef theItem = CFArrayGetValueAtIndex(identArray, numItems - 1);
857	if(CFGetTypeID(theItem) == SecIdentityGetTypeID()) {
858		/* identity */
859		SecCertificateRef certRef;
860		OSStatus ortn = SecIdentityCopyCertificate(
861			(SecIdentityRef)theItem, &certRef);
862		if(ortn) {
863			cssmPerror("SecIdentityCopyCertificate", ortn);
864			printf("***Error gettting cert from identity\n");
865			return ortn;
866		}
867		ortn = addTrustedSecCert(ctx, certRef, CSSM_FALSE);
868		CFRelease(certRef);
869		return ortn;
870	}
871	else if(CFGetTypeID(theItem) == SecCertificateGetTypeID()) {
872		/* certificate */
873		return addTrustedSecCert(ctx, (SecCertificateRef)theItem, CSSM_FALSE);
874	}
875	else {
876		printf("***Bogus item in identity array\n");
877		return paramErr;
878	}
879}
880#else
881OSStatus addIdentityAsTrustedRoot(
882	SSLContextRef 	ctx,
883	CFArrayRef		identArray)
884{
885	return noErr;
886}
887#endif
888
889/*
890 * Lists of SSLCipherSuites used in sslSetCipherRestrictions. Note that the
891 * SecureTransport library does not implement all of these; we only specify
892 * the ones it claims to support.
893 */
894const SSLCipherSuite suites40[] = {
895	SSL_RSA_EXPORT_WITH_RC4_40_MD5,
896	SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
897	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
898	SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
899	SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
900	SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
901	SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
902	SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
903	SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
904	SSL_NO_SUCH_CIPHERSUITE
905};
906const SSLCipherSuite suitesDES[] = {
907	SSL_RSA_WITH_DES_CBC_SHA,
908	SSL_DH_DSS_WITH_DES_CBC_SHA,
909	SSL_DH_RSA_WITH_DES_CBC_SHA,
910	SSL_DHE_DSS_WITH_DES_CBC_SHA,
911	SSL_DHE_RSA_WITH_DES_CBC_SHA,
912	SSL_DH_anon_WITH_DES_CBC_SHA,
913	SSL_RSA_WITH_DES_CBC_MD5,
914	SSL_NO_SUCH_CIPHERSUITE
915};
916const SSLCipherSuite suitesDES40[] = {
917	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
918	SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
919	SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
920	SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
921	SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
922	SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
923	SSL_NO_SUCH_CIPHERSUITE
924};
925const SSLCipherSuite suites3DES[] = {
926	SSL_RSA_WITH_3DES_EDE_CBC_SHA,
927	SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
928	SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
929	SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
930	SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
931	SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
932	SSL_RSA_WITH_3DES_EDE_CBC_MD5,
933	SSL_NO_SUCH_CIPHERSUITE
934};
935const SSLCipherSuite suitesRC4[] = {
936	SSL_RSA_WITH_RC4_128_MD5,
937	SSL_RSA_WITH_RC4_128_SHA,
938	SSL_DH_anon_WITH_RC4_128_MD5,
939	SSL_NO_SUCH_CIPHERSUITE
940};
941const SSLCipherSuite suitesRC4_40[] = {
942	SSL_RSA_EXPORT_WITH_RC4_40_MD5,
943	SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
944	SSL_NO_SUCH_CIPHERSUITE
945};
946const SSLCipherSuite suitesRC2[] = {
947	SSL_RSA_WITH_RC2_CBC_MD5,
948	SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
949	SSL_NO_SUCH_CIPHERSUITE
950};
951const SSLCipherSuite suitesAES128[] = {
952	TLS_RSA_WITH_AES_128_CBC_SHA,
953	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
954	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
955	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
956	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
957	TLS_DH_anon_WITH_AES_128_CBC_SHA
958};
959const SSLCipherSuite suitesAES256[] = {
960	TLS_RSA_WITH_AES_256_CBC_SHA,
961	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
962	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
963	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
964	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
965	TLS_DH_anon_WITH_AES_256_CBC_SHA
966};
967const SSLCipherSuite suitesDH[] = {
968    SSL_DH_DSS_WITH_DES_CBC_SHA,
969    SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
970    SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
971    SSL_DH_RSA_WITH_DES_CBC_SHA,
972    SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
973    SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
974    SSL_DHE_DSS_WITH_DES_CBC_SHA,
975    SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
976    SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
977    SSL_DHE_RSA_WITH_DES_CBC_SHA,
978    SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
979    SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
980    SSL_DH_anon_WITH_RC4_128_MD5,
981    SSL_DH_anon_WITH_DES_CBC_SHA,
982    SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
983    SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
984    SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
985	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
986	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
987	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
988	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
989	TLS_DH_anon_WITH_AES_128_CBC_SHA,
990	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
991	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
992	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
993	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
994	TLS_DH_anon_WITH_AES_256_CBC_SHA,
995	SSL_NO_SUCH_CIPHERSUITE
996};
997const SSLCipherSuite suitesDHAnon[] = {
998    SSL_DH_anon_WITH_RC4_128_MD5,
999    SSL_DH_anon_WITH_DES_CBC_SHA,
1000    SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
1001    SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
1002    SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
1003	TLS_DH_anon_WITH_AES_128_CBC_SHA,
1004	TLS_DH_anon_WITH_AES_256_CBC_SHA,
1005	SSL_NO_SUCH_CIPHERSUITE
1006};
1007const SSLCipherSuite suitesDH_RSA[] = {
1008    SSL_DH_RSA_WITH_DES_CBC_SHA,
1009    SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
1010    SSL_DHE_RSA_WITH_DES_CBC_SHA,
1011    SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
1012    SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
1013    SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
1014	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
1015	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
1016	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
1017	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
1018	SSL_NO_SUCH_CIPHERSUITE
1019};
1020const SSLCipherSuite suitesDH_DSS[] = {
1021    SSL_DH_DSS_WITH_DES_CBC_SHA,
1022    SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
1023    SSL_DHE_DSS_WITH_DES_CBC_SHA,
1024    SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
1025    SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
1026    SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
1027	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
1028	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
1029	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
1030	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
1031	SSL_NO_SUCH_CIPHERSUITE
1032};
1033const SSLCipherSuite suites_SHA1[] = {
1034	SSL_RSA_WITH_RC4_128_SHA,
1035	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
1036	SSL_RSA_WITH_IDEA_CBC_SHA,
1037	SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
1038	SSL_RSA_WITH_DES_CBC_SHA,
1039	SSL_RSA_WITH_3DES_EDE_CBC_SHA,
1040	SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA,
1041	SSL_DH_DSS_WITH_DES_CBC_SHA,
1042	SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA,
1043	SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA,
1044	SSL_DH_RSA_WITH_DES_CBC_SHA,
1045	SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA,
1046	SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
1047	SSL_DHE_DSS_WITH_DES_CBC_SHA,
1048	SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
1049	SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
1050	SSL_DHE_RSA_WITH_DES_CBC_SHA,
1051	SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
1052	SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
1053	SSL_DH_anon_WITH_DES_CBC_SHA,
1054	SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
1055	SSL_FORTEZZA_DMS_WITH_NULL_SHA,
1056	SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA,
1057	TLS_RSA_WITH_AES_128_CBC_SHA,
1058	TLS_DH_DSS_WITH_AES_128_CBC_SHA,
1059	TLS_DH_RSA_WITH_AES_128_CBC_SHA,
1060	TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
1061	TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
1062	TLS_DH_anon_WITH_AES_128_CBC_SHA,
1063	TLS_RSA_WITH_AES_256_CBC_SHA,
1064	TLS_DH_DSS_WITH_AES_256_CBC_SHA,
1065	TLS_DH_RSA_WITH_AES_256_CBC_SHA,
1066	TLS_DHE_DSS_WITH_AES_256_CBC_SHA,
1067	TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
1068	TLS_DH_anon_WITH_AES_256_CBC_SHA,
1069	SSL_NO_SUCH_CIPHERSUITE
1070};
1071const SSLCipherSuite suites_MD5[] = {
1072	SSL_RSA_EXPORT_WITH_RC4_40_MD5,
1073	SSL_RSA_WITH_RC4_128_MD5,
1074	SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
1075	SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
1076	SSL_DH_anon_WITH_RC4_128_MD5,
1077	SSL_NO_SUCH_CIPHERSUITE
1078};
1079const SSLCipherSuite suites_NULL[] = {
1080	SSL_RSA_WITH_NULL_MD5,
1081	SSL_NO_SUCH_CIPHERSUITE
1082};
1083
1084const SSLCipherSuite suites_ECDHE[] = {
1085	TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
1086	TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
1087	TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
1088	TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
1089	TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
1090	TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
1091	TLS_ECDHE_RSA_WITH_RC4_128_SHA,
1092	TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
1093	SSL_NO_SUCH_CIPHERSUITE
1094};
1095
1096const SSLCipherSuite suites_ECDH[] = {
1097	TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
1098	TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
1099	TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
1100	TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
1101	TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
1102	TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
1103	TLS_ECDH_RSA_WITH_RC4_128_SHA,
1104	TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
1105	SSL_NO_SUCH_CIPHERSUITE
1106};
1107
1108
1109/*
1110 * Given an SSLContextRef and an array of SSLCipherSuites, terminated by
1111 * SSL_NO_SUCH_CIPHERSUITE, select those SSLCipherSuites which the library
1112 * supports and do a SSLSetEnabledCiphers() specifying those.
1113 */
1114OSStatus sslSetEnabledCiphers(
1115	SSLContextRef ctx,
1116	const SSLCipherSuite *ciphers)
1117{
1118	size_t numSupported;
1119	OSStatus ortn;
1120	SSLCipherSuite *supported = NULL;
1121	SSLCipherSuite *enabled = NULL;
1122	unsigned enabledDex = 0;	// index into enabled
1123	unsigned supportedDex = 0;	// index into supported
1124	unsigned inDex = 0;			// index into ciphers
1125
1126	/* first get all the supported ciphers */
1127	ortn = SSLGetNumberSupportedCiphers(ctx, &numSupported);
1128	if(ortn) {
1129		printSslErrStr("SSLGetNumberSupportedCiphers", ortn);
1130		return ortn;
1131	}
1132	supported = (SSLCipherSuite *)malloc(numSupported * sizeof(SSLCipherSuite));
1133	ortn = SSLGetSupportedCiphers(ctx, supported, &numSupported);
1134	if(ortn) {
1135		printSslErrStr("SSLGetSupportedCiphers", ortn);
1136		return ortn;
1137	}
1138
1139	/*
1140	 * Malloc an array we'll use for SSLGetEnabledCiphers - this will  be
1141	 * bigger than the number of suites we actually specify
1142	 */
1143	enabled = (SSLCipherSuite *)malloc(numSupported * sizeof(SSLCipherSuite));
1144
1145	/*
1146	 * For each valid suite in ciphers, see if it's in the list of
1147	 * supported ciphers. If it is, add it to the list of ciphers to be
1148	 * enabled.
1149	 */
1150	for(inDex=0; ciphers[inDex] != SSL_NO_SUCH_CIPHERSUITE; inDex++) {
1151		for(supportedDex=0; supportedDex<numSupported; supportedDex++) {
1152			if(ciphers[inDex] == supported[supportedDex]) {
1153				enabled[enabledDex++] = ciphers[inDex];
1154				break;
1155			}
1156		}
1157	}
1158
1159	/* send it on down. */
1160	ortn = SSLSetEnabledCiphers(ctx, enabled, enabledDex);
1161	if(ortn) {
1162		printSslErrStr("SSLSetEnabledCiphers", ortn);
1163	}
1164	free(enabled);
1165	free(supported);
1166	return ortn;
1167}
1168
1169/*
1170 * Specify a restricted set of cipherspecs.
1171 */
1172OSStatus sslSetCipherRestrictions(
1173	SSLContextRef ctx,
1174	char cipherRestrict)
1175{
1176	OSStatus ortn;
1177
1178	if(cipherRestrict == '\0') {
1179		return noErr;		// actually should not have been called
1180	}
1181	switch(cipherRestrict) {
1182		case 'e':
1183			ortn = sslSetEnabledCiphers(ctx, suites40);
1184			break;
1185		case 'd':
1186			ortn = sslSetEnabledCiphers(ctx, suitesDES);
1187			break;
1188		case 'D':
1189			ortn = sslSetEnabledCiphers(ctx, suitesDES40);
1190			break;
1191		case '3':
1192			ortn = sslSetEnabledCiphers(ctx, suites3DES);
1193			break;
1194		case '4':
1195			ortn = sslSetEnabledCiphers(ctx, suitesRC4);
1196			break;
1197		case '$':
1198			ortn = sslSetEnabledCiphers(ctx, suitesRC4_40);
1199			break;
1200		case '2':
1201			ortn = sslSetEnabledCiphers(ctx, suitesRC2);
1202			break;
1203		case 'a':
1204			ortn = sslSetEnabledCiphers(ctx, suitesAES128);
1205			break;
1206		case 'A':
1207			ortn = sslSetEnabledCiphers(ctx, suitesAES256);
1208			break;
1209		case 'h':
1210			ortn = sslSetEnabledCiphers(ctx, suitesDH);
1211			break;
1212		case 'H':
1213			ortn = sslSetEnabledCiphers(ctx, suitesDHAnon);
1214			break;
1215		case 'r':
1216			ortn = sslSetEnabledCiphers(ctx, suitesDH_RSA);
1217			break;
1218		case 's':
1219			ortn = sslSetEnabledCiphers(ctx, suitesDH_DSS);
1220			break;
1221		case 'n':
1222			ortn = sslSetEnabledCiphers(ctx, suites_NULL);
1223			break;
1224		case 'E':
1225			ortn = sslSetEnabledCiphers(ctx, suites_ECDHE);
1226			break;
1227		case 'F':
1228			ortn = sslSetEnabledCiphers(ctx, suites_ECDH);
1229			break;
1230		default:
1231			printf("***bad cipherSpec***\n");
1232			exit(1);
1233	}
1234	return ortn;
1235}
1236
1237int sslVerifyClientCertState(
1238	const char					*whichSide,		// "client" or "server"
1239	SSLClientCertificateState	expectState,
1240	SSLClientCertificateState	gotState)
1241{
1242	if(expectState == SSL_CLIENT_CERT_IGNORE) {
1243		/* app says "don't bother checking" */
1244		return 0;
1245	}
1246	if(expectState == gotState) {
1247		return 0;
1248	}
1249	printf("***%s: Expected clientCertState %s; got %s\n", whichSide,
1250		sslGetClientCertStateString(expectState),
1251		sslGetClientCertStateString(gotState));
1252	return 1;
1253}
1254
1255int sslVerifyRtn(
1256	const char	*whichSide,		// "client" or "server"
1257	OSStatus	expectRtn,
1258	OSStatus	gotRtn)
1259{
1260	if(expectRtn == gotRtn) {
1261		return 0;
1262	}
1263	printf("***%s: Expected return %s; got %s\n", whichSide,
1264		sslGetSSLErrString(expectRtn),
1265		sslGetSSLErrString(gotRtn));
1266	return 1;
1267}
1268
1269int sslVerifyProtVers(
1270	const char	*whichSide,		// "client" or "server"
1271	SSLProtocol	expectProt,
1272	SSLProtocol	gotProt)
1273{
1274	if(expectProt == SSL_PROTOCOL_IGNORE) {
1275		/* app says "don't bopther checking" */
1276		return 0;
1277	}
1278	if(expectProt == gotProt) {
1279		return 0;
1280	}
1281	printf("***%s: Expected return %s; got %s\n", whichSide,
1282		sslGetProtocolVersionString(expectProt),
1283		sslGetProtocolVersionString(gotProt));
1284	return 1;
1285}
1286
1287int sslVerifyCipher(
1288	const char		*whichSide,		// "client" or "server"
1289	SSLCipherSuite	expectCipher,
1290	SSLCipherSuite	gotCipher)
1291{
1292	if(expectCipher == SSL_CIPHER_IGNORE) {
1293		/* app says "don't bopther checking" */
1294		return 0;
1295	}
1296	if(expectCipher == gotCipher) {
1297		return 0;
1298	}
1299	printf("***%s: Expected return %s; got %s\n", whichSide,
1300		sslGetCipherSuiteString(expectCipher),
1301		sslGetCipherSuiteString(gotCipher));
1302	return 1;
1303}
1304
1305
1306OSStatus sslSetProtocols(
1307	SSLContextRef 	ctx,
1308	const char		*acceptedProts,
1309	SSLProtocol		tryVersion)			// only used if acceptedProts NULL
1310{
1311	OSStatus ortn;
1312
1313	if(acceptedProts) {
1314		ortn = SSLSetProtocolVersionEnabled(ctx, kSSLProtocolAll, false);
1315		if(ortn) {
1316			printSslErrStr("SSLSetProtocolVersionEnabled(all off)", ortn);
1317			return ortn;
1318		}
1319		for(const char *cp = acceptedProts; *cp; cp++) {
1320			SSLProtocol prot;
1321			switch(*cp) {
1322				case '2':
1323					prot = kSSLProtocol2;
1324					break;
1325				case '3':
1326					prot = kSSLProtocol3;
1327					break;
1328				case 't':
1329					prot = kTLSProtocol1;
1330					break;
1331				default:
1332					printf("***BRRZAP! Bad acceptedProts string %s. Aborting.\n", acceptedProts);
1333					exit(1);
1334			}
1335			ortn = SSLSetProtocolVersionEnabled(ctx, prot, true);
1336			if(ortn) {
1337				printSslErrStr("SSLSetProtocolVersionEnabled", ortn);
1338				return ortn;
1339			}
1340		}
1341	}
1342	else {
1343		ortn = SSLSetProtocolVersion(ctx, tryVersion);
1344		if(ortn) {
1345			printSslErrStr("SSLSetProtocolVersion", ortn);
1346			return ortn;
1347		}
1348	}
1349	return noErr;
1350}
1351
1352void sslShowResult(
1353	const char			*whichSide,		// "client" or "server"
1354	SslAppTestParams	*params)
1355{
1356	printf("%s status:\n", whichSide);
1357	if(params->acceptedProts) {
1358		printf("   Allowed SSL versions   : %s\n", params->acceptedProts);
1359	}
1360	else {
1361		printf("   Attempted  SSL version : %s\n",
1362			sslGetProtocolVersionString(params->tryVersion));
1363	}
1364	printf("   Result                 : %s\n", sslGetSSLErrString(params->ortn));
1365	printf("   Negotiated SSL version : %s\n",
1366		sslGetProtocolVersionString(params->negVersion));
1367	printf("   Negotiated CipherSuite : %s\n",
1368		sslGetCipherSuiteString(params->negCipher));
1369	if(params->certState != kSSLClientCertNone) {
1370		printf("   Client Cert State      : %s\n",
1371			sslGetClientCertStateString(params->certState));
1372	}
1373}
1374
1375/* print a '.' every few seconds to keep UI alive while connecting */
1376static CFAbsoluteTime lastTime = (CFAbsoluteTime)0.0;
1377#define TIME_INTERVAL		3.0
1378
1379void sslOutputDot()
1380{
1381	CFAbsoluteTime thisTime = CFAbsoluteTimeGetCurrent();
1382
1383	if(lastTime == 0.0) {
1384		/* avoid printing first time thru */
1385		lastTime = thisTime;
1386		return;
1387	}
1388	if((thisTime - lastTime) >= TIME_INTERVAL) {
1389		printf("."); fflush(stdout);
1390		lastTime = thisTime;
1391	}
1392}
1393
1394/* main server pthread body */
1395static void *sslServerThread(void *arg)
1396{
1397	SslAppTestParams *testParams = (SslAppTestParams *)arg;
1398	OSStatus status;
1399
1400	status = sslAppServe(testParams);
1401	pthread_exit((void*)status);
1402	/* NOT REACHED */
1403	return (void *)status;
1404}
1405
1406/*
1407 * Run one session, with the server in a separate thread.
1408 * On entry, serverParams->port is the port we attempt to run on;
1409 * the server thread may overwrite that with a different port if it's
1410 * unable to open the port we specify. Whatever is left in
1411 * serverParams->port is what's used for the client side.
1412 */
1413#define CLIENT_WAIT_SECONDS		1
1414int sslRunSession(
1415	SslAppTestParams*serverParams,
1416	SslAppTestParams *clientParams,
1417	const char 		*testDesc)
1418{
1419	pthread_t serverPthread;
1420	OSStatus clientRtn;
1421	void *serverRtn;
1422
1423	if(testDesc && !clientParams->quiet) {
1424		printf("===== %s =====\n", testDesc);
1425	}
1426
1427	/*
1428	 * Workaround for Radar 4619502: resolve references to Security.framework
1429	 * here, in main thread, before we fork off the server thread.
1430	 */
1431	SecKeychainRef defaultKc = NULL;
1432	SecKeychainCopyDefault(&defaultKc);
1433	/* end workaround */
1434
1435	if(pthread_mutex_init(&serverParams->pthreadMutex, NULL)) {
1436		printf("***Error initializing mutex; aborting.\n");
1437		return -1;
1438	}
1439	if(pthread_cond_init(&serverParams->pthreadCond, NULL)) {
1440		printf("***Error initializing pthreadCond; aborting.\n");
1441		return -1;
1442	}
1443	serverParams->serverReady = false;		// server sets true
1444
1445	int result = pthread_create(&serverPthread, NULL,
1446			sslServerThread, serverParams);
1447	if(result) {
1448		printf("***Error starting up server thread; aborting.\n");
1449		return result;
1450	}
1451
1452	/* wait for server to set up a socket we can connect to */
1453	if(pthread_mutex_lock(&serverParams->pthreadMutex)) {
1454		printf("***Error acquiring server lock; aborting.\n");
1455		return -1;
1456	}
1457	while(!serverParams->serverReady) {
1458		if(pthread_cond_wait(&serverParams->pthreadCond, &serverParams->pthreadMutex)) {
1459			printf("***Error waiting server thread; aborting.\n");
1460			return -1;
1461		}
1462	}
1463	pthread_mutex_unlock(&serverParams->pthreadMutex);
1464	pthread_cond_destroy(&serverParams->pthreadCond);
1465	pthread_mutex_destroy(&serverParams->pthreadMutex);
1466
1467	clientParams->port = serverParams->port;
1468	clientRtn = sslAppClient(clientParams);
1469	/* server doesn't shut down its socket until it sees this */
1470	serverParams->clientDone = 1;
1471	result = pthread_join(serverPthread, &serverRtn);
1472	if(result) {
1473		printf("***pthread_join returned %d, aborting\n", result);
1474		return result;
1475	}
1476
1477	if(serverParams->verbose) {
1478		sslShowResult("server", serverParams);
1479	}
1480	if(clientParams->verbose) {
1481		sslShowResult("client", clientParams);
1482	}
1483
1484	/* verify results */
1485	int ourRtn = 0;
1486	ourRtn += sslVerifyRtn("server", serverParams->expectRtn, serverParams->ortn);
1487	ourRtn += sslVerifyRtn("client", clientParams->expectRtn, clientParams->ortn);
1488	ourRtn += sslVerifyProtVers("server", serverParams->expectVersion,
1489		serverParams->negVersion);
1490	ourRtn += sslVerifyProtVers("client", clientParams->expectVersion,
1491		clientParams->negVersion);
1492	ourRtn += sslVerifyClientCertState("server", serverParams->expectCertState,
1493		serverParams->certState);
1494	ourRtn += sslVerifyClientCertState("client", clientParams->expectCertState,
1495		clientParams->certState);
1496	if(serverParams->ortn == noErr) {
1497		ourRtn += sslVerifyCipher("server", serverParams->expectCipher,
1498			serverParams->negCipher);
1499	}
1500	if(clientParams->ortn == noErr) {
1501		ourRtn += sslVerifyCipher("client", clientParams->expectCipher,
1502			clientParams->negCipher);
1503	}
1504
1505	if(defaultKc) {
1506		/* for workaround for Radar 4619502 */
1507		CFRelease(defaultKc);
1508	}
1509	return ourRtn;
1510}
1511
1512/*
1513 * Add all of the roots in a given KC to SSL ctx's trusted anchors.
1514 */
1515OSStatus sslAddTrustedRoots(
1516	SSLContextRef 	ctx,
1517	SecKeychainRef	keychain,
1518	bool			*foundOne)		// RETURNED, true if we found
1519									//    at least one root cert
1520{
1521	OSStatus 				ortn;
1522	SecCertificateRef 		secCert;
1523	SecKeychainSearchRef 	srch;
1524
1525	*foundOne = false;
1526	ortn = SecKeychainSearchCreateFromAttributes(keychain,
1527		kSecCertificateItemClass,
1528		NULL,			// any attrs
1529		&srch);
1530	if(ortn) {
1531		printSslErrStr("SecKeychainSearchCreateFromAttributes", ortn);
1532		return ortn;
1533	}
1534
1535	/*
1536	 * Only use root certs. Not an error if we don't find any.
1537	 */
1538	do {
1539		ortn = SecKeychainSearchCopyNext(srch,
1540			(SecKeychainItemRef *)&secCert);
1541		if(ortn) {
1542			break;
1543		}
1544
1545		/* see if it's a root */
1546		if(!isCertRefRoot(secCert)) {
1547			continue;
1548		}
1549
1550		/* Tell Secure Transport to trust this one. */
1551		ortn = addTrustedSecCert(ctx, secCert, false);
1552		if(ortn) {
1553			/* fatal */
1554			printSslErrStr("addTrustedSecCert", ortn);
1555			return ortn;
1556		}
1557		CFRelease(secCert);
1558		*foundOne = true;
1559	} while(ortn == noErr);
1560	CFRelease(srch);
1561	return noErr;
1562}
1563
1564/*
1565 * Wrapper for sslIdentPicker, with optional trusted anchor specified as a filename.
1566 */
1567OSStatus sslIdentityPicker(
1568	SecKeychainRef		kcRef,			// NULL means use default list
1569	const char			*trustedAnchor,	// optional additional trusted anchor
1570	bool				includeRoot,	// true --> root is appended to outArray
1571										// false --> root not included
1572	const CSSM_OID		*vfyPolicy,		// optional - if NULL, use SSL
1573	CFArrayRef			*outArray)		// created and RETURNED
1574{
1575	SecCertificateRef trustedCert = NULL;
1576	OSStatus ortn;
1577
1578	if(trustedAnchor) {
1579		ortn = sslReadAnchor(trustedAnchor, &trustedCert);
1580		if(ortn) {
1581			printf("***Error reading %s. sslIdentityPicker proceeding with no anchor.\n",
1582				trustedAnchor);
1583			trustedCert = NULL;
1584		}
1585	}
1586	ortn = sslIdentPicker(kcRef, trustedCert, includeRoot, vfyPolicy, outArray);
1587	if(trustedCert) {
1588		CFRelease(trustedCert);
1589	}
1590	return ortn;
1591}
1592
1593/*
1594 * Given a keychain name, convert it into a full path using the "SSL regression
1595 * test suite algorithm". The Sec layer by default locates root root's keychains
1596 * in different places depending on whether we're actually logged in as root
1597 * or running via e.g. cron, so we force the location of root keychains to
1598 * a hard-coded path. User keychain names we leave alone.
1599 * This has to be kept in sync with the sslKcSetup script fragment in
1600 * sslScripts.
1601 */
1602void sslKeychainPath(
1603	const char *kcName,
1604	char *kcPath)			// allocd by caller, MAXPATHLEN
1605{
1606	if(kcName[0] == '\0') {
1607		kcPath[0] = '\0';
1608	}
1609	else if(geteuid() == 0) {
1610		/* root */
1611		const char *buildDir = getenv("LOCAL_BUILD_DIR");
1612		if(buildDir == NULL) {
1613			buildDir = "";
1614		}
1615		sprintf(kcPath, "%s/Library/Keychains/%s", buildDir, kcName);
1616	}
1617	else {
1618		/* user, leave alone */
1619		strcpy(kcPath, kcName);
1620	}
1621}
1622
1623/* Verify presence of required file. Returns nonzero if not found. */
1624int sslCheckFile(const char *path)
1625{
1626	struct stat sb;
1627
1628	if(stat(path, &sb)) {
1629		printf("***Can't find file %s.\n", path);
1630		printf("   Try running in the build directory, perhaps after running the\n"
1631			   "   makeLocalCert script.\n");
1632		return 1;
1633	}
1634	return 0;
1635}
1636
1637/* Stringify a SSL_ECDSA_NamedCurve */
1638extern const char *sslCurveString(
1639	SSL_ECDSA_NamedCurve namedCurve)
1640{
1641	static char unk[100];
1642
1643	switch(namedCurve) {
1644		case SSL_Curve_None:	  return "Curve_None";
1645		case SSL_Curve_secp256r1: return "secp256r1";
1646		case SSL_Curve_secp384r1: return "secp384r1";
1647		case SSL_Curve_secp521r1: return "secp521r1";
1648		default:
1649			sprintf(unk, "Unknown <%d>", (int)namedCurve);
1650			return unk;
1651	}
1652}
1653
1654