[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r7753 - in libmicrohttpd/doc: . chapters examples
From: |
gnunet |
Subject: |
[GNUnet-SVN] r7753 - in libmicrohttpd/doc: . chapters examples |
Date: |
Sat, 11 Oct 2008 11:55:14 -0600 (MDT) |
Author: sebdocwriter
Date: 2008-10-11 11:55:14 -0600 (Sat, 11 Oct 2008)
New Revision: 7753
Added:
libmicrohttpd/doc/chapters/tlsauthentication.inc
libmicrohttpd/doc/examples/tlsauthentication.c
Modified:
libmicrohttpd/doc/tutorial.texi
Log:
Tutorial: New chapter for SSL/TLS
Added: libmicrohttpd/doc/chapters/tlsauthentication.inc
===================================================================
--- libmicrohttpd/doc/chapters/tlsauthentication.inc
(rev 0)
+++ libmicrohttpd/doc/chapters/tlsauthentication.inc 2008-10-11 17:55:14 UTC
(rev 7753)
@@ -0,0 +1,130 @@
+We left the basic authentication chapter with the unsatisfactory conclusion
that
+any traffic, including the credentials, could be intercepted by anyone between
+the browser client and the server. Protecting the data while it is sent over
+unsecured lines will be the goal of this chapter.
+
+Since version 0.4, the @emph{MHD} library includes support for encrypting the
+traffic by employing SSL/TSL. If @emph{GNU libmicrohttpd} has been configured
to
+support these, encryption and decryption can be applied transparently on the
+data being sent, with only minimal changes to the actual source code of the
example.
+
+
address@hidden Preparation
+
+First, a private key for the server will be generated. With this key, the
server
+will later be able to authenticate itself to the client---preventing anyone
else
+from stealing the password by faking its identity. The @emph{OpenSSL} suite,
which
+is available on many operating systems, can generate such a key. For the scope
of
+this tutorial, we will be content with a 1024 bit key:
address@hidden
+> openssl genrsa -out server.key 1024
address@hidden verbatim
address@hidden
+
+In addition to the key, a certificate describing the server in human readable
tokens
+is also needed. This certificate will be attested with our aforementioned key.
In this way,
+we obtain a self-signed certificate, valid for one year.
+
address@hidden
+> openssl req -days 365 -out server.pem -new -x509 -key server.key
address@hidden verbatim
address@hidden
+
+To avoid unnecessary error messages in the browser, the certificate needs to
+have a name that matches the @emph{URI}, for example, "localhost" or the
domain.
+If you plan to have a publicly reachable server, you will need to ask a
trusted third party,
+called @emph{Certificate Authority}, or @emph{CA}, to attest the certificate
for you. This way,
+any visitor can make sure the server's identity is real.
+
+Whether the server's certificate is signed by us or a third party, once it has
been accepted
+by the client, both sides will be communicating over encrypted channels. From
this point on,
+it is the client's turn to authenticate itself. But this has already been
implemented in the basic
+authentication scheme.
+
+
address@hidden Changing the source code
+
+We merely have to extend the server program so that it loads the two files
into memory,
+
address@hidden
+int
+main ()
+{
+ struct MHD_Daemon *daemon;
+ char *key_pem;
+ char *cert_pem;
+
+ key_pem = load_file (SERVERKEYFILE);
+ cert_pem = load_file (SERVERCERTFILE);
+
+ if ((key_pem == NULL) || (cert_pem == NULL))
+ {
+ printf ("The key/certificate files could not be read.\n");
+ return 1;
+ }
address@hidden verbatim
address@hidden
+
+and then we point the @emph{MHD} daemon to it upon initalization.
address@hidden
+
+ daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL, PORT,
NULL, NULL,
+ &answer_to_connection, NULL,
+ MHD_OPTION_HTTPS_MEM_KEY, key_pem,
+ MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
+ MHD_OPTION_END);
+
+ if (NULL == daemon)
+ {
+ printf ("%s\n", cert_pem);
+
+ free (key_pem);
+ free (cert_pem);
+
+ return 1;
+ }
address@hidden verbatim
address@hidden
+
+
+The rest consists of little new besides some additional memory cleanups.
address@hidden
+
+ getchar ();
+
+ MHD_stop_daemon (daemon);
+ free (key_pem);
+ free (cert_pem);
+
+ return 0;
+}
address@hidden verbatim
address@hidden
+
+
+The rather unexciting file loader can be found in the complete example
@code{tlsauthentication.c}.
+
address@hidden Remarks
address@hidden @bullet
address@hidden
+While the standard @emph{HTTP} port is 80, it is 443 for @emph{HTTPS}. The
common internet browsers assume
+standard @emph{HTTP} if they are asked to access other ports than these.
Therefore, you will have to type
address@hidden://localhost:8888} explicitly when you test the example, or the
browser will not know how to
+handle the answer properly.
+
address@hidden
+The remaining weak point is the question how the server will be trusted
initially. Either a @emph{CA} signs the
+certificate or the client obtains the key over secure means. Anyway, the
clients have to be aware (or configured)
+that they should not accept certificates of unknown origin.
+
address@hidden
+The introduced method of certificates makes it mandatory to set an expiration
date---making it less feasible to
+hardcode certificates in embedded devices.
+
address@hidden
+The cryptographic facilities consume memory space and computing time. For this
reason, websites usually consists
+both of uncritically @emph{HTTP} parts and secured @emph{HTTPS}.
+
address@hidden itemize
+
+
Added: libmicrohttpd/doc/examples/tlsauthentication.c
===================================================================
--- libmicrohttpd/doc/examples/tlsauthentication.c
(rev 0)
+++ libmicrohttpd/doc/examples/tlsauthentication.c 2008-10-11 17:55:14 UTC
(rev 7753)
@@ -0,0 +1,253 @@
+#include <platform.h>
+#include <microhttpd.h>
+
+#define PORT 8888
+
+#define REALM "\"Maintenance\""
+#define USER "a legitimate user"
+#define PASSWORD "and his password"
+
+#define SERVERKEYFILE "server.key"
+#define SERVERCERTFILE "server.pem"
+
+char *string_to_base64 (const char *message);
+
+long
+get_file_size (const char *filename)
+{
+ FILE *fp;
+
+ fp = fopen (filename, "rb");
+ if (fp)
+ {
+ long size;
+
+ if ((0 != fseek (fp, 0, SEEK_END)) || (-1 == (size = ftell (fp))))
+ size = 0;
+
+ fclose (fp);
+
+ return size;
+ }
+ else
+ return 0;
+}
+
+char*
+load_file (const char* filename)
+{
+ FILE *fp;
+ char *buffer;
+ long size;
+
+ size = get_file_size (filename);
+ if (size == 0) return NULL;
+
+ fp = fopen (filename, "rb");
+ if (!fp) return NULL;
+
+ buffer = malloc (size);
+ if (!buffer) {fclose (fp); return NULL;}
+
+ if (size != fread (buffer, 1, size, fp))
+ {
+ free (buffer);
+ buffer = NULL;
+ }
+
+ fclose (fp);
+ return buffer;
+}
+
+int
+ask_for_authentication (struct MHD_Connection *connection, const char *realm)
+{
+ int ret;
+ struct MHD_Response *response;
+ char *headervalue;
+ const char *strbase = "Basic realm=";
+
+ response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO);
+ if (!response)
+ return MHD_NO;
+
+ headervalue = malloc (strlen (strbase) + strlen (realm) + 1);
+ if (!headervalue)
+ return MHD_NO;
+
+ strcpy (headervalue, strbase);
+ strcat (headervalue, realm);
+
+ ret = MHD_add_response_header (response, "WWW-Authenticate", headervalue);
+ free (headervalue);
+ if (!ret)
+ {
+ MHD_destroy_response (response);
+ return MHD_NO;
+ }
+
+ ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response);
+
+ MHD_destroy_response (response);
+
+ return ret;
+}
+
+int
+is_authenticated (struct MHD_Connection *connection,
+ const char *username, const char *password)
+{
+ const char *headervalue;
+ char *expected_b64, *expected;
+ const char *strbase = "Basic ";
+ int authenticated;
+
+ headervalue =
+ MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
+ "Authorization");
+ if (NULL == headervalue)
+ return 0;
+ if (0 != strncmp (headervalue, strbase, strlen (strbase)))
+ return 0;
+
+ expected = malloc (strlen (username) + 1 + strlen (password) + 1);
+ if (NULL == expected)
+ return 0;
+
+ strcpy (expected, username);
+ strcat (expected, ":");
+ strcat (expected, password);
+
+ expected_b64 = string_to_base64 (expected);
+ if (NULL == expected_b64)
+ return 0;
+
+ strcpy (expected, strbase);
+ authenticated =
+ (strcmp (headervalue + strlen (strbase), expected_b64) == 0);
+
+ free (expected_b64);
+
+ return authenticated;
+}
+
+
+int
+secret_page (struct MHD_Connection *connection)
+{
+ int ret;
+ struct MHD_Response *response;
+ const char *page = "<html><body>A secret.</body></html>";
+
+ response =
+ MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
+ MHD_NO);
+ if (!response)
+ return MHD_NO;
+
+ ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+ MHD_destroy_response (response);
+
+ return ret;
+}
+
+
+int
+answer_to_connection (void *cls, struct MHD_Connection *connection,
+ const char *url, const char *method,
+ const char *version, const char *upload_data,
+ unsigned int *upload_data_size, void **con_cls)
+{
+ if (0 != strcmp (method, "GET"))
+ return MHD_NO;
+ if (NULL == *con_cls)
+ {
+ *con_cls = connection;
+ return MHD_YES;
+ }
+
+ if (!is_authenticated (connection, USER, PASSWORD))
+ return ask_for_authentication (connection, REALM);
+
+ return secret_page (connection);
+}
+
+
+int
+main ()
+{
+ struct MHD_Daemon *daemon;
+ char *key_pem;
+ char *cert_pem;
+
+ key_pem = load_file (SERVERKEYFILE);
+ cert_pem = load_file (SERVERCERTFILE);
+
+ if ((key_pem == NULL) || (cert_pem == NULL))
+ {
+ printf ("The key/certificate files could not be read.\n");
+ return 1;
+ }
+
+ daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL, PORT,
NULL, NULL,
+ &answer_to_connection, NULL,
+ MHD_OPTION_HTTPS_MEM_KEY, key_pem,
MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
+ MHD_OPTION_END);
+ if (NULL == daemon)
+ {
+ printf ("%s\n", cert_pem);
+
+ free (key_pem);
+ free (cert_pem);
+
+ return 1;
+ }
+
+ getchar ();
+
+ MHD_stop_daemon (daemon);
+ free (key_pem);
+ free (cert_pem);
+
+ return 0;
+}
+
+
+char *
+string_to_base64 (const char *message)
+{
+ const char *lookup =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ unsigned long l;
+ int i;
+ char *tmp;
+ size_t length = strlen (message);
+
+ tmp = malloc (length * 2);
+ if (NULL == tmp)
+ return tmp;
+
+ tmp[0] = 0;
+
+ for (i = 0; i < length; i += 3)
+ {
+ l = (((unsigned long) message[i]) << 16)
+ | (((i + 1) < length) ? (((unsigned long) message[i + 1]) << 8) : 0)
+ | (((i + 2) < length) ? ((unsigned long) message[i + 2]) : 0);
+
+
+ strncat (tmp, &lookup[(l >> 18) & 0x3F], 1);
+ strncat (tmp, &lookup[(l >> 12) & 0x3F], 1);
+
+ if (i + 1 < length)
+ strncat (tmp, &lookup[(l >> 6) & 0x3F], 1);
+ if (i + 2 < length)
+ strncat (tmp, &lookup[l & 0x3F], 1);
+ }
+
+ if (length % 3)
+ strncat (tmp, "===", 3 - length % 3);
+
+ return tmp;
+}
+
Modified: libmicrohttpd/doc/tutorial.texi
===================================================================
--- libmicrohttpd/doc/tutorial.texi 2008-10-11 14:08:15 UTC (rev 7752)
+++ libmicrohttpd/doc/tutorial.texi 2008-10-11 17:55:14 UTC (rev 7753)
@@ -39,6 +39,7 @@
* Supporting basic authentication::
* Processing POST data::
* Improved processing of POST data::
+* Adding a layer of security::
* Bibliography::
* License text::
* Example programs::
@@ -72,6 +73,10 @@
@chapter Improved processing of POST data
@include chapters/largerpost.inc
address@hidden Adding a layer of security
address@hidden Adding a layer of security
address@hidden chapters/tlsauthentication.inc
+
@node Bibliography
@appendix Bibliography
@include chapters/bibliography.inc
@@ -89,6 +94,7 @@
* basicauthentication.c::
* simplepost.c::
* largepost.c::
+* tlsauthentication.c::
@end menu
@node hellobrowser.c
@@ -127,5 +133,10 @@
@verbatiminclude examples/largepost.c
@end smalldisplay
address@hidden tlsauthentication.c
address@hidden tlsauthentication.c
address@hidden
address@hidden examples/tlsauthentication.c
address@hidden smalldisplay
@bye
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r7753 - in libmicrohttpd/doc: . chapters examples,
gnunet <=