26 : session_(&session), handler_(
std::move(handler)) {
27 ssh_callbacks_init((&server_cb_));
28 server_cb_.userdata =
this;
29 server_cb_.auth_none_function = &HandlerBridge::auth_none_cb;
30 server_cb_.auth_password_function = &HandlerBridge::auth_password_cb;
31 server_cb_.auth_pubkey_function = &HandlerBridge::auth_pubkey_cb;
32 server_cb_.auth_gssapi_mic_function = &HandlerBridge::auth_gssapi_mic_cb;
33 server_cb_.channel_open_request_session_function = &HandlerBridge::channel_open_session_cb;
34 server_cb_.service_request_function = &HandlerBridge::service_request_cb;
42 if (ssh_set_server_callbacks(raw, &server_cb_) != SSH_OK) {
49 if (!handler_)
return;
51 handler_->on_disconnect(*session_);
60 for (
auto raw : pending_removals_) channels_.erase(raw);
61 pending_removals_.clear();
67 std::shared_ptr<server::ChannelHandler> handler;
68 ssh_channel_callbacks_struct
cb{};
69 HandlerBridge* bridge =
nullptr;
72 void report_error(
const ErrorInfo&
info) {
73 if (!handler_)
return;
75 handler_->on_error(*session_,
info);
80 ChannelState* register_channel(
native_channel raw, std::shared_ptr<server::ChannelHandler> handler) {
81 auto state = std::make_unique<ChannelState>();
83 state->handler = std::move(handler);
85 ssh_callbacks_init((&state->cb));
86 state->cb.userdata = state.get();
87 state->cb.channel_data_function = &HandlerBridge::channel_data_cb;
88 state->cb.channel_eof_function = &HandlerBridge::channel_eof_cb;
89 state->cb.channel_close_function = &HandlerBridge::channel_close_cb;
90 state->cb.channel_signal_function = &HandlerBridge::channel_signal_cb;
91 state->cb.channel_pty_request_function = &HandlerBridge::channel_pty_request_cb;
92 state->cb.channel_shell_request_function = &HandlerBridge::channel_shell_request_cb;
93 state->cb.channel_x11_req_function = &HandlerBridge::channel_x11_req_cb;
94 state->cb.channel_pty_window_change_function = &HandlerBridge::channel_pty_window_change_cb;
95 state->cb.channel_exec_request_function = &HandlerBridge::channel_exec_request_cb;
96 state->cb.channel_env_request_function = &HandlerBridge::channel_env_request_cb;
97 state->cb.channel_subsystem_request_function = &HandlerBridge::channel_subsystem_request_cb;
98 ssh_set_channel_callbacks(raw, &state->cb);
99 ChannelState* ptr = state.get();
100 channels_[raw] = std::move(state);
105 static int auth_none_cb(ssh_session,
const char* user,
void* userdata) {
108 auto r = self->handler_->on_auth_none(*self->session_, user !=
nullptr ? user :
"");
109 return self->apply_auth_result(r, user);
110 }
catch (
const std::exception& e) {
112 return SSH_AUTH_DENIED;
114 return SSH_AUTH_DENIED;
118 static int auth_password_cb(ssh_session,
const char* user,
const char* password,
void* userdata) {
121 auto r = self->handler_->on_auth_password(*self->session_, user !=
nullptr ? user :
"",
123 return self->apply_auth_result(r, user);
124 }
catch (
const std::exception& e) {
126 return SSH_AUTH_DENIED;
128 return SSH_AUTH_DENIED;
132 static int auth_pubkey_cb(ssh_session,
const char* user, ssh_key pubkey,
char signature_state,
void* userdata) {
139 auto r = self->handler_->on_auth_public_key(*self->session_, user !=
nullptr ? user :
"", key, state);
144 }
catch (
const std::exception& e) {
146 return SSH_AUTH_DENIED;
148 return SSH_AUTH_DENIED;
152 static int auth_gssapi_mic_cb(ssh_session,
const char* user,
const char* principal,
void* userdata) {
155 auto r = self->handler_->on_auth_gssapi_mic(*self->session_, user !=
nullptr ? user :
"",
156 principal != nullptr ? principal :
"");
157 return self->apply_auth_result(r, user);
159 return SSH_AUTH_DENIED;
166 session_->authenticated_ =
true;
167 session_->user_ = user !=
nullptr ? user :
"";
169 return SSH_AUTH_SUCCESS;
172 return SSH_AUTH_DENIED;
176 static ssh_channel channel_open_session_cb(ssh_session sess,
void* userdata) {
179 auto ch_handler = self->handler_->on_channel_open_session(*self->session_);
180 if (!ch_handler)
return nullptr;
181 ssh_channel raw = ssh_channel_new(sess);
182 if (raw ==
nullptr)
return nullptr;
183 self->register_channel(raw, std::move(ch_handler));
185 }
catch (
const std::exception& e) {
193 static int service_request_cb(ssh_session,
const char* service,
void* userdata) {
196 self->handler_->on_service_request(*self->session_, service !=
nullptr ? service :
"");
203 static int channel_data_cb(ssh_session, ssh_channel,
void* data, uint32_t len,
int is_stderr,
void* userdata) {
204 auto* state =
static_cast<ChannelState*
>(userdata);
206 auto consumed = state->handler->on_data(state->channel,
207 ByteView(
static_cast<const std::byte*
>(data), len),
209 return static_cast<int>(consumed);
215 static void channel_eof_cb(ssh_session, ssh_channel,
void* userdata) {
216 auto* state =
static_cast<ChannelState*
>(userdata);
218 state->handler->on_eof(state->channel);
223 static void channel_close_cb(ssh_session, ssh_channel raw,
void* userdata) {
224 auto* state =
static_cast<ChannelState*
>(userdata);
226 state->handler->on_close(state->channel);
236 state->bridge->pending_removals_.push_back(raw);
239 static void channel_signal_cb(ssh_session, ssh_channel,
const char* signal,
void* userdata) {
240 auto* state =
static_cast<ChannelState*
>(userdata);
242 state->handler->on_signal(state->channel, signal !=
nullptr ? signal :
"");
247 static int channel_pty_request_cb(ssh_session, ssh_channel,
const char*
term,
int width,
int height,
248 int,
int,
void* userdata) {
249 auto* state =
static_cast<ChannelState*
>(userdata);
251 PtySize size{width, height};
252 return state->handler->on_pty_request(state->channel,
term !=
nullptr ?
term :
"", size) ? 0 : -1;
258 static int channel_pty_window_change_cb(ssh_session, ssh_channel,
int width,
int height,
int,
int,
260 auto* state =
static_cast<ChannelState*
>(userdata);
262 PtySize size{width, height};
263 return state->handler->on_pty_resize(state->channel, size) ? 0 : -1;
269 static int channel_shell_request_cb(ssh_session, ssh_channel,
void* userdata) {
270 auto* state =
static_cast<ChannelState*
>(userdata);
272 return state->handler->on_shell_request(state->channel) ? 0 : 1;
278 static int channel_exec_request_cb(ssh_session, ssh_channel,
const char* command,
void* userdata) {
279 auto* state =
static_cast<ChannelState*
>(userdata);
281 return state->handler->on_exec_request(state->channel, command !=
nullptr ? command :
"") ? 0 : 1;
287 static int channel_env_request_cb(ssh_session, ssh_channel,
const char* name,
const char* value,
289 auto* state =
static_cast<ChannelState*
>(userdata);
291 return state->handler->on_env_request(state->channel, name !=
nullptr ? name :
"",
292 value != nullptr ? value :
"")
300 static int channel_subsystem_request_cb(ssh_session, ssh_channel raw,
const char* name,
void* userdata) {
301 auto* state =
static_cast<ChannelState*
>(userdata);
303 bool accepted = state->handler->on_subsystem_request(state->channel, name !=
nullptr ? name :
"");
310 ssh_remove_channel_callbacks(raw, &state->cb);
312 return accepted ? 0 : 1;
318 static void channel_x11_req_cb(ssh_session, ssh_channel,
int single_connection,
const char* auth_protocol,
319 const char* auth_cookie, uint32_t screen_number,
void* userdata) {
320 auto* state =
static_cast<ChannelState*
>(userdata);
322 state->handler->on_x11_request(state->channel, single_connection != 0,
323 auth_protocol !=
nullptr ? auth_protocol :
"",
324 auth_cookie != nullptr ? auth_cookie :
"", screen_number);
329 server::Session* session_;
330 std::shared_ptr<server::SessionHandler> handler_;
331 ssh_server_callbacks_struct server_cb_{};
332 std::unordered_map<ssh_channel, std::unique_ptr<ChannelState>> channels_;
333 std::vector<ssh_channel> pending_removals_;