~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to src/eap_peer/eap_gtc.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2007-08-26 16:06:57 UTC
  • mto: This revision was merged to the branch mainline in revision 26.
  • Revision ID: james.westby@ubuntu.com-20070826160657-mxk5ivjjh65ptxlr
Tags: upstream-0.6.0+0.5.8
ImportĀ upstreamĀ versionĀ 0.6.0+0.5.8

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * EAP peer method: EAP-GTC (RFC 3748)
3
 
 * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License version 2 as
7
 
 * published by the Free Software Foundation.
8
 
 *
9
 
 * Alternatively, this software may be distributed under the terms of BSD
10
 
 * license.
11
 
 *
12
 
 * See README and COPYING for more details.
13
 
 */
14
 
 
15
 
#include "includes.h"
16
 
 
17
 
#include "common.h"
18
 
#include "eap_i.h"
19
 
 
20
 
 
21
 
struct eap_gtc_data {
22
 
        int prefix;
23
 
};
24
 
 
25
 
 
26
 
static void * eap_gtc_init(struct eap_sm *sm)
27
 
{
28
 
        struct eap_gtc_data *data;
29
 
        data = os_zalloc(sizeof(*data));
30
 
        if (data == NULL)
31
 
                return NULL;
32
 
 
33
 
        if (sm->m && sm->m->method == EAP_TYPE_FAST) {
34
 
                wpa_printf(MSG_DEBUG, "EAP-GTC: EAP-FAST tunnel - use prefix "
35
 
                           "with challenge/response");
36
 
                data->prefix = 1;
37
 
        }
38
 
        return data;
39
 
}
40
 
 
41
 
 
42
 
static void eap_gtc_deinit(struct eap_sm *sm, void *priv)
43
 
{
44
 
        struct eap_gtc_data *data = priv;
45
 
        os_free(data);
46
 
}
47
 
 
48
 
 
49
 
static u8 * eap_gtc_process(struct eap_sm *sm, void *priv,
50
 
                            struct eap_method_ret *ret,
51
 
                            const u8 *reqData, size_t reqDataLen,
52
 
                            size_t *respDataLen)
53
 
{
54
 
        struct eap_gtc_data *data = priv;
55
 
        const struct eap_hdr *req;
56
 
        struct eap_hdr *resp;
57
 
        const u8 *pos, *password, *identity;
58
 
        u8 *rpos;
59
 
        size_t password_len, identity_len, len, plen;
60
 
        int otp;
61
 
 
62
 
        pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC,
63
 
                               reqData, reqDataLen, &len);
64
 
        if (pos == NULL) {
65
 
                ret->ignore = TRUE;
66
 
                return NULL;
67
 
        }
68
 
        req = (const struct eap_hdr *) reqData;
69
 
 
70
 
        wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-GTC: Request message", pos, len);
71
 
        if (data->prefix &&
72
 
            (len < 10 || os_memcmp(pos, "CHALLENGE=", 10) != 0)) {
73
 
                wpa_printf(MSG_DEBUG, "EAP-GTC: Challenge did not start with "
74
 
                           "expected prefix");
75
 
 
76
 
                /* Send an empty response in order to allow tunneled
77
 
                 * acknowledgement of the failure. This will also cover the
78
 
                 * error case which seems to use EAP-MSCHAPv2 like error
79
 
                 * reporting with EAP-GTC inside EAP-FAST tunnel. */
80
 
                resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC,
81
 
                                     respDataLen, 0, EAP_CODE_RESPONSE,
82
 
                                     req->identifier, NULL);
83
 
                return (u8 *) resp;
84
 
        }
85
 
 
86
 
        password = eap_get_config_otp(sm, &password_len);
87
 
        if (password)
88
 
                otp = 1;
89
 
        else {
90
 
                password = eap_get_config_password(sm, &password_len);
91
 
                otp = 0;
92
 
        }
93
 
 
94
 
        if (password == NULL) {
95
 
                wpa_printf(MSG_INFO, "EAP-GTC: Password not configured");
96
 
                eap_sm_request_otp(sm, (const char *) pos, len);
97
 
                ret->ignore = TRUE;
98
 
                return NULL;
99
 
        }
100
 
 
101
 
        ret->ignore = FALSE;
102
 
 
103
 
        ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE;
104
 
        ret->decision = DECISION_COND_SUCC;
105
 
        ret->allowNotifications = FALSE;
106
 
 
107
 
        plen = password_len;
108
 
        identity = eap_get_config_identity(sm, &identity_len);
109
 
        if (identity == NULL)
110
 
                return NULL;
111
 
        if (data->prefix)
112
 
                plen += 9 + identity_len + 1;
113
 
        resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GTC, respDataLen,
114
 
                             plen, EAP_CODE_RESPONSE, req->identifier, &rpos);
115
 
        if (resp == NULL)
116
 
                return NULL;
117
 
        if (data->prefix) {
118
 
                os_memcpy(rpos, "RESPONSE=", 9);
119
 
                rpos += 9;
120
 
                os_memcpy(rpos, identity, identity_len);
121
 
                rpos += identity_len;
122
 
                *rpos++ = '\0';
123
 
        }
124
 
        os_memcpy(rpos, password, password_len);
125
 
        wpa_hexdump_ascii_key(MSG_MSGDUMP, "EAP-GTC: Response",
126
 
                              (u8 *) (resp + 1) + 1, plen);
127
 
 
128
 
        if (otp) {
129
 
                wpa_printf(MSG_DEBUG, "EAP-GTC: Forgetting used password");
130
 
                eap_clear_config_otp(sm);
131
 
        }
132
 
 
133
 
        return (u8 *) resp;
134
 
}
135
 
 
136
 
 
137
 
int eap_peer_gtc_register(void)
138
 
{
139
 
        struct eap_method *eap;
140
 
        int ret;
141
 
 
142
 
        eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
143
 
                                    EAP_VENDOR_IETF, EAP_TYPE_GTC, "GTC");
144
 
        if (eap == NULL)
145
 
                return -1;
146
 
 
147
 
        eap->init = eap_gtc_init;
148
 
        eap->deinit = eap_gtc_deinit;
149
 
        eap->process = eap_gtc_process;
150
 
 
151
 
        ret = eap_peer_method_register(eap);
152
 
        if (ret)
153
 
                eap_peer_method_free(eap);
154
 
        return ret;
155
 
}