0

I want to automate the mounting of a sshfs connection inside my C program (meant for linux) using only password for ssh. (I don't want to use public/private keys.)

It seems i could do it with libexpect. Based on this thread it seems possible to use libexpect to give the password when required. For example, i made a successful test program that creates a dir with sudo mkdir test and then provide the user password with libexpect. So that pipe seems really to be bidirectional. Thou, with sshfs and my simple function below, it doesn't work: i do have a sshfs mount produced by it, but it doesn't work and i can't see the files.

enum{ASKCONTINUE,ASKPWD};

int sshfs_connect (char data[10][200], char ip[]) {

    char commandline[300];
    sprintf(commandline,"sshfs %s@%s:%s %s -p %s -o ServerAliveInterval=15",
            data[4],ip,data[6],data[5],data[7]);

    bool shouldBreak = false;

    FILE* fp = exp_popen(commandline);

    while(shouldBreak == false)
    {
        switch(exp_fexpectl(fp,
              //if asked for continuing (authenticity can't be established)
              exp_glob, "ontinue connecting (yes/no)?", ASKCONTINUE, 
              //if asked for pwd 
              exp_glob, "s password:", ASKPWD,  
              exp_end))  //
        {
            case ASKCONTINUE:
                printf("asked continue? !\n");
                fprintf(fp,"%s\n","yes");
                break;

            case ASKPWD:
                printf("asked pwd ! sending pwd: %s\n",data[8]);
                fprintf(fp,"%s\n",data[8]);
                shouldBreak = true;
                break;

            case EXP_TIMEOUT:
                shouldBreak = true;
                break;

            case EXP_EOF:
                shouldBreak = true;
                break;
        }
    }

    fclose(fp);
    return 0;

}
  • Would you mind elaborating on why you don't want to use keys? If you still want to protect the resource with a password, just encrypt the key and prompt for the key decryption password. Not only will you get better security, but the task would be much simpler as you could directly use libssl to decrypt the key. You could also implement a ssh-agent to sign the challenge keeping the decrypted key off the disk. – Geoffrey Mar 04 '18 at 06:17
  • You're right about the fact i could use keys and passphrase and that'd be better security. Actually, i'm going to do that. But, it doesn't change much about my problem since i'll still have to provide the passphrase when required. I don't know libssh and wanted to spare time struggling with it. Plus what i want to do is sshfs, with i think is related to libfuse also. So, even if it's ugly, i was planning to connect and deconnect sshfs just bash-ing. Btw, about security, i want a good user not to be able to ssh on the computer to that server when the program's not running. – Rafi's Revenge Mar 04 '18 at 10:07
  • To be more precise, the sshfs mount resulting error is "Transport endpoint is not connected". I've tried to fix it with the hint [here](http://slopjong.de/2013/04/26/sshfs-transport-endpoint-is-not-connected/) with no success. That sshfs mount works well when i type it in a terminal.. so that should be a libexpect problem in my code. – Rafi's Revenge Mar 04 '18 at 11:06
  • Why not use Expect directly since it's much easier? –  Mar 04 '18 at 12:30
  • If you want to only allow SCP/SFTP on the account see [MySecureShell](https://mysecureshell.readthedocs.io/en/latest/) – Geoffrey Mar 05 '18 at 03:01
  • @Emily : i would if i knew how to do it. I've found tons of examples on how to use expect from a bash script. But my connection data are in my C program, so i guess i can't use a bash script. – Rafi's Revenge Mar 05 '18 at 21:31

1 Answers1

1

It seems that expect (even the tcl version) cannot be used with sshfs, probably because the spawned process does not have a controlling tty and so the command tries to get the password from the user by other means, e.g. using a gui popup.

What works is adding the option -o password_stdin to ask sshfs to read the password from stdin. It does this without writing a prompt, so libexpect is a bit heavyweight, but nonetheless this should work for you: send the password and wait for eof (which would probably be within the default timeout of 10 seconds).

ssh = exp_popen("sshfs -o password_stdin user@host:/dir /mntpoint");
if(ssh==NULL)fatal("fail to spawn");
fprintf(ssh, "%s\n", password);
switch(exp_fexpectl(ssh,exp_end)) {
case EXP_EOF:
    break;  // ok
case EXP_TIMEOUT:
    break;  // fail
default:
    break;  // fail
}
meuh
  • 11,500
  • 2
  • 29
  • 45
  • It works ! Thx ! That's too bad expect can't really talk with sshfs. It's then not possible to catch the rare case when i have to tell sshfs to continue (when IP changes or..). Anyway, i know this solution is not the best one (i'll dig into libssl and libfuse if i have the time) but at least, it works. – Rafi's Revenge Mar 05 '18 at 21:43
  • 1
    Answering my own comment: it seems possible to add the options `-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no` to the ssh command to prevent that rare changed IP question. – Rafi's Revenge Mar 06 '18 at 08:07