2 * Copyright (c) 2009, 2010, 2012, 2013, 2015, 2018 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 #include <sys/types.h>
26 #include <sys/param.h>
29 #include <mach-o/dyld_priv.h>
30 #include <sys/codesign.h>
32 #include <SystemConfiguration/CaptiveNetwork.h>
33 #include <SystemConfiguration/SCPrivate.h>
37 #pragma mark CaptiveNetwork.framework APIs (exported through the SystemConfiguration.framework)
40 const CFStringRef kCNNetworkInfoKeySSIDData
= CFSTR("SSIDDATA");
41 const CFStringRef kCNNetworkInfoKeySSID
= CFSTR("SSID");
42 const CFStringRef kCNNetworkInfoKeyBSSID
= CFSTR("BSSID");
46 __loadCaptiveNetwork(void) {
47 static void *image
= NULL
;
48 static dispatch_once_t once
;
50 dispatch_once(&once
, ^{
51 image
= _SC_dlopen("/System/Library/PrivateFrameworks/CaptiveNetwork.framework/CaptiveNetwork");
59 CNSetSupportedSSIDs(CFArrayRef ssidArray
)
61 static typeof (CNSetSupportedSSIDs
) *dyfunc
= NULL
;
63 void *image
= __loadCaptiveNetwork();
64 if (image
) dyfunc
= dlsym(image
, "__CNSetSupportedSSIDs");
66 return dyfunc
? dyfunc(ssidArray
) : FALSE
;
71 CNMarkPortalOnline(CFStringRef interfaceName
)
73 static typeof (CNMarkPortalOnline
) *dyfunc
= NULL
;
75 void *image
= __loadCaptiveNetwork();
76 if (image
) dyfunc
= dlsym(image
, "__CNMarkPortalOnline");
78 return dyfunc
? dyfunc(interfaceName
) : FALSE
;
83 CNMarkPortalOffline(CFStringRef interfaceName
)
85 static typeof (CNMarkPortalOffline
) *dyfunc
= NULL
;
87 void *image
= __loadCaptiveNetwork();
88 if (image
) dyfunc
= dlsym(image
, "__CNMarkPortalOffline");
90 return dyfunc
? dyfunc(interfaceName
) : FALSE
;
94 CNCopySupportedInterfaces(void)
96 static typeof (CNCopySupportedInterfaces
) *dyfunc
= NULL
;
98 void *image
= __loadCaptiveNetwork();
99 if (image
) dyfunc
= dlsym(image
, "__CNCopySupportedInterfaces");
101 return dyfunc
? dyfunc() : NULL
;
106 #define CN_COPY_ENTITLEMENT CFSTR("com.apple.developer.networking.wifi-info")
108 static CFDictionaryRef
109 __CopyEntitlementsForPID(pid_t pid
)
111 uint8_t *buffer
= NULL
;
112 size_t bufferlen
= 0L;
113 int64_t datalen
= 0L;
114 CFDataRef cfdata
= NULL
;
118 } csheader
= { 0, 0 };
120 CFPropertyListRef plist
= NULL
;
123 * Get the length of the actual entitlement data
125 error
= csops(pid
, CS_OPS_ENTITLEMENTS_BLOB
, &csheader
, sizeof(csheader
));
127 if (error
== -1 && errno
== ERANGE
) {
128 bufferlen
= ntohl(csheader
.length
);
129 if (bufferlen
> 1024 * 1024 || bufferlen
< 8) {
133 buffer
= malloc(bufferlen
);
134 if (buffer
== NULL
) {
137 error
= csops(pid
, CS_OPS_ENTITLEMENTS_BLOB
, buffer
, bufferlen
);
143 datalen
= bufferlen
- sizeof(csheader
);
145 if (error
== 0 && buffer
&& datalen
> 0) {
146 cfdata
= CFDataCreateWithBytesNoCopy(kCFAllocatorDefault
, buffer
+ sizeof(csheader
), datalen
, kCFAllocatorNull
);
147 if (cfdata
== NULL
) {
151 plist
= CFPropertyListCreateWithData(NULL
, cfdata
, kCFPropertyListImmutable
, NULL
, NULL
);
153 SC_log(LOG_ERR
, "Could not decode entitlements for pid %d", pid
);
157 SC_log(LOG_ERR
, "Could not get valid codesigning data for pid %d. Error %d", pid
, error
);
161 SC_log(LOG_ERR
, "Error getting entitlements for pid %d: %s", pid
, strerror(errno
));
163 if (cfdata
!= NULL
) {
166 if (buffer
!= NULL
) {
169 if (plist
&& !isA_CFDictionary(plist
)) {
170 SC_log(LOG_ERR
, "Could not decode entitlements for pid %d as a dictionary.", pid
);
179 __isApplicationEntitled(void)
181 if (dyld_get_program_sdk_version() >= DYLD_IOS_VERSION_12_0
) {
182 /* application is linked on or after iOS 12.0 SDK so it must have the entitlement */
183 CFTypeRef entitlement
= NULL
;
184 CFDictionaryRef entitlements
= __CopyEntitlementsForPID(getpid());
185 if (entitlements
!= NULL
) {
186 Boolean entitled
= FALSE
;
187 entitlement
= CFDictionaryGetValue(entitlements
, CN_COPY_ENTITLEMENT
);
188 if(isA_CFBoolean(entitlement
)) {
189 entitled
= CFBooleanGetValue(entitlement
);
191 CFRelease(entitlements
);
194 /* application is linked on or after iOS 12.0 SDK but missing entitlement */
197 /* application is linked before iOS 12.0 SDK */
201 #endif /* TARGET_OS_IPHONE */
204 CNCopyCurrentNetworkInfo(CFStringRef interfaceName
)
206 #if TARGET_OS_IPHONE && !TARGET_OS_IOSMAC
207 if (__isApplicationEntitled() == FALSE
) {
208 SC_log(LOG_DEBUG
, "Application does not have %@ entitlement", CN_COPY_ENTITLEMENT
);
211 static typeof (CNCopyCurrentNetworkInfo
) *dyfunc
= NULL
;
213 void *image
= __loadCaptiveNetwork();
214 if (image
) dyfunc
= dlsym(image
, "__CNCopyCurrentNetworkInfo");
216 return dyfunc
? dyfunc(interfaceName
) : NULL
;
217 #else // TARGET_OS_IPHONE && !TARGET_OS_IOSMAC
218 #pragma unused(interfaceName)
220 #endif // TARGET_OS_IPHONE && !TARGET_OS_IOSMAC