* s3cmd: Added encryption key support to --configure
git-svn-id: https://s3tools.svn.sourceforge.net/svnroot/s3tools/s3cmd/trunk@125 830e0280-6d2a-0410-9c65-932aecc39d9d
... | ... |
@@ -21,7 +21,7 @@ class Config(object): |
21 | 21 |
acl_public = False |
22 | 22 |
encrypt = False |
23 | 23 |
gpg_passphrase = "" |
24 |
- gpg_command = "/usr/bin/gpg" |
|
24 |
+ gpg_command = "" |
|
25 | 25 |
gpg_encrypt = "%(gpg_command)s -c --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s" |
26 | 26 |
gpg_decrypt = "%(gpg_command)s -d --verbose --no-use-agent --batch --yes --passphrase-fd %(passphrase_fd)s -o %(output_file)s %(input_file)s" |
27 | 27 |
|
... | ... |
@@ -9,6 +9,7 @@ import re |
9 | 9 |
import elementtree.ElementTree as ET |
10 | 10 |
import string |
11 | 11 |
import random |
12 |
+import md5 |
|
12 | 13 |
|
13 | 14 |
def parseNodes(nodes, xmlns = ""): |
14 | 15 |
retval = [] |
... | ... |
@@ -104,3 +105,10 @@ def mktmpdir(prefix = "/tmp/tmpdir-", randchars = 10): |
104 | 104 |
def mktmpfile(prefix = "/tmp/tmpfile-", randchars = 20): |
105 | 105 |
createfunc = lambda filename : os.close(os.open(filename, os.O_CREAT | os.O_EXCL)) |
106 | 106 |
return mktmpsomething(prefix, randchars, createfunc) |
107 |
+ |
|
108 |
+def hash_file_md5(filename): |
|
109 |
+ h = md5.new() |
|
110 |
+ f = open(filename, "r") |
|
111 |
+ h.update(f.read()) |
|
112 |
+ f.close() |
|
113 |
+ return h.hexdigest() |
... | ... |
@@ -13,6 +13,7 @@ from copy import copy |
13 | 13 |
from optparse import OptionParser, Option, OptionValueError, IndentedHelpFormatter |
14 | 14 |
from logging import debug, info, warning, error |
15 | 15 |
import elementtree.ElementTree as ET |
16 |
+from distutils.spawn import find_executable |
|
16 | 17 |
|
17 | 18 |
## Our modules |
18 | 19 |
from S3 import PkgInfo |
... | ... |
@@ -250,7 +251,7 @@ def gpg_encrypt(filename): |
250 | 250 |
code = gpg_command(command, cfg.gpg_passphrase) |
251 | 251 |
return (code, tmp_filename, "gpg") |
252 | 252 |
|
253 |
-def gpg_decrypt(filename, gpgenc_header = ""): |
|
253 |
+def gpg_decrypt(filename, gpgenc_header = "", in_place = True): |
|
254 | 254 |
tmp_filename = Utils.mktmpfile(filename) |
255 | 255 |
args = { |
256 | 256 |
"gpg_command" : cfg.gpg_command, |
... | ... |
@@ -261,22 +262,28 @@ def gpg_decrypt(filename, gpgenc_header = ""): |
261 | 261 |
info("Decrypting file %(input_file)s to %(output_file)s..." % args) |
262 | 262 |
command = resolve_list(cfg.gpg_decrypt.split(" "), args) |
263 | 263 |
code = gpg_command(command, cfg.gpg_passphrase) |
264 |
- if code == 0: |
|
264 |
+ if code == 0 and in_place: |
|
265 | 265 |
debug("Renaming %s to %s" % (tmp_filename, filename)) |
266 | 266 |
os.unlink(filename) |
267 | 267 |
os.rename(tmp_filename, filename) |
268 |
- return (code) |
|
268 |
+ tmp_filename = filename |
|
269 |
+ return (code, tmp_filename) |
|
269 | 270 |
|
270 | 271 |
def run_configure(config_file): |
271 | 272 |
cfg = Config() |
272 | 273 |
options = [ |
273 | 274 |
("access_key", "Access Key", "Access key and Secret key are your identifiers for Amazon S3"), |
274 | 275 |
("secret_key", "Secret Key"), |
276 |
+ ("gpg_passphrase", "Encryption password", "Encryption password is used to protect your files from reading\nby unauthorized persons while in transfer to S3"), |
|
277 |
+ ("gpg_command", "Path to GPG program"), |
|
275 | 278 |
] |
279 |
+ if getattr(cfg, "gpg_command") == "": |
|
280 |
+ setattr(cfg, "gpg_command", find_executable("gpg")) |
|
281 |
+ |
|
276 | 282 |
try: |
277 | 283 |
while 1: |
278 | 284 |
output("\nEnter new values or accept defaults in brackets with Enter.") |
279 |
- output("Refer to user manual for detailed description of all options.\n") |
|
285 |
+ output("Refer to user manual for detailed description of all options.") |
|
280 | 286 |
for option in options: |
281 | 287 |
prompt = option[1] |
282 | 288 |
try: |
... | ... |
@@ -287,7 +294,7 @@ def run_configure(config_file): |
287 | 287 |
pass |
288 | 288 |
|
289 | 289 |
if len(option) >= 3: |
290 |
- output("%s" % option[2]) |
|
290 |
+ output("\n%s" % option[2]) |
|
291 | 291 |
|
292 | 292 |
val = raw_input(prompt + ": ") |
293 | 293 |
if val != "": |
... | ... |
@@ -300,12 +307,38 @@ def run_configure(config_file): |
300 | 300 |
try: |
301 | 301 |
output("Please wait...") |
302 | 302 |
S3(Config()).bucket_list("", "") |
303 |
- output("\nSuccess. Your access key and secret key worked fine :-)") |
|
304 |
- except S3Error, e: |
|
303 |
+ output("Success. Your access key and secret key worked fine :-)") |
|
304 |
+ |
|
305 |
+ output("\nNow verifying that encryption works...") |
|
306 |
+ if not getattr(cfg, "gpg_command"): |
|
307 |
+ raise Exception("Path to GPG program not set") |
|
308 |
+ if not os.path.isfile(getattr(cfg, "gpg_command")): |
|
309 |
+ raise Exception("GPG program not found") |
|
310 |
+ filename = Utils.mktmpfile() |
|
311 |
+ f = open(filename, "w") |
|
312 |
+ f.write(os.sys.copyright) |
|
313 |
+ f.close() |
|
314 |
+ ret_enc = gpg_encrypt(filename) |
|
315 |
+ ret_dec = gpg_decrypt(ret_enc[1], ret_enc[2], False) |
|
316 |
+ hash = [ |
|
317 |
+ Utils.hash_file_md5(filename), |
|
318 |
+ Utils.hash_file_md5(ret_enc[1]), |
|
319 |
+ Utils.hash_file_md5(ret_dec[1]), |
|
320 |
+ ] |
|
321 |
+ os.unlink(filename) |
|
322 |
+ os.unlink(ret_enc[1]) |
|
323 |
+ os.unlink(ret_dec[1]) |
|
324 |
+ if hash[0] == hash[2] and hash[0] != hash[1]: |
|
325 |
+ output ("Success. Encryption and decryption worked fine :-)") |
|
326 |
+ else: |
|
327 |
+ raise Exception("Encryption verification error.") |
|
328 |
+ |
|
329 |
+ except Exception, e: |
|
305 | 330 |
error("Test failed: %s" % (e)) |
306 | 331 |
val = raw_input("\nRetry configuration? [Y/n] ") |
307 | 332 |
if val.lower().startswith("y") or val == "": |
308 | 333 |
continue |
334 |
+ |
|
309 | 335 |
|
310 | 336 |
val = raw_input("\nSave settings? [y/N] ") |
311 | 337 |
if val.lower().startswith("y"): |