Search code examples
c++bashsshlibssh

How to execute bash script with sudo password needed via libssh


I need to execute script on remote computer with libssh. Trying to follow this tutorial, but can't understand how to send sudo password

That's my code, sudo password is hard coded for now, but I'll change that when I figure out how to pass the password.

When executing the code, nothing happens

int shell_session(ssh_session session) {
    std::string cmd1 = {"sudo -S bash ./tmp/update_project"};
    std::string sudo_password = {"87654321"};
    ssh_channel channel;
    int rc;
    channel = ssh_channel_new(session);
    if (channel == NULL)
        return SSH_ERROR;
    rc = ssh_channel_open_session(channel);
    if (rc != SSH_OK)
    {
        ssh_channel_free(channel);
        return rc;
    }

    rc = ssh_channel_request_shell(channel);
    if (rc != SSH_OK) return rc;

    rc = ssh_channel_request_exec(channel, cmd1.c_str());
    if (!(rc > 0))
        return SSH_ERROR;

    rc = ssh_channel_request_exec(channel, sudo_password.c_str());
    if (!(rc > 0))
        return SSH_ERROR;

    ssh_channel_close(channel);
    ssh_channel_send_eof(channel);
    ssh_channel_free(channel);
    return SSH_OK;
}

-----------------EDIT:

Right now I'm trying to do it with interactive session like this but it doesn't works

int shell_session(ssh_session session) {
    std::string cmd1 = {"sudo bash /tmp/update_project"};
    std::string sudo_password = {"87654321"};
    ssh_channel channel;
    int rc;
    channel = ssh_channel_new(session);
    if (channel == NULL)
        return SSH_ERROR;
    rc = ssh_channel_open_session(channel);
    if (rc != SSH_OK)
    {
        ssh_channel_free(channel);
        return rc;
    }

    rc = ssh_channel_request_pty(channel);
    if (rc != SSH_OK) return rc;
    rc = ssh_channel_change_pty_size(channel, 80, 24);
    if (rc != SSH_OK) return rc;
    rc = ssh_channel_request_shell(channel);
    if (rc != SSH_OK) return rc;

    char buffer[256];
    int nbytes, nwritten;
    std::vector<std::string> cmds {"sudo bash /tmp/update_project",
                                   "87654321"};
    std::vector<int> cmd_szs {sizeof(cmds[0]), sizeof(cmds[1])};
    while (ssh_channel_is_open(channel) &&
           !ssh_channel_is_eof(channel))
    {
        struct timeval timeout;
        ssh_channel in_channels[2], out_channels[2];
        fd_set fds;
        int maxfd;
        timeout.tv_sec = 30;
        timeout.tv_usec = 0;
        in_channels[0] = channel;
        in_channels[1] = NULL;
        FD_ZERO(&fds);
        FD_SET(0, &fds);
        FD_SET(ssh_get_fd(session), &fds);
        maxfd = ssh_get_fd(session) + 1;
        ssh_select(in_channels, out_channels, maxfd, &fds, &timeout);
        if (out_channels[0] != NULL)
        {
            nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
            if (nbytes < 0) return SSH_ERROR;
            if (nbytes > 0)
            {
                nwritten = write(1, buffer, nbytes);
                if (nwritten != nbytes) return SSH_ERROR;
            }
        }
        nwritten = ssh_channel_write(channel, &cmds[0], cmd_szs[0]);
        nwritten = ssh_channel_write(channel, &cmds[1], cmd_szs[1]);
    }

    ssh_channel_close(channel);
    ssh_channel_send_eof(channel);
    ssh_channel_free(channel);
    return SSH_OK;
}

Solution

  • On my side I have to append the escape character (\n) to the command strings for the command to actually execute. This allowed me to ssh into a PDU that is running peta linux.

    You should also try logging in as sudo instead of doing it through the command line like in linux. To do this just set the sudo username and password using the ssh_options_set as such

        ssh_options_set(m_session, SSH_OPTIONS_HOST, m_IP.c_str());
        ssh_options_set(m_session, SSH_OPTIONS_USER, m_username.c_str()); // m_username = sudo username
        ssh_options_set(m_session, SSH_OPTIONS_PORT_STR, &m_port);
        int rc = ssh_userauth_password(m_session, NULL, m_password.c_str()); //m_password = sudo password
    

    This will allow you to logging as sudo directly. Then send commands using the ssh_channel_write() method as such:

    std::string command = "ls -alh\n"  //example command note that I included \n 
    int rc = ssh_channel_write(channel, command.c_str(), command.length());
    

    This should solve your issue.