X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=utilities%2Fpspp-convert.c;h=4a2f0f029127b176aa84f983c72be422a4ca38fc;hb=078b003b3171c6158a3419a01189b9658896f470;hp=cd760199d3813340626727db584c85e13bca992c;hpb=3dd0f6ae0d5eb73a2270a243e443c4ae03c2c16e;p=pspp diff --git a/utilities/pspp-convert.c b/utilities/pspp-convert.c index cd760199d3..4a2f0f0291 100644 --- a/utilities/pspp-convert.c +++ b/utilities/pspp-convert.c @@ -50,7 +50,9 @@ static void usage (void); 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 *password, + const char *alphabet, int max_length, + const char *password_list); int main (int argc, char *argv[]) @@ -69,6 +71,9 @@ main (int argc, char *argv[]) struct file_handle *output_fh = NULL; 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; @@ -79,11 +84,19 @@ main (int argc, char *argv[]) for (;;) { + enum + { + OPT_PASSWORD_LIST = UCHAR_MAX + 1, + }; static const struct option long_options[] = { { "cases", required_argument, NULL, 'c' }, { "encoding", required_argument, NULL, 'e' }, + { "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' }, @@ -94,7 +107,7 @@ main (int argc, char *argv[]) int c; - c = getopt_long (argc, argv, "c:e:p:O:hv", long_options, NULL); + c = getopt_long (argc, argv, "c:e:p:a:l:O:hv", long_options, NULL); if (c == -1) break; @@ -112,6 +125,26 @@ main (int argc, char *argv[]) password = optarg; break; + case 'l': + 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]) + { + for (int ch = p[0]; ch <= p[2]; ch++) + ds_put_byte (&alphabet, ch); + p += 3; + } + else + ds_put_byte (&alphabet, *p++); + break; + case 'O': output_format = optarg; break; @@ -164,7 +197,8 @@ main (int argc, char *argv[]) "format")); } - if (! decrypt_file (enc, input_fh, output_fh, password)) + if (!decrypt_file (enc, input_fh, output_fh, password, + ds_cstr (&alphabet), length, password_list)) goto error; goto exit; @@ -203,6 +237,8 @@ main (int argc, char *argv[]) output_filename); NOT_REACHED (); } + if (!writer) + error (1, 0, _("%s: error opening output file"), output_filename); for (i = 0; i < max_cases; i++) { @@ -221,7 +257,8 @@ main (int argc, char *argv[]) error (1, 0, _("%s: error writing output file"), output_filename); exit: - dict_destroy (dict); + ds_destroy (&alphabet); + dict_unref (dict); fh_unref (output_fh); fh_unref (input_fh); fh_done (); @@ -230,7 +267,8 @@ exit: return 0; error: - dict_destroy (dict); + ds_destroy (&alphabet); + dict_unref (dict); fh_unref (output_fh); fh_unref (input_fh); fh_done (); @@ -243,22 +281,144 @@ static bool decrypt_file (struct encrypted_file *enc, const struct file_handle *ifh, const struct file_handle *ofh, - const char *password) + const char *password, + const char *alphabet, + 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 (password == NULL) + if (password_list) { - password = getpass ("password: "); - if (password == NULL) - return false; + 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); + int *indexes = xzalloc (max_length * sizeof *indexes); + + for (int len = password ? strlen (password) : 0; + len <= max_length; len++) + { + if (password && len == strlen (password)) + { + for (int i = 0; i < len; i++) + { + const char *p = strchr (alphabet, password[i]); + if (!p) + error (1, 0, _("%s: '%c' is not in alphabet"), + password, password[i]); + indexes[i] = p - alphabet; + pw[i] = *p; + } + } + else + { + memset (indexes, 0, len * sizeof *indexes); + for (int i = 0; i < len; i++) + pw[i] = alphabet[0]; + } + pw[len] = '\0'; + + unsigned int target = 0; + for (unsigned int j = 0; ; j++) + { + if (j >= target) + { + target += 100000; + if (isatty (STDOUT_FILENO)) + { + printf ("\rlength %d: %s", len, pw); + fflush (stdout); + } + } + if (encrypted_file_unlock__ (enc, pw)) + { + printf ("\npassword is: \"%s\"\n", pw); + password = pw; + goto success; + } + + int i; + for (i = 0; i < len; i++) + if (++indexes[i] < alphabet_size) + { + pw[i] = alphabet[indexes[i]]; + break; + } + else + { + indexes[i] = 0; + pw[i] = alphabet[indexes[i]]; + } + if (i == len) + break; + } + } + free (indexes); + free (pw); + + success:; } + else + { + if (password == NULL) + { + password = getpass ("password: "); + if (password == NULL) + return false; + } - if (!encrypted_file_unlock (enc, password)) - error (1, 0, _("sorry, wrong password")); + if (!encrypted_file_unlock (enc, password)) + error (1, 0, _("sorry, wrong password")); + } out = fn_open (ofh, "wb"); if (out == NULL) @@ -303,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);