minimal_auth_basic.c (5115B)
1 /* SPDX-License-Identifier: 0BSD */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2024 Evgeny Grin (Karlson2k) 5 6 Permission to use, copy, modify, and/or distribute this software for 7 any purpose with or without fee is hereby granted. 8 9 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES 11 OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE 12 FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY 13 DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 14 AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 /** 18 * @file minimal_auth_basic.c 19 * @brief Minimal example for Basic Authentication 20 * @author Karlson2k (Evgeny Grin) 21 */ 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <microhttpd2.h> 27 28 static MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_NONNULL_ (3) 29 const struct MHD_Action * 30 req_cb (void *cls, 31 struct MHD_Request *MHD_RESTRICT request, 32 const struct MHD_String *MHD_RESTRICT path, 33 enum MHD_HTTP_Method method, 34 uint_fast64_t upload_size) 35 { 36 static const char secret_page[] = "Welcome to the cave of treasures!\n"; 37 static const char auth_required_page[] = 38 "You need to know the secret to get in.\n"; 39 static const char msg_forbidden_page[] = 40 "You are not allowed to enter. Go away!\n"; 41 static const char msg_bad_header_page[] = 42 "The Authorization header data is invalid\n"; 43 static const char allowed_username[] = "alibaba"; 44 static const char allowed_password[] = "open sesam"; 45 static const size_t allowed_username_len = 46 (sizeof(allowed_username) / sizeof(char) - 1); 47 static const size_t allowed_password_len = 48 (sizeof(allowed_password) / sizeof(char) - 1); 49 union MHD_RequestInfoDynamicData req_data; 50 const struct MHD_AuthBasicCreds *creds; /* a shortcut */ 51 enum MHD_StatusCode res; 52 53 (void) cls; 54 (void) path; 55 (void) method; 56 (void) upload_size; /* Unused */ 57 58 res = MHD_request_get_info_dynamic (request, 59 MHD_REQUEST_INFO_DYNAMIC_AUTH_BASIC_CREDS, 60 &req_data); 61 if (MHD_SC_AUTH_ABSENT == res) 62 return MHD_action_basic_auth_challenge_a ( 63 request, 64 "The secret cave", 65 MHD_YES, 66 MHD_response_from_buffer_static ( 67 MHD_HTTP_STATUS_UNAUTHORIZED, 68 sizeof(auth_required_page) / sizeof(char) - 1, 69 auth_required_page)); 70 71 if (MHD_SC_REQ_AUTH_DATA_BROKEN == res) 72 return MHD_action_from_response ( 73 request, 74 MHD_response_from_buffer_static ( 75 MHD_HTTP_STATUS_BAD_REQUEST, 76 sizeof(msg_bad_header_page) / sizeof(char) - 1, 77 msg_bad_header_page)); 78 79 if (MHD_SC_OK != res) 80 return MHD_action_abort_request (request); 81 82 /* Assign result to short-named variable for convenience */ 83 creds = req_data.v_auth_basic_creds; 84 if ((creds->username.len == allowed_username_len) && 85 (memcmp (allowed_username, 86 creds->username.cstr, 87 creds->username.len) == 0) && 88 (creds->password.len == allowed_password_len) && 89 (memcmp (allowed_password, 90 creds->password.cstr, 91 creds->password.len) == 0)) 92 { 93 /* The client gave the correct username and password */ 94 return MHD_action_from_response ( 95 request, 96 MHD_response_from_buffer_static ( 97 MHD_HTTP_STATUS_OK, 98 sizeof(secret_page) / sizeof(char) - 1, 99 secret_page)); 100 } 101 /* Wrong username or/and password */ 102 103 return MHD_action_from_response ( 104 request, 105 MHD_response_from_buffer_static ( 106 MHD_HTTP_STATUS_FORBIDDEN, 107 sizeof(msg_forbidden_page) / sizeof(char) - 1, 108 msg_forbidden_page)); 109 } 110 111 112 int 113 main (int argc, 114 char *const *argv) 115 { 116 struct MHD_Daemon *d; 117 int port; 118 119 if (argc != 2) 120 { 121 fprintf (stderr, 122 "Usage:\n%s PORT\n", 123 argv[0]); 124 return 1; 125 } 126 port = atoi (argv[1]); 127 if ((1 > port) || (65535 < port)) 128 { 129 fprintf (stderr, 130 "The PORT must be a numeric value between 1 and 65535.\n"); 131 return 2; 132 } 133 d = MHD_daemon_create (&req_cb, 134 NULL); 135 if (NULL == d) 136 { 137 fprintf (stderr, 138 "Failed to create MHD daemon.\n"); 139 return 3; 140 } 141 if (MHD_SC_OK != 142 MHD_DAEMON_SET_OPTIONS ( 143 d, 144 MHD_D_OPTION_WM_WORKER_THREADS (1), 145 MHD_D_OPTION_BIND_PORT (MHD_AF_AUTO, 146 (uint_least16_t) port))) 147 { 148 fprintf (stderr, 149 "Failed to set MHD daemon run parameters.\n"); 150 } 151 else 152 { 153 if (MHD_SC_OK != 154 MHD_daemon_start (d)) 155 { 156 fprintf (stderr, 157 "Failed to start MHD daemon.\n"); 158 } 159 else 160 { 161 printf ("The MHD daemon is listening on port %d\n" 162 "Press ENTER to stop.\n", port); 163 (void) fgetc (stdin); 164 } 165 } 166 printf ("Stopping... "); 167 fflush (stdout); 168 MHD_daemon_destroy (d); 169 printf ("OK\n"); 170 return 0; 171 }