Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 45 additions & 2 deletions .github/workflows/verify-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,18 @@ jobs:
debug: nodebug
coverage: nocoverage
shell: bash
# Test build without digest auth support (issue #232)
- test-group: extra
os: ubuntu-latest
os-type: ubuntu
build-type: no-dauth
compiler-family: gcc
c-compiler: gcc
cc-compiler: g++
debug: nodebug
coverage: nocoverage
linking: dynamic
shell: bash
- test-group: extra
os: ubuntu-latest
os-type: ubuntu
Expand Down Expand Up @@ -467,7 +479,7 @@ jobs:
with:
path: libmicrohttpd-0.9.77
key: ${{ matrix.os }}-${{ matrix.c-compiler }}-libmicrohttpd-0.9.77-pre-built
if: ${{ matrix.os-type != 'windows' }}
if: ${{ matrix.os-type != 'windows' && matrix.build-type != 'no-dauth' }}

- name: Build libmicrohttpd dependency (if not cached)
run: |
Expand All @@ -476,12 +488,31 @@ jobs:
cd libmicrohttpd-0.9.77 ;
./configure --disable-examples ;
make ;
if: ${{ matrix.os-type != 'windows' && steps.cache-libmicrohttpd.outputs.cache-hit != 'true' }}
if: ${{ matrix.os-type != 'windows' && matrix.build-type != 'no-dauth' && steps.cache-libmicrohttpd.outputs.cache-hit != 'true' }}

- name: Build libmicrohttpd without digest auth (no-dauth test)
run: |
curl https://s3.amazonaws.com/libhttpserver/libmicrohttpd_releases/libmicrohttpd-0.9.77.tar.gz -o libmicrohttpd-0.9.77.tar.gz ;
tar -xzf libmicrohttpd-0.9.77.tar.gz ;
cd libmicrohttpd-0.9.77 ;
./configure --disable-examples --disable-dauth ;
make ;
if: ${{ matrix.build-type == 'no-dauth' }}

- name: Install libmicrohttpd
run: cd libmicrohttpd-0.9.77 ; sudo make install ;
if: ${{ matrix.os-type != 'windows' }}

- name: Verify digest auth is disabled (no-dauth test)
run: |
# Verify that MHD_queue_auth_fail_response is NOT present in libmicrohttpd
if nm /usr/local/lib/libmicrohttpd.so 2>/dev/null | grep -q MHD_queue_auth_fail_response; then
echo "ERROR: libmicrohttpd was built WITH digest auth support" ;
exit 1 ;
fi
echo "Verified: libmicrohttpd built without digest auth support" ;
if: ${{ matrix.build-type == 'no-dauth' }}

- name: Build and install libmicrohttpd (Windows)
if: ${{ matrix.os-type == 'windows' }}
run: |
Expand Down Expand Up @@ -532,6 +563,18 @@ jobs:
../configure --disable-fastopen;
fi

- name: Verify libhttpserver detected no digest auth (no-dauth test)
run: |
cd build ;
if grep -q "Digest Auth.*:.*no" config.log; then
echo "Verified: libhttpserver correctly detected digest auth is disabled" ;
else
echo "ERROR: libhttpserver did not detect that digest auth is disabled" ;
grep "Digest Auth" config.log || echo "Digest Auth line not found" ;
exit 1 ;
fi
if: ${{ matrix.build-type == 'no-dauth' }}

- name: Print config.log
shell: bash
run: |
Expand Down
13 changes: 13 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ fi
AM_CONDITIONAL([COND_CROSS_COMPILE],[test x"$cond_cross_compile" = x"yes"])
AC_SUBST(COND_CROSS_COMPILE)

# Check for digest auth support in libmicrohttpd
AC_CHECK_LIB([microhttpd], [MHD_queue_auth_fail_response],
[have_dauth="yes"],
[have_dauth="no"; AC_MSG_WARN("libmicrohttpd digest auth support not found. Digest auth will be disabled")])

