2 * Copyright (c) 2012 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@
25 Copyright (c) 2000-2011, Apple Inc. All rights reserved.
26 Responsibility: Jeremy Wyld
28 // Original Author: Becky Willrich
29 #include <CoreFoundation/CFStream.h>
30 #include <CoreFoundation/CFNumber.h>
31 #include "CFInternal.h"
32 #include "CFStreamInternal.h"
33 #include "CFStreamPriv.h"
35 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
36 // On Mach these live in CF for historical reasons, even though they are declared in CFNetwork
38 const int kCFStreamErrorDomainSSL
= 3;
39 const int kCFStreamErrorDomainSOCKS
= 5;
41 CONST_STRING_DECL(kCFStreamPropertyShouldCloseNativeSocket
, "kCFStreamPropertyShouldCloseNativeSocket")
42 CONST_STRING_DECL(kCFStreamPropertyAutoErrorOnSystemChange
, "kCFStreamPropertyAutoErrorOnSystemChange");
44 CONST_STRING_DECL(kCFStreamPropertySOCKSProxy
, "kCFStreamPropertySOCKSProxy")
45 CONST_STRING_DECL(kCFStreamPropertySOCKSProxyHost
, "SOCKSProxy")
46 CONST_STRING_DECL(kCFStreamPropertySOCKSProxyPort
, "SOCKSPort")
47 CONST_STRING_DECL(kCFStreamPropertySOCKSVersion
, "kCFStreamPropertySOCKSVersion")
48 CONST_STRING_DECL(kCFStreamSocketSOCKSVersion4
, "kCFStreamSocketSOCKSVersion4")
49 CONST_STRING_DECL(kCFStreamSocketSOCKSVersion5
, "kCFStreamSocketSOCKSVersion5")
50 CONST_STRING_DECL(kCFStreamPropertySOCKSUser
, "kCFStreamPropertySOCKSUser")
51 CONST_STRING_DECL(kCFStreamPropertySOCKSPassword
, "kCFStreamPropertySOCKSPassword")
53 CONST_STRING_DECL(kCFStreamPropertySocketSecurityLevel
, "kCFStreamPropertySocketSecurityLevel");
54 CONST_STRING_DECL(kCFStreamSocketSecurityLevelNone
, "kCFStreamSocketSecurityLevelNone");
55 CONST_STRING_DECL(kCFStreamSocketSecurityLevelSSLv2
, "kCFStreamSocketSecurityLevelSSLv2");
56 CONST_STRING_DECL(kCFStreamSocketSecurityLevelSSLv3
, "kCFStreamSocketSecurityLevelSSLv3");
57 CONST_STRING_DECL(kCFStreamSocketSecurityLevelTLSv1
, "kCFStreamSocketSecurityLevelTLSv1");
58 CONST_STRING_DECL(kCFStreamSocketSecurityLevelNegotiatedSSL
, "kCFStreamSocketSecurityLevelNegotiatedSSL");
63 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
64 #elif DEPLOYMENT_TARGET_WINDOWS
65 typedef void (*CF_SOCKET_STREAM_PAIR
)(CFAllocatorRef
, CFStringRef
, UInt32
, CFSocketNativeHandle
, const CFSocketSignature
*, CFReadStreamRef
*, CFWriteStreamRef
*);
67 #error Unknown or unspecified DEPLOYMENT_TARGET
70 // These are duplicated in CFNetwork, who actually externs them in its headers
71 CONST_STRING_DECL(kCFStreamPropertySocketSSLContext
, "kCFStreamPropertySocketSSLContext")
72 CONST_STRING_DECL(_kCFStreamPropertySocketSecurityAuthenticatesServerCertificate
, "_kCFStreamPropertySocketSecurityAuthenticatesServerCertificate");
76 void _CFSocketStreamSetAuthenticatesServerCertificateDefault(Boolean shouldAuthenticate
) {
77 CFLog(__kCFLogAssertion
, CFSTR("_CFSocketStreamSetAuthenticatesServerCertificateDefault(): This call has been deprecated. Use SetProperty(_kCFStreamPropertySocketSecurityAuthenticatesServerCertificate, kCFBooleanTrue/False)\n"));
81 /* CF_EXPORT */ Boolean
82 _CFSocketStreamGetAuthenticatesServerCertificateDefault(void) {
83 CFLog(__kCFLogAssertion
, CFSTR("_CFSocketStreamGetAuthenticatesServerCertificateDefault(): This call has been removed as a security risk. Use security properties on individual streams instead.\n"));
89 _CFSocketStreamPairSetAuthenticatesServerCertificate(CFReadStreamRef rStream
, CFWriteStreamRef wStream
, Boolean authenticates
) {
91 CFBooleanRef value
= (!authenticates
? kCFBooleanFalse
: kCFBooleanTrue
);
94 CFReadStreamSetProperty(rStream
, _kCFStreamPropertySocketSecurityAuthenticatesServerCertificate
, value
);
96 CFWriteStreamSetProperty(wStream
, _kCFStreamPropertySocketSecurityAuthenticatesServerCertificate
, value
);
100 // Flags for dyld loading of libraries.
109 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
110 #elif DEPLOYMENT_TARGET_WINDOWS
113 #error Unknown or unspecified DEPLOYMENT_TARGET
115 void (*_CFSocketStreamCreatePair
)(CFAllocatorRef
, CFStringRef
, UInt32
, CFSocketNativeHandle
, const CFSocketSignature
*, CFReadStreamRef
*, CFWriteStreamRef
*);
116 CFErrorRef (*_CFErrorCreateWithStreamError
)(CFAllocatorRef
, CFStreamError
*);
117 CFStreamError (*_CFStreamErrorFromCFError
)(CFErrorRef
);
118 } CFNetworkSupport
= {
121 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
122 #elif DEPLOYMENT_TARGET_WINDOWS
125 #error Unknown or unspecified DEPLOYMENT_TARGET
132 #define CFNETWORK_CALL(sym, args) ((CFNetworkSupport.sym)args)
134 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
135 #define CFNETWORK_LOAD_SYM(sym) __CFLookupCFNetworkFunction(#sym)
136 #elif DEPLOYMENT_TARGET_WINDOWS
137 #define CFNETWORK_LOAD_SYM(sym) (void *)GetProcAddress(CFNetworkSupport.image, #sym)
139 #error Unknown or unspecified DEPLOYMENT_TARGET
142 static void initializeCFNetworkSupport(void) {
143 __CFBitSet(CFNetworkSupport
.flags
, kTriedToLoad
);
145 #if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
146 CFNetworkSupport
._CFSocketStreamCreatePair
= CFNETWORK_LOAD_SYM(_CFSocketStreamCreatePair
);
147 CFNetworkSupport
._CFErrorCreateWithStreamError
= CFNETWORK_LOAD_SYM(_CFErrorCreateWithStreamError
);
148 CFNetworkSupport
._CFStreamErrorFromCFError
= CFNETWORK_LOAD_SYM(_CFStreamErrorFromCFError
);
149 #elif DEPLOYMENT_TARGET_WINDOWS
150 if (!CFNetworkSupport
.image
) {
152 CFNetworkSupport
.image
= GetModuleHandleW(L
"CFNetwork_debug.dll");
154 CFNetworkSupport
.image
= GetModuleHandleW(L
"CFNetwork.dll");
158 if (!CFNetworkSupport
.image
) {
159 // not loaded yet, try to load from the filesystem
160 char path
[MAX_PATH
+1];
161 if (!CFNetworkSupport
.image
) {
162 strlcpy(path
, (const char *)_CFDLLPath(), sizeof(path
));
164 strlcat(path
, "\\CFNetwork_debug.dll", sizeof(path
));
166 strlcat(path
, "\\CFNetwork.dll", sizeof(path
));
168 CFNetworkSupport
.image
= LoadLibraryA(path
);
172 if (!CFNetworkSupport
.image
) {
173 CFLog(__kCFLogAssertion
, CFSTR("CoreFoundation: failed to dynamically load CFNetwork"));
175 CFNetworkSupport
._CFSocketStreamCreatePair
= (CF_SOCKET_STREAM_PAIR
)CFNETWORK_LOAD_SYM(_CFSocketStreamCreatePair
);
176 CFNetworkSupport
._CFErrorCreateWithStreamError
= (CFErrorRef(*)(CFAllocatorRef
, CFStreamError
*))CFNETWORK_LOAD_SYM(_CFErrorCreateWithStreamError
);
177 CFNetworkSupport
._CFStreamErrorFromCFError
= (CFStreamError(*)(CFErrorRef
))CFNETWORK_LOAD_SYM(_CFStreamErrorFromCFError
);
180 #error Unknown or unspecified DEPLOYMENT_TARGET
183 if (!CFNetworkSupport
._CFSocketStreamCreatePair
) CFLog(__kCFLogAssertion
, CFSTR("CoreFoundation: failed to dynamically link symbol _CFSocketStreamCreatePair"));
184 if (!CFNetworkSupport
._CFErrorCreateWithStreamError
) CFLog(__kCFLogAssertion
, CFSTR("CoreFoundation: failed to dynamically link symbol _CFErrorCreateWithStreamError"));
185 if (!CFNetworkSupport
._CFStreamErrorFromCFError
) CFLog(__kCFLogAssertion
, CFSTR("CoreFoundation: failed to dynamically link symbol _CFStreamErrorFromCFError"));
187 __CFBitSet(CFNetworkSupport
.flags
, kInitialized
);
191 createPair(CFAllocatorRef alloc
, CFStringRef host
, UInt32 port
, CFSocketNativeHandle sock
, const CFSocketSignature
* sig
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
)
199 __CFSpinLock(&(CFNetworkSupport
.lock
));
200 if (!__CFBitIsSet(CFNetworkSupport
.flags
, kTriedToLoad
)) initializeCFNetworkSupport();
201 __CFSpinUnlock(&(CFNetworkSupport
.lock
));
203 CFNETWORK_CALL(_CFSocketStreamCreatePair
, (alloc
, host
, port
, sock
, sig
, readStream
, writeStream
));
207 CF_EXPORT
void CFStreamCreatePairWithSocket(CFAllocatorRef alloc
, CFSocketNativeHandle sock
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
) {
208 createPair(alloc
, NULL
, 0, sock
, NULL
, readStream
, writeStream
);
211 CF_EXPORT
void CFStreamCreatePairWithSocketToHost(CFAllocatorRef alloc
, CFStringRef host
, UInt32 port
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
) {
212 createPair(alloc
, host
, port
, 0, NULL
, readStream
, writeStream
);
215 CF_EXPORT
void CFStreamCreatePairWithPeerSocketSignature(CFAllocatorRef alloc
, const CFSocketSignature
* sig
, CFReadStreamRef
*readStream
, CFWriteStreamRef
*writeStream
) {
216 createPair(alloc
, NULL
, 0, 0, sig
, readStream
, writeStream
);
219 __private_extern__ CFStreamError
_CFStreamErrorFromError(CFErrorRef error
) {
220 CFStreamError result
;
223 __CFSpinLock(&(CFNetworkSupport
.lock
));
224 if (!__CFBitIsSet(CFNetworkSupport
.flags
, kTriedToLoad
)) initializeCFNetworkSupport();
225 canUpCall
= (CFNetworkSupport
._CFStreamErrorFromCFError
!= NULL
);
226 __CFSpinUnlock(&(CFNetworkSupport
.lock
));
229 result
= CFNETWORK_CALL(_CFStreamErrorFromCFError
, (error
));
231 CFStringRef domain
= CFErrorGetDomain(error
);
232 if (CFEqual(domain
, kCFErrorDomainPOSIX
)) {
233 result
.domain
= kCFStreamErrorDomainPOSIX
;
234 } else if (CFEqual(domain
, kCFErrorDomainOSStatus
)) {
235 result
.domain
= kCFStreamErrorDomainMacOSStatus
;
236 } else if (CFEqual(domain
, kCFErrorDomainMach
)) {
237 result
.domain
= 11; // kCFStreamErrorDomainMach, but that symbol is in CFNetwork
239 result
.domain
= kCFStreamErrorDomainCustom
;
241 result
.error
= CFErrorGetCode(error
);
246 __private_extern__ CFErrorRef
_CFErrorFromStreamError(CFAllocatorRef alloc
, CFStreamError
*streamError
) {
250 __CFSpinLock(&(CFNetworkSupport
.lock
));
251 if (!__CFBitIsSet(CFNetworkSupport
.flags
, kTriedToLoad
)) initializeCFNetworkSupport();
252 canUpCall
= (CFNetworkSupport
._CFErrorCreateWithStreamError
!= NULL
);
253 __CFSpinUnlock(&(CFNetworkSupport
.lock
));
256 result
= CFNETWORK_CALL(_CFErrorCreateWithStreamError
, (alloc
, streamError
));
258 if (streamError
->domain
== kCFStreamErrorDomainPOSIX
) {
259 return CFErrorCreate(alloc
, kCFErrorDomainPOSIX
, streamError
->error
, NULL
);
260 } else if (streamError
->domain
== kCFStreamErrorDomainMacOSStatus
) {
261 return CFErrorCreate(alloc
, kCFErrorDomainOSStatus
, streamError
->error
, NULL
);
263 CFStringRef key
= CFSTR("CFStreamErrorDomainKey");
264 CFNumberRef value
= CFNumberCreate(alloc
, kCFNumberCFIndexType
, &streamError
->domain
);
265 CFDictionaryRef dict
= CFDictionaryCreate(alloc
, (const void **)(&key
), (const void **)(&value
), 1, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
266 result
= CFErrorCreate(alloc
, CFSTR("BogusCFStreamErrorCompatibilityDomain"), streamError
->error
, dict
);