]> git.saurik.com Git - apple/security.git/blob - SecureTransport/sslctx.c
Security-54.1.tar.gz
[apple/security.git] / SecureTransport / sslctx.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 File: sslctx.c
21
22 Contains: SSLContext accessors
23
24 Written by: Doug Mitchell, based on Netscape SSLRef 3.0
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28 */
29 /* *********************************************************************
30 File: sslctx.c
31
32 SSLRef 3.0 Final -- 11/19/96
33
34 Copyright (c)1996 by Netscape Communications Corp.
35
36 By retrieving this software you are bound by the licensing terms
37 disclosed in the file "LICENSE.txt". Please read it, and if you don't
38 accept the terms, delete this software.
39
40 SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
41 View, California <http://home.netscape.com/> and Consensus Development
42 Corporation of Berkeley, California <http://www.consensus.com/>.
43
44 *********************************************************************
45
46 File: sslctx.c SSLContext accessors
47
48 Functions called by the end user which configure an SSLContext
49 structure or access data stored there.
50
51 ****************************************************************** */
52
53
54 #include "ssl.h"
55 #include "sslctx.h"
56 #include "sslalloc.h"
57 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
58 #include "digests.h"
59 #include "sslDebug.h"
60 #include "appleCdsa.h"
61 #include "appleGlue.h"
62 #include "sslKeychain.h"
63 #include "sslutil.h"
64 #include "cipherSpecs.h"
65 #include "appleSession.h"
66 #include <string.h>
67 #include <Security/SecCertificate.h>
68
69 static void sslFreeDnList(
70 SSLContext *ctx)
71 {
72 DNListElem *dn, *nextDN;
73 SSLBuffer buf;
74
75 dn = ctx->acceptableDNList;
76
77 while (dn)
78 {
79 SSLFreeBuffer(&dn->derDN, &ctx->sysCtx);
80 nextDN = dn->next;
81 buf.data = (uint8*)dn;
82 buf.length = sizeof(DNListElem);
83 SSLFreeBuffer(&buf, &ctx->sysCtx);
84 dn = nextDN;
85 }
86 ctx->acceptableDNList = NULL;
87 }
88
89 static SSLErr sslFreeTrustedRoots(
90 SSLContext *ctx)
91 {
92 int i;
93
94 CASSERT(ctx != NULL);
95 if((ctx->numTrustedCerts == 0) || (ctx->trustedCerts == NULL)) {
96 /* they really should both be zero, right? */
97 CASSERT((ctx->numTrustedCerts == 0) && (ctx->trustedCerts == NULL));
98 }
99 else {
100 for(i=0; i<ctx->numTrustedCerts; i++) {
101 stFreeCssmData(&ctx->trustedCerts[i], CSSM_FALSE);
102 }
103 sslFree(ctx->trustedCerts);
104 }
105 ctx->numTrustedCerts = 0;
106 ctx->trustedCerts = NULL;
107 sslFreeDnList(ctx);
108 return SSLNoErr;
109 }
110
111 /*
112 * Default attempted version.
113 */
114 #define DEFAULT_MAX_VERSION TLS_Version_1_0
115
116 OSStatus
117 SSLNewContext (Boolean isServer,
118 SSLContextRef *contextPtr) /* RETURNED */
119 {
120 SSLContext *ctx;
121 OSStatus oerr;
122 SSLErr serr;
123
124 if(contextPtr == NULL) {
125 return paramErr;
126 }
127 *contextPtr = NULL;
128 ctx = (SSLContext *)sslMalloc(sizeof(SSLContext));
129 if(ctx == NULL) {
130 return memFullErr;
131 }
132 /* subsequent errors to errOut: */
133
134 memset(ctx, 0, sizeof(SSLContext));
135 ctx->state = SSLUninitialized;
136
137 /* different defaults for client and server ... */
138 if(isServer) {
139 ctx->protocolSide = SSL_ServerSide;
140 ctx->reqProtocolVersion = DEFAULT_MAX_VERSION;
141 }
142 else {
143 ctx->protocolSide = SSL_ClientSide;
144 ctx->reqProtocolVersion = SSL_Version_Undetermined;
145 }
146 ctx->negProtocolVersion = SSL_Version_Undetermined;
147 ctx->maxProtocolVersion = DEFAULT_MAX_VERSION;
148 /* Default value so we can send and receive hello msgs */
149 ctx->sslTslCalls = &Ssl3Callouts;
150
151 /* Initialize the cipher state to NULL_WITH_NULL_NULL */
152 ctx->selectedCipherSpec = &SSL_NULL_WITH_NULL_NULL_CipherSpec;
153 ctx->selectedCipher = ctx->selectedCipherSpec->cipherSpec;
154 ctx->writeCipher.macRef = ctx->selectedCipherSpec->macAlgorithm;
155 ctx->readCipher.macRef = ctx->selectedCipherSpec->macAlgorithm;
156 ctx->readCipher.symCipher = ctx->selectedCipherSpec->cipher;
157 ctx->writeCipher.symCipher = ctx->selectedCipherSpec->cipher;
158
159 /* these two are invariant */
160 ctx->writeCipher.encrypting = 1;
161 ctx->writePending.encrypting = 1;
162
163 /* this gets init'd on first call to SSLHandshake() */
164 ctx->validCipherSpecs = NULL;
165 ctx->numValidCipherSpecs = 0;
166
167 ctx->peerDomainName = NULL;
168 ctx->peerDomainNameLen = 0;
169
170 SSLInitMACPads();
171
172 /* attach to CSP, CL, TP */
173 serr = attachToAll(ctx);
174 if(serr) {
175 oerr = sslErrToOsStatus(serr);
176 goto errOut;
177 }
178
179 /* snag root certs from Keychain, tolerate error */
180 addBuiltInCerts(ctx);
181
182 *contextPtr = ctx;
183 return noErr;
184
185 errOut:
186 sslFree(ctx);
187 return oerr;
188 }
189
190
191 /*
192 * Dispose of an SSLContext.
193 */
194 OSStatus
195 SSLDisposeContext (SSLContext *ctx)
196 {
197 WaitingRecord *wait, *next;
198 SSLBuffer buf;
199
200 if(ctx == NULL) {
201 return paramErr;
202 }
203 sslDeleteCertificateChain(ctx->localCert, ctx);
204 sslDeleteCertificateChain(ctx->encryptCert, ctx);
205 sslDeleteCertificateChain(ctx->peerCert, ctx);
206 ctx->localCert = ctx->encryptCert = ctx->peerCert = NULL;
207 SSLFreeBuffer(&ctx->partialReadBuffer, &ctx->sysCtx);
208
209 wait = ctx->recordWriteQueue;
210 while (wait)
211 { SSLFreeBuffer(&wait->data, &ctx->sysCtx);
212 next = wait->next;
213 buf.data = (uint8*)wait;
214 buf.length = sizeof(WaitingRecord);
215 SSLFreeBuffer(&buf, &ctx->sysCtx);
216 wait = next;
217 }
218
219 SSLFreeBuffer(&ctx->dhPeerPublic, &ctx->sysCtx);
220 SSLFreeBuffer(&ctx->dhExchangePublic, &ctx->sysCtx);
221 SSLFreeBuffer(&ctx->dhPrivate, &ctx->sysCtx);
222
223 CloseHash(&SSLHashSHA1, &ctx->shaState, ctx);
224 CloseHash(&SSLHashMD5, &ctx->md5State, ctx);
225
226 SSLFreeBuffer(&ctx->sessionID, &ctx->sysCtx);
227 SSLFreeBuffer(&ctx->peerID, &ctx->sysCtx);
228 SSLFreeBuffer(&ctx->resumableSession, &ctx->sysCtx);
229 SSLFreeBuffer(&ctx->preMasterSecret, &ctx->sysCtx);
230 SSLFreeBuffer(&ctx->partialReadBuffer, &ctx->sysCtx);
231 SSLFreeBuffer(&ctx->fragmentedMessageCache, &ctx->sysCtx);
232 SSLFreeBuffer(&ctx->receivedDataBuffer, &ctx->sysCtx);
233
234 if(ctx->peerDomainName) {
235 sslFree(ctx->peerDomainName);
236 ctx->peerDomainName = NULL;
237 ctx->peerDomainNameLen = 0;
238 }
239 SSLDisposeCipherSuite(&ctx->readCipher, ctx);
240 SSLDisposeCipherSuite(&ctx->writeCipher, ctx);
241 SSLDisposeCipherSuite(&ctx->readPending, ctx);
242 SSLDisposeCipherSuite(&ctx->writePending, ctx);
243
244 sslFree(ctx->validCipherSpecs);
245 ctx->validCipherSpecs = NULL;
246 ctx->numValidCipherSpecs = 0;
247
248 /* free APPLE_CDSA stuff */
249 #if 0
250 /* As of 5/3/02, we don't need to free these keys; they belong
251 * to SecKeychain */
252 #if ST_KEYCHAIN_ENABLE && ST_KC_KEYS_NEED_REF
253 sslFreeKey(ctx->signingKeyCsp, &ctx->signingPrivKey, &ctx->signingKeyRef);
254 sslFreeKey(ctx->encryptKeyCsp, &ctx->encryptPrivKey, &ctx->encryptKeyRef);
255 #else
256 sslFreeKey(ctx->signingKeyCsp, (CSSM_KEY_PTR *)&ctx->signingPrivKey, NULL);
257 sslFreeKey(ctx->encryptKeyCsp, (CSSM_KEY_PTR *)&ctx->encryptPrivKey, NULL);
258 #endif /* ST_KEYCHAIN_ENABLE && ST_KC_KEYS_NEED_REF */
259 #endif /* 0 */
260
261 /*
262 * NOTE: currently, all public keys come from the CL via CSSM_CL_CertGetKeyInfo.
263 * We really don't know what CSP the CL used to generate a public key (in fact,
264 * it uses the raw CSP only to get LogicalKeySizeInBits, but we can't know
265 * that). Thus using e.g. signingKeyCsp (or any other CSP) to free
266 * signingPubKey is not tecnically accurate. However, our public keys
267 * are all raw keys, and all Apple CSPs dispose of raw keys in the same
268 * way.
269 */
270 sslFreeKey(ctx->signingKeyCsp, &ctx->signingPubKey, NULL);
271 sslFreeKey(ctx->encryptKeyCsp, &ctx->encryptPubKey, NULL);
272 sslFreeKey(ctx->peerPubKeyCsp, &ctx->peerPubKey, NULL);
273
274 #if SSL_DEBUG
275 if(ctx->rootCertName != NULL) {
276 sslFree(ctx->rootCertName);
277 }
278 #endif /* SSL_DEBUG */
279
280 sslFreeTrustedRoots(ctx);
281
282 detachFromAll(ctx);
283
284 memset(ctx, 0, sizeof(SSLContext));
285 sslFree(ctx);
286 sslCleanupSession();
287 return noErr;
288 }
289
290 /*
291 * Determine the state of an SSL session.
292 */
293 OSStatus
294 SSLGetSessionState (SSLContextRef context,
295 SSLSessionState *state) /* RETURNED */
296 {
297 SSLSessionState rtnState = kSSLIdle;
298
299 if(context == NULL) {
300 return paramErr;
301 }
302 *state = rtnState;
303 switch(context->state) {
304 case SSLUninitialized:
305 case HandshakeServerUninit:
306 case HandshakeClientUninit:
307 rtnState = kSSLIdle;
308 break;
309 case SSLGracefulClose:
310 rtnState = kSSLClosed;
311 break;
312 case SSLErrorClose:
313 case SSLNoNotifyClose:
314 rtnState = kSSLAborted;
315 break;
316 case HandshakeServerReady:
317 case HandshakeClientReady:
318 rtnState = kSSLConnected;
319 break;
320 default:
321 CASSERT((context->state >= HandshakeServerHello) &&
322 (context->state <= HandshakeSSL2ServerFinished));
323 rtnState = kSSLHandshake;
324 break;
325
326 }
327 *state = rtnState;
328 return noErr;
329 }
330
331 OSStatus
332 SSLSetIOFuncs (SSLContextRef ctx,
333 SSLReadFunc read,
334 SSLWriteFunc write)
335 {
336 if(ctx == NULL) {
337 return paramErr;
338 }
339 if(sslIsSessionActive(ctx)) {
340 /* can't do this with an active session */
341 return badReqErr;
342 }
343 ctx->ioCtx.read = read;
344 ctx->ioCtx.write = write;
345 return noErr;
346 }
347
348 OSStatus
349 SSLSetConnection (SSLContextRef ctx,
350 SSLConnectionRef connection)
351 {
352 if(ctx == NULL) {
353 return paramErr;
354 }
355 if(sslIsSessionActive(ctx)) {
356 /* can't do this with an active session */
357 return badReqErr;
358 }
359 ctx->ioCtx.ioRef = connection;
360 return noErr;
361 }
362
363 OSStatus
364 SSLSetPeerDomainName (SSLContextRef ctx,
365 const char *peerName,
366 size_t peerNameLen)
367 {
368 if(ctx == NULL) {
369 return paramErr;
370 }
371 if(sslIsSessionActive(ctx)) {
372 /* can't do this with an active session */
373 return badReqErr;
374 }
375
376 /* free possible existing name */
377 if(ctx->peerDomainName) {
378 sslFree(ctx->peerDomainName);
379 }
380
381 /* copy in */
382 ctx->peerDomainName = sslMalloc(peerNameLen);
383 if(ctx->peerDomainName == NULL) {
384 return memFullErr;
385 }
386 memmove(ctx->peerDomainName, peerName, peerNameLen);
387 ctx->peerDomainNameLen = peerNameLen;
388 return noErr;
389 }
390
391 /*
392 * Determine the buffer size needed for SSLGetPeerDomainName().
393 */
394 OSStatus
395 SSLGetPeerDomainNameLength (SSLContextRef ctx,
396 size_t *peerNameLen) // RETURNED
397 {
398 if(ctx == NULL) {
399 return paramErr;
400 }
401 *peerNameLen = ctx->peerDomainNameLen;
402 return noErr;
403 }
404
405 OSStatus
406 SSLGetPeerDomainName (SSLContextRef ctx,
407 char *peerName, // returned here
408 size_t *peerNameLen) // IN/OUT
409 {
410 if(ctx == NULL) {
411 return paramErr;
412 }
413 if(*peerNameLen < ctx->peerDomainNameLen) {
414 return errSSLBufferOverflow;
415 }
416 memmove(peerName, ctx->peerDomainName, ctx->peerDomainNameLen);
417 *peerNameLen = ctx->peerDomainNameLen;
418 return noErr;
419 }
420
421 OSStatus
422 SSLSetProtocolVersion (SSLContextRef ctx,
423 SSLProtocol version)
424 {
425 SSLProtocolVersion versInt;
426 SSLProtocolVersion versMax;
427
428 if(ctx == NULL) {
429 return paramErr;
430 }
431 if(sslIsSessionActive(ctx)) {
432 /* can't do this with an active session */
433 return badReqErr;
434 }
435
436 /* convert external representation to private */
437 switch(version) {
438 case kSSLProtocolUnknown:
439 versInt = SSL_Version_Undetermined;
440 versMax = DEFAULT_MAX_VERSION;
441 break;
442 case kSSLProtocol2:
443 versInt = versMax = SSL_Version_2_0;
444 break;
445 case kSSLProtocol3:
446 /* this tells us to do our best but allows 2.0 */
447 versInt = SSL_Version_Undetermined;
448 versMax = SSL_Version_3_0;
449 break;
450 case kSSLProtocol3Only:
451 versInt = SSL_Version_3_0_Only;
452 versMax = SSL_Version_3_0;
453 break;
454 case kTLSProtocol1:
455 /* this tells us to do our best but allows 2.0 */
456 versInt = SSL_Version_Undetermined;
457 versMax = TLS_Version_1_0;
458 break;
459 case kTLSProtocol1Only:
460 versInt = TLS_Version_1_0_Only;
461 versMax = TLS_Version_1_0;
462 break;
463 default:
464 return paramErr;
465 }
466 ctx->reqProtocolVersion = ctx->negProtocolVersion = versInt;
467 ctx->maxProtocolVersion = versMax;
468 return noErr;
469 }
470
471 static SSLProtocol convertProtToExtern(SSLProtocolVersion prot)
472 {
473 switch(prot) {
474 case SSL_Version_Undetermined:
475 return kSSLProtocolUnknown;
476 case SSL_Version_3_0_Only:
477 return kSSLProtocol3Only;
478 case SSL_Version_2_0:
479 return kSSLProtocol2;
480 case SSL_Version_3_0:
481 return kSSLProtocol3;
482 case TLS_Version_1_0_Only:
483 return kTLSProtocol1Only;
484 case TLS_Version_1_0:
485 return kTLSProtocol1;
486 /* this can happen in an intermediate state while negotiation
487 * is in progress...right? */
488 case SSL_Version_3_0_With_2_0_Hello:
489 return kSSLProtocolUnknown;
490 default:
491 sslPanic("convertProtToExtern: bad prot");
492 }
493 /* not reached but make compiler happy */
494 return kSSLProtocolUnknown;
495 }
496
497 OSStatus
498 SSLGetProtocolVersion (SSLContextRef ctx,
499 SSLProtocol *protocol) /* RETURNED */
500 {
501 if(ctx == NULL) {
502 return paramErr;
503 }
504 *protocol = convertProtToExtern(ctx->reqProtocolVersion);
505 return noErr;
506 }
507
508 OSStatus
509 SSLGetNegotiatedProtocolVersion (SSLContextRef ctx,
510 SSLProtocol *protocol) /* RETURNED */
511 {
512 if(ctx == NULL) {
513 return paramErr;
514 }
515 *protocol = convertProtToExtern(ctx->negProtocolVersion);
516 return noErr;
517 }
518
519 OSStatus
520 SSLSetAllowsExpiredCerts(SSLContextRef ctx,
521 Boolean allowExpired)
522 {
523 if(ctx == NULL) {
524 return paramErr;
525 }
526 if(sslIsSessionActive(ctx)) {
527 /* can't do this with an active session */
528 return badReqErr;
529 }
530 ctx->allowExpiredCerts = allowExpired;
531 return noErr;
532 }
533
534 OSStatus
535 SSLGetAllowsExpiredCerts (SSLContextRef ctx,
536 Boolean *allowExpired)
537 {
538 if(ctx == NULL) {
539 return paramErr;
540 }
541 *allowExpired = ctx->allowExpiredCerts;
542 return noErr;
543 }
544
545 OSStatus SSLSetAllowsAnyRoot(
546 SSLContextRef ctx,
547 Boolean anyRoot)
548 {
549 if(ctx == NULL) {
550 return paramErr;
551 }
552 ctx->allowAnyRoot = anyRoot;
553 return noErr;
554 }
555
556 OSStatus
557 SSLGetAllowsAnyRoot(
558 SSLContextRef ctx,
559 Boolean *anyRoot)
560 {
561 if(ctx == NULL) {
562 return paramErr;
563 }
564 *anyRoot = ctx->allowAnyRoot;
565 return noErr;
566 }
567
568 #if ST_SERVER_MODE_ENABLE
569 OSStatus
570 SSLSetClientSideAuthenticate (SSLContext *ctx,
571 SSLAuthenticate auth)
572 {
573 if(ctx == NULL) {
574 return paramErr;
575 }
576 if(sslIsSessionActive(ctx)) {
577 /* can't do this with an active session */
578 return badReqErr;
579 }
580 ctx->clientAuth = auth;
581 switch(auth) {
582 case kNeverAuthenticate:
583 ctx->tryClientAuth = false;
584 break;
585 case kAlwaysAuthenticate:
586 case kTryAuthenticate:
587 /* FIXME - needs work to distinguish these cases at
588 * handshake time */
589 ctx->tryClientAuth = true;
590 break;
591 }
592 return noErr;
593 }
594 #endif /* ST_SERVER_MODE_ENABLE */
595
596 #if (ST_SERVER_MODE_ENABLE || ST_CLIENT_AUTHENTICATION)
597
598 OSStatus
599 SSLSetCertificate (SSLContextRef ctx,
600 CFArrayRef certRefs)
601 {
602 /*
603 * -- free localCerts if we have any
604 * -- Get raw cert data, convert to ctx->localCert
605 * -- get pub, priv keys from certRef[0]
606 * -- validate cert chain
607 */
608 if(ctx == NULL) {
609 return paramErr;
610 }
611 if(sslIsSessionActive(ctx)) {
612 /* can't do this with an active session */
613 return badReqErr;
614 }
615 return parseIncomingCerts(ctx,
616 certRefs,
617 &ctx->localCert,
618 &ctx->signingPubKey,
619 &ctx->signingPrivKey,
620 &ctx->signingKeyCsp
621 #if ST_KC_KEYS_NEED_REF
622 ,
623 &ctx->signingKeyRef
624 #else
625 );
626 #endif
627 }
628 #endif /* (ST_SERVER_MODE_ENABLE || ST_CLIENT_AUTHENTICATION) */
629
630 #if ST_SERVER_MODE_ENABLE
631 OSStatus
632 SSLSetEncryptionCertificate (SSLContextRef ctx,
633 CFArrayRef certRefs)
634 {
635 /*
636 * -- free encryptCert if we have any
637 * -- Get raw cert data, convert to ctx->encryptCert
638 * -- get pub, priv keys from certRef[0]
639 * -- validate cert chain
640 */
641 if(ctx == NULL) {
642 return paramErr;
643 }
644 if(sslIsSessionActive(ctx)) {
645 /* can't do this with an active session */
646 return badReqErr;
647 }
648 return parseIncomingCerts(ctx,
649 certRefs,
650 &ctx->encryptCert,
651 &ctx->encryptPubKey,
652 &ctx->encryptPrivKey,
653 &ctx->encryptKeyCsp
654 #if ST_KC_KEYS_NEED_REF
655 ,
656 &ctx->encryptKeyRef);
657 #else
658 );
659 #endif
660 }
661 #endif /* ST_SERVER_MODE_ENABLE*/
662
663 #if ST_KEYCHAIN_ENABLE && ST_MANAGES_TRUSTED_ROOTS
664
665 /*
666 * Add (optional, additional) trusted root certs.
667 */
668 OSStatus
669 SSLSetTrustedRootCertKC (SSLContextRef ctx,
670 KCRef keyChainRef,
671 Boolean deleteExisting)
672 {
673 /*
674 * -- free trustedCerts if deleteExisting
675 * -- Get raw cert data, add to ctx->trustedCerts
676 * -- verify that each of these is a valid (self-verifying)
677 * root cert
678 * -- add each subject name to acceptableDNList
679 */
680 if((ctx == NULL) || (keyChainRef == nil)) {
681 return paramErr;
682 }
683 if(sslIsSessionActive(ctx)) {
684 /* can't do this with an active session */
685 return badReqErr;
686 }
687 if(deleteExisting) {
688 sslFreeTrustedRoots(ctx);
689 }
690 return parseTrustedKeychain(ctx, keyChainRef);
691 }
692
693 OSStatus
694 SSLSetNewRootKC (SSLContextRef ctx,
695 KCRef keyChainRef,
696 void *accessCreds)
697 {
698 if((ctx == NULL) || (keyChainRef == nil)) {
699 return paramErr;
700 }
701 if(sslIsSessionActive(ctx)) {
702 /* can't do this with an active session */
703 return badReqErr;
704 }
705 if(ctx->newRootCertKc != NULL) {
706 /* can't do this multiple times */
707 return badReqErr;
708 }
709 ctx->newRootCertKc = keyChainRef;
710 ctx->accessCreds = accessCreds;
711 return noErr;
712 }
713 #endif /* ST_KEYCHAIN_ENABLE && ST_MANAGES_TRUSTED_ROOTS */
714
715 OSStatus
716 SSLSetPeerID (SSLContext *ctx,
717 const void *peerID,
718 size_t peerIDLen)
719 {
720 SSLErr serr;
721
722 /* copy peerId to context->peerId */
723 if((ctx == NULL) ||
724 (peerID == NULL) ||
725 (peerIDLen == 0)) {
726 return paramErr;
727 }
728 if(sslIsSessionActive(ctx)) {
729 /* can't do this with an active session */
730 return badReqErr;
731 }
732 SSLFreeBuffer(&ctx->peerID, &ctx->sysCtx);
733 serr = SSLAllocBuffer(&ctx->peerID, peerIDLen, &ctx->sysCtx);
734 if(serr) {
735 return sslErrToOsStatus(serr);
736 }
737 memmove(ctx->peerID.data, peerID, peerIDLen);
738 return noErr;
739 }
740
741 OSStatus
742 SSLGetPeerID (SSLContextRef ctx,
743 const void **peerID,
744 size_t *peerIDLen)
745 {
746 *peerID = ctx->peerID.data; // may be NULL
747 *peerIDLen = ctx->peerID.length;
748 return noErr;
749 }
750
751 OSStatus
752 SSLGetNegotiatedCipher (SSLContextRef ctx,
753 SSLCipherSuite *cipherSuite)
754 {
755 if(ctx == NULL) {
756 return paramErr;
757 }
758 if(!sslIsSessionActive(ctx)) {
759 return badReqErr;
760 }
761 *cipherSuite = (SSLCipherSuite)ctx->selectedCipher;
762 return noErr;
763 }
764
765 /*
766 * Add an acceptable distinguished name.
767 * FIXME - this looks like a big hole in the SSLRef code;
768 * acceptableDNList is set here and in SSLProcessCertificateRequest();
769 * it's used and sent to a client in SSLEncodeCertificateRequest();
770 * but the list is never used to decide what certs to send!
771 *
772 * Also FIXME - this allocation of dnBufs is preposterous. The
773 * SSLBufs can never get freed. Why not just allocate the
774 * raw DNListElems? Sheesh.
775 */
776 #if 0
777 /* not used */
778 static SSLErr
779 SSLAddDistinguishedName(SSLContext *ctx, SSLBuffer derDN)
780 { SSLBuffer dnBuf;
781 DNListElem *dn;
782 SSLErr err;
783
784 if ((err = SSLAllocBuffer(&dnBuf, sizeof(DNListElem), &ctx->sysCtx)) != 0)
785 return err;
786 dn = (DNListElem*)dnBuf.data;
787 if ((err = SSLAllocBuffer(&dn->derDN, derDN.length, &ctx->sysCtx)) != 0)
788 { SSLFreeBuffer(&dnBuf, &ctx->sysCtx);
789 return err;
790 }
791 memcpy(dn->derDN.data, derDN.data, derDN.length);
792 dn->next = ctx->acceptableDNList;
793 ctx->acceptableDNList = dn;
794 return SSLNoErr;
795 }
796 #endif /* not used */
797
798 /*
799 * Request peer certificates. Valid anytime, subsequent to
800 * a handshake attempt.
801 */
802 OSStatus
803 SSLGetPeerCertificates (SSLContextRef ctx,
804 CFArrayRef *certs)
805 {
806 uint32 numCerts;
807 CFMutableArrayRef ca;
808 CFIndex i;
809 SecCertificateRef cfd;
810 OSStatus ortn;
811 CSSM_DATA certData;
812 SSLCertificate *scert;
813
814 if(ctx == NULL) {
815 return paramErr;
816 }
817 *certs = NULL;
818
819 /*
820 * Copy peerCert, a chain of SSLCertificates, to a CFArray of
821 * CFDataRefs, each of which is one DER-encoded cert.
822 */
823 numCerts = SSLGetCertificateChainLength(ctx->peerCert);
824 if(numCerts == 0) {
825 return noErr;
826 }
827 ca = CFArrayCreateMutable(kCFAllocatorDefault,
828 (CFIndex)numCerts, &kCFTypeArrayCallBacks);
829 if(ca == NULL) {
830 return memFullErr;
831 }
832
833 /*
834 * Caller gets leaf cert first, the opposite of the way we store them.
835 */
836 scert = ctx->peerCert;
837 for(i=0; i<numCerts; i++) {
838 CASSERT(scert != NULL); /* else SSLGetCertificateChainLength
839 * broken */
840 SSLBUF_TO_CSSM(&scert->derCert, &certData);
841 ortn = SecCertificateCreateFromData(&certData,
842 CSSM_CERT_X_509v3,
843 CSSM_CERT_ENCODING_DER,
844 &cfd);
845 if(ortn) {
846 CFRelease(ca);
847 return ortn;
848 }
849 /* insert at head of array */
850 CFArrayInsertValueAtIndex(ca, 0, cfd);
851 scert = scert->next;
852 }
853 *certs = ca;
854 return noErr;
855 }
856
857
858