libmicrohttpd2

HTTP server C library (MHD 2.x, alpha)
Log | Files | Refs | README | LICENSE

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 }