[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: libssh questions


Hello,

I am not sure what's the follow up process. Requesting some pointers or
suggestions or answers for these question(s).

Thanks,
Vish

On Mon, Nov 9, 2020 at 8:12 AM Vishwanathan Chandru <vishwanathanc@xxxxxxxxx>
wrote:

> Hello,
>
> My name is Vish and I am a newbie to socket programming in general. This
> library was very easy to understand and made my life easier as
> I got curious about secure communications, so would like to thank the
> developers.
>
> I am trying to develop a peer to peer application using libssh (for
> learning sake). From the documentation it seems like using
> ssh_event_dopoll seems to be the way to go. There's also some aspect of
> non-secure communication with a local client and ssh_event_dopoll
> handles it fine.
>
> Here's what I am came up with for the server implementation:
>
> int process_call_back(socket_t fd, int revents, void* userdata) {
>     if(revents & POLLIN) {
>             // non libssh socket
>             if(fd == normal_listener_socket_fd) {
>                   // accept and all.
>             }
>             if(fd == ssh_listener_socket) {
>                   // allocate session
>                   sd = accept(fd...)
>                   int rc = fcntl(sd, F_SETFL, O_NONBLOCK);
>                   ssh_bind_accept_fd(sshbind, session, new_sd);
>                   // one of these callbacks set the channel_data_function
> to keep track of data coming from ssh client via channels.
>                   ssh_callbacks_init(&cb);
>                   ssh_set_server_callbacks(session, &cb);
>                   ssh_callbacks_init(&scb);
>                   ssh_set_callbacks(session, &scb);
>                   if (ssh_handle_key_exchange(session)) {
>                     printf("ssh_handle_key_exchange: %s\n",
> ssh_get_error(session));
>                   } else {
>                     ssh_set_auth_methods(session,SSH_AUTH_METHOD_PASSWORD);
>                     ssh_event_add_session(mainloop, session);
>                   }
>             }
>             else if(is_non_ssh_socket(fd)) {
>                   recv(fd)
>                   send(fd...)
>             }
>     }
> }
>
> int main() {
>      // setup boilerplate
>     if (ssh_bind_listen(sshbind) < 0) {
>                 printf("Error listening to socket: %s\n",
> ssh_get_error(sshbind));
>                 return 1;
>     }
>    ssh_listener_socket = ssh_bind_get_fd(sshbind);
>    ssh_event_add_fd(mainloop, ssh_listener_socket, POLLIN,
> process_call_back, NULL);
>    ssh_event_add_fd(mainloop, ssh_listener_socket, POLLPRI,
> process_call_back, NULL);
>    do {
>         if(ssh_event_dopoll(mainloop, -1)) == SSH_ERROR) {
>              printf("\n something went wrong with errno %d ", errno);
> for(auto session : sessions) {
> // check if session is alive
> if(ssh_is_connected(session)) {
> continue;
> }
> else {
> auto emsg = ssh_get_error(session);
>                     auto ecode = ssh_get_error_code(session);
> // this session has gone to hell, take it out
> ssh_event_remove_session(mainloop, session);
> // more possible cleanup here.
> }
> }
>         }
>    } while (true)
> }
>
> Now this thing works. I was hoping to use incoming_connections callback on
> ssh_bind to accept incoming ssh connections but it didnt
> seem to work out. Is this the best way to achieve this?
>
> Second question is about handling timeouts and connection closures. I came
> across this
> thread https://www.libssh.org/archive/libssh/2019-03/0000011.html, which
> answered some questions. So I came up with do while loop
> style error handling, if ssh_event_dopoll returns error, loop through all
> the active sessions and remove the bad session using
> ssh_is_connected. Is there a better way to acheive the error handling?
>
> Third question is I also want to add the client part of the code (since
> this a peer to peer application). I understand that there is non blocking
> usage of ssh_connect.
> From what I can read in the documentation, I will have to call ssh_connect
> if SSH_AGAIN is returned and until it returns SSH_OK, I cannot
> proceed with the authentication step. Can I do something like this on a
> separate thread (the previous code snippet will be in the server thread)?
>
> ssh_session session;
> int session_fd = -1;
> int connected = 0;
>
> int process_call_back(socket_t fd, int revents, void* userdata) {
>     if(revents & POLLOUT) {
> if(fd == session_fd) {
> int optval = 0;
> int optlen = sizeof(optval);
> int rc = getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, optlen);
> if (optval == 0 ) {
> rc = ssh_connect(session);
> }
> if (rc == SSH_OK) {
> // remove the fd, because session callbacks will be added.
> ssh_event_remove_fd(mainloop, fd);
> // enable the blocking mode otherwise we have to call authentication
> // until it returns success.
> ssh_is_blocking(session, 1);
> // authenticate
> ....
> // set the channels and associate callbacks
> ....
> // add the session to event loop.
> ssh_event_add_session(mainloop, session);
> connected = 1;
> }
> }
> }
> }
>
>
> int main() {
> // boiler plate
> ....
> session = ssh_new();
> ssh_set_blocking(session, 0);
> int rc = ssh_connect(session);
> if (rc == SSH_ERROR) {
> return 1;
> }
> if (rc == SSH_AGAIN) {
> session_fd = ssh_get_fd(session);
> // add POLLOUT for eastablishing connection
> ssh_event_add_fd(mainloop, session_fd, POLLOUT, process_call_back, NULL);
> }
> do {
> if (ssh_event_dopoll(mainloop, -1) == SSH_ERROR) {
> break;
> }
> } while (!connected);
> // exchange buffers with server via channel read/write
> ...
> }
>
> Thanks and Best regards,
> Vish
>

References:
libssh questionsVishwanathan Chandru <vishwanathanc@xxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org