1This 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, ¬_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 4232