2 * Copyright (c) 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
24 Copyright (c) 2000-2009, Apple Inc. All rights reserved.
25 Responsibility: Jeremy Wyld
27 // Original Author: Becky Willrich
28 #include <CoreFoundation/CFStream.h>
29 #include <CoreFoundation/CFNumber.h>
30 #include "CFInternal.h"
31 #include "CFStreamInternal.h"
32 #include "CFStreamPriv.h"
34 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
35 // On Mach these live in CF for historical reasons, even though they are declared in CFNetwork
37 const int kCFStreamErrorDomainSSL
= 3;
38 const int kCFStreamErrorDomainSOCKS
= 5;
40 CONST_STRING_DECL(kCFStreamPropertyShouldCloseNativeSocket
, "kCFStreamPropertyShouldCloseNativeSocket")
41 CONST_STRING_DECL(kCFStreamPropertyAutoErrorOnSystemChange
, "kCFStreamPropertyAutoErrorOnSystemChange");
43 CONST_STRING_DECL(kCFStreamPropertySOCKSProxy
, "kCFStreamPropertySOCKSProxy")
44 CONST_STRING_DECL(kCFStreamPropertySOCKSProxyHost
, "SOCKSProxy")
45 CONST_STRING_DECL(kCFStreamPropertySOCKSProxyPort
, "SOCKSPort")
46 CONST_STRING_DECL(kCFStreamPropertySOCKSVersion
, "kCFStreamPropertySOCKSVersion")
47 CONST_STRING_DECL(kCFStreamSocketSOCKSVersion4
, "kCFStreamSocketSOCKSVersion4")
48 CONST_STRING_DECL(kCFStreamSocketSOCKSVersion5
, "kCFStreamSocketSOCKSVersion5")
49 CONST_STRING_DECL(kCFStreamPropertySOCKSUser
, "kCFStreamPropertySOCKSUser")
50 CONST_STRING_DECL(kCFStreamPropertySOCKSPassword
, "kCFStreamPropertySOCKSPassword")
52 CONST_STRING_DECL(kCFStreamPropertySocketSecurityLevel
, "kCFStreamPropertySocketSecurityLevel");
53 CONST_STRING_DECL(kCFStreamSocketSecurityLevelNone
, "kCFStreamSocketSecurityLevelNone");
54 CONST_STRING_DECL(kCFStreamSocketSecurityLevelSSLv2
, "kCFStreamSocketSecurityLevelSSLv2");
55 CONST_STRING_DECL(kCFStreamSocketSecurityLevelSSLv3
, "kCFStreamSocketSecurityLevelSSLv3");
56 CONST_STRING_DECL(kCFStreamSocketSecurityLevelTLSv1
, "kCFStreamSocketSecurityLevelTLSv1");
57 CONST_STRING_DECL(kCFStreamSocketSecurityLevelNegotiatedSSL
, "kCFStreamSocketSecurityLevelNegotiatedSSL");
62 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
63 #elif DEPLOYMENT_TARGET_WINDOWS
64 typedef void (*CF_SOCKET_STREAM_PAIR
)(CFAllocatorRef
, CFStringRef
, UInt32
, CFSocketNativeHandle
, const CFSocketSignature
*, CFReadStreamRef
*, CFWriteStreamRef
*);
66 #error Unknown or unspecified DEPLOYMENT_TARGET
69 // These are duplicated in CFNetwork, who actually externs them in its headers
70 CONST_STRING_DECL(kCFStreamPropertySocketSSLContext
, "kCFStreamPropertySocketSSLContext")
71 CONST_STRING_DECL(_kCFStreamPropertySocketSecurityAuthenticatesServerCertificate
, "_kCFStreamPropertySocketSecurityAuthenticatesServerCertificate");
75 void _CFSocketStreamSetAuthenticatesServerCertificateDefault(Boolean shouldAuthenticate
) {
76 CFLog(__kCFLogAssertion
, CFSTR("_CFSocketStreamSetAuthenticatesServerCertificateDefault(): This call has been deprecated. Use SetProperty(_kCFStreamPropertySocketSecurityAuthenticatesServerCertificate, kCFBooleanTrue/False)\n"));
80 /* CF_EXPORT */ Boolean
81 _CFSocketStreamGetAuthenticatesServerCertificateDefault(void) {
82 CFLog(__kCFLogAssertion
, CFSTR("_CFSocketStreamGetAuthenticatesServerCertificateDefault(): This call has been removed as a security risk. Use security properties on individual streams instead.\n"));
88 _CFSocketStreamPairSetAuthenticatesServerCertificate(CFReadStreamRef rStream
, CFWriteStreamRef wStream
, Boolean authenticates
) {
90 CFBooleanRef value
= (!authenticates
? kCFBooleanFalse
: kCFBooleanTrue
);
93 CFReadStreamSetProperty(rStream
, _kCFStreamPropertySocketSecurityAuthenticatesServerCertificate
, value
);
95 CFWriteStreamSetProperty(wStream
, _kCFStreamPropertySocketSecurityAuthenticatesServerCertificate
, value
);
99 // Flags for dyld loading of libraries.
108 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
109 #elif DEPLOYMENT_TARGET_WINDOWS
112 #error Unknown or unspecified DEPLOYMENT_TARGET
114 void (*_CFSocketStreamCreatePair
)(CFAllocatorRef
, CFStringRef
, UInt32
, CFSocketNativeHandle
, const CFSocketSignature
*, CFReadStreamRef
*, CFWriteStreamRef
*);
115 CFErrorRef (*_CFErrorCreateWithStreamError
)(CFAllocatorRef
, CFStreamError
*);
116 CFStreamError (*_CFStreamErrorFromCFError
)(CFErrorRef
);
117 } CFNetworkSupport
= {
120 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
121 #elif DEPLOYMENT_TARGET_WINDOWS
124 #error Unknown or unspecified DEPLOYMENT_TARGET
131 #define CFNETWORK_CALL(sym, args) ((CFNetworkSupport.sym)args)
133 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
134 #define CFNETWORK_LOAD_SYM(sym) __CFLookupCFNetworkFunction(#sym)
135 #elif DEPLOYMENT_TARGET_WINDOWS
136 #define CFNETWORK_LOAD_SYM(sym) (void *)GetProcAddress(CFNetworkSupport.image, #sym)
138 #error Unknown or unspecified DEPLOYMENT_TARGET
141 static void initializeCFNetworkSupport(void) {
142 __CFBitSet(CFNetworkSupport
.flags
, kTriedToLoad
);
144 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
145 CFNetworkSupport
._CFSocketStreamCreatePair
= CFNETWORK_LOAD_SYM(_CFSocketStreamCreatePair
);
146 CFNetworkSupport
._CFErrorCreateWithStreamError
= CFNETWORK_LOAD_SYM(_CFErrorCreateWithStreamError
);
147 CFNetworkSupport
._CFStreamErrorFromCFError
= CFNETWORK_LOAD_SYM(_CFStreamErrorFromCFError
);
148 #elif DEPLOYMENT_TARGET_WINDOWS
149 if (!CFNetworkSupport
.image
) {
151 CFNetworkSupport
.image
= GetModuleHandleW(L
"CFNetwork_debug.dll");
153 CFNetworkSupport
.image
= GetModuleHandleW(L
"CFNetwork.dll");
157 if (!CFNetworkSupport
.image
) {
158 // not loaded yet, try to load from the filesystem
159 char path
[MAX_PATH
+1];
160 if (!CFNetworkSupport
.image
) {
161 strlcpy(path
, (const char *)_CFDLLPath(), sizeof(path
));
163 strlcat(path
, "\\CFNetwork_debug.dll", sizeof(path
));
165 strlcat(path
, "\\CFNetwork.dll", sizeof(path
));
167 CFNetworkSupport
.image
= LoadLibraryA(path
);
171 if (!CFNetworkSupport
.image
) {
172 CFLog(__kCFLogAssertion
, CFSTR("CoreFoundation: failed to dynamically load CFNetwork"));
174 CFNetworkSupport
._CFSocketStreamCreatePair
= (CF_SOCKET_STREAM_PAIR
)CFNETWORK_LOAD_SYM(_CFSocketStreamCreatePair
);
175 CFNetworkSupport
._CFErrorCreateWithStreamError
= (CFErrorRef(*)(CFAllocatorRef
, CFStreamError
*))CFNETWORK_LOAD_SYM(_CFErrorCreateWithStreamError
);
176 CFNetworkSupport
._CFStreamErrorFromCFError
= (CFStreamError(*)(CFErrorRef
))CFNETWORK_LOAD_SYM(_CFStreamErrorFromCFError
);
179 #error Unknown or unspecified DEPLOYMENT_TARGET
182 if (!CFNetworkSupport
._CFSocketStreamCreatePair
) CFLog(__kCFLogAssertion
, CFSTR("CoreFoundation: failed to dynamically link symbol _CFSocketStreamCreatePair"));
183 if (!CFNetworkSupport
._CFErrorCreateWithStreamError
) CFLog(__kCFLogAssertion
, CFSTR("CoreFoundation: failed to dynamically link symbol _CFErrorCreateWithStreamError"));
184 if (!CFNetworkSupport
._CFStreamErrorFromCFError
) CFLog(__kCFLogAssertion
, CFSTR("CoreFoundation: failed to dynamically link symbol _CFStreamErrorFromCFError"));
186 __CFBitSet(CFNetworkSupport
.flags
, kInitialized
);
190 createPair(CFAllocatorRef alloc
, CFStringRef host
, UInt32 port
, CFSocketNativeHandle sock
, const CFSocketSignature
* sig
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
)
198 __CFSpinLock(&(CFNetworkSupport
.lock
));
199 if (!__CFBitIsSet(CFNetworkSupport
.flags
, kTriedToLoad
)) initializeCFNetworkSupport();
200 __CFSpinUnlock(&(CFNetworkSupport
.lock
));
202 CFNETWORK_CALL(_CFSocketStreamCreatePair
, (alloc
, host
, port
, sock
, sig
, readStream
, writeStream
));
206 CF_EXPORT
void CFStreamCreatePairWithSocket(CFAllocatorRef alloc
, CFSocketNativeHandle sock
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
) {
207 createPair(alloc
, NULL
, 0, sock
, NULL
, readStream
, writeStream
);
210 CF_EXPORT
void CFStreamCreatePairWithSocketToHost(CFAllocatorRef alloc
, CFStringRef host
, UInt32 port
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
) {
211 createPair(alloc
, host
, port
, 0, NULL
, readStream
, writeStream
);
214 CF_EXPORT
void CFStreamCreatePairWithPeerSocketSignature(CFAllocatorRef alloc
, const CFSocketSignature
* sig
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
) {
215 createPair(alloc
, NULL
, 0, 0, sig
, readStream
, writeStream
);
218 __private_extern__ CFStreamError
_CFStreamErrorFromError(CFErrorRef error
) {
219 CFStreamError result
;
222 __CFSpinLock(&(CFNetworkSupport
.lock
));
223 if (!__CFBitIsSet(CFNetworkSupport
.flags
, kTriedToLoad
)) initializeCFNetworkSupport();
224 canUpCall
= (CFNetworkSupport
._CFStreamErrorFromCFError
!= NULL
);
225 __CFSpinUnlock(&(CFNetworkSupport
.lock
));
228 result
= CFNETWORK_CALL(_CFStreamErrorFromCFError
, (error
));
230 CFStringRef domain
= CFErrorGetDomain(error
);
231 if (CFEqual(domain
, kCFErrorDomainPOSIX
)) {
232 result
.domain
= kCFStreamErrorDomainPOSIX
;
233 } else if (CFEqual(domain
, kCFErrorDomainOSStatus
)) {
234 result
.domain
= kCFStreamErrorDomainMacOSStatus
;
235 } else if (CFEqual(domain
, kCFErrorDomainMach
)) {
236 result
.domain
= 11; // kCFStreamErrorDomainMach, but that symbol is in CFNetwork
238 result
.domain
= kCFStreamErrorDomainCustom
;
240 result
.error
= CFErrorGetCode(error
);
245 __private_extern__ CFErrorRef
_CFErrorFromStreamError(CFAllocatorRef alloc
, CFStreamError
*streamError
) {
249 __CFSpinLock(&(CFNetworkSupport
.lock
));
250 if (!__CFBitIsSet(CFNetworkSupport
.flags
, kTriedToLoad
)) initializeCFNetworkSupport();
251 canUpCall
= (CFNetworkSupport
._CFErrorCreateWithStreamError
!= NULL
);
252 __CFSpinUnlock(&(CFNetworkSupport
.lock
));
255 result
= CFNETWORK_CALL(_CFErrorCreateWithStreamError
, (alloc
, streamError
));
257 if (streamError
->domain
== kCFStreamErrorDomainPOSIX
) {
258 return CFErrorCreate(alloc
, kCFErrorDomainPOSIX
, streamError
->error
, NULL
);
259 } else if (streamError
->domain
== kCFStreamErrorDomainMacOSStatus
) {
260 return CFErrorCreate(alloc
, kCFErrorDomainOSStatus
, streamError
->error
, NULL
);
262 CFStringRef key
= CFSTR("CFStreamErrorDomainKey");
263 CFNumberRef value
= CFNumberCreate(alloc
, kCFNumberCFIndexType
, &streamError
->domain
);
264 CFDictionaryRef dict
= CFDictionaryCreate(alloc
, (const void **)(&key
), (const void **)(&value
), 1, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
265 result
= CFErrorCreate(alloc
, CFSTR("BogusCFStreamErrorCompatibilityDomain"), streamError
->error
, dict
);