tlsauthentication.c (4815B)
1 /* Feel free to use this example code in any way 2 you see fit (Public Domain) */ 3 4 #include <sys/types.h> 5 #ifndef _WIN32 6 #include <sys/select.h> 7 #include <sys/socket.h> 8 #else 9 #include <winsock2.h> 10 #endif 11 #include <microhttpd.h> 12 #include <string.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 16 #define PORT 8888 17 18 #define REALM "Maintenance" 19 #define USER "a legitimate user" 20 #define PASSWORD "and his password" 21 22 #define SERVERKEYFILE "server.key" 23 #define SERVERCERTFILE "server.pem" 24 25 26 static size_t 27 get_file_size (const char *filename) 28 { 29 FILE *fp; 30 31 fp = fopen (filename, "rb"); 32 if (fp) 33 { 34 long size; 35 36 if ((0 != fseek (fp, 0, SEEK_END)) || (-1 == (size = ftell (fp)))) 37 size = 0; 38 39 fclose (fp); 40 41 return (size_t) size; 42 } 43 else 44 return 0; 45 } 46 47 48 static char * 49 load_file (const char *filename) 50 { 51 FILE *fp; 52 char *buffer; 53 size_t size; 54 55 size = get_file_size (filename); 56 if (0 == size) 57 return NULL; 58 59 fp = fopen (filename, "rb"); 60 if (! fp) 61 return NULL; 62 63 buffer = malloc (size + 1); 64 if (! buffer) 65 { 66 fclose (fp); 67 return NULL; 68 } 69 buffer[size] = '\0'; 70 71 if (size != fread (buffer, 1, size, fp)) 72 { 73 free (buffer); 74 buffer = NULL; 75 } 76 77 fclose (fp); 78 return buffer; 79 } 80 81 82 static enum MHD_Result 83 ask_for_authentication (struct MHD_Connection *connection, const char *realm) 84 { 85 enum MHD_Result ret; 86 struct MHD_Response *response; 87 88 response = MHD_create_response_empty (MHD_RF_NONE); 89 if (! response) 90 return MHD_NO; 91 92 ret = MHD_queue_basic_auth_required_response3 (connection, 93 realm, 94 MHD_YES, 95 response); 96 MHD_destroy_response (response); 97 return ret; 98 } 99 100 101 static int 102 is_authenticated (struct MHD_Connection *connection, 103 const char *username, 104 const char *password) 105 { 106 struct MHD_BasicAuthInfo *auth_info; 107 int authenticated; 108 109 auth_info = MHD_basic_auth_get_username_password3 (connection); 110 if (NULL == auth_info) 111 return 0; 112 authenticated = 113 ( (strlen (username) == auth_info->username_len) && 114 (0 == memcmp (auth_info->username, username, auth_info->username_len)) && 115 /* The next check against NULL is optional, 116 * if 'password' is NULL then 'password_len' is always zero. */ 117 (NULL != auth_info->password) && 118 (strlen (password) == auth_info->password_len) && 119 (0 == memcmp (auth_info->password, password, auth_info->password_len)) ); 120 121 MHD_free (auth_info); 122 123 return authenticated; 124 } 125 126 127 static enum MHD_Result 128 secret_page (struct MHD_Connection *connection) 129 { 130 enum MHD_Result ret; 131 struct MHD_Response *response; 132 const char *page = "<html><body>A secret.</body></html>"; 133 134 response = MHD_create_response_from_buffer_static (strlen (page), page); 135 if (! response) 136 return MHD_NO; 137 138 ret = MHD_queue_response (connection, MHD_HTTP_OK, response); 139 MHD_destroy_response (response); 140 141 return ret; 142 } 143 144 145 static enum MHD_Result 146 answer_to_connection (void *cls, struct MHD_Connection *connection, 147 const char *url, const char *method, 148 const char *version, const char *upload_data, 149 size_t *upload_data_size, void **req_cls) 150 { 151 (void) cls; /* Unused. Silent compiler warning. */ 152 (void) url; /* Unused. Silent compiler warning. */ 153 (void) version; /* Unused. Silent compiler warning. */ 154 (void) upload_data; /* Unused. Silent compiler warning. */ 155 (void) upload_data_size; /* Unused. Silent compiler warning. */ 156 157 if (0 != strcmp (method, "GET")) 158 return MHD_NO; 159 if (NULL == *req_cls) 160 { 161 *req_cls = connection; 162 return MHD_YES; 163 } 164 165 if (! is_authenticated (connection, USER, PASSWORD)) 166 return ask_for_authentication (connection, REALM); 167 168 return secret_page (connection); 169 } 170 171 172 int 173 main (void) 174 { 175 struct MHD_Daemon *daemon; 176 char *key_pem; 177 char *cert_pem; 178 179 key_pem = load_file (SERVERKEYFILE); 180 cert_pem = load_file (SERVERCERTFILE); 181 182 if ((key_pem == NULL) || (cert_pem == NULL)) 183 { 184 printf ("The key/certificate files could not be read.\n"); 185 if (NULL != key_pem) 186 free (key_pem); 187 if (NULL != cert_pem) 188 free (cert_pem); 189 return 1; 190 } 191 192 daemon = 193 MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_TLS, PORT, NULL, 194 NULL, &answer_to_connection, NULL, 195 MHD_OPTION_HTTPS_MEM_KEY, key_pem, 196 MHD_OPTION_HTTPS_MEM_CERT, cert_pem, MHD_OPTION_END); 197 if (NULL == daemon) 198 { 199 printf ("%s\n", cert_pem); 200 201 free (key_pem); 202 free (cert_pem); 203 204 return 1; 205 } 206 207 (void) getchar (); 208 209 MHD_stop_daemon (daemon); 210 free (key_pem); 211 free (cert_pem); 212 213 return 0; 214 }