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.
@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.
be the same format (decrypted).
.
.SH "OPTIONS"
+.SS "General Options"
.
.IP "\fB\-O format\fR"
.IQ "\fB\-\-output\-format=\fIformat\fR"
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
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.
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[])
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;
for (;;)
{
+ enum
+ {
+ OPT_PASSWORD_LIST = UCHAR_MAX + 1,
+ };
static const struct option long_options[] =
{
{ "cases", required_argument, NULL, 'c' },
{ "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' },
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])
}
if (!decrypt_file (enc, input_fh, output_fh, password,
- ds_cstr (&alphabet), length))
+ ds_cstr (&alphabet), length, password_list))
goto error;
goto exit;
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);
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);