2 * Copyright (c) 2012 Apple Computer, 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>
29 #include <sys/fcntl.h>
30 #include <CoreFoundation/CoreFoundation.h>
31 #include <CoreFoundation/CFBundle.h>
32 #include <mach/mach.h>
33 #include <EAP8021X/EAP.h>
34 #include <EAP8021X/EAPClientModule.h>
35 #include <EAP8021X/EAPClientProperties.h>
36 #if !TARGET_OS_EMBEDDED // This file is not built for Embedded
37 #include <Security/SecKeychain.h>
38 #include <Security/SecKeychainSearch.h>
39 #include <Security/SecKeychainItem.h>
40 #include <Security/SecIdentity.h>
41 #endif /* TARGET_OS_EMBEDDED */
42 #include <SystemConfiguration/SCNetworkConnection.h>
47 /*---------------------------------------------------------------------------
49 **---------------------------------------------------------------------------
52 static CFBundleRef bundle
= 0; /* our bundle ref */
53 static char eapsim_unique
[17];
55 static EAPClientModuleRef eapRef
= NULL
;
56 static EAPClientPluginData eapData
;
57 static CFMutableDictionaryRef eapProperties
= NULL
;
58 static CFDictionaryRef eapOptions
= NULL
;
59 static struct EAP_Packet
*eapSavePacket
= NULL
;
61 extern EAPClientPluginFuncRef
eapsim_introspect(EAPClientPluginFuncName name
);
63 /* ------------------------------------------------------------------------------------
64 get the EAP dictionary from the options
65 ------------------------------------------------------------------------------------ */
67 EAPSIMGetOptions (void)
72 // no option, use empty dictionary
74 eapOptions
= CFDictionaryCreate(0, 0, 0, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
77 /* ------------------------------------------------------------------------------------
78 ------------------------------------------------------------------------------------ */
82 EAPClientModuleStatus status
;
87 status
= EAPClientModuleAddBuiltinModule(eapsim_introspect
);
88 if (status
!= kEAPClientModuleStatusOK
) {
89 plog(ASL_LEVEL_INFO
, "EAP-SIM: EAPClientAddBuiltinModule(eapsim) failed %d\n", status
);
90 return EAP_ERROR_GENERIC
;
93 eapRef
= EAPClientModuleLookup(kEAPTypeEAPSIM
);
95 plog(ASL_LEVEL_INFO
, "EAP-SIM: EAPClientModuleLookup(eapsim) failed\n");
96 return EAP_ERROR_GENERIC
;
102 /* ------------------------------------------------------------------------------------
103 ------------------------------------------------------------------------------------ */
104 int EAPSIMIdentity (char *identity
, int maxlen
)
106 CFStringRef identRef
= NULL
;
108 int ret
= EAP_ERROR_GENERIC
;
110 error
= EAPSIMLoad();
115 if (eapOptions
== NULL
)
118 identRef
= EAPClientModulePluginUserName(eapRef
, eapOptions
);
120 if (CFStringGetCString(identRef
, identity
, maxlen
, kCFStringEncodingUTF8
))
128 /* ------------------------------------------------------------------------------------
129 Init routine called by the EAP engine when it needs the module.
130 Identity of the peer is known at this point.
131 mode is 0 for client, 1 for server.
132 cookie is the EAP engine context, to pass to subsequent calls to EAP.
133 context is EAP module context, that will be passed to subsequent calls to the module
134 ------------------------------------------------------------------------------------ */
136 EAPSIMInit (EAP_Input_t
*eap_in
, void **context
, CFDictionaryRef eapOptions
)
139 EAPClientModuleStatus status
;
140 int ret
= EAP_ERROR_GENERIC
;
142 error
= EAPSIMLoad();
146 bundle
= (CFBundleRef
)eap_in
->data
;
152 bzero(&eapData
, sizeof(eapData
));
154 /* remaining fields are read-only: */
155 *((bool *)&eapData
.log_enabled
) = 1;
156 *((uint32_t *)&eapData
.log_level
) = LOG_NOTICE
;
157 *((uint32_t *)&eapData
.mtu
) = eap_in
->mtu
;
158 *((uint32_t *)&eapData
.generation
) = 0;/* changed when user updates */
160 arc4random_buf(eapsim_unique
, sizeof(eapsim_unique
) - 1);
161 eapsim_unique
[sizeof(eapsim_unique
)-1] = 0;
163 eapData
.unique_id
= eapsim_unique
; /* used for TLS session resumption??? */
164 *((uint32_t *)&eapData
.unique_id_length
) = strlen(eapData
.unique_id
);
167 CFTypeRef value
= CFDictionaryGetValue(eapOptions
, kEAPPropertiesTypeEAPSIM
);
168 if (value
&& CFGetTypeID(value
) == CFDictionaryGetTypeID()) {
169 eapProperties
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, (CFDictionaryRef
)value
);
171 eapProperties
= CFDictionaryCreateMutableCopy(kCFAllocatorDefault
, 0, eapOptions
);
174 eapProperties
= CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks
, &kCFTypeDictionaryValueCallBacks
);
175 if (eapProperties
== NULL
) {
176 plog(ASL_LEVEL_ERR
, "EAP-SIM: Cannot allocate memory\n");
180 *((CFDictionaryRef
*)&eapData
.properties
) = (CFDictionaryRef
)eapProperties
;
182 status
= EAPClientModulePluginInit(eapRef
, &eapData
, NULL
, &error
);
183 if (status
!= kEAPClientStatusOK
) {
184 plog(ASL_LEVEL_ERR
, "EAP-SIM: EAPClientPluginInit(eapsim) failed, error %d\n", status
);
188 eapSavePacket
= NULL
;
197 /* ------------------------------------------------------------------------------------
198 ------------------------------------------------------------------------------------ */
199 int EAPSIMDispose (void *context
)
202 EAPClientModulePluginFree(eapRef
, &eapData
);
211 CFRelease(eapOptions
);
216 CFRelease(eapProperties
);
228 /* ------------------------------------------------------------------------------------
229 ------------------------------------------------------------------------------------ */
231 EAPSIMProcess (void *context
, EAP_Input_t
*eap_in
, EAP_Output_t
*eap_out
)
233 struct EAP_Packet
*pkt_in
= NULL
;
234 struct EAP_Packet
*pkt_out
= NULL
;
235 EAPClientStatus status
;
236 EAPClientState state
;
237 EAPClientDomainSpecificError error
;
240 // by default, ignore the message
241 eap_out
->action
= EAP_ACTION_NONE
;
243 eap_out
->data_len
= 0;
245 switch (eap_in
->notification
) {
247 case EAP_NOTIFICATION_DATA_FROM_UI
:
248 plog(ASL_LEVEL_ERR
, "unexpected EAP UI event");
251 case EAP_NOTIFICATION_PACKET
:
253 pkt_in
= (struct EAP_Packet
*)eap_in
->data
;
260 state
= EAPClientModulePluginProcess(eapRef
, &eapData
, (EAPPacketRef
)pkt_in
, (EAPPacketRef
*)&pkt_out
, &status
, &error
);
262 case kEAPClientStateAuthenticating
:
265 case kEAPClientStatusOK
:
266 eap_out
->data
= pkt_out
;
267 eap_out
->data_len
= ntohs(pkt_out
->len
);
268 eap_out
->action
= EAP_ACTION_SEND
;
271 case kEAPClientStatusUserInputRequired
:
272 plog(ASL_LEVEL_ERR
, "unsupported EAP UI input");
274 eap_out
->action
= EAP_ACTION_ACCESS_DENIED
;
278 case kEAPClientStateSuccess
:
279 eap_out
->action
= EAP_ACTION_ACCESS_GRANTED
;
283 case kEAPClientStateFailure
:
284 eap_out
->action
= EAP_ACTION_ACCESS_DENIED
;
297 /* ------------------------------------------------------------------------------------
298 ------------------------------------------------------------------------------------ */
300 EAPSIMFree (void *context
, EAP_Output_t
*eap_out
)
303 EAPClientModulePluginFreePacket(eapRef
, &eapData
, eap_out
->data
);
307 /* ------------------------------------------------------------------------------------
308 ------------------------------------------------------------------------------------ */
310 EAPSIMGetAttribute (void *context
, EAP_Attribute_t
*eap_attr
)
317 switch (eap_attr
->type
) {
319 case EAP_ATTRIBUTE_MPPE_SEND_KEY
:
320 data
= EAPClientModulePluginSessionKey(eapRef
, &eapData
, &len
);
322 case EAP_ATTRIBUTE_MPPE_RECV_KEY
:
323 data
= EAPClientModulePluginServerKey(eapRef
, &eapData
, &len
);
330 eap_attr
->data
= data
;
332 eap_attr
->data_len
= 64;
334 eap_attr
->data_len
= len
;