Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Completes flake8 linting of Python files #66

Merged
merged 6 commits into from
Feb 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ flake8: ## Lints all Python files with flake8
# Not requiring dom0 since linting requires extra packages,
# available only in the developer environment, i.e. Work VM.
@flake8 .
@find -type f -exec file -i {} + \
| perl -F':\s+' -nE '$$F[1] =~ m/text\/x-python/ and say $$F[0]' \
| xargs flake8

# Explanation of the below shell command should it ever break.
# 1. Set the field separator to ": ##" to parse lines for make targets.
Expand Down
82 changes: 42 additions & 40 deletions sd-decrypt/decrypt-sd-submission
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env python

import sys
import tarfile
import tempfile
Expand All @@ -12,11 +11,12 @@ import shutil


def send_progress(msg):
p = subprocess.Popen(["qrexec-client-vm","sd-journalist",
"sd-process.Feedback"],
close_fds=True,
stdin=subprocess.PIPE)
p.communicate(msg)
p = subprocess.Popen(["qrexec-client-vm", "sd-journalist",
"sd-process.Feedback"],
close_fds=True,
stdin=subprocess.PIPE)
p.communicate(msg)


input = sys.argv[1]

Expand All @@ -29,61 +29,63 @@ tmpdir = tempfile.mkdtemp()
# first step, extract that archive
try:

with tarfile.open(input) as tar:
# potentially unsafe, can create arbitrary files on the filesystem
# given a malicious tarball
tar.extractall(tmpdir)
with tarfile.open(input) as tar:
# potentially unsafe, can create arbitrary files on the filesystem
# given a malicious tarball
tar.extractall(tmpdir)

except Exception as e:
send_progress("DECRYPTION_BUNDLE_OPEN_FAILURE")
sys.exit(0) # although we're exiting with failure, we return a
# 0 exit code so xdg does not try to re-open this file with
# another application
send_progress("DECRYPTION_BUNDLE_OPEN_FAILURE")
# although we're exiting with failure, we return a
# 0 exit code so xdg does not try to re-open this file with
# another application
sys.exit(0)

send_progress("SUBMISSION_BUNDLE_UNBUNDLED")

# everything in the archive should be zips, as created by SD
# let's unzip those here
zips = glob.glob(tmpdir + "/*zip")
for z in zips:
with zipfile.ZipFile(z) as zf:
zf.extractall(tmpdir + "/extracted/")
os.unlink(z)
with zipfile.ZipFile(z) as zf:
zf.extractall(tmpdir + "/extracted/")
os.unlink(z)

send_progress("SUBMISSION_FILES_EXTRACTED")

# great, we should be left with a directory tree filled with files
# encrypted to our public key. let's find those and decrypt them
for root, dirnames, filenames in os.walk(tmpdir):
for fn in fnmatch.filter(filenames, '*.gpg'):
[fn_no_ext, _] = os.path.splitext(fn)

out = open(os.path.join(root, fn_no_ext), 'w')
err = tempfile.NamedTemporaryFile(suffix=".gpg-err")
res = subprocess.call(["qubes-gpg-client", "--decrypt" , os.path.join(root, fn)], stdout=out, stderr=err)
out.close()
os.unlink(os.path.join(root, fn))
if res != 0:
os.unlink(os.path.join(root, fn_no_ext))
with open(err.name) as e:
msg = e.read()
send_progress("SUBMISSION_FILE_DECRYPTION_FAILED")
else:
send_progress("SUBMISSION_FILE_DECRYPTION_SUCCEEDED")
err.close()
for fn in fnmatch.filter(filenames, '*.gpg'):
[fn_no_ext, _] = os.path.splitext(fn)

out = open(os.path.join(root, fn_no_ext), 'w')
err = tempfile.NamedTemporaryFile(suffix=".gpg-err")
cmd = ["qubes-gpg-client", "--decrypt", os.path.join(root, fn)]
res = subprocess.call(cmd, stdout=out, stderr=err)
out.close()
os.unlink(os.path.join(root, fn))
if res != 0:
os.unlink(os.path.join(root, fn_no_ext))
with open(err.name) as e:
msg = e.read()
send_progress("SUBMISSION_FILE_DECRYPTION_FAILED")
else:
send_progress("SUBMISSION_FILE_DECRYPTION_SUCCEEDED")
err.close()

# almost done. docs are gzipped. let's ungzip them.
any_files = False
for root, dirnames, filenames in os.walk(tmpdir):
for fn in fnmatch.filter(filenames, '*.gz'):
any_files = True
# maybe sorta lazy, could do this using python gzip module.
# XXX also catch errors here...
subprocess.call(["gunzip", os.path.join(root, fn)])
for fn in fnmatch.filter(filenames, '*.gz'):
any_files = True
# maybe sorta lazy, could do this using python gzip module.
# XXX also catch errors here...
subprocess.call(["gunzip", os.path.join(root, fn)])

