From 2ea422dcad13f121dfb5a2f390c3e456f5bcec83 Mon Sep 17 00:00:00 2001
From: Ben Pfaff <blp@cs.stanford.edu>
Date: Sat, 26 Sep 2015 16:42:13 -0700
Subject: [PATCH] pspp-convert: Support decrypting encrypted SPSS syntax files.

Thanks to charlesjohnsont@outlook.com for providing an example.
Bug #45974.
---
 NEWS                                          |   5 ++
 doc/pspp-convert.texi                         |  26 ++++---
 src/data/automake.mk                          |   4 +-
 ...sys-file-encryption.c => encrypted-file.c} |  67 ++++++++++++------
 ...sys-file-encryption.h => encrypted-file.h} |  24 +++----
 tests/automake.mk                             |   2 +-
 tests/data/encrypted-file.at                  |  51 +++++++++++++
 tests/data/sys-file-encryption.at             |  27 -------
 tests/data/test-encrypted.sps                 | Bin 0 -> 244 bytes
 utilities/pspp-convert.1                      |  17 +++--
 utilities/pspp-convert.c                      |  52 ++++++++------
 11 files changed, 175 insertions(+), 100 deletions(-)
 rename src/data/{sys-file-encryption.c => encrypted-file.c} (82%)
 rename src/data/{sys-file-encryption.h => encrypted-file.h} (55%)
 create mode 100644 tests/data/encrypted-file.at
 delete mode 100644 tests/data/sys-file-encryption.at
 create mode 100644 tests/data/test-encrypted.sps

diff --git a/NEWS b/NEWS
index 5da8bf74dd..b1031e7edb 100644
--- a/NEWS
+++ b/NEWS
@@ -11,6 +11,11 @@ Changes since 0.8.5:
  * The graphical user interface uses Gtk+ version 3 instead of version 2.
    Accordingly, it has a somewhat different look and feel.
 
+ * The pspp-convert utility can now decrypt encrypted syntax files.
+   The encrypted syntax file format is unacceptably insecure, so to
+   discourage its use PSPP and PSPPIRE do not directly read or write
+   this format.
+
  * Bug fixes, including the following notable ones:
 
    - The correlation coefficient in the paired samples t-test
diff --git a/doc/pspp-convert.texi b/doc/pspp-convert.texi
index 838f81167c..3719de224c 100644
--- a/doc/pspp-convert.texi
+++ b/doc/pspp-convert.texi
@@ -4,7 +4,8 @@
 @cindex @command{pspp-convert}
 
 @command{pspp-convert} is a command-line utility accompanying
-@pspp{}. It reads an SPSS system or portable file @var{input} and
+@pspp{}. It reads an SPSS or SPSS/PC+ system file or SPSS portable
+file or encrypted SPSS syntax file @var{input} and
 writes a copy of it to another @var{output} in a different format.
 Synopsis:
 
@@ -38,13 +39,19 @@ SPSS system file.
 
 @item por
 SPSS portable file.
+
+@item sps
+SPSS syntax file.  (Only encrypted syntax files may be converted to
+this format.)
 @end table
 
-As a special case of format conversion, @command{pspp-convert} can
-decrypt an encrypted SPSS system file.  Specify the encrypted file as
-@var{input}.  The output will be the equivalent plaintext SPSS system
-file.  You will be prompted for the password (or use @option{-p},
-documented below).
+@command{pspp-convert} can convert most input formats to most output
+formats.  Encrypted system file and syntax files are exceptions: if
+the input file is in an encrypted format, then the output file must be
+the same format (decrypted).  To decrypt such a file, specify the
+encrypted file as @var{input}.  The output will be the equivalent
+plaintext file.  You will be prompted for the password (or use
+@option{-p}, documented below).
 
 Use @code{-O @var{extension}} to override the inferred format or to
 specify the format for unrecognized extensions.
@@ -72,9 +79,10 @@ and SPSS/PC+ system files, do not self-identify their encoding.
 
 @item -p @var{password}
 @item --password=@var{password}
-Specifies the password to use to decrypt an encrypted SPSS system
-file.  If this option is not specified, @command{pspp-convert} will
-prompt interactively for the password as necessary.
+Specifies the password to use to decrypt an encrypted SPSS system file
+or syntax file.  If this option is not specified,
+@command{pspp-convert} will prompt interactively for the password as
+necessary.
 
 Be aware that command-line options, including passwords, may be
 visible to other users on multiuser systems.
