From: Ben Pfaff Date: Wed, 16 Jan 2019 01:28:53 +0000 (-0800) Subject: pspp-convert: Add --password-list option. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pspp;a=commitdiff_plain;h=788d080e2302048dbcb5ae74c9d5ac38a01bc889 pspp-convert: Add --password-list option. --- diff --git a/NEWS b/NEWS index 715e4d3c50..53c96b6885 100644 --- a/NEWS +++ b/NEWS @@ -9,8 +9,8 @@ Changes since 1.2.0: * Plain text output is no longer divided into pages, since it is now rarely printed on paper. - * pspp-convert: New "-a" and "-l" options to search for an encrypted file's - password. + * pspp-convert: New "-a", "-l", "--password-list" options to search + for an encrypted file's password. * Bug fix for CVE-2018-20230. diff --git a/doc/pspp-convert.texi b/doc/pspp-convert.texi index 915313298c..7af90a113c 100644 --- a/doc/pspp-convert.texi +++ b/doc/pspp-convert.texi @@ -65,7 +65,8 @@ The password for encrypted files can be specified a few different ways. If the password is known, use the @option{-p} option (documented below) or allow @command{pspp-convert} to prompt for it. If the password is unknown, use the @option{-a} and @option{-l} -options to specify how to search for it. +options to specify how to search for it, or @option{--password-list} +to specify a file of passwords to try. Use @code{-O @var{extension}} to override the inferred format or to specify the format for unrecognized extensions. @@ -119,6 +120,10 @@ characters. @item --password-length=@var{max-length} Specifies the maximum length of the passwords to try. +@item --password-list=@var{file} +Specifies a file to read containing a list of passwords to try, one +per line. If @var{file} is @file{-}, reads from stdin. + @item -h @itemx --help Prints a usage message on stdout and exits. diff --git a/utilities/pspp-convert.1 b/utilities/pspp-convert.1 index 00828c2cb8..6e2e9f5224 100644 --- a/utilities/pspp-convert.1 +++ b/utilities/pspp-convert.1 @@ -60,6 +60,7 @@ the input file is in an encrypted format, then the output file must be the same format (decrypted). . .SH "OPTIONS" +.SS "General Options" . .IP "\fB\-O format\fR" .IQ "\fB\-\-output\-format=\fIformat\fR" @@ -79,12 +80,20 @@ Overrides the encoding in which character strings in \fIinput\fR are interpreted. This option is necessary because old SPSS system files do not self-identify their encoding. . +.SS "Password Options" +When the input file is encrypted, \fBpspp\-convert\fR needs to obtain +a password to decrypt it. To do so, the user may specify the password +with \f\-p\fR (or \fB\-\-password), or the name of a file containing a +list of possible passwords with \fB\-\-password\-list\fR, or an +alphabet of possible passwords to try along with a maximum length with +\fB\-a\fR (or \fB\-\-password\-alphabet\fR) and \fB\-l\fR (or +\-\-password\-length\fR). If none of these options is used, +\fBpspp\-convert\fR prompts for the password. The password options +are: +. .IP "\fB\-p \fIpassword\fR" .IQ "\fB\-\-password=\fIpassword\fR" -Specifies the password to use to decrypt encrypted SPSS system file -or syntax file -\fIinput\fR. If this option is not specified, \fBpspp\-convert\fR -prompts for the password. +Specifies the password to use to decrypt the input file. . .IP On multiuser systems, this option may not be safe because other users @@ -103,6 +112,11 @@ characters long. When these options are used, \fB\-p\fR may additionally specify a starting point for the search. . +.IP "\fB\-\-password\-list=\fIfile\fR" +Specifies a file to read containing a list of passwords to try, one +per line. If \fIfile\fR is \fB\-\fR, reads from stdin. +. +.SS "Other Options" .IP "\fB\-h\fR" .IQ "\fB\-\-help\fR" Prints a usage message on stdout and exits. diff --git a/utilities/pspp-convert.c b/utilities/pspp-convert.c index 7eb6b55668..4a2f0f0291 100644 --- a/utilities/pspp-convert.c +++ b/utilities/pspp-convert.c @@ -51,7 +51,8 @@ static bool decrypt_file (struct encrypted_file *enc, const struct file_handle *input_filename, const struct file_handle *output_filename, const char *password, - const char *alphabet, int max_length); + const char *alphabet, int max_length, + const char *password_list); int main (int argc, char *argv[]) @@ -71,6 +72,7 @@ main (int argc, char *argv[]) struct casewriter *writer; const char *password = NULL; struct string alphabet = DS_EMPTY_INITIALIZER; + const char *password_list = NULL; int length = 0; long long int i; @@ -82,6 +84,10 @@ main (int argc, char *argv[]) for (;;) { + enum + { + OPT_PASSWORD_LIST = UCHAR_MAX + 1, + }; static const struct option long_options[] = { { "cases", required_argument, NULL, 'c' }, @@ -90,6 +96,7 @@ main (int argc, char *argv[]) { "password", required_argument, NULL, 'p' }, { "password-alphabet", required_argument, NULL, 'a' }, { "password-length", required_argument, NULL, 'l' }, + { "password-list", required_argument, NULL, OPT_PASSWORD_LIST }, { "output-format", required_argument, NULL, 'O' }, @@ -122,6 +129,10 @@ main (int argc, char *argv[]) length = atoi (optarg); break; + case OPT_PASSWORD_LIST: + password_list = optarg; + break; + case 'a': for (const char *p = optarg; *p; ) if (p[1] == '-' && p[2] > p[0]) @@ -187,7 +198,7 @@ main (int argc, char *argv[]) } if (!decrypt_file (enc, input_fh, output_fh, password, - ds_cstr (&alphabet), length)) + ds_cstr (&alphabet), length, password_list)) goto error; goto exit; @@ -272,14 +283,62 @@ decrypt_file (struct encrypted_file *enc, const struct file_handle *ofh, const char *password, const char *alphabet, - int max_length) + int max_length, + const char *password_list) { FILE *out; int err; const char *input_filename = fh_get_file_name (ifh); const char *output_filename = fh_get_file_name (ofh); - if (alphabet[0] && max_length) + if (password_list) + { + FILE *password_file; + if (!strcmp (password_list, "-")) + password_file = stdin; + else + { + password_file = fopen (password_list, "r"); + if (!password_file) + error (1, errno, _("%s: error opening password file"), + password_list); + } + + struct string pw = DS_EMPTY_INITIALIZER; + unsigned int target = 100000; + for (unsigned int i = 0; ; i++) + { + ds_clear (&pw); + if (!ds_read_line (&pw, password_file, SIZE_MAX)) + { + if (isatty (STDOUT_FILENO)) + { + putchar ('\r'); + fflush (stdout); + } + error (1, 0, _("\n%s: password not in file"), password_list); + } + ds_chomp_byte (&pw, '\n'); + + if (i >= target) + { + target += 100000; + if (isatty (STDOUT_FILENO)) + { + printf ("\r%u", i); + fflush (stdout); + } + } + + if (encrypted_file_unlock__ (enc, ds_cstr (&pw))) + { + printf ("\npassword is: \"%s\"\n", ds_cstr (&pw)); + password = ds_cstr (&pw); + break; + } + } + } + else if (alphabet[0] && max_length) { size_t alphabet_size = strlen (alphabet); char *pw = xmalloc (max_length + 1); @@ -404,12 +463,17 @@ The desired format of OUTPUT is by default inferred from its extension:\n\ por SPSS portable file\n\ sps SPSS syntax file (encrypted syntax input files only)\n\ \n\ -Options:\n\ +General options:\n\ -O, --output-format=FORMAT set specific output format, where FORMAT\n\ is one of the extensions listed above\n\ -e, --encoding=CHARSET override encoding of input data file\n\ -c MAXCASES limit number of cases to copy (default is all cases)\n\ - -p PASSWORD password for encrypted files\n\ +Password options (for used with encrypted files):\n\ + -p PASSWORD individual password\n\ + -a ALPHABET with -l, alphabet of passwords to try\n\ + -l MAX-LENGTH with -a, maximum number of characters to try\n\ + --password-list=FILE try all of the passwords in FILE (one per line)\n\ +Other options:\n\ --help display this help and exit\n\ --version output version information and exit\n", program_name, program_name);