On 5/17/23 05:04, The Geek on Skates wrote:
Good evening(or afternoon, or morning), :)
I've been on something of a quest, a project that (at the moment) is
just for fun, but maybe not exclusively a game thing. I would like to
create something like SSH Tron <http://sshtron.zachlatta.com/>; the
workflow is simple:
1. ssh sshtron.zachlatta.com <http://sshtron.zachlatta.com>
2. You play the game
3. You get disconnected
No room for shenanigans. No passing commands, no CTRL-C or CTRL-Z to
kill the program (you do that, you get disconnected). Even so, I'm
shocked it hasn't been hacked into oblivion. 😄
But unfortunately, it's written in Go (a language I don't know and
don't care to learn) and some library that's just for Go. Now I'm an
experienced C/C++ programmer - I'm all too familiar with things like
buffer overflows, double-frees, dereferencing NULL pointers etc. but
all I really know about SSH is basic stuff like how to configure sshd,
how to generate keys and stuff like that. I also know a bunch of
other languages, but since C is my goto (see what I did there? 😄) I
started playing with libssh. I'm trying to see if I can figure out
how to set up a program to receive incoming connections, send data to
the client (the default ssh "command"), receive data from the client
and disconnect. I think I've got it connecting (on localhost) but I'm
a bit stuck on the reading/writing. ssh_channel_new is failing,
ssh_last_error or whatever it is isn't giving me anything... and there
are no tutorials.
Correct. We miss some good tutorials on writing servers. We have some
examples in tests though, which can already help you to get started:
https://gitlab.com/libssh/libssh-mirror/-/tree/master/tests/pkd
https://gitlab.com/libssh/libssh-mirror/-/tree/master/tests/server/test_server
Another example of server implementation is tmate-ssh-server, which is
probably closest what you want -- no authentication, just running stuff:
https://github.com/tmate-io/tmate-ssh-server/
So what I'm asking for - if this is okay - is a high-level walkthrough
of the process. I'm not asking you to write my program for me (people
who do that drive me nuts too 😄) but I'd like to get some idea of the
workflow. Like right now what I have is:
* Some forum posts say you need to call ssh_init(), so I started there.
* Then I created a "bind" structure using ssh_bind_new()
* Then I used ssh_bind_options_set to set the host name, port, and
private key path
* I also used ssh_set_blocking (with 0) because a game like Tron
shouldn't wait for the user to press Enter (like getchar())
* Then I used ssh_new() to create a new session structure
* Then ssh_bind_listen. At this point, my program waits for a new
connection. Then I do ssh me@localhost -p 12345 or whatever.
This seems to work.
* Then ssh_bind_accept. It seems to accept my connection and then
immediately disconnect. So that's progress.
* With NULL-checks and error-checks and all that every step of the
way, cuz this is C and that's how we roll. 😄
And here's where I am stuck. Forum posts suggest I need to create a
"channel" with ssh_channel_new; from there, theoretically, the
ssh_channel_write and ssh_channel_read do the reading/writing. Then
of course are all the close and free functions to clean up at the
end. And of course to support multiple users it would probably have
to call fork() and all that... but I'm nowhere near that point.
ssh_channel_new fails. I tried using session->channel, but apparently
that is a pointer to an "incomplete" type (an error I've never seen
before and will be researching this evening after work 😄)... so...
stalemate.
Any ideas? What am I missing here? At this point, my best guess is
that there another step required to "complete" the session's channel
pointer, some secondary initialization involved that isn't clear from
a long list of function names. 😄 Any ideas would be greatly
appreciated. Thanks and have a great day!
We currently recommend creation of callback based servers. Previously,
there was some other way to do that, but yeah ... no documentation.
For callback based server, you define what functions are called when
user/clients makes some progress in the SSH protocol: authentication,
channel request, shell request, ... yes, these are requested by the
client so you can not just start them from the server side when you
think it is the right time. They are set here:
https://gitlab.com/libssh/libssh-mirror/-/blob/master/tests/server/test_server/default_cb.c#L767
You need to provide some authentication functions, to let the user in
and when session is requested, the callback
channel_open_request_session_function is called.
Then we have bunch of channel callbacks, which handle the terminal and
IO for you:
https://gitlab.com/libssh/libssh-mirror/-/blob/master/tests/server/test_server/default_cb.c#L795
I think this should give you some idea and help you started.
If you would be willing to write a couple of paragraphs about writing
ssh server, we would be very happy to accept them into the tutorial, as
this is quite common topic, but nobody picked this up yet.
Regards,
--
Jakub Jelen
Crypto Team, Security Engineering
Red Hat, Inc.