1/* 2 * Copyright (c) 2001-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * Modification History 26 * 27 * December 10, 2001 Dieter Siegmund (dieter@apple.com) 28 * - created 29 */ 30 31#include <EAP8021X/EAPClientPlugin.h> 32#include <EAP8021X/EAPClientProperties.h> 33#include <EAP8021X/chap.h> 34#include <mach/boolean.h> 35#include <unistd.h> 36#include <stdlib.h> 37#include <string.h> 38#include <stdio.h> 39#include "EAPLog.h" 40 41/* 42 * Declare these here to ensure that the compiler 43 * generates appropriate errors/warnings 44 */ 45EAPClientPluginFuncIntrospect md5_introspect; 46static EAPClientPluginFuncVersion md5_version; 47static EAPClientPluginFuncEAPType md5_type; 48static EAPClientPluginFuncEAPName md5_name; 49static EAPClientPluginFuncInit md5_init; 50static EAPClientPluginFuncFree md5_free; 51static EAPClientPluginFuncProcess md5_process; 52static EAPClientPluginFuncRequireProperties md5_require_props; 53static EAPClientPluginFuncFreePacket md5_free_packet; 54 55static EAPPacketRef 56md5_request(EAPClientPluginDataRef plugin, const EAPPacketRef in_pkt_p) 57{ 58 uint16_t in_length = EAPPacketGetLength(in_pkt_p); 59 EAPMD5ChallengePacketRef in_md5_p = (EAPMD5ChallengePacketRef)in_pkt_p; 60 EAPMD5ResponsePacketRef out_md5_p = NULL; 61 int size; 62 63 if (in_length < sizeof(*in_md5_p)) { 64 EAPLOG_FL(LOG_NOTICE, "header too short (length %d < %ld)", 65 in_length, sizeof(*in_md5_p)); 66 goto failed; 67 } 68 if (in_length < (sizeof(*in_md5_p) + in_md5_p->value_size)) { 69 EAPLOG_FL(LOG_NOTICE, "value too short (length %d < %ld)", 70 in_length, sizeof(*in_md5_p) + in_md5_p->value_size); 71 goto failed; 72 } 73 size = sizeof(*out_md5_p) + plugin->username_length; 74 out_md5_p = malloc(size); 75 if (out_md5_p == NULL) { 76 goto failed; 77 } 78 out_md5_p->code = kEAPCodeResponse; 79 out_md5_p->identifier = in_md5_p->identifier; 80 EAPPacketSetLength((EAPPacketRef)out_md5_p, size); 81 out_md5_p->type = kEAPTypeMD5Challenge; 82 out_md5_p->value_size = sizeof(out_md5_p->value); 83 chap_md5(in_md5_p->identifier, plugin->password, plugin->password_length, 84 in_md5_p->value, in_md5_p->value_size, out_md5_p->value); 85 bcopy(plugin->username, out_md5_p->name, plugin->username_length); 86 return ((EAPPacketRef)out_md5_p); 87 failed: 88 if (out_md5_p != NULL) { 89 free(out_md5_p); 90 } 91 return (NULL); 92} 93 94static EAPClientStatus 95md5_init(EAPClientPluginDataRef plugin, 96 CFArrayRef * required_props, 97 EAPClientDomainSpecificError * error) 98{ 99 *error = 0; 100 *required_props = NULL; 101 return (kEAPClientStatusOK); 102} 103 104static void 105md5_free(EAPClientPluginDataRef plugin) 106{ 107 /* ignore, no context data */ 108 return; 109} 110 111static void 112md5_free_packet(EAPClientPluginDataRef plugin, EAPPacketRef arg) 113{ 114 if (arg != NULL) { 115 /* we malloc'd the packet, so free it */ 116 free(arg); 117 } 118 return; 119} 120 121static EAPClientState 122md5_process(EAPClientPluginDataRef plugin, 123 const EAPPacketRef in_pkt, 124 EAPPacketRef * out_pkt_p, 125 EAPClientStatus * client_status, 126 EAPClientDomainSpecificError * error) 127{ 128 EAPClientState plugin_state; 129 130 *client_status = kEAPClientStatusOK; 131 *error = 0; 132 plugin_state = kEAPClientStateAuthenticating; 133 *out_pkt_p = NULL; 134 135 switch (in_pkt->code) { 136 case kEAPCodeRequest: 137 if (plugin->password == NULL) { 138 *client_status = kEAPClientStatusUserInputRequired; 139 } 140 else { 141 *out_pkt_p = md5_request(plugin, in_pkt); 142 } 143 break; 144 case kEAPCodeSuccess: 145 plugin_state = kEAPClientStateSuccess; 146 break; 147 case kEAPCodeFailure: 148 *client_status = kEAPClientStatusFailed; 149 plugin_state = kEAPClientStateFailure; 150 break; 151 default: 152 break; 153 } 154 return (plugin_state); 155} 156 157static CFArrayRef 158md5_require_props(EAPClientPluginDataRef plugin) 159{ 160 CFStringRef prop; 161 162 if (plugin->password != NULL) { 163 return (NULL); 164 } 165 prop = kEAPClientPropUserPassword; 166 return (CFArrayCreate(NULL, (const void **)&prop, 1, 167 &kCFTypeArrayCallBacks)); 168} 169 170static EAPType 171md5_type() 172{ 173 return (kEAPTypeMD5Challenge); 174} 175 176static const char * 177md5_name() 178{ 179 return ("MD5"); 180} 181 182static EAPClientPluginVersion 183md5_version() 184{ 185 return (kEAPClientPluginVersion); 186} 187 188static struct func_table_ent { 189 const char * name; 190 void * func; 191} func_table[] = { 192 { kEAPClientPluginFuncNameVersion, md5_version }, 193 { kEAPClientPluginFuncNameEAPType, md5_type }, 194 { kEAPClientPluginFuncNameEAPName, md5_name }, 195 { kEAPClientPluginFuncNameInit, md5_init }, 196 { kEAPClientPluginFuncNameFree, md5_free }, 197 { kEAPClientPluginFuncNameProcess, md5_process }, 198 { kEAPClientPluginFuncNameRequireProperties, md5_require_props }, 199 { kEAPClientPluginFuncNameFreePacket, md5_free_packet }, 200 { NULL, NULL}, 201}; 202 203 204EAPClientPluginFuncRef 205md5_introspect(EAPClientPluginFuncName name) 206{ 207 struct func_table_ent * scan; 208 209 210 for (scan = func_table; scan->name != NULL; scan++) { 211 if (strcmp(name, scan->name) == 0) { 212 return (scan->func); 213 } 214 } 215 return (NULL); 216} 217