17#ifndef WIN32_LEAN_AND_MEAN
18#define WIN32_LEAN_AND_MEAN
31namespace fs = std::filesystem;
44 CurveAuth(zmq::context_t & context) : _authenticator(context) {}
62 _authenticator.
allow(ip);
66 _authenticator.
start();
81 if (!fs::exists(key_dir) || !fs::is_directory(key_dir)) {
82 throw runtime_error(
"Key directory does not exist: " + key_dir.string());
84 for (
const auto &entry : fs::directory_iterator(key_dir)) {
85 if (entry.path().extension() ==
".pub") {
86 _client_keys.push_back(entry.path().stem().string());
89 if (_client_keys.empty()) {
90 throw runtime_error(
"No client public keys found in " + key_dir.string());
105 if (_key_dir.empty()) {
106 throw runtime_error(
"Key directory not set. Call fetch_public_keys() first.");
112 name = (_key_dir / (key_name +
".pub")).string();
113 ifstream server_pub_file(name);
114 if (!server_pub_file.is_open()) {
115 throw runtime_error(
string(
"cannot open server public key file ") + name +
" from " + _key_dir.string());
117 getline(server_pub_file, server_keypair.
public_key);
118 server_pub_file.close();
120 name = (_key_dir / (key_name +
".key")).string();
121 ifstream server_key_file(name);
122 if (!server_key_file.is_open()) {
123 throw runtime_error(
string(
"cannot open server secret key file ") + name +
" from " + _key_dir.string());
125 getline(server_key_file, server_keypair.
secret_key);
126 server_key_file.close();
127 }
catch (
const std::exception &e) {
128 throw runtime_error(e.what());
130 for (
const auto &client_key_name : _client_keys) {
131 name = (_key_dir / (client_key_name +
".pub")).string();
132 ifstream client_pub_file(name);
133 if (!client_pub_file.is_open()) {
134 throw runtime_error(
"cannot open client public key file " + name +
" from " + _key_dir.string());
137 getline(client_pub_file, client_key);
138 client_pub_file.close();
141 socket.set(zmq::sockopt::routing_id,
"IDENT");
142 socket.set(zmq::sockopt::curve_server, 1);
143 socket.set(zmq::sockopt::curve_secretkey, server_keypair.
secret_key);
157 void setup_curve_client(zmq::socket_t &socket,
string const &client_name,
string const &server_name) {
160 string name = (_key_dir / (client_name +
".pub")).string();
161 ifstream client_pub_file(name);
162 if (!client_pub_file.is_open()) {
163 throw runtime_error(
string(
"cannot open client public key file ") + name +
" from " + _key_dir.string());
165 getline(client_pub_file, _client_keypair.
public_key);
166 client_pub_file.close();
168 name = (_key_dir / (server_name +
".pub")).string();
169 ifstream server_pub_file(name);
170 if (!server_pub_file.is_open()) {
171 throw runtime_error(
string(
"cannot open server public key file ") + name +
" from " + _key_dir.string());
173 getline(server_pub_file, _server_public_key);
174 server_pub_file.close();
176 name = (_key_dir / (client_name +
".key")).string();
177 ifstream client_key_file(name);
178 if (!client_key_file.is_open()) {
179 throw runtime_error(
string(
"cannot open client private key file ") + name +
" from " + _key_dir.string());
181 getline(client_key_file, _client_keypair.
secret_key);
182 client_key_file.close();
183 }
catch (
const std::exception &e) {
184 throw runtime_error(e.what());
198 if (_client_keypair.
public_key.empty() || _client_keypair.
secret_key.empty() || _server_public_key.empty()) {
199 throw runtime_error(
"Client or server keys not set. Call setup_curve_client() or set them individually first.");
201 socket.set(zmq::sockopt::curve_publickey, _client_keypair.
public_key);
202 socket.set(zmq::sockopt::curve_secretkey, _client_keypair.
secret_key);
203 socket.set(zmq::sockopt::curve_serverkey, _server_public_key);
208 if (!fs::exists(_key_dir) || !fs::is_directory(_key_dir)) {
209 throw runtime_error(
"Key directory does not exist: " + _key_dir.string());
230 _server_public_key = key;
234 return _server_public_key;
242 vector<string> _client_keys{};
244 CurveKeypair _client_keypair = {
"",
""};
245 string _server_public_key =
"";
string server_public_key() const
vector< string > allowed_ips
string client_public_key() const
void set_key_dir(fs::path const &key_dir)
void setup_auth(auth_verbose verbose=auth_verbose::off)
Sets up ZAP authentication with the specified verbosity.
void set_server_public_key(string const &key)
void set_client_public_key(string const &key)
void set_client_secret_key(string const &key)
string client_secret_key() const
CurveAuth(zmq::context_t &context)
Constructs a CurveAuth object for managing CURVE authentication.
void setup_curve_client(zmq::socket_t &socket)
Sets up CURVE security for a client socket using raw keys.
void fetch_public_keys(fs::path const &key_dir)
Fetches client public keys from the specified directory.
void setup_curve_client(zmq::socket_t &socket, string const &client_name, string const &server_name)
Sets up CURVE security for a client socket.
void setup_curve_server(zmq::socket_t &socket, string const &key_name)
Sets up CURVE security for a server socket.
In-process ZAP (ZeroMQ Authentication Protocol, RFC 27) handler.
void configure_curve(const std::string &z85_public_key)
Add a client public key to the CURVE allowlist.
void start()
Bind the ZAP endpoint and start servicing requests.
void set_verbose(bool verbose)
Log every authentication decision to stdout.
void allow(const std::string &address)
Add an address to the whitelist.
void configure_domain(const std::string &domain)
Restrict the handler to one ZAP domain.
A CURVE keypair, both keys Z85-encoded (40 characters each).