~ubuntu-branches/ubuntu/dapper/freeradius/dapper-updates

« back to all changes in this revision

Viewing changes to src/modules/rlm_eap/types/rlm_eap_gtc/rlm_eap_gtc.c

  • Committer: Bazaar Package Importer
  • Author(s): Paul Hampson
  • Date: 2004-12-29 20:19:42 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20041229201942-uj2e95la965uthc7
Tags: 1.0.1-2
* freeradius-dialupadmin Suggests php4-mysql | php4-pgsql
   Closes: #279419
* Added a two-second pause to restart in init.d script
   Closes: #262635
* FreeRADIUS module packages now depend on the same source
  version of the main FreeRADIUS package.
   Closes: #284353
* FreeRADIUS-dialupadmin's default paths in admin.conf are
  now correct.
   Closes: #280942
* FreeRADIUS-dialupadmin's help.php3 can now find README.
   Closes: #280941
* Fixes stolen from 1.0.2 CVS:
  - Bug fix to make udpfromto code work
  - radrelay shouldn't dump core if it can't read a VP from the
    detail file.
  - Only initialize the random pool once.
  - In rlm_sql, don't escape characters twice.
  - In rlm_ldap, only claim Auth-Type if a plain text password is present.
  - Locking fixes in threading code
  - Fix building on gcc-4.0 by not trying to access static auth_port from
    other files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * rlm_eap_gtc.c    Handles that are called from eap
 
3
 *
 
4
 * Version:     $Id: rlm_eap_gtc.c,v 1.3 2004/02/26 19:04:30 aland Exp $
 
5
 *
 
6
 *   This program is free software; you can redistribute it and/or modify
 
7
 *   it under the terms of the GNU General Public License as published by
 
8
 *   the Free Software Foundation; either version 2 of the License, or
 
9
 *   (at your option) any later version.
 
10
 *
 
11
 *   This program is distributed in the hope that it will be useful,
 
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *   GNU General Public License for more details.
 
15
 *
 
16
 *   You should have received a copy of the GNU General Public License
 
17
 *   along with this program; if not, write to the Free Software
 
18
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
 *
 
20
 * Copyright 2003  The FreeRADIUS server project
 
21
 */
 
22
 
 
23
#include "autoconf.h"
 
24
 
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
 
 
28
#include "eap.h"
 
29
 
 
30
#include <rad_assert.h>
 
31
 
 
32
/*
 
33
 *      EAP-GTC is just ASCII data carried inside of the EAP session.
 
34
 *      The length of the data is indicated by the encapsulating EAP
 
35
 *      protocol.
 
36
 */
 
37
typedef struct rlm_eap_gtc_t {
 
38
        const char      *challenge;
 
39
        const char      *auth_type_name;
 
40
        int             auth_type;
 
41
} rlm_eap_gtc_t;
 
42
 
 
43
static CONF_PARSER module_config[] = {
 
44
        { "challenge", PW_TYPE_STRING_PTR,
 
45
          offsetof(rlm_eap_gtc_t, challenge), NULL, "Password: " },
 
46
 
 
47
        { "auth_type", PW_TYPE_STRING_PTR,
 
48
          offsetof(rlm_eap_gtc_t, auth_type_name), NULL, "PAP" },
 
49
 
 
50
        { NULL, -1, 0, NULL, NULL }           /* end the list */
 
51
};
 
52
 
 
53
 
 
54
/*
 
55
 *      Detach the module.
 
56
 */
 
57
static int gtc_detach(void *arg)
 
58
{
 
59
        rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) arg;
 
60
 
 
61
        if (inst->challenge) free(inst->challenge);
 
62
        if (inst->auth_type_name) free(inst->auth_type_name);
 
63
 
 
64
        free(inst);
 
65
 
 
66
        return 0;
 
67
}
 
68
 
 
69
/*
 
70
 *      Attach the module.
 
71
 */
 
72
static int gtc_attach(CONF_SECTION *cs, void **instance)
 
