Delete trailing whitespace.
[freeradius.git] / src / modules / rlm_eap / types / rlm_eap_psk / rlm_eap_psk.cpp
1 /* $Id$ */
2
3 /*
4  * rlm_eap_psk.cpp
5  *
6  * Implementation of the interface between the radius server and
7  * the eap-psk protocol
8  *
9  *
10  * Copyright (C) France Télécom R&D (DR&D/MAPS/NSS)
11  *
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.
16  *
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.
21  *
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
25  *
26  * Copyright 2006 The FreeRADIUS server project
27  *
28  */
29
30 #include <freeradius-devel/ident.h>
31 RCSID("$Id$")
32
33
34
35 #include "autoconf.h"
36
37 #include <stdio.h>
38 #include <stdlib.h>
39
40
41 #include "eap_psk.h"
42 #include "eap_psk_ssm.h"
43
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 */
60 };
61
62
63 /**
64  *@memo         this function add value pair to reply
65  */
66 static void addReply(VALUE_PAIR** vp,
67                       const char* name, unsigned char* value, int len)
68 {
69         VALUE_PAIR *reply_attr;
70         reply_attr = pairmake(name, "", T_OP_EQ);
71         if (!reply_attr) {
72                 DEBUG("rlm_eap_psk: "
73                       "add_reply failed to create attribute %s: %s\n",
74                       name, librad_errstr);
75                 return;
76         }
77
78         memcpy(reply_attr->vp_octets, value, len);
79         reply_attr->length = len;
80         pairadd(vp, reply_attr);
81 }
82
83 /*
84  *@memo         this function detaches the module
85  */
86 static int pskDetach(void *arg)
87 {
88         PSK_CONF *inst = (PSK_CONF *) arg;
89
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);
95
96         free(inst);
97
98         return 0;
99 }
100
101
102 /*
103  *@memo          this function attaches the module
104  */
105 static int pskAttach(CONF_SECTION *cs, void **instance)
106 {
107         PSK_CONF *inst;
108
109         inst = (PSK_CONF*)malloc(sizeof(*inst));
110         if (!inst) {
111                 radlog(L_ERR, "rlm_eap_psk: out of memory");
112                 return -1;
113         }
114         memset(inst, 0, sizeof(*inst));
115
116         // parse the configuration attributes
117         if (cf_section_parse(cs, inst, moduleConfig) < 0) {
118           pskDetach(inst);
119           return -1;
120         }
121
122         *instance = inst;
123         return 0;
124 }
125
126
127
128 /**
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
132  */
133 static int pskInitiate(void *type_arg, EAP_HANDLER *handler)
134 {
135   PSK_SESSION *session;
136   PSK_CONF *conf=(PSK_CONF*)type_arg;
137
138   if(conf==NULL)
139     {
140       radlog(L_ERR,"rlm_eap_psk: Cannot initiate EAP-PSK without having its configuration");
141       return 0;
142     }
143
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);
149
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");
154     return 0;
155   }
156
157   // save this pointer in the handler
158   session=(PSK_SESSION *)handler->opaque;
159   handler->free_opaque=pskFreeSession;
160
161   // initializing session information
162   memset(session,0,sizeof(PSK_SESSION));
163   session->state=INIT;
164
165   handler->stage=AUTHENTICATE;
166
167   // initiate the eap-psk protocol
168   return pskProcess(conf,session,NULL,handler->eap_ds->request);
169
170 }
171
172
173
174
175 /**
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
179  */
180 static int pskAuthenticate(void *arg, EAP_HANDLER *handler)
181 {
182   PSK_SESSION *session;
183   PSK_CONF *conf=(PSK_CONF*)arg;
184   int resul;
185
186   if(conf==NULL)
187     {
188       radlog(L_ERR,"rlm_eap_psk: Cannot authenticate without having EAP-PSK configuration");
189       return 0;
190     }
191
192   if(!handler->opaque) {
193     radlog(L_ERR,"rlm_eap_psk: Cannot authenticate without EAP-PSK session information");
194     return 0;
195   }
196
197   // find the session information
198   session=(PSK_SESSION *)handler->opaque;
199
200   resul=pskProcess(conf,session,handler->eap_ds->response,handler->eap_ds->request);
201
202   if(handler->eap_ds->request->code==PW_EAP_SUCCESS) {
203     // sending keys
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);
206   }
207
208   return resul;
209
210 }
211
212
213 EAP_TYPE rlm_eap_psk = {
214         "eap_psk",
215         pskAttach,              // attach
216         pskInitiate,            // Start the initial request, after Identity
217         NULL,
218         pskAuthenticate,        // authentication
219         pskDetach               // detach
220 };