ported parts of two-sim branch
[strongswan.git] / src / charon / plugins / eap_identity / eap_identity.c
1 /*
2 * Copyright (C) 2007-2008 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include "eap_identity.h"
19
20 #include <daemon.h>
21 #include <library.h>
22
23 typedef struct private_eap_identity_t private_eap_identity_t;
24
25 /**
26 * Private data of an eap_identity_t object.
27 */
28 struct private_eap_identity_t {
29
30 /**
31 * Public authenticator_t interface.
32 */
33 eap_identity_t public;
34
35 /**
36 * ID of the peer
37 */
38 identification_t *peer;
39
40 /**
41 * received identity chunk
42 */
43 chunk_t identity;
44 };
45
46 typedef struct eap_identity_header_t eap_identity_header_t;
47
48 /**
49 * packed EAP Identity header struct
50 */
51 struct eap_identity_header_t {
52 /** EAP code (REQUEST/RESPONSE) */
53 u_int8_t code;
54 /** unique message identifier */
55 u_int8_t identifier;
56 /** length of whole message */
57 u_int16_t length;
58 /** EAP type */
59 u_int8_t type;
60 /** identity data */
61 u_int8_t data[];
62 } __attribute__((__packed__));
63
64 /**
65 * Implementation of eap_method_t.process for the peer
66 */
67 static status_t process_peer(private_eap_identity_t *this,
68 eap_payload_t *in, eap_payload_t **out)
69 {
70 chunk_t id;
71 eap_identity_header_t *hdr;
72 size_t len;
73
74 id = this->peer->get_encoding(this->peer);
75 len = sizeof(eap_identity_header_t) + id.len;
76
77 hdr = alloca(len);
78 hdr->code = EAP_RESPONSE;
79 hdr->identifier = in->get_identifier(in);
80 hdr->length = htons(len);
81 hdr->type = EAP_IDENTITY;
82 memcpy(hdr->data, id.ptr, id.len);
83
84 *out = eap_payload_create_data(chunk_create((u_char*)hdr, len));
85 return SUCCESS;
86 }
87
88 /**
89 * Implementation of eap_method_t.initiate for the peer
90 */
91 static status_t initiate_peer(private_eap_identity_t *this, eap_payload_t **out)
92 {
93 /* peer never initiates */
94 return FAILED;
95 }
96
97 /**
98 * Implementation of eap_method_t.process for the server
99 */
100 static status_t process_server(private_eap_identity_t *this,
101 eap_payload_t *in, eap_payload_t **out)
102 {
103 chunk_t data;
104
105 data = chunk_skip(in->get_data(in), 5);
106 if (data.len)
107 {
108 this->identity = chunk_clone(data);
109 }
110 return SUCCESS;
111 }
112
113 /**
114 * Implementation of eap_method_t.initiate for the server
115 */
116 static status_t initiate_server(private_eap_identity_t *this, eap_payload_t **out)
117 {
118 eap_identity_header_t hdr;
119
120 hdr.code = EAP_REQUEST;
121 hdr.identifier = 0;
122 hdr.length = htons(sizeof(eap_identity_header_t));
123 hdr.type = EAP_IDENTITY;
124
125 *out = eap_payload_create_data(chunk_create((u_char*)&hdr,
126 sizeof(eap_identity_header_t)));
127 return NEED_MORE;
128 }
129
130 /**
131 * Implementation of eap_method_t.get_type.
132 */
133 static eap_type_t get_type(private_eap_identity_t *this, u_int32_t *vendor)
134 {
135 *vendor = 0;
136 return EAP_IDENTITY;
137 }
138
139 /**
140 * Implementation of eap_method_t.get_msk.
141 */
142 static status_t get_msk(private_eap_identity_t *this, chunk_t *msk)
143 {
144 if (this->identity.ptr)
145 {
146 *msk = this->identity;
147 return SUCCESS;
148 }
149 return FAILED;
150 }
151
152 /**
153 * Implementation of eap_method_t.is_mutual.
154 */
155 static bool is_mutual(private_eap_identity_t *this)
156 {
157 return FALSE;
158 }
159
160 /**
161 * Implementation of eap_method_t.destroy.
162 */
163 static void destroy(private_eap_identity_t *this)
164 {
165 this->peer->destroy(this->peer);
166 free(this->identity.ptr);
167 free(this);
168 }
169
170 /**
171 * Generic constructor
172 */
173 static private_eap_identity_t *eap_identity_create(identification_t *server,
174 identification_t *peer)
175 {
176 private_eap_identity_t *this = malloc_thing(private_eap_identity_t);
177
178 this->public.eap_method_interface.initiate = NULL;
179 this->public.eap_method_interface.process = NULL;
180 this->public.eap_method_interface.get_type = (eap_type_t(*)(eap_method_t*,u_int32_t*))get_type;
181 this->public.eap_method_interface.is_mutual = (bool(*)(eap_method_t*))is_mutual;
182 this->public.eap_method_interface.get_msk = (status_t(*)(eap_method_t*,chunk_t*))get_msk;
183 this->public.eap_method_interface.destroy = (void(*)(eap_method_t*))destroy;
184
185 this->peer = peer->clone(peer);
186 this->identity = chunk_empty;
187
188 return this;
189 }
190
191 /*
192 * Described in header.
193 */
194 eap_identity_t *eap_identity_create_peer(identification_t *server,
195 identification_t *peer)
196 {
197 private_eap_identity_t *this = eap_identity_create(server, peer);
198
199 /* public functions */
200 this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_peer;
201 this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_peer;
202
203 return &this->public;
204 }
205
206 /*
207 * Described in header.
208 */
209 eap_identity_t *eap_identity_create_server(identification_t *server,
210 identification_t *peer)
211 {
212 private_eap_identity_t *this = eap_identity_create(server, peer);
213
214 /* public functions */
215 this->public.eap_method_interface.initiate = (status_t(*)(eap_method_t*,eap_payload_t**))initiate_server;
216 this->public.eap_method_interface.process = (status_t(*)(eap_method_t*,eap_payload_t*,eap_payload_t**))process_server;
217
218 return &this->public;
219 }
220