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

[help] how to develop multithread sshd


Dear Developers,

Our company is currently using libssh for developing server side softwares.
Thanks for your wonderful work.

Here 's problem we met. When we are trying to develop multithread ssh server
to serve clients (each client has its serving thread), the server only
responses to the newly added client ! ie. the old connection is not
responsing anymore after new client joins. And after the newly added client
quits, the old connection recover again !!!

We search through the internet but find little help. Could you please give
me a hint?.

Here's the sshd like code we use:


#include <libssh/libssh.h>
#include <libssh/server.h>
#include <argp.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <string>
#include <iostream>
#include <boost/thread.hpp>

static int auth_password(char *user, char *password){
    if(strcmp(user,"aris"))
        return 0;
    if(strcmp(password,"lala"))
        return 0;
    return 1; // authenticated
}

class Console
{
public:
    explicit Console(const std::string addr,
                     const std::string port)

:addr_(addr),port_(port),SSH_HOST_DSA_KEY_PATH_("./ssh_host_dsa_key"),SSH_HOST_RSA_KEY_PATH_("./ssh_host_rsa_key"){}


~Console(){};


private:
    Console(const Console&);
    Console& operator=(const Console&);

private:
    std::string addr_;
    std::string port_;
    std::string SSH_HOST_DSA_KEY_PATH_;
    std::string SSH_HOST_RSA_KEY_PATH_;
    //ssh_session session;
    ssh_bind sshbind;
    //ssh_message message;
    //ssh_channel chan;
    //int i;

public:
    int32_t Start() {
        sshbind=ssh_bind_new();

        ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY,
SSH_HOST_DSA_KEY_PATH_.c_str());
        ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY,
SSH_HOST_RSA_KEY_PATH_.c_str());
        ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR,
port_.c_str());
        //ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY,
arg);
        //ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR,
"3");
        ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR,
addr_.c_str());

        if (ssh_bind_listen(sshbind) < 0) {
            std::cout << "ERROR: listening to socket: " <<
ssh_get_error(sshbind) << std::endl;

ssh_bind_free(sshbind);

            return
-1;

}

        for(;;)
{

            ssh_session
session=ssh_new();
            if (ssh_bind_accept(sshbind,session) != SSH_ERROR) {
                // every client will use a thread running Session(...)

                boost::thread *t = new
boost::thread(boost::bind(&Console::Session, this, session));

sleep(10);

            }else
{

                std::cout << "ERROR: accepting a connection: " <<
ssh_get_error(sshbind) << std::endl;

ssh_bind_free(sshbind);


ssh_free(session);

                return
-1;


}


}


}


    int32_t Session(ssh_session newSession) {
        ssh_session session = newSession;
        ssh_channel chan = 0;
        ssh_message message;
        int auth = 0;
        int sftp = 0;
        if (ssh_handle_key_exchange(session)) {
            std::cout << "ERROR: ssh_handle_key_exchange: " <<
ssh_get_error(session) << std::endl;
            return
-1;


}

        do
{


message=ssh_message_get(session);


if(!message)


break;


switch(ssh_message_type(message)){

            case
SSH_REQUEST_AUTH:


switch(ssh_message_subtype(message)){

                case
SSH_AUTH_METHOD_PASSWORD:

                    std::cout << "User " << ssh_message_auth_user(message)
<< " wants to auth with pass " <<
                        ssh_message_auth_password(message) <<
std::endl;

if(auth_password(ssh_message_auth_user(message),


ssh_message_auth_password(message))){

auth=1;


ssh_message_auth_reply_success(message,0);


break;


}

                    // not authenticated, send default
message
                case
SSH_AUTH_METHOD_NONE:


default:


ssh_message_auth_set_methods(message,SSH_AUTH_METHOD_PASSWORD);


ssh_message_reply_default(message);


break;


}


break;


default:


ssh_message_reply_default(message);


}


ssh_message_free(message);

        } while
(!auth);


if(!auth){

            std::cout << "ERROR: auth error: " << ssh_get_error(session) <<
std::endl;

ssh_disconnect(session);

            return
-1;


}

        do
{


message=ssh_message_get(session);


if(message){


switch(ssh_message_type(message)){

                case
SSH_REQUEST_CHANNEL_OPEN:


if(ssh_message_subtype(message)==SSH_CHANNEL_SESSION){


chan=ssh_message_channel_request_open_reply_accept(message);


break;


}


default:


ssh_message_reply_default(message);


}


ssh_message_free(message);


}

        } while(message &&
!chan);


if(!chan){

            std::cout << "ERROR: " << ssh_get_error(session) <<
std::endl;
            return
-1;


}

        do
{


message=ssh_message_get(session);

            if(message && ssh_message_type(message)==SSH_REQUEST_CHANNEL
&&

ssh_message_subtype(message)==SSH_CHANNEL_REQUEST_SHELL){

                //
if(!strcmp(ssh_message_channel_request_subsystem(message),"sftp")){


sftp=1;


ssh_message_channel_request_reply_success(message);


break;

                //
}


}


if(!sftp){


ssh_message_reply_default(message);


}

            ssh_message_free(message);
        } while (message && !sftp);
        if(!sftp){
            std::cout << "ERROR: " << ssh_get_error(session) << std::endl;
            return -1;
        }
        printf("it works !\n");
        char buf[2048];
        int i = 0;
        ssh_channel_write(chan, "#:", 2);
        do{
            i = ssh_channel_read(chan, buf, 2048, 0);
            if (i > 0) {
                ssh_channel_write(chan, buf, i);
                if (buf[0] == 'q') {
                    break;
                }
                if (buf[0] == '\r'|| buf[i] == '\r')
                    ssh_channel_write(chan, "\r\nabcd\r\n#:", 10);
                if (write(1,buf,i) < 0) {
                    printf("error writing to buffer\n");
                    return 1;
                }
            }
        } while (i > 0);
        ssh_disconnect(session);
        ssh_channel_close(chan); //?
        ssh_channel_free(chan); //?
        ssh_free(session);
        return 0;
    }
    int32_t Stop()
    {
        ssh_finalize();
    }
};

int main()
{
    Console c("127.0.0.1", "1200");
    c.Start();

    return 0;
}


Thanks & Best Regards,
FY

Follow-Ups:
Re: [help] how to develop multithread sshdAris Adamantiadis <aris@xxxxxxxxxxxx>
Archive administrator: postmaster@lists.cynapses.org