gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r6988 - in libmicrohttpd/src: daemon examples include


From: gnunet
Subject: [GNUnet-SVN] r6988 - in libmicrohttpd/src: daemon examples include
Date: Sun, 1 Jun 2008 20:11:54 -0600 (MDT)

Author: lv-426
Date: 2008-06-01 20:11:51 -0600 (Sun, 01 Jun 2008)
New Revision: 6988

Modified:
   libmicrohttpd/src/daemon/Makefile.am
   libmicrohttpd/src/daemon/daemon.c
   libmicrohttpd/src/daemon/internal.h
   libmicrohttpd/src/examples/Makefile.am
   libmicrohttpd/src/examples/https_server_example.c
   libmicrohttpd/src/include/microhttpd.h
Log:
added X.509 parameters to the daemon struct
added https daemon creation functionality
https file server example [overriding existing echo server]

Modified: libmicrohttpd/src/daemon/Makefile.am
===================================================================
--- libmicrohttpd/src/daemon/Makefile.am        2008-06-02 02:03:03 UTC (rev 
6987)
+++ libmicrohttpd/src/daemon/Makefile.am        2008-06-02 02:11:51 UTC (rev 
6988)
@@ -11,8 +11,6 @@
 lib_LTLIBRARIES = \
   libmicrohttpd.la
 
-libmicrohttpd_la_LDFLAGS = \
-  -export-dynamic -version-info 4:3:0 $(retaincommand)
 libmicrohttpd_la_SOURCES = \
   connection.c connection.h \
   reason_phrase.c reason_phrase.h \
@@ -21,7 +19,13 @@
   memorypool.c memorypool.h \
   plibc.h \
   postprocessor.c \
-  response.c response.h 
+  response.c response.h
+libmicrohttpd_la_LDFLAGS = \
+  -export-dynamic -version-info 4:3:0 $(retaincommand) \
+  -L$(GNUTLS_LIB_PATH) \
+  -lgnutls
+libmicrohttpd_la_CPPFLAGS = \
+  $(GNUTLS_CPPFLAGS) 
 
 check_PROGRAMS = \
   postprocessor_test \

Modified: libmicrohttpd/src/daemon/daemon.c
===================================================================
--- libmicrohttpd/src/daemon/daemon.c   2008-06-02 02:03:03 UTC (rev 6987)
+++ libmicrohttpd/src/daemon/daemon.c   2008-06-02 02:11:51 UTC (rev 6988)
@@ -29,6 +29,7 @@
 #include "response.h"
 #include "connection.h"
 #include "memorypool.h"
+#include <gnutls/gnutls.h>
 
 /**
  * Default connection limit.
@@ -52,6 +53,12 @@
  */
 #define DEBUG_CONNECT MHD_NO
 
+// TODO rm
+/* HTTPS file path limit, leaving room for file name */
+#define MHD_PATH_LEN 240
+
+int MHDS_init (struct MHD_Daemon *daemon);
+
 /**
  * Obtain the select sets for this daemon.
  *
@@ -174,6 +181,8 @@
   if (con == NULL)
     abort ();
 
+  // TODO add connection time out code
+
   /* forward call to handler */
   con->daemon->default_handler (NULL, con, NULL, NULL, NULL, NULL, NULL,
                                 NULL);
@@ -690,6 +699,13 @@
   retVal->pool_size = MHD_POOL_SIZE_DEFAULT;
   retVal->connection_timeout = 0;       /* no timeout */
 
+  /* set server default document root path */
+  getcwd (retVal->doc_root, MHD_PATH_LEN);
+
+  /* initialize ssl path parameters to the local path */
+  strcpy (retVal->https_cert_path, "cert.pem");
+  strcpy (retVal->https_key_path, "key.pem");
+
   /* initializes the argument pointer variable */
   va_start (ap, dh_cls);
 
