]>
Commit | Line | Data |
---|---|---|
0aaf5ccf MW |
1 | /* |
2 | * Copyright (C) 2012 Martin Willi | |
3 | * Copyright (C) 2012 revosec AG | |
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 "error_notify_listener.h" | |
17 | ||
18 | #include <daemon.h> | |
19 | ||
20 | typedef struct private_error_notify_listener_t private_error_notify_listener_t; | |
21 | ||
22 | /** | |
23 | * Private data of an error_notify_listener_t object. | |
24 | */ | |
25 | struct private_error_notify_listener_t { | |
26 | ||
27 | /** | |
28 | * Public error_notify_listener_t interface. | |
29 | */ | |
30 | error_notify_listener_t public; | |
31 | ||
32 | /** | |
33 | * Socket to send notifications over | |
34 | */ | |
35 | error_notify_socket_t *socket; | |
36 | }; | |
37 | ||
38 | METHOD(listener_t, alert, bool, | |
39 | private_error_notify_listener_t *this, ike_sa_t *ike_sa, | |
40 | alert_t alert, va_list args) | |
41 | { | |
42 | error_notify_msg_t msg; | |
43 | message_t *message; | |
44 | host_t *host; | |
45 | identification_t *id; | |
46 | linked_list_t *list, *list2; | |
47 | peer_cfg_t *peer_cfg; | |
868abd06 MW |
48 | certificate_t *cert; |
49 | time_t not_before, not_after; | |
801bb853 | 50 | int num; |
0aaf5ccf MW |
51 | |
52 | if (!this->socket->has_listeners(this->socket)) | |
53 | { | |
54 | return TRUE; | |
55 | } | |
56 | ||
57 | memset(&msg, 0, sizeof(msg)); | |
58 | ||
59 | switch (alert) | |
60 | { | |
61 | case ALERT_RADIUS_NOT_RESPONDING: | |
c2a6fdf2 | 62 | msg.type = htonl(ERROR_NOTIFY_RADIUS_NOT_RESPONDING); |
0aaf5ccf MW |
63 | snprintf(msg.str, sizeof(msg.str), |
64 | "a RADIUS request message timed out"); | |
65 | break; | |
66 | case ALERT_LOCAL_AUTH_FAILED: | |
c2a6fdf2 | 67 | msg.type = htonl(ERROR_NOTIFY_LOCAL_AUTH_FAILED); |
801bb853 | 68 | snprintf(msg.str, sizeof(msg.str), "local authentication failed"); |
0aaf5ccf MW |
69 | break; |
70 | case ALERT_PEER_AUTH_FAILED: | |
c2a6fdf2 | 71 | msg.type = htonl(ERROR_NOTIFY_PEER_AUTH_FAILED); |
0aaf5ccf MW |
72 | snprintf(msg.str, sizeof(msg.str), "peer authentication failed"); |
73 | break; | |
801bb853 TB |
74 | case ALERT_PEER_ADDR_FAILED: |
75 | msg.type = htonl(ERROR_NOTIFY_PEER_ADDR_FAILED); | |
76 | snprintf(msg.str, sizeof(msg.str), "failed to resolve peer address"); | |
77 | break; | |
78 | case ALERT_PEER_INIT_UNREACHABLE: | |
79 | msg.type = htonl(ERROR_NOTIFY_PEER_INIT_UNREACHABLE); | |
80 | num = va_arg(args, int) + 1; | |
81 | snprintf(msg.str, sizeof(msg.str), "peer did not respond to initial " | |
82 | "message, try %d", num); | |
83 | break; | |
84 | case ALERT_INVALID_IKE_SPI: | |
85 | msg.type = htonl(ERROR_NOTIFY_INVALID_IKE_SPI); | |
86 | message = va_arg(args, message_t*); | |
87 | snprintf(msg.str, sizeof(msg.str), "received IKE message with unknown " | |
88 | "SPI from %#H", message->get_source(message)); | |
89 | break; | |
0aaf5ccf | 90 | case ALERT_PARSE_ERROR_HEADER: |
c2a6fdf2 | 91 | msg.type = htonl(ERROR_NOTIFY_PARSE_ERROR_HEADER); |
0aaf5ccf MW |
92 | message = va_arg(args, message_t*); |
93 | snprintf(msg.str, sizeof(msg.str), "parsing IKE header from " | |
94 | "%#H failed", message->get_source(message)); | |
95 | break; | |
96 | case ALERT_PARSE_ERROR_BODY: | |
c2a6fdf2 | 97 | msg.type = htonl(ERROR_NOTIFY_PARSE_ERROR_BODY); |
0aaf5ccf MW |
98 | message = va_arg(args, message_t*); |
99 | snprintf(msg.str, sizeof(msg.str), "parsing IKE message from " | |
100 | "%#H failed", message->get_source(message)); | |
101 | break; | |
aa6d4a3d TE |
102 | case ALERT_RETRANSMIT_SEND: |
103 | msg.type = htonl(ERROR_NOTIFY_RETRANSMIT_SEND); | |
801bb853 | 104 | va_arg(args, packet_t*); |
aa6d4a3d TE |
105 | snprintf(msg.str, sizeof(msg.str), "IKE message retransmission " |
106 | "number %u", va_arg(args, u_int)); | |
107 | break; | |
801bb853 TB |
108 | case ALERT_RETRANSMIT_SEND_CLEARED: |
109 | msg.type = htonl(ERROR_NOTIFY_RETRANSMIT_CLEARED); | |
110 | snprintf(msg.str, sizeof(msg.str), "IKE response received after " | |
111 | "retransmission"); | |
112 | break; | |
0aaf5ccf | 113 | case ALERT_RETRANSMIT_SEND_TIMEOUT: |
c2a6fdf2 | 114 | msg.type = htonl(ERROR_NOTIFY_RETRANSMIT_SEND_TIMEOUT); |
0aaf5ccf MW |
115 | snprintf(msg.str, sizeof(msg.str), |
116 | "IKE message retransmission timed out"); | |
117 | break; | |
801bb853 TB |
118 | case ALERT_RETRANSMIT_RECEIVE: |
119 | msg.type = htonl(ERROR_NOTIFY_RETRANSMIT_RECEIVE); | |
120 | message = va_arg(args, message_t*); | |
121 | snprintf(msg.str, sizeof(msg.str), "received retransmit of request " | |
122 | "with ID %d from %#H", message->get_message_id(message), | |
123 | message->get_source(message)); | |
124 | break; | |
0aaf5ccf | 125 | case ALERT_HALF_OPEN_TIMEOUT: |
c2a6fdf2 | 126 | msg.type = htonl(ERROR_NOTIFY_HALF_OPEN_TIMEOUT); |
0aaf5ccf MW |
127 | snprintf(msg.str, sizeof(msg.str), "IKE_SA timed out before it " |
128 | "could be established"); | |
129 | break; | |
130 | case ALERT_PROPOSAL_MISMATCH_IKE: | |
c2a6fdf2 | 131 | msg.type = htonl(ERROR_NOTIFY_PROPOSAL_MISMATCH_IKE); |
0aaf5ccf | 132 | list = va_arg(args, linked_list_t*); |
f809e485 | 133 | snprintf(msg.str, sizeof(msg.str), "the received IKE_SA proposals " |
0aaf5ccf MW |
134 | "did not match: %#P", list); |
135 | break; | |
136 | case ALERT_PROPOSAL_MISMATCH_CHILD: | |
c2a6fdf2 | 137 | msg.type = htonl(ERROR_NOTIFY_PROPOSAL_MISMATCH_CHILD); |
0aaf5ccf | 138 | list = va_arg(args, linked_list_t*); |
f809e485 | 139 | snprintf(msg.str, sizeof(msg.str), "the received CHILD_SA proposals " |
0aaf5ccf MW |
140 | "did not match: %#P", list); |
141 | break; | |
142 | case ALERT_TS_MISMATCH: | |
c2a6fdf2 | 143 | msg.type = htonl(ERROR_NOTIFY_TS_MISMATCH); |
0aaf5ccf MW |
144 | list = va_arg(args, linked_list_t*); |
145 | list2 = va_arg(args, linked_list_t*); | |
146 | snprintf(msg.str, sizeof(msg.str), "the received traffic selectors " | |
ebeb8c87 | 147 | "did not match: %#R === %#R", list, list2); |
0aaf5ccf | 148 | break; |
801bb853 TB |
149 | case ALERT_TS_NARROWED: |
150 | msg.type = htonl(ERROR_NOTIFY_TS_NARROWED); | |
151 | num = va_arg(args, int); | |
152 | list = va_arg(args, linked_list_t*); | |
153 | snprintf(msg.str, sizeof(msg.str), "%s traffic selectors narrowed " | |
154 | "to %#R", num ? "local" : "remote", list); | |
155 | break; | |
0aaf5ccf | 156 | case ALERT_INSTALL_CHILD_SA_FAILED: |
c2a6fdf2 | 157 | msg.type = htonl(ERROR_NOTIFY_INSTALL_CHILD_SA_FAILED); |
0aaf5ccf MW |
158 | snprintf(msg.str, sizeof(msg.str), "installing IPsec SA failed"); |
159 | break; | |
160 | case ALERT_INSTALL_CHILD_POLICY_FAILED: | |
c2a6fdf2 | 161 | msg.type = htonl(ERROR_NOTIFY_INSTALL_CHILD_POLICY_FAILED); |
0aaf5ccf MW |
162 | snprintf(msg.str, sizeof(msg.str), "installing IPsec policy failed"); |
163 | break; | |
164 | case ALERT_UNIQUE_REPLACE: | |
c2a6fdf2 | 165 | msg.type = htonl(ERROR_NOTIFY_UNIQUE_REPLACE); |
0aaf5ccf MW |
166 | snprintf(msg.str, sizeof(msg.str), |
167 | "replaced old IKE_SA due to uniqueness policy"); | |
168 | break; | |
169 | case ALERT_UNIQUE_KEEP: | |
c2a6fdf2 | 170 | msg.type = htonl(ERROR_NOTIFY_UNIQUE_KEEP); |
0aaf5ccf MW |
171 | snprintf(msg.str, sizeof(msg.str), "keep existing in favor of " |
172 | "rejected new IKE_SA due to uniqueness policy"); | |
173 | break; | |
801bb853 TB |
174 | case ALERT_KEEP_ON_CHILD_SA_FAILURE: |
175 | msg.type = htonl(ERROR_NOTIFY_KEEP_ON_CHILD_SA_FAILURE); | |
176 | num = va_arg(args, int); | |
177 | snprintf(msg.str, sizeof(msg.str), "keeping IKE_SA after failing to " | |
178 | "establish %sCHILD_SA", num ? "first " : ""); | |
179 | break; | |
0aaf5ccf | 180 | case ALERT_VIP_FAILURE: |
c2a6fdf2 | 181 | msg.type = htonl(ERROR_NOTIFY_VIP_FAILURE); |
0aaf5ccf MW |
182 | list = va_arg(args, linked_list_t*); |
183 | if (list->get_first(list, (void**)&host) == SUCCESS) | |
184 | { | |
185 | snprintf(msg.str, sizeof(msg.str), | |
186 | "allocating a virtual IP failed, requested was %H", host); | |
187 | } | |
188 | else | |
189 | { | |
190 | snprintf(msg.str, sizeof(msg.str), | |
191 | "expected a virtual IP request, but none found"); | |
192 | } | |
193 | break; | |
194 | case ALERT_AUTHORIZATION_FAILED: | |
c2a6fdf2 | 195 | msg.type = htonl(ERROR_NOTIFY_AUTHORIZATION_FAILED); |
0aaf5ccf MW |
196 | snprintf(msg.str, sizeof(msg.str), "an authorization plugin " |
197 | "prevented establishment of an IKE_SA"); | |
198 | break; | |
801bb853 TB |
199 | case ALERT_IKE_SA_EXPIRED: |
200 | msg.type = htonl(ERROR_NOTIFY_IKE_SA_EXPIRED); | |
201 | snprintf(msg.str, sizeof(msg.str), "IKE_SA expired without " | |
202 | "replacement"); | |
203 | break; | |
868abd06 MW |
204 | case ALERT_CERT_EXPIRED: |
205 | msg.type = htonl(ERROR_NOTIFY_CERT_EXPIRED); | |
206 | cert = va_arg(args, certificate_t*); | |
207 | cert->get_validity(cert, NULL, ¬_before, ¬_after); | |
f809e485 | 208 | snprintf(msg.str, sizeof(msg.str), "certificate expired: '%Y' " |
868abd06 MW |
209 | "(valid from %T to %T)", cert->get_subject(cert), |
210 | ¬_before, TRUE, ¬_after, TRUE); | |
211 | break; | |
212 | case ALERT_CERT_REVOKED: | |
213 | msg.type = htonl(ERROR_NOTIFY_CERT_REVOKED); | |
214 | cert = va_arg(args, certificate_t*); | |
f809e485 | 215 | snprintf(msg.str, sizeof(msg.str), "certificate revoked: '%Y'", |
868abd06 MW |
216 | cert->get_subject(cert)); |
217 | break; | |
801bb853 TB |
218 | case ALERT_CERT_VALIDATION_FAILED: |
219 | msg.type = htonl(ERROR_NOTIFY_CERT_VALIDATION_FAILED); | |
220 | cert = va_arg(args, certificate_t*); | |
221 | snprintf(msg.str, sizeof(msg.str), "failed to validate certificate " | |
222 | "status: '%Y'", cert->get_subject(cert)); | |
223 | break; | |
868abd06 MW |
224 | case ALERT_CERT_NO_ISSUER: |
225 | msg.type = htonl(ERROR_NOTIFY_NO_ISSUER_CERT); | |
226 | cert = va_arg(args, certificate_t*); | |
227 | snprintf(msg.str, sizeof(msg.str), "no trusted issuer certificate " | |
228 | "found: '%Y'", cert->get_issuer(cert)); | |
229 | break; | |
801bb853 TB |
230 | case ALERT_CERT_UNTRUSTED_ROOT: |
231 | msg.type = htonl(ERROR_NOTIFY_UNTRUSTED_ROOT_CERT); | |
232 | cert = va_arg(args, certificate_t*); | |
233 | snprintf(msg.str, sizeof(msg.str), "self-signed issuer certificate " | |
234 | "is not trusted: '%Y'", cert->get_issuer(cert)); | |
235 | break; | |
236 | case ALERT_CERT_EXCEEDED_PATH_LEN: | |
237 | msg.type = htonl(ERROR_NOTIFY_CERT_EXCEEDED_PATH_LEN); | |
238 | cert = va_arg(args, certificate_t*); | |
239 | snprintf(msg.str, sizeof(msg.str), "maximum path length in trust " | |
240 | "chain exceeded: '%Y'", cert->get_issuer(cert)); | |
241 | break; | |
242 | case ALERT_CERT_POLICY_VIOLATION: | |
243 | msg.type = htonl(ERROR_NOTIFY_CERT_POLICY_VIOLATION); | |
244 | cert = va_arg(args, certificate_t*); | |
245 | snprintf(msg.str, sizeof(msg.str), "certificate rejected because of " | |
246 | "policy violation: '%Y'", cert->get_issuer(cert)); | |
247 | break; | |
248 | case ALERT_SHUTDOWN_SIGNAL: | |
0aaf5ccf MW |
249 | return TRUE; |
250 | } | |
251 | ||
252 | if (ike_sa) | |
253 | { | |
254 | id = ike_sa->get_other_eap_id(ike_sa); | |
255 | if (id->get_type(id) != ID_ANY) | |
256 | { | |
257 | snprintf(msg.id, sizeof(msg.id), "%Y", id); | |
258 | } | |
259 | host = ike_sa->get_other_host(ike_sa); | |
260 | if (!host->is_anyaddr(host)) | |
261 | { | |
262 | snprintf(msg.ip, sizeof(msg.ip), "%#H", host); | |
263 | } | |
264 | peer_cfg = ike_sa->get_peer_cfg(ike_sa); | |
265 | if (peer_cfg) | |
266 | { | |
267 | snprintf(msg.name, sizeof(msg.name), "%s", | |
268 | peer_cfg->get_name(peer_cfg)); | |
269 | } | |
270 | } | |
271 | ||
272 | this->socket->notify(this->socket, &msg); | |
273 | ||
274 | return TRUE; | |
275 | } | |
276 | ||
277 | METHOD(error_notify_listener_t, destroy, void, | |
278 | private_error_notify_listener_t *this) | |
279 | { | |
280 | free(this); | |
281 | } | |
282 | ||
283 | /** | |
284 | * See header | |
285 | */ | |
286 | error_notify_listener_t *error_notify_listener_create(error_notify_socket_t *s) | |
287 | { | |
288 | private_error_notify_listener_t *this; | |
289 | ||
290 | INIT(this, | |
291 | .public = { | |
292 | .listener = { | |
293 | .alert = _alert, | |
294 | }, | |
295 | .destroy = _destroy, | |
296 | }, | |
297 | .socket = s, | |
298 | ); | |
299 | ||
300 | return &this->public; | |
301 | } |