diff --git a/src/data/automake.mk b/src/data/automake.mk
index 8b26f525e4..8031de188a 100644
--- a/src/data/automake.mk
+++ b/src/data/automake.mk
@@ -58,6 +58,8 @@ src_data_libdata_la_SOURCES = \
 	src/data/dict-class.h \
 	src/data/dictionary.c \
 	src/data/dictionary.h \
+	src/data/encrypted-file.c \
+	src/data/encrypted-file.h \
 	src/data/file-handle-def.c \
 	src/data/file-handle-def.h \
 	src/data/file-name.c \
@@ -99,8 +101,6 @@ src_data_libdata_la_SOURCES = \
 	src/data/subcase.c \
 	src/data/subcase.h \
 	src/data/sys-file-encoding.c \
-	src/data/sys-file-encryption.c \
-	src/data/sys-file-encryption.h \
 	src/data/sys-file-private.c \
 	src/data/sys-file-private.h \
 	src/data/sys-file-reader.c \
diff --git a/src/data/sys-file-encryption.c b/src/data/encrypted-file.c
similarity index 82%
rename from src/data/sys-file-encryption.c
rename to src/data/encrypted-file.c
index 51e253fbe3..b90126ed26 100644
--- a/src/data/sys-file-encryption.c
+++ b/src/data/encrypted-file.c
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2013 Free Software Foundation, Inc.
+   Copyright (C) 2013, 2015 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -16,7 +16,7 @@
 
 #include <config.h>
 
-#include "data/sys-file-encryption.h"
+#include "data/encrypted-file.h"
 
 #include <errno.h>
 #include <stdlib.h>
@@ -34,34 +34,35 @@
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
-struct encrypted_sys_file
+struct encrypted_file
   {
     FILE *file;
+    enum { SYSTEM, SYNTAX } type;
     int error;
 
     uint8_t ciphertext[16];
     uint8_t plaintext[16];
-    unsigned int n;
+    unsigned int ofs, n;
 
     uint32_t rk[4 * (RIJNDAEL_MAXNR + 1)];
     int Nr;
   };
 
-static bool try_password(struct encrypted_sys_file *, const char *password);
+static bool try_password(struct encrypted_file *, const char *password);
 static bool decode_password (const char *input, char output[11]);
-static bool fill_buffer (struct encrypted_sys_file *);
+static bool fill_buffer (struct encrypted_file *);
 
-/* If FILENAME names an encrypted system file, returns 1 and initializes *FP
+/* If FILENAME names an encrypted SPSS file, returns 1 and initializes *FP
    for further use by the caller.
 
-   If FILENAME can be opened and read, but is not an encrypted system file,
+   If FILENAME can be opened and read, but is not an encrypted SPSS file,
    returns 0.
 
    If FILENAME cannot be open or read, returns a negative errno value. */
 int
-encrypted_sys_file_open (struct encrypted_sys_file **fp, const char *filename)
+encrypted_file_open (struct encrypted_file **fp, const char *filename)
 {
-  struct encrypted_sys_file *f;
+  struct encrypted_file *f;
   char header[36 + 16];
   int retval;
   int n;
@@ -88,7 +89,11 @@ encrypted_sys_file_open (struct encrypted_sys_file **fp, const char *filename)
       goto error;
     }
 
