/* Feel free to use this example code in any way you see fit (Public Domain) */ #include #ifndef _WIN32 #include #include #else #include #endif #include #include #include #include #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 = "A secret."; 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; }