chiark / gitweb /
stop passing passphrases via args, instead use prepared files
authorHans-Christoph Steiner <hans@eds.org>
Tue, 1 Apr 2014 01:02:42 +0000 (21:02 -0400)
committerHans-Christoph Steiner <hans@eds.org>
Tue, 1 Apr 2014 01:02:42 +0000 (21:02 -0400)
Any process can read the process table, and can therefore see the entire
command line of any other process.  That means its a bad idea to ever put
passwords as part of a command line.  Python is executing keytool and
jarsigner command lines here, so now instead of putting the password on the
command line, a file is passed instead with suitable file permissions.
This should reduce the exposure a lot.  But still, sensitive passwords
should not be written to any text file.

This change requires OpenJDK-7 since the :file option to -storepass and
-keypass was only added in Java 7's keytool and jarsigner.

fdroidserver/common.py
fdroidserver/init.py
fdroidserver/publish.py
fdroidserver/update.py
sampleconfigs/config.py

index 5014a0be13b3021143b9c9a1eb2d8446e5841c56..a89bfdc364729a12d9e7dac101c5c9f199577e44 100644 (file)
@@ -94,8 +94,26 @@ def read_config(opts, config_file='config.py'):
         if st.st_mode & stat.S_IRWXG or st.st_mode & stat.S_IRWXO:
             logging.warn("unsafe permissions on {0} (should be 0600)!".format(config_file))
 
+    for k in ["keystorepass", "keypass"]:
+        if k in config:
+            write_password_file(k)
+
     return config
 
+def write_password_file(pwtype, password=None):
+    '''
+    writes out passwords to a protected file instead of passing passwords as
+    command line argments
+    '''
+    filename = '.fdroid.' + pwtype + '.txt'
+    fd = os.open(filename, os.O_CREAT | os.O_WRONLY, 0600)
+    if password == None:
+        os.write(fd, config[pwtype])
+    else:
+        os.write(fd, password)
+    os.close(fd)
+    config[pwtype + 'file'] = filename
+
 # Given the arguments in the form of multiple appid:[vc] strings, this returns
 # a dictionary with the set of vercodes specified for each package.
 def read_pkg_args(args, allow_vercodes=False):
index 0c33400cbfea4715a76a0a214527ac43d2fe2f9b..4a02e9a4196919d76b351357d2b60ae331acf522 100644 (file)
@@ -56,12 +56,15 @@ def genpassword():
 def genkey(keystore, repo_keyalias, password, keydname):
     '''generate a new keystore with a new key in it for signing repos'''
     logging.info('Generating a new key in "' + keystore + '"...')
+    write_password_file("keystorepass", password)
+    write_password_file("keypass", password)
     p = FDroidPopen(['keytool', '-genkey',
                 '-keystore', keystore, '-alias', repo_keyalias,
                 '-keyalg', 'RSA', '-keysize', '4096',
                 '-sigalg', 'SHA256withRSA',
                 '-validity', '10000',
-                '-storepass', password, '-keypass', password,
+                '-storepass:file', config['keystorepassfile'],
+                '-keypass:file', config['keypassfile'],
                 '-dname', keydname])
     if p.returncode != 0:
         raise BuildException("Failed to generate key", p.stdout)
index c7878d514f45ea2210c23981ccb6cc8bf1b509b4..1c241501002a8cd67ba1ace068eea5d0a4898cf2 100644 (file)
@@ -122,23 +122,23 @@ def main():
         # if not generate one...
         p = FDroidPopen(['keytool', '-list',
             '-alias', keyalias, '-keystore', config['keystore'],
-            '-storepass', config['keystorepass']])
+            '-storepass:file', config['keystorepass']])
         if p.returncode !=0:
             logging.info("Key does not exist - generating...")
             p = FDroidPopen(['keytool', '-genkey',
                 '-keystore', config['keystore'], '-alias', keyalias,
                 '-keyalg', 'RSA', '-keysize', '2048',
                 '-validity', '10000',
-                '-storepass', config['keystorepass'],
-                '-keypass', config['keypass'],
+                '-storepass:file', config['keystorepassfile'],
+                '-keypass:file', config['keypassfile'],
                 '-dname', config['keydname']])
             if p.returncode != 0:
                 raise BuildException("Failed to generate key")
 
         # Sign the application...
         p = FDroidPopen(['jarsigner', '-keystore', config['keystore'],
-            '-storepass', config['keystorepass'],
-            '-keypass', config['keypass'], '-sigalg',
+            '-storepass:file', config['keystorepassfile'],
+            '-keypass:file', config['keypassfile'], '-sigalg',
             'MD5withRSA', '-digestalg', 'SHA1',
                 apkfile, keyalias])
         if p.returncode != 0:
index 939af5871281331e80fa8a6055ce2b31d6e9f5d1..55d4b0e2ec3ecff3badafe1c8c48e46260e960f5 100644 (file)
@@ -642,7 +642,7 @@ def make_index(apps, apks, repodir, archive, categories):
             p = FDroidPopen(['keytool', '-exportcert',
                                   '-alias', config['repo_keyalias'],
                                   '-keystore', config['keystore'],
-                                  '-storepass', config['keystorepass']])
+                                  '-storepass:file', config['keystorepassfile']])
             if p.returncode != 0:
                 logging.critical("Failed to get repo pubkey")
                 sys.exit(1)
@@ -796,7 +796,8 @@ def make_index(apps, apks, repodir, archive, categories):
 
         # Sign the index...
         p = FDroidPopen(['jarsigner', '-keystore', config['keystore'],
-            '-storepass', config['keystorepass'], '-keypass', config['keypass'],
+            '-storepass:file', config['keystorepassfile'],
+            '-keypass:file', config['keypassfile'],
             '-digestalg', 'SHA1', '-sigalg', 'MD5withRSA',
             os.path.join(repodir, 'index.jar') , config['repo_keyalias']])
         if p.returncode != 0:
index 0e1919db68c41fe857e372804075e0eb2c8d6ab6..56b37ca6314d88a4742294a8ab0435a6df9d1646 100644 (file)
@@ -62,12 +62,16 @@ repo_keyalias = None
 #somewhere safe and secure, and backed up!
 keystore = "/home/me/somewhere/my.keystore"
 
-#The password for the keystore (at least 6 characters).
-keystorepass = "password1"
-
-#The password for keys - the same is used for each auto-generated key
-#as well as for the repository key.
-keypass = "password2"
+# The password for the keystore (at least 6 characters).  If this password is
+# different than the keypass below, it can be OK to store the password in this
+# file for real use.  But in general, sensitive passwords should not be stored
+# in text files!
+#keystorepass = "password1"
+
+# The password for keys - the same is used for each auto-generated key as well
+# as for the repository key.  You should not normally store this password in a
+# file since it is a sensitive password.
+#keypass = "password2"
 
 #The distinguished name used for all keys.
 keydname = "CN=Birdman, OU=Cell, O=Alcatraz, L=Alcatraz, S=California, C=US"