| /* Feel free to use this example code in any way |
| you see fit (Public Domain) */ |
| |
| #include <sys/types.h> |
| #ifndef _WIN32 |
| #include <sys/select.h> |
| #include <sys/socket.h> |
| #else |
| #include <winsock2.h> |
| #endif |
| #include <microhttpd.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #define PORT 8888 |
| |
| #define REALM "Maintenance" |
| #define USER "a legitimate user" |
| #define PASSWORD "and his password" |
| |
| #define SERVERKEYFILE "server.key" |
| #define SERVERCERTFILE "server.pem" |
| |
| |
| static size_t |
| get_file_size (const char *filename) |
| { |
| FILE *fp; |
| |
| fp = fopen (filename, "rb"); |
| if (fp) |
| { |
| long size; |
| |
| if ((0 != fseek (fp, 0, SEEK_END)) || (-1 == (size = ftell (fp)))) |
| size = 0; |
| |
| fclose (fp); |
| |
| return (size_t) size; |
| } |
| else |
| return 0; |
| } |
| |
| |
| static char * |
| load_file (const char *filename) |
| { |
| FILE *fp; |
| char *buffer; |
| size_t size; |
| |
| size = get_file_size (filename); |
| if (0 == size) |
| return NULL; |
| |
| fp = fopen (filename, "rb"); |
| if (! fp) |
| return NULL; |
| |
| buffer = malloc (size + 1); |
| if (! buffer) |
| { |
| fclose (fp); |
| return NULL; |
| } |
| buffer[size] = '\0'; |
| |
| if (size != fread (buffer, 1, size, fp)) |
| { |
| free (buffer); |
| buffer = NULL; |
| } |
| |
| fclose (fp); |
| return buffer; |
| } |
| |
| |
| static enum MHD_Result |
| ask_for_authentication (struct MHD_Connection *connection, const char *realm) |
| { |
| enum MHD_Result ret; |
| struct MHD_Response *response; |
| |
| response = MHD_create_response_empty (MHD_RF_NONE); |
| if (! response) |
| return MHD_NO; |
| |
| ret = MHD_queue_basic_auth_fail_response3 (connection, |
| realm, |
| MHD_YES, |
| response); |
| MHD_destroy_response (response); |
| return ret; |
| } |
| |
| |
| static int |
| is_authenticated (struct MHD_Connection *connection, |
| const char *username, |
| const char *password) |
| { |
| struct MHD_BasicAuthInfo *auth_info; |
| int authenticated; |
| |
| auth_info = MHD_basic_auth_get_username_password3 (connection); |
| if (NULL == auth_info) |
| return 0; |
| authenticated = |
| ( (strlen (username) == auth_info->username_len) && |
| (0 == memcmp (auth_info->username, username, auth_info->username_len)) && |
| /* The next check against NULL is optional, |
| * if 'password' is NULL then 'password_len' is always zero. */ |
| (NULL != auth_info->password) && |
| (strlen (password) == auth_info->password_len) && |
| (0 == memcmp (auth_info->password, password, auth_info->password_len)) ); |
| |
| MHD_free (auth_info); |
| |
| return authenticated; |
| } |
| |
| |
| static enum MHD_Result |
| secret_page (struct MHD_Connection *connection) |
| { |
| enum MHD_Result ret; |
| struct MHD_Response *response; |
| const char *page = "<html><body>A secret.</body></html>"; |
| |
| response = MHD_create_response_from_buffer_static (strlen (page), page); |
| if (! response) |
| return MHD_NO; |
| |
| ret = MHD_queue_response (connection, MHD_HTTP_OK, response); |
| MHD_destroy_response (response); |
| |
| return ret; |
| } |
| |
| |
| static enum MHD_Result |
| answer_to_connection (void *cls, struct MHD_Connection *connection, |
| const char *url, const char *method, |
| const char *version, const char *upload_data, |
| size_t *upload_data_size, void **req_cls) |
| { |
| (void) cls; /* Unused. Silent compiler warning. */ |
| (void) url; /* Unused. Silent compiler warning. */ |
| (void) version; /* Unused. Silent compiler warning. */ |
| (void) upload_data; /* Unused. Silent compiler warning. */ |
| (void) upload_data_size; /* Unused. Silent compiler warning. */ |
| |
| if (0 != strcmp (method, "GET")) |
| return MHD_NO; |
| if (NULL == *req_cls) |
| { |
| *req_cls = connection; |
| return MHD_YES; |
| } |
| |
| if (! is_authenticated (connection, USER, PASSWORD)) |
| return ask_for_authentication (connection, REALM); |
| |
| return secret_page (connection); |
| } |
| |
| |
| int |
| main (void) |
| { |
| struct MHD_Daemon *daemon; |
| char *key_pem; |
| char *cert_pem; |
| |
| key_pem = load_file (SERVERKEYFILE); |
| cert_pem = load_file (SERVERCERTFILE); |
| |
| if ((key_pem == NULL) || (cert_pem == NULL)) |
| { |
| printf ("The key/certificate files could not be read.\n"); |
| if (NULL != key_pem) |
| free (key_pem); |
| if (NULL != cert_pem) |
| free (cert_pem); |
| return 1; |
| } |
| |
| daemon = |
| MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS, PORT, NULL, |
| NULL, &answer_to_connection, NULL, |
| MHD_OPTION_HTTPS_MEM_KEY, key_pem, |
| MHD_OPTION_HTTPS_MEM_CERT, cert_pem, MHD_OPTION_END); |
| if (NULL == daemon) |
| { |
| printf ("%s\n", cert_pem); |
| |
| free (key_pem); |
| free (cert_pem); |
| |
| return 1; |
| } |
| |
| (void) getchar (); |
| |
| MHD_stop_daemon (daemon); |
| free (key_pem); |
| free (cert_pem); |
| |
| return 0; |
| } |