if not any_files:
send_progress("SUBMISSION_FILE_NO_FILES_FOUND")
sys.exit(0)
send_progress("SUBMISSION_FILE_NO_FILES_FOUND")
sys.exit(0)

# ok. we're going to send all the decrypted stuff to the svs vm.
# let's tar it all up again, so we can `qvm-open-in-vm` it.
Expand Down
4 changes: 3 additions & 1 deletion sd-journalist/do-not-open-here
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import sys
from PyQt4 import Qt


a = Qt.QApplication(sys.argv)

nope = Qt.QLabel("Please do not use this VM to open any files aside from those downloaded from SecureDrop.")
nope = Qt.QLabel("Please do not use this VM to open any files"
" aside from those downloaded from SecureDrop.")

nope.show()
a.exec_()
10 changes: 6 additions & 4 deletions sd-journalist/move-to-svs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import tempfile
import os.path
import subprocess

TB_DL_LOC="/home/user/.tb/tor-browser/Browser/Downloads"
TB_DL_LOC = "/home/user/.tb/tor-browser/Browser/Downloads"

zips = glob.glob(TB_DL_LOC + "/*.zip")

matched_sd_pattern = [re.match('[a-z]+\_[a-z]+[\d-]+\.zip', os.path.basename(z)) for z in zips]
matched_sd_pattern = [
re.match('[a-z]+\_[a-z]+[\d-]+\.zip', os.path.basename(z)) for z in zips]

probable_sd_downloads = [z.group(0) for z in matched_sd_pattern if z]

Expand All @@ -23,10 +24,11 @@ print "fh name " + fh.name
out_tar = tarfile.open(mode='w', fileobj=fh)

for f in probable_sd_downloads:
out_tar.add(os.path.join(TB_DL_LOC, f), arcname=f)
out_tar.add(os.path.join(TB_DL_LOC, f), arcname=f)

out_tar.close()
fh.close()

# ship this to the next phase
subprocess.call(["qvm-open-in-vm", "$dispvm:sd-dispvm", os.path.join(TB_DL_LOC, fh.name)])
cmd = ["qvm-open-in-vm", "$dispvm:sd-dispvm", os.path.join(TB_DL_LOC, fh.name)]
subprocess.call(cmd)
53 changes: 35 additions & 18 deletions sd-journalist/sd-process-display
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import sys
import PyQt4.QtCore as QtCore
from PyQt4.QtGui import QDialog, QDialogButtonBox, QApplication, QLabel, QVBoxLayout, QImage, QPixmap
from PyQt4.QtGui import QDialog, QDialogButtonBox, QApplication, \
QLabel, QVBoxLayout, QImage, QPixmap
from PyQt4.QtCore import Qt
import os
import errno
import threading
import pipereader


class SDDialog(QDialog):
def __init__(self, parent = None):
def __init__(self, parent=None):
fn = r'/usr/local/share/sd/logo-small.png'
image = QImage(fn)
self.logo = QLabel()
Expand Down Expand Up @@ -36,32 +37,47 @@ class SDDialog(QDialog):

messages = {
# bootstrapping
'EXISTING_SIGFILE': ("error", "Internal error: signal file given by caller already exists"),
'POLLING_ERROR': {"error": "An internal error occurred while listening for events from VMs."},
'EXISTING_SIGFILE': (
"error", "Internal error: signal file given by caller already exists"),
'POLLING_ERROR': {
"error": ("An internal error occurred while listening"
" for events from VMs.")},

# sd-journalist
'DOWNLOAD_FILE_MISSING': ("error", "The file downloaded from SecureDrop wasn't found."),
'DOWNLOAD_FILE_MISSING': (
"error", "The file downloaded from SecureDrop wasn't found."),
'DOWNLOAD_BUNDLE_CREATED': ("success", "Initial download bundle created."),

# decrypt
'DECRYPTION_PROCESS_START': ("success", "Decryption process started."),
'DECRYPTION_BUNDLE_OPEN_FAILURE': ("error", "Decryption bundle could not be opened."),
'SUBMISSION_BUNDLE_UNBUNDLED': ("success", "Submission bundle looks valid."),
'SUBMISSION_FILES_EXTRACTED': ("success", "Submission bundle files extracted."),
'SUBMISSION_FILE_DECRYPTION_FAILED': ('error', "Submission file decryption failed."),
'SUBMISSION_FILE_DECRYPTION_SUCCEEDED': ("success", "Submission file decrypted."),
'SUBMISSION_DECRYPTED': ("success", "All submission files decrypted"),
'DECRYPTION_BUNDLE_OPEN_FAILURE':
("error", "Decryption bundle could not be opened."),
'SUBMISSION_BUNDLE_UNBUNDLED':
("success", "Submission bundle looks valid."),
'SUBMISSION_FILES_EXTRACTED':
("success", "Submission bundle files extracted."),
'SUBMISSION_FILE_DECRYPTION_FAILED':
('error', "Submission file decryption failed."),
'SUBMISSION_FILE_DECRYPTION_SUCCEEDED':
("success", "Submission file decrypted."),
'SUBMISSION_DECRYPTED':
("success", "All submission files decrypted"),

# SVS
'DECRYPTED_BUNDLE_ON_SVS': ("success", "Decrypted file bundle arrived on SVS."),
'DECRYPTED_FILES_AVAILABLE': ("success", "Submitted files available for use on SVS."),
'DECRYPTED_BUNDLE UNBUNDLE_ERROR': ("error", "Bundle of decrypted files could not be unbundle on SVS." )
'DECRYPTED_BUNDLE_ON_SVS':
("success", "Decrypted file bundle arrived on SVS."),
'DECRYPTED_FILES_AVAILABLE':
("success", "Submitted files available for use on SVS."),
'DECRYPTED_BUNDLE UNBUNDLE_ERROR':
("error", "Bundle of decrypted files could not be unbundle on SVS.")
}


