34static inline void emit(uint8_t i,
const uint8_t *p,
size_t n)
44static void emit_auth_failure_disconnect(uint8_t i,
pc_span out)
46 static const char desc[] =
"too many authentication failures";
48 const uint32_t dl = (uint32_t)(
sizeof(desc) - 1);
49 const size_t need = 13 + dl;
56 out.
buf[o++] = (uint8_t)(reason >> 24);
57 out.
buf[o++] = (uint8_t)(reason >> 16);
58 out.
buf[o++] = (uint8_t)(reason >> 8);
59 out.
buf[o++] = (uint8_t)(reason);
60 out.
buf[o++] = (uint8_t)(dl >> 24);
61 out.
buf[o++] = (uint8_t)(dl >> 16);
62 out.
buf[o++] = (uint8_t)(dl >> 8);
63 out.
buf[o++] = (uint8_t)(dl);
64 memcpy(out.
buf + o, desc, dl);
112 emit(i, reply.
buf, n);
129 emit(i, reply.
buf, n);
132 emit(i, &newkeys, 1);
145 emit(i, reply.
buf, n);
165 emit(i, reply.
buf, n);
178 emit(i, reply.
buf, n);
179#if PC_ENABLE_SSH_ZLIB
184 ssh_comp_on_auth_success(i);
194 emit_auth_failure_disconnect(i, reply);
200#if PC_ENABLE_SSH_KEYBOARD_INTERACTIVE
210 if (pc_ssh_auth_handle_info_response(i, payload, len, reply.
buf, &n, reply.
cap) != 0)
214 emit(i, reply.
buf, n);
215#if PC_ENABLE_SSH_ZLIB
218 ssh_comp_on_auth_success(i);
225 emit_auth_failure_disconnect(i, reply);
245 emit(i, reply.
buf, n);
258 emit(i, reply.
buf, n);
289 emit(i, reply.
buf, n);
301 emit(i, reply.
buf, n);
320 emit(i, reply.
buf, 5);
321 emit(i, reply.
buf + 5, 5);
333 reply.
buf[1] = (uint8_t)(rej >> 24);
334 reply.
buf[2] = (uint8_t)(rej >> 16);
335 reply.
buf[3] = (uint8_t)(rej >> 8);
336 reply.
buf[4] = (uint8_t)(rej);
337 emit(i, reply.
buf, 5);
A scratch borrow whose acquire and release are one call each.
const pc_span & span() const
The borrowed region; empty if the arena could not satisfy it.
#define SSH_MAX_AUTH_ATTEMPTS
Maximum failed SSH authentication attempts per connection.
#define SSH_PKT_BUF_SIZE
Packet assembly buffer per SSH connection (bytes).
Shared per-dispatch scratch arena (Layer 5, session-scoped memory).
bool pc_span_ok(const pc_span &s)
True when the span refers to real storage and every write so far has fit.
int pc_ssh_auth_handle_service_request(const uint8_t *payload, size_t len, uint8_t *out, size_t *out_len, size_t cap)
Handle SSH_MSG_SERVICE_REQUEST; emit SERVICE_ACCEPT for ssh-userauth.
int pc_ssh_auth_handle_request(uint8_t i, const uint8_t *payload, size_t len, uint8_t *out, size_t *out_len, size_t cap)
Handle a USERAUTH_REQUEST end-to-end for slot i.
SSH user-authentication layer (RFC 4252).
int pc_ssh_channel_handle_window_adjust(uint8_t i, const uint8_t *payload, size_t len)
Handle SSH_MSG_CHANNEL_WINDOW_ADJUST (grows the peer window).
int pc_ssh_channel_handle_close(uint8_t i, const uint8_t *payload, size_t len, uint8_t *out, size_t *out_len, size_t cap)
Handle an inbound SSH_MSG_CHANNEL_CLOSE: route to the recipient channel, reply with EOF + CLOSE,...
int pc_ssh_channel_handle_open(uint8_t i, const uint8_t *payload, size_t len, uint8_t *out, size_t *out_len, size_t cap)
Handle SSH_MSG_CHANNEL_OPEN and emit CHANNEL_OPEN_CONFIRMATION.
int pc_ssh_channel_handle_data(uint8_t i, const uint8_t *payload, size_t len, uint8_t *out, size_t *out_len, size_t cap)
Handle SSH_MSG_CHANNEL_DATA: bounds-check, update the window, and invoke the data callback....
int ssh_global_request_handle(uint8_t i, const uint8_t *payload, size_t len, uint8_t *out, size_t *out_len, size_t cap)
Handle SSH_MSG_GLOBAL_REQUEST (RFC 4254 §4).
int pc_ssh_channel_handle_open_confirm(uint8_t i, const uint8_t *payload, size_t len)
Handle SSH_MSG_CHANNEL_OPEN_CONFIRMATION for a channel we opened (ssh -R).
int pc_ssh_channel_handle_open_failure(uint8_t i, const uint8_t *payload, size_t len)
Handle SSH_MSG_CHANNEL_OPEN_FAILURE for a channel we opened (ssh -R).
int pc_ssh_channel_handle_request(uint8_t i, const uint8_t *payload, size_t len, uint8_t *out, size_t *out_len, size_t cap)
Handle SSH_MSG_CHANNEL_REQUEST.
SSH connection protocol - multiplexed "session" channels (RFC 4254).
SSH per-connection compression owner (server-to-client zlib / zlib@openssh.com).
DH-group14-SHA256 key exchange (RFC 4253 §8 + RFC 8268).
SshPacketState ssh_pkt[MAX_SSH_CONNS]
Static packet state pool (BSS). One entry per SSH slot.
SSH binary packet protocol: framing, AES-256-CTR encryption, HMAC-SHA2-256 integrity,...
#define SSH_MSG_CHANNEL_EOF
#define SSH_MSG_CHANNEL_DATA
#define SSH_MSG_USERAUTH_INFO_RESPONSE
#define SSH_MSG_DISCONNECT
#define SSH_MSG_CHANNEL_OPEN_CONFIRM
#define SSH_MSG_UNIMPLEMENTED
#define SSH_MSG_USERAUTH_REQUEST
#define SSH_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE
#define SSH_MSG_CHANNEL_OPEN
#define SSH_MSG_CHANNEL_REQUEST
#define SSH_MSG_CHANNEL_OPEN_FAILURE
#define SSH_MSG_SERVICE_REQUEST
#define SSH_MSG_KEXDH_INIT
#define SSH_MSG_USERAUTH_SUCCESS
#define SSH_MSG_CHANNEL_CLOSE
#define SSH_MSG_USERAUTH_FAILURE
#define SSH_MSG_GLOBAL_REQUEST
#define SSH_MSG_CHANNEL_WINDOW_ADJUST
void pc_ssh_server_set_emit_cb(SshEmitCb cb)
Install the outbound-message callback.
int pc_ssh_server_dispatch(uint8_t i, uint8_t msg_type, const uint8_t *payload, size_t len)
Dispatch one decrypted inbound SSH message for slot i.
SSH message dispatcher - ties the transport, auth, and channel layers into one server state machine.
void(* SshEmitCb)(uint8_t slot, const uint8_t *payload, size_t len)
Emit one outbound SSH message payload for slot slot.
int ssh_kex_generate(uint8_t i)
Generate the server ephemeral for the negotiated KEX method (call after parse).
int ssh_extinfo_build(uint8_t *out, size_t *len, size_t cap)
Build SSH_MSG_EXT_INFO advertising server-sig-algs (RFC 8308).
int ssh_kexinit_build(uint8_t i, uint8_t *payload, size_t *len, size_t cap)
Build the server KEXINIT payload for slot i (RFC 4253 §7.1).
void ssh_newkeys_complete(uint8_t i)
Complete the NEWKEYS exchange: activate the inbound direction and advance phase.
void ssh_newkeys_sent(uint8_t i)
Activate the outbound direction after emitting our SSH_MSG_NEWKEYS.
SshSession ssh_sess[MAX_SSH_CONNS]
Static pool of SSH session state (BSS), one per SSH slot.
int ssh_kexinit_parse(uint8_t i, const uint8_t *payload, size_t len)
Parse and negotiate the client KEXINIT payload (RFC 4253 §7.1).
int ssh_kexdh_handle(uint8_t i, const uint8_t *payload, size_t len, uint8_t *reply_out, size_t *reply_len, size_t cap)
Handle KEXDH/ECDH_INIT (msg 30) end-to-end and produce the reply payload.
SSH transport-layer protocol state machine (RFC 4253).
@ SSH_PHASE_AUTH
User authentication in progress (RFC 4252).
@ SSH_PHASE_SERVICE
Awaiting SERVICE_REQUEST ("ssh-userauth").
@ SSH_PHASE_DH_INIT
Awaiting SSH_MSG_KEXDH_INIT.
uint32_t seq_no_recv
Incoming sequence number (incremented per packet).
bool ext_info_c
Client advertised ext-info-c (RFC 8308): send EXT_INFO.
SshPhase phase
Current handshake phase.
bool authed
True after successful user authentication.
uint8_t auth_failures
Failed USERAUTH_REQUESTs (brute-force limit, RFC 4252 §4).
A writable byte region: the storage, the capacity that belongs to it, and what has been produced into...
uint8_t * buf
first byte, or nullptr when the region could not be obtained
size_t cap
bytes writable at buf (0 whenever buf is nullptr)