aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Gerhardt <sebgerhardt@gmx.net>2008-10-11 17:55:14 +0000
committerSebastian Gerhardt <sebgerhardt@gmx.net>2008-10-11 17:55:14 +0000
commit8636c4b3084d678bf99f2ff0ee46d07727e07a8a (patch)
tree677c4fd712ad6751d571da5238edf942893b5c28
parent8bee920d50ed850e0354b18c6b8cd4a993069620 (diff)
downloadlibmicrohttpd-8636c4b3084d678bf99f2ff0ee46d07727e07a8a.tar.gz
libmicrohttpd-8636c4b3084d678bf99f2ff0ee46d07727e07a8a.zip
Tutorial: New chapter for SSL/TLS
-rw-r--r--doc/chapters/tlsauthentication.inc130
-rw-r--r--doc/examples/tlsauthentication.c253
-rw-r--r--doc/tutorial.texi11
3 files changed, 394 insertions, 0 deletions
diff --git a/doc/chapters/tlsauthentication.inc b/doc/chapters/tlsauthentication.inc
new file mode 100644
index 00000000..37b45b8e
--- /dev/null
+++ b/doc/chapters/tlsauthentication.inc
@@ -0,0 +1,130 @@
1We left the basic authentication chapter with the unsatisfactory conclusion that
2any traffic, including the credentials, could be intercepted by anyone between
3the browser client and the server. Protecting the data while it is sent over
4unsecured lines will be the goal of this chapter.
5
6Since version 0.4, the @emph{MHD} library includes support for encrypting the
7traffic by employing SSL/TSL. If @emph{GNU libmicrohttpd} has been configured to
8support these, encryption and decryption can be applied transparently on the
9data being sent, with only minimal changes to the actual source code of the example.
10
11
12@heading Preparation
13
14First, a private key for the server will be generated. With this key, the server
15will later be able to authenticate itself to the client---preventing anyone else
16from stealing the password by faking its identity. The @emph{OpenSSL} suite, which
17is available on many operating systems, can generate such a key. For the scope of
18this tutorial, we will be content with a 1024 bit key:
19@verbatim
20> openssl genrsa -out server.key 1024
21@end verbatim
22@noindent
23
24In addition to the key, a certificate describing the server in human readable tokens
25is also needed. This certificate will be attested with our aforementioned key. In this way,
26we obtain a self-signed certificate, valid for one year.
27
28@verbatim
29> openssl req -days 365 -out server.pem -new -x509 -key server.key
30@end verbatim
31@noindent
32
33To avoid unnecessary error messages in the browser, the certificate needs to
34have a name that matches the @emph{URI}, for example, "localhost" or the domain.
35If you plan to have a publicly reachable server, you will need to ask a trusted third party,
36called @emph{Certificate Authority}, or @emph{CA}, to attest the certificate for you. This way,
37any visitor can make sure the server's identity is real.
38
39Whether the server's certificate is signed by us or a third party, once it has been accepted
40by the client, both sides will be communicating over encrypted channels. From this point on,
41it is the client's turn to authenticate itself. But this has already been implemented in the basic
42authentication scheme.
43
44
45@heading Changing the source code
46
47We merely have to extend the server program so that it loads the two files into memory,
48
49@verbatim
50int
51main ()
52{
53 struct MHD_Daemon *daemon;
54 char *key_pem;
55 char *cert_pem;
56
57 key_pem = load_file (SERVERKEYFILE);
58 cert_pem = load_file (SERVERCERTFILE);
59
60 if ((key_pem == NULL) || (cert_pem == NULL))
61 {
62 printf ("The key/certificate files could not be read.\n");
63 return 1;
64 }
65@end verbatim
66@noindent
67
68and then we point the @emph{MHD} daemon to it upon initalization.
69@verbatim
70
71 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL, PORT, NULL, NULL,
72 &answer_to_connection, NULL,
73 MHD_OPTION_HTTPS_MEM_KEY, key_pem,
74 MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
75 MHD_OPTION_END);
76
77 if (NULL == daemon)
78 {
79 printf ("%s\n", cert_pem);
80
81 free (key_pem);
82 free (cert_pem);
83
84 return 1;
85 }
86@end verbatim
87@noindent
88
89
90The rest consists of little new besides some additional memory cleanups.
91@verbatim
92
93 getchar ();
94
95 MHD_stop_daemon (daemon);
96 free (key_pem);
97 free (cert_pem);
98
99 return 0;
100}
101@end verbatim
102@noindent
103
104
105The rather unexciting file loader can be found in the complete example @code{tlsauthentication.c}.
106
107@heading Remarks
108@itemize @bullet
109@item
110While the standard @emph{HTTP} port is 80, it is 443 for @emph{HTTPS}. The common internet browsers assume
111standard @emph{HTTP} if they are asked to access other ports than these. Therefore, you will have to type
112@code{https://localhost:8888} explicitly when you test the example, or the browser will not know how to
113handle the answer properly.
114
115@item
116The remaining weak point is the question how the server will be trusted initially. Either a @emph{CA} signs the
117certificate or the client obtains the key over secure means. Anyway, the clients have to be aware (or configured)
118that they should not accept certificates of unknown origin.
119
120@item
121The introduced method of certificates makes it mandatory to set an expiration date---making it less feasible to
122hardcode certificates in embedded devices.
123
124@item
125The cryptographic facilities consume memory space and computing time. For this reason, websites usually consists
126both of uncritically @emph{HTTP} parts and secured @emph{HTTPS}.
127
128@end itemize
129
130
diff --git a/doc/examples/tlsauthentication.c b/doc/examples/tlsauthentication.c
new file mode 100644
index 00000000..437d795a
--- /dev/null
+++ b/doc/examples/tlsauthentication.c
@@ -0,0 +1,253 @@
1#include <platform.h>
2#include <microhttpd.h>
3
4#define PORT 8888
5
6#define REALM "\"Maintenance\""
7#define USER "a legitimate user"
8#define PASSWORD "and his password"
9
10#define SERVERKEYFILE "server.key"
11#define SERVERCERTFILE "server.pem"
12
13char *string_to_base64 (const char *message);
14
15long
16get_file_size (const char *filename)
17{
18 FILE *fp;
19
20 fp = fopen (filename, "rb");
21 if (fp)
22 {
23 long size;
24
25 if ((0 != fseek (fp, 0, SEEK_END)) || (-1 == (size = ftell (fp))))
26 size = 0;
27
28 fclose (fp);
29
30 return size;
31 }
32 else
33 return 0;
34}
35
36char*
37load_file (const char* filename)
38{
39 FILE *fp;
40 char *buffer;
41 long size;
42
43 size = get_file_size (filename);
44 if (size == 0) return NULL;
45
46 fp = fopen (filename, "rb");
47 if (!fp) return NULL;
48
49 buffer = malloc (size);
50 if (!buffer) {fclose (fp); return NULL;}
51
52 if (size != fread (buffer, 1, size, fp))
53 {
54 free (buffer);
55 buffer = NULL;
56 }
57
58 fclose (fp);
59 return buffer;
60}
61
62int
63ask_for_authentication (struct MHD_Connection *connection, const char *realm)
64{
65 int ret;
66 struct MHD_Response *response;
67 char *headervalue;
68 const char *strbase = "Basic realm=";
69
70 response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO);
71 if (!response)
72 return MHD_NO;
73
74 headervalue = malloc (strlen (strbase) + strlen (realm) + 1);
75 if (!headervalue)
76 return MHD_NO;
77
78 strcpy (headervalue, strbase);
79 strcat (headervalue, realm);
80
81 ret = MHD_add_response_header (response, "WWW-Authenticate", headervalue);
82 free (headervalue);
83 if (!ret)
84 {
85 MHD_destroy_response (response);
86 return MHD_NO;
87 }
88
89 ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response);
90
91 MHD_destroy_response (response);
92
93 return ret;
94}
95
96int
97is_authenticated (struct MHD_Connection *connection,
98 const char *username, const char *password)
99{
100 const char *headervalue;
101 char *expected_b64, *expected;
102 const char *strbase = "Basic ";
103 int authenticated;
104
105 headervalue =
106 MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
107 "Authorization");
108 if (NULL == headervalue)
109 return 0;
110 if (0 != strncmp (headervalue, strbase, strlen (strbase)))
111 return 0;
112
113 expected = malloc (strlen (username) + 1 + strlen (password) + 1);
114 if (NULL == expected)
115 return 0;
116
117 strcpy (expected, username);
118 strcat (expected, ":");
119 strcat (expected, password);
120
121 expected_b64 = string_to_base64 (expected);
122 if (NULL == expected_b64)
123 return 0;
124
125 strcpy (expected, strbase);
126 authenticated =
127 (strcmp (headervalue + strlen (strbase), expected_b64) == 0);
128
129 free (expected_b64);
130
131 return authenticated;
132}
133
134
135int
136secret_page (struct MHD_Connection *connection)
137{
138 int ret;
139 struct MHD_Response *response;
140 const char *page = "<html><body>A secret.</body></html>";
141
142 response =
143 MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
144 MHD_NO);
145 if (!response)
146 return MHD_NO;
147
148 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
149 MHD_destroy_response (response);
150
151 return ret;
152}
153
154
155int
156answer_to_connection (void *cls, struct MHD_Connection *connection,
157 const char *url, const char *method,
158 const char *version, const char *upload_data,
159 unsigned int *upload_data_size, void **con_cls)
160{
161 if (0 != strcmp (method, "GET"))
162 return MHD_NO;
163 if (NULL == *con_cls)
164 {
165 *con_cls = connection;
166 return MHD_YES;
167 }
168
169 if (!is_authenticated (connection, USER, PASSWORD))
170 return ask_for_authentication (connection, REALM);
171
172 return secret_page (connection);
173}
174
175
176int
177main ()
178{
179 struct MHD_Daemon *daemon;
180 char *key_pem;
181 char *cert_pem;
182
183 key_pem = load_file (SERVERKEYFILE);
184 cert_pem = load_file (SERVERCERTFILE);
185
186 if ((key_pem == NULL) || (cert_pem == NULL))
187 {
188 printf ("The key/certificate files could not be read.\n");
189 return 1;
190 }
191
192 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL, PORT, NULL, NULL,
193 &answer_to_connection, NULL,
194 MHD_OPTION_HTTPS_MEM_KEY, key_pem, MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
195 MHD_OPTION_END);
196 if (NULL == daemon)
197 {
198 printf ("%s\n", cert_pem);
199
200 free (key_pem);
201 free (cert_pem);
202
203 return 1;
204 }
205
206 getchar ();
207
208 MHD_stop_daemon (daemon);
209 free (key_pem);
210 free (cert_pem);
211
212 return 0;
213}
214
215
216char *
217string_to_base64 (const char *message)
218{
219 const char *lookup =
220 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
221 unsigned long l;
222 int i;
223 char *tmp;
224 size_t length = strlen (message);
225
226 tmp = malloc (length * 2);
227 if (NULL == tmp)
228 return tmp;
229
230 tmp[0] = 0;
231
232 for (i = 0; i < length; i += 3)
233 {
234 l = (((unsigned long) message[i]) << 16)
235 | (((i + 1) < length) ? (((unsigned long) message[i + 1]) << 8) : 0)
236 | (((i + 2) < length) ? ((unsigned long) message[i + 2]) : 0);
237
238
239 strncat (tmp, &lookup[(l >> 18) & 0x3F], 1);
240 strncat (tmp, &lookup[(l >> 12) & 0x3F], 1);
241
242 if (i + 1 < length)
243 strncat (tmp, &lookup[(l >> 6) & 0x3F], 1);
244 if (i + 2 < length)
245 strncat (tmp, &lookup[l & 0x3F], 1);
246 }
247
248 if (length % 3)
249 strncat (tmp, "===", 3 - length % 3);
250
251 return tmp;
252}
253
diff --git a/doc/tutorial.texi b/doc/tutorial.texi
index bc6ebe54..7b9b877e 100644
--- a/doc/tutorial.texi
+++ b/doc/tutorial.texi
@@ -39,6 +39,7 @@ Free Documentation License".
39* Supporting basic authentication:: 39* Supporting basic authentication::
40* Processing POST data:: 40* Processing POST data::
41* Improved processing of POST data:: 41* Improved processing of POST data::
42* Adding a layer of security::
42* Bibliography:: 43* Bibliography::
43* License text:: 44* License text::
44* Example programs:: 45* Example programs::
@@ -72,6 +73,10 @@ Free Documentation License".
72@chapter Improved processing of POST data 73@chapter Improved processing of POST data
73@include chapters/largerpost.inc 74@include chapters/largerpost.inc
74 75
76@node Adding a layer of security
77@chapter Adding a layer of security
78@include chapters/tlsauthentication.inc
79
75@node Bibliography 80@node Bibliography
76@appendix Bibliography 81@appendix Bibliography
77@include chapters/bibliography.inc 82@include chapters/bibliography.inc
@@ -89,6 +94,7 @@ Free Documentation License".
89* basicauthentication.c:: 94* basicauthentication.c::
90* simplepost.c:: 95* simplepost.c::
91* largepost.c:: 96* largepost.c::
97* tlsauthentication.c::
92@end menu 98@end menu
93 99
94@node hellobrowser.c 100@node hellobrowser.c
@@ -127,5 +133,10 @@ Free Documentation License".
127@verbatiminclude examples/largepost.c 133@verbatiminclude examples/largepost.c
128@end smalldisplay 134@end smalldisplay
129 135
136@node tlsauthentication.c
137@section tlsauthentication.c
138@smalldisplay
139@verbatiminclude examples/tlsauthentication.c
140@end smalldisplay
130 141
131@bye 142@bye