@@ -717,6 +733,22 @@
         case MHD_OPTION_PER_IP_CONNECTION_LIMIT:
           retVal->per_ip_connection_limit = va_arg (ap, unsigned int);
           break;
+        case MHD_OPTION_DOC_ROOT:
+          strncpy (retVal->doc_root, va_arg (ap, char *), MHD_PATH_LEN);
+          break;
+        case MHD_OPTION_HTTPS_KEY_PATH:
+          strncpy (retVal->https_key_path, va_arg (ap, char *), MHD_PATH_LEN);
+          strcat (retVal->https_key_path, DIR_SEPARATOR_STR);
+          strcat (retVal->https_key_path, "key.pem");
+          break;
+        case MHD_OPTION_HTTPS_CERT_PATH:
+
+          strncpy (retVal->https_cert_path,
+                   va_arg (ap, char *), MHD_PATH_LEN);
+          strcat (retVal->https_cert_path, DIR_SEPARATOR_STR);
+          strcat (retVal->https_cert_path, "cert.pem");
+          break;
+
         default:
 #if HAVE_MESSAGES
           fprintf (stderr,
@@ -725,6 +757,29 @@
           abort ();
         }
     }
+
+  /* initialize HTTPS daemon certificate aspects */
+  if (options & MHD_USE_SSL)
+    {
+      /* test for private key & certificate file exsitance */
+      FILE *cert_file = fopen (retVal->https_cert_path, "r");
+      FILE *key_file = fopen (retVal->https_key_path, "r");
+      if (key_file == NULL || cert_file == NULL)
+        {
+          printf ("missing cert files");
+#if HAVE_MESSAGES
+          MHD_DLOG (retVal, "Missing X.509 key or certificate file\n");
+#endif
+          free (retVal);
+          CLOSE (socket_fd);
+          return NULL;
+        }
+
+      fclose (cert_file);
+      fclose (key_file);
+      MHDS_init (retVal);
+    }
+
   va_end (ap);
   if (((0 != (options & MHD_USE_THREAD_PER_CONNECTION)) || (0 != (options
                                                                   &
@@ -793,9 +848,51 @@
         }
       MHD_cleanup_connections (daemon);
     }
+
+  /* TLS clean up */
+  if (daemon->options & MHD_USE_SSL)
+    {
+      gnutls_priority_deinit (daemon->priority_cache);
+      gnutls_global_deinit ();
+    }
+
   free (daemon);
 }
 
+int
+MHDS_init (struct MHD_Daemon *daemon)
+{
+  gnutls_global_init ();
+  /* Generate Diffie Hellman parameters - for use with DHE kx algorithms. */
+  gnutls_dh_params_init (&daemon->dh_params);
+  gnutls_dh_params_generate2 (daemon->dh_params, DH_BITS);
+
+  // TODO make room for cipher settings adjustment
+  gnutls_priority_init (&daemon->priority_cache,
+                        "NORMAL:+AES-256-CBC:+RSA:+SHA1:+COMP-NULL", NULL);
+
+  /* setup server certificate */
+  gnutls_certificate_allocate_credentials (&daemon->x509_cret);
+
+  // TODO remove if unused
+  /* add trusted CAs to certificate */
+  // gnutls_certificate_set_x509_trust_file(x509_cret, 
CAFILE,GNUTLS_X509_FMT_PEM);
+
+  /* add Certificate revocation list to certificate */
+  //gnutls_certificate_set_x509_crl_file(x509_cret, CRLFILE, 
GNUTLS_X509_FMT_PEM);
+
+  /* sets a certificate private key pair */
+  gnutls_certificate_set_x509_key_file (daemon->x509_cret,
+                                        daemon->https_cert_path,
+                                        daemon->https_key_path,
+                                        GNUTLS_X509_FMT_PEM);
+
+  gnutls_certificate_set_dh_params (daemon->x509_cret, daemon->dh_params);
+
+  // TODO address error case return value
+  return 0;
+}
+
 #ifndef WINDOWS
 
 static struct sigaction sig;