-  if (memcmp (header + 8, "ENCRYPTEDSAV", 12))
+  if (!memcmp (header + 8, "ENCRYPTEDSAV", 12))
+    f->type = SYSTEM;
+  else if (!memcmp (header + 8, "ENCRYPTEDSPS", 12))
+    f->type = SYNTAX;
+  else
     {
       retval = 0;
       goto error;
@@ -96,6 +101,7 @@ encrypted_sys_file_open (struct encrypted_sys_file **fp, const char *filename)
 
   memcpy (f->ciphertext, header + 36, 16);
   f->n = 16;
+  f->ofs = 0;
   *fp = f;
   return 1;
 
@@ -111,7 +117,7 @@ error:
 /* Attempts to use PASSWORD, which may be a plaintext or "encrypted" password,
    to unlock F.  Returns true if successful, otherwise false. */
 bool
-encrypted_sys_file_unlock (struct encrypted_sys_file *f, const char *password)
+encrypted_file_unlock (struct encrypted_file *f, const char *password)
 {
   char decoded_password[11];
 
@@ -122,12 +128,12 @@ encrypted_sys_file_unlock (struct encrypted_sys_file *f, const char *password)
 
 /* Attempts to read N bytes of plaintext from F into BUF.  Returns the number
    of bytes successfully read.  A return value less than N may indicate end of
-   file or an error; use encrypted_sys_file_close() to distinguish.
+   file or an error; use encrypted_file_close() to distinguish.
 
-   This function can only be used after encrypted_sys_file_unlock() returns
+   This function can only be used after encrypted_file_unlock() returns
    true. */
 size_t
-encrypted_sys_file_read (struct encrypted_sys_file *f, void *buf_, size_t n)
+encrypted_file_read (struct encrypted_file *f, void *buf_, size_t n)
 {
   uint8_t *buf = buf_;
   size_t ofs = 0;
@@ -137,12 +143,12 @@ encrypted_sys_file_read (struct encrypted_sys_file *f, void *buf_, size_t n)
 
   while (ofs < n)
     {
-      unsigned int chunk = MIN (n - ofs, f->n);
+      unsigned int chunk = MIN (n - ofs, f->n - f->ofs);
       if (chunk > 0)
         {
-          memcpy (buf + ofs, &f->plaintext[16 - f->n], chunk);
+          memcpy (buf + ofs, &f->plaintext[f->ofs], chunk);
           ofs += chunk;
-          f->n -= chunk;
+          f->ofs += chunk;
         }
       else
         {
@@ -157,7 +163,7 @@ encrypted_sys_file_read (struct encrypted_sys_file *f, void *buf_, size_t n)
 /* Closes F.  Returns 0 if no read errors occurred, otherwise a positive errno
    value. */
 int
-encrypted_sys_file_close (struct encrypted_sys_file *f)
+encrypted_file_close (struct encrypted_file *f)
 {
   int error = f->error;
   if (fclose (f->file) == EOF && !error)
@@ -166,6 +172,14 @@ encrypted_sys_file_close (struct encrypted_sys_file *f)
 
   return error;
 }
+
+/* Returns true if F is an encrypted system file,
+   false if it is an encrypted syntax file. */
+bool
+encrypted_file_is_sav (const struct encrypted_file *f)
+{
+  return f->type == SYSTEM;
+}
 
 #define b(x) (1 << (x))
 
@@ -277,7 +291,7 @@ decode_password (const char *input, char output[11])
 
    Otherwise, returns zero. */
 static bool
-try_password(struct encrypted_sys_file *f, const char *password)
+try_password(struct encrypted_file *f, const char *password)
 {
   /* NIST SP 800-108 fixed data. */
   static const uint8_t fixed[] = {
@@ -329,22 +343,29 @@ try_password(struct encrypted_sys_file *f, const char *password)
   assert (sizeof key == 32);
   f->Nr = rijndaelKeySetupDec (f->rk, CHAR_CAST (const char *, key), 256);
 
-  /* Check for magic number "$FL" always present in SPSS .sav file. */
+  /* Check for magic number at beginning of plaintext. */
   rijndaelDecrypt (f->rk, f->Nr,
                    CHAR_CAST (const char *, f->ciphertext),
                    CHAR_CAST (char *, f->plaintext));
-  return !memcmp (f->plaintext, "$FL", 3);
+  return !memcmp (f->plaintext, f->type == SYSTEM ? "$FL" : "* E", 3);
 }
 
 static bool
-fill_buffer (struct encrypted_sys_file *f)
+fill_buffer (struct encrypted_file *f)
 {
   f->n = fread (f->ciphertext, 1, sizeof f->ciphertext, f->file);
+  f->ofs = 0;
   if (f->n == sizeof f->ciphertext)
     {
       rijndaelDecrypt (f->rk, f->Nr,
                        CHAR_CAST (const char *, f->ciphertext),
                        CHAR_CAST (char *, f->plaintext));
+      if (f->type == SYNTAX)
+        {
+          const char *eof = memchr (f->plaintext, '\04', sizeof f->plaintext);
+          if (eof)
+            f->n = CHAR_CAST (const uint8_t *, eof) - f->plaintext;
+        }
       return true;
     }
   else
diff --git a/src/data/sys-file-encryption.h b/src/data/encrypted-file.h
similarity index 55%
rename from src/data/sys-file-encryption.h
rename to src/data/encrypted-file.h
index b406cb2644..d089a046f0 100644
--- a/src/data/sys-file-encryption.h
+++ b/src/data/encrypted-file.h
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2013 Free Software Foundation, Inc.
+   Copyright (C) 2013, 2015 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -14,21 +14,21 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef SYS_FILE_ENCRYPTION_H
-#define SYS_FILE_ENCRYPTION_H 1
+#ifndef ENCRYPTED_FILE_H
+#define ENCRYPTED_FILE_H 1
 
 #include <stdbool.h>
 #include <stdio.h>
 
-/* Reading encrypted system files. */
+/* Reading encrypted SPSS files. */
 
-struct encrypted_sys_file;
+struct encrypted_file;
 
-int encrypted_sys_file_open (struct encrypted_sys_file **,
-                             const char *filename);
-bool encrypted_sys_file_unlock (struct encrypted_sys_file *,
-                                const char *password);
-size_t encrypted_sys_file_read (struct encrypted_sys_file *, void *, size_t);
-int encrypted_sys_file_close (struct encrypted_sys_file *);
+int encrypted_file_open (struct encrypted_file **, const char *filename);
+bool encrypted_file_unlock (struct encrypted_file *, const char *password);
+size_t encrypted_file_read (struct encrypted_file *, void *, size_t);
+int encrypted_file_close (struct encrypted_file *);
 
-#endif /* sys-file-encryption.h */
+bool encrypted_file_is_sav (const struct encrypted_file *);
+
+#endif /* encrypted-file.h */
diff --git a/tests/automake.mk b/tests/automake.mk
index 3b9a553503..188ffa3792 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -283,7 +283,7 @@ TESTSUITE_AT = \
 	tests/data/por-file.at \
 	tests/data/sys-file-reader.at \
 	tests/data/sys-file.at \
-	tests/data/sys-file-encryption.at \
+	tests/data/encrypted-file.at \
 	tests/language/command.at \
 	tests/language/control/do-if.at \
 	tests/language/control/do-repeat.at \
diff --git a/tests/data/encrypted-file.at b/tests/data/encrypted-file.at
new file mode 100644
index 0000000000..241e4e59bb
--- /dev/null
+++ b/tests/data/encrypted-file.at
@@ -0,0 +1,51 @@
+AT_BANNER([encrypted files])
+
+AT_SETUP([decrypt an encrypted system file])
+AT_KEYWORDS([system file decrypt pspp-convert])
+AT_CHECK([pspp-convert $srcdir/data/hotel-encrypted.sav hotel.sav -p pspp])
+AT_CHECK([pspp-convert hotel.sav hotel.csv])
+AT_CHECK([cat hotel.csv], [0], [dnl
+v1,v2,v3,v4,v5
+4,2,3,4,1
+1,1,3,1,1
+5,2,2,3,4
+3,1,3,1,2
+5,3,1,5,3
+1,2,5,4,2
+3,2,4,3,1
+1,4,5,2,1
+3,2,3,1,2
+2,5,4,2,1
+4,2,2,3,5
+2,1,4,1,1
+1,2,5,5,2
+2,3,3,3,1
+4,1,1,1,3
+1,1,5,1,2
+2,5,5,2,2
+])
+AT_CLEANUP
+
+AT_SETUP([decrypt an encrypted syntax file])
+AT_KEYWORDS([syntax file decrypt pspp-convert])
+AT_CHECK([pspp-convert $srcdir/data/test-encrypted.sps test.sps -p password])
+
+# The sample file is not ideal: lines end in CRLF and its last line
+# lacks a new-line, so "sed" and "echo" make it easier to work with.
+AT_CHECK([sed 's/
//' test.sps; echo], [0], [dnl
+* Encoding: windows-1252.
+DATA LIST LIST /name (a25) quantity (f8).
+BEGIN DATA.
+widgets 10345
+oojars 2345
+dubreys 98
+thingumies 518
+END DATA.
+ @&t@
+LIST.
+ @&t@
+DESCRIPTIVES /quantity
+ /statistics ALL.
+])
+AT_CLEANUP
+
diff --git a/tests/data/sys-file-encryption.at b/tests/data/sys-file-encryption.at
deleted file mode 100644
index 337595d3ee..0000000000
--- a/tests/data/sys-file-encryption.at
+++ /dev/null
@@ -1,27 +0,0 @@
-AT_BANNER([system file encryption])
-
-AT_SETUP([decrypt an encrypted system file])
-AT_KEYWORDS([system file decrypt pspp-convert])
-AT_CHECK([pspp-convert $srcdir/data/hotel-encrypted.sav hotel.sav -p pspp])
-AT_CHECK([pspp-convert hotel.sav hotel.csv])
-AT_CHECK([cat hotel.csv], [0], [dnl
-v1,v2,v3,v4,v5
-4,2,3,4,1
-1,1,3,1,1
-5,2,2,3,4
-3,1,3,1,2
-5,3,1,5,3
-1,2,5,4,2
-3,2,4,3,1
-1,4,5,2,1
-3,2,3,1,2
-2,5,4,2,1
-4,2,2,3,5
-2,1,4,1,1
-1,2,5,5,2
-2,3,3,3,1
-4,1,1,1,3
-1,1,5,1,2
-2,5,5,2,2
-])
-AT_CLEANUP
diff --git a/tests/data/test-encrypted.sps b/tests/data/test-encrypted.sps
new file mode 100644
index 0000000000000000000000000000000000000000..58ed181f3a787eb58c6a862b3b1fbb71bb6ca478
GIT binary patch
literal 244
zcmb1PfB;uN=b*@d5LcJrfM8Lm7>qi>{M+3mN&jcK$fSGoGk;Aol$|0d{V+3_o$HkK
zjz3?UFZ2n&F#Bh>J9&M0x>tbi9j25y2I>WKCb2w{YS(#?wJm6Eh{*d7`&rk<t$LRf
zRiAbv>CTxcCwX)DmvZmB{rp~I#^R`b3JV+AL{)iwr6d+SxbZYWfZZX(_HniOjCScy
zD_@HIu$nU`ekO~YFv}h5*)|Uf?s{=0Zdi1<CGCmAfwekv0)~48Of;E(ieJ9_s99|O
m-@NB;(>N5r{=Q^$Qe64+>x!!m{2s3#<o~P_Szu@>xd8y8`DSqd

literal 0
HcmV?d00001

diff --git a/utilities/pspp-convert.1 b/utilities/pspp-convert.1
index 2dc608980e..bbbdd62a4c 100644
--- a/utilities/pspp-convert.1
+++ b/utilities/pspp-convert.1
@@ -7,7 +7,7 @@
 .TH pspp\-convert 1 "October 2013" "PSPP" "PSPP Manual"
 .
 .SH NAME
-pspp\-convert \- convert SPSS system and portable files to other formats
+pspp\-convert \- convert SPSS files to other formats
 .
 .SH SYNOPSIS
 \fBpspp\-convert\fR [\fIoptions\fR] \fIinput\fR \fIoutput\fR
@@ -18,7 +18,8 @@ pspp\-convert \- convert SPSS system and portable files to other formats
 .
 .SH DESCRIPTION
 The \fBpspp\-convert\fR program reads \fIinput\fR, which may be an
-SPSS system file, an SPSS/PC+ system file, or an SPSS portable file,
+SPSS system file, an SPSS/PC+ system file, an SPSS portable file,
+or an encrypted SPSS syntax file,
 and writes it to \fIoutput\fR, performing format conversion as
 necessary.
 .PP
@@ -44,14 +45,19 @@ SPSS system file.
 .IP \fBpor\fR
 SPSS portable file.
 .
+.IP \fBsps\fR
+SPSS syntax file.  (Only encrypted syntax files may be converted to
+this format.)
+.
 .PP
 Use \fB\-O \fIextension\fR to override the inferred format or to
 specify the format for unrecognized extensions.
 .
 .PP
 \fBpspp\-convert\fR can convert most input formats to most output
-formats, with one exception: if the input file is an encrypted system
-file, then the output file must also be an (unencrypted) system file.
+formats.  Encrypted system file and syntax files are exceptions: if
+the input file is in an encrypted format, then the output file must
+be the same format (decrypted).
 .
 .SH "OPTIONS"
 .
@@ -75,7 +81,8 @@ do not self-identify their encoding.
 .
 .IP "\fB\-p \fIpassword\fR"
 .IQ "\fB\-\-password=\fIpassword\fR"
-Specifies the password to use to decrypt an encrypted SPSS system file
+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.
 .
diff --git a/utilities/pspp-convert.c b/utilities/pspp-convert.c
index ebd340ec35..264ec7a705 100644
--- a/utilities/pspp-convert.c
+++ b/utilities/pspp-convert.c
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2013, 2014 Free Software Foundation, Inc.
+   Copyright (C) 2013, 2014, 2015 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -26,10 +26,10 @@
 #include "data/casereader.h"
 #include "data/casewriter.h"
 #include "data/csv-file-writer.h"
+#include "data/encrypted-file.h"
 #include "data/file-name.h"
 #include "data/por-file-writer.h"
 #include "data/settings.h"
-#include "data/sys-file-encryption.h"
 #include "data/sys-file-writer.h"
 #include "data/file-handle-def.h"
 #include "libpspp/assertion.h"
@@ -46,10 +46,10 @@
 
 static void usage (void);
 
-static void decrypt_sav_file (struct encrypted_sys_file *enc,
-                              const char *input_filename,
-                              const char *output_filename,
-                              const char *password);
+static void decrypt_file (struct encrypted_file *enc,
+                          const char *input_filename,
+                          const char *output_filename,
+                          const char *password);
 
 int
 main (int argc, char *argv[])
@@ -62,7 +62,7 @@ main (int argc, char *argv[])
   struct casereader *reader;
   struct file_handle *input_fh;
   const char *encoding = NULL;
-  struct encrypted_sys_file *enc;
+  struct encrypted_file *enc;
 
   const char *output_format = NULL;
   struct file_handle *output_fh;
@@ -145,13 +145,22 @@ main (int argc, char *argv[])
       output_format = dot + 1;
     }
 
-  if (encrypted_sys_file_open (&enc, input_filename) > 0)
+  if (encrypted_file_open (&enc, input_filename) > 0)
     {
-      if (strcmp (output_format, "sav") && strcmp (output_format, "sys"))
-        error (1, 0, _("can only convert encrypted data file to sav or sys "
-                       "format"));
+      if (encrypted_file_is_sav (enc))
+        {
+          if (strcmp (output_format, "sav") && strcmp (output_format, "sys"))
+            error (1, 0, _("can only convert encrypted data file to sav or "
+                           "sys format"));
+        }
+      else
+        {
+          if (strcmp (output_format, "sps"))
+            error (1, 0, _("can only convert encrypted syntax file to sps "
+                           "format"));
+        }
 
-      decrypt_sav_file (enc, input_filename, output_filename, password);
+      decrypt_file (enc, input_filename, output_filename, password);
       goto exit;
     }
 
@@ -214,10 +223,10 @@ exit:
 }
 
 static void
-decrypt_sav_file (struct encrypted_sys_file *enc,
-                  const char *input_filename,
-                  const char *output_filename,
-                  const char *password)
+decrypt_file (struct encrypted_file *enc,
+              const char *input_filename,
+              const char *output_filename,
+              const char *password)
 {
   FILE *out;
   int err;
@@ -229,7 +238,7 @@ decrypt_sav_file (struct encrypted_sys_file *enc,
         exit (1);
     }
 
-  if (!encrypted_sys_file_unlock (enc, password))
+  if (!encrypted_file_unlock (enc, password))
     error (1, 0, _("sorry, wrong password"));
 
   out = fn_open (output_filename, "wb");
@@ -241,7 +250,7 @@ decrypt_sav_file (struct encrypted_sys_file *enc,
       uint8_t buffer[1024];
       size_t n;
 
-      n = encrypted_sys_file_read (enc, buffer, sizeof buffer);
+      n = encrypted_file_read (enc, buffer, sizeof buffer);
       if (n == 0)
         break;
 
@@ -249,7 +258,7 @@ decrypt_sav_file (struct encrypted_sys_file *enc,
         error (1, errno, ("%s: write error"), output_filename);
     }
 
-  err = encrypted_sys_file_close (enc);
+  err = encrypted_file_close (enc);
   if (err)
     error (1, err, ("%s: read error"), input_filename);
 
@@ -264,20 +273,21 @@ usage (void)
   printf ("\
 %s, a utility for converting SPSS data files to other formats.\n\
 Usage: %s [OPTION]... INPUT OUTPUT\n\
-where INPUT is an SPSS system or portable file\n\
+where INPUT is an SPSS data file or encrypted syntax file\n\
   and OUTPUT is the name of the desired output file.\n\
 \n\
 The desired format of OUTPUT is by default inferred from its extension:\n\
   csv txt             comma-separated value\n\
   sav sys             SPSS system file\n\
   por                 SPSS portable file\n\
+  sps                 SPSS syntax file (encrypted syntax input files only)\n\
 \n\
 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 .sav files\n\
+  -p PASSWORD         password for encrypted files\n\
   --help              display this help and exit\n\
   --version           output version information and exit\n",
           program_name, program_name);
-- 
2.30.2