Last active
July 1, 2024 03:33
-
-
Save leiless/63595ec49d446beac79579af2ef08bf0 to your computer and use it in GitHub Desktop.
sshpass main.c diff 1.09 vs 1.10
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/sshpass-1.09/main.c b/sshpass-1.10/main.c | |
index 8a75d61..2bad28b 100644 | |
--- a/sshpass-1.09/main.c | |
+++ b/sshpass-1.10/main.c | |
@@ -29,6 +29,7 @@ | |
#include <sys/ioctl.h> | |
#include <sys/select.h> | |
+#include <assert.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
#include <signal.h> | |
@@ -50,6 +51,7 @@ enum program_return_codes { | |
RETURN_INCORRECT_PASSWORD, | |
RETURN_HOST_KEY_UNKNOWN, | |
RETURN_HOST_KEY_CHANGED, | |
+ RETURN_HELP, | |
}; | |
// Some systems don't define posix_openpt | |
@@ -61,12 +63,15 @@ posix_openpt(int flags) | |
} | |
#endif | |
+#define DEFAULT_ENV_PASSWORD "SSHPASS" | |
+ | |
int runprogram( int argc, char *argv[] ); | |
void reliable_write( int fd, const void *data, size_t size ); | |
int handleoutput( int fd ); | |
void window_resize_handler(int signum); | |
void sigchld_handler(int signum); | |
void term_handler(int signum); | |
+void term_child(int signum); | |
int match( const char *reference, const char *buffer, ssize_t bufsize, int state ); | |
void write_pass( int fd ); | |
@@ -83,19 +88,34 @@ struct { | |
char *orig_password; | |
} args; | |
+static void hide_password() | |
+{ | |
+ assert(args.pwsrc.password==NULL); | |
+ | |
+ args.pwsrc.password = strdup(args.orig_password); | |
+ | |
+ // Hide the original password from prying eyes | |
+ while( *args.orig_password != '\0' ) { | |
+ *args.orig_password = '\0'; | |
+ ++args.orig_password; | |
+ } | |
+ | |
+ args.orig_password = NULL; | |
+} | |
+ | |
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"); | |
+ printf("Usage: " PACKAGE_NAME " [-f|-d|-p|-e[env_var]] [-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[env_var] Password is passed as env-var \"env_var\" if given, \"SSHPASS\" otherwise.\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"); | |
} | |
// Parse the command line. Fill in the "args" global struct with the results. Return argv offset | |
@@ -113,7 +133,7 @@ static int parse_options( int argc, char *argv[] ) | |
fprintf(stderr, "Conflicting password source\n"); \ | |
error=RETURN_CONFLICTING_ARGUMENTS; } | |
- while( (opt=getopt(argc, argv, "+f:d:p:P:heVv"))!=-1 && error==-1 ) { | |
+ while( (opt=getopt(argc, argv, "+f:d:p:P:he::Vv"))!=-1 && error==-1 ) { | |
switch( opt ) { | |
case 'f': | |
// Password should come from a file | |
@@ -146,24 +166,29 @@ static int parse_options( int argc, char *argv[] ) | |
VIRGIN_PWTYPE; | |
args.pwtype=PWT_PASS; | |
- args.orig_password=getenv("SSHPASS"); | |
+ if( optarg==NULL ) | |
+ optarg = "SSHPASS"; | |
+ args.orig_password=getenv(optarg); | |
+ | |
if( args.orig_password==NULL ) { | |
- fprintf(stderr, "SSHPASS: -e option given but SSHPASS environment variable not set\n"); | |
+ fprintf(stderr, "sshpass: -e option given but \"%s\" environment variable is not set.\n", optarg); | |
error=RETURN_INVALID_ARGUMENTS; | |
} | |
+ | |
+ hide_password(); | |
+ unsetenv(optarg); | |
break; | |
case '?': | |
case ':': | |
error=RETURN_INVALID_ARGUMENTS; | |
break; | |
case 'h': | |
- error=RETURN_NOERROR; | |
- break; | |
+ return -(RETURN_HELP+1); | |
case 'V': | |
printf("%s\n" | |
"(C) 2006-2011 Lingnu Open Source Consulting Ltd.\n" | |
- "(C) 2015-2016, 2021 Shachar Shemesh\n" | |
+ "(C) 2015-2016, 2021-2022 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" | |
@@ -183,9 +208,14 @@ int main( int argc, char *argv[] ) | |
{ | |
int opt_offset=parse_options( argc, argv ); | |
+ if( opt_offset==-(RETURN_HELP+1) ) { | |
+ show_help(); | |
+ return 0; | |
+ } | |
+ | |
if( opt_offset<0 ) { | |
// There was some error | |
- show_help(); | |
+ fprintf(stderr, "Use \"sshpass -h\" to get help\n"); | |
return -(opt_offset+1); // -1 becomes 0, -2 becomes 1 etc. | |
} | |
@@ -197,13 +227,7 @@ int main( int argc, char *argv[] ) | |
} | |
if( args.orig_password!=NULL ) { | |
- args.pwsrc.password = strdup(args.orig_password); | |
- | |
- // Hide the original password from prying eyes | |
- while( *args.orig_password != '\0' ) { | |
- *args.orig_password = 'x'; | |
- ++args.orig_password; | |
- } | |
+ hide_password(); | |
} | |
return runprogram( argc-opt_offset, argv+opt_offset ); | |
@@ -214,7 +238,7 @@ static int ourtty; // Our own tty | |
static int masterpt; | |
int childpid; | |
-int term; | |
+int termsig; | |
int runprogram( int argc, char *argv[] ) | |
{ | |
@@ -310,18 +334,16 @@ int runprogram( int argc, char *argv[] ) | |
// Detach us from the current TTY | |
setsid(); | |
- // This line makes the ptty our controlling tty. We do not otherwise need it open | |
- slavept=open(name, O_RDWR ); | |
-#ifdef TIOCSCTTY | |
- // On some systems, an open(2) is insufficient to set the | |
- // controlling tty (see the documentation for TIOCSCTTY in | |
- // tty(4)). | |
- if (ioctl(slavept, TIOCSCTTY) == -1) { | |
+ | |
+ // Attach the process to a controlling TTY. | |
+ slavept=open(name, O_RDWR | O_NOCTTY); | |
+ // On some systems, an open(2) is insufficient to set the controlling tty (see the documentation for | |
+ // TIOCSCTTY in tty(4)). | |
+ if (ioctl(slavept, TIOCSCTTY, 0) == -1) { | |
perror("sshpass: Failed to set controlling terminal in child (TIOCSCTTY)"); | |
exit(RETURN_RUNTIME_ERROR); | |
} | |
-#endif | |
- close( slavept ); | |
+ close( slavept ); // We don't need the controlling TTY actually open | |
close( masterpt ); | |
@@ -362,6 +384,16 @@ int runprogram( int argc, char *argv[] ) | |
int selret=pselect( masterpt+1, &readfd, NULL, NULL, NULL, &sigmask_select ); | |
+ if( termsig!=0 ) { | |
+ // Copying termsig isn't strictly necessary, as signals are masked at this point. | |
+ int signum = termsig; | |
+ termsig = 0; | |
+ | |
+ term_child(signum); | |
+ | |
+ continue; | |
+ } | |
+ | |
if( selret>0 ) { | |
if( FD_ISSET( masterpt, &readfd ) ) { | |
int ret; | |
@@ -546,6 +578,13 @@ void sigchld_handler(int signum) | |
} | |
void term_handler(int signum) | |
+{ | |
+ // BUG: There is a potential race here if two signals arrive before the main code had a chance to handle them. | |
+ // This seems low enough risk not to justify the extra code to correctly handle this. | |
+ termsig = signum; | |
+} | |
+ | |
+void term_child(int signum) | |
{ | |
fflush(stdout); | |
switch(signum) { | |
@@ -560,8 +599,6 @@ void term_handler(int signum) | |
kill( childpid, signum ); | |
} | |
} | |
- | |
- term = 1; | |
} | |
void reliable_write( int fd, const void *data, size_t size ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment