aboutsummaryrefslogtreecommitdiff
path: root/doc/examples/tlsauthentication.c
diff options
context:
space:
mode:
Diffstat (limited to 'doc/examples/tlsauthentication.c')
-rw-r--r--doc/examples/tlsauthentication.c253
1 files changed, 253 insertions, 0 deletions
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