]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/libcharon/plugins/error_notify/error_notify_listener.c
error-notify: Handle missing alerts
[people/ms/strongswan.git] / src / libcharon / plugins / error_notify / error_notify_listener.c
CommitLineData
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
20typedef struct private_error_notify_listener_t private_error_notify_listener_t;
21
22/**
23 * Private data of an error_notify_listener_t object.
24 */
25struct 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
38METHOD(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, &not_before, &not_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 &not_before, TRUE, &not_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
277METHOD(error_notify_listener_t, destroy, void,
278 private_error_notify_listener_t *this)
279{
280 free(this);
281}
282
283/**
284 * See header
285 */
286error_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}