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

libssh questions


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

Follow-Ups:
Re: libssh questionsVishwanathan Chandru <vishwanathanc@xxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org