libmicrohttpd2

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

auth_basic.c (5539B)


      1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */
      2 /*
      3   This file is part of GNU libmicrohttpd.
      4   Copyright (C) 2024 Evgeny Grin (Karlson2k)
      5 
      6   GNU libmicrohttpd is free software; you can redistribute it and/or
      7   modify it under the terms of the GNU Lesser General Public
      8   License as published by the Free Software Foundation; either
      9   version 2.1 of the License, or (at your option) any later version.
     10 
     11   GNU libmicrohttpd is distributed in the hope that it will be useful,
     12   but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14   Lesser General Public License for more details.
     15 
     16   Alternatively, you can redistribute GNU libmicrohttpd and/or
     17   modify it under the terms of the GNU General Public License as
     18   published by the Free Software Foundation; either version 2 of
     19   the License, or (at your option) any later version, together
     20   with the eCos exception, as follows:
     21 
     22     As a special exception, if other files instantiate templates or
     23     use macros or inline functions from this file, or you compile this
     24     file and link it with other works to produce a work based on this
     25     file, this file does not by itself cause the resulting work to be
     26     covered by the GNU General Public License. However the source code
     27     for this file must still be made available in accordance with
     28     section (3) of the GNU General Public License v2.
     29 
     30     This exception does not invalidate any other reasons why a work
     31     based on this file might be covered by the GNU General Public
     32     License.
     33 
     34   You should have received copies of the GNU Lesser General Public
     35   License and the GNU General Public License along with this library;
     36   if not, see <https://www.gnu.org/licenses/>.
     37 */
     38 
     39 /**
     40  * @file src/mhd2/auth_basic.c
     41  * @brief  The implementation of the Basic Authorization header parser
     42  * @author Karlson2k (Evgeny Grin)
     43  */
     44 
     45 #include "mhd_sys_options.h"
     46 
     47 #include "sys_bool_type.h"
     48 #include "sys_base_types.h"
     49 
     50 #include <string.h>
     51 
     52 #include "mhd_cntnr_ptr.h"
     53 
     54 #include "mhd_assert.h"
     55 
     56 #include "mhd_str_types.h"
     57 #include "mhd_connection.h"
     58 
     59 #include "mhd_str.h"
     60 #include "stream_funcs.h"
     61 #include "request_auth_get.h"
     62 
     63 #include "auth_basic.h"
     64 
     65 static MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
     66 enum MHD_StatusCode
     67 find_and_parse_auth_basic (struct MHD_Request *restrict req)
     68 {
     69   struct MHD_String token68;
     70   size_t alloc_size;
     71   size_t dec_size;
     72   char *dec_buf;
     73   char *colon_ptr;
     74 
     75   mhd_assert (NULL == req->auth.basic.intr.username.cstr);
     76 
     77   if (! mhd_request_get_auth_header_value (req,
     78                                            mhd_AUTH_HDR_BASIC,
     79                                            &token68))
     80     return MHD_SC_AUTH_ABSENT;
     81 
     82   mhd_assert (NULL != token68.cstr);
     83 
     84   if (0 == token68.len)
     85   {
     86     /* Zero-length token68 */
     87     req->auth.basic.intr.username.cstr = token68.cstr;
     88     mhd_assert (0 == req->auth.basic.intr.username.len);
     89     mhd_assert (NULL == req->auth.basic.intr.password.cstr);
     90     mhd_assert (0 == req->auth.basic.intr.password.len);
     91     return MHD_SC_OK;
     92   }
     93 
     94   alloc_size = mhd_base64_max_dec_size (token68.len) + 1;
     95   dec_buf = (char *)
     96             mhd_stream_alloc_memory (mhd_CNTNR_PTR (req, \
     97                                                     struct MHD_Connection, \
     98                                                     rq),
     99                                      alloc_size);
    100   if (NULL == dec_buf)
    101     return MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA;
    102 
    103   /* The 'dec_buf' remains allocated until start of sending reply or until
    104      end of the request processing. */
    105 
    106   dec_size = mhd_base64_to_bin_n (token68.cstr,
    107                                   token68.len,
    108                                   dec_buf,
    109                                   alloc_size);
    110   if (0 == dec_size)
    111     return MHD_SC_REQ_AUTH_DATA_BROKEN;
    112 
    113   dec_buf[dec_size] = 0; /* Zero-terminate the result */
    114   req->auth.basic.intr.username.cstr = dec_buf;
    115   colon_ptr = (char *) memchr (dec_buf,
    116                                ':',
    117                                dec_size);
    118   if (NULL == colon_ptr)
    119   {
    120     /* No password provided. Only username. */
    121     req->auth.basic.intr.username.len = dec_size;
    122     mhd_assert (NULL == req->auth.basic.intr.password.cstr);
    123     mhd_assert (0 == req->auth.basic.intr.password.len);
    124     return MHD_SC_OK;
    125   }
    126   *colon_ptr = 0; /* Zero-terminate the username */
    127   req->auth.basic.intr.username.len = (size_t) (colon_ptr - dec_buf);
    128   req->auth.basic.intr.password.cstr = colon_ptr + 1;
    129   mhd_assert ((req->auth.basic.intr.username.len + 1) <= dec_size);
    130   req->auth.basic.intr.password.len =
    131     dec_size - (req->auth.basic.intr.username.len + 1);
    132   return MHD_SC_OK;
    133 }
    134 
    135 
    136 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
    137 MHD_FN_PAR_OUT_ (2) enum MHD_StatusCode
    138 mhd_request_get_auth_basic_creds (
    139   struct MHD_Request *restrict req,
    140   const struct MHD_AuthBasicCreds **restrict v_auth_basic_creds)
    141 {
    142   enum MHD_StatusCode res;
    143   mhd_assert (mhd_HTTP_STAGE_HEADERS_PROCESSED <=
    144               mhd_CNTNR_CPTR (req, struct MHD_Connection, rq)->stage);
    145   mhd_assert (mhd_HTTP_STAGE_REQ_RECV_FINISHED >=
    146               mhd_CNTNR_CPTR (req, struct MHD_Connection, rq)->stage);
    147 
    148   if (NULL != req->auth.basic.intr.username.cstr)
    149     res = MHD_SC_OK;
    150   else
    151     res = find_and_parse_auth_basic (req);
    152 
    153   if (MHD_SC_OK != res)
    154     return res; /* Failure exit point */
    155 
    156   *v_auth_basic_creds = &(req->auth.basic.extr);
    157 
    158   return MHD_SC_OK; /* Success exit point */
    159 }