6 * Implementation of the interface between the radius server and
10 * Copyright (C) France Télécom R&D (DR&D/MAPS/NSS)
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * Copyright 2006 The FreeRADIUS server project
30 #include <freeradius-devel/ident.h>
42 #include "eap_psk_ssm.h"
44 static CONF_PARSER moduleConfig[] = {
45 { "private_key", PW_TYPE_STRING_PTR,
46 offsetof(PSK_CONF, privateKey), NULL, NULL },
47 { "server_name", PW_TYPE_STRING_PTR,
48 offsetof(PSK_CONF, id_s), NULL, "pskserver" },
49 { "peer_nai_attribute", PW_TYPE_STRING_PTR,
50 offsetof(PSK_CONF, peerNaiAttribute), NULL, "eapPskPeerNAI" },
51 { "peer_key_attribute", PW_TYPE_STRING_PTR,
52 offsetof(PSK_CONF, peerKeyAttribute), NULL, "eapPskPeerKey" },
53 { "users_file_path", PW_TYPE_STRING_PTR,
54 offsetof(PSK_CONF, usersFilePath), NULL, "/etc/raddb/users.psk" },
55 { "nb_retry", PW_TYPE_INTEGER,
56 offsetof(PSK_CONF, nbRetry), NULL, "3" },
57 { "max_delay", PW_TYPE_INTEGER,
58 offsetof(PSK_CONF, maxDelay), NULL, "5" },
59 { NULL, -1, 0, NULL, NULL } /* end the list */
64 *@memo this function add value pair to reply
66 static void addReply(VALUE_PAIR** vp,
67 const char* name, unsigned char* value, int len)
69 VALUE_PAIR *reply_attr;
70 reply_attr = pairmake(name, "", T_OP_EQ);
73 "add_reply failed to create attribute %s: %s\n",
78 memcpy(reply_attr->vp_octets, value, len);
79 reply_attr->length = len;
80 pairadd(vp, reply_attr);
84 *@memo this function detaches the module
86 static int pskDetach(void *arg)
88 PSK_CONF *inst = (PSK_CONF *) arg;
90 if (inst->privateKey) free(inst->privateKey);
91 if (inst->id_s) free(inst->id_s);
92 if (inst->peerNaiAttribute) free(inst->peerNaiAttribute);
93 if (inst->peerKeyAttribute) free(inst->peerKeyAttribute);
94 if(inst->usersFilePath) free(inst->usersFilePath);
103 *@memo this function attaches the module
105 static int pskAttach(CONF_SECTION *cs, void **instance)
109 inst = (PSK_CONF*)malloc(sizeof(*inst));
111 radlog(L_ERR, "rlm_eap_psk: out of memory");
114 memset(inst, 0, sizeof(*inst));
116 // parse the configuration attributes
117 if (cf_section_parse(cs, inst, moduleConfig) < 0) {
129 *@memo this function begins the conversation when the EAP-Identity response is received
130 * send an initial eap-psk request, ie IDREQ
131 *@param handler, pointer to specific information about the eap-psk protocol
133 static int pskInitiate(void *type_arg, EAP_HANDLER *handler)
135 PSK_SESSION *session;
136 PSK_CONF *conf=(PSK_CONF*)type_arg;
140 radlog(L_ERR,"rlm_eap_psk: Cannot initiate EAP-PSK without having its configuration");
144 DEBUG2("rlm_eap_psk: privateKey: %s",conf->privateKey);
145 DEBUG2("rlm_eap_psk: id_s: %s", conf->id_s);
146 DEBUG2("rlm_eap_psk: peerNaiAttribute: %s", conf->peerNaiAttribute);
147 DEBUG2("rlm_eap_psk: peerKeyAttribute: %s", conf->peerKeyAttribute);
148 DEBUG2("rlm_eap_psk: usersFilePath: %s", conf->usersFilePath);
150 // allocate memory in order to save the state of session
151 handler->opaque=malloc(sizeof(PSK_SESSION));
152 if(!handler->opaque) {
153 radlog(L_ERR,"rlm_eap_psk: Out of memory");
157 // save this pointer in the handler
158 session=(PSK_SESSION *)handler->opaque;
159 handler->free_opaque=pskFreeSession;
161 // initializing session information
162 memset(session,0,sizeof(PSK_SESSION));
165 handler->stage=AUTHENTICATE;
167 // initiate the eap-psk protocol
168 return pskProcess(conf,session,NULL,handler->eap_ds->request);
176 *@memo this function uses specific EAP-Type authentication mechanism to authenticate the user
177 * may be called many times
178 *@param handler, pointer to specific information about the eap-psk protocol
180 static int pskAuthenticate(void *arg, EAP_HANDLER *handler)
182 PSK_SESSION *session;
183 PSK_CONF *conf=(PSK_CONF*)arg;
188 radlog(L_ERR,"rlm_eap_psk: Cannot authenticate without having EAP-PSK configuration");
192 if(!handler->opaque) {
193 radlog(L_ERR,"rlm_eap_psk: Cannot authenticate without EAP-PSK session information");
197 // find the session information
198 session=(PSK_SESSION *)handler->opaque;
200 resul=pskProcess(conf,session,handler->eap_ds->response,handler->eap_ds->request);
202 if(handler->eap_ds->request->code==PW_EAP_SUCCESS) {
204 addReply(&handler->request->reply->vps,"MS-MPPE-Recv-Key",session->msk,32);
205 addReply(&handler->request->reply->vps,"MS-MPPE-Send-Key",&session->msk[32],32);
213 EAP_TYPE rlm_eap_psk = {
216 pskInitiate, // Start the initial request, after Identity
218 pskAuthenticate, // authentication