]>
Commit | Line | Data |
---|---|---|
caf4b88e MW |
1 | /* |
2 | * Copyright (C) 2012 Martin Willi | |
19ef2aec TB |
3 | * |
4 | * Copyright (C) secunet Security Networks AG | |
caf4b88e MW |
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 "radattr_listener.h" | |
18 | ||
3ccc8a19 MW |
19 | #include <sys/types.h> |
20 | #include <sys/stat.h> | |
21 | #include <unistd.h> | |
22 | #include <fcntl.h> | |
3ccc8a19 MW |
23 | #include <errno.h> |
24 | ||
caf4b88e MW |
25 | #include <daemon.h> |
26 | ||
27 | #include <radius_message.h> | |
28 | ||
3ccc8a19 MW |
29 | /** |
30 | * Maximum size of an attribute to add | |
31 | */ | |
32 | #define MAX_ATTR_SIZE 1024 | |
33 | ||
caf4b88e MW |
34 | typedef struct private_radattr_listener_t private_radattr_listener_t; |
35 | ||
36 | /** | |
37 | * Private data of an radattr_listener_t object. | |
38 | */ | |
39 | struct private_radattr_listener_t { | |
40 | ||
41 | /** | |
42 | * Public radattr_listener_t interface. | |
43 | */ | |
44 | radattr_listener_t public; | |
3ccc8a19 MW |
45 | |
46 | /** | |
47 | * Directory to look for attribute files | |
48 | */ | |
49 | char *dir; | |
50 | ||
51 | /** | |
52 | * IKE_AUTH message ID to attribute | |
53 | */ | |
54 | int mid; | |
caf4b88e MW |
55 | }; |
56 | ||
57 | /** | |
58 | * Print RADIUS attributes found in IKE message notifies | |
59 | */ | |
60 | static void print_radius_attributes(private_radattr_listener_t *this, | |
61 | message_t *message) | |
62 | { | |
63 | radius_attribute_type_t type; | |
64 | enumerator_t *enumerator; | |
65 | notify_payload_t *notify; | |
66 | payload_t *payload; | |
67 | chunk_t data; | |
68 | ||
69 | enumerator = message->create_payload_enumerator(message); | |
70 | while (enumerator->enumerate(enumerator, &payload)) | |
71 | { | |
3ecfc83c | 72 | if (payload->get_type(payload) == PLV2_NOTIFY) |
caf4b88e MW |
73 | { |
74 | notify = (notify_payload_t*)payload; | |
75 | if (notify->get_notify_type(notify) == RADIUS_ATTRIBUTE) | |
76 | { | |
77 | data = notify->get_notification_data(notify); | |
78 | if (data.len >= 2) | |
79 | { | |
80 | type = data.ptr[0]; | |
81 | data = chunk_skip(data, 2); | |
82 | if (chunk_printable(data, NULL, 0)) | |
83 | { | |
84 | DBG1(DBG_IKE, "received RADIUS %N: %.*s", | |
85 | radius_attribute_type_names, type, | |
86 | (int)data.len, data.ptr); | |
87 | } | |
88 | else | |
89 | { | |
90 | DBG1(DBG_IKE, "received RADIUS %N: %#B", | |
91 | radius_attribute_type_names, type, &data); | |
92 | ||
93 | } | |
94 | } | |
95 | } | |
96 | } | |
97 | } | |
98 | enumerator->destroy(enumerator); | |
99 | } | |
100 | ||
3ccc8a19 MW |
101 | /** |
102 | * Add a RADIUS attribute from a client-ID specific file to an IKE message | |
103 | */ | |
104 | static void add_radius_attribute(private_radattr_listener_t *this, | |
2e3615e4 | 105 | ike_sa_t *ike_sa, message_t *message) |
3ccc8a19 | 106 | { |
bb0b2031 MW |
107 | if (this->dir && |
108 | (this->mid == -1 || message->get_message_id(message) == this->mid)) | |
3ccc8a19 | 109 | { |
2e3615e4 MW |
110 | identification_t *id; |
111 | auth_cfg_t *auth; | |
3ccc8a19 | 112 | char path[PATH_MAX]; |
b8d0103e | 113 | chunk_t *data; |
3ccc8a19 | 114 | |
2e3615e4 MW |
115 | auth = ike_sa->get_auth_cfg(ike_sa, TRUE); |
116 | id = auth->get(auth, AUTH_RULE_EAP_IDENTITY); | |
117 | if (!id) | |
118 | { | |
119 | id = ike_sa->get_my_id(ike_sa); | |
120 | } | |
121 | ||
3ccc8a19 | 122 | snprintf(path, sizeof(path), "%s/%Y", this->dir, id); |
b8d0103e MW |
123 | data = chunk_map(path, FALSE); |
124 | if (data) | |
3ccc8a19 | 125 | { |
b8d0103e | 126 | if (data->len >= 2) |
3ccc8a19 | 127 | { |
b8d0103e MW |
128 | DBG1(DBG_CFG, "adding RADIUS %N attribute", |
129 | radius_attribute_type_names, data->ptr[0]); | |
130 | message->add_notify(message, FALSE, RADIUS_ATTRIBUTE, *data); | |
3ccc8a19 | 131 | } |
b8d0103e | 132 | chunk_unmap(data); |
3ccc8a19 MW |
133 | } |
134 | else | |
135 | { | |
136 | DBG1(DBG_CFG, "reading RADIUS attribute '%s' failed: %s", | |
137 | path, strerror(errno)); | |
138 | } | |
139 | } | |
140 | } | |
141 | ||
caf4b88e MW |
142 | METHOD(listener_t, message, bool, |
143 | private_radattr_listener_t *this, | |
b1f2f05c | 144 | ike_sa_t *ike_sa, message_t *message, bool incoming, bool plain) |
caf4b88e | 145 | { |
b1f2f05c | 146 | if (plain && ike_sa->supports_extension(ike_sa, EXT_STRONGSWAN) && |
4bbd9430 | 147 | message->get_exchange_type(message) == IKE_AUTH && |
3ecfc83c | 148 | message->get_payload(message, PLV2_EAP)) |
caf4b88e MW |
149 | { |
150 | if (incoming) | |
151 | { | |
152 | print_radius_attributes(this, message); | |
153 | } | |
3ccc8a19 MW |
154 | else |
155 | { | |
2e3615e4 | 156 | add_radius_attribute(this, ike_sa, message); |
3ccc8a19 | 157 | } |
caf4b88e MW |
158 | } |
159 | return TRUE; | |
160 | } | |
161 | ||
162 | ||
163 | METHOD(radattr_listener_t, destroy, void, | |
164 | private_radattr_listener_t *this) | |
165 | { | |
166 | free(this); | |
167 | } | |
168 | ||
169 | /** | |
170 | * See header | |
171 | */ | |
172 | radattr_listener_t *radattr_listener_create() | |
173 | { | |
174 | private_radattr_listener_t *this; | |
175 | ||
176 | INIT(this, | |
177 | .public = { | |
178 | .listener = { | |
179 | .message = _message, | |
180 | }, | |
181 | .destroy = _destroy, | |
182 | }, | |
3ccc8a19 | 183 | .dir = lib->settings->get_str(lib->settings, |
d223fe80 | 184 | "%s.plugins.radattr.dir", NULL, lib->ns), |
3ccc8a19 | 185 | .mid = lib->settings->get_int(lib->settings, |
d223fe80 | 186 | "%s.plugins.radattr.message_id", -1, lib->ns), |
caf4b88e MW |
187 | ); |
188 | ||
189 | return &this->public; | |
190 | } |