Controlling ssh from an external C program - Code Follows

From: Jeff Anderson (jander_at_hundredacrewood.org)
Date: 10/23/04

  • Next message: Philip Le Riche: "Re: How to verify Privilege Separation is working?"
    To: secureshell@securityfocus.com
    Date: Fri, 22 Oct 2004 19:42:20 -0400
    
    

    Earlier, I had asked the list for any suggestions on how to control ssh from
    an external program without using expect. Since this seems to be a topic that
    comes up frequently, I will share what I have found (maybe this could be
    added to a FAQ?)

    I would like to thank everyone who has sent suggestions to me -

    Here are the solutions offered:

    Expect and/or like expect modules for perl/python
    Net::SSH::Perl (available from CPAN - I had actually prototyped my app in Perl
    using this. However, the final version of the app needs to be in C)

    Empty passphrase keypairs (however, does not allow for systems which no
    keypair exists)

    ssh-agent: (Same problem as above)

    Here is my final solution: I am apologizing in advance ;-)
    Suggestions for improvement welcome (as well as any case I hadn't thought of)

    /* sshopen.c */
    #include <pty.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <utmp.h>

    #define MAX 4096

    // You will need to do a close from your external calling program
    // from you main program alll you need to do is:
    // if((ssh=sshopen(argv[1], argv[2], argv[3], argv[4])) == NULL ) {
    // printf("Error opening %s\n", argv[2]);
    // exit(1);
    // }
    //
    // while(fgets(buff, MAX, ssh) != NULL ) {
    // printf("line: "); /* do something */
    // printf("%s\n",buff);
    // }

    FILE *sshopen( char *username, char *host, char *rcommand, char *pass) {

            int fd, count;
            pid_t pid;
            char buffer[MAX];
            char target[MAX];
            char tmpchar[2];
            char remotecmd[MAX];
            FILE *sshcmd;

    // Build the command options
            strcpy(target, username);
            strcat(target, "@");
            strcat(target, host);
            strcpy(remotecmd,"echo __Found__ ; ");
            strcat(remotecmd, rcommand);

            pid = forkpty(&fd, 0, 0, 0);

            if (pid == 0) {
                    execlp("ssh", "ssh", target, remotecmd, (void *)0);
                    exit(1);
            } else if (pid == -1) {
                    return (FILE *)NULL;
            } else {
                    sshcmd=fdopen(fd, "a+");
                    strcpy(buffer,"\0");
    // Read 1 char at a time and build up a string
    // This will wait forever until "__Found__" is found... Adjust as necessary
                    count=0;
                    while((fgets(tmpchar, 2, sshcmd) != NULL ) && (count++ <
    MAX)){
                            strcat(buffer, tmpchar);
                            if ((int *)strstr(buffer,"ssword:") != NULL) {
                                    fprintf(sshcmd, pass);
                                    fprintf(sshcmd, "\n");
                                    fflush(sshcmd);
                                    // reset search string
                                    strcpy(buffer,"\0");
                            }
                            if ((int *)strstr(buffer,"connecting (yes/no)?") !=
    NULL) {
                                    fprintf (sshcmd,"yes\n");
                                    fflush (sshcmd);
                                    // reset search string
                                    strcpy(buffer,"\0");
                            }
                            if ((int *)strstr(buffer,"Enter passphrase") != NULL)
    {
                                    fprintf(sshcmd, pass);
                                    fprintf(sshcmd, "\n");
                                    fflush(sshcmd);
                                    // reset search string
                                    strcpy(buffer,"\0");
                            }
                            if ((int *)strstr(buffer,"No route to host") != NULL)
    {
                                    fclose(sshcmd);
                                    return (FILE *)NULL;
                            }
                            if ((int *)strstr(buffer,"Permission denied") != NULL)
    {
                                    fclose(sshcmd);
                                    return (FILE *)NULL;
                            }
                            if ((int *)strstr(buffer,"Connection refused") !=
    NULL) {
                                    fclose(sshcmd);
                                    return (FILE *)NULL;
                            }
                            if ((int *)strstr(buffer,"__Found__") != NULL) {
                                    printf("found it\n");
                                    return (FILE *)sshcmd;
                            }
                    }
            }
    }

    =====================================================
    Jeff Anderson


  • Next message: Philip Le Riche: "Re: How to verify Privilege Separation is working?"