0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-19 19:52:15 +02:00

Allow ACC communication before PUSH_REPLY by using auth pending method

This is reusing the auth pending method as this is just another method where
the final authentication decision is pending on some results. In this case
custom messages going back and forth. This can be tested using

   client-pending-auth 5 1 "ACC:1000 A:6 cck1:certcheck:cxa1:fortune" 60'

with OpenVPN 2.x servers easily.

Also correctly use ClientEvent::Base::Ptr with the Clientevents to avoid
problems with not correctly using RCPtr

Signed-off-by: Arne Schwabe <arne@openvpn.net>
This commit is contained in:
Arne Schwabe 2024-05-13 15:25:19 +02:00 committed by Jenkins-dev
parent 8c15ed2ac5
commit 3ceb4fff0c
2 changed files with 48 additions and 21 deletions

View File

@ -841,25 +841,37 @@ class Session : ProtoContextCallbackInterface,
// race conditions in the client app, if the INFO event
// triggers the client app to perform an operation that
// requires the VPN tunnel to be ready.
ClientEvent::Base::Ptr ev;
std::string info_msg;
if (info_pre)
info_msg = msg.substr(std::string_view{"INFO_PRE,"}.length());
else
info_msg = msg.substr(std::string_view{"INFO,"}.length());
if (string::starts_with(info_msg, "ACC:"))
{
ev = new ClientEvent::Info(msg.substr(std::strlen("INFO_PRE,")));
if ((string::starts_with(ev->render(), "WEB_AUTH:") || string::starts_with(ev->render(), "CR_TEXT:")) && creds)
// We want this to be parsed exactly like the custom-control option.
// That means we replace ACC: with custom-control for the parser.
auto acc_options = OptionList::parse_from_csv_static("custom-control " + info_msg.substr(std::strlen("ACC:")), &pushed_options_limit);
proto_context.conf().parse_custom_app_control(acc_options);
// check if we need to notify about ACC protocols
notify_client_acc_protocols();
}
else
{
if ((string::starts_with(info_msg, "WEB_AUTH:") || string::starts_with(info_msg, "CR_TEXT:")) && creds)
{
creds->set_need_user_interaction();
}
}
else
{
ev = new ClientEvent::Info(msg.substr(std::strlen("INFO,")));
}
// INFO_PRE is like INFO but it is never buffered
if (info_hold && !info_pre)
info_hold->push_back(std::move(ev));
else
cli_events->add_event(std::move(ev));
ClientEvent::Info::Ptr ev = new ClientEvent::Info(std::move(info_msg));
// INFO_PRE is like INFO but it is never buffered
if (info_hold && !info_pre)
info_hold->push_back(std::move(ev));
else
cli_events->add_event(std::move(ev));
}
}
// proto base class calls here for app-level control-channel messages received
@ -930,7 +942,7 @@ class Session : ProtoContextCallbackInterface,
}
else if (proto_context.conf().app_control_config.supports_protocol(proto))
{
auto ev = new ClientEvent::AppCustomControlMessage(std::move(proto), std::move(app_proto_msg));
ClientEvent::Base::Ptr ev = new ClientEvent::AppCustomControlMessage(std::move(proto), std::move(app_proto_msg));
cli_events->add_event(std::move(ev));
}
else
@ -970,6 +982,16 @@ class Session : ProtoContextCallbackInterface,
}
}
void notify_client_acc_protocols()
{
if (!proto_context.conf().app_control_config.supported_protocols.empty())
{
// Signal support for supported protocols
ClientEvent::Base::Ptr ev = new ClientEvent::AppCustomControlMessage("internal:supported_protocols", string::join(proto_context.conf().app_control_config.supported_protocols, ":"));
cli_events->add_event(std::move(ev));
}
}
void recv_push_reply(const std::string &msg)
{
if (!received_options.complete())
@ -1054,12 +1076,7 @@ class Session : ProtoContextCallbackInterface,
cli_events->add_event(connected_);
// send an event for custom app control if present
if (!proto_context.conf().app_control_config.supported_protocols.empty())
{
// Signal support for supported protocols
auto ev = new ClientEvent::AppCustomControlMessage("internal:supported_protocols", string::join(proto_context.conf().app_control_config.supported_protocols, ":"));
cli_events->add_event(std::move(ev));
}
notify_client_acc_protocols();
// check for proto options
check_proto_warnings();

View File

@ -342,13 +342,18 @@ class Client : public ClientBase
}
}
}
/**
@brief Handles ACC messages
@param acev The current ACC event
*/
virtual void acc_event(const ClientAPI::AppCustomControlMessageEvent &acev) override
{
if (acev.protocol == certcheck_init_verb)
if (acev.protocol == "internal:supported_protocols")
{
std::cout << "Client/server common app custom control protocols: " << acev.payload << std::endl;
}
else if (acev.protocol == certcheck_init_verb)
{
if (string::starts_with(acev.payload, "{\"dpc_certcheck_cert_req\""))
{
@ -356,6 +361,11 @@ class Client : public ClientBase
handle_certcheck_request();
}
}
else
{
std::cout << "received app custom control message for protocol " << acev.protocol
<< " msg payload: " << acev.payload << std::endl;
}
}
/**