123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 |
- #if HAVE_CONFIG_H
- #include "config.h"
- #endif
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <sys/ioctl.h>
- #include <sys/select.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <signal.h>
- #if HAVE_TERMIOS_H
- #include <termios.h>
- #endif
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- enum program_return_codes {
- RETURN_NOERROR,
- RETURN_INVALID_ARGUMENTS,
- RETURN_CONFLICTING_ARGUMENTS,
- RETURN_RUNTIME_ERROR,
- RETURN_PARSE_ERRROR,
- RETURN_INCORRECT_PASSWORD,
- RETURN_HOST_KEY_UNKNOWN,
- RETURN_HOST_KEY_CHANGED,
- };
- #ifndef HAVE_POSIX_OPENPT
- int
- posix_openpt(int flags)
- {
- return open("/dev/ptmx", flags);
- }
- #endif
- int runprogram( int argc, char *argv[] );
- struct {
- enum { PWT_STDIN, PWT_FILE, PWT_FD, PWT_PASS } pwtype;
- union {
- const char *filename;
- int fd;
- const char *password;
- } pwsrc;
- const char *pwprompt;
- int verbose;
- } args;
- static void show_help()
- {
- printf("Usage: " PACKAGE_NAME " [-f|-d|-p|-e] [-hV] command parameters\n"
- " -f filename Take password to use from file\n"
- " -d number Use number as file descriptor for getting password\n"
- " -p password Provide password as argument (security unwise)\n"
- " -e Password is passed as env-var \"SSHPASS\"\n"
- " With no parameters - password will be taken from stdin\n\n"
- " -P prompt Which string should sshpass search for to detect a password prompt\n"
- " -v Be verbose about what you're doing\n"
- " -h Show help (this screen)\n"
- " -V Print version information\n"
- "At most one of -f, -d, -p or -e should be used\n");
- }
- static int parse_options( int argc, char *argv[] )
- {
- int error=-1;
- int opt;
-
- args.pwtype=PWT_STDIN;
- args.pwsrc.fd=0;
- #define VIRGIN_PWTYPE if( args.pwtype!=PWT_STDIN ) { \
- fprintf(stderr, "Conflicting password source\n"); \
- error=RETURN_CONFLICTING_ARGUMENTS; }
- while( (opt=getopt(argc, argv, "+f:d:p:P:heVv"))!=-1 && error==-1 ) {
- switch( opt ) {
- case 'f':
-
- VIRGIN_PWTYPE;
-
- args.pwtype=PWT_FILE;
- args.pwsrc.filename=optarg;
- break;
- case 'd':
-
- VIRGIN_PWTYPE;
- args.pwtype=PWT_FD;
- args.pwsrc.fd=atoi(optarg);
- break;
- case 'p':
-
- VIRGIN_PWTYPE;
- args.pwtype=PWT_PASS;
- args.pwsrc.password=strdup(optarg);
-
-
- {
- int i;
- for( i=0; optarg[i]!='\0'; ++i )
- optarg[i]='z';
- }
- break;
- case 'P':
- args.pwprompt=optarg;
- break;
- case 'v':
- args.verbose++;
- break;
- case 'e':
- VIRGIN_PWTYPE;
- args.pwtype=PWT_PASS;
- args.pwsrc.password=getenv("SSHPASS");
- if( args.pwsrc.password==NULL ) {
- fprintf(stderr, "sshpass: -e option given but SSHPASS environment variable not set\n");
- error=RETURN_INVALID_ARGUMENTS;
- }
- break;
- case '?':
- case ':':
- error=RETURN_INVALID_ARGUMENTS;
- break;
- case 'h':
- error=RETURN_NOERROR;
- break;
- case 'V':
- printf("%s\n"
- "(C) 2006-2011 Lingnu Open Source Consulting Ltd.\n"
- "(C) 2015-2016 Shachar Shemesh\n"
- "This program is free software, and can be distributed under the terms of the GPL\n"
- "See the COPYING file for more information.\n"
- "\n"
- "Using \"%s\" as the default password prompt indicator.\n", PACKAGE_STRING, PASSWORD_PROMPT );
- exit(0);
- break;
- }
- }
- if( error>=0 )
- return -(error+1);
- else
- return optind;
- }
- int main( int argc, char *argv[] )
- {
- int opt_offset=parse_options( argc, argv );
- if( opt_offset<0 ) {
-
- show_help();
- return -(opt_offset+1);
- }
- if( argc-opt_offset<1 ) {
- show_help();
- return 0;
- }
- return runprogram( argc-opt_offset, argv+opt_offset );
- }
- int handleoutput( int fd );
- static int ourtty;
- static int masterpt;
- void window_resize_handler(int signum);
- void sigchld_handler(int signum);
- int runprogram( int argc, char *argv[] )
- {
- struct winsize ttysize;
-
- signal( SIGCHLD,sigchld_handler );
-
- masterpt=posix_openpt(O_RDWR);
- if( masterpt==-1 ) {
- perror("Failed to get a pseudo terminal");
- return RETURN_RUNTIME_ERROR;
- }
- fcntl(masterpt, F_SETFL, O_NONBLOCK);
- if( grantpt( masterpt )!=0 ) {
- perror("Failed to change pseudo terminal's permission");
- return RETURN_RUNTIME_ERROR;
- }
- if( unlockpt( masterpt )!=0 ) {
- perror("Failed to unlock pseudo terminal");
- return RETURN_RUNTIME_ERROR;
- }
- ourtty=open("/dev/tty", 0);
- if( ourtty!=-1 && ioctl( ourtty, TIOCGWINSZ, &ttysize )==0 ) {
- signal(SIGWINCH, window_resize_handler);
- ioctl( masterpt, TIOCSWINSZ, &ttysize );
- }
- const char *name=ptsname(masterpt);
- int slavept;
-
- int childpid=fork();
- if( childpid==0 ) {
-
-
- setsid();
-
- slavept=open(name, O_RDWR );
- close( slavept );
-
- close( masterpt );
- char **new_argv=malloc(sizeof(char *)*(argc+1));
- int i;
- for( i=0; i<argc; ++i ) {
- new_argv[i]=argv[i];
- }
- new_argv[i]=NULL;
- execvp( new_argv[0], new_argv );
- perror("sshpass: Failed to run command");
- exit(RETURN_RUNTIME_ERROR);
- } else if( childpid<0 ) {
- perror("sshpass: Failed to create child process");
- return RETURN_RUNTIME_ERROR;
- }
-
-
- slavept=open(name, O_RDWR|O_NOCTTY );
- int status=0;
- int terminate=0;
- pid_t wait_id;
- sigset_t sigmask, sigmask_select;
-
- sigemptyset(&sigmask_select);
-
- sigemptyset(&sigmask);
- sigaddset(&sigmask, SIGCHLD);
- sigprocmask( SIG_SETMASK, &sigmask, NULL );
- do {
- if( !terminate ) {
- fd_set readfd;
- FD_ZERO(&readfd);
- FD_SET(masterpt, &readfd);
- int selret=pselect( masterpt+1, &readfd, NULL, NULL, NULL, &sigmask_select );
- if( selret>0 ) {
- if( FD_ISSET( masterpt, &readfd ) ) {
- int ret;
- if( (ret=handleoutput( masterpt )) ) {
-
-
-
- if( ret>0 ) {
- close( masterpt );
- close(slavept);
- }
- terminate=ret;
- if( terminate ) {
- close( slavept );
- }
- }
- }
- }
- wait_id=waitpid( childpid, &status, WNOHANG );
- } else {
- wait_id=waitpid( childpid, &status, 0 );
- }
- } while( wait_id==0 || (!WIFEXITED( status ) && !WIFSIGNALED( status )) );
- if( terminate>0 )
- return terminate;
- else if( WIFEXITED( status ) )
- return WEXITSTATUS(status);
- else
- return 255;
- }
- int match( const char *reference, const char *buffer, ssize_t bufsize, int state );
- void write_pass( int fd );
- int handleoutput( int fd )
- {
-
- static int prevmatch=0;
- static int state1, state2;
- static int firsttime = 1;
- static const char *compare1=PASSWORD_PROMPT;
- static const char compare2[]="The authenticity of host ";
-
-
-
- char buffer[256];
- int ret=0;
- if( args.pwprompt ) {
- compare1 = args.pwprompt;
- }
- if( args.verbose && firsttime ) {
- firsttime=0;
- fprintf(stderr, "SSHPASS searching for password prompt using match \"%s\"\n", compare1);
- }
- int numread=read(fd, buffer, sizeof(buffer)-1 );
- buffer[numread] = '\0';
- if( args.verbose ) {
- fprintf(stderr, "SSHPASS read: %s\n", buffer);
- }
- state1=match( compare1, buffer, numread, state1 );
-
- if( compare1[state1]=='\0' ) {
- if( !prevmatch ) {
- if( args.verbose )
- fprintf(stderr, "SSHPASS detected prompt. Sending password.\n");
- write_pass( fd );
- state1=0;
- prevmatch=1;
- } else {
-
- if( args.verbose )
- fprintf(stderr, "SSHPASS detected prompt, again. Wrong password. Terminating.\n");
- ret=RETURN_INCORRECT_PASSWORD;
- }
- }
- if( ret==0 ) {
- state2=match( compare2, buffer, numread, state2 );
-
- if( compare2[state2]=='\0' ) {
- if( args.verbose )
- fprintf(stderr, "SSHPASS detected host authentication prompt. Exiting.\n");
- ret=RETURN_HOST_KEY_UNKNOWN;
- }
- }
- return ret;
- }
- int match( const char *reference, const char *buffer, ssize_t bufsize, int state )
- {
-
- int i;
- for( i=0;reference[state]!='\0' && i<bufsize; ++i ) {
- if( reference[state]==buffer[i] )
- state++;
- else {
- state=0;
- if( reference[state]==buffer[i] )
- state++;
- }
- }
- return state;
- }
- void write_pass_fd( int srcfd, int dstfd );
- void write_pass( int fd )
- {
- switch( args.pwtype ) {
- case PWT_STDIN:
- write_pass_fd( STDIN_FILENO, fd );
- break;
- case PWT_FD:
- write_pass_fd( args.pwsrc.fd, fd );
- break;
- case PWT_FILE:
- {
- int srcfd=open( args.pwsrc.filename, O_RDONLY );
- if( srcfd!=-1 ) {
- write_pass_fd( srcfd, fd );
- close( srcfd );
- }
- }
- break;
- case PWT_PASS:
- write( fd, args.pwsrc.password, strlen( args.pwsrc.password ) );
- write( fd, "\n", 1 );
- break;
- }
- }
- void write_pass_fd( int srcfd, int dstfd )
- {
- int done=0;
- while( !done ) {
- char buffer[40];
- int i;
- int numread=read( srcfd, buffer, sizeof(buffer) );
- done=(numread<1);
- for( i=0; i<numread && !done; ++i ) {
- if( buffer[i]!='\n' )
- write( dstfd, buffer+i, 1 );
- else
- done=1;
- }
- }
- write( dstfd, "\n", 1 );
- }
- void window_resize_handler(int signum)
- {
- struct winsize ttysize;
- if( ioctl( ourtty, TIOCGWINSZ, &ttysize )==0 )
- ioctl( masterpt, TIOCSWINSZ, &ttysize );
- }
- void sigchld_handler(int signum)
- {
- }
|