Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ Acton server, to OpenSSH `sshd`, or be driven by the OpenSSH `ssh` client.

## Requirements

This package depends on a fork of libssh that adds the hooks needed for an
external event loop (`ssh_session_handle_poll`, `ssh_channel_read_buffered`,
server build) and builds with Zig. The dependency is declared in
[`Build.act`](Build.act); point it at your checkout of the fork.
This package builds libssh from the unmodified upstream release tarball; the
Zig build wrapper in [`deps/libssh`](deps/libssh) owns the build configuration
and compiles in the hooks needed for an external event loop
(`ssh_session_handle_poll`, `ssh_channel_read_buffered`) as extra sources
([`deps/libssh/src/libssh_acton.c`](deps/libssh/src/libssh_acton.c)) — no fork
of libssh is required. The dependency is declared in [`Build.act`](Build.act).

libssh and its crypto backend (mbedtls) run on the C library heap with their
own ownership; only libuv and Acton objects live on the GC heap. See the
Expand Down
48 changes: 44 additions & 4 deletions deps/libssh/build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,18 @@ pub fn build(b: *std.Build) void {
},
.{
.PACKAGE = "libssh",
.VERSION = "0.11.0",
.VERSION = "0.12.0",
.PROJECT_NAME = "libssh",
.PROJECT_VERSION = "0.11.0",
.PROJECT_VERSION = "0.12.0",
.SYSCONFDIR = "/etc",
.BINARYDIR = "/usr/bin",
.SOURCEDIR = ".",
.GLOBAL_CONF_DIR = "/etc/ssh",
.USR_GLOBAL_CONF_DIR = "/usr/etc/ssh",
.GLOBAL_BIND_CONFIG = "/etc/ssh/libssh_server_config",
.USR_GLOBAL_BIND_CONFIG = "/usr/etc/ssh/libssh_server_config",
.GLOBAL_CLIENT_CONFIG = "/etc/ssh/ssh_config",
.USR_GLOBAL_CLIENT_CONFIG = "/usr/etc/ssh/ssh_config",
.HAVE_ARGP_H = true,
.HAVE_ARPA_INET_H = true,
.HAVE_IFADDRS_H = (t.os.tag != .windows),
Expand Down Expand Up @@ -116,6 +120,18 @@ pub fn build(b: *std.Build) void {
.HAVE_LIBMBEDCRYPTO = true,
.HAVE_PTHREAD = has_pthread,
.HAVE_CMOCKA = false,
.HAVE_LIBFIDO2 = false,

// No native curve25519 in either backend config: use the bundled
// reference implementation (external/curve25519_ref.c +
// curve25519_fallback.c). Likewise ML-KEM uses the bundled
// libcrux code (mlkem_native.c) rather than a crypto backend.
.HAVE_MBEDTLS_CURVE25519 = false,
.HAVE_GCRYPT_CURVE25519 = false,
.HAVE_GCRYPT_MLKEM = false,
.HAVE_OPENSSL_MLKEM = false,
.HAVE_MLKEM1024 = false,
.HAVE_MEMSET_EXPLICIT = false,

.HAVE_GCC_THREAD_LOCAL_STORAGE = false,
.HAVE_MSC_THREAD_LOCAL_STORAGE = false,
Expand All @@ -135,6 +151,7 @@ pub fn build(b: *std.Build) void {
.HAVE_GCC_BOUNDED_ATTRIBUTE = false,
.WITH_GSSAPI = false,
.WITH_ZLIB = false,
.WITH_FIDO2 = false,
.WITH_SFTP = false,
.WITH_SERVER = with_server,
.WITH_EXEC = true,
Expand All @@ -158,7 +175,7 @@ pub fn build(b: *std.Build) void {
.include_path = "libssh/libssh_version.h",
}, .{
.libssh_VERSION_MAJOR = 0,
.libssh_VERSION_MINOR = 11,
.libssh_VERSION_MINOR = 12,
.libssh_VERSION_PATCH = 0,
});

Expand Down Expand Up @@ -194,6 +211,8 @@ pub fn build(b: *std.Build) void {
"src/ecdh.c",
"src/error.c",
"src/getpass.c",
"src/gzip.c",
"src/hybrid_mlkem.c",
"src/init.c",
"src/kdf.c",
"src/kex.c",
Expand All @@ -204,16 +223,19 @@ pub fn build(b: *std.Build) void {
"src/match.c",
"src/messages.c",
"src/misc.c",
"src/mlkem.c",
"src/options.c",
"src/packet.c",
"src/packet_cb.c",
"src/packet_crypt.c",
"src/pcap.c",
"src/pki.c",
"src/pki_container_openssh.c",
"src/pki_context.c",
"src/poll.c",
"src/session.c",
"src/scp.c",
"src/sntrup761.c",
"src/socket.c",
"src/string.c",
"src/threads.c",
Expand Down Expand Up @@ -259,15 +281,32 @@ pub fn build(b: *std.Build) void {
"src/external/chacha.c",
"src/external/poly1305.c",
"src/chachapoly.c",
"src/external/curve25519_ref.c",
"src/external/sntrup761.c",
"src/dh-gex.c",
// curve25519: no backend-native implementation is enabled
// (HAVE_MBEDTLS_CURVE25519=false), so use the bundled reference code.
"src/external/curve25519_ref.c",
"src/curve25519_fallback.c",
// ML-KEM: no backend support (HAVE_MLKEM1024=false), so use the
// bundled libcrux implementation.
"src/mlkem_native.c",
"src/external/libcrux_mlkem768_sha3.c",
}) catch unreachable;

lib.root_module.addCSourceFiles(.{
.root = upstream.path("."),
.files = source_files.items,
.flags = flags.items,
});
// Acton's event-loop hooks (ssh_session_handle_poll,
// ssh_channel_read_buffered): new functions on top of the unmodified
// upstream sources, kept local to this wrapper instead of patching the
// tarball. Declarations live in include/libssh/libssh_acton.h.
lib.root_module.addCSourceFiles(.{
.files = &.{"src/libssh_acton.c"},
.flags = flags.items,
});
lib.root_module.addIncludePath(b.path("include"));
lib.root_module.addIncludePath(upstream.path("include"));
// mbedtls headers only — the objects are linked via Acton's base at the final
// executable link (see top-of-file note). acton_sysdeps points at the
Expand All @@ -279,6 +318,7 @@ pub fn build(b: *std.Build) void {

lib.installHeadersDirectory(upstream.path("include/libssh"), "libssh", .{});
lib.installHeader(version_header.getOutputFile(), "libssh/libssh_version.h");
lib.installHeader(b.path("include/libssh/libssh_acton.h"), "libssh/libssh_acton.h");

b.installArtifact(lib);
}
15 changes: 9 additions & 6 deletions deps/libssh/build.zig.zon
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
.{
.name = .libssh,
.version = "0.11.0",
.version = "0.12.0",
.fingerprint = 0xda35516053c953ab,
.minimum_zig_version = "0.16.0",
.dependencies = .{
// libssh as a pure-source dependency: the actonlang/libssh "acton"
// branch carries no build.zig (only a minimal set of source patches);
// this wrapper owns the build configuration. Pinned by commit.
// libssh as a pure-source dependency: the unmodified upstream release
// tarball. This wrapper owns the build configuration, and the Acton
// event-loop hooks are added as extra sources (src/libssh_acton.c)
// rather than patches, so no fork of libssh is needed.
.libssh_upstream = .{
.url = "https://github.com/actonlang/libssh/archive/82c6ffcea9ab3ae2b61c082d6b6900899af8b655.tar.gz",
.hash = "N-V-__8AAOhETABotmEwFsdxaIh9QrKb55e9pRhi4IOlEugd",
.url = "https://git.libssh.org/projects/libssh.git/snapshot/libssh-0.12.0.tar.gz",
.hash = "N-V-__8AAJQ3YACvCqTRvZk5i48MCnXp0JPImYjVIjw_fEG2",
.lazy = false,
},
// No mbedtls dependency here: libssh compiles against the toolchain's
Expand All @@ -19,5 +20,7 @@
.paths = .{
"build.zig",
"build.zig.zon",
"include",
"src",
},
}
31 changes: 31 additions & 0 deletions deps/libssh/include/libssh/libssh_acton.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Acton additions to the libssh API.
*
* These functions are NOT part of upstream libssh. They are compiled into
* the library by this wrapper's build.zig (src/libssh_acton.c) on top of the
* unmodified upstream source tarball pinned in build.zig.zon. They provide
* the hooks Acton's external (libuv) event loop needs:
*
* - ssh_session_handle_poll: feed poll(2)-style revents for the session's
* fd into libssh's internal poll machinery, so libssh makes progress
* without owning the event loop.
* - ssh_channel_read_buffered: drain data libssh has already buffered for
* a channel without touching the socket, for callback-driven reads.
*/
#ifndef LIBSSH_ACTON_H
#define LIBSSH_ACTON_H

#include <libssh/libssh.h>

#ifdef __cplusplus
extern "C" {
#endif

LIBSSH_API int ssh_session_handle_poll(ssh_session session, int revents);
LIBSSH_API int ssh_channel_read_buffered(ssh_channel channel, void *dest,
uint32_t count, int is_stderr);

#ifdef __cplusplus
}
#endif

#endif /* LIBSSH_ACTON_H */
Loading