aboutsummaryrefslogtreecommitdiff
path: root/src/libssh2.c
diff options
context:
space:
mode:
authorDavid Timber <mieabby@gmail.com>2020-09-18 00:39:10 +0930
committerDavid Timber <mieabby@gmail.com>2020-09-18 00:39:10 +0930
commit54166c46f32555532dc3c0e922fe6a591cb74128 (patch)
treedee32ffb8a15365cc2800f6c2cbc3520ef56324e /src/libssh2.c
parente6953dcb47193746a4f4d9fff0193723fadbb3e6 (diff)
* Impl: bne
* Add prne_index_nybin()
Diffstat (limited to 'src/libssh2.c')
-rw-r--r--src/libssh2.c375
1 files changed, 375 insertions, 0 deletions
diff --git a/src/libssh2.c b/src/libssh2.c
new file mode 100644
index 0000000..b55e093
--- /dev/null
+++ b/src/libssh2.c
@@ -0,0 +1,375 @@
+#include "libssh2.h"
+#include "util_ct.h"
+#include "util_rt.h"
+#include "pth.h"
+
+#include <stdbool.h>
+#include <errno.h>
+
+
+typedef struct {
+ LIBSSH2_SESSION *s;
+ int fd;
+} lssh2_cbctx_s_t;
+
+typedef struct {
+ LIBSSH2_SESSION *s;
+ const char *id;
+ const char *pw;
+ unsigned int id_len;
+ unsigned int pw_len;
+ void *ret;
+} lssh2_cbctx_ua_cred_t;
+
+typedef struct {
+ LIBSSH2_SESSION *s;
+ LIBSSH2_CHANNEL *ret;
+} lssh2_cbctx_open_channel_t;
+
+typedef struct {
+ LIBSSH2_CHANNEL *c;
+ void *buf;
+ size_t len;
+ int s_id;
+} lssh2_cbctx_ch_f_t;
+
+typedef struct {
+ LIBSSH2_SESSION *s;
+ int reason;
+ const char *desc;
+ const char *lang;
+} lssh2_cbctx_discon_t;
+
+static ssize_t lssh2_crippled_send (
+ int __fd,
+ const void *__buf,
+ size_t __n,
+ int __flags)
+{
+ errno = 0;
+ return -1;
+}
+
+static ssize_t lssh2_crippled_recv (
+ int __fd,
+ void *__buf,
+ size_t __n,
+ int __flags)
+{
+ errno = 0;
+ return -1;
+}
+
+static int lssh2_handle (
+ LIBSSH2_SESSION *s,
+ const int fd,
+ pth_event_t ev,
+ void *ctx,
+ int (*lssh2_f)(void*))
+{
+ int f_ret;
+ struct pollfd pfd;
+
+ pfd.fd = fd;
+ while (true) {
+ f_ret = lssh2_f(ctx);
+ if (f_ret != LIBSSH2_ERROR_EAGAIN) {
+ break;
+ }
+
+ f_ret = libssh2_session_block_directions(s);
+ pfd.events = 0;
+ if (f_ret & LIBSSH2_SESSION_BLOCK_INBOUND) {
+ pfd.events |= POLLIN;
+ }
+ if (f_ret & LIBSSH2_SESSION_BLOCK_OUTBOUND) {
+ pfd.events |= POLLOUT;
+ }
+
+ f_ret = prne_pth_poll(&pfd, 1, -1, ev);
+ if (f_ret < 0) {
+ break;
+ }
+ else if (f_ret == 0) {
+ f_ret = -1;
+ errno = ETIMEDOUT;
+ break;
+ }
+ }
+
+ return f_ret;
+}
+
+static int lssh2_handshake_f (void *p) {
+ lssh2_cbctx_s_t *ctx = (lssh2_cbctx_s_t*)p;
+ return libssh2_session_handshake(ctx->s, ctx->fd);
+}
+
+int prne_lssh2_handshake (LIBSSH2_SESSION *s, const int fd, pth_event_t ev) {
+ lssh2_cbctx_s_t ctx;
+ ctx.fd = fd;
+ ctx.s = s;
+ return lssh2_handle(s, fd, ev, &ctx, lssh2_handshake_f);
+}
+
+static int lssh2_ua_pwd_f (void *p) {
+ lssh2_cbctx_ua_cred_t *ctx = (lssh2_cbctx_ua_cred_t*)p;
+ return libssh2_userauth_password_ex(
+ ctx->s,
+ ctx->id,
+ ctx->id_len,
+ ctx->pw,
+ ctx->pw_len,
+ NULL);
+}
+
+int prne_lssh2_ua_pwd (
+ LIBSSH2_SESSION *s,
+ const int fd,
+ const char *id,
+ const char *pw,
+ pth_event_t ev)
+{
+ lssh2_cbctx_ua_cred_t ctx;
+ const size_t id_len = prne_nstrlen(id);
+ const size_t pw_len = prne_nstrlen(pw);
+
+ if (id_len > UINT_MAX || pw_len > UINT_MAX) {
+ errno = E2BIG;
+ return -1;
+ }
+
+ ctx.s = s;
+ ctx.id = id;
+ ctx.id_len = (unsigned int)id_len;
+ ctx.pw = pw;
+ ctx.pw_len = (unsigned int)pw_len;
+
+ return lssh2_handle(s, fd, ev, &ctx, lssh2_ua_pwd_f);
+}
+
+static int lssh2_open_channel_f (void *p) {
+ lssh2_cbctx_open_channel_t *ctx = (lssh2_cbctx_open_channel_t*)p;
+ int err;
+
+ ctx->ret = libssh2_channel_open_session(ctx->s);
+ if (ctx->ret == NULL) {
+ err = libssh2_session_last_errno(ctx->s);
+ prne_dbgast(err != 0);
+ }
+ else {
+ err = 0;
+ }
+
+ return err;
+}
+
+LIBSSH2_CHANNEL *prne_lssh2_open_ch (
+ LIBSSH2_SESSION *s,
+ const int fd,
+ pth_event_t ev,
+ int *err)
+{
+ lssh2_cbctx_open_channel_t ctx;
+ int f_ret;
+ ctx.s = s;
+ ctx.ret = NULL;
+
+ f_ret = lssh2_handle(s, fd, ev, &ctx, lssh2_open_channel_f);
+ prne_chk_assign(err, f_ret);
+ return ctx.ret;
+}
+
+static int lssh2_ch_req_pty_f (void *p) {
+ lssh2_cbctx_ch_f_t *ctx = (lssh2_cbctx_ch_f_t*)p;
+ return libssh2_channel_request_pty(ctx->c, (const char*)ctx->buf);
+}
+
+int prne_lssh2_ch_req_pty (
+ LIBSSH2_SESSION *s,
+ LIBSSH2_CHANNEL *c,
+ const int fd,
+ const char *term,
+ pth_event_t ev)
+{
+ lssh2_cbctx_ch_f_t ctx;
+ ctx.c = c;
+ ctx.buf = (void*)term;
+ return lssh2_handle(s, fd, ev, &ctx, lssh2_ch_req_pty_f);
+}
+
+static int lssh2_ch_sh_f (void *p) {
+ lssh2_cbctx_ch_f_t *ctx = (lssh2_cbctx_ch_f_t*)p;
+ return libssh2_channel_shell(ctx->c);
+}
+
+int prne_lssh2_ch_sh (
+ LIBSSH2_SESSION *s,
+ LIBSSH2_CHANNEL *c,
+ const int fd,
+ pth_event_t ev)
+{
+ lssh2_cbctx_ch_f_t ctx;
+ ctx.c = c;
+ return lssh2_handle(s, fd, ev, &ctx, lssh2_ch_sh_f);
+}
+
+static int lssh2_ch_io_f (void *p) {
+ lssh2_cbctx_ch_f_t *ctx = (lssh2_cbctx_ch_f_t*)p;
+ ssize_t ret;
+
+ switch (ctx->s_id) {
+ case 0:
+ ret = libssh2_channel_write(ctx->c, ctx->buf, ctx->len);
+ break;
+ case 1:
+ ret = libssh2_channel_read(ctx->c, ctx->buf, ctx->len);
+ break;
+ case 2:
+ ret = libssh2_channel_read_stderr(ctx->c, ctx->buf, ctx->len);
+ break;
+ default: ret = -1;
+ }
+
+ return (int)ret;
+}
+
+int prne_lssh2_ch_read (
+ LIBSSH2_SESSION *s,
+ LIBSSH2_CHANNEL *c,
+ const int fd,
+ const bool s_err,
+ void *buf,
+ const size_t len,
+ pth_event_t ev)
+{
+ lssh2_cbctx_ch_f_t ctx;
+ if (len > INT_MAX) {
+ errno = E2BIG;
+ return -1;
+ }
+ ctx.c = c;
+ ctx.buf = buf;
+ ctx.len = len;
+ ctx.s_id = s_err ? 2 : 1;
+
+ return lssh2_handle(s, fd, ev, &ctx, lssh2_ch_io_f);
+}
+
+int prne_lssh2_ch_write (
+ LIBSSH2_SESSION *s,
+ LIBSSH2_CHANNEL *c,
+ const int fd,
+ const void *buf,
+ const size_t len,
+ pth_event_t ev)
+{
+ lssh2_cbctx_ch_f_t ctx;
+ if (len > INT_MAX) {
+ errno = E2BIG;
+ return -1;
+ }
+ ctx.c = c;
+ ctx.buf = (void*)buf;
+ ctx.len = len;
+ ctx.s_id = 0;
+
+ return lssh2_handle(s, fd, ev, &ctx, lssh2_ch_io_f);
+}
+
+static int lssh2_disconn_f (void *p) {
+ lssh2_cbctx_discon_t *ctx = (lssh2_cbctx_discon_t*)p;
+ return libssh2_session_disconnect_ex(
+ ctx->s,
+ ctx->reason,
+ ctx->desc,
+ ctx->lang);
+}
+
+int prne_lssh2_discon (
+ LIBSSH2_SESSION *s,
+ const int fd,
+ const int reason,
+ const char *desc,
+ const char *lang,
+ pth_event_t ev)
+{
+ lssh2_cbctx_discon_t ctx;
+ ctx.s = s;
+ ctx.reason = reason;
+ ctx.desc = desc;
+ ctx.lang = lang;
+
+ return lssh2_handle(s, fd, ev, &ctx, lssh2_disconn_f);
+}
+
+static int lssh2_ua_list_f (void *p) {
+ lssh2_cbctx_ua_cred_t *ctx = (lssh2_cbctx_ua_cred_t*)p;
+ int err;
+
+ ctx->ret = libssh2_userauth_list(ctx->s, ctx->id, ctx->id_len);
+ if (ctx->ret == NULL) {
+ err = libssh2_session_last_errno(ctx->s);
+ }
+ else {
+ err = 0;
+ }
+
+ return err;
+}
+
+const char *prne_lssh2_ua_list (
+ LIBSSH2_SESSION *s,
+ const int fd,
+ const char *username,
+ pth_event_t ev,
+ int *out_err)
+{
+ lssh2_cbctx_ua_cred_t ctx;
+ int err;
+ ctx.s = s;
+ ctx.id = username;
+ ctx.id_len = strlen(username);
+
+ err = lssh2_handle(s, fd, ev, &ctx, lssh2_ua_list_f);
+ prne_chk_assign(out_err, err);
+ return (const char*)ctx.ret;
+}
+
+static int lssh2_ua_authd (void *p) {
+ lssh2_cbctx_s_t *ctx = (lssh2_cbctx_s_t*)p;
+ return libssh2_userauth_authenticated(ctx->s);
+}
+
+int prne_lssh2_ua_authd (
+ LIBSSH2_SESSION *s,
+ const int fd,
+ pth_event_t ev)
+{
+ lssh2_cbctx_s_t ctx;
+ ctx.s = s;
+ ctx.fd = fd;
+ return lssh2_handle(s, fd, ev, &ctx, lssh2_ua_authd);
+}
+
+void prne_lssh2_cripple_session (LIBSSH2_SESSION *s) {
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wpedantic"
+ libssh2_session_callback_set(
+ s,
+ LIBSSH2_CALLBACK_SEND,
+ (void*)lssh2_crippled_send);
+ libssh2_session_callback_set(
+ s,
+ LIBSSH2_CALLBACK_RECV,
+ (void*)lssh2_crippled_recv);
+ #pragma GCC diagnostic pop
+}
+
+void prne_lssh2_free_session (LIBSSH2_SESSION *s) {
+ if (s == NULL) {
+ return;
+ }
+ prne_lssh2_cripple_session(s);
+ libssh2_session_free(s);
+}