Modified: libmicrohttpd/src/daemon/internal.h
===================================================================
--- libmicrohttpd/src/daemon/internal.h 2008-06-02 02:03:03 UTC (rev 6987)
+++ libmicrohttpd/src/daemon/internal.h 2008-06-02 02:11:51 UTC (rev 6988)
@@ -35,6 +35,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <gnutls/gnutls.h>
 
 #include "config.h"
 #include "plibc.h"
@@ -58,6 +59,9 @@
  */
 #define MHD_BUF_INC_SIZE 2048
 
+/* TLS Diffie-Hellman parameter */
+#define DH_BITS 1024
+
 #if HAVE_MESSAGES
 /**
  * fprintf-like helper function for logging debug
@@ -606,6 +610,22 @@
      */
   unsigned short port;
 
+  /* server credintials */
+  gnutls_certificate_credentials_t x509_cret;
+
+  /* cipher priority cache */
+  gnutls_priority_t priority_cache;
+
+  /* Diffie-Hellman parameters */
+  gnutls_dh_params_t dh_params;
+
+  // TODO consider switching to variadic length paths
+  /* server root path used while serving http pages */
+  char doc_root[255];
+
+  char https_key_path[255];
+
+  char https_cert_path[255];
 };
 
 #endif

Modified: libmicrohttpd/src/examples/Makefile.am
===================================================================
--- libmicrohttpd/src/examples/Makefile.am      2008-06-02 02:03:03 UTC (rev 
6987)
+++ libmicrohttpd/src/examples/Makefile.am      2008-06-02 02:11:51 UTC (rev 
6988)
@@ -6,6 +6,7 @@
 
 noinst_PROGRAMS = \
 https_server_example \
+https_echo_server_example \
 https_echo_client_example \
 minimal_example \
 querystring_example \
@@ -43,6 +44,18 @@
 https_server_example_LDFLAGS = \
  -L$(GNUTLS_LIB_PATH) \
  -lgnutls
+
+https_echo_server_example_CPPFLAGS = \
+ $(GNUTLS_CPPFLAGS) \
+ -I$(top_srcdir)/src/daemon \
+ -I$(top_srcdir)/src/include 
+https_echo_server_example_SOURCES = \
+ https_echo_server_example.c
+https_echo_server_example_LDADD = \
+ $(top_builddir)/src/daemon/libmicrohttpd.la
+https_echo_server_example_LDFLAGS = \
+ -L$(GNUTLS_LIB_PATH) \
+ -lgnutls
  
 https_echo_client_example_CPPFLAGS = \
  $(GNUTLS_CPPFLAGS) \

Modified: libmicrohttpd/src/examples/https_server_example.c
===================================================================
--- libmicrohttpd/src/examples/https_server_example.c   2008-06-02 02:03:03 UTC 
(rev 6987)
+++ libmicrohttpd/src/examples/https_server_example.c   2008-06-02 02:11:51 UTC 
(rev 6988)
@@ -20,7 +20,17 @@
 
 /**
  * @file https_server_example.c
- * @brief a simple echo server using TLS. echo input from client until 'exit' 
message is received. 
+ * @brief a simple https file server using TLS.
+ * 
+ * This example assumes the existence of a private key file named "key.pem"
+ * and a server certificate file named "cert.pem". File path for these should 
be
+ * provided as command-line arguments. 'certtool' may be used to generate 
these if
+ * missing. 
+ * 
+ * Access server with your browser of choice or with curl : 
+ * 
+ *   curl --insecure --tlsv1 --ciphers AES256-SHA <url>
+ * 
  * @author LV-426
  */
 
@@ -35,64 +45,76 @@
 #include <string.h>
 #include <stdio.h>
 #include <gnutls/gnutls.h>
+#include <gcrypt.h>
 
-#define DH_BITS 1024
-#define MAX_BUF 1024
-/* server credintials */
-gnutls_anon_server_credentials_t anoncred;
+#define BUF_SIZE 1024
+#define MAX_URL_LEN 255
 
-/* server Diffie-Hellman parameters */
-static gnutls_dh_params_t dh_params;
+#define KEYFILE "key.pem"
+#define CERTFILE "cert.pem"
 
+// TODO remove if unused
+#define CAFILE "ca.pem"
+#define CRLFILE "crl.pem"
 
-/* Generate Diffie Hellman parameters - for use with DHE kx algorithms. */
-static int
-generate_dh_params (void)
-{
+#define PAGE_NOT_FOUND "<html><head><title>File not 
found</title></head><body>File not found</body></html>"
 
-  gnutls_dh_params_init (&dh_params);
-  gnutls_dh_params_generate2 (dh_params, DH_BITS);
-  return 0;
-}
-
 gnutls_session_t
-initialize_tls_session (void)
+initialize_tls_session (struct MHD_Connection *connection)
 {
   gnutls_session_t session;
 
   gnutls_init (&session, GNUTLS_SERVER);
 
-  gnutls_priority_set_direct (session, "NORMAL:+ANON-DH", NULL);
+  /* sets cipher priorities */
+  gnutls_priority_set (session, connection->daemon->priority_cache);
 
-  gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
+  /* set needed credentials for certificate authentication. */
+  gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE,
+                          connection->daemon->x509_cret);
 
-  gnutls_dh_set_prime_bits (session, DH_BITS);
-
   return session;
 }
 
-/* Accept Policy Callback */
 static int
-TLS_echo (void *cls,
-          struct MHD_Connection *connection,
-          const char *url,
-          const char *method,
-          const char *upload_data,
-          const char *version, unsigned int *upload_data_size, void **ptr)
+file_reader (void *cls, size_t pos, char *buf, int max)
 {
+  FILE *file = cls;
+
+  fseek (file, pos, SEEK_SET);
+  return fread (buf, 1, max, file);
+}
+
+/* HTTPS access handler call back */
+static int
+https_ahc (void *cls,
+           struct MHD_Connection *connection,
+           const char *url,
+           const char *method,
+           const char *upload_data,
+           const char *version, unsigned int *upload_data_size, void **ptr)
+{
+  /* loopback HTTP socket */
+  int loopback_sd, err;
+  ssize_t ret;
+  struct sockaddr_in servaddr4;
+  const struct sockaddr *servaddr;
+  struct sockaddr_in loopback_sa;
+  socklen_t addrlen;
+
   gnutls_session_t session;
   static int aptr;
   struct MHD_Response *response;
-  char buffer[MAX_BUF + 1];
-  int ret;
+  char buffer[BUF_SIZE];
 
   printf ("accepted connection from %d\n", connection->addr->sin_addr);
 
-  session = initialize_tls_session ();
+  session = initialize_tls_session (connection);
 
   gnutls_transport_set_ptr (session, connection->socket_fd);
 
   ret = gnutls_handshake (session);
+
   if (ret < 0)
     {
       /* set connection as closed */
@@ -106,77 +128,182 @@
   printf ("TLS Handshake completed\n");
   connection->state = MHDS_HANDSHAKE_COMPLETE;
 
-  /* simple echo loop. message encryption/decryption is acheived through 
'gnutls_record_send'
-   *  & gnutls_record_recv calls. */
+  /* initialize loopback socket */
+  loopback_sd = socket (AF_INET, SOCK_STREAM, 0);
+  memset (&loopback_sa, '\0', sizeof (loopback_sa));
+  loopback_sa.sin_family = AF_INET;
+
+  // TODO solve magic number issue - the http's daemons port must be shared 
with the https daemon - rosolve data sharing point
+  loopback_sa.sin_port = htons (50000);
+  inet_pton (AF_INET, "127.0.0.1", &loopback_sa.sin_addr);
+
+  /* connect loopback socket */
+  err = connect (loopback_sd, (struct sockaddr *) &loopback_sa,
+                 sizeof (loopback_sa));
+  if (err < 0)
+    {
+      // TODO err handle
+      fprintf (stderr, "Error : failed to create TLS loopback socket\n");
+      exit (1);
+    }
+
+  /* 
+   * This loop pipes data received through the TLS tunnel into the loopback 
connection.  
+   * message encryption/decryption is acheived via 'gnutls_record_send' & 
gnutls_record_recv calls.
+   */
+  memset (buffer, 0, BUF_SIZE);
+  if (gnutls_record_recv (session, buffer, BUF_SIZE) < 0)
+    {
+      fprintf (stderr, "\n*** Received corrupted "
+               "data(%d). Closing the connection.\n\n", ret);
+      connection->socket_fd = -1;
+      gnutls_deinit (session);
+      return MHD_NO;
+    }
+
+  if (write (loopback_sd, buffer, BUF_SIZE) < 0)
+    {
+      printf ("failed to write to TLS loopback socket\n");
+      connection->socket_fd = -1;
+      gnutls_deinit (session);
+      return MHD_NO;
+    }
+
   for (;;)
     {
-      memset (buffer, 0, MAX_BUF + 1);
-      ret = gnutls_record_recv (session, buffer, MAX_BUF);
+      memset (buffer, 0, BUF_SIZE);
 
+      ret = read (loopback_sd, buffer, BUF_SIZE);
+
       if (ret < 0)
         {
-          fprintf (stderr, "\n*** Received corrupted "
-                   "data(%d). Closing the connection.\n\n", ret);
+          printf ("failed to read from TLS loopback socket\n");
           break;
         }
-      else if (ret >= 0)
+
+      if (ret == 0)
         {
-          if (strcmp (buffer, "exit") == 0)
-            {
-              printf ("\n- Peer has closed the GNUTLS connection\n");
-              break;
-            }
-          else
-            {
-              /* echo data back to the client */
-              gnutls_record_send (session, buffer, strlen (buffer));
-            }
+          break;
         }
+
+      /* echo data back to the client */
+      ret = gnutls_record_send (session, buffer, ret);
+      if (ret < 0)
+        {
+          printf ("failed to write to TLS socket\n");
+          break;
+        }
     }
-  printf ("\n");
-
   /* mark connection as closed */
   connection->socket_fd = -1;
-
   gnutls_deinit (session);
 
+  return MHD_YES;
+}
+
+/* HTTP access handler call back */
+static int
+http_ahc (void *cls,
+          struct MHD_Connection *connection,
+          const char *url,
+          const char *method,
+          const char *upload_data,
+          const char *version, unsigned int *upload_data_size, void **ptr)
+{
+  static int aptr;
+  static char full_url[MAX_URL_LEN];
+  struct MHD_Response *response;
+  int ret;
+  FILE *file;
+  struct stat buf;
+
+  if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
+    return MHD_NO;              /* unexpected method */
+  if (&aptr != *ptr)
+    {
+      /* do never respond on first call */
+      *ptr = &aptr;
+      return MHD_YES;
+    }
+  *ptr = NULL;                  /* reset when done */
+
+  /* assemble full url */
+  strcpy (full_url, connection->daemon->doc_root);
+  strncat (full_url, url,
+           MAX_URL_LEN - strlen (connection->daemon->doc_root) - 1);
+
+  file = fopen (full_url, "r");
+  if (file == NULL)
+    {
+      response = MHD_create_response_from_data (strlen (PAGE_NOT_FOUND),
+                                                (void *) PAGE_NOT_FOUND,
+                                                MHD_NO, MHD_NO);
+      ret = MHD_queue_response (connection, MHD_HTTP_NOT_FOUND, response);
+      MHD_destroy_response (response);
+    }
+  else
+    {
+      stat (&url[1], &buf);
+      response = MHD_create_response_from_callback (buf.st_size, 32 * 1024,    
 /* 32k PAGE_NOT_FOUND size */
+                                                    &file_reader, file,
+                                                    
(MHD_ContentReaderFreeCallback)
+                                                    & fclose);
+      ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+      MHD_destroy_response (response);
+    }
   return ret;
 }
 
 int
 main (int argc, char *const *argv)
 {
-  struct MHD_Daemon *daemon;
+  char keyfile[255] = KEYFILE;
+  char certfile[255] = CERTFILE;
+  struct MHD_Daemon *HTTP_daemon;
   struct MHD_Daemon *TLS_daemon;
 
-  /* look for HTTPS port argument */
-  if (argc < 4)
+  /* look for HTTPS arguments */
+  if (argc < 5)
     {
-      printf ("Usage : %s HTTP-PORT SECONDS-TO-RUN HTTPS-PORT\n", argv[0]);
+      printf
+        ("Usage : %s HTTP-PORT SECONDS-TO-RUN HTTPS-PORT X.509_FILE_PATH\n",
+         argv[0]);
       return 1;
     }
 
-  gnutls_global_init ();
+  // TODO check if this is truly necessary -  disallow usage of the blocking 
/dev/random */
+  // gcry_control(GCRYCTL_ENABLE_QUICK_RANDOM, 0);
 
-  gnutls_anon_allocate_server_credentials (&anoncred);
+  HTTP_daemon =
+    MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG,
+                      atoi (argv[1]), NULL, NULL, &http_ahc, MHD_OPTION_END);
 
-  generate_dh_params ();
+  if (HTTP_daemon == NULL)
+    {
+      printf ("Error: failed to start HTTP_daemon");
+      return 1;
+    }
 
-  gnutls_anon_set_server_dh_params (anoncred, dh_params);
-
-  TLS_daemon = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION
-                                 | MHD_USE_DEBUG | MHD_USE_SSL,
-                                 atoi (argv[3]), NULL, NULL, &TLS_echo, NULL,
+  TLS_daemon = MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_DEBUG
+                                 | MHD_USE_SSL, atoi (argv[3]),
+                                 NULL,
+                                 NULL, &https_ahc,
+                                 NULL, MHD_OPTION_CONNECTION_TIMEOUT, 256,
+                                 MHD_OPTION_HTTPS_KEY_PATH, argv[4],
+                                 MHD_OPTION_HTTPS_CERT_PATH, argv[4],
                                  MHD_OPTION_END);
 
   if (TLS_daemon == NULL)
