Leosac  0.7.0
OpenSourceAccessControl
WebServiceNotifier.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014-2016 Leosac
3 
4  This file is part of Leosac.
5 
6  Leosac is free software: you can redistribute it and/or modify
7  it under the terms of the GNU Affero General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Leosac 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
14  GNU Affero General Public License for more details.
15 
16  You should have received a copy of the GNU Affero General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "WebServiceNotifier.hpp"
21 #include "core/auth/Auth.hpp"
23 #include <curl/curl.h>
24 
25 using namespace Leosac;
26 using namespace Leosac::Module;
27 using namespace Leosac::Module::WSNotifier;
28 
29 WebServiceNotifier::WebServiceNotifier(zmqpp::context &ctx, zmqpp::socket *pipe,
30  const boost::property_tree::ptree &cfg,
31  CoreUtilsPtr utils)
32  : BaseModule(ctx, pipe, cfg, utils)
33  , bus_sub_(ctx, zmqpp::socket_type::sub)
34 {
35  int ret;
36  long flags = 0;
37 
38  if (config_.get<bool>("module_config.want_ssl", true))
39  flags |= CURL_GLOBAL_SSL;
40  if ((ret = curl_global_init(flags)) != 0)
41  {
42  throw std::runtime_error("Failed to initialize curl: return code: " +
43  std::to_string(ret));
44  }
45  bus_sub_.connect("inproc://zmq-bus-pub");
48 }
49 
51 {
52  curl_global_cleanup();
53 }
54 
56 {
57  zmqpp::message msg;
58  std::string src;
60  std::string card;
61  int bits;
62 
63  bus_sub_.receive(msg);
64  if (msg.parts() < 4)
65  {
66  WARN("Unexpected message content.");
67  return;
68  }
69  msg >> src >> type >> card >> bits;
71  {
72  INFO("WS-Notifier cannot handle this type of credential yet.");
73  return;
74  }
75 
76  send_card_info_to_remote(src, card, bits);
77 }
78 
80 {
81  for (auto &&itr : config_.get_child("module_config.sources"))
82  {
83  auto name = itr.second.get<std::string>("");
84  bus_sub_.subscribe("S_" + name);
85  }
86 
87  for (auto &&itr : config_.get_child("module_config.targets"))
88  {
89  TargetInfo target;
90  target.url_ = itr.second.get<std::string>("url");
91  target.connect_timeout_ = itr.second.get<int>("connect_timeout", 7000);
92  target.request_timeout_ = itr.second.get<int>("request_timeout", 7000);
93  target.verify_host_ = itr.second.get<bool>("verify_host", true);
94  target.verify_peer_ = itr.second.get<bool>("verify_peer", true);
95  target.CA_info_file_ = itr.second.get<std::string>("ca_file", "");
96 
97  INFO("WS-Notifier remote target: "
98  << Colorize::green(target.url_)
99  << " (connect_timeout: " << Colorize::green(target.connect_timeout_)
100  << ", request_timeout: " << Colorize::green(target.request_timeout_)
101  << ", verify_host: " << Colorize::green(target.verify_host_)
102  << ", verify_peer: " << Colorize::green(target.verify_peer_)
103  << ", ca_info: " << Colorize::green(target.CA_info_file_) << ")");
104  targets_.push_back(std::move(target));
105  }
106 }
107 
108 void WebServiceNotifier::send_card_info_to_remote(const std::string &auth_source,
109  const std::string &card_hex,
110  int nb_bits)
111 {
112  auto card = Cred::RFIDCard();
113  card.card_id(card_hex);
114  card.nb_bits(nb_bits);
115 
116  for (const auto &target : targets_)
117  {
118  auto curl = curl_easy_init();
119  if (curl)
120  {
121  if (!target.CA_info_file_.empty())
122  curl_easy_setopt(curl, CURLOPT_CAINFO, target.CA_info_file_.c_str());
123  if (!target.verify_host_)
124  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
125  if (!target.verify_peer_)
126  curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
127  send_to_target(curl, auth_source, card, target);
128  curl_easy_cleanup(curl);
129  }
130  else
131  {
132  ERROR("Cannot initialize curl_easy.");
133  }
134  }
135 }
136 
142 static size_t write_callback(char * /*ptr*/, size_t size, size_t nmemb,
143  void * /*userdata*/)
144 {
145  return size * nmemb;
146 }
147 
149  void *curl, const std::string &auth_source, const Cred::RFIDCard &card,
150  const WebServiceNotifier::TargetInfo &target) noexcept
151 {
152  assert(curl);
153 
154  std::string post_fields =
155  fmt::format("card_id={}&auth_source={}&card_id_raw={}", card.to_int(),
156  auth_source, card.to_raw_int());
157 
158  curl_easy_setopt(curl, CURLOPT_URL, target.url_.c_str());
159  curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_fields.c_str());
160 
161  // timeouts
162  curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, target.connect_timeout_);
163  curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, target.request_timeout_);
164 
165  curl_easy_setopt(curl, CURLOPT_WRITEDATA, nullptr);
166  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_callback);
167 
168  auto res = curl_easy_perform(curl);
169  if (res != CURLE_OK)
170  {
171  WARN("curl_easy_perform() failed: " << curl_easy_strerror(res));
172  }
173 }
void send_to_target(void *curl, const std::string &auth_source, const Cred::RFIDCard &card, const TargetInfo &target) noexcept
This define message formatting for data source SIMPLE_WIEGAND.
This is the header file for a generated source file, GitSHA1.cpp.
void process_config()
Process the configuration file.
Definition: log.hpp:37
void send_card_info_to_remote(const std::string &auth_source, const std::string &card, int nb_bits)
Send an HTTP request to the remote webservice to let it know a card was read.
bool verify_peer_
If SSL is enabled, do we perform certificate validation ?
Definition: log.hpp:35
std::string green(const T &in)
Definition: Colorize.hpp:82
All modules that provides features to Leosac shall be in this namespace.
Base class for module implementation.
Definition: BaseModule.hpp:110
void handle_msg_bus()
Process a message that was read on the bus.
zmqpp::reactor reactor_
The reactor object we poll() on in the main loop.
Definition: BaseModule.hpp:214
WebServiceNotifier(zmqpp::context &ctx, zmqpp::socket *pipe, const boost::property_tree::ptree &cfg, CoreUtilsPtr utils)
Definition: log.hpp:34
std::shared_ptr< CoreUtils > CoreUtilsPtr
Definition: LeosacFwd.hpp:35
Some information for each webservice target.
An RFID card credential.
Definition: RFIDCard.hpp:33
bool verify_host_
If SSL is enabled, do we perform certificate hostname validation ?
boost::property_tree::ptree config_
The configuration tree passed to the start_module function.
Definition: BaseModule.hpp:193
zmqpp::socket bus_sub_
Read internal message bus.
std::string format(const std::string &escape_code, const T &in)
Return a string containing the escape code, a string representation of T and the clear escape string...
Definition: Colorize.hpp:49