blob: 79632a403bde04386566eaefb6c3c3f100ebbd74 [file] [log] [blame]
Daniel Erat748945e2015-08-11 09:22:30 -06001This is libmicrohttpd-tutorial.info, produced by makeinfo version 4.13
2from libmicrohttpd-tutorial.texi.
3
4INFO-DIR-SECTION Software libraries
5START-INFO-DIR-ENTRY
6* libmicrohttpdtutorial: (libmicrohttpd). A tutorial for GNU libmicrohttpd.
7END-INFO-DIR-ENTRY
8
9 This tutorial documents GNU libmicrohttpd version 0.9.23, last
10updated 17 November 2013.
11
12 Copyright (c) 2008 Sebastian Gerhardt.
13
14 Copyright (c) 2010, 2011, 2012, 2013 Christian Grothoff.
15
16 Permission is granted to copy, distribute and/or modify this
17 document under the terms of the GNU Free Documentation License,
18 Version 1.3 or any later version published by the Free Software
19 Foundation; with no Invariant Sections, no Front-Cover Texts, and
20 no Back-Cover Texts. A copy of the license is included in the
21 section entitled "GNU Free Documentation License".
22
23
24File: libmicrohttpd-tutorial.info, Node: Top, Next: Introduction, Up: (dir)
25
26A Tutorial for GNU libmicrohttpd
27********************************
28
29This tutorial documents GNU libmicrohttpd version 0.9.23, last updated
3017 November 2013.
31
32 Copyright (c) 2008 Sebastian Gerhardt.
33
34 Copyright (c) 2010, 2011, 2012, 2013 Christian Grothoff.
35
36 Permission is granted to copy, distribute and/or modify this
37 document under the terms of the GNU Free Documentation License,
38 Version 1.3 or any later version published by the Free Software
39 Foundation; with no Invariant Sections, no Front-Cover Texts, and
40 no Back-Cover Texts. A copy of the license is included in the
41 section entitled "GNU Free Documentation License".
42
43* Menu:
44
45* Introduction::
46* Hello browser example::
47* Exploring requests::
48* Response headers::
49* Supporting basic authentication::
50* Processing POST data::
51* Improved processing of POST data::
52* Session management::
53* Adding a layer of security::
54* Bibliography::
55* License text::
56* Example programs::
57
58
59File: libmicrohttpd-tutorial.info, Node: Introduction, Next: Hello browser example, Prev: Top, Up: Top
60
611 Introduction
62**************
63
64This tutorial is for developers who want to learn how they can add HTTP
65serving capabilities to their applications with the _GNU libmicrohttpd_
66library, abbreviated _MHD_. The reader will learn how to implement
67basic HTTP functions from simple executable sample programs that
68implement various features.
69
70 The text is supposed to be a supplement to the API reference manual
71of _GNU libmicrohttpd_ and for that reason does not explain many of the
72parameters. Therefore, the reader should always consult the manual to
73find the exact meaning of the functions used in the tutorial.
74Furthermore, the reader is encouraged to study the relevant _RFCs_,
75which document the HTTP standard.
76
77 _GNU libmicrohttpd_ is assumed to be already installed. This
78tutorial is written for version 0.9.23. At the time being, this
79tutorial has only been tested on _GNU/Linux_ machines even though
80efforts were made not to rely on anything that would prevent the
81samples from being built on similar systems.
82
831.1 History
84===========
85
86This tutorial was originally written by Sebastian Gerhardt for MHD
870.4.0. It was slighly polished and updated to MHD 0.9.0 by Christian
88Grothoff.
89
90
91File: libmicrohttpd-tutorial.info, Node: Hello browser example, Next: Exploring requests, Prev: Introduction, Up: Top
92
932 Hello browser example
94***********************
95
96The most basic task for a HTTP server is to deliver a static text
97message to any client connecting to it. Given that this is also easy
98to implement, it is an excellent problem to start with.
99
100 For now, the particular URI the client asks for shall have no effect
101on the message that will be returned. In addition, the server shall end
102the connection after the message has been sent so that the client will
103know there is nothing more to expect.
104
105 The C program `hellobrowser.c', which is to be found in the examples
106section, does just that. If you are very eager, you can compile and
107start it right away but it is advisable to type the lines in by
108yourself as they will be discussed and explained in detail.
109
110 After the necessary includes and the definition of the port which
111our server should listen on
112#include <sys/types.h>
113#include <sys/select.h>
114#include <sys/socket.h>
115#include <microhttpd.h>
116
117#define PORT 8888
118
119the desired behaviour of our server when HTTP request arrive has to be
120implemented. We already have agreed that it should not care about the
121particular details of the request, such as who is requesting what. The
122server will respond merely with the same small HTML page to every
123request.
124
125 The function we are going to write now will be called by _GNU
126libmicrohttpd_ every time an appropriate request comes in. While the
127name of this callback function is arbitrary, its parameter list has to
128follow a certain layout. So please, ignore the lot of parameters for
129now, they will be explained at the point they are needed. We have to
130use only one of them, `struct MHD_Connection *connection', for the
131minimalistic functionality we want to archive at the moment.
132
133 This parameter is set by the _libmicrohttpd_ daemon and holds the
134necessary information to relate the call with a certain connection.
135Keep in mind that a server might have to satisfy hundreds of concurrent
136connections and we have to make sure that the correct data is sent to
137the destined client. Therefore, this variable is a means to refer to a
138particular connection if we ask the daemon to sent the reply.
139
140 Talking about the reply, it is defined as a string right after the
141function header
142int answer_to_connection (void *cls, struct MHD_Connection *connection,
143 const char *url,
144 const char *method, const char *version,
145 const char *upload_data,
146 size_t *upload_data_size, void **con_cls)
147{
148 const char *page = "<html><body>Hello, browser!</body></html>";
149
150HTTP is a rather strict protocol and the client would certainly
151consider it "inappropriate" if we just sent the answer string "as is".
152Instead, it has to be wrapped with additional information stored in
153so-called headers and footers. Most of the work in this area is done
154by the library for us--we just have to ask. Our reply string packed in
155the necessary layers will be called a "response". To obtain such a
156response we hand our data (the reply-string) and its size over to the
157`MHD_create_response_from_buffer' function. The last two parameters
158basically tell _MHD_ that we do not want it to dispose the message data
159for us when it has been sent and there also needs no internal copy to
160be done because the _constant_ string won't change anyway.
161
162 struct MHD_Response *response;
163 int ret;
164
165 response = MHD_create_response_from_buffer (strlen (page),
166 (void*) page, MHD_RESPMEM_PERSISTENT);
167
168Now that the the response has been laced up, it is ready for delivery
169and can be queued for sending. This is done by passing it to another
170_GNU libmicrohttpd_ function. As all our work was done in the scope of
171one function, the recipient is without doubt the one associated with the
172local variable `connection' and consequently this variable is given to
173the queue function. Every HTTP response is accompanied by a status
174code, here "OK", so that the client knows this response is the intended
175result of his request and not due to some error or malfunction.
176
177 Finally, the packet is destroyed and the return value from the queue
178returned, already being set at this point to either MHD_YES or MHD_NO
179in case of success or failure.
180
181 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
182 MHD_destroy_response (response);
183
184 return ret;
185}
186
187With the primary task of our server implemented, we can start the
188actual server daemon which will listen on `PORT' for connections. This
189is done in the main function.
190int main ()
191{
192 struct MHD_Daemon *daemon;
193
194 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
195 &answer_to_connection, NULL, MHD_OPTION_END);
196 if (NULL == daemon) return 1;
197
198The first parameter is one of three possible modes of operation. Here
199we want the daemon to run in a separate thread and to manage all
200incoming connections in the same thread. This means that while
201producing the response for one connection, the other connections will
202be put on hold. In this example, where the reply is already known and
203therefore the request is served quickly, this poses no problem.
204
205 We will allow all clients to connect regardless of their name or
206location, therefore we do not check them on connection and set the
207forth and fifth parameter to NULL.
208
209 Parameter six is the address of the function we want to be called
210whenever a new connection has been established. Our
211`answer_to_connection' knows best what the client wants and needs no
212additional information (which could be passed via the next parameter)
213so the next parameter is NULL. Likewise, we do not need to pass extra
214options to the daemon so we just write the MHD_OPTION_END as the last
215parameter.
216
217 As the server daemon runs in the background in its own thread, the
218execution flow in our main function will contine right after the call.
219Because of this, we must delay the execution flow in the main thread or
220else the program will terminate prematurely. We let it pause in a
221processing-time friendly manner by waiting for the enter key to be
222pressed. In the end, we stop the daemon so it can do its cleanup tasks.
223 getchar ();
224
225 MHD_stop_daemon (daemon);
226 return 0;
227}
228
229The first example is now complete.
230
231 Compile it with
232cc hellobrowser.c -o hellobrowser -I$PATH_TO_LIBMHD_INCLUDES
233 -L$PATH_TO_LIBMHD_LIBS -lmicrohttpd
234 with the two paths set accordingly and run it.
235
236 Now open your favorite Internet browser and go to the address
237`http://localhost:8888/', provided that 8888 is the port you chose. If
238everything works as expected, the browser will present the message of
239the static HTML page it got from our minimal server.
240
241Remarks
242=======
243
244To keep this first example as small as possible, some drastic shortcuts
245were taken and are to be discussed now.
246
247 Firstly, there is no distinction made between the kinds of requests
248a client could send. We implied that the client sends a GET request,
249that means, that he actually asked for some data. Even when it is not
250intended to accept POST requests, a good server should at least
251recognize that this request does not constitute a legal request and
252answer with an error code. This can be easily implemented by checking
253if the parameter `method' equals the string "GET" and returning a
254`MHD_NO' if not so.
255
256 Secondly, the above practice of queuing a response upon the first
257call of the callback function brings with it some limitations. This is
258because the content of the message body will not be received if a
259response is queued in the first iteration. Furthermore, the connection
260will be closed right after the response has been transferred then.
261This is typically not what you want as it disables HTTP pipelining.
262The correct approach is to simply not queue a message on the first
263callback unless there is an error. The `void**' argument to the
264callback provides a location for storing information about the history
265of the connection; for the first call, the pointer will point to NULL.
266A simplistic way to differenciate the first call from others is to check
267if the pointer is NULL and set it to a non-NULL value during the first
268call.
269
270 Both of these issues you will find addressed in the official
271`minimal_example.c' residing in the `src/examples' directory of the
272_MHD_ package. The source code of this program should look very
273familiar to you by now and easy to understand.
274
275 For our example, the `must_copy' and `must_free' parameter at the
276response construction function could be set to `MHD_NO'. In the usual
277case, responses cannot be sent immediately after being queued. For
278example, there might be other data on the system that needs to be sent
279with a higher priority. Nevertheless, the queue function will return
280successfully--raising the problem that the data we have pointed to may
281be invalid by the time it is about being sent. This is not an issue
282here because we can expect the `page' string, which is a constant
283_string literal_ here, to be static. That means it will be present and
284unchanged for as long as the program runs. For dynamic data, one could
285choose to either have _MHD_ free the memory `page' points to itself
286when it is not longer needed or, alternatively, have the library to
287make and manage its own copy of it.
288
289Exercises
290=========
291
292 * While the server is running, use a program like `telnet' or
293 `netcat' to connect to it. Try to form a valid HTTP 1.1 request
294 yourself like GET /dontcare HTTP/1.1
295 Host: itsme
296 <enter>
297 and see what the server returns to you.
298
299 * Also, try other requests, like POST, and see how our server does
300 not mind and why. How far in malforming a request can you go
301 before the builtin functionality of _MHD_ intervenes and an
302 altered response is sent? Make sure you read about the status
303 codes in the _RFC_.
304
305 * Add the option `MHD_USE_PEDANTIC_CHECKS' to the start function of
306 the daemon in `main'. Mind the special format of the parameter
307 list here which is described in the manual. How indulgent is the
308 server now to your input?
309
310 * Let the main function take a string as the first command line
311 argument and pass `argv[1]' to the `MHD_start_daemon' function as
312 the sixth parameter. The address of this string will be passed to
313 the callback function via the `cls' variable. Decorate the text
314 given at the command line when the server is started with proper
315 HTML tags and send it as the response instead of the former static
316 string.
317
318 * _Demanding:_ Write a separate function returning a string
319 containing some useful information, for example, the time. Pass
320 the function's address as the sixth parameter and evaluate this
321 function on every request anew in `answer_to_connection'. Remember
322 to free the memory of the string every time after satisfying the
323 request.
324
325
326
327File: libmicrohttpd-tutorial.info, Node: Exploring requests, Next: Response headers, Prev: Hello browser example, Up: Top
328
3293 Exploring requests
330********************
331
332This chapter will deal with the information which the client sends to
333the server at every request. We are going to examine the most useful
334fields of such an request and print them out in a readable manner. This
335could be useful for logging facilities.
336
337 The starting point is the _hellobrowser_ program with the former
338response removed.
339
340 This time, we just want to collect information in the callback
341function, thus we will just return MHD_NO after we have probed the
342request. This way, the connection is closed without much ado by the
343server.
344
345static int
346answer_to_connection (void *cls, struct MHD_Connection *connection,
347 const char *url,
348 const char *method, const char *version,
349 const char *upload_data,
350 size_t *upload_data_size, void **con_cls)
351{
352 ...
353 return MHD_NO;
354}
355 The ellipsis marks the position where the following instructions shall
356be inserted.
357
358 We begin with the most obvious information available to the server,
359the request line. You should already have noted that a request consists
360of a command (or "HTTP method") and a URI (e.g. a filename). It also
361contains a string for the version of the protocol which can be found in
362`version'. To call it a "new request" is justified because we return
363only `MHD_NO', thus ensuring the function will not be called again for
364this connection.
365printf ("New %s request for %s using version %s\n", method, url, version);
366 The rest of the information is a bit more hidden. Nevertheless, there
367is lot of it sent from common Internet browsers. It is stored in
368"key-value" pairs and we want to list what we find in the header. As
369there is no mandatory set of keys a client has to send, each key-value
370pair is printed out one by one until there are no more left. We do this
371by writing a separate function which will be called for each pair just
372like the above function is called for each HTTP request. It can then
373print out the content of this pair.
374int print_out_key (void *cls, enum MHD_ValueKind kind,
375 const char *key, const char *value)
376{
377 printf ("%s: %s\n", key, value);
378 return MHD_YES;
379}
380 To start the iteration process that calls our new function for every
381key, the line
382MHD_get_connection_values (connection, MHD_HEADER_KIND, &print_out_key, NULL);
383 needs to be inserted in the connection callback function too. The
384second parameter tells the function that we are only interested in keys
385from the general HTTP header of the request. Our iterating function
386`print_out_key' does not rely on any additional information to fulfill
387its duties so the last parameter can be NULL.
388
389 All in all, this constitutes the complete `logging.c' program for
390this chapter which can be found in the `examples' section.
391
392 Connecting with any modern Internet browser should yield a handful
393of keys. You should try to interpret them with the aid of _RFC 2616_.
394Especially worth mentioning is the "Host" key which is often used to
395serve several different websites hosted under one single IP address but
396reachable by different domain names (this is called virtual hosting).
397
398Conclusion
399==========
400
401The introduced capabilities to itemize the content of a simple GET
402request--especially the URI--should already allow the server to satisfy
403clients' requests for small specific resources (e.g. files) or even
404induce alteration of server state. However, the latter is not
405recommended as the GET method (including its header data) is by
406convention considered a "safe" operation, which should not change the
407server's state in a significant way. By convention, GET operations can
408thus be performed by crawlers and other automatic software. Naturally
409actions like searching for a passed string are fine.
410
411 Of course, no transmission can occur while the return value is still
412set to `MHD_NO' in the callback function.
413
414Exercises
415=========
416
417 * By parsing the `url' string and delivering responses accordingly,
418 implement a small server for "virtual" files. When asked for
419 `/index.htm{l}', let the response consist of a HTML page
420 containing a link to `/another.html' page which is also to be
421 created "on the fly" in case of being requested. If neither of
422 these two pages are requested, `MHD_HTTP_NOT_FOUND' shall be
423 returned accompanied by an informative message.
424
425 * A very interesting information has still been ignored by our
426 logger--the client's IP address. Implement a callback function static int on_client_connect (void *cls,
427 const struct sockaddr *addr,
428 socklen_t addrlen)
429 that prints out the IP address in an appropriate format. You
430 might want to use the POSIX function `inet_ntoa' but bear in mind
431 that `addr' is actually just a structure containing other
432 substructures and is _not_ the variable this function expects.
433 Make sure to return `MHD_YES' so that the library knows the client
434 is allowed to connect (and to then process the request). If one
435 wanted to limit access basing on IP addresses, this would be the
436 place to do it. The address of your `on_client_connect' function
437 must be passed as the third parameter to the `MHD_start_daemon'
438 call.
439
440
441
442File: libmicrohttpd-tutorial.info, Node: Response headers, Next: Supporting basic authentication, Prev: Exploring requests, Up: Top
443
4444 Response headers
445******************
446
447Now that we are able to inspect the incoming request in great detail,
448this chapter discusses the means to enrich the outgoing responses
449likewise.
450
451 As you have learned in the _Hello, Browser_ chapter, some obligatory
452header fields are added and set automatically for simple responses by
453the library itself but if more advanced features are desired,
454additional fields have to be created. One of the possible fields is
455the content type field and an example will be developed around it.
456This will lead to an application capable of correctly serving different
457types of files.
458
459 When we responded with HTML page packed in the static string
460previously, the client had no choice but guessing about how to handle
461the response, because the server had not told him. What if we had sent
462a picture or a sound file? Would the message have been understood or
463merely been displayed as an endless stream of random characters in the
464browser? This is what the mime content types are for. The header of
465the response is extended by certain information about how the data is
466to be interpreted.
467
468 To introduce the concept, a picture of the format _PNG_ will be sent
469to the client and labeled accordingly with `image/png'. Once again, we
470can base the new example on the `hellobrowser' program.
471
472#define FILENAME "picture.png"
473#define MIMETYPE "image/png"
474
475static int
476answer_to_connection (void *cls, struct MHD_Connection *connection,
477 const char *url,
478 const char *method, const char *version,
479 const char *upload_data,
480 size_t *upload_data_size, void **con_cls)
481{
482 unsigned char *buffer = NULL;
483 struct MHD_Response *response;
484 We want the program to open the file for reading and determine its
485size:
486 int fd;
487 int ret;
488 struct stat sbuf;
489
490 if (0 != strcmp (method, "GET"))
491 return MHD_NO;
492 if ( (-1 == (fd = open (FILENAME, O_RDONLY))) ||
493 (0 != fstat (fd, &sbuf)) )
494 {
495 /* error accessing file */
496 /* ... (see below) */
497 }
498 /* ... (see below) */
499 When dealing with files, there is a lot that could go wrong on the
500server side and if so, the client should be informed with
501`MHD_HTTP_INTERNAL_SERVER_ERROR'.
502
503 /* error accessing file */
504 if (fd != -1) close (fd);
505 const char *errorstr =
506 "<html><body>An internal server error has occured!\
507 </body></html>";
508 response =
509 MHD_create_response_from_buffer (strlen (errorstr),
510 (void *) errorstr,
511 MHD_RESPMEM_PERSISTENT);
512 if (response)
513 {
514 ret =
515 MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
516 response);
517 MHD_destroy_response (response);
518
519 return MHD_YES;
520 }
521 else
522 return MHD_NO;
523 if (!ret)
524 {
525 const char *errorstr = "<html><body>An internal server error has occured!\
526 </body></html>";
527
528 if (buffer) free(buffer);
529
530 response = MHD_create_response_from_buffer (strlen(errorstr), (void*) errorstr,
531 MHD_RESPMEM_PERSISTENT);
532
533 if (response)
534 {
535 ret = MHD_queue_response (connection,
536 MHD_HTTP_INTERNAL_SERVER_ERROR,
537 response);
538 MHD_destroy_response (response);
539
540 return MHD_YES;
541 }
542 else return MHD_NO;
543 }
544 Note that we nevertheless have to create a response object even for
545sending a simple error code. Otherwise, the connection would just be
546closed without comment, leaving the client curious about what has
547happened.
548
549 But in the case of success a response will be constructed directly
550from the file descriptor:
551
552 /* error accessing file */
553 /* ... (see above) */
554 }
555
556 response =
557 MHD_create_response_from_fd_at_offset (sbuf.st_size, fd, 0);
558 MHD_add_response_header (response, "Content-Type", MIMETYPE);
559 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
560 MHD_destroy_response (response);
561 Note that the response object will take care of closing the file
562desciptor for us.
563
564 Up to this point, there was little new. The actual novelty is that
565we enhance the header with the meta data about the content. Aware of
566the field's name we want to add, it is as easy as that:
567MHD_add_response_header(response, "Content-Type", MIMETYPE);
568 We do not have to append a colon expected by the protocol behind the
569first field--_GNU libhttpdmicro_ will take care of this.
570
571 The function finishes with the well-known lines
572 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
573 MHD_destroy_response (response);
574 return ret;
575}
576 The complete program `responseheaders.c' is in the `examples' section
577as usual. Find a _PNG_ file you like and save it to the directory the
578example is run from under the name `picture.png'. You should find the
579image displayed on your browser if everything worked well.
580
581Remarks
582=======
583
584The include file of the _MHD_ library comes with the header types
585mentioned in _RFC 2616_ already defined as macros. Thus, we could have
586written `MHD_HTTP_HEADER_CONTENT_TYPE' instead of `"Content-Type"' as
587well. However, one is not limited to these standard headers and could
588add custom response headers without violating the protocol. Whether,
589and how, the client would react to these custom header is up to the
590receiver. Likewise, the client is allowed to send custom request
591headers to the server as well, opening up yet more possibilities how
592client and server could communicate with each other.
593
594 The method of creating the response from a file on disk only works
595for static content. Serving dynamically created responses will be a
596topic of a future chapter.
597
598Exercises
599=========
600
601 * Remember that the original program was written under a few
602 assumptions--a static response using a local file being one of
603 them. In order to simulate a very large or hard to reach file that
604 cannot be provided instantly, postpone the queuing in the callback
605 with the `sleep' function for 30 seconds _if_ the file `/big.png'
606 is requested (but deliver the same as above). A request for
607 `/picture.png' should provide just the same but without any
608 artificial delays.
609
610 Now start two instances of your browser (or even use two machines)
611 and see how the second client is put on hold while the first waits
612 for his request on the slow file to be fulfilled.
613
614 Finally, change the sourcecode to use
615 `MHD_USE_THREAD_PER_CONNECTION' when the daemon is started and try
616 again.
617
618 * Did you succeed in implementing the clock exercise yet? This time,
619 let the server save the program's start time `t' and implement a
620 response simulating a countdown that reaches 0 at `t+60'.
621 Returning a message saying on which point the countdown is, the
622 response should ultimately be to reply "Done" if the program has
623 been running long enough,
624
625 An unofficial, but widely understood, response header line is
626 `Refresh: DELAY; url=URL' with the uppercase words substituted to
627 tell the client it should request the given resource after the
628 given delay again. Improve your program in that the browser (any
629 modern browser should work) automatically reconnects and asks for
630 the status again every 5 seconds or so. The URL would have to be
631 composed so that it begins with "http://", followed by the _URI_
632 the server is reachable from the client's point of view.
633
634 Maybe you want also to visualize the countdown as a status bar by
635 creating a `<table>' consisting of one row and `n' columns whose
636 fields contain small images of either a red or a green light.
637
638
639
640File: libmicrohttpd-tutorial.info, Node: Supporting basic authentication, Next: Processing POST data, Prev: Response headers, Up: Top
641
6425 Supporting basic authentication
643*********************************
644
645With the small exception of IP address based access control, requests
646from all connecting clients where served equally until now. This
647chapter discusses a first method of client's authentication and its
648limits.
649
650 A very simple approach feasible with the means already discussed
651would be to expect the password in the _URI_ string before granting
652access to the secured areas. The password could be separated from the
653actual resource identifier by a certain character, thus the request
654line might look like
655GET /picture.png?mypassword
656 In the rare situation where the client is customized enough and the
657connection occurs through secured lines (e.g., a embedded device
658directly attached to another via wire) and where the ability to embedd
659a password in the URI or to pass on a URI with a password are desired,
660this can be a reasonable choice.
661
662 But when it is assumed that the user connecting does so with an
663ordinary Internet browser, this implementation brings some problems
664about. For example, the URI including the password stays in the address
665field or at least in the history of the browser for anybody near enough
666to see. It will also be inconvenient to add the password manually to
667any new URI when the browser does not know how to compose this
668automatically.
669
670 At least the convenience issue can be addressed by employing the
671simplest built-in password facilities of HTTP compliant browsers, hence
672we want to start there. It will however turn out to have still severe
673weaknesses in terms of security which need consideration.
674
675 Before we will start implementing _Basic Authentication_ as
676described in _RFC 2617_, we should finally abandon the bad practice of
677responding every request the first time our callback is called for a
678given connection. This is becoming more important now because the
679client and the server will have to talk in a more bi-directional way
680than before to
681
682 But how can we tell whether the callback has been called before for
683the particular connection? Initially, the pointer this parameter
684references is set by _MHD_ in the callback. But it will also be
685"remembered" on the next call (for the same connection). Thus, we will
686generate no response until the parameter is non-null--implying the
687callback was called before at least once. We do not need to share
688information between different calls of the callback, so we can set the
689parameter to any adress that is assured to be not null. The pointer to
690the `connection' structure will be pointing to a legal address, so we
691take this.
692
693 The first time `answer_to_connection' is called, we will not even
694look at the headers.
695
696static int
697answer_to_connection (void *cls, struct MHD_Connection *connection,
698 const char *url, const char *method, const char *version,
699 const char *upload_data, size_t *upload_data_size,
700 void **con_cls)
701{
702 if (0 != strcmp(method, "GET")) return MHD_NO;
703 if (NULL == *con_cls) {*con_cls = connection; return MHD_YES;}
704
705 ...
706 /* else respond accordingly */
707 ...
708}
709 Note how we lop off the connection on the first condition (no "GET"
710request), but return asking for more on the other one with `MHD_YES'.
711With this minor change, we can proceed to implement the actual
712authentication process.
713
714Request for authentication
715==========================
716
717Let us assume we had only files not intended to be handed out without
718the correct username/password, so every "GET" request will be
719challenged. _RFC 2617_ describes how the server shall ask for
720authentication by adding a _WWW-Authenticate_ response header with the
721name of the _realm_ protected. MHD can generate and queue such a
722failure response for you using the `MHD_queue_basic_auth_fail_response'
723API. The only thing you need to do is construct a response with the
724error page to be shown to the user if he aborts basic authentication.
725But first, you should check if the proper credentials were already
726supplied using the `MHD_basic_auth_get_username_password' call.
727
728 Your code would then look like this:
729static int
730answer_to_connection (void *cls, struct MHD_Connection *connection,
731 const char *url, const char *method,
732 const char *version, const char *upload_data,
733 size_t *upload_data_size, void **con_cls)
734{
735 char *user;
736 char *pass;
737 int fail;
738 struct MHD_Response *response;
739
740 if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
741 return MHD_NO;
742 if (NULL == *con_cls)
743 {
744 *con_cls = connection;
745 return MHD_YES;
746 }
747 pass = NULL;
748 user = MHD_basic_auth_get_username_password (connection, &pass);
749 fail = ( (user == NULL) ||
750 (0 != strcmp (user, "root")) ||
751 (0 != strcmp (pass, "pa$$w0rd") ) );
752 if (user != NULL) free (user);
753 if (pass != NULL) free (pass);
754 if (fail)
755 {
756 const char *page = "<html><body>Go away.</body></html>";
757 response =
758 MHD_create_response_from_buffer (strlen (page), (void *) page,
759 MHD_RESPMEM_PERSISTENT);
760 ret = MHD_queue_basic_auth_fail_response (connection,
761 "my realm",
762 response);
763 }
764 else
765 {
766 const char *page = "<html><body>A secret.</body></html>";
767 response =
768 MHD_create_response_from_buffer (strlen (page), (void *) page,
769 MHD_RESPMEM_PERSISTENT);
770 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
771 }
772 MHD_destroy_response (response);
773 return ret;
774}
775
776 See the `examples' directory for the complete example file.
777
778Remarks
779=======
780
781For a proper server, the conditional statements leading to a return of
782`MHD_NO' should yield a response with a more precise status code
783instead of silently closing the connection. For example, failures of
784memory allocation are best reported as _internal server error_ and
785unexpected authentication methods as _400 bad request_.
786
787Exercises
788=========
789
790 * Make the server respond to wrong credentials (but otherwise
791 well-formed requests) with the recommended _401 unauthorized_
792 status code. If the client still does not authenticate correctly
793 within the same connection, close it and store the client's IP
794 address for a certain time. (It is OK to check for expiration not
795 until the main thread wakes up again on the next connection.) If
796 the client fails authenticating three times during this period,
797 add it to another list for which the `AcceptPolicyCallback'
798 function denies connection (temporally).
799
800 * With the network utility `netcat' connect and log the response of
801 a "GET" request as you did in the exercise of the first example,
802 this time to a file. Now stop the server and let _netcat_ listen
803 on the same port the server used to listen on and have it fake
804 being the proper server by giving the file's content as the
805 response (e.g. `cat log | nc -l -p 8888'). Pretending to think
806 your were connecting to the actual server, browse to the
807 eavesdropper and give the correct credentials.
808
809 Copy and paste the encoded string you see in `netcat''s output to
810 some of the Base64 decode tools available online and see how both
811 the user's name and password could be completely restored.
812
813
814
815File: libmicrohttpd-tutorial.info, Node: Processing POST data, Next: Improved processing of POST data, Prev: Supporting basic authentication, Up: Top
816
8176 Processing POST data
818**********************
819
820The previous chapters already have demonstrated a variety of
821possibilities to send information to the HTTP server, but it is not
822recommended that the _GET_ method is used to alter the way the server
823operates. To induce changes on the server, the _POST_ method is
824preferred over and is much more powerful than _GET_ and will be
825introduced in this chapter.
826
827 We are going to write an application that asks for the visitor's
828name and, after the user has posted it, composes an individual response
829text. Even though it was not mandatory to use the _POST_ method here,
830as there is no permanent change caused by the POST, it is an
831illustrative example on how to share data between different functions
832for the same connection. Furthermore, the reader should be able to
833extend it easily.
834
835GET request
836===========
837
838When the first _GET_ request arrives, the server shall respond with a
839HTML page containing an edit field for the name.
840
841const char* askpage = "<html><body>\
842 What's your name, Sir?<br>\
843 <form action=\"/namepost\" method=\"post\">\
844 <input name=\"name\" type=\"text\"\
845 <input type=\"submit\" value=\" Send \"></form>\
846 </body></html>";
847 The `action' entry is the _URI_ to be called by the browser when
848posting, and the `name' will be used later to be sure it is the
849editbox's content that has been posted.
850
851 We also prepare the answer page, where the name is to be filled in
852later, and an error page as the response for anything but proper _GET_
853and _POST_ requests:
854
855const char* greatingpage="<html><body><h1>Welcome, %s!</center></h1></body></html>";
856
857const char* errorpage="<html><body>This doesn't seem to be right.</body></html>";
858 Whenever we need to send a page, we use an extra function `int
859send_page(struct MHD_Connection *connection, const char* page)' for
860this, which does not contain anything new and whose implementation is
861therefore not discussed further in the tutorial.
862
863POST request
864============
865
866Posted data can be of arbitrary and considerable size; for example, if
867a user uploads a big image to the server. Similar to the case of the
868header fields, there may also be different streams of posted data, such
869as one containing the text of an editbox and another the state of a
870button. Likewise, we will have to register an iterator function that
871is going to be called maybe several times not only if there are
872different POSTs but also if one POST has only been received partly yet
873and needs processing before another chunk can be received.
874
875 Such an iterator function is called by a _postprocessor_, which must
876be created upon arriving of the post request. We want the iterator
877function to read the first post data which is tagged `name' and to
878create an individual greeting string based on the template and the name.
879But in order to pass this string to other functions and still be able
880to differentiate different connections, we must first define a
881structure to share the information, holding the most import entries.
882
883struct connection_info_struct
884{
885 int connectiontype;
886 char *answerstring;
887 struct MHD_PostProcessor *postprocessor;
888};
889 With these information available to the iterator function, it is able
890to fulfill its task. Once it has composed the greeting string, it
891returns `MHD_NO' to inform the post processor that it does not need to
892be called again. Note that this function does not handle processing of
893data for the same `key'. If we were to expect that the name will be
894posted in several chunks, we had to expand the namestring dynamically
895as additional parts of it with the same `key' came in. But in this
896example, the name is assumed to fit entirely inside one single packet.
897
898static int
899iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
900 const char *filename, const char *content_type,
901 const char *transfer_encoding, const char *data,
902 uint64_t off, size_t size)
903{
904 struct connection_info_struct *con_info = coninfo_cls;
905
906 if (0 == strcmp (key, "name"))
907 {
908 if ((size > 0) && (size <= MAXNAMESIZE))
909 {
910 char *answerstring;
911 answerstring = malloc (MAXANSWERSIZE);
912 if (!answerstring) return MHD_NO;
913
914 snprintf (answerstring, MAXANSWERSIZE, greatingpage, data);
915 con_info->answerstring = answerstring;
916 }
917 else con_info->answerstring = NULL;
918
919 return MHD_NO;
920 }
921
922 return MHD_YES;
923}
924 Once a connection has been established, it can be terminated for many
925reasons. As these reasons include unexpected events, we have to
926register another function that cleans up any resources that might have
927been allocated for that connection by us, namely the post processor and
928the greetings string. This cleanup function must take into account that
929it will also be called for finished requests other than _POST_ requests.
930
931void request_completed (void *cls, struct MHD_Connection *connection,
932 void **con_cls,
933 enum MHD_RequestTerminationCode toe)
934{
935 struct connection_info_struct *con_info = *con_cls;
936
937 if (NULL == con_info) return;
938 if (con_info->connectiontype == POST)
939 {
940 MHD_destroy_post_processor (con_info->postprocessor);
941 if (con_info->answerstring) free (con_info->answerstring);
942 }
943
944 free (con_info);
945 *con_cls = NULL;
946}
947 _GNU libmicrohttpd_ is informed that it shall call the above function
948when the daemon is started in the main function.
949
950...
951daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
952 &answer_to_connection, NULL,
953 MHD_OPTION_NOTIFY_COMPLETED, &request_completed, NULL,
954 MHD_OPTION_END);
955...
956
957Request handling
958================
959
960With all other functions prepared, we can now discuss the actual
961request handling.
962
963 On the first iteration for a new request, we start by allocating a
964new instance of a `struct connection_info_struct' structure, which will
965store all necessary information for later iterations and other
966functions.
967
968static int
969answer_to_connection (void *cls, struct MHD_Connection *connection,
970 const char *url,
971 const char *method, const char *version,
972 const char *upload_data,
973 size_t *upload_data_size, void **con_cls)
974{
975 if(NULL == *con_cls)
976 {
977 struct connection_info_struct *con_info;
978
979 con_info = malloc (sizeof (struct connection_info_struct));
980 if (NULL == con_info) return MHD_NO;
981 con_info->answerstring = NULL;
982 If the new request is a _POST_, the postprocessor must be created now.
983In addition, the type of the request is stored for convenience.
984 if (0 == strcmp (method, "POST"))
985 {
986 con_info->postprocessor
987 = MHD_create_post_processor (connection, POSTBUFFERSIZE,
988 iterate_post, (void*) con_info);
989
990 if (NULL == con_info->postprocessor)
991 {
992 free (con_info);
993 return MHD_NO;
994 }
995 con_info->connectiontype = POST;
996 }
997 else con_info->connectiontype = GET;
998 The address of our structure will both serve as the indicator for
999successive iterations and to remember the particular details about the
1000connection.
1001 *con_cls = (void*) con_info;
1002 return MHD_YES;
1003 }
1004 The rest of the function will not be executed on the first iteration.
1005A _GET_ request is easily satisfied by sending the question form.
1006 if (0 == strcmp (method, "GET"))
1007 {
1008 return send_page (connection, askpage);
1009 }
1010 In case of _POST_, we invoke the post processor for as long as data
1011keeps incoming, setting `*upload_data_size' to zero in order to
1012indicate that we have processed--or at least have considered--all of it.
1013 if (0 == strcmp (method, "POST"))
1014 {
1015 struct connection_info_struct *con_info = *con_cls;
1016
1017 if (*upload_data_size != 0)
1018 {
1019 MHD_post_process (con_info->postprocessor, upload_data,
1020 *upload_data_size);
1021 *upload_data_size = 0;
1022
1023 return MHD_YES;
1024 }
1025 else if (NULL != con_info->answerstring)
1026 return send_page (connection, con_info->answerstring);
1027 }
1028 Finally, if they are neither _GET_ nor _POST_ requests, the error page
1029is returned.
1030 return send_page(connection, errorpage);
1031}
1032 These were the important parts of the program `simplepost.c'.
1033
1034
1035File: libmicrohttpd-tutorial.info, Node: Improved processing of POST data, Next: Session management, Prev: Processing POST data, Up: Top
1036
10377 Improved processing of POST data
1038**********************************
1039
1040The previous chapter introduced a way to upload data to the server, but
1041the developed example program has some shortcomings, such as not being
1042able to handle larger chunks of data. In this chapter, we are going to
1043discuss a more advanced server program that allows clients to upload a
1044file in order to have it stored on the server's filesystem. The server
1045shall also watch and limit the number of clients concurrently
1046uploading, responding with a proper busy message if necessary.
1047
1048Prepared answers
1049================
1050
1051We choose to operate the server with the `SELECT_INTERNALLY' method.
1052This makes it easier to synchronize the global states at the cost of
1053possible delays for other connections if the processing of a request is
1054too slow. One of these variables that needs to be shared for all
1055connections is the total number of clients that are uploading.
1056
1057#define MAXCLIENTS 2
1058static unsigned int nr_of_uploading_clients = 0;
1059 If there are too many clients uploading, we want the server to respond
1060to all requests with a busy message.
1061const char* busypage =
1062 "<html><body>This server is busy, please try again later.</body></html>";
1063 Otherwise, the server will send a _form_ that informs the user of the
1064current number of uploading clients, and ask her to pick a file on her
1065local filesystem which is to be uploaded.
1066const char* askpage = "<html><body>\n\
1067 Upload a file, please!<br>\n\
1068 There are %u clients uploading at the moment.<br>\n\
1069 <form action=\"/filepost\" method=\"post\" \
1070 enctype=\"multipart/form-data\">\n\
1071 <input name=\"file\" type=\"file\">\n\
1072 <input type=\"submit\" value=\" Send \"></form>\n\
1073 </body></html>";
1074 If the upload has succeeded, the server will respond with a message
1075saying so.
1076const char* completepage = "<html><body>The upload has been completed.</body></html>";
1077 We want the server to report internal errors, such as memory shortage
1078or file access problems, adequately.
1079const char* servererrorpage
1080 = "<html><body>An internal server error has occured.</body></html>";
1081const char* fileexistspage
1082 = "<html><body>This file already exists.</body></html>";
1083 It would be tolerable to send all these responses undifferentiated
1084with a `200 HTTP_OK' status code but in order to improve the `HTTP'
1085conformance of our server a bit, we extend the `send_page' function so
1086that it accepts individual status codes.
1087
1088static int
1089send_page (struct MHD_Connection *connection,
1090 const char* page, int status_code)
1091{
1092 int ret;
1093 struct MHD_Response *response;
1094
1095 response = MHD_create_response_from_buffer (strlen (page), (void*) page,
1096 MHD_RESPMEM_MUST_COPY);
1097 if (!response) return MHD_NO;
1098
1099 ret = MHD_queue_response (connection, status_code, response);
1100 MHD_destroy_response (response);
1101
1102 return ret;
1103}
1104 Note how we ask _MHD_ to make its own copy of the message data. The
1105reason behind this will become clear later.
1106
1107Connection cycle
1108================
1109
1110The decision whether the server is busy or not is made right at the
1111beginning of the connection. To do that at this stage is especially
1112important for _POST_ requests because if no response is queued at this
1113point, and `MHD_YES' returned, _MHD_ will not sent any queued messages
1114until a postprocessor has been created and the post iterator is called
1115at least once.
1116
1117static int
1118answer_to_connection (void *cls, struct MHD_Connection *connection,
1119 const char *url,
1120 const char *method, const char *version,
1121 const char *upload_data,
1122 size_t *upload_data_size, void **con_cls)
1123{
1124 if (NULL == *con_cls)
1125 {
1126 struct connection_info_struct *con_info;
1127
1128 if (nr_of_uploading_clients >= MAXCLIENTS)
1129 return send_page(connection, busypage, MHD_HTTP_SERVICE_UNAVAILABLE);
1130 If the server is not busy, the `connection_info' structure is
1131initialized as usual, with the addition of a filepointer for each
1132connection.
1133
1134 con_info = malloc (sizeof (struct connection_info_struct));
1135 if (NULL == con_info) return MHD_NO;
1136 con_info->fp = 0;
1137
1138 if (0 == strcmp (method, "POST"))
1139 {
1140 ...
1141 }
1142 else con_info->connectiontype = GET;
1143
1144 *con_cls = (void*) con_info;
1145
1146 return MHD_YES;
1147 }
1148 For _POST_ requests, the postprocessor is created and we register a
1149new uploading client. From this point on, there are many possible
1150places for errors to occur that make it necessary to interrupt the
1151uploading process. We need a means of having the proper response
1152message ready at all times. Therefore, the `connection_info' structure
1153is extended to hold the most current response message so that whenever
1154a response is sent, the client will get the most informative message.
1155Here, the structure is initialized to "no error".
1156 if (0 == strcmp (method, "POST"))
1157 {
1158 con_info->postprocessor
1159 = MHD_create_post_processor (connection, POSTBUFFERSIZE,
1160 iterate_post, (void*) con_info);
1161
1162 if (NULL == con_info->postprocessor)
1163 {
1164 free (con_info);
1165 return MHD_NO;
1166 }
1167
1168 nr_of_uploading_clients++;
1169
1170 con_info->connectiontype = POST;
1171 con_info->answercode = MHD_HTTP_OK;
1172 con_info->answerstring = completepage;
1173 }
1174 else con_info->connectiontype = GET;
1175 If the connection handler is called for the second time, _GET_
1176requests will be answered with the _form_. We can keep the buffer under
1177function scope, because we asked _MHD_ to make its own copy of it for
1178as long as it is needed.
1179 if (0 == strcmp (method, "GET"))
1180 {
1181 int ret;
1182 char buffer[1024];
1183
1184 sprintf (buffer, askpage, nr_of_uploading_clients);
1185 return send_page (connection, buffer, MHD_HTTP_OK);
1186 }
1187 The rest of the `answer_to_connection' function is very similar to the
1188`simplepost.c' example, except the more flexible content of the
1189responses. The _POST_ data is processed until there is none left and
1190the execution falls through to return an error page if the connection
1191constituted no expected request method.
1192 if (0 == strcmp (method, "POST"))
1193 {
1194 struct connection_info_struct *con_info = *con_cls;
1195
1196 if (0 != *upload_data_size)
1197 {
1198 MHD_post_process (con_info->postprocessor,
1199 upload_data, *upload_data_size);
1200 *upload_data_size = 0;
1201
1202 return MHD_YES;
1203 }
1204 else
1205 return send_page (connection, con_info->answerstring,
1206 con_info->answercode);
1207 }
1208
1209 return send_page(connection, errorpage, MHD_HTTP_BAD_REQUEST);
1210}
1211
1212Storing to data
1213===============
1214
1215Unlike the `simplepost.c' example, here it is to be expected that post
1216iterator will be called several times now. This means that for any
1217given connection (there might be several concurrent of them) the posted
1218data has to be written to the correct file. That is why we store a file
1219handle in every `connection_info', so that the it is preserved between
1220successive iterations.
1221static int
1222iterate_post (void *coninfo_cls, enum MHD_ValueKind kind,
1223 const char *key,
1224 const char *filename, const char *content_type,
1225 const char *transfer_encoding, const char *data,
1226 uint64_t off, size_t size)
1227{
1228 struct connection_info_struct *con_info = coninfo_cls;
1229 Because the following actions depend heavily on correct file
1230processing, which might be error prone, we default to reporting
1231internal errors in case anything will go wrong.
1232
1233con_info->answerstring = servererrorpage;
1234con_info->answercode = MHD_HTTP_INTERNAL_SERVER_ERROR;
1235 In the "askpage" _form_, we told the client to label its post data
1236with the "file" key. Anything else would be an error.
1237
1238 if (0 != strcmp (key, "file")) return MHD_NO;
1239 If the iterator is called for the first time, no file will have been
1240opened yet. The `filename' string contains the name of the file
1241(without any paths) the user selected on his system. We want to take
1242this as the name the file will be stored on the server and make sure no
1243file of that name exists (or is being uploaded) before we create one
1244(note that the code below technically contains a race between the two
1245"fopen" calls, but we will overlook this for portability sake).
1246 if (!con_info->fp)
1247 {
1248 if (NULL != (fp = fopen (filename, "rb")) )
1249 {
1250 fclose (fp);
1251 con_info->answerstring = fileexistspage;
1252 con_info->answercode = MHD_HTTP_FORBIDDEN;
1253 return MHD_NO;
1254 }
1255
1256 con_info->fp = fopen (filename, "ab");
1257 if (!con_info->fp) return MHD_NO;
1258 }
1259 Occasionally, the iterator function will be called even when there are
12600 new bytes to process. The server only needs to write data to the file
1261if there is some.
1262if (size > 0)
1263 {
1264 if (!fwrite (data, size, sizeof(char), con_info->fp))
1265 return MHD_NO;
1266 }
1267 If this point has been reached, everything worked well for this
1268iteration and the response can be set to success again. If the upload
1269has finished, this iterator function will not be called again.
1270 con_info->answerstring = completepage;
1271 con_info->answercode = MHD_HTTP_OK;
1272
1273 return MHD_YES;
1274}
1275 The new client was registered when the postprocessor was created.
1276Likewise, we unregister the client on destroying the postprocessor when
1277the request is completed.
1278void request_completed (void *cls, struct MHD_Connection *connection,
1279 void **con_cls,
1280 enum MHD_RequestTerminationCode toe)
1281{
1282 struct connection_info_struct *con_info = *con_cls;
1283
1284 if (NULL == con_info) return;
1285
1286 if (con_info->connectiontype == POST)
1287 {
1288 if (NULL != con_info->postprocessor)
1289 {
1290 MHD_destroy_post_processor (con_info->postprocessor);
1291 nr_of_uploading_clients--;
1292 }
1293
1294 if (con_info->fp) fclose (con_info->fp);
1295 }
1296
1297 free (con_info);
1298 *con_cls = NULL;
1299}
1300 This is essentially the whole example `largepost.c'.
1301
1302Remarks
1303=======
1304
1305Now that the clients are able to create files on the server, security
1306aspects are becoming even more important than before. Aside from proper
1307client authentication, the server should always make sure explicitly
1308that no files will be created outside of a dedicated upload directory.
1309In particular, filenames must be checked to not contain strings like
1310"../".
1311
1312
1313File: libmicrohttpd-tutorial.info, Node: Session management, Next: Adding a layer of security, Prev: Improved processing of POST data, Up: Top
1314
13158 Session management
1316********************
1317
1318This chapter discusses how one should manage sessions, that is, share
1319state between multiple HTTP requests from the same user. We use a
1320simple example where the user submits multiple forms and the server is
1321supposed to accumulate state from all of these forms. Naturally, as
1322this is a network protocol, our session mechanism must support having
1323many users with many concurrent sessions at the same time.
1324
1325 In order to track users, we use a simple session cookie. A session
1326cookie expires when the user closes the browser. Changing from session
1327cookies to persistent cookies only requires adding an expiration time
1328to the cookie. The server creates a fresh session cookie whenever a
1329request without a cookie is received, or if the supplied session cookie
1330is not known to the server.
1331
1332Looking up the cookie
1333=====================
1334
1335Since MHD parses the HTTP cookie header for us, looking up an existing
1336cookie is straightforward:
1337
1338FIXME.
1339
1340 Here, FIXME is the name we chose for our session cookie.
1341
1342Setting the cookie header
1343=========================
1344
1345MHD requires the user to provide the full cookie format string in order
1346to set cookies. In order to generate a unique cookie, our example
1347creates a random 64-character text string to be used as the value of
1348the cookie:
1349
1350FIXME.
1351
1352 Given this cookie value, we can then set the cookie header in our
1353HTTP response as follows:
1354
1355FIXME.
1356
1357Remark: Session expiration
1358==========================
1359
1360It is of course possible that clients stop their interaction with the
1361server at any time. In order to avoid using too much storage, the
1362server must thus discard inactive sessions at some point. Our example
1363implements this by discarding inactive sessions after a certain amount
1364of time. Alternatively, the implementation may limit the total number
1365of active sessions. Which bounds are used for idle sessions or the
1366total number of sessions obviously depends largely on the type of the
1367application and available server resources.
1368
1369Example code
1370============
1371
1372A sample application implementing a website with multiple forms (which
1373are dynamically created using values from previous POST requests from
1374the same session) is available as the example `sessions.c'.
1375
1376 Note that the example uses a simple, $O(n)$ linked list traversal to
1377look up sessions and to expire old sessions. Using a hash table and a
1378heap would be more appropriate if a large number of concurrent sessions
1379is expected.
1380
1381Remarks
1382=======
1383
1384Naturally, it is quite conceivable to store session data in a database
1385instead of in memory. Still, having mechanisms to expire data
1386associated with long-time idle sessions (where the business process has
1387still not finished) is likely a good idea.
1388
1389
1390File: libmicrohttpd-tutorial.info, Node: Adding a layer of security, Next: Bibliography, Prev: Session management, Up: Top
1391
13929 Adding a layer of security
1393****************************
1394
1395We left the basic authentication chapter with the unsatisfactory
1396conclusion that any traffic, including the credentials, could be
1397intercepted by anyone between the browser client and the server.
1398Protecting the data while it is sent over unsecured lines will be the
1399goal of this chapter.
1400
1401 Since version 0.4, the _MHD_ library includes support for encrypting
1402the traffic by employing SSL/TSL. If _GNU libmicrohttpd_ has been
1403configured to support these, encryption and decryption can be applied
1404transparently on the data being sent, with only minimal changes to the
1405actual source code of the example.
1406
1407Preparation
1408===========
1409
1410First, a private key for the server will be generated. With this key,
1411the server will later be able to authenticate itself to the
1412client--preventing anyone else from stealing the password by faking its
1413identity. The _OpenSSL_ suite, which is available on many operating
1414systems, can generate such a key. For the scope of this tutorial, we
1415will be content with a 1024 bit key:
1416> openssl genrsa -out server.key 1024
1417 In addition to the key, a certificate describing the server in human
1418readable tokens is also needed. This certificate will be attested with
1419our aforementioned key. In this way, we obtain a self-signed
1420certificate, valid for one year.
1421
1422> openssl req -days 365 -out server.pem -new -x509 -key server.key
1423 To avoid unnecessary error messages in the browser, the certificate
1424needs to have a name that matches the _URI_, for example, "localhost"
1425or the domain. If you plan to have a publicly reachable server, you
1426will need to ask a trusted third party, called _Certificate Authority_,
1427or _CA_, to attest the certificate for you. This way, any visitor can
1428make sure the server's identity is real.
1429
1430 Whether the server's certificate is signed by us or a third party,
1431once it has been accepted by the client, both sides will be
1432communicating over encrypted channels. From this point on, it is the
1433client's turn to authenticate itself. But this has already been
1434implemented in the basic authentication scheme.
1435
1436Changing the source code
1437========================
1438
1439We merely have to extend the server program so that it loads the two
1440files into memory,
1441
1442int
1443main ()
1444{
1445 struct MHD_Daemon *daemon;
1446 char *key_pem;
1447 char *cert_pem;
1448
1449 key_pem = load_file (SERVERKEYFILE);
1450 cert_pem = load_file (SERVERCERTFILE);
1451
1452 if ((key_pem == NULL) || (cert_pem == NULL))
1453 {
1454 printf ("The key/certificate files could not be read.\n");
1455 return 1;
1456 }
1457 and then we point the _MHD_ daemon to it upon initalization.
1458
1459 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL,
1460 PORT, NULL, NULL,
1461 &answer_to_connection, NULL,
1462 MHD_OPTION_HTTPS_MEM_KEY, key_pem,
1463 MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
1464 MHD_OPTION_END);
1465
1466 if (NULL == daemon)
1467 {
1468 printf ("%s\n", cert_pem);
1469
1470 free (key_pem);
1471 free (cert_pem);
1472
1473 return 1;
1474 }
1475 The rest consists of little new besides some additional memory
1476cleanups.
1477
1478 getchar ();
1479
1480 MHD_stop_daemon (daemon);
1481 free (key_pem);
1482 free (cert_pem);
1483
1484 return 0;
1485}
1486 The rather unexciting file loader can be found in the complete example
1487`tlsauthentication.c'.
1488
1489Remarks
1490=======
1491
1492 * While the standard _HTTP_ port is 80, it is 443 for _HTTPS_. The
1493 common internet browsers assume standard _HTTP_ if they are asked
1494 to access other ports than these. Therefore, you will have to type
1495 `https://localhost:8888' explicitly when you test the example, or
1496 the browser will not know how to handle the answer properly.
1497
1498 * The remaining weak point is the question how the server will be
1499 trusted initially. Either a _CA_ signs the certificate or the
1500 client obtains the key over secure means. Anyway, the clients have
1501 to be aware (or configured) that they should not accept
1502 certificates of unknown origin.
1503
1504 * The introduced method of certificates makes it mandatory to set an
1505 expiration date--making it less feasible to hardcode certificates
1506 in embedded devices.
1507
1508 * The cryptographic facilities consume memory space and computing
1509 time. For this reason, websites usually consists both of
1510 uncritically _HTTP_ parts and secured _HTTPS_.
1511
1512
1513Client authentication
1514=====================
1515
1516You can also use MHD to authenticate the client via SSL/TLS certificates
1517(as an alternative to using the password-based Basic or Digest
1518authentication). To do this, you will need to link your application
1519against _gnutls_. Next, when you start the MHD daemon, you must
1520specify the root CA that you're willing to trust:
1521 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL,
1522 PORT, NULL, NULL,
1523 &answer_to_connection, NULL,
1524 MHD_OPTION_HTTPS_MEM_KEY, key_pem,
1525 MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
1526 MHD_OPTION_HTTPS_MEM_TRUST, root_ca_pem,
1527 MHD_OPTION_END);
1528
1529 With this, you can then obtain client certificates for each session.
1530In order to obtain the identity of the client, you first need to obtain
1531the raw GnuTLS session handle from _MHD_ using
1532`MHD_get_connection_info'.
1533
1534#include <gnutls/gnutls.h>
1535#include <gnutls/x509.h>
1536
1537gnutls_session_t tls_session;
1538union MHD_ConnectionInfo *ci;
1539
1540ci = MHD_get_connection_info (connection,
1541 MHD_CONNECTION_INFO_GNUTLS_SESSION);
1542tls_session = ci->tls_session;
1543
1544 You can then extract the client certificate:
1545
1546/**
1547 * Get the client's certificate
1548 *
1549 * @param tls_session the TLS session
1550 * @return NULL if no valid client certificate could be found, a pointer
1551 * to the certificate if found
1552 */
1553static gnutls_x509_crt_t
1554get_client_certificate (gnutls_session_t tls_session)
1555{
1556 unsigned int listsize;
1557 const gnutls_datum_t * pcert;
1558 gnutls_certificate_status_t client_cert_status;
1559 gnutls_x509_crt_t client_cert;
1560
1561 if (tls_session == NULL)
1562 return NULL;
1563 if (gnutls_certificate_verify_peers2(tls_session,
1564 &client_cert_status))
1565 return NULL;
1566 pcert = gnutls_certificate_get_peers(tls_session,
1567 &listsize);
1568 if ( (pcert == NULL) ||
1569 (listsize == 0))
1570 {
1571 fprintf (stderr,
1572 "Failed to retrieve client certificate chain\n");
1573 return NULL;
1574 }
1575 if (gnutls_x509_crt_init(&client_cert))
1576 {
1577 fprintf (stderr,
1578 "Failed to initialize client certificate\n");
1579 return NULL;
1580 }
1581 /* Note that by passing values between 0 and listsize here, you
1582 can get access to the CA's certs */
1583 if (gnutls_x509_crt_import(client_cert,
1584 &pcert[0],
1585 GNUTLS_X509_FMT_DER))
1586 {
1587 fprintf (stderr,
1588 "Failed to import client certificate\n");
1589 gnutls_x509_crt_deinit(client_cert);
1590 return NULL;
1591 }
1592 return client_cert;
1593}
1594
1595 Using the client certificate, you can then get the client's
1596distinguished name and alternative names:
1597
1598/**
1599 * Get the distinguished name from the client's certificate
1600 *
1601 * @param client_cert the client certificate
1602 * @return NULL if no dn or certificate could be found, a pointer
1603 * to the dn if found
1604 */
1605char *
1606cert_auth_get_dn(gnutls_x509_crt_c client_cert)
1607{
1608 char* buf;
1609 size_t lbuf;
1610
1611 lbuf = 0;
1612 gnutls_x509_crt_get_dn(client_cert, NULL, &lbuf);
1613 buf = malloc(lbuf);
1614 if (buf == NULL)
1615 {
1616 fprintf (stderr,
1617 "Failed to allocate memory for certificate dn\n");
1618 return NULL;
1619 }
1620 gnutls_x509_crt_get_dn(client_cert, buf, &lbuf);
1621 return buf;
1622}
1623
1624
1625/**
1626 * Get the alternative name of specified type from the client's certificate
1627 *
1628 * @param client_cert the client certificate
1629 * @param nametype The requested name type
1630 * @param index The position of the alternative name if multiple names are
1631 * matching the requested type, 0 for the first matching name
1632 * @return NULL if no matching alternative name could be found, a pointer
1633 * to the alternative name if found
1634 */
1635char *
1636MHD_cert_auth_get_alt_name(gnutls_x509_crt_t client_cert,
1637 int nametype,
1638 unsigned int index)
1639{
1640 char* buf;
1641 size_t lbuf;
1642 unsigned int seq;
1643 unsigned int subseq;
1644 unsigned int type;
1645 int result;
1646
1647 subseq = 0;
1648 for (seq=0;;seq++)
1649 {
1650 lbuf = 0;
1651 result = gnutls_x509_crt_get_subject_alt_name2(client_cert, seq, NULL, &lbuf,
1652 &type, NULL);
1653 if (result == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1654 return NULL;
1655 if (nametype != (int) type)
1656 continue;
1657 if (subseq == index)
1658 break;
1659 subseq++;
1660 }
1661 buf = malloc(lbuf);
1662 if (buf == NULL)
1663 {
1664 fprintf (stderr,
1665 "Failed to allocate memory for certificate alt name\n");
1666 return NULL;
1667 }
1668 result = gnutls_x509_crt_get_subject_alt_name2(client_cert,
1669 seq,
1670 buf,
1671 &lbuf,
1672 NULL, NULL);
1673 if (result != nametype)
1674 {
1675 fprintf (stderr,
1676 "Unexpected return value from gnutls: %d\n",
1677 result);
1678 free (buf);
1679 return NULL;
1680 }
1681 return buf;
1682}
1683
1684 Finally, you should release the memory associated with the client
1685certificate:
1686
1687gnutls_x509_crt_deinit (client_cert);
1688
1689Using TLS Server Name Indication (SNI)
1690======================================
1691
1692SNI enables hosting multiple domains under one IP address with TLS. So
1693SNI is the TLS-equivalent of virtual hosting. To use SNI with MHD, you
1694need at least GnuTLS 3.0. The main change compared to the simple
1695hosting of one domain is that you need to provide a callback instead of
1696the key and certificate. For example, when you start the MHD daemon,
1697you could do this:
1698 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL,
1699 PORT, NULL, NULL,
1700 &answer_to_connection, NULL,
1701 MHD_OPTION_HTTPS_CERT_CALLBACK, &sni_callback,
1702 MHD_OPTION_END);
1703 Here, `sni_callback' is the name of a function that you will have to
1704implement to retrieve the X.509 certificate for an incoming connection.
1705The callback has type `gnutls_certificate_retrieve_function2' and is
1706documented in the GnuTLS API for the
1707`gnutls_certificate_set_retrieve_function2' as follows:
1708
1709 -- Function Pointer: int *gnutls_certificate_retrieve_function2
1710 (gnutls_session_t, const gnutls_datum_t* req_ca_dn, int
1711 nreqs, const gnutls_pk_algorithm_t* pk_algos, int
1712 pk_algos_length, gnutls_pcert_st** pcert, unsigned int
1713 *pcert_length, gnutls_privkey_t * pkey)
1714 REQ_CA_CERT
1715 is only used in X.509 certificates. Contains a list with the
1716 CA names that the server considers trusted. Normally we
1717 should send a certificate that is signed by one of these CAs.
1718 These names are DER encoded. To get a more meaningful value
1719 use the function `gnutls_x509_rdn_get()'.
1720
1721 PK_ALGOS
1722 contains a list with server’s acceptable signature
1723 algorithms. The certificate returned should support the
1724 server’s given algorithms.
1725
1726 PCERT
1727 should contain a single certificate and public or a list of
1728 them.
1729
1730 PCERT_LENGTH
1731 is the size of the previous list.
1732
1733 PKEY
1734 is the private key.
1735
1736 A possible implementation of this callback would look like this:
1737
1738struct Hosts
1739{
1740 struct Hosts *next;
1741 const char *hostname;
1742 gnutls_pcert_st pcrt;
1743 gnutls_privkey_t key;
1744};
1745
1746static struct Hosts *hosts;
1747
1748int
1749sni_callback (gnutls_session_t session,
1750 const gnutls_datum_t* req_ca_dn,
1751 int nreqs,
1752 const gnutls_pk_algorithm_t* pk_algos,
1753 int pk_algos_length,
1754 gnutls_pcert_st** pcert,
1755 unsigned int *pcert_length,
1756 gnutls_privkey_t * pkey)
1757{
1758 char name[256];
1759 size_t name_len;
1760 struct Hosts *host;
1761 unsigned int type;
1762
1763 name_len = sizeof (name);
1764 if (GNUTLS_E_SUCCESS !=
1765 gnutls_server_name_get (session,
1766 name,
1767 &name_len,
1768 &type,
1769 0 /* index */))
1770 return -1;
1771 for (host = hosts; NULL != host; host = host->next)
1772 if (0 == strncmp (name, host->hostname, name_len))
1773 break;
1774 if (NULL == host)
1775 {
1776 fprintf (stderr,
1777 "Need certificate for %.*s\n",
1778 (int) name_len,
1779 name);
1780 return -1;
1781 }
1782 fprintf (stderr,
1783 "Returning certificate for %.*s\n",
1784 (int) name_len,
1785 name);
1786 *pkey = host->key;
1787 *pcert_length = 1;
1788 *pcert = &host->pcrt;
1789 return 0;
1790}
1791
1792 Note that MHD cannot offer passing a closure or any other additional
1793information to this callback, as the GnuTLS API unfortunately does not
1794permit this at this point.
1795
1796 The `hosts' list can be initialized by loading the private keys and
1797X.509 certificats from disk as follows:
1798
1799static void
1800load_keys(const char *hostname,
1801 const char *CERT_FILE,
1802 const char *KEY_FILE)
1803{
1804 int ret;
1805 gnutls_datum_t data;
1806 struct Hosts *host;
1807
1808 host = malloc (sizeof (struct Hosts));
1809 host->hostname = hostname;
1810 host->next = hosts;
1811 hosts = host;
1812
1813 ret = gnutls_load_file (CERT_FILE, &data);
1814 if (ret < 0)
1815 {
1816 fprintf (stderr,
1817 "*** Error loading certificate file %s.\n",
1818 CERT_FILE);
1819 exit(1);
1820 }
1821 ret =
1822 gnutls_pcert_import_x509_raw (&host->pcrt, &data, GNUTLS_X509_FMT_PEM,
1823 0);
1824 if (ret < 0)
1825 {
1826 fprintf(stderr,
1827 "*** Error loading certificate file: %s\n",
1828 gnutls_strerror (ret));
1829 exit(1);
1830 }
1831 gnutls_free (data.data);
1832
1833 ret = gnutls_load_file (KEY_FILE, &data);
1834 if (ret < 0)
1835 {
1836 fprintf (stderr,
1837 "*** Error loading key file %s.\n",
1838 KEY_FILE);
1839 exit(1);
1840 }
1841
1842 gnutls_privkey_init (&host->key);
1843 ret =
1844 gnutls_privkey_import_x509_raw (host->key,
1845 &data, GNUTLS_X509_FMT_PEM,
1846 NULL, 0);
1847 if (ret < 0)
1848 {
1849 fprintf (stderr,
1850 "*** Error loading key file: %s\n",
1851 gnutls_strerror (ret));
1852 exit(1);
1853 }
1854 gnutls_free (data.data);
1855}
1856
1857 The code above was largely lifted from GnuTLS. You can find other
1858methods for initializing certificates and keys in the GnuTLS manual and
1859source code.
1860
1861
1862File: libmicrohttpd-tutorial.info, Node: Bibliography, Next: License text, Prev: Adding a layer of security, Up: Top
1863
1864Appendix A Bibliography
1865***********************
1866
1867API reference
1868=============
1869
1870 * The _GNU libmicrohttpd_ manual by Marco Maggi and Christian
1871 Grothoff 2008 `http://gnunet.org/libmicrohttpd/microhttpd.html'
1872
1873 * All referenced RFCs can be found on the website of _The Internet
1874 Engineering Task Force_ `http://www.ietf.org/'
1875
1876 * _RFC 2616_: Fielding, R., Gettys, J., Mogul, J., Frystyk, H., and
1877 T. Berners-Lee, "Hypertext Transfer Protocol - HTTP/1.1", RFC
1878 2016, January 1997.
1879
1880 * _RFC 2617_: Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence,
1881 S., Leach, P., Luotonen, A., and L. Stewart, "HTTP Authentication:
1882 Basic and Digest Access Authentication", RFC 2617, June 1999.
1883
1884 * A well-structured _HTML_ reference can be found on
1885 `http://www.echoecho.com/html.htm'
1886
1887 For those readers understanding German or French, there is an
1888 excellent document both for learning _HTML_ and for reference,
1889 whose English version unfortunately has been discontinued.
1890 `http://de.selfhtml.org/' and `http://fr.selfhtml.org/'
1891
1892
1893
1894File: libmicrohttpd-tutorial.info, Node: License text, Next: Example programs, Prev: Bibliography, Up: Top
1895
1896Appendix B GNU Free Documentation License
1897*****************************************
1898
1899 Version 1.3, 3 November 2008
1900
1901 Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
1902 `http://fsf.org/'
1903
1904 Everyone is permitted to copy and distribute verbatim copies
1905 of this license document, but changing it is not allowed.
1906
1907 0. PREAMBLE
1908
1909 The purpose of this License is to make a manual, textbook, or other
1910 functional and useful document "free" in the sense of freedom: to
1911 assure everyone the effective freedom to copy and redistribute it,
1912 with or without modifying it, either commercially or
1913 noncommercially. Secondarily, this License preserves for the
1914 author and publisher a way to get credit for their work, while not
1915 being considered responsible for modifications made by others.
1916
1917 This License is a kind of "copyleft", which means that derivative
1918 works of the document must themselves be free in the same sense.
1919 It complements the GNU General Public License, which is a copyleft
1920 license designed for free software.
1921
1922 We have designed this License in order to use it for manuals for
1923 free software, because free software needs free documentation: a
1924 free program should come with manuals providing the same freedoms
1925 that the software does. But this License is not limited to
1926 software manuals; it can be used for any textual work, regardless
1927 of subject matter or whether it is published as a printed book.
1928 We recommend this License principally for works whose purpose is
1929 instruction or reference.
1930
1931 1. APPLICABILITY AND DEFINITIONS
1932
1933 This License applies to any manual or other work, in any medium,
1934 that contains a notice placed by the copyright holder saying it
1935 can be distributed under the terms of this License. Such a notice
1936 grants a world-wide, royalty-free license, unlimited in duration,
1937 to use that work under the conditions stated herein. The
1938 "Document", below, refers to any such manual or work. Any member
1939 of the public is a licensee, and is addressed as "you". You
1940 accept the license if you copy, modify or distribute the work in a
1941 way requiring permission under copyright law.
1942
1943 A "Modified Version" of the Document means any work containing the
1944 Document or a portion of it, either copied verbatim, or with
1945 modifications and/or translated into another language.
1946
1947 A "Secondary Section" is a named appendix or a front-matter section
1948 of the Document that deals exclusively with the relationship of the
1949 publishers or authors of the Document to the Document's overall
1950 subject (or to related matters) and contains nothing that could
1951 fall directly within that overall subject. (Thus, if the Document
1952 is in part a textbook of mathematics, a Secondary Section may not
1953 explain any mathematics.) The relationship could be a matter of
1954 historical connection with the subject or with related matters, or
1955 of legal, commercial, philosophical, ethical or political position
1956 regarding them.
1957
1958 The "Invariant Sections" are certain Secondary Sections whose
1959 titles are designated, as being those of Invariant Sections, in
1960 the notice that says that the Document is released under this
1961 License. If a section does not fit the above definition of
1962 Secondary then it is not allowed to be designated as Invariant.
1963 The Document may contain zero Invariant Sections. If the Document
1964 does not identify any Invariant Sections then there are none.
1965
1966 The "Cover Texts" are certain short passages of text that are
1967 listed, as Front-Cover Texts or Back-Cover Texts, in the notice
1968 that says that the Document is released under this License. A
1969 Front-Cover Text may be at most 5 words, and a Back-Cover Text may
1970 be at most 25 words.
1971
1972 A "Transparent" copy of the Document means a machine-readable copy,
1973 represented in a format whose specification is available to the
1974 general public, that is suitable for revising the document
1975 straightforwardly with generic text editors or (for images
1976 composed of pixels) generic paint programs or (for drawings) some
1977 widely available drawing editor, and that is suitable for input to
1978 text formatters or for automatic translation to a variety of
1979 formats suitable for input to text formatters. A copy made in an
1980 otherwise Transparent file format whose markup, or absence of
1981 markup, has been arranged to thwart or discourage subsequent
1982 modification by readers is not Transparent. An image format is
1983 not Transparent if used for any substantial amount of text. A
1984 copy that is not "Transparent" is called "Opaque".
1985
1986 Examples of suitable formats for Transparent copies include plain
1987 ASCII without markup, Texinfo input format, LaTeX input format,
1988 SGML or XML using a publicly available DTD, and
1989 standard-conforming simple HTML, PostScript or PDF designed for
1990 human modification. Examples of transparent image formats include
1991 PNG, XCF and JPG. Opaque formats include proprietary formats that
1992 can be read and edited only by proprietary word processors, SGML or
1993 XML for which the DTD and/or processing tools are not generally
1994 available, and the machine-generated HTML, PostScript or PDF
1995 produced by some word processors for output purposes only.
1996
1997 The "Title Page" means, for a printed book, the title page itself,
1998 plus such following pages as are needed to hold, legibly, the
1999 material this License requires to appear in the title page. For
2000 works in formats which do not have any title page as such, "Title
2001 Page" means the text near the most prominent appearance of the
2002 work's title, preceding the beginning of the body of the text.
2003
2004 The "publisher" means any person or entity that distributes copies
2005 of the Document to the public.
2006
2007 A section "Entitled XYZ" means a named subunit of the Document
2008 whose title either is precisely XYZ or contains XYZ in parentheses
2009 following text that translates XYZ in another language. (Here XYZ
2010 stands for a specific section name mentioned below, such as
2011 "Acknowledgements", "Dedications", "Endorsements", or "History".)
2012 To "Preserve the Title" of such a section when you modify the
2013 Document means that it remains a section "Entitled XYZ" according
2014 to this definition.
2015
2016 The Document may include Warranty Disclaimers next to the notice
2017 which states that this License applies to the Document. These
2018 Warranty Disclaimers are considered to be included by reference in
2019 this License, but only as regards disclaiming warranties: any other
2020 implication that these Warranty Disclaimers may have is void and
2021 has no effect on the meaning of this License.
2022
2023 2. VERBATIM COPYING
2024
2025 You may copy and distribute the Document in any medium, either
2026 commercially or noncommercially, provided that this License, the
2027 copyright notices, and the license notice saying this License
2028 applies to the Document are reproduced in all copies, and that you
2029 add no other conditions whatsoever to those of this License. You
2030 may not use technical measures to obstruct or control the reading
2031 or further copying of the copies you make or distribute. However,
2032 you may accept compensation in exchange for copies. If you
2033 distribute a large enough number of copies you must also follow
2034 the conditions in section 3.
2035
2036 You may also lend copies, under the same conditions stated above,
2037 and you may publicly display copies.
2038
2039 3. COPYING IN QUANTITY
2040
2041 If you publish printed copies (or copies in media that commonly
2042 have printed covers) of the Document, numbering more than 100, and
2043 the Document's license notice requires Cover Texts, you must
2044 enclose the copies in covers that carry, clearly and legibly, all
2045 these Cover Texts: Front-Cover Texts on the front cover, and
2046 Back-Cover Texts on the back cover. Both covers must also clearly
2047 and legibly identify you as the publisher of these copies. The
2048 front cover must present the full title with all words of the
2049 title equally prominent and visible. You may add other material
2050 on the covers in addition. Copying with changes limited to the
2051 covers, as long as they preserve the title of the Document and
2052 satisfy these conditions, can be treated as verbatim copying in
2053 other respects.
2054
2055 If the required texts for either cover are too voluminous to fit
2056 legibly, you should put the first ones listed (as many as fit
2057 reasonably) on the actual cover, and continue the rest onto
2058 adjacent pages.
2059
2060 If you publish or distribute Opaque copies of the Document
2061 numbering more than 100, you must either include a
2062 machine-readable Transparent copy along with each Opaque copy, or
2063 state in or with each Opaque copy a computer-network location from
2064 which the general network-using public has access to download
2065 using public-standard network protocols a complete Transparent
2066 copy of the Document, free of added material. If you use the
2067 latter option, you must take reasonably prudent steps, when you
2068 begin distribution of Opaque copies in quantity, to ensure that
2069 this Transparent copy will remain thus accessible at the stated
2070 location until at least one year after the last time you
2071 distribute an Opaque copy (directly or through your agents or
2072 retailers) of that edition to the public.
2073
2074 It is requested, but not required, that you contact the authors of
2075 the Document well before redistributing any large number of
2076 copies, to give them a chance to provide you with an updated
2077 version of the Document.
2078
2079 4. MODIFICATIONS
2080
2081 You may copy and distribute a Modified Version of the Document
2082 under the conditions of sections 2 and 3 above, provided that you
2083 release the Modified Version under precisely this License, with
2084 the Modified Version filling the role of the Document, thus
2085 licensing distribution and modification of the Modified Version to
2086 whoever possesses a copy of it. In addition, you must do these
2087 things in the Modified Version:
2088
2089 A. Use in the Title Page (and on the covers, if any) a title
2090 distinct from that of the Document, and from those of
2091 previous versions (which should, if there were any, be listed
2092 in the History section of the Document). You may use the
2093 same title as a previous version if the original publisher of
2094 that version gives permission.
2095
2096 B. List on the Title Page, as authors, one or more persons or
2097 entities responsible for authorship of the modifications in
2098 the Modified Version, together with at least five of the
2099 principal authors of the Document (all of its principal
2100 authors, if it has fewer than five), unless they release you
2101 from this requirement.
2102
2103 C. State on the Title page the name of the publisher of the
2104 Modified Version, as the publisher.
2105
2106 D. Preserve all the copyright notices of the Document.
2107
2108 E. Add an appropriate copyright notice for your modifications
2109 adjacent to the other copyright notices.
2110
2111 F. Include, immediately after the copyright notices, a license
2112 notice giving the public permission to use the Modified
2113 Version under the terms of this License, in the form shown in
2114 the Addendum below.
2115
2116 G. Preserve in that license notice the full lists of Invariant
2117 Sections and required Cover Texts given in the Document's
2118 license notice.
2119
2120 H. Include an unaltered copy of this License.
2121
2122 I. Preserve the section Entitled "History", Preserve its Title,
2123 and add to it an item stating at least the title, year, new
2124 authors, and publisher of the Modified Version as given on
2125 the Title Page. If there is no section Entitled "History" in
2126 the Document, create one stating the title, year, authors,
2127 and publisher of the Document as given on its Title Page,
2128 then add an item describing the Modified Version as stated in
2129 the previous sentence.
2130
2131 J. Preserve the network location, if any, given in the Document
2132 for public access to a Transparent copy of the Document, and
2133 likewise the network locations given in the Document for
2134 previous versions it was based on. These may be placed in
2135 the "History" section. You may omit a network location for a
2136 work that was published at least four years before the
2137 Document itself, or if the original publisher of the version
2138 it refers to gives permission.
2139
2140 K. For any section Entitled "Acknowledgements" or "Dedications",
2141 Preserve the Title of the section, and preserve in the
2142 section all the substance and tone of each of the contributor
2143 acknowledgements and/or dedications given therein.
2144
2145 L. Preserve all the Invariant Sections of the Document,
2146 unaltered in their text and in their titles. Section numbers
2147 or the equivalent are not considered part of the section
2148 titles.
2149
2150 M. Delete any section Entitled "Endorsements". Such a section
2151 may not be included in the Modified Version.
2152
2153 N. Do not retitle any existing section to be Entitled
2154 "Endorsements" or to conflict in title with any Invariant
2155 Section.
2156
2157 O. Preserve any Warranty Disclaimers.
2158
2159 If the Modified Version includes new front-matter sections or
2160 appendices that qualify as Secondary Sections and contain no
2161 material copied from the Document, you may at your option
2162 designate some or all of these sections as invariant. To do this,
2163 add their titles to the list of Invariant Sections in the Modified
2164 Version's license notice. These titles must be distinct from any
2165 other section titles.
2166
2167 You may add a section Entitled "Endorsements", provided it contains
2168 nothing but endorsements of your Modified Version by various
2169 parties--for example, statements of peer review or that the text
2170 has been approved by an organization as the authoritative
2171 definition of a standard.
2172
2173 You may add a passage of up to five words as a Front-Cover Text,
2174 and a passage of up to 25 words as a Back-Cover Text, to the end
2175 of the list of Cover Texts in the Modified Version. Only one
2176 passage of Front-Cover Text and one of Back-Cover Text may be
2177 added by (or through arrangements made by) any one entity. If the
2178 Document already includes a cover text for the same cover,
2179 previously added by you or by arrangement made by the same entity
2180 you are acting on behalf of, you may not add another; but you may
2181 replace the old one, on explicit permission from the previous
2182 publisher that added the old one.
2183
2184 The author(s) and publisher(s) of the Document do not by this
2185 License give permission to use their names for publicity for or to
2186 assert or imply endorsement of any Modified Version.
2187
2188 5. COMBINING DOCUMENTS
2189
2190 You may combine the Document with other documents released under
2191 this License, under the terms defined in section 4 above for
2192 modified versions, provided that you include in the combination
2193 all of the Invariant Sections of all of the original documents,
2194 unmodified, and list them all as Invariant Sections of your
2195 combined work in its license notice, and that you preserve all
2196 their Warranty Disclaimers.
2197
2198 The combined work need only contain one copy of this License, and
2199 multiple identical Invariant Sections may be replaced with a single
2200 copy. If there are multiple Invariant Sections with the same name
2201 but different contents, make the title of each such section unique
2202 by adding at the end of it, in parentheses, the name of the
2203 original author or publisher of that section if known, or else a
2204 unique number. Make the same adjustment to the section titles in
2205 the list of Invariant Sections in the license notice of the
2206 combined work.
2207
2208 In the combination, you must combine any sections Entitled
2209 "History" in the various original documents, forming one section
2210 Entitled "History"; likewise combine any sections Entitled
2211 "Acknowledgements", and any sections Entitled "Dedications". You
2212 must delete all sections Entitled "Endorsements."
2213
2214 6. COLLECTIONS OF DOCUMENTS
2215
2216 You may make a collection consisting of the Document and other
2217 documents released under this License, and replace the individual
2218 copies of this License in the various documents with a single copy
2219 that is included in the collection, provided that you follow the
2220 rules of this License for verbatim copying of each of the
2221 documents in all other respects.
2222
2223 You may extract a single document from such a collection, and
2224 distribute it individually under this License, provided you insert
2225 a copy of this License into the extracted document, and follow
2226 this License in all other respects regarding verbatim copying of
2227 that document.
2228
2229 7. AGGREGATION WITH INDEPENDENT WORKS
2230
2231 A compilation of the Document or its derivatives with other
2232 separate and independent documents or works, in or on a volume of
2233 a storage or distribution medium, is called an "aggregate" if the
2234 copyright resulting from the compilation is not used to limit the
2235 legal rights of the compilation's users beyond what the individual
2236 works permit. When the Document is included in an aggregate, this
2237 License does not apply to the other works in the aggregate which
2238 are not themselves derivative works of the Document.
2239
2240 If the Cover Text requirement of section 3 is applicable to these
2241 copies of the Document, then if the Document is less than one half
2242 of the entire aggregate, the Document's Cover Texts may be placed
2243 on covers that bracket the Document within the aggregate, or the
2244 electronic equivalent of covers if the Document is in electronic
2245 form. Otherwise they must appear on printed covers that bracket
2246 the whole aggregate.
2247
2248 8. TRANSLATION
2249
2250 Translation is considered a kind of modification, so you may
2251 distribute translations of the Document under the terms of section
2252 4. Replacing Invariant Sections with translations requires special
2253 permission from their copyright holders, but you may include
2254 translations of some or all Invariant Sections in addition to the
2255 original versions of these Invariant Sections. You may include a
2256 translation of this License, and all the license notices in the
2257 Document, and any Warranty Disclaimers, provided that you also
2258 include the original English version of this License and the
2259 original versions of those notices and disclaimers. In case of a
2260 disagreement between the translation and the original version of
2261 this License or a notice or disclaimer, the original version will
2262 prevail.
2263
2264 If a section in the Document is Entitled "Acknowledgements",
2265 "Dedications", or "History", the requirement (section 4) to
2266 Preserve its Title (section 1) will typically require changing the
2267 actual title.
2268
2269 9. TERMINATION
2270
2271 You may not copy, modify, sublicense, or distribute the Document
2272 except as expressly provided under this License. Any attempt
2273 otherwise to copy, modify, sublicense, or distribute it is void,
2274 and will automatically terminate your rights under this License.
2275
2276 However, if you cease all violation of this License, then your
2277 license from a particular copyright holder is reinstated (a)
2278 provisionally, unless and until the copyright holder explicitly
2279 and finally terminates your license, and (b) permanently, if the
2280 copyright holder fails to notify you of the violation by some
2281 reasonable means prior to 60 days after the cessation.
2282
2283 Moreover, your license from a particular copyright holder is
2284 reinstated permanently if the copyright holder notifies you of the
2285 violation by some reasonable means, this is the first time you have
2286 received notice of violation of this License (for any work) from
2287 that copyright holder, and you cure the violation prior to 30 days
2288 after your receipt of the notice.
2289
2290 Termination of your rights under this section does not terminate
2291 the licenses of parties who have received copies or rights from
2292 you under this License. If your rights have been terminated and
2293 not permanently reinstated, receipt of a copy of some or all of
2294 the same material does not give you any rights to use it.
2295
2296 10. FUTURE REVISIONS OF THIS LICENSE
2297
2298 The Free Software Foundation may publish new, revised versions of
2299 the GNU Free Documentation License from time to time. Such new
2300 versions will be similar in spirit to the present version, but may
2301 differ in detail to address new problems or concerns. See
2302 `http://www.gnu.org/copyleft/'.
2303
2304 Each version of the License is given a distinguishing version
2305 number. If the Document specifies that a particular numbered
2306 version of this License "or any later version" applies to it, you
2307 have the option of following the terms and conditions either of
2308 that specified version or of any later version that has been
2309 published (not as a draft) by the Free Software Foundation. If
2310 the Document does not specify a version number of this License,
2311 you may choose any version ever published (not as a draft) by the
2312 Free Software Foundation. If the Document specifies that a proxy
2313 can decide which future versions of this License can be used, that
2314 proxy's public statement of acceptance of a version permanently
2315 authorizes you to choose that version for the Document.
2316
2317 11. RELICENSING
2318
2319 "Massive Multiauthor Collaboration Site" (or "MMC Site") means any
2320 World Wide Web server that publishes copyrightable works and also
2321 provides prominent facilities for anybody to edit those works. A
2322 public wiki that anybody can edit is an example of such a server.
2323 A "Massive Multiauthor Collaboration" (or "MMC") contained in the
2324 site means any set of copyrightable works thus published on the MMC
2325 site.
2326
2327 "CC-BY-SA" means the Creative Commons Attribution-Share Alike 3.0
2328 license published by Creative Commons Corporation, a not-for-profit
2329 corporation with a principal place of business in San Francisco,
2330 California, as well as future copyleft versions of that license
2331 published by that same organization.
2332
2333 "Incorporate" means to publish or republish a Document, in whole or
2334 in part, as part of another Document.
2335
2336 An MMC is "eligible for relicensing" if it is licensed under this
2337 License, and if all works that were first published under this
2338 License somewhere other than this MMC, and subsequently
2339 incorporated in whole or in part into the MMC, (1) had no cover
2340 texts or invariant sections, and (2) were thus incorporated prior
2341 to November 1, 2008.
2342
2343 The operator of an MMC Site may republish an MMC contained in the
2344 site under CC-BY-SA on the same site at any time before August 1,
2345 2009, provided the MMC is eligible for relicensing.
2346
2347
2348ADDENDUM: How to use this License for your documents
2349====================================================
2350
2351To use this License in a document you have written, include a copy of
2352the License in the document and put the following copyright and license
2353notices just after the title page:
2354
2355 Copyright (C) YEAR YOUR NAME.
2356 Permission is granted to copy, distribute and/or modify this document
2357 under the terms of the GNU Free Documentation License, Version 1.3
2358 or any later version published by the Free Software Foundation;
2359 with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
2360 Texts. A copy of the license is included in the section entitled ``GNU
2361 Free Documentation License''.
2362
2363 If you have Invariant Sections, Front-Cover Texts and Back-Cover
2364Texts, replace the "with...Texts." line with this:
2365
2366 with the Invariant Sections being LIST THEIR TITLES, with
2367 the Front-Cover Texts being LIST, and with the Back-Cover Texts
2368 being LIST.
2369
2370 If you have Invariant Sections without Cover Texts, or some other
2371combination of the three, merge those two alternatives to suit the
2372situation.
2373
2374 If your document contains nontrivial examples of program code, we
2375recommend releasing these examples in parallel under your choice of
2376free software license, such as the GNU General Public License, to
2377permit their use in free software.
2378
2379
2380File: libmicrohttpd-tutorial.info, Node: Example programs, Prev: License text, Up: Top
2381
2382Appendix C Example programs
2383***************************
2384
2385* Menu:
2386
2387* hellobrowser.c::
2388* logging.c::
2389* responseheaders.c::
2390* basicauthentication.c::
2391* simplepost.c::
2392* largepost.c::
2393* sessions.c::
2394* tlsauthentication.c::
2395
2396
2397File: libmicrohttpd-tutorial.info, Node: hellobrowser.c, Next: logging.c, Up: Example programs
2398
2399C.1 hellobrowser.c
2400==================
2401
2402 /* Feel free to use this example code in any way
2403 you see fit (Public Domain) */
2404
2405 #include <sys/types.h>
2406 #ifndef _WIN32
2407 #include <sys/select.h>
2408 #include <sys/socket.h>
2409 #else
2410 #include <winsock2.h>
2411 #endif
2412 #include <string.h>
2413 #include <microhttpd.h>
2414 #include <stdio.h>
2415
2416 #define PORT 8888
2417
2418 static int
2419 answer_to_connection (void *cls, struct MHD_Connection *connection,
2420 const char *url, const char *method,
2421 const char *version, const char *upload_data,
2422 size_t *upload_data_size, void **con_cls)
2423 {
2424 const char *page = "<html><body>Hello, browser!</body></html>";
2425 struct MHD_Response *response;
2426 int ret;
2427
2428 response =
2429 MHD_create_response_from_buffer (strlen (page), (void *) page,
2430 MHD_RESPMEM_PERSISTENT);
2431 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
2432 MHD_destroy_response (response);
2433
2434 return ret;
2435 }
2436
2437
2438 int
2439 main ()
2440 {
2441 struct MHD_Daemon *daemon;
2442
2443 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
2444 &answer_to_connection, NULL, MHD_OPTION_END);
2445 if (NULL == daemon)
2446 return 1;
2447
2448 (void) getchar ();
2449
2450 MHD_stop_daemon (daemon);
2451 return 0;
2452 }
2453
2454
2455File: libmicrohttpd-tutorial.info, Node: logging.c, Next: responseheaders.c, Prev: hellobrowser.c, Up: Example programs
2456
2457C.2 logging.c
2458=============
2459
2460 /* Feel free to use this example code in any way
2461 you see fit (Public Domain) */
2462
2463 #include <sys/types.h>
2464 #ifndef _WIN32
2465 #include <sys/select.h>
2466 #include <sys/socket.h>
2467 #else
2468 #include <winsock2.h>
2469 #endif
2470 #include <microhttpd.h>
2471 #include <stdio.h>
2472
2473 #define PORT 8888
2474
2475
2476 static int
2477 print_out_key (void *cls, enum MHD_ValueKind kind, const char *key,
2478 const char *value)
2479 {
2480 printf ("%s: %s\n", key, value);
2481 return MHD_YES;
2482 }
2483
2484
2485 static int
2486 answer_to_connection (void *cls, struct MHD_Connection *connection,
2487 const char *url, const char *method,
2488 const char *version, const char *upload_data,
2489 size_t *upload_data_size, void **con_cls)
2490 {
2491 printf ("New %s request for %s using version %s\n", method, url, version);
2492
2493 MHD_get_connection_values (connection, MHD_HEADER_KIND, print_out_key,
2494 NULL);
2495
2496 return MHD_NO;
2497 }
2498
2499
2500 int
2501 main ()
2502 {
2503 struct MHD_Daemon *daemon;
2504
2505 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
2506 &answer_to_connection, NULL, MHD_OPTION_END);
2507 if (NULL == daemon)
2508 return 1;
2509
2510 (void) getchar ();
2511
2512 MHD_stop_daemon (daemon);
2513 return 0;
2514 }
2515
2516
2517File: libmicrohttpd-tutorial.info, Node: responseheaders.c, Next: basicauthentication.c, Prev: logging.c, Up: Example programs
2518
2519C.3 responseheaders.c
2520=====================
2521
2522 /* Feel free to use this example code in any way
2523 you see fit (Public Domain) */
2524
2525 #include <sys/types.h>
2526 #ifndef _WIN32
2527 #include <sys/select.h>
2528 #include <sys/socket.h>
2529 #else
2530 #include <winsock2.h>
2531 #endif
2532 #include <microhttpd.h>
2533 #include <time.h>
2534 #include <sys/stat.h>
2535 #include <fcntl.h>
2536 #include <string.h>
2537 #include <stdio.h>
2538
2539 #define PORT 8888
2540 #define FILENAME "picture.png"
2541 #define MIMETYPE "image/png"
2542
2543 static int
2544 answer_to_connection (void *cls, struct MHD_Connection *connection,
2545 const char *url, const char *method,
2546 const char *version, const char *upload_data,
2547 size_t *upload_data_size, void **con_cls)
2548 {
2549 struct MHD_Response *response;
2550 int fd;
2551 int ret;
2552 struct stat sbuf;
2553
2554 if (0 != strcmp (method, "GET"))
2555 return MHD_NO;
2556
2557 if ( (-1 == (fd = open (FILENAME, O_RDONLY))) ||
2558 (0 != fstat (fd, &sbuf)) )
2559 {
2560 /* error accessing file */
2561 if (fd != -1)
2562 (void) close (fd);
2563 const char *errorstr =
2564 "<html><body>An internal server error has occured!\
2565 </body></html>";
2566 response =
2567 MHD_create_response_from_buffer (strlen (errorstr),
2568 (void *) errorstr,
2569 MHD_RESPMEM_PERSISTENT);
2570 if (NULL != response)
2571 {
2572 ret =
2573 MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR,
2574 response);
2575 MHD_destroy_response (response);
2576
2577 return ret;
2578 }
2579 else
2580 return MHD_NO;
2581 }
2582 response =
2583 MHD_create_response_from_fd_at_offset (sbuf.st_size, fd, 0);
2584 MHD_add_response_header (response, "Content-Type", MIMETYPE);
2585 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
2586 MHD_destroy_response (response);
2587
2588 return ret;
2589 }
2590
2591
2592 int
2593 main ()
2594 {
2595 struct MHD_Daemon *daemon;
2596
2597 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
2598 &answer_to_connection, NULL, MHD_OPTION_END);
2599 if (NULL == daemon)
2600 return 1;
2601
2602 (void) getchar ();
2603
2604 MHD_stop_daemon (daemon);
2605
2606 return 0;
2607 }
2608
2609
2610File: libmicrohttpd-tutorial.info, Node: basicauthentication.c, Next: simplepost.c, Prev: responseheaders.c, Up: Example programs
2611
2612C.4 basicauthentication.c
2613=========================
2614
2615 /* Feel free to use this example code in any way
2616 you see fit (Public Domain) */
2617
2618 #include <sys/types.h>
2619 #ifndef _WIN32
2620 #include <sys/select.h>
2621 #include <sys/socket.h>
2622 #else
2623 #include <winsock2.h>
2624 #endif
2625 #include <microhttpd.h>
2626 #include <time.h>
2627 #include <string.h>
2628 #include <stdlib.h>
2629 #include <stdio.h>
2630
2631 #define PORT 8888
2632
2633
2634 static int
2635 answer_to_connection (void *cls, struct MHD_Connection *connection,
2636 const char *url, const char *method,
2637 const char *version, const char *upload_data,
2638 size_t *upload_data_size, void **con_cls)
2639 {
2640 char *user;
2641 char *pass;
2642 int fail;
2643 int ret;
2644 struct MHD_Response *response;
2645
2646 if (0 != strcmp (method, "GET"))
2647 return MHD_NO;
2648 if (NULL == *con_cls)
2649 {
2650 *con_cls = connection;
2651 return MHD_YES;
2652 }
2653 pass = NULL;
2654 user = MHD_basic_auth_get_username_password (connection, &pass);
2655 fail = ( (user == NULL) ||
2656 (0 != strcmp (user, "root")) ||
2657 (0 != strcmp (pass, "pa$$w0rd") ) );
2658 if (user != NULL) free (user);
2659 if (pass != NULL) free (pass);
2660 if (fail)
2661 {
2662 const char *page = "<html><body>Go away.</body></html>";
2663 response =
2664 MHD_create_response_from_buffer (strlen (page), (void *) page,
2665 MHD_RESPMEM_PERSISTENT);
2666 ret = MHD_queue_basic_auth_fail_response (connection,
2667 "my realm",
2668 response);
2669 }
2670 else
2671 {
2672 const char *page = "<html><body>A secret.</body></html>";
2673 response =
2674 MHD_create_response_from_buffer (strlen (page), (void *) page,
2675 MHD_RESPMEM_PERSISTENT);
2676 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
2677 }
2678 MHD_destroy_response (response);
2679 return ret;
2680 }
2681
2682
2683 int
2684 main ()
2685 {
2686 struct MHD_Daemon *daemon;
2687
2688 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
2689 &answer_to_connection, NULL, MHD_OPTION_END);
2690 if (NULL == daemon)
2691 return 1;
2692
2693 (void) getchar ();
2694
2695 MHD_stop_daemon (daemon);
2696 return 0;
2697 }
2698
2699
2700File: libmicrohttpd-tutorial.info, Node: simplepost.c, Next: largepost.c, Prev: basicauthentication.c, Up: Example programs
2701
2702C.5 simplepost.c
2703================
2704
2705 /* Feel free to use this example code in any way
2706 you see fit (Public Domain) */
2707
2708 #include <sys/types.h>
2709 #ifndef _WIN32
2710 #include <sys/select.h>
2711 #include <sys/socket.h>
2712 #else
2713 #include <winsock2.h>
2714 #endif
2715 #include <microhttpd.h>
2716 #include <stdio.h>
2717 #include <string.h>
2718 #include <stdlib.h>
2719
2720 #define PORT 8888
2721 #define POSTBUFFERSIZE 512
2722 #define MAXNAMESIZE 20
2723 #define MAXANSWERSIZE 512
2724
2725 #define GET 0
2726 #define POST 1
2727
2728 struct connection_info_struct
2729 {
2730 int connectiontype;
2731 char *answerstring;
2732 struct MHD_PostProcessor *postprocessor;
2733 };
2734
2735 const char *askpage = "<html><body>\
2736 What's your name, Sir?<br>\
2737 <form action=\"/namepost\" method=\"post\">\
2738 <input name=\"name\" type=\"text\"\
2739 <input type=\"submit\" value=\" Send \"></form>\
2740 </body></html>";
2741
2742 const char *greetingpage =
2743 "<html><body><h1>Welcome, %s!</center></h1></body></html>";
2744
2745 const char *errorpage =
2746 "<html><body>This doesn't seem to be right.</body></html>";
2747
2748
2749 static int
2750 send_page (struct MHD_Connection *connection, const char *page)
2751 {
2752 int ret;
2753 struct MHD_Response *response;
2754
2755
2756 response =
2757 MHD_create_response_from_buffer (strlen (page), (void *) page,
2758 MHD_RESPMEM_PERSISTENT);
2759 if (!response)
2760 return MHD_NO;
2761
2762 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
2763 MHD_destroy_response (response);
2764
2765 return ret;
2766 }
2767
2768
2769 static int
2770 iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
2771 const char *filename, const char *content_type,
2772 const char *transfer_encoding, const char *data, uint64_t off,
2773 size_t size)
2774 {
2775 struct connection_info_struct *con_info = coninfo_cls;
2776
2777 if (0 == strcmp (key, "name"))
2778 {
2779 if ((size > 0) && (size <= MAXNAMESIZE))
2780 {
2781 char *answerstring;
2782 answerstring = malloc (MAXANSWERSIZE);
2783 if (!answerstring)
2784 return MHD_NO;
2785
2786 snprintf (answerstring, MAXANSWERSIZE, greetingpage, data);
2787 con_info->answerstring = answerstring;
2788 }
2789 else
2790 con_info->answerstring = NULL;
2791
2792 return MHD_NO;
2793 }
2794
2795 return MHD_YES;
2796 }
2797
2798 static void
2799 request_completed (void *cls, struct MHD_Connection *connection,
2800 void **con_cls, enum MHD_RequestTerminationCode toe)
2801 {
2802 struct connection_info_struct *con_info = *con_cls;
2803
2804 if (NULL == con_info)
2805 return;
2806
2807 if (con_info->connectiontype == POST)
2808 {
2809 MHD_destroy_post_processor (con_info->postprocessor);
2810 if (con_info->answerstring)
2811 free (con_info->answerstring);
2812 }
2813
2814 free (con_info);
2815 *con_cls = NULL;
2816 }
2817
2818
2819 static int
2820 answer_to_connection (void *cls, struct MHD_Connection *connection,
2821 const char *url, const char *method,
2822 const char *version, const char *upload_data,
2823 size_t *upload_data_size, void **con_cls)
2824 {
2825 if (NULL == *con_cls)
2826 {
2827 struct connection_info_struct *con_info;
2828
2829 con_info = malloc (sizeof (struct connection_info_struct));
2830 if (NULL == con_info)
2831 return MHD_NO;
2832 con_info->answerstring = NULL;
2833
2834 if (0 == strcmp (method, "POST"))
2835 {
2836 con_info->postprocessor =
2837 MHD_create_post_processor (connection, POSTBUFFERSIZE,
2838 iterate_post, (void *) con_info);
2839
2840 if (NULL == con_info->postprocessor)
2841 {
2842 free (con_info);
2843 return MHD_NO;
2844 }
2845
2846 con_info->connectiontype = POST;
2847 }
2848 else
2849 con_info->connectiontype = GET;
2850
2851 *con_cls = (void *) con_info;
2852
2853 return MHD_YES;
2854 }
2855
2856 if (0 == strcmp (method, "GET"))
2857 {
2858 return send_page (connection, askpage);
2859 }
2860
2861 if (0 == strcmp (method, "POST"))
2862 {
2863 struct connection_info_struct *con_info = *con_cls;
2864
2865 if (*upload_data_size != 0)
2866 {
2867 MHD_post_process (con_info->postprocessor, upload_data,
2868 *upload_data_size);
2869 *upload_data_size = 0;
2870
2871 return MHD_YES;
2872 }
2873 else if (NULL != con_info->answerstring)
2874 return send_page (connection, con_info->answerstring);
2875 }
2876
2877 return send_page (connection, errorpage);
2878 }
2879
2880 int
2881 main ()
2882 {
2883 struct MHD_Daemon *daemon;
2884
2885 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
2886 &answer_to_connection, NULL,
2887 MHD_OPTION_NOTIFY_COMPLETED, request_completed,
2888 NULL, MHD_OPTION_END);
2889 if (NULL == daemon)
2890 return 1;
2891
2892 (void) getchar ();
2893
2894 MHD_stop_daemon (daemon);
2895
2896 return 0;
2897 }
2898
2899
2900File: libmicrohttpd-tutorial.info, Node: largepost.c, Next: sessions.c, Prev: simplepost.c, Up: Example programs
2901
2902C.6 largepost.c
2903===============
2904
2905 /* Feel free to use this example code in any way
2906 you see fit (Public Domain) */
2907
2908 #include <sys/types.h>
2909 #ifndef _WIN32
2910 #include <sys/select.h>
2911 #include <sys/socket.h>
2912 #else
2913 #include <winsock2.h>
2914 #endif
2915 #include <stdio.h>
2916 #include <stdlib.h>
2917 #include <string.h>
2918 #include <microhttpd.h>
2919
2920 #define PORT 8888
2921 #define POSTBUFFERSIZE 512
2922 #define MAXCLIENTS 2
2923
2924 #define GET 0
2925 #define POST 1
2926
2927 static unsigned int nr_of_uploading_clients = 0;
2928
2929 struct connection_info_struct
2930 {
2931 int connectiontype;
2932 struct MHD_PostProcessor *postprocessor;
2933 FILE *fp;
2934 const char *answerstring;
2935 int answercode;
2936 };
2937
2938 const char *askpage = "<html><body>\n\
2939 Upload a file, please!<br>\n\
2940 There are %u clients uploading at the moment.<br>\n\
2941 <form action=\"/filepost\" method=\"post\" enctype=\"multipart/form-data\">\n\
2942 <input name=\"file\" type=\"file\">\n\
2943 <input type=\"submit\" value=\" Send \"></form>\n\
2944 </body></html>";
2945
2946 const char *busypage =
2947 "<html><body>This server is busy, please try again later.</body></html>";
2948
2949 const char *completepage =
2950 "<html><body>The upload has been completed.</body></html>";
2951
2952 const char *errorpage =
2953 "<html><body>This doesn't seem to be right.</body></html>";
2954 const char *servererrorpage =
2955 "<html><body>An internal server error has occured.</body></html>";
2956 const char *fileexistspage =
2957 "<html><body>This file already exists.</body></html>";
2958
2959
2960 static int
2961 send_page (struct MHD_Connection *connection, const char *page,
2962 int status_code)
2963 {
2964 int ret;
2965 struct MHD_Response *response;
2966
2967 response =
2968 MHD_create_response_from_buffer (strlen (page), (void *) page,
2969 MHD_RESPMEM_MUST_COPY);
2970 if (!response)
2971 return MHD_NO;
2972 MHD_add_response_header (response, MHD_HTTP_HEADER_CONTENT_TYPE, "text/html");
2973 ret = MHD_queue_response (connection, status_code, response);
2974 MHD_destroy_response (response);
2975
2976 return ret;
2977 }
2978
2979
2980 static int
2981 iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
2982 const char *filename, const char *content_type,
2983 const char *transfer_encoding, const char *data, uint64_t off,
2984 size_t size)
2985 {
2986 struct connection_info_struct *con_info = coninfo_cls;
2987 FILE *fp;
2988
2989 con_info->answerstring = servererrorpage;
2990 con_info->answercode = MHD_HTTP_INTERNAL_SERVER_ERROR;
2991
2992 if (0 != strcmp (key, "file"))
2993 return MHD_NO;
2994
2995 if (!con_info->fp)
2996 {
2997 if (NULL != (fp = fopen (filename, "rb")))
2998 {
2999 fclose (fp);
3000 con_info->answerstring = fileexistspage;
3001 con_info->answercode = MHD_HTTP_FORBIDDEN;
3002 return MHD_NO;
3003 }
3004
3005 con_info->fp = fopen (filename, "ab");
3006 if (!con_info->fp)
3007 return MHD_NO;
3008 }
3009
3010 if (size > 0)
3011 {
3012 if (!fwrite (data, size, sizeof (char), con_info->fp))
3013 return MHD_NO;
3014 }
3015
3016 con_info->answerstring = completepage;
3017 con_info->answercode = MHD_HTTP_OK;
3018
3019 return MHD_YES;
3020 }
3021
3022
3023 static void
3024 request_completed (void *cls, struct MHD_Connection *connection,
3025 void **con_cls, enum MHD_RequestTerminationCode toe)
3026 {
3027 struct connection_info_struct *con_info = *con_cls;
3028
3029 if (NULL == con_info)
3030 return;
3031
3032 if (con_info->connectiontype == POST)
3033 {
3034 if (NULL != con_info->postprocessor)
3035 {
3036 MHD_destroy_post_processor (con_info->postprocessor);
3037 nr_of_uploading_clients--;
3038 }
3039
3040 if (con_info->fp)
3041 fclose (con_info->fp);
3042 }
3043
3044 free (con_info);
3045 *con_cls = NULL;
3046 }
3047
3048
3049 static int
3050 answer_to_connection (void *cls, struct MHD_Connection *connection,
3051 const char *url, const char *method,
3052 const char *version, const char *upload_data,
3053 size_t *upload_data_size, void **con_cls)
3054 {
3055 if (NULL == *con_cls)
3056 {
3057 struct connection_info_struct *con_info;
3058
3059 if (nr_of_uploading_clients >= MAXCLIENTS)
3060 return send_page (connection, busypage, MHD_HTTP_SERVICE_UNAVAILABLE);
3061
3062 con_info = malloc (sizeof (struct connection_info_struct));
3063 if (NULL == con_info)
3064 return MHD_NO;
3065
3066 con_info->fp = NULL;
3067
3068 if (0 == strcmp (method, "POST"))
3069 {
3070 con_info->postprocessor =
3071 MHD_create_post_processor (connection, POSTBUFFERSIZE,
3072 iterate_post, (void *) con_info);
3073
3074 if (NULL == con_info->postprocessor)
3075 {
3076 free (con_info);
3077 return MHD_NO;
3078 }
3079
3080 nr_of_uploading_clients++;
3081
3082 con_info->connectiontype = POST;
3083 con_info->answercode = MHD_HTTP_OK;
3084 con_info->answerstring = completepage;
3085 }
3086 else
3087 con_info->connectiontype = GET;
3088
3089 *con_cls = (void *) con_info;
3090
3091 return MHD_YES;
3092 }
3093
3094 if (0 == strcmp (method, "GET"))
3095 {
3096 char buffer[1024];
3097
3098 snprintf (buffer, sizeof (buffer), askpage, nr_of_uploading_clients);
3099 return send_page (connection, buffer, MHD_HTTP_OK);
3100 }
3101
3102 if (0 == strcmp (method, "POST"))
3103 {
3104 struct connection_info_struct *con_info = *con_cls;
3105
3106 if (0 != *upload_data_size)
3107 {
3108 MHD_post_process (con_info->postprocessor, upload_data,
3109 *upload_data_size);
3110 *upload_data_size = 0;
3111
3112 return MHD_YES;
3113 }
3114 else
3115 {
3116 if (NULL != con_info->fp)
3117 {
3118 fclose (con_info->fp);
3119 con_info->fp = NULL;
3120 }
3121 /* Now it is safe to open and inspect the file before calling send_page with a response */
3122 return send_page (connection, con_info->answerstring,
3123 con_info->answercode);
3124 }
3125
3126 }
3127
3128 return send_page (connection, errorpage, MHD_HTTP_BAD_REQUEST);
3129 }
3130
3131
3132 int
3133 main ()
3134 {
3135 struct MHD_Daemon *daemon;
3136
3137 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
3138 &answer_to_connection, NULL,
3139 MHD_OPTION_NOTIFY_COMPLETED, request_completed,
3140 NULL, MHD_OPTION_END);
3141 if (NULL == daemon)
3142 return 1;
3143 (void) getchar ();
3144 MHD_stop_daemon (daemon);
3145 return 0;
3146 }
3147
3148
3149File: libmicrohttpd-tutorial.info, Node: sessions.c, Next: tlsauthentication.c, Prev: largepost.c, Up: Example programs
3150
3151C.7 sessions.c
3152==============
3153
3154 /* Feel free to use this example code in any way
3155 you see fit (Public Domain) */
3156
3157 /* needed for asprintf */
3158 #define _GNU_SOURCE
3159
3160 #include <stdlib.h>
3161 #include <string.h>
3162 #include <stdio.h>
3163 #include <errno.h>
3164 #include <time.h>
3165 #include <microhttpd.h>
3166
3167 #if defined _WIN32 && !defined(__MINGW64_VERSION_MAJOR)
3168 static int
3169 asprintf (char **resultp, const char *format, ...)
3170 {
3171 va_list argptr;
3172 char *result = NULL;
3173 int len = 0;
3174
3175 if (format == NULL)
3176 return -1;
3177
3178 va_start (argptr, format);
3179
3180 len = _vscprintf ((char *) format, argptr);
3181 if (len >= 0)
3182 {
3183 len += 1;
3184 result = (char *) malloc (sizeof (char *) * len);
3185 if (result != NULL)
3186 {
3187 int len2 = _vscprintf ((char *) format, argptr);
3188 if (len2 != len - 1 || len2 <= 0)
3189 {
3190 free (result);
3191 result = NULL;
3192 len = -1;
3193 }
3194 else
3195 {
3196 len = len2;
3197 if (resultp)
3198 *resultp = result;
3199 }
3200 }
3201 }
3202 va_end (argptr);
3203 return len;
3204 }
3205 #endif
3206
3207 /**
3208 * Invalid method page.
3209 */
3210 #define METHOD_ERROR "<html><head><title>Illegal request</title></head><body>Go away.</body></html>"
3211
3212 /**
3213 * Invalid URL page.
3214 */
3215 #define NOT_FOUND_ERROR "<html><head><title>Not found</title></head><body>Go away.</body></html>"
3216
3217 /**
3218 * Front page. (/)
3219 */
3220 #define MAIN_PAGE "<html><head><title>Welcome</title></head><body><form action=\"/2\" method=\"post\">What is your name? <input type=\"text\" name=\"v1\" value=\"%s\" /><input type=\"submit\" value=\"Next\" /></body></html>"
3221
3222 /**
3223 * Second page. (/2)
3224 */
3225 #define SECOND_PAGE "<html><head><title>Tell me more</title></head><body><a href=\"/\">previous</a> <form action=\"/S\" method=\"post\">%s, what is your job? <input type=\"text\" name=\"v2\" value=\"%s\" /><input type=\"submit\" value=\"Next\" /></body></html>"
3226
3227 /**
3228 * Second page (/S)
3229 */
3230 #define SUBMIT_PAGE "<html><head><title>Ready to submit?</title></head><body><form action=\"/F\" method=\"post\"><a href=\"/2\">previous </a> <input type=\"hidden\" name=\"DONE\" value=\"yes\" /><input type=\"submit\" value=\"Submit\" /></body></html>"
3231
3232 /**
3233 * Last page.
3234 */
3235 #define LAST_PAGE "<html><head><title>Thank you</title></head><body>Thank you.</body></html>"
3236
3237 /**
3238 * Name of our cookie.
3239 */
3240 #define COOKIE_NAME "session"
3241
3242
3243 /**
3244 * State we keep for each user/session/browser.
3245 */
3246 struct Session
3247 {
3248 /**
3249 * We keep all sessions in a linked list.
3250 */
3251 struct Session *next;
3252
3253 /**
3254 * Unique ID for this session.
3255 */
3256 char sid[33];
3257
3258 /**
3259 * Reference counter giving the number of connections
3260 * currently using this session.
3261 */
3262 unsigned int rc;
3263
3264 /**
3265 * Time when this session was last active.
3266 */
3267 time_t start;
3268
3269 /**
3270 * String submitted via form.
3271 */
3272 char value_1[64];
3273
3274 /**
3275 * Another value submitted via form.
3276 */
3277 char value_2[64];
3278
3279 };
3280
3281
3282 /**
3283 * Data kept per request.
3284 */
3285 struct Request
3286 {
3287
3288 /**
3289 * Associated session.
3290 */
3291 struct Session *session;
3292
3293 /**
3294 * Post processor handling form data (IF this is
3295 * a POST request).
3296 */
3297 struct MHD_PostProcessor *pp;
3298
3299 /**
3300 * URL to serve in response to this POST (if this request
3301 * was a 'POST')
3302 */
3303 const char *post_url;
3304
3305 };
3306
3307
3308 /**
3309 * Linked list of all active sessions. Yes, O(n) but a
3310 * hash table would be overkill for a simple example...
3311 */
3312 static struct Session *sessions;
3313
3314
3315
3316
3317 /**
3318 * Return the session handle for this connection, or
3319 * create one if this is a new user.
3320 */
3321 static struct Session *
3322 get_session (struct MHD_Connection *connection)
3323 {
3324 struct Session *ret;
3325 const char *cookie;
3326
3327 cookie = MHD_lookup_connection_value (connection,
3328 MHD_COOKIE_KIND,
3329 COOKIE_NAME);
3330 if (cookie != NULL)
3331 {
3332 /* find existing session */
3333 ret = sessions;
3334 while (NULL != ret)
3335 {
3336 if (0 == strcmp (cookie, ret->sid))
3337 break;
3338 ret = ret->next;
3339 }
3340 if (NULL != ret)
3341 {
3342 ret->rc++;
3343 return ret;
3344 }
3345 }
3346 /* create fresh session */
3347 ret = calloc (1, sizeof (struct Session));
3348 if (NULL == ret)
3349 {
3350 fprintf (stderr, "calloc error: %s\n", strerror (errno));
3351 return NULL;
3352 }
3353 /* not a super-secure way to generate a random session ID,
3354 but should do for a simple example... */
3355 snprintf (ret->sid,
3356 sizeof (ret->sid),
3357 "%X%X%X%X",
3358 (unsigned int) rand (),
3359 (unsigned int) rand (),
3360 (unsigned int) rand (),
3361 (unsigned int) rand ());
3362 ret->rc++;
3363 ret->start = time (NULL);
3364 ret->next = sessions;
3365 sessions = ret;
3366 return ret;
3367 }
3368
3369
3370 /**
3371 * Type of handler that generates a reply.
3372 *
3373 * @param cls content for the page (handler-specific)
3374 * @param mime mime type to use
3375 * @param session session information
3376 * @param connection connection to process
3377 * @param MHD_YES on success, MHD_NO on failure
3378 */
3379 typedef int (*PageHandler)(const void *cls,
3380 const char *mime,
3381 struct Session *session,
3382 struct MHD_Connection *connection);
3383
3384
3385 /**
3386 * Entry we generate for each page served.
3387 */
3388 struct Page
3389 {
3390 /**
3391 * Acceptable URL for this page.
3392 */
3393 const char *url;
3394
3395 /**
3396 * Mime type to set for the page.
3397 */
3398 const char *mime;
3399
3400 /**
3401 * Handler to call to generate response.
3402 */
3403 PageHandler handler;
3404
3405 /**
3406 * Extra argument to handler.
3407 */
3408 const void *handler_cls;
3409 };
3410
3411
3412 /**
3413 * Add header to response to set a session cookie.
3414 *
3415 * @param session session to use
3416 * @param response response to modify
3417 */
3418 static void
3419 add_session_cookie (struct Session *session,
3420 struct MHD_Response *response)
3421 {
3422 char cstr[256];
3423 snprintf (cstr,
3424 sizeof (cstr),
3425 "%s=%s",
3426 COOKIE_NAME,
3427 session->sid);
3428 if (MHD_NO ==
3429 MHD_add_response_header (response,
3430 MHD_HTTP_HEADER_SET_COOKIE,
3431 cstr))
3432 {
3433 fprintf (stderr,
3434 "Failed to set session cookie header!\n");
3435 }
3436 }
3437
3438
3439 /**
3440 * Handler that returns a simple static HTTP page that
3441 * is passed in via 'cls'.
3442 *
3443 * @param cls a 'const char *' with the HTML webpage to return
3444 * @param mime mime type to use
3445 * @param session session handle
3446 * @param connection connection to use
3447 */
3448 static int
3449 serve_simple_form (const void *cls,
3450 const char *mime,
3451 struct Session *session,
3452 struct MHD_Connection *connection)
3453 {
3454 int ret;
3455 const char *form = cls;
3456 struct MHD_Response *response;
3457
3458 /* return static form */
3459 response = MHD_create_response_from_buffer (strlen (form),
3460 (void *) form,
3461 MHD_RESPMEM_PERSISTENT);
3462 add_session_cookie (session, response);
3463 MHD_add_response_header (response,
3464 MHD_HTTP_HEADER_CONTENT_ENCODING,
3465 mime);
3466 ret = MHD_queue_response (connection,
3467 MHD_HTTP_OK,
3468 response);
3469 MHD_destroy_response (response);
3470 return ret;
3471 }
3472
3473
3474 /**
3475 * Handler that adds the 'v1' value to the given HTML code.
3476 *
3477 * @param cls a 'const char *' with the HTML webpage to return
3478 * @param mime mime type to use
3479 * @param session session handle
3480 * @param connection connection to use
3481 */
3482 static int
3483 fill_v1_form (const void *cls,
3484 const char *mime,
3485 struct Session *session,
3486 struct MHD_Connection *connection)
3487 {
3488 int ret;
3489 const char *form = cls;
3490 char *reply;
3491 struct MHD_Response *response;
3492
3493 if (-1 == asprintf (&reply,
3494 form,
3495 session->value_1))
3496 {
3497 /* oops */
3498 return MHD_NO;
3499 }
3500 /* return static form */
3501 response = MHD_create_response_from_buffer (strlen (reply),
3502 (void *) reply,
3503 MHD_RESPMEM_MUST_FREE);
3504 add_session_cookie (session, response);
3505 MHD_add_response_header (response,
3506 MHD_HTTP_HEADER_CONTENT_ENCODING,
3507 mime);
3508 ret = MHD_queue_response (connection,
3509 MHD_HTTP_OK,
3510 response);
3511 MHD_destroy_response (response);
3512 return ret;
3513 }
3514
3515
3516 /**
3517 * Handler that adds the 'v1' and 'v2' values to the given HTML code.
3518 *
3519 * @param cls a 'const char *' with the HTML webpage to return
3520 * @param mime mime type to use
3521 * @param session session handle
3522 * @param connection connection to use
3523 */
3524 static int
3525 fill_v1_v2_form (const void *cls,
3526 const char *mime,
3527 struct Session *session,
3528 struct MHD_Connection *connection)
3529 {
3530 int ret;
3531 const char *form = cls;
3532 char *reply;
3533 struct MHD_Response *response;
3534
3535 if (-1 == asprintf (&reply,
3536 form,
3537 session->value_1,
3538 session->value_2))
3539 {
3540 /* oops */
3541 return MHD_NO;
3542 }
3543 /* return static form */
3544 response = MHD_create_response_from_buffer (strlen (reply),
3545 (void *) reply,
3546 MHD_RESPMEM_MUST_FREE);
3547 add_session_cookie (session, response);
3548 MHD_add_response_header (response,
3549 MHD_HTTP_HEADER_CONTENT_ENCODING,
3550 mime);
3551 ret = MHD_queue_response (connection,
3552 MHD_HTTP_OK,
3553 response);
3554 MHD_destroy_response (response);
3555 return ret;
3556 }
3557
3558
3559 /**
3560 * Handler used to generate a 404 reply.
3561 *
3562 * @param cls a 'const char *' with the HTML webpage to return
3563 * @param mime mime type to use
3564 * @param session session handle
3565 * @param connection connection to use
3566 */
3567 static int
3568 not_found_page (const void *cls,
3569 const char *mime,
3570 struct Session *session,
3571 struct MHD_Connection *connection)
3572 {
3573 int ret;
3574 struct MHD_Response *response;
3575
3576 /* unsupported HTTP method */
3577 response = MHD_create_response_from_buffer (strlen (NOT_FOUND_ERROR),
3578 (void *) NOT_FOUND_ERROR,
3579 MHD_RESPMEM_PERSISTENT);
3580 ret = MHD_queue_response (connection,
3581 MHD_HTTP_NOT_FOUND,
3582 response);
3583 MHD_add_response_header (response,
3584 MHD_HTTP_HEADER_CONTENT_ENCODING,
3585 mime);
3586 MHD_destroy_response (response);
3587 return ret;
3588 }
3589
3590
3591 /**
3592 * List of all pages served by this HTTP server.
3593 */
3594 static struct Page pages[] =
3595 {
3596 { "/", "text/html", &fill_v1_form, MAIN_PAGE },
3597 { "/2", "text/html", &fill_v1_v2_form, SECOND_PAGE },
3598 { "/S", "text/html", &serve_simple_form, SUBMIT_PAGE },
3599 { "/F", "text/html", &serve_simple_form, LAST_PAGE },
3600 { NULL, NULL, &not_found_page, NULL } /* 404 */
3601 };
3602
3603
3604
3605 /**
3606 * Iterator over key-value pairs where the value
3607 * maybe made available in increments and/or may
3608 * not be zero-terminated. Used for processing
3609 * POST data.
3610 *
3611 * @param cls user-specified closure
3612 * @param kind type of the value
3613 * @param key 0-terminated key for the value
3614 * @param filename name of the uploaded file, NULL if not known
3615 * @param content_type mime-type of the data, NULL if not known
3616 * @param transfer_encoding encoding of the data, NULL if not known
3617 * @param data pointer to size bytes of data at the
3618 * specified offset
3619 * @param off offset of data in the overall value
3620 * @param size number of bytes in data available
3621 * @return MHD_YES to continue iterating,
3622 * MHD_NO to abort the iteration
3623 */
3624 static int
3625 post_iterator (void *cls,
3626 enum MHD_ValueKind kind,
3627 const char *key,
3628 const char *filename,
3629 const char *content_type,
3630 const char *transfer_encoding,
3631 const char *data, uint64_t off, size_t size)
3632 {
3633 struct Request *request = cls;
3634 struct Session *session = request->session;
3635
3636 if (0 == strcmp ("DONE", key))
3637 {
3638 fprintf (stdout,
3639 "Session `%s' submitted `%s', `%s'\n",
3640 session->sid,
3641 session->value_1,
3642 session->value_2);
3643 return MHD_YES;
3644 }
3645 if (0 == strcmp ("v1", key))
3646 {
3647 if (size + off > sizeof(session->value_1))
3648 size = sizeof (session->value_1) - off;
3649 memcpy (&session->value_1[off],
3650 data,
3651 size);
3652 if (size + off < sizeof (session->value_1))
3653 session->value_1[size+off] = '\0';
3654 return MHD_YES;
3655 }
3656 if (0 == strcmp ("v2", key))
3657 {
3658 if (size + off > sizeof(session->value_2))
3659 size = sizeof (session->value_2) - off;
3660 memcpy (&session->value_2[off],
3661 data,
3662 size);
3663 if (size + off < sizeof (session->value_2))
3664 session->value_2[size+off] = '\0';
3665 return MHD_YES;
3666 }
3667 fprintf (stderr, "Unsupported form value `%s'\n", key);
3668 return MHD_YES;
3669 }
3670
3671
3672 /**
3673 * Main MHD callback for handling requests.
3674 *
3675 *
3676 * @param cls argument given together with the function
3677 * pointer when the handler was registered with MHD
3678 * @param connection handle to connection which is being processed
3679 * @param url the requested url
3680 * @param method the HTTP method used ("GET", "PUT", etc.)
3681 * @param version the HTTP version string (i.e. "HTTP/1.1")
3682 * @param upload_data the data being uploaded (excluding HEADERS,
3683 * for a POST that fits into memory and that is encoded
3684 * with a supported encoding, the POST data will NOT be
3685 * given in upload_data and is instead available as
3686 * part of MHD_get_connection_values; very large POST
3687 * data *will* be made available incrementally in
3688 * upload_data)
3689 * @param upload_data_size set initially to the size of the
3690 * upload_data provided; the method must update this
3691 * value to the number of bytes NOT processed;
3692 * @param ptr pointer that the callback can set to some
3693 * address and that will be preserved by MHD for future
3694 * calls for this request; since the access handler may
3695 * be called many times (i.e., for a PUT/POST operation
3696 * with plenty of upload data) this allows the application
3697 * to easily associate some request-specific state.
3698 * If necessary, this state can be cleaned up in the
3699 * global "MHD_RequestCompleted" callback (which
3700 * can be set with the MHD_OPTION_NOTIFY_COMPLETED).
3701 * Initially, <tt>*con_cls</tt> will be NULL.
3702 * @return MHS_YES if the connection was handled successfully,
3703 * MHS_NO if the socket must be closed due to a serios
3704 * error while handling the request
3705 */
3706 static int
3707 create_response (void *cls,
3708 struct MHD_Connection *connection,
3709 const char *url,
3710 const char *method,
3711 const char *version,
3712 const char *upload_data,
3713 size_t *upload_data_size,
3714 void **ptr)
3715 {
3716 struct MHD_Response *response;
3717 struct Request *request;
3718 struct Session *session;
3719 int ret;
3720 unsigned int i;
3721
3722 request = *ptr;
3723 if (NULL == request)
3724 {
3725 request = calloc (1, sizeof (struct Request));
3726 if (NULL == request)
3727 {
3728 fprintf (stderr, "calloc error: %s\n", strerror (errno));
3729 return MHD_NO;
3730 }
3731 *ptr = request;
3732 if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
3733 {
3734 request->pp = MHD_create_post_processor (connection, 1024,
3735 &post_iterator, request);
3736 if (NULL == request->pp)
3737 {
3738 fprintf (stderr, "Failed to setup post processor for `%s'\n",
3739 url);
3740 return MHD_NO; /* internal error */
3741 }
3742 }
3743 return MHD_YES;
3744 }
3745 if (NULL == request->session)
3746 {
3747 request->session = get_session (connection);
3748 if (NULL == request->session)
3749 {
3750 fprintf (stderr, "Failed to setup session for `%s'\n",
3751 url);
3752 return MHD_NO; /* internal error */
3753 }
3754 }
3755 session = request->session;
3756 session->start = time (NULL);
3757 if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
3758 {
3759 /* evaluate POST data */
3760 MHD_post_process (request->pp,
3761 upload_data,
3762 *upload_data_size);
3763 if (0 != *upload_data_size)
3764 {
3765 *upload_data_size = 0;
3766 return MHD_YES;
3767 }
3768 /* done with POST data, serve response */
3769 MHD_destroy_post_processor (request->pp);
3770 request->pp = NULL;
3771 method = MHD_HTTP_METHOD_GET; /* fake 'GET' */
3772 if (NULL != request->post_url)
3773 url = request->post_url;
3774 }
3775
3776 if ( (0 == strcmp (method, MHD_HTTP_METHOD_GET)) ||
3777 (0 == strcmp (method, MHD_HTTP_METHOD_HEAD)) )
3778 {
3779 /* find out which page to serve */
3780 i=0;
3781 while ( (pages[i].url != NULL) &&
3782 (0 != strcmp (pages[i].url, url)) )
3783 i++;
3784 ret = pages[i].handler (pages[i].handler_cls,
3785 pages[i].mime,
3786 session, connection);
3787 if (ret != MHD_YES)
3788 fprintf (stderr, "Failed to create page for `%s'\n",
3789 url);
3790 return ret;
3791 }
3792 /* unsupported HTTP method */
3793 response = MHD_create_response_from_buffer (strlen (METHOD_ERROR),
3794 (void *) METHOD_ERROR,
3795 MHD_RESPMEM_PERSISTENT);
3796 ret = MHD_queue_response (connection,
3797 MHD_HTTP_METHOD_NOT_ACCEPTABLE,
3798 response);
3799 MHD_destroy_response (response);
3800 return ret;
3801 }
3802
3803
3804 /**
3805 * Callback called upon completion of a request.
3806 * Decrements session reference counter.
3807 *
3808 * @param cls not used
3809 * @param connection connection that completed
3810 * @param con_cls session handle
3811 * @param toe status code
3812 */
3813 static void
3814 request_completed_callback (void *cls,
3815 struct MHD_Connection *connection,
3816 void **con_cls,
3817 enum MHD_RequestTerminationCode toe)
3818 {
3819 struct Request *request = *con_cls;
3820
3821 if (NULL == request)
3822 return;
3823 if (NULL != request->session)
3824 request->session->rc--;
3825 if (NULL != request->pp)
3826 MHD_destroy_post_processor (request->pp);
3827 free (request);
3828 }
3829
3830
3831 /**
3832 * Clean up handles of sessions that have been idle for
3833 * too long.
3834 */
3835 static void
3836 expire_sessions ()
3837 {
3838 struct Session *pos;
3839 struct Session *prev;
3840 struct Session *next;
3841 time_t now;
3842
3843 now = time (NULL);
3844 prev = NULL;
3845 pos = sessions;
3846 while (NULL != pos)
3847 {
3848 next = pos->next;
3849 if (now - pos->start > 60 * 60)
3850 {
3851 /* expire sessions after 1h */
3852 if (NULL == prev)
3853 sessions = pos->next;
3854 else
3855 prev->next = next;
3856 free (pos);
3857 }
3858 else
3859 prev = pos;
3860 pos = next;
3861 }
3862 }
3863
3864
3865 /**
3866 * Call with the port number as the only argument.
3867 * Never terminates (other than by signals, such as CTRL-C).
3868 */
3869 int
3870 main (int argc, char *const *argv)
3871 {
3872 struct MHD_Daemon *d;
3873 struct timeval tv;
3874 struct timeval *tvp;
3875 fd_set rs;
3876 fd_set ws;
3877 fd_set es;
3878 int max;
3879 MHD_UNSIGNED_LONG_LONG mhd_timeout;
3880
3881 if (argc != 2)
3882 {
3883 printf ("%s PORT\n", argv[0]);
3884 return 1;
3885 }
3886 /* initialize PRNG */
3887 srand ((unsigned int) time (NULL));
3888 d = MHD_start_daemon (MHD_USE_DEBUG,
3889 atoi (argv[1]),
3890 NULL, NULL,
3891 &create_response, NULL,
3892 MHD_OPTION_CONNECTION_TIMEOUT, (unsigned int) 15,
3893 MHD_OPTION_NOTIFY_COMPLETED, &request_completed_callback, NULL,
3894 MHD_OPTION_END);
3895 if (NULL == d)
3896 return 1;
3897 while (1)
3898 {
3899 expire_sessions ();
3900 max = 0;
3901 FD_ZERO (&rs);
3902 FD_ZERO (&ws);
3903 FD_ZERO (&es);
3904 if (MHD_YES != MHD_get_fdset (d, &rs, &ws, &es, &max))
3905 break; /* fatal internal error */
3906 if (MHD_get_timeout (d, &mhd_timeout) == MHD_YES)
3907 {
3908 tv.tv_sec = mhd_timeout / 1000;
3909 tv.tv_usec = (mhd_timeout - (tv.tv_sec * 1000)) * 1000;
3910 tvp = &tv;
3911 }
3912 else
3913 tvp = NULL;
3914 if (-1 == select (max + 1, &rs, &ws, &es, tvp))
3915 {
3916 if (EINTR != errno)
3917 fprintf (stderr,
3918 "Aborting due to error during select: %s\n",
3919 strerror (errno));
3920 break;
3921 }
3922 MHD_run (d);
3923 }
3924 MHD_stop_daemon (d);
3925 return 0;
3926 }
3927
3928
3929File: libmicrohttpd-tutorial.info, Node: tlsauthentication.c, Prev: sessions.c, Up: Example programs
3930
3931C.8 tlsauthentication.c
3932=======================
3933
3934 /* Feel free to use this example code in any way
3935 you see fit (Public Domain) */
3936
3937 #include <sys/types.h>
3938 #ifndef _WIN32
3939 #include <sys/select.h>
3940 #include <sys/socket.h>
3941 #else
3942 #include <winsock2.h>
3943 #endif
3944 #include <microhttpd.h>
3945 #include <string.h>
3946 #include <stdio.h>
3947 #include <stdlib.h>
3948
3949 #define PORT 8888
3950
3951 #define REALM "\"Maintenance\""
3952 #define USER "a legitimate user"
3953 #define PASSWORD "and his password"
3954
3955 #define SERVERKEYFILE "server.key"
3956 #define SERVERCERTFILE "server.pem"
3957
3958
3959 static char *
3960 string_to_base64 (const char *message)
3961 {
3962 const char *lookup =
3963 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
3964 unsigned long l;
3965 int i;
3966 char *tmp;
3967 size_t length = strlen (message);
3968
3969 tmp = malloc (length * 2);
3970 if (NULL == tmp)
3971 return tmp;
3972
3973 tmp[0] = 0;
3974
3975 for (i = 0; i < length; i += 3)
3976 {
3977 l = (((unsigned long) message[i]) << 16)
3978 | (((i + 1) < length) ? (((unsigned long) message[i + 1]) << 8) : 0)
3979 | (((i + 2) < length) ? ((unsigned long) message[i + 2]) : 0);
3980
3981
3982 strncat (tmp, &lookup[(l >> 18) & 0x3F], 1);
3983 strncat (tmp, &lookup[(l >> 12) & 0x3F], 1);
3984
3985 if (i + 1 < length)
3986 strncat (tmp, &lookup[(l >> 6) & 0x3F], 1);
3987 if (i + 2 < length)
3988 strncat (tmp, &lookup[l & 0x3F], 1);
3989 }
3990
3991 if (length % 3)
3992 strncat (tmp, "===", 3 - length % 3);
3993
3994 return tmp;
3995 }
3996
3997
3998 static long
3999 get_file_size (const char *filename)
4000 {
4001 FILE *fp;
4002
4003 fp = fopen (filename, "rb");
4004 if (fp)
4005 {
4006 long size;
4007
4008 if ((0 != fseek (fp, 0, SEEK_END)) || (-1 == (size = ftell (fp))))
4009 size = 0;
4010
4011 fclose (fp);
4012
4013 return size;
4014 }
4015 else
4016 return 0;
4017 }
4018
4019 static char *
4020 load_file (const char *filename)
4021 {
4022 FILE *fp;
4023 char *buffer;
4024 long size;
4025
4026 size = get_file_size (filename);
4027 if (size == 0)
4028 return NULL;
4029
4030 fp = fopen (filename, "rb");
4031 if (!fp)
4032 return NULL;
4033
4034 buffer = malloc (size);
4035 if (!buffer)
4036 {
4037 fclose (fp);
4038 return NULL;
4039 }
4040
4041 if (size != fread (buffer, 1, size, fp))
4042 {
4043 free (buffer);
4044 buffer = NULL;
4045 }
4046
4047 fclose (fp);
4048 return buffer;
4049 }
4050
4051 static int
4052 ask_for_authentication (struct MHD_Connection *connection, const char *realm)
4053 {
4054 int ret;
4055 struct MHD_Response *response;
4056 char *headervalue;
4057 const char *strbase = "Basic realm=";
4058
4059 response = MHD_create_response_from_buffer (0, NULL,
4060 MHD_RESPMEM_PERSISTENT);
4061 if (!response)
4062 return MHD_NO;
4063
4064 headervalue = malloc (strlen (strbase) + strlen (realm) + 1);
4065 if (!headervalue)
4066 return MHD_NO;
4067
4068 strcpy (headervalue, strbase);
4069 strcat (headervalue, realm);
4070
4071 ret = MHD_add_response_header (response, "WWW-Authenticate", headervalue);
4072 free (headervalue);
4073 if (!ret)
4074 {
4075 MHD_destroy_response (response);
4076 return MHD_NO;
4077 }
4078
4079 ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response);
4080
4081 MHD_destroy_response (response);
4082
4083 return ret;
4084 }
4085
4086 static int
4087 is_authenticated (struct MHD_Connection *connection,
4088 const char *username, const char *password)
4089 {
4090 const char *headervalue;
4091 char *expected_b64, *expected;
4092 const char *strbase = "Basic ";
4093 int authenticated;
4094
4095 headervalue =
4096 MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
4097 "Authorization");
4098 if (NULL == headervalue)
4099 return 0;
4100 if (0 != strncmp (headervalue, strbase, strlen (strbase)))
4101 return 0;
4102
4103 expected = malloc (strlen (username) + 1 + strlen (password) + 1);
4104 if (NULL == expected)
4105 return 0;
4106
4107 strcpy (expected, username);
4108 strcat (expected, ":");
4109 strcat (expected, password);
4110
4111 expected_b64 = string_to_base64 (expected);
4112 free (expected);
4113 if (NULL == expected_b64)
4114 return 0;
4115
4116 authenticated =
4117 (strcmp (headervalue + strlen (strbase), expected_b64) == 0);
4118
4119 free (expected_b64);
4120
4121 return authenticated;
4122 }
4123
4124
4125 static int
4126 secret_page (struct MHD_Connection *connection)
4127 {
4128 int ret;
4129 struct MHD_Response *response;
4130 const char *page = "<html><body>A secret.</body></html>";
4131
4132 response =
4133 MHD_create_response_from_buffer (strlen (page), (void *) page,
4134 MHD_RESPMEM_PERSISTENT);
4135 if (!response)
4136 return MHD_NO;
4137
4138 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
4139 MHD_destroy_response (response);
4140
4141 return ret;
4142 }
4143
4144
4145 static int
4146 answer_to_connection (void *cls, struct MHD_Connection *connection,
4147 const char *url, const char *method,
4148 const char *version, const char *upload_data,
4149 size_t *upload_data_size, void **con_cls)
4150 {
4151 if (0 != strcmp (method, "GET"))
4152 return MHD_NO;
4153 if (NULL == *con_cls)
4154 {
4155 *con_cls = connection;
4156 return MHD_YES;
4157 }
4158
4159 if (!is_authenticated (connection, USER, PASSWORD))
4160 return ask_for_authentication (connection, REALM);
4161
4162 return secret_page (connection);
4163 }
4164
4165
4166 int
4167 main ()
4168 {
4169 struct MHD_Daemon *daemon;
4170 char *key_pem;
4171 char *cert_pem;
4172
4173 key_pem = load_file (SERVERKEYFILE);
4174 cert_pem = load_file (SERVERCERTFILE);
4175
4176 if ((key_pem == NULL) || (cert_pem == NULL))
4177 {
4178 printf ("The key/certificate files could not be read.\n");
4179 return 1;
4180 }
4181
4182 daemon =
4183 MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL, PORT, NULL,
4184 NULL, &answer_to_connection, NULL,
4185 MHD_OPTION_HTTPS_MEM_KEY, key_pem,
4186 MHD_OPTION_HTTPS_MEM_CERT, cert_pem, MHD_OPTION_END);
4187 if (NULL == daemon)
4188 {
4189 printf ("%s\n", cert_pem);
4190
4191 free (key_pem);
4192 free (cert_pem);
4193
4194 return 1;
4195 }
4196
4197 (void) getchar ();
4198
4199 MHD_stop_daemon (daemon);
4200 free (key_pem);
4201 free (cert_pem);
4202
4203 return 0;
4204 }
4205
4206
4207
4208Tag Table:
4209Node: Top866
4210Node: Introduction1917
4211Node: Hello browser example3223
4212Node: Exploring requests14247
4213Node: Response headers19643
4214Node: Supporting basic authentication27522
4215Node: Processing POST data34913
4216Node: Improved processing of POST data43534
4217Node: Session management54177
4218Node: Adding a layer of security57072
4219Node: Bibliography71602
4220Node: License text72797
4221Node: Example programs97972
4222Node: hellobrowser.c98285
4223Node: logging.c99828
4224Node: responseheaders.c101411
4225Node: basicauthentication.c104035
4226Node: simplepost.c106574
4227Node: largepost.c112254
4228Node: sessions.c119619
4229Node: tlsauthentication.c141964
4230
4231End Tag Table