981ab77d0ef31f65b321e3d6d91856fba76c75ba
[strongswan.git] / src / libcharon / plugins / xauth_generic / xauth_generic.c
1 /*
2 * Copyright (C) 2011 Tobias Brunner
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
16 #include "xauth_generic.h"
17
18 #include <daemon.h>
19 #include <library.h>
20
21 typedef struct private_xauth_generic_t private_xauth_generic_t;
22
23 /**
24 * Private data of an xauth_generic_t object.
25 */
26 struct private_xauth_generic_t {
27
28 /**
29 * Public interface.
30 */
31 xauth_generic_t public;
32
33 /**
34 * ID of the server
35 */
36 identification_t *server;
37
38 /**
39 * ID of the peer
40 */
41 identification_t *peer;
42
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 shared_key_t *shared;
56 cp_payload_t *cp;
57 chunk_t user, pass;
58
59 shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, this->peer,
60 this->server);
61 if (!shared)
62 {
63 DBG1(DBG_IKE, "no XAuth secret found for '%Y' - '%Y'", this->peer,
64 this->server);
65 return FAILED;
66 }
67
68 user = this->peer->get_encoding(this->peer);
69 pass = shared->get_key(shared);
70
71 cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REPLY);
72 cp->add_attribute(cp, configuration_attribute_create_chunk(
73 CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, user));
74 cp->add_attribute(cp, configuration_attribute_create_chunk(
75 CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, pass));
76 shared->destroy(shared);
77 *out = cp;
78 return NEED_MORE;
79 }
80
81 METHOD(xauth_method_t, initiate_server, status_t,
82 private_xauth_generic_t *this, cp_payload_t **out)
83 {
84 cp_payload_t *cp;
85
86 cp = cp_payload_create_type(CONFIGURATION_V1, CFG_REQUEST);
87 cp->add_attribute(cp, configuration_attribute_create_chunk(
88 CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_NAME, chunk_empty));
89 cp->add_attribute(cp, configuration_attribute_create_chunk(
90 CONFIGURATION_ATTRIBUTE_V1, XAUTH_USER_PASSWORD, chunk_empty));
91 *out = cp;
92 return NEED_MORE;
93 }
94
95 METHOD(xauth_method_t, process_server, status_t,
96 private_xauth_generic_t *this, cp_payload_t *in, cp_payload_t **out)
97 {
98 configuration_attribute_t *attr;
99 enumerator_t *enumerator;
100 shared_key_t *shared;
101 identification_t *id = NULL, *peer;
102 chunk_t user = chunk_empty, pass = chunk_empty;
103 status_t status = SUCCESS;
104
105 enumerator = in->create_attribute_enumerator(in);
106 while (enumerator->enumerate(enumerator, &attr))
107 {
108 switch (attr->get_type(attr))
109 {
110 case XAUTH_USER_NAME:
111 user = attr->get_chunk(attr);
112 break;
113 case XAUTH_USER_PASSWORD:
114 pass = attr->get_chunk(attr);
115 break;
116 default:
117 break;
118 }
119 }
120 enumerator->destroy(enumerator);
121
122 if (!user.ptr || !pass.ptr)
123 {
124 DBG1(DBG_IKE, "peer did not respond to our XAuth request");
125 return FAILED;
126 }
127 if (user.len)
128 {
129 id = identification_create_from_data(user);
130 if (!id)
131 {
132 DBG1(DBG_IKE, "failed to parse provided XAuth username");
133 return FAILED;
134 }
135 }
136
137 peer = id ?: this->peer;
138 shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, this->server,
139 peer);
140 if (!shared)
141 {
142 DBG1(DBG_IKE, "no XAuth secret found for '%Y' - '%Y'", this->server,
143 peer);
144 status = FAILED;
145 }
146 else if (!chunk_equals(shared->get_key(shared), pass))
147 {
148 DBG1(DBG_IKE, "failed to authenticate '%Y' with XAuth", peer);
149 status = FAILED;
150 }
151 else
152 {
153 DBG2(DBG_IKE, "authentication of '%Y' with XAuth successful", peer);
154 }
155 DESTROY_IF(shared);
156 DESTROY_IF(id);
157 return status;
158 }
159
160 METHOD(xauth_method_t, destroy, void,
161 private_xauth_generic_t *this)
162 {
163 this->server->destroy(this->server);
164 this->peer->destroy(this->peer);
165 free(this);
166 }
167
168 /*
169 * Described in header.
170 */
171 xauth_generic_t *xauth_generic_create_peer(identification_t *server,
172 identification_t *peer)
173 {
174 private_xauth_generic_t *this;
175
176 INIT(this,
177 .public = {
178 .xauth_method = {
179 .initiate = _initiate_peer,
180 .process = _process_peer,
181 .destroy = _destroy,
182 },
183 },
184 .server = server->clone(server),
185 .peer = peer->clone(peer),
186 );
187
188 return &this->public;
189 }
190
191 /*
192 * Described in header.
193 */
194 xauth_generic_t *xauth_generic_create_server(identification_t *server,
195 identification_t *peer)
196 {
197 private_xauth_generic_t *this;
198
199 INIT(this,
200 .public = {
201 .xauth_method = {
202 .initiate = _initiate_server,
203 .process = _process_server,
204 .destroy = _destroy,
205 },
206 },
207 .server = server->clone(server),
208 .peer = peer->clone(peer),
209 );
210
211 return &this->public;
212 }