Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
login_plugin.cpp
Go to the documentation of this file.
4
5#include <fc/io/json.hpp>
6
7namespace sysio {
8
9static appbase::abstract_plugin& _login_plugin = app().register_plugin<login_plugin>();
10
11using namespace sysio;
12
18
21
22using login_request_container = boost::multi_index_container<
24 indexed_by< //
25 ordered_unique<tag<login_request_pub_key_index>,
26 member<login_request, chain::public_key_type, &login_request::server_ephemeral_pub_key>>,
27 ordered_non_unique<tag<login_request_time_index>,
28 member<login_request, chain::time_point_sec, &login_request::expiration_time>> //
29 >>;
30
32 public:
36
38 auto& index = requests.get<login_request_time_index>();
39 auto now = fc::time_point::now();
40 for (auto it = index.begin(); it != index.end() && it->expiration_time < now; it = index.erase(it))
41 ;
42 }
43};
44
45login_plugin::login_plugin() : my{std::make_unique<login_plugin_impl>()} {}
47
48void login_plugin::set_program_options(options_description&, options_description& cfg) {
49 cfg.add_options() //
50 ("max-login-requests", bpo::value<uint32_t>()->default_value(1000000),
51 "The maximum number of pending login requests") //
52 ("max-login-timeout", bpo::value<uint32_t>()->default_value(60),
53 "The maximum timeout for pending login requests (in seconds)");
54}
55
56void login_plugin::plugin_initialize(const variables_map& options) {
57 my->max_login_requests = options.at("max-login-requests").as<uint32_t>();
58 my->max_login_timeout = options.at("max-login-timeout").as<uint32_t>();
59}
60
61#define CALL(call_name, http_response_code) \
62 { \
63 std::string("/v1/login/" #call_name), [this](string, string body, url_response_callback cb) mutable { \
64 try { \
65 if (body.empty()) \
66 body = "{}"; \
67 fc::variant result( call_name(fc::json::from_string(body).as<login_plugin::call_name##_params>()) ); \
68 cb(http_response_code, std::move(result)); \
69 } catch (...) { \
70 http_plugin::handle_exception("login", #call_name, body, cb); \
71 } \
72 } \
73 }
74
76 ilog("starting login_plugin");
77 app().get_plugin<http_plugin>().add_api({
80 // CALL(do_not_use_gen_r1_key, 200), //
81 // CALL(do_not_use_sign, 200), //
82 // CALL(do_not_use_get_secret, 200), //
83 });
84}
85
87
90 my->expire_requests();
91 SYS_ASSERT(params.expiration_time > fc::time_point::now(), fc::timeout_exception,
92 "Requested expiration time ${expiration_time} is in the past",
93 ("expiration_time", params.expiration_time));
94 SYS_ASSERT(my->requests.size() < my->max_login_requests, fc::timeout_exception, "Too many pending login requests");
95 login_request request;
97 request.server_ephemeral_pub_key = request.server_ephemeral_priv_key.get_public_key();
98 request.expiration_time =
99 std::min(params.expiration_time, fc::time_point_sec{fc::time_point::now()} + my->max_login_timeout);
100 my->requests.insert(request);
101 return {request.server_ephemeral_pub_key};
102}
103
107 my->expire_requests();
108 auto& index = my->requests.get<login_request_pub_key_index>();
109 auto it = index.find(params.server_ephemeral_pub_key);
110 if (it == index.end()) {
111 result.error = "server_ephemeral_pub_key expired or not found";
112 return result;
113 }
114 auto request = *it;
115 index.erase(it);
116
117 auto shared_secret = request.server_ephemeral_priv_key.generate_shared_secret(params.client_ephemeral_pub_key);
118
119 chain::bytes combined_data(1024 * 1024);
120 chain::datastream<char*> sig_data_ds{combined_data.data(), combined_data.size()};
121 fc::raw::pack(sig_data_ds, params.permission);
122 fc::raw::pack(sig_data_ds, shared_secret);
123 fc::raw::pack(sig_data_ds, params.data);
124 combined_data.resize(sig_data_ds.tellp());
125
126 result.digest = chain::sha256::hash(combined_data);
127 for (auto& sig : params.signatures)
128 result.recovered_keys.insert(chain::public_key_type{sig, result.digest});
129
130 try {
131 auto noop_checktime = [] {};
132 auto& chain = app().get_plugin<chain_plugin>().chain();
133 chain.get_authorization_manager().check_authorization( //
134 params.permission.actor, params.permission.permission, result.recovered_keys, {}, fc::microseconds(0),
135 noop_checktime, true);
136 result.permission_satisfied = true;
137 } catch (...) {
138 result.error = "keys do not satisfy permission";
139 }
140
141 return result;
142}
143
149
152 return {params.priv_key.sign(chain::sha256::hash(params.data))};
153}
154
157 return {params.priv_key.generate_shared_secret(params.pub_key)};
158}
159
160} // namespace sysio
#define SYS_ASSERT(expr, exc_type, FORMAT,...)
Definition exceptions.hpp:7
abstract_plugin & get_plugin(const string &name) const
static private_key generate_r1()
static time_point now()
Definition time.cpp:14
login_request_container requests
void plugin_initialize(const variables_map &)
do_not_use_gen_r1_key_results do_not_use_gen_r1_key(const do_not_use_gen_r1_key_params &)
start_login_request_results start_login_request(const start_login_request_params &)
do_not_use_sign_results do_not_use_sign(const do_not_use_sign_params &)
do_not_use_get_secret_results do_not_use_get_secret(const do_not_use_get_secret_params &)
virtual void set_program_options(options_description &, options_description &) override
finalize_login_request_results finalize_login_request(const finalize_login_request_params &)
#define ilog(FORMAT,...)
Definition logger.hpp:118
#define CALL(call_name, http_response_code)
application & app()
void pack(Stream &s, const std::deque< T > &value)
Definition raw.hpp:531
Definition name.hpp:106
boost::multi_index_container< login_request, indexed_by< ordered_unique< tag< login_request_pub_key_index >, member< login_request, chain::public_key_type, &login_request::server_ephemeral_pub_key > >, ordered_non_unique< tag< login_request_time_index >, member< login_request, chain::time_point_sec, &login_request::expiration_time > > > > login_request_container
unsigned int uint32_t
Definition stdint.h:126
chain::private_key_type server_ephemeral_priv_key
chain::time_point_sec expiration_time
chain::public_key_type server_ephemeral_pub_key