def finish():
d.buttons.hide()
d.layout.removeWidget(d.buttons)


def display(keyword):

if keyword in messages:
Expand All @@ -70,6 +86,7 @@ def display(keyword):
# XXX dev only, remove before deploying!
d.display.setText("bad keyword: {}".format(keyword))


def poller_cb(poller, msg, err):
# we're called with a keyword in `msg`. We look up that keyword
# for the user-facing message to display.
Expand All @@ -90,9 +107,9 @@ def create_sigfile(sigfile):
display('EXISTING_SIGFILE')
else:
try:
with open(sigfile,'a'):
with open(sigfile, 'a'):
pass
except Exception as e:
except Exception:
display('BAD_SIGFILE')


Expand All @@ -111,7 +128,7 @@ if __name__ == '__main__':
d.show()

if sigfile != "":
# tyvm https://stackoverflow.com/questions/6215690/how-to-execute-a-method-automatically-after-entering-qt-event-loop
# tyvm https://stackoverflow.com/questions/6215690/how-to-execute-a-method-automatically-after-entering-qt-event-loop # noqa: E501
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm? noqa?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, noqa on E501 permits the extra-long line. I'd much rather skip linting on a URL than break the URL up over multiple lines in order to satisfy the linter!

def on_start():
create_sigfile(sigfile)

Expand Down
7 changes: 5 additions & 2 deletions sd-journalist/sd-process-download
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import subprocess

fn = sys.argv[1]


# remember your Stevens and do a double fork
def spawn_monitor_process(sigfile):

try:
pid = os.fork()
if pid > 0:
# congrats, new parent!
# congrats, new parent!
return
except OSError as e:
print >>sys.stderr, "fork #1 failed: %d (%s)" % (e.errno, e.strerror)
Expand Down Expand Up @@ -50,6 +51,7 @@ def wait_for_sigfile(sigfile):

os.remove(sigfile)


# spawn the GUI monitoring process, then wait for it to be available...
sigfile = tempfile.mktemp()
spawn_monitor_process(sigfile)
Expand All @@ -75,7 +77,8 @@ fh.close()

# this is sort of a one-off... how shall we send messages to the GUI
# from the same machine? This can only happen on sd-journalist.
c = subprocess.Popen(["/usr/local/bin/sd-process-feedback"], stdin=subprocess.PIPE)
c = subprocess.Popen(["/usr/local/bin/sd-process-feedback"],
stdin=subprocess.PIPE)
c.communicate(input="DOWNLOAD_BUNDLE_CREATED\n")

# ship this to the next phase
Expand Down
18 changes: 11 additions & 7 deletions sd-svs/accept-sd-xfer-extracted
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,22 @@ import os

fn = sys.argv[1]

## pull this in to a library... XXX

# TODO: pull this in to a library... XXX
def send_progress(msg):
p = subprocess.Popen(["qrexec-client-vm","sd-journalist",
"sd-process.Feedback"],
close_fds=True,
stdin=subprocess.PIPE)
p.communicate(msg)
p = subprocess.Popen(["qrexec-client-vm", "sd-journalist",
"sd-process.Feedback"],
close_fds=True,
stdin=subprocess.PIPE)
p.communicate(msg)


send_progress("DECRYPTED_BUNDLE_ON_SVS")

try:
res = subprocess.call(["tar", "-xf", fn, "--strip-components=1", "-C", "/home/user/Sources"])
cmd = ["tar", "-xf", fn,
"--strip-components=1", "-C", "/home/user/Sources"]
res = subprocess.call(cmd)
if res != 0:
send_progress("DECRYPTED_BUNDLE_UNBUNDLE_ERROR")
sys.exit(1)
Expand Down
Loading