Files
libmicrohttpd/src/mhd2/auth_basic.c
T

140 lines
4.4 KiB
C

/*
This file is part of GNU libmicrohttpd
Copyright (C) 2024 Evgeny Grin (Karlson2k)
GNU libmicrohttpd is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
GNU libmicrohttpd is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file src/mhd2/auth_basic.c
* @brief The implementation of the Basic Authorization header parser
* @author Karlson2k (Evgeny Grin)
*/
#include "mhd_sys_options.h"
#include "sys_bool_type.h"
#include "sys_base_types.h"
#include <string.h>
#include "mhd_cntnr_ptr.h"
#include "mhd_assert.h"
#include "mhd_str_types.h"
#include "mhd_connection.h"
#include "mhd_str.h"
#include "stream_funcs.h"
#include "request_auth_get.h"
#include "auth_basic.h"
static MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
enum MHD_StatusCode
find_and_parse_auth_basic (struct MHD_Request *restrict req)
{
struct MHD_String token68;
size_t alloc_size;
size_t dec_size;
char *dec_buf;
char *colon_ptr;
mhd_assert (NULL == req->auth.basic.intr.username.cstr);
if (! mhd_request_get_auth_header_value (req,
mhd_AUTH_HDR_BASIC,
&token68))
return MHD_SC_AUTH_ABSENT;
mhd_assert (NULL != token68.cstr);
if (0 == token68.len)
{
/* Zero-length token68 */
req->auth.basic.intr.username.cstr = token68.cstr;
mhd_assert (0 == req->auth.basic.intr.username.len);
mhd_assert (NULL == req->auth.basic.intr.password.cstr);
mhd_assert (0 == req->auth.basic.intr.password.len);
return MHD_SC_OK;
}
alloc_size = mhd_base64_max_dec_size (token68.len) + 1;
dec_buf = (char *)
mhd_stream_alloc_memory (mhd_CNTNR_PTR (req, \
struct MHD_Connection, \
rq),
alloc_size);
if (NULL == dec_buf)
return MHD_SC_CONNECTION_POOL_NO_MEM_AUTH_DATA;
/* The 'dec_buf' remains allocated until start of sending reply or until
end of the request processing. */
dec_size = mhd_base64_to_bin_n (token68.cstr,
token68.len,
dec_buf,
alloc_size);
if (0 == dec_size)
return MHD_SC_REQ_AUTH_DATA_BROKEN;
dec_buf[dec_size] = 0; /* Zero-terminate the result */
req->auth.basic.intr.username.cstr = dec_buf;
colon_ptr = memchr (dec_buf, ':', dec_size);
if (NULL == colon_ptr)
{
/* No password provided. Only username. */
req->auth.basic.intr.username.len = dec_size;
mhd_assert (NULL == req->auth.basic.intr.password.cstr);
mhd_assert (0 == req->auth.basic.intr.password.len);
return MHD_SC_OK;
}
*colon_ptr = 0; /* Zero-terminate the username */
req->auth.basic.intr.username.len = (size_t) (colon_ptr - dec_buf);
req->auth.basic.intr.password.cstr = colon_ptr + 1;
mhd_assert ((req->auth.basic.intr.username.len + 1) <= dec_size);
req->auth.basic.intr.password.len =
dec_size - (req->auth.basic.intr.username.len + 1);
return MHD_SC_OK;
}
MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_
MHD_FN_PAR_OUT_ (2) enum MHD_StatusCode
mhd_request_get_auth_basic_creds (
struct MHD_Request *restrict req,
const struct MHD_AuthBasicCreds **restrict v_auth_basic_creds)
{
enum MHD_StatusCode res;
mhd_assert (mhd_HTTP_STAGE_HEADERS_PROCESSED <=
mhd_CNTNR_CPTR (req, struct MHD_Connection, rq)->stage);
mhd_assert (mhd_HTTP_STAGE_REQ_RECV_FINISHED >=
mhd_CNTNR_CPTR (req, struct MHD_Connection, rq)->stage);
if (NULL != req->auth.basic.intr.username.cstr)
res = MHD_SC_OK;
else
res = find_and_parse_auth_basic (req);
if (MHD_SC_OK != res)
return res; /* Failure exit point */
*v_auth_basic_creds = &(req->auth.basic.extr);
return MHD_SC_OK; /* Success exit point */
}