]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libcharon/plugins/xauth_generic/xauth_generic.c
Update copyright headers after acquisition by secunet
[thirdparty/strongswan.git] / src / libcharon / plugins / xauth_generic / xauth_generic.c
1 /*
2 * Copyright (C) 2011 Tobias Brunner
3 *
4 * Copyright (C) secunet Security Networks AG
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "xauth_generic.h"
18
19 #include <daemon.h>
20 #include <library.h>
21
22 typedef struct private_xauth_generic_t private_xauth_generic_t;
23
24 /**
25 * Private data of an xauth_generic_t object.
26 */
27 struct private_xauth_generic_t {
28
29 /**
30 * Public interface.
31 */
32 xauth_generic_t public;
33
34 /**
35 * ID of the server
36 */
37 identification_t *server;
38
39 /**
40 * ID of the peer
41 */
42 identification_t *peer;
43 };
44
45 METHOD(xauth_method_t, initiate_peer, status_t,
46 private_xauth_generic_t *this, cp_payload_t **out)
47 {
48 /* peer never initiates */
49 return FAILED;
50 }
51
52 METHOD(xauth_method_t, process_peer, status_t,
53 private_xauth_generic_t *this, cp_payload_t *in, cp_payload_t **out)
54 {
55 configuration_attribute_t *attr;
56 enumerator_t *enumerator;
57 shared_key_t *shared;
58 cp_payload_t *cp;
59 chunk_t msg;
60
61 enumerator = in->create_attribute_enumerator(in);
62 while (enumerator->enumerate(enumerator, &attr))
63 {
64 if (attr->get_type(attr) == XAUTH_MESSAGE)
65 {
66 chunk_printable(attr->get_chunk(attr), &msg, '?');
67 DBG1(DBG_CFG, "XAuth message: %.*s", (int)msg.len, msg.ptr);
68 free(msg.ptr);
69 }
70 }
71 enumerator->destroy(enumerator);
72
73 cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REPLY);
74
75 enumerator = in->create_attribute_enumerator(in);
76 while (enumerator->enumerate(enumerator, &attr))
77 {
78 shared_key_type_t type = SHARED_EAP;
79
80 switch (attr->get_type(attr))
81 {
82 case XAUTH_USER_NAME:
83 cp->add_attribute(cp, configuration_attribute_create_chunk(
84 PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME,
85 this->peer->get_encoding(this->peer)));
86 break;
87 case XAUTH_NEXT_PIN:
88 type = SHARED_PIN;
89 /* FALL */
90 case XAUTH_USER_PASSWORD:
91 shared = lib->credmgr->get_shared(lib->credmgr, type,
92 this->peer, this->server);
93 if (!shared)
94 {
95 DBG1(DBG_IKE, "no XAuth %s found for '%Y' - '%Y'",
96 type == SHARED_EAP ? "password" : "PIN",
97 this->peer, this->server);
98 enumerator->destroy(enumerator);
99 cp->destroy(cp);
100 return FAILED;
101 }
102 cp->add_attribute(cp, configuration_attribute_create_chunk(
103 PLV1_CONFIGURATION_ATTRIBUTE, attr->get_type(attr),
104 shared->get_key(shared)));
105 shared->destroy(shared);
106 break;
107 default:
108 break;
109 }
110 }
111 enumerator->destroy(enumerator);
112
113 *out = cp;
114 return NEED_MORE;
115 }
116
117 METHOD(xauth_method_t, initiate_server, status_t,
118 private_xauth_generic_t *this, cp_payload_t **out)
119 {
120 cp_payload_t *cp;
121
122 cp = cp_payload_create_type(PLV1_CONFIGURATION, CFG_REQUEST);
123 cp->add_attribute(cp, configuration_attribute_create_chunk(
124 PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_NAME, chunk_empty));
125 cp->add_attribute(cp, configuration_attribute_create_chunk(
126 PLV1_CONFIGURATION_ATTRIBUTE, XAUTH_USER_PASSWORD, chunk_empty));
127 *out = cp;
128 return NEED_MORE;
129 }
130
131 METHOD(xauth_method_t, process_server, status_t,
132 private_xauth_generic_t *this, cp_payload_t *in, cp_payload_t **out)
133 {
134 configuration_attribute_t *attr;
135 enumerator_t *enumerator;
136 shared_key_t *shared;
137 identification_t *id;
138 chunk_t user = chunk_empty, pass = chunk_empty;
139 status_t status = FAILED;
140 int tried = 0;
141
142 enumerator = in->create_attribute_enumerator(in);
143 while (enumerator->enumerate(enumerator, &attr))
144 {
145 switch (attr->get_type(attr))
146 {
147 case XAUTH_USER_NAME:
148 user = attr->get_chunk(attr);
149 break;
150 case XAUTH_USER_PASSWORD:
151 pass = attr->get_chunk(attr);
152 break;
153 default:
154 break;
155 }
156 }
157 enumerator->destroy(enumerator);
158
159 if (!user.ptr || !pass.ptr)
160 {
161 DBG1(DBG_IKE, "peer did not respond to our XAuth request");
162 return FAILED;
163 }
164 if (user.len)
165 {
166 id = identification_create_from_data(user);
167 if (!id)
168 {
169 DBG1(DBG_IKE, "failed to parse provided XAuth username");
170 return FAILED;
171 }
172 this->peer->destroy(this->peer);
173 this->peer = id;
174 }
175 if (pass.len && pass.ptr[pass.len - 1] == 0)
176 { /* fix null-terminated passwords (Android etc.) */
177 pass.len -= 1;
178 }
179
180 enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr,
181 SHARED_EAP, this->server, this->peer);
182 while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
183 {
184 if (chunk_equals_const(shared->get_key(shared), pass))
185 {
186 status = SUCCESS;
187 break;
188 }
189 tried++;
190 }
191 enumerator->destroy(enumerator);
192 if (status != SUCCESS)
193 {
194 if (!tried)
195 {
196 DBG1(DBG_IKE, "no XAuth secret found for '%Y' - '%Y'",
197 this->server, this->peer);
198 }
199 else
200 {
201 DBG1(DBG_IKE, "none of %d found XAuth secrets for '%Y' - '%Y' "
202 "matched", tried, this->server, this->peer);
203 }
204 }
205 return status;
206 }
207
208 METHOD(xauth_method_t, get_identity, identification_t*,
209 private_xauth_generic_t *this)
210 {
211 return this->peer;
212 }
213
214 METHOD(xauth_method_t, destroy, void,
215 private_xauth_generic_t *this)
216 {
217 this->server->destroy(this->server);
218 this->peer->destroy(this->peer);
219 free(this);
220 }
221
222 /*
223 * Described in header.
224 */
225 xauth_generic_t *xauth_generic_create_peer(identification_t *server,
226 identification_t *peer,
227 char *profile)
228 {
229 private_xauth_generic_t *this;
230
231 INIT(this,
232 .public = {
233 .xauth_method = {
234 .initiate = _initiate_peer,
235 .process = _process_peer,
236 .get_identity = _get_identity,
237 .destroy = _destroy,
238 },
239 },
240 .server = server->clone(server),
241 .peer = peer->clone(peer),
242 );
243
244 return &this->public;
245 }
246
247 /*
248 * Described in header.
249 */
250 xauth_generic_t *xauth_generic_create_server(identification_t *server,
251 identification_t *peer,
252 char *profile)
253 {
254 private_xauth_generic_t *this;
255
256 INIT(this,
257 .public = {
258 .xauth_method = {
259 .initiate = _initiate_server,
260 .process = _process_server,
261 .get_identity = _get_identity,
262 .destroy = _destroy,
263 },
264 },
265 .server = server->clone(server),
266 .peer = peer->clone(peer),
267 );
268
269 return &this->public;
270 }