-    return 1;
+    {
+      printf ("Error: failed to start TLS_daemon");
+      return 1;
+    }
+
   sleep (atoi (argv[2]));
 
-  MHD_stop_daemon (daemon);
+  MHD_stop_daemon (HTTP_daemon);
 
-  gnutls_anon_free_server_credentials (anoncred);
+  MHD_stop_daemon (TLS_daemon);
 
-  gnutls_global_deinit ();
   return 0;
 }

Modified: libmicrohttpd/src/include/microhttpd.h
===================================================================
--- libmicrohttpd/src/include/microhttpd.h      2008-06-02 02:03:03 UTC (rev 
6987)
+++ libmicrohttpd/src/include/microhttpd.h      2008-06-02 02:11:51 UTC (rev 
6988)
@@ -345,6 +345,14 @@
    */
   MHD_OPTION_PER_IP_CONNECTION_LIMIT = 5,
 
+  /* server root path used while serving http pages */
+  MHD_OPTION_DOC_ROOT = 6,
+
+  /* private key path used by the HTTPS daemon */
+  MHD_OPTION_HTTPS_KEY_PATH = 7,
+
+  /* certificate path used by the HTTPS daemon */
+  MHD_OPTION_HTTPS_CERT_PATH = 8,
 };
 
 /**





reply via email to

[Prev in Thread] Current Thread [Next in Thread]