I was rewrite this feature as plugin using your recommendations. Info about plugin:
After the last retransmit has been sent and the peer is considered dead ( plugin hooks ALERT_RETRANSMIT_SEND_TIMEOUT alert ), plugin sends an email with notification, which contains a name and an ip address of the dead peer, or( and ) executes external command with two arguments: dead peer name and ip address. System administrators may find it useful for configuring email alerts and customizing other actions.? > For now, > strongSwan supports some dpd actions such as 'clear', 'hold' and > 'restart'. The patch implements new dpdaction named 'script'. It means > that if no activity is detected, strongSwan executes external command > with the dead peer passed as the argument for the command. >> I don't agree with this approach. The actions are things to do with a >> particular CHILD_SA/policy not unrelated things like calling a script to >> email notifications. Instead, I propose you write a plugin that hooks >> the ALERT_RETRANSMIT_SEND_TIMEOUT alert to get notified after the last >> retransmit has been sent and the peer is considered dead. The plugin is >> then free to do whatever it likes (e.g. calling a script). >> Regards, >> Tobias
diff -Naur strongswan-5.3.5.orig/conf/Makefile.am strongswan-5.3.5/conf/Makefile.am --- strongswan-5.3.5.orig/conf/Makefile.am 2016-02-16 14:53:18.687943320 +0300 +++ strongswan-5.3.5/conf/Makefile.am 2016-02-16 14:56:51.266932642 +0300 @@ -32,6 +32,7 @@ plugins/bliss.opt \ plugins/certexpire.opt \ plugins/coupling.opt \ + plugins/dead-peer-notify.opt \ plugins/dhcp.opt \ plugins/dnscert.opt \ plugins/duplicheck.opt \ diff -Naur strongswan-5.3.5.orig/conf/plugins/dead-peer-notify.conf strongswan-5.3.5/conf/plugins/dead-peer-notify.conf --- strongswan-5.3.5.orig/conf/plugins/dead-peer-notify.conf 1970-01-01 03:00:00.000000000 +0300 +++ strongswan-5.3.5/conf/plugins/dead-peer-notify.conf 2016-02-16 14:56:51.266932642 +0300 @@ -0,0 +1,36 @@ +dead-peer-notify { + + # Whether to load the plugin. Can also be an integer to increase the + # priority of this plugin. + load = yes + + # Enable or disable sending notifications by email. + # send_email = no + + # Sender's email address. + # mail_from = + + # Recipient's email address. + # mail_to = + + # Sender's SMTP user name. + # mail_username = + + # Sender's SMTP password. + # mail_password = + + # SMTP server url. + # smtp_url = + + # Path to public certificate of the SMTP server. + # smtp_cacert = + + + # Enable or disable external command execution. + # run_command = no + + # Path to external command. + # command_path = + +} + diff -Naur strongswan-5.3.5.orig/conf/plugins/dead-peer-notify.opt strongswan-5.3.5/conf/plugins/dead-peer-notify.opt --- strongswan-5.3.5.orig/conf/plugins/dead-peer-notify.opt 1970-01-01 03:00:00.000000000 +0300 +++ strongswan-5.3.5/conf/plugins/dead-peer-notify.opt 2016-02-16 14:56:51.266932642 +0300 @@ -0,0 +1,40 @@ +charon.plugins.dead-peer-notify.send_email = no + Enable or disable sending notifications by email. + + Enable or disable sending notifications by email. + After the last retransmit has been sent and the peer is considered dead, + plugin sends an email with notification, which contains a name and an ip address of the dead peer. + +charon.plugins.dead-peer-notify.mail_from = + Sender's email address. + +charon.plugins.dead-peer-notify.mail_to = + Recipient's email address. + +charon.plugins.dead-peer-notify.mail_username = + Sender's SMTP user name. + +charon.plugins.dead-peer-notify.mail_password = + Sender's SMTP password. + +charon.plugins.dead-peer-notify.smtp_url = + SMTP server url. + + SMTP server url. Format: smtp://host:port. + Plugin supports only SSL/TLS connections. + (e.g. smtp://smtp.example.com:587) + +charon.plugins.dead-peer-notify.smtp_cacert = + Path to public certificate of the SMTP server. + (e.g. /etc/certs/mta_ca.pem) + +charon.plugins.dead-peer-notify.run_command = no + Enable or disable external command execution. + + Enable or disable external command execution. + After the last retransmit has been sent and the peer is considered dead, + plugin executes external command with two arguments: dead peer name and ip address. + +charon.plugins.dead-peer-notify.command_path = + Path to external command. + (e.g. /usr/local/bin/user_script.sh) diff -Naur strongswan-5.3.5.orig/configure.ac strongswan-5.3.5/configure.ac --- strongswan-5.3.5.orig/configure.ac 2016-02-16 14:53:18.686943320 +0300 +++ strongswan-5.3.5/configure.ac 2016-02-16 15:02:12.613916500 +0300 @@ -257,6 +257,7 @@ ARG_ENABL_SET([forecast], [enable forecast plugin forwarding broadcast/multicast messages.]) ARG_ENABL_SET([duplicheck], [advanced duplicate checking plugin using liveness checks.]) ARG_ENABL_SET([error-notify], [enable error notification plugin.]) +ARG_ENABL_SET([dead-peer-notify],[enable dead peer notification plugin.]) ARG_ENABL_SET([farp], [enable ARP faking plugin that responds to ARP requests to peers virtual IP]) ARG_ENABL_SET([ha], [enable high availability cluster plugin.]) ARG_ENABL_SET([led], [enable plugin to control LEDs on IKEv2 activity using the Linux kernel LED subsystem.]) @@ -908,6 +909,11 @@ AC_CHECK_HEADER([curl/curl.h],,[AC_MSG_ERROR([CURL header curl/curl.h not found!])]) fi +if test x$dead_peer_notify = xtrue; then + AC_CHECK_LIB([curl],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([CURL library curl not found])],[]) + AC_CHECK_HEADER([curl/curl.h],,[AC_MSG_ERROR([CURL header curl/curl.h not found!])]) +fi + if test x$unbound = xtrue; then AC_HAVE_LIBRARY([ldns],[LIBS="$LIBS"],[AC_MSG_ERROR([UNBOUND library ldns not found])]) AC_CHECK_HEADER([ldns/ldns.h],,[AC_MSG_ERROR([UNBOUND header ldns/ldns.h not found!])]) @@ -1391,6 +1397,7 @@ ADD_PLUGIN([ext-auth], [c charon]) ADD_PLUGIN([lookip], [c charon]) ADD_PLUGIN([error-notify], [c charon]) +ADD_PLUGIN([dead-peer-notify], [c charon]) ADD_PLUGIN([certexpire], [c charon]) ADD_PLUGIN([systime-fix], [c charon]) ADD_PLUGIN([led], [c charon]) @@ -1506,6 +1513,7 @@ AM_CONDITIONAL(USE_EXT_AUTH, test x$ext_auth = xtrue) AM_CONDITIONAL(USE_LOOKIP, test x$lookip = xtrue) AM_CONDITIONAL(USE_ERROR_NOTIFY, test x$error_notify = xtrue) +AM_CONDITIONAL(USE_DEAD_PEER_NOTIFY, test x$dead_peer_notify = xtrue) AM_CONDITIONAL(USE_CERTEXPIRE, test x$certexpire = xtrue) AM_CONDITIONAL(USE_SYSTIME_FIX, test x$systime_fix = xtrue) AM_CONDITIONAL(USE_LED, test x$led = xtrue) @@ -1822,6 +1830,7 @@ src/libcharon/plugins/ext_auth/Makefile src/libcharon/plugins/lookip/Makefile src/libcharon/plugins/error_notify/Makefile + src/libcharon/plugins/dead_peer_notify/Makefile src/libcharon/plugins/certexpire/Makefile src/libcharon/plugins/systime_fix/Makefile src/libcharon/plugins/led/Makefile diff -Naur strongswan-5.3.5.orig/src/libcharon/Makefile.am strongswan-5.3.5/src/libcharon/Makefile.am --- strongswan-5.3.5.orig/src/libcharon/Makefile.am 2016-02-16 14:53:18.645943322 +0300 +++ strongswan-5.3.5/src/libcharon/Makefile.am 2016-02-16 14:56:51.267932642 +0300 @@ -553,6 +553,13 @@ endif endif +if USE_DEAD_PEER_NOTIFY + SUBDIRS += plugins/dead_peer_notify +if MONOLITHIC + libcharon_la_LIBADD += plugins/dead_peer_notify/libstrongswan-dead-peer-notify.la +endif +endif + if USE_CERTEXPIRE SUBDIRS += plugins/certexpire if MONOLITHIC diff -Naur strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/Makefile.am strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/Makefile.am --- strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/Makefile.am 1970-01-01 03:00:00.000000000 +0300 +++ strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/Makefile.am 2016-02-16 14:56:51.267932642 +0300 @@ -0,0 +1,22 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-dead-peer-notify.la +else +plugin_LTLIBRARIES = libstrongswan-dead-peer-notify.la +endif + +libstrongswan_dead_peer_notify_la_SOURCES = \ + dead_peer_notify_plugin.h dead_peer_notify_plugin.c \ + dead_peer_notify_listener.h dead_peer_notify_listener.c \ + dead_peer_notify_mail.h dead_peer_notify_mail.c \ + dead_peer_notify_exec.h dead_peer_notify_exec.c + +libstrongswan_dead_peer_notify_la_LDFLAGS = -module -avoid-version +libstrongswan_dead_peer_notify_la_LIBADD = -lcurl diff -Naur strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_exec.c strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_exec.c --- strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_exec.c 1970-01-01 03:00:00.000000000 +0300 +++ strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_exec.c 2016-02-16 14:56:51.267932642 +0300 @@ -0,0 +1,143 @@ +/* vim: set ts=4 sw=4 noexpandtab: */ +/* + * Copyright (C) 2015 Pavel Balaev. + * Copyright (C) 2015 InfoTeCS JSC. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <sys/stat.h> + +#include <daemon.h> +#include "dead_peer_notify_exec.h" + +typedef struct private_dead_peer_notify_exec_t private_dead_peer_notify_exec_t; + +/** + * Private data of an dead_peer_notify_exec_t object. + */ +struct private_dead_peer_notify_exec_t { + + /** + * Public dead_peer_notify_exec_t interface. + */ + dead_peer_notify_exec_t public; + + /** + * Enable/disable execute external command flag. + */ + bool script_enabled; + + /** + * External command path. + */ + char *script_path; +}; + +METHOD(dead_peer_notify_exec_t, run, void, + private_dead_peer_notify_exec_t *this, const char *peer, const char *host) +{ + FILE *shell; + char command[1024]; + int cmd_len; + + memset(command, 0, sizeof(command)); + + if (!this->script_enabled) + { + return; + } + + cmd_len = snprintf(command, sizeof(command), "%s '%s' '%s'", + this->script_path, peer, host); + if (cmd_len >= sizeof(command) || cmd_len < 0) + { + DBG1(DBG_LIB, "external script path was truncated due to length limitation " + "of %lu characters", sizeof(command)); + DBG1(DBG_LIB, "could not execute external script"); + return; + } + DBG2(DBG_LIB, "trying to run external script: '%s'...", command); + + shell = popen(command, "r"); + if (shell == NULL) + { + DBG1(DBG_LIB, "could not execute external script"); + return; + } + if (pclose(shell) == -1) + { + DBG1(DBG_LIB, "pclose error: %s", strerror(errno)); + } +} + +METHOD(dead_peer_notify_exec_t, destroy, void, + private_dead_peer_notify_exec_t *this) +{ + free(this); +} + +/** + * See header + */ +dead_peer_notify_exec_t *dead_peer_notify_exec_create() +{ + private_dead_peer_notify_exec_t *this; + bool script_ok = true; + struct stat script_info; + + INIT(this, + .public = { + .run = _run, + .destroy = _destroy, + }, + ); + + this->script_enabled = lib->settings->get_bool(lib->settings, + "%s.plugins.dead-peer-notify.run_command", FALSE, + lib->ns); + if (this->script_enabled) + { + this->script_path = lib->settings->get_str(lib->settings, + "%s.plugins.dead-peer-notify.command_path", NULL, + lib->ns); + + if (!this->script_path) + { + DBG1(DBG_CFG, "no exetrnal command path set"); + script_ok = false; + } + else + { + if (stat(this->script_path, &script_info) == -1) + { + DBG1(DBG_CFG, "failed to read external command: %s", strerror(errno)); + script_ok = false; + } + else if (!(script_info.st_mode & S_IXUSR)) + { + DBG1(DBG_CFG, "script has no execute permission for owner"); + script_ok = false; + } + } + + if (!script_ok) + { + this->script_enabled = false; + DBG1(DBG_CFG, "execution of the external command is disabled"); + } + } + + return &this->public; +} diff -Naur strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_exec.h strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_exec.h --- strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_exec.h 1970-01-01 03:00:00.000000000 +0300 +++ strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_exec.h 2016-02-16 14:56:51.267932642 +0300 @@ -0,0 +1,51 @@ +/* vim: set ts=4 sw=4 noexpandtab: */ +/* + * Copyright (C) 2015 Pavel Balaev. + * Copyright (C) 2015 InfoTeCS JSC. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup dead_peer_notify_exec dead_peer_notify_exec + * @{ @ingroup dead_peer_notify + */ + +#ifndef DEAD_PEER_NOTIFY_EXEC_H_ +#define DEAD_PEER_NOTIFY_EXEC_H_ + +typedef struct dead_peer_notify_exec_t dead_peer_notify_exec_t; + +/** + * Execute command interface. + */ +struct dead_peer_notify_exec_t { + + /** + * Execute external command. + * + * @param peer peer name + * @param host host address + */ + void (*run)(dead_peer_notify_exec_t *this, const char *peer, const char *host); + + /** + * Destroy a dead_peer_notify_exec_t. + */ + void (*destroy)(dead_peer_notify_exec_t *this); +}; + +/** + * Create a dead_peer_notify_exec instance. + */ +dead_peer_notify_exec_t *dead_peer_notify_exec_create(); + +#endif /** DEAD_PEER_NOTIFY_EXEC_H_ @}*/ diff -Naur strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_listener.c strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_listener.c --- strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_listener.c 1970-01-01 03:00:00.000000000 +0300 +++ strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_listener.c 2016-02-16 14:56:51.267932642 +0300 @@ -0,0 +1,107 @@ +/* vim: set ts=4 sw=4 noexpandtab: */ +/* + * Copyright (C) 2015 Pavel Balaev. + * Copyright (C) 2015 InfoTeCS JSC. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "dead_peer_notify_listener.h" + +#include <daemon.h> + +typedef struct private_dead_peer_notify_listener_t private_dead_peer_notify_listener_t; + +/** + * Private data of an dead_peer_notify_listener_t object. + */ +struct private_dead_peer_notify_listener_t { + + /** + * Public dead_peer_notify_listener_t interface. + */ + dead_peer_notify_listener_t public; + + /** + * Send email interface. + */ + dead_peer_notify_mail_t *mail; + + /** + * Execute external command interface. + */ + dead_peer_notify_exec_t *script; +}; + +METHOD(listener_t, alert, bool, + private_dead_peer_notify_listener_t *this, ike_sa_t *ike_sa, + alert_t alert, va_list args) +{ + host_t *host; + peer_cfg_t *peer_cfg; + char host_str[64]; + + memset(host_str, 0, sizeof(host_str)); + + if (alert == ALERT_RETRANSMIT_SEND_TIMEOUT) + { + if (ike_sa) + { + peer_cfg = ike_sa->get_peer_cfg(ike_sa); + host = ike_sa->get_other_host(ike_sa); + + if (!host->is_anyaddr(host)) + { + snprintf(host_str, sizeof(host_str), "%#H", host); + } + else + { + snprintf(host_str, sizeof(host_str), "unknown"); + } + + if (peer_cfg) + { + this->mail->send_mail(this->mail, peer_cfg->get_name(peer_cfg), host_str); + this->script->run(this->script, peer_cfg->get_name(peer_cfg), host_str); + } + } + } + + return TRUE; +} + +METHOD(dead_peer_notify_listener_t, destroy, void, + private_dead_peer_notify_listener_t *this) +{ + free(this); +} + +/** + * See header + */ +dead_peer_notify_listener_t *dead_peer_notify_listener_create(dead_peer_notify_mail_t *m, + dead_peer_notify_exec_t *s) +{ + private_dead_peer_notify_listener_t *this; + + INIT(this, + .public = { + .listener = { + .alert = _alert, + }, + .destroy = _destroy, + }, + .mail = m, + .script = s, + ); + + return &this->public; +} diff -Naur strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_listener.h strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_listener.h --- strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_listener.h 1970-01-01 03:00:00.000000000 +0300 +++ strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_listener.h 2016-02-16 14:56:51.267932642 +0300 @@ -0,0 +1,53 @@ +/* vim: set ts=4 sw=4 noexpandtab: */ +/* + * Copyright (C) 2015 Pavel Balaev. + * Copyright (C) 2015 InfoTeCS JSC. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup dead_peer_notify_listener dead_peer_notify_listener + * @{ @ingroup dead_peer_notify + */ + +#ifndef DEAD_PEER_NOTIFY_LISTENER_H_ +#define DEAD_PEER_NOTIFY_LISTENER_H_ + +#include <bus/listeners/listener.h> +#include "dead_peer_notify_mail.h" +#include "dead_peer_notify_exec.h" + +typedef struct dead_peer_notify_listener_t dead_peer_notify_listener_t; + +/** + * Listener catching bus alerts. + */ +struct dead_peer_notify_listener_t { + + /** + * Implements listener_t interface. + */ + listener_t listener; + + /** + * Destroy a dead_peer_notify_listener_t. + */ + void (*destroy)(dead_peer_notify_listener_t *this); +}; + +/** + * Create a dead_peer_notify_listener instance. + */ +dead_peer_notify_listener_t *dead_peer_notify_listener_create(dead_peer_notify_mail_t *m, + dead_peer_notify_exec_t *s); + +#endif /** DEAD_PEER_NOTIFY_LISTENER_H_ @}*/ diff -Naur strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_mail.c strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_mail.c --- strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_mail.c 1970-01-01 03:00:00.000000000 +0300 +++ strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_mail.c 2016-02-16 14:56:51.267932642 +0300 @@ -0,0 +1,277 @@ +/* vim: set ts=4 sw=4 noexpandtab: */ +/* + * Copyright (C) 2015 Pavel Balaev. + * Copyright (C) 2015 InfoTeCS JSC. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <sys/stat.h> + +#include <curl/curl.h> + +#include <daemon.h> +#include "dead_peer_notify_mail.h" + +#define CONNECT_TIMEOUT 10 + +typedef struct private_dead_peer_notify_mail_t private_dead_peer_notify_mail_t; + +/** + * Private data of an dead_peer_notify_mail_t object. + */ +struct private_dead_peer_notify_mail_t { + + /** + * Public dead_peer_notify_mail_t interface. + */ + dead_peer_notify_mail_t public; + + /** + * CURL handle + */ + CURL* curl; + + /** + * Enable/disable email reports flag + */ + bool email_enabled; + + /** + * Sender email address + */ + char *mail_from; + + /** + * Recipient email address + */ + char *mail_to; + + /** + * MTA url + */ + char *smtp_url; + + /** + * MTA CA certificate path + */ + char *cacert_path; + + /** + * Sender email user name + */ + char *mail_user; + + /** + * Sender email user password + */ + char *mail_passwd; +}; + +/** + * Data to pass to curl callback + */ +typedef struct { + char *payload; + int len; + bool done; +} cb_data_t; + +/** + * Curl callback function + */ +static size_t curl_cb(void *ptr, size_t size, size_t nmemb, cb_data_t *data) +{ + cb_data_t *mail = (cb_data_t *) data; + + if (mail->len > size * nmemb || mail->len == 0) + { + return 0; + } + + if (!mail->done) + { + memcpy(ptr, mail->payload, mail->len); + mail->done = true; + return mail->len; + } + + return 0; +} + +METHOD(dead_peer_notify_mail_t, send_mail, void, + private_dead_peer_notify_mail_t *this, const char *peer, const char *host) +{ + CURLcode res = CURLE_OK; + char error[CURL_ERROR_SIZE]; + struct curl_slist *recipients = NULL; + char mail_payload[BUFSIZ]; + cb_data_t data; + time_t time_raw; + + if (!this->email_enabled) + { + return; + } + + if (this->curl) + { + time(&time_raw); + memset(mail_payload, 0, sizeof(mail_payload)); + data.len = snprintf(mail_payload, sizeof(mail_payload), + "%s<%s>\r\n%s<%s>\r\n%s\r\n\r\n%s (%s)%s%s\r\n\r\n%s\r\n", + "To: ", this->mail_to, "From: ", this->mail_from, + MAIL_SUBJ, peer, host, MAIL_BODY, ctime(&time_raw), MAIL_SIGN); + + if (data.len < 0) + { + data.len = 0; + data.payload = 0; + } + else + { + data.payload = mail_payload; + } + data.done = false; + + curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, error); + curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, FALSE); + curl_easy_setopt(this->curl, CURLOPT_USERNAME, this->mail_user); + curl_easy_setopt(this->curl, CURLOPT_PASSWORD, this->mail_passwd); + curl_easy_setopt(this->curl, CURLOPT_URL, this->smtp_url); + curl_easy_setopt(this->curl, CURLOPT_USE_SSL, (long) CURLUSESSL_ALL); + curl_easy_setopt(this->curl, CURLOPT_CAINFO, this->cacert_path); + curl_easy_setopt(this->curl, CURLOPT_MAIL_FROM, this->mail_from); + recipients = curl_slist_append(recipients, this->mail_to); + curl_easy_setopt(this->curl, CURLOPT_MAIL_RCPT, recipients); + curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, CONNECT_TIMEOUT); + curl_easy_setopt(this->curl, CURLOPT_READFUNCTION, (void *) curl_cb); + curl_easy_setopt(this->curl, CURLOPT_READDATA, &data); + curl_easy_setopt(this->curl, CURLOPT_UPLOAD, 1L); + + DBG2(DBG_LIB, "trying to send email via '%s'...", this->smtp_url); + res = curl_easy_perform(this->curl); + + if (res != CURLE_OK) + { + DBG1(DBG_LIB, "libcurl email send failed [%d]: %s", res, error); + } + + curl_slist_free_all(recipients); + } +} + +METHOD(dead_peer_notify_mail_t, destroy, void, + private_dead_peer_notify_mail_t *this) +{ + curl_easy_cleanup(this->curl); + free(this); +} + +/** + * See header + */ +dead_peer_notify_mail_t *dead_peer_notify_mail_create() +{ + private_dead_peer_notify_mail_t *this; + bool email_ok = true; + struct stat cert_info; + + INIT(this, + .public = { + .send_mail = _send_mail, + .destroy = _destroy, + }, + .curl = curl_easy_init(), + ); + + this->email_enabled = lib->settings->get_bool(lib->settings, + "%s.plugins.dead-peer-notify.send_email", FALSE, + lib->ns); + if (this->email_enabled) + { + this->mail_from = lib->settings->get_str(lib->settings, + "%s.plugins.dead-peer-notify.mail_from", NULL, + lib->ns); + this->mail_to = lib->settings->get_str(lib->settings, + "%s.plugins.dead-peer-notify.mail_to", NULL, + lib->ns); + this->smtp_url = lib->settings->get_str(lib->settings, + "%s.plugins.dead-peer-notify.smtp_url", NULL, + lib->ns); + this->cacert_path = lib->settings->get_str(lib->settings, + "%s.plugins.dead-peer-notify.smtp_cacert", NULL, + lib->ns); + this->mail_user = lib->settings->get_str(lib->settings, + "%s.plugins.dead-peer-notify.mail_username", NULL, + lib->ns); + this->mail_passwd = lib->settings->get_str(lib->settings, + "%s.plugins.dead-peer-notify.mail_password", NULL, + lib->ns); + if (!this->mail_from) + { + DBG1(DBG_CFG, "no sender email address set"); + email_ok = false; + } + if (!this->mail_to) + { + DBG1(DBG_CFG, "no recipient email address set"); + email_ok = false; + } + if (!this->smtp_url) + { + DBG1(DBG_CFG, "no MTA url address set"); + email_ok = false; + } + else + { + if (!strstr(this->smtp_url, "smtp://")) + { + DBG1(DBG_CFG, "invalid MTA url address format"); + email_ok = false; + } + } + if (!this->cacert_path) + { + DBG1(DBG_CFG, "no MTA CA certificate path set"); + email_ok = false; + } + else + { + if (stat(this->cacert_path, &cert_info) == -1) + { + DBG1(DBG_CFG, "error read MTA CA certificate: %s", strerror(errno)); + email_ok = false; + } + } + if (!this->mail_user) + { + DBG1(DBG_CFG, "no sender email username set"); + email_ok = false; + } + if (!this->mail_passwd) + { + DBG1(DBG_CFG, "no sender email password set"); + email_ok = false; + } + + if (!email_ok) + { + this->email_enabled = false; + DBG1(DBG_CFG, "email reports disabled"); + } + } + + return &this->public; +} diff -Naur strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_mail.h strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_mail.h --- strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_mail.h 1970-01-01 03:00:00.000000000 +0300 +++ strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_mail.h 2016-02-16 14:56:51.268932642 +0300 @@ -0,0 +1,55 @@ +/* vim: set ts=4 sw=4 noexpandtab: */ +/* + * Copyright (C) 2015 Pavel Balaev. + * Copyright (C) 2015 InfoTeCS JSC. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup dead_peer_notify_mail dead_peer_notify_mail + * @{ @ingroup dead_peer_notify + */ + +#ifndef DEAD_PEER_NOTIFY_MAIL_H_ +#define DEAD_PEER_NOTIFY_MAIL_H_ + +#define MAIL_SUBJ "Subject: strongSwan notification" +#define MAIL_BODY " shut down at " +#define MAIL_SIGN "This message was sent by dead-peer-notify plugin" + +typedef struct dead_peer_notify_mail_t dead_peer_notify_mail_t; + +/** + * Send email interface. + */ +struct dead_peer_notify_mail_t { + + /** + * Send a notification email. + * + * @param peer peer name + * @param host host address + */ + void (*send_mail)(dead_peer_notify_mail_t *this, const char *peer, const char *host); + + /** + * Destroy a dead_peer_notify_mail_t. + */ + void (*destroy)(dead_peer_notify_mail_t *this); +}; + +/** + * Create a dead_peer_notify_mail instance. + */ +dead_peer_notify_mail_t *dead_peer_notify_mail_create(); + +#endif /** DEAD_PEER_NOTIFY_MAIL_H_ @}*/ diff -Naur strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_plugin.c strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_plugin.c --- strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_plugin.c 1970-01-01 03:00:00.000000000 +0300 +++ strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_plugin.c 2016-02-16 14:56:51.268932642 +0300 @@ -0,0 +1,116 @@ +/* vim: set ts=4 sw=4 noexpandtab: */ +/* + * Copyright (C) 2015 Pavel Balaev. + * Copyright (C) 2015 InfoTeCS JSC. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "dead_peer_notify_plugin.h" +#include "dead_peer_notify_listener.h" +#include "dead_peer_notify_mail.h" + +#include <daemon.h> + +typedef struct private_dead_peer_notify_plugin_t private_dead_peer_notify_plugin_t; + +/** + * private data of dead_peer_notify plugin + */ +struct private_dead_peer_notify_plugin_t { + + /** + * Implements plugin interface + */ + dead_peer_notify_plugin_t public; + + /** + * Listener catching error alerts + */ + dead_peer_notify_listener_t *listener; + + /** + * Email send instance + */ + dead_peer_notify_mail_t *mail; + + /** + * External command instance + */ + dead_peer_notify_exec_t *script; +}; + +METHOD(plugin_t, get_name, char*, + private_dead_peer_notify_plugin_t *this) +{ + return "dead-peer-notify"; +} + +/** + * Register listener + */ +static bool plugin_cb(private_dead_peer_notify_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->listener->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->listener->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_dead_peer_notify_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "dead-peer-notify"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_dead_peer_notify_plugin_t *this) +{ + this->listener->destroy(this->listener); + this->mail->destroy(this->mail); + this->script->destroy(this->script); + free(this); +} + +/** + * Plugin constructor + */ +plugin_t *dead_peer_notify_plugin_create() +{ + private_dead_peer_notify_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + .mail = dead_peer_notify_mail_create(), + .script = dead_peer_notify_exec_create(), + ); + + this->listener = dead_peer_notify_listener_create(this->mail, this->script); + + return &this->public.plugin; +} diff -Naur strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_plugin.h strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_plugin.h --- strongswan-5.3.5.orig/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_plugin.h 1970-01-01 03:00:00.000000000 +0300 +++ strongswan-5.3.5/src/libcharon/plugins/dead_peer_notify/dead_peer_notify_plugin.h 2016-02-16 14:56:51.268932642 +0300 @@ -0,0 +1,43 @@ +/* vim: set ts=4 sw=4 noexpandtab: */ +/* + * Copyright (C) 2015 Pavel Balaev. + * Copyright (C) 2015 InfoTeCS JSC. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup dead_peer_notify dead_peer_notify + * @ingroup cplugins + * + * @defgroup dead_peer_notify_plugin dead_peer_notify_plugin + * @{ @ingroup dead_peer_notify + */ + +#ifndef DEAD_PEER_NOTIFY_PLUGIN_H_ +#define DEAD_PEER_NOTIFY_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct dead_peer_notify_plugin_t dead_peer_notify_plugin_t; + +/** + * Plugin sending error notifications over a UNIX socket. + */ +struct dead_peer_notify_plugin_t { + + /** + * Implements plugin interface. + */ + plugin_t plugin; +}; + +#endif /** DEAD_PEER_NOTIFY_PLUGIN_H_ @}*/
_______________________________________________ Dev mailing list Dev@lists.strongswan.org https://lists.strongswan.org/mailman/listinfo/dev