Implemented an alternative HTTP fetcher based on libsoup
authorMartin Willi <martin@revosec.ch>
Mon, 17 Jan 2011 12:27:18 +0000 (13:27 +0100)
committerMartin Willi <martin@revosec.ch>
Mon, 17 Jan 2011 17:20:06 +0000 (18:20 +0100)
configure.in
src/libstrongswan/Makefile.am
src/libstrongswan/plugins/soup/Makefile.am [new file with mode: 0644]
src/libstrongswan/plugins/soup/soup_fetcher.c [new file with mode: 0644]
src/libstrongswan/plugins/soup/soup_fetcher.h [new file with mode: 0644]
src/libstrongswan/plugins/soup/soup_plugin.c [new file with mode: 0644]
src/libstrongswan/plugins/soup/soup_plugin.h [new file with mode: 0644]

index 9a7f8d8..4c972db 100644 (file)
@@ -66,6 +66,7 @@ AC_ARG_WITH(
 m4_include(m4/macros/enable-disable.m4)
 
 ARG_ENABL_SET([curl],           [enable CURL fetcher plugin to fetch files via libcurl. Requires libcurl.])
 m4_include(m4/macros/enable-disable.m4)
 
 ARG_ENABL_SET([curl],           [enable CURL fetcher plugin to fetch files via libcurl. Requires libcurl.])
+ARG_ENABL_SET([soup],           [enable soup fetcher plugin to fetch from HTTP via libsoup. Requires libsoup.])
 ARG_ENABL_SET([ldap],           [enable LDAP fetching plugin to fetch files via libldap. Requires openLDAP.])
 ARG_DISBL_SET([aes],            [disable AES software implementation plugin.])
 ARG_DISBL_SET([des],            [disable DES/3DES software implementation plugin.])
 ARG_ENABL_SET([ldap],           [enable LDAP fetching plugin to fetch files via libldap. Requires openLDAP.])
 ARG_DISBL_SET([aes],            [disable AES software implementation plugin.])
 ARG_DISBL_SET([des],            [disable DES/3DES software implementation plugin.])
@@ -498,6 +499,12 @@ if test x$curl = xtrue; then
        AC_CHECK_HEADER([curl/curl.h],,[AC_MSG_ERROR([CURL header curl/curl.h not found!])])
 fi
 
        AC_CHECK_HEADER([curl/curl.h],,[AC_MSG_ERROR([CURL header curl/curl.h not found!])])
 fi
 
+if test x$soup = xtrue; then
+       PKG_CHECK_MODULES(soup, [libsoup-2.4])
+       AC_SUBST(soup_CFLAGS)
+       AC_SUBST(soup_LIBS)
+fi
+
 if test x$xml = xtrue; then
        PKG_CHECK_MODULES(xml, [libxml-2.0])
        AC_SUBST(xml_CFLAGS)
 if test x$xml = xtrue; then
        PKG_CHECK_MODULES(xml, [libxml-2.0])
        AC_SUBST(xml_CFLAGS)
@@ -689,8 +696,9 @@ h_plugins=
 s_plugins=
 
 ADD_PLUGIN([test-vectors],         [s libcharon pluto openac scepclient pki])
 s_plugins=
 
 ADD_PLUGIN([test-vectors],         [s libcharon pluto openac scepclient pki])
-ADD_PLUGIN([curl],                 [s libcharon pluto scepclient])
-ADD_PLUGIN([ldap],                 [s libcharon pluto scepclient])
+ADD_PLUGIN([curl],                 [s libcharon pluto scepclient scripts])
+ADD_PLUGIN([soup],                 [s libcharon pluto scripts])
+ADD_PLUGIN([ldap],                 [s libcharon pluto scepclient scripts])
 ADD_PLUGIN([mysql],                [s libcharon pluto pool manager medsrv])
 ADD_PLUGIN([sqlite],               [s libcharon pluto pool manager medsrv])
 ADD_PLUGIN([aes],                  [s libcharon pluto openac scepclient pki scripts])
 ADD_PLUGIN([mysql],                [s libcharon pluto pool manager medsrv])
 ADD_PLUGIN([sqlite],               [s libcharon pluto pool manager medsrv])
 ADD_PLUGIN([aes],                  [s libcharon pluto openac scepclient pki scripts])
@@ -793,6 +801,7 @@ dnl libstrongswan plugins
 dnl =====================
 AM_CONDITIONAL(USE_TEST_VECTORS, test x$test_vectors = xtrue)
 AM_CONDITIONAL(USE_CURL, test x$curl = xtrue)
 dnl =====================
 AM_CONDITIONAL(USE_TEST_VECTORS, test x$test_vectors = xtrue)
 AM_CONDITIONAL(USE_CURL, test x$curl = xtrue)
+AM_CONDITIONAL(USE_SOUP, test x$soup = xtrue)
 AM_CONDITIONAL(USE_LDAP, test x$ldap = xtrue)
 AM_CONDITIONAL(USE_AES, test x$aes = xtrue)
 AM_CONDITIONAL(USE_DES, test x$des = xtrue)
 AM_CONDITIONAL(USE_LDAP, test x$ldap = xtrue)
 AM_CONDITIONAL(USE_AES, test x$aes = xtrue)
 AM_CONDITIONAL(USE_DES, test x$des = xtrue)
@@ -960,6 +969,7 @@ AC_OUTPUT(
        src/libstrongswan/plugins/dnskey/Makefile
        src/libstrongswan/plugins/pem/Makefile
        src/libstrongswan/plugins/curl/Makefile
        src/libstrongswan/plugins/dnskey/Makefile
        src/libstrongswan/plugins/pem/Makefile
        src/libstrongswan/plugins/curl/Makefile
+       src/libstrongswan/plugins/soup/Makefile
        src/libstrongswan/plugins/ldap/Makefile
        src/libstrongswan/plugins/mysql/Makefile
        src/libstrongswan/plugins/sqlite/Makefile
        src/libstrongswan/plugins/ldap/Makefile
        src/libstrongswan/plugins/mysql/Makefile
        src/libstrongswan/plugins/sqlite/Makefile
index debfaf7..6a29d8e 100644 (file)
@@ -282,6 +282,13 @@ if MONOLITHIC
 endif
 endif
 
 endif
 endif
 
+if USE_SOUP
+  SUBDIRS += plugins/soup
+if MONOLITHIC
+  libstrongswan_la_LIBADD += plugins/soup/libstrongswan-soup.la
+endif
+endif
+
 if USE_LDAP
   SUBDIRS += plugins/ldap
 if MONOLITHIC
 if USE_LDAP
   SUBDIRS += plugins/ldap
 if MONOLITHIC
diff --git a/src/libstrongswan/plugins/soup/Makefile.am b/src/libstrongswan/plugins/soup/Makefile.am
new file mode 100644 (file)
index 0000000..9006f1b
--- /dev/null
@@ -0,0 +1,16 @@
+
+INCLUDES = -I$(top_srcdir)/src/libstrongswan ${soup_CFLAGS}
+
+AM_CFLAGS = -rdynamic
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-soup.la
+else
+plugin_LTLIBRARIES = libstrongswan-soup.la
+endif
+
+libstrongswan_soup_la_SOURCES = \
+       soup_plugin.h soup_plugin.c soup_fetcher.c soup_fetcher.h
+
+libstrongswan_soup_la_LDFLAGS = -module -avoid-version
+libstrongswan_soup_la_LIBADD  = ${soup_LIBS}
diff --git a/src/libstrongswan/plugins/soup/soup_fetcher.c b/src/libstrongswan/plugins/soup/soup_fetcher.c
new file mode 100644 (file)
index 0000000..fd97631
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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 "soup_fetcher.h"
+
+#include <libsoup/soup.h>
+
+#include <library.h>
+#include <debug.h>
+
+#define DEFAULT_TIMEOUT 10
+
+typedef struct private_soup_fetcher_t private_soup_fetcher_t;
+
+/**
+ * private data of a soup_fetcher_t object.
+ */
+struct private_soup_fetcher_t {
+
+       /**
+        * Public data
+        */
+       soup_fetcher_t public;
+
+       /**
+        * HTTP request method
+        */
+       const char *method;
+
+       /**
+        * Request content type
+        */
+       char *type;
+
+       /**
+        * Request data
+        */
+       chunk_t data;
+
+       /**
+        * Request timeout
+        */
+       u_int timeout;
+
+       /**
+        * HTTP request version
+        */
+       SoupHTTPVersion version;
+};
+
+METHOD(fetcher_t, fetch, status_t,
+       private_soup_fetcher_t *this, char *uri, chunk_t *result)
+{
+       SoupSession *session;
+       SoupMessage *message;
+       status_t status = FAILED;
+
+       message = soup_message_new(this->method, uri);
+       if (!message)
+       {
+               return NOT_SUPPORTED;
+       }
+       if (this->type)
+       {
+               soup_message_set_request(message, this->type, SOUP_MEMORY_STATIC,
+                                                                this->data.ptr, this->data.len);
+       }
+       soup_message_set_http_version(message, this->version);
+       session = soup_session_sync_new();
+       g_object_set(G_OBJECT(session),
+                                SOUP_SESSION_TIMEOUT, (guint)this->timeout, NULL);
+
+       DBG2(DBG_LIB, "sending http request to '%s'...", uri);
+       soup_session_send_message(session, message);
+       if (SOUP_STATUS_IS_SUCCESSFUL(message->status_code))
+       {
+               *result = chunk_clone(chunk_create((u_char*)message->response_body->data,
+                                                                                  message->response_body->length));
+               status = SUCCESS;
+       }
+       else
+       {
+               DBG1(DBG_LIB, "HTTP request failed, code %d", message->status_code);
+       }
+       g_object_unref(G_OBJECT(message));
+       g_object_unref(G_OBJECT(session));
+       return status;
+}
+
+METHOD(fetcher_t, set_option, bool,
+       private_soup_fetcher_t *this, fetcher_option_t option, ...)
+{
+       bool supported = TRUE;
+       va_list args;
+
+       va_start(args, option);
+       switch (option)
+       {
+               case FETCH_REQUEST_DATA:
+                       this->method = SOUP_METHOD_POST;
+                       this->data = va_arg(args, chunk_t);
+                       break;
+               case FETCH_REQUEST_TYPE:
+                       this->type = va_arg(args, char*);
+                       break;
+               case FETCH_HTTP_VERSION_1_0:
+                       this->version = SOUP_HTTP_1_0;
+                       break;
+               case FETCH_TIMEOUT:
+                       this->timeout = va_arg(args, u_int);
+                       break;
+               default:
+                       supported = FALSE;
+                       break;
+       }
+       va_end(args);
+       return supported;
+}
+
+METHOD(fetcher_t, destroy, void,
+       private_soup_fetcher_t *this)
+{
+       free(this);
+}
+
+/*
+ * Described in header.
+ */
+soup_fetcher_t *soup_fetcher_create()
+{
+       private_soup_fetcher_t *this;
+
+       INIT(this,
+               .public = {
+                       .interface = {
+                               .fetch = _fetch,
+                               .set_option = _set_option,
+                               .destroy = _destroy,
+                       },
+               },
+               .method = SOUP_METHOD_GET,
+               .version = SOUP_HTTP_1_1,
+               .timeout = DEFAULT_TIMEOUT,
+       );
+
+       return &this->public;
+}
diff --git a/src/libstrongswan/plugins/soup/soup_fetcher.h b/src/libstrongswan/plugins/soup/soup_fetcher.h
new file mode 100644 (file)
index 0000000..9b25795
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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 soup_fetcher soup_fetcher
+ * @{ @ingroup soup_p
+ */
+
+#ifndef SOUP_FETCHER_H_
+#define SOUP_FETCHER_H_
+
+#include <library.h>
+
+typedef struct soup_fetcher_t soup_fetcher_t;
+
+/**
+ * Fetcher implementation for HTTP using libsoup.
+ */
+struct soup_fetcher_t {
+
+       /**
+        * Implements fetcher interface.
+        */
+       fetcher_t interface;
+};
+
+/**
+ * Create a soup_fetcher instance.
+ */
+soup_fetcher_t *soup_fetcher_create();
+
+#endif /** SOUP_FETCHER_H_ @}*/
diff --git a/src/libstrongswan/plugins/soup/soup_plugin.c b/src/libstrongswan/plugins/soup/soup_plugin.c
new file mode 100644 (file)
index 0000000..970e324
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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 "soup_plugin.h"
+#include "soup_fetcher.h"
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <library.h>
+
+typedef struct private_soup_plugin_t private_soup_plugin_t;
+
+/**
+ * private data of soup_plugin
+ */
+struct private_soup_plugin_t {
+
+       /**
+        * public functions
+        */
+       soup_plugin_t public;
+};
+
+METHOD(plugin_t, destroy, void,
+       private_soup_plugin_t *this)
+{
+       lib->fetcher->remove_fetcher(lib->fetcher,
+                                                                (fetcher_constructor_t)soup_fetcher_create);
+       free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *soup_plugin_create()
+{
+       private_soup_plugin_t *this;
+
+       g_type_init();
+       if (!g_thread_get_initialized())
+       {
+               g_thread_init(NULL);
+       }
+
+       INIT(this,
+               .public = {
+                       .plugin = {
+                               .destroy = _destroy,
+                       },
+               },
+       );
+
+       lib->fetcher->add_fetcher(lib->fetcher,
+                                       (fetcher_constructor_t)soup_fetcher_create, "http://");
+       lib->fetcher->add_fetcher(lib->fetcher,
+                                       (fetcher_constructor_t)soup_fetcher_create, "https://");
+
+       return &this->public.plugin;
+}
diff --git a/src/libstrongswan/plugins/soup/soup_plugin.h b/src/libstrongswan/plugins/soup/soup_plugin.h
new file mode 100644 (file)
index 0000000..2dfa1d2
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2010 Martin Willi
+ * Copyright (C) 2010 revosec AG
+ *
+ * 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 soup_p soup
+ * @ingroup plugins
+ *
+ * @defgroup soup_plugin soup_plugin
+ * @{ @ingroup soup_p
+ */
+
+#ifndef SOUP_PLUGIN_H_
+#define SOUP_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct soup_plugin_t soup_plugin_t;
+
+/**
+ * Plugin implementing fetcher interface for HTTP using libsoup.
+ */
+struct soup_plugin_t {
+
+       /**
+        * Implements plugin interface
+        */
+       plugin_t plugin;
+};
+
+#endif /** SOUP_PLUGIN_H_ @}*/