AC_MSG_CHECKING([whether to build with TCP_FASTOPEN support])
AC_ARG_ENABLE([fastopen],
[AS_HELP_STRING([--enable-fastopen],
Expand Down Expand Up @@ -259,6 +264,13 @@ fi

AM_CONDITIONAL([HAVE_GNUTLS],[test x"$have_gnutls" = x"yes"])

if test x"$have_dauth" = x"yes"; then
AM_CXXFLAGS="$AM_CXXFLAGS -DHAVE_DAUTH"
AM_CFLAGS="$AM_CXXFLAGS -DHAVE_DAUTH"
fi

AM_CONDITIONAL([HAVE_DAUTH],[test x"$have_dauth" = x"yes"])

DX_HTML_FEATURE(ON)
DX_CHM_FEATURE(OFF)
DX_CHI_FEATURE(OFF)
Expand Down Expand Up @@ -309,6 +321,7 @@ AC_MSG_NOTICE([Configuration Summary:
License : LGPL only
Debug : ${debugit}
TLS Enabled : ${have_gnutls}
Digest Auth : ${have_dauth}
TCP_FASTOPEN : ${is_fastopen_supported}
Static : ${static}
Windows build : ${is_windows}
Expand Down
8 changes: 6 additions & 2 deletions examples/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
LDADD = $(top_builddir)/src/libhttpserver.la
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/src/httpserver/
METASOURCES = AUTO
noinst_PROGRAMS = hello_world service minimal_hello_world custom_error allowing_disallowing_methods handlers hello_with_get_arg setting_headers custom_access_log basic_authentication digest_authentication minimal_https minimal_file_response minimal_deferred url_registration minimal_ip_ban benchmark_select benchmark_threads benchmark_nodelay deferred_with_accumulator file_upload file_upload_with_callback
noinst_PROGRAMS = hello_world service minimal_hello_world custom_error allowing_disallowing_methods handlers hello_with_get_arg setting_headers custom_access_log basic_authentication minimal_https minimal_file_response minimal_deferred url_registration minimal_ip_ban benchmark_select benchmark_threads benchmark_nodelay deferred_with_accumulator file_upload file_upload_with_callback

hello_world_SOURCES = hello_world.cpp
service_SOURCES = service.cpp
Expand All @@ -31,7 +31,6 @@ hello_with_get_arg_SOURCES = hello_with_get_arg.cpp
setting_headers_SOURCES = setting_headers.cpp
custom_access_log_SOURCES = custom_access_log.cpp
basic_authentication_SOURCES = basic_authentication.cpp
digest_authentication_SOURCES = digest_authentication.cpp
minimal_https_SOURCES = minimal_https.cpp
minimal_file_response_SOURCES = minimal_file_response.cpp
minimal_deferred_SOURCES = minimal_deferred.cpp
Expand All @@ -49,3 +48,8 @@ LDADD += -lgnutls
noinst_PROGRAMS += minimal_https_psk
minimal_https_psk_SOURCES = minimal_https_psk.cpp
endif

if HAVE_DAUTH
noinst_PROGRAMS += digest_authentication
digest_authentication_SOURCES = digest_authentication.cpp
endif
4 changes: 4 additions & 0 deletions src/digest_auth_fail_response.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
USA
*/

#ifdef HAVE_DAUTH

#include "httpserver/digest_auth_fail_response.hpp"
#include <microhttpd.h>
#include <iosfwd>
Expand All @@ -32,3 +34,5 @@ int digest_auth_fail_response::enqueue_response(MHD_Connection* connection, MHD_
}

} // namespace httpserver

#endif // HAVE_DAUTH
4 changes: 4 additions & 0 deletions src/http_request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ void http_request::set_method(const std::string& method) {
this->method = string_utilities::to_upper_copy(method);
}

#ifdef HAVE_DAUTH
bool http_request::check_digest_auth(const std::string& realm, const std::string& password, int nonce_timeout, bool* reload_nonce) const {
std::string_view digested_user = get_digested_user();

Expand All @@ -57,6 +58,7 @@ bool http_request::check_digest_auth(const std::string& realm, const std::string
*reload_nonce = false;
return true;
}
#endif // HAVE_DAUTH

std::string_view http_request::get_connection_value(std::string_view key, enum MHD_ValueKind kind) const {
const char* header_c = MHD_lookup_connection_value(underlying_connection, kind, key.data());
Expand Down Expand Up @@ -257,6 +259,7 @@ std::string_view http_request::get_pass() const {
return cache->password;
}

#ifdef HAVE_DAUTH
std::string_view http_request::get_digested_user() const {
if (!cache->digested_user.empty()) {
return cache->digested_user;
Expand All @@ -272,6 +275,7 @@ std::string_view http_request::get_digested_user() const {

return cache->digested_user;
}
#endif // HAVE_DAUTH

#ifdef HAVE_GNUTLS
bool http_request::has_tls_session() const {
Expand Down
2 changes: 2 additions & 0 deletions src/httpserver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@

#include "httpserver/basic_auth_fail_response.hpp"
#include "httpserver/deferred_response.hpp"
#ifdef HAVE_DAUTH
#include "httpserver/digest_auth_fail_response.hpp"
#endif // HAVE_DAUTH
#include "httpserver/file_response.hpp"
#include "httpserver/http_arg_value.hpp"
#include "httpserver/http_request.hpp"
Expand Down
4 changes: 4 additions & 0 deletions src/httpserver/digest_auth_fail_response.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#ifndef SRC_HTTPSERVER_DIGEST_AUTH_FAIL_RESPONSE_HPP_
#define SRC_HTTPSERVER_DIGEST_AUTH_FAIL_RESPONSE_HPP_

#ifdef HAVE_DAUTH

#include <string>
#include "httpserver/http_utils.hpp"
#include "httpserver/string_response.hpp"
Expand Down Expand Up @@ -66,4 +68,6 @@ class digest_auth_fail_response : public string_response {

} // namespace httpserver

#endif // HAVE_DAUTH

#endif // SRC_HTTPSERVER_DIGEST_AUTH_FAIL_RESPONSE_HPP_
6 changes: 6 additions & 0 deletions src/httpserver/http_request.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,13 @@ class http_request {
**/
std::string_view get_user() const;

#ifdef HAVE_DAUTH
/**
* Method used to get the username extracted from a digest authentication
* @return the username
**/
std::string_view get_digested_user() const;
#endif // HAVE_DAUTH

/**
* Method used to get the password eventually passed through basic authentication.
Expand Down Expand Up @@ -250,7 +252,9 @@ class http_request {
**/
uint16_t get_requestor_port() const;

#ifdef HAVE_DAUTH
bool check_digest_auth(const std::string& realm, const std::string& password, int nonce_timeout, bool* reload_nonce) const;
#endif // HAVE_DAUTH

friend std::ostream &operator<< (std::ostream &os, http_request &r);

Expand Down Expand Up @@ -412,7 +416,9 @@ class http_request {
std::string password;
std::string querystring;
std::string requestor_ip;
#ifdef HAVE_DAUTH
std::string digested_user;
#endif // HAVE_DAUTH
std::map<std::string, std::vector<std::string>, http::arg_comparator> unescaped_args;

bool args_populated = false;
Expand Down
4 changes: 4 additions & 0 deletions src/webserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,11 @@ bool webserver::start(bool blocking) {
iov.push_back(gen(MHD_OPTION_THREAD_STACK_SIZE, max_thread_stack_size));
}

#ifdef HAVE_DAUTH
if (nonce_nc_size != 0) {
iov.push_back(gen(MHD_OPTION_NONCE_NC_SIZE, nonce_nc_size));
}
#endif // HAVE_DAUTH

if (use_ssl) {
// Need for const_cast to respect MHD interface that needs a void*
Expand All @@ -278,10 +280,12 @@ bool webserver::start(bool blocking) {
iov.push_back(gen(MHD_OPTION_HTTPS_PRIORITIES, 0, reinterpret_cast<void*>(const_cast<char*>(https_priorities.c_str()))));
}

#ifdef HAVE_DAUTH
if (digest_auth_random != "") {
// Need for const_cast to respect MHD interface that needs a char*
iov.push_back(gen(MHD_OPTION_DIGEST_AUTH_RANDOM, digest_auth_random.size(), const_cast<char*>(digest_auth_random.c_str())));
}
#endif // HAVE_DAUTH

#ifdef HAVE_GNUTLS
if (cred_type != http_utils::NONE) {
Expand Down
7 changes: 6 additions & 1 deletion test/integ/authentication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ using httpserver::webserver;
using httpserver::create_webserver;
using httpserver::http_response;
using httpserver::basic_auth_fail_response;
#ifdef HAVE_DAUTH
using httpserver::digest_auth_fail_response;
#endif // HAVE_DAUTH
using httpserver::string_response;
using httpserver::http_resource;
using httpserver::http_request;
Expand Down Expand Up @@ -74,6 +76,7 @@ class user_pass_resource : public http_resource {
}
};

#ifdef HAVE_DAUTH
class digest_resource : public http_resource {
public:
shared_ptr<http_response> render_GET(const http_request& req) {
Expand All @@ -88,6 +91,7 @@ class digest_resource : public http_resource {
return std::make_shared<string_response>("SUCCESS", 200, "text/plain");
}
};
#endif // HAVE_DAUTH

LT_BEGIN_SUITE(authentication_suite)
void set_up() {
Expand Down Expand Up @@ -150,7 +154,8 @@ LT_END_AUTO_TEST(base_auth_fail)
// do not run the digest auth tests on windows as curl
// appears to have problems with it.
// Will fix this separately
#ifndef _WINDOWS
// Also skip if libmicrohttpd was built without digest auth support
#if !defined(_WINDOWS) && defined(HAVE_DAUTH)

LT_BEGIN_AUTO_TEST(authentication_suite, digest_auth)
webserver ws = create_webserver(PORT)
Expand Down
Loading