73
{
 
74
        rlm_eap_gtc_t   *inst;
 
75
        DICT_VALUE      *dval;
 
76
 
 
77
        inst = malloc(sizeof(*inst));
 
78
        if (!inst) {
 
79
                radlog(L_ERR, "rlm_eap_gtc: out of memory");
 
80
                return -1;
 
81
        }
 
82
        memset(inst, 0, sizeof(*inst));
 
83
 
 
84
        /*
 
85
         *      Parse the configuration attributes.
 
86
         */
 
87
        if (cf_section_parse(cs, inst, module_config) < 0) {
 
88
                gtc_detach(inst);
 
89
                return -1;
 
90
        }
 
91
 
 
92
        dval = dict_valbyname(PW_AUTH_TYPE, inst->auth_type_name);
 
93
        if (!dval) {
 
94
                radlog(L_ERR, "rlm_eap_gtc: Unknown Auth-Type %s",
 
95
                       inst->auth_type_name);
 
96
                gtc_detach(inst);
 
97
                return -1;
 
98
        }
 
99
 
 
100
        inst->auth_type = dval->value;
 
101
 
 
102
        *instance = inst;
 
103
 
 
104
        return 0;
 
105
}
 
106
 
 
107
/*
 
108
 *      Initiate the EAP-GTC session by sending a challenge to the peer.
 
109
 */
 
110
static int gtc_initiate(void *type_data, EAP_HANDLER *handler)
 
111
{
 
112
        int length;
 
113
        EAP_DS *eap_ds = handler->eap_ds;
 
114
        rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) type_data;
 
115
 
 
116
        /*
 
117
         *      FIXME: call radius_xlat on the challenge
 
118
         */
 
119
        length = strlen(inst->challenge);
 
120
 
 
121
        /*
 
122
         *      We're sending a request...
 
123
         */
 
124
        eap_ds->request->code = PW_EAP_REQUEST;
 
125
 
 
126
        eap_ds->request->type.data = malloc(length);
 
127
        if (eap_ds->request->type.data == NULL) {
 
128
                radlog(L_ERR, "rlm_eap_gtc: out of memory");
 
129
                return 0;
 
130
        }
 
131
 
 
132
        memcpy(eap_ds->request->type.data, inst->challenge, length);
 
133
        eap_ds->request->type.length = length;
 
134
 
 
135
        /*
 
136
         *      We don't need to authorize the user at this point.
 
137
         *
 
138
         *      We also don't need to keep the challenge, as it's
 
139
         *      stored in 'handler->eap_ds', which will be given back
 
140
         *      to us...
 
141
         */
 
142
        handler->stage = AUTHENTICATE;
 
143
 
 
144
        return 1;
 
145
}
 
146
 
 
147
 
 
148
/*
 
149
 *      Authenticate a previously sent challenge.
 
150
 */
 
151
static int gtc_authenticate(void *type_data, EAP_HANDLER *handler)
 
152
{
 
153
        VALUE_PAIR *vp;
 
154
        EAP_DS *eap_ds = handler->eap_ds;
 
155
        rlm_eap_gtc_t *inst = (rlm_eap_gtc_t *) type_data;
 
156
 
 
157
        /*
 
158
         *      Get the User-Password for this user.
 
159
         */
 
160
        rad_assert(handler->request != NULL);
 
161
        rad_assert(handler->stage == AUTHENTICATE);
 
162
 
 
163
        /*
 
164
         *      Sanity check the response.  We need at least one byte
 
165
         *      of data.
 
166
         */
 
167
        if (eap_ds->response->length <= 4) {
 
168
                radlog(L_ERR, "rlm_eap_gtc: corrupted data");
 
169
                eap_ds->request->code = PW_EAP_FAILURE;
 
170
                return 0;
 
171
        }
 
172
 
 
173
#if 0
 
174
        if (debug_flag > 2) {
 
175
                int i;
 
176
 
 
177
                for (i = 0; i < eap_ds->response->length - 4; i++) {
 
178
                        if ((i & 0x0f) == 0) printf("%d: ", i);
 
179
 
 
180
                        printf("%02x ", eap_ds->response->type.data[i]);
 
181
 
 
182
                        if ((i & 0x0f) == 0x0f) printf("\n");
 
183
                }
 
184
        }
 
185
#endif
 
186
 
 
187
        /*
 
188
         *      Handle passwords here.
 
189
         */
 
190
        if (inst->auth_type == PW_AUTHTYPE_LOCAL) {
 
191
                /*
 
192
                 *      For now, do clear-text password authentication.
 
193
                 */
 
194
                vp = pairfind(handler->request->config_items, PW_PASSWORD);
 
195
                if (!vp) {
 
196
                        DEBUG2("  rlm_eap_gtc: ERROR: Clear-test User-Password is required for authentication.");
 
197
                        eap_ds->request->code = PW_EAP_FAILURE;
 
198
                        return 0;
 
199
                }
 
200
 
 
201
                if (eap_ds->response->type.length != vp->length) {
 
202
                        DEBUG2("  rlm_eap_gtc: ERROR: Passwords are of different length. %d %d", eap_ds->response->type.length, vp->length);
 
203
                        eap_ds->request->code = PW_EAP_FAILURE;
 
204
                        return 0;
 
205
                }
 
206
 
 
207
                if (memcmp(eap_ds->response->type.data,
 
208
                           vp->strvalue, vp->length) != 0) {
 
209
                        DEBUG2("  rlm_eap_gtc: ERROR: Passwords are different");
 
210
                        eap_ds->request->code = PW_EAP_FAILURE;
 
211
                        return 0;
 
212
                }
 
213
 
 
214
                /*
 
215
                 *      EAP packets can be ~64k long maximum, and
 
216
                 *      we don't like that.
 
217
                 */
 
218
        } else if (eap_ds->response->type.length <= 128) {
 
219
                int rcode;
 
220
 
 
221
                /*
 
222
                 *      If there was a User-Password in the request,
 
223
                 *      why the heck are they using EAP-GTC?
 
224
                 */
 
225
                rad_assert(handler->request->password == NULL);
 
226
 
 
227
                vp = pairmake("User-Password", "", T_OP_EQ);
 
228
                if (!vp) {
 
229
                        radlog(L_ERR, "rlm_eap_gtc: out of memory");
 
230
                        return 0;
 
231
                }
 
232
                vp->length = eap_ds->response->type.length;
 
233
                memcpy(vp->strvalue, eap_ds->response->type.data, vp->length);
 
234
                vp->strvalue[vp->length] = 0;
 
235
 
 
236
                /*
 
237
                 *      Add the password to the request, and allow
 
238
                 *      another module to do the work of authenticating it.
 
239
                 */
 
240
                pairadd(&handler->request->packet->vps, vp);
 
241
                handler->request->password = vp;
 
242
 
 
243
                /*
 
244
                 *      This is a wild & crazy hack.
 
245
                 */
 
246
                rcode = module_authenticate(inst->auth_type, handler->request);
 
247
                if (rcode != RLM_MODULE_OK) {
 
248
                        eap_ds->request->code = PW_EAP_FAILURE;
 
249
                        return 0;
 
250
                }
 
251
 
 
252
        } else {
 
253
                radlog(L_ERR, "rlm_eap_gtc: Response is too large to understand");
 
254
                eap_ds->request->code = PW_EAP_FAILURE;
 
255
                return 0;
 
256
 
 
257
        }
 
258
 
 
259
        DEBUG2("  rlm_eap_gtc: Everything is OK.");
 
260
 
 
261
        eap_ds->request->code = PW_EAP_SUCCESS;
 
262
 
 
263
        return 1;
 
264
}
 
265
 
 
266
/*
 
267
 *      The module name should be the only globally exported symbol.
 
268
 *      That is, everything else should be 'static'.
 
269
 */
 
270
EAP_TYPE rlm_eap_gtc = {
 
271
        "eap_gtc",
 
272
        gtc_attach,                     /* attach */
 
273
        gtc_initiate,                   /* Start the initial request */
 
274
        NULL,                           /* authorization */
 
275
        gtc_authenticate,               /* authentication */
 
276
        gtc_detach                      /* detach */
 
277
};