dom0/qrexec: Add always allow option in qrexec confirmation dialog (#278)

This commit is contained in:
Marek Marczykowski 2011-10-12 00:08:28 +02:00
parent 810a59b6ce
commit ede96353af
3 changed files with 96 additions and 10 deletions

View File

@ -0,0 +1,55 @@
#!/usr/bin/python2
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2011 Marek Marczykowski <marmarek@invisiblethingslab.com>
#
# 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 the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
#
import sys
from optparse import OptionParser
from PyQt4.QtCore import *
from PyQt4.QtGui import *
app = None
def prepare_app():
global app
app = QApplication(sys.argv)
app.setOrganizationName("The Qubes Project")
app.setOrganizationDomain("http://qubes-os.org")
app.setApplicationName("Qubes")
def ask(text, title="Question", yestoall=False):
global app
if app is None:
prepare_app()
buttons = QMessageBox.Yes | QMessageBox.No
if yestoall:
buttons |= QMessageBox.YesToAll
reply = QMessageBox.question(None, title, text, buttons)
if reply == QMessageBox.Yes:
return 0
elif reply == QMessageBox.No:
return 1
elif reply == QMessageBox.YesToAll:
return 2
else:
#?!
return 127

View File

@ -4,10 +4,17 @@ import os
import os.path
import subprocess
import xen.lowlevel.xl
import qubes.guihelpers
import fcntl
POLICY_FILE_DIR="/etc/qubes_rpc/policy"
QREXEC_CLIENT="/usr/lib/qubes/qrexec_client"
class UserChoice:
ALLOW=0
DENY=1
ALWAYS_ALLOW=2
def line_to_dict(line):
tokens=line.split()
if len(tokens) < 3:
@ -20,6 +27,7 @@ def line_to_dict(line):
dict['source']=tokens[0]
dict['dest']=tokens[1]
dict['full-action']=tokens[2]
action_list=tokens[2].split(',')
dict['action']=action_list.pop(0)
@ -36,6 +44,7 @@ def read_policy_file(exec_index):
return None
policy_list=list()
f = open(policy_file)
fcntl.flock(f, fcntl.LOCK_SH)
for iter in f.readlines():
dict = line_to_dict(iter)
if dict is not None:
@ -92,9 +101,23 @@ def do_execute(domain, target, user, exec_index, process_ident):
def confirm_execution(domain, target, exec_index):
text = "Do you allow domain \"" +domain + "\" to execute " + exec_index
text+= " operation on the domain \"" + target +"\"?"
retcode = subprocess.call(["/usr/bin/zenity", "--question", "--text", text])
return retcode==0
text+= " operation on the domain \"" + target +"\"?<br>"
text+= " \"Yes to All\" option will automatically allow this operation in the future."
return qubes.guihelpers.ask(text, yestoall=True)
def add_always_allow(domain, target, exec_index, options):
policy_file=POLICY_FILE_DIR+"/"+exec_index
if not os.path.isfile(policy_file):
return None
f = open(policy_file, 'r+')
fcntl.flock(f, fcntl.LOCK_EX)
lines = []
for l in f.readlines():
lines.append(l)
lines.insert(0, "%s\t%s\tallow%s\n" % (domain, target, options))
f.seek(0)
f.write("".join(lines))
f.close()
def policy_editor(domain, target, exec_index):
text = "Policy editor not yet implemented. Please add a line in the form \""
@ -118,7 +141,11 @@ def main():
policy_dict=find_policy(policy_list, domain, target)
if policy_dict["action"] == "ask":
if confirm_execution(domain, target, exec_index):
user_choice = confirm_execution(domain, target, exec_index)
if user_choice == UserChoice.ALWAYS_ALLOW:
add_always_allow(domain, target, exec_index, policy_dict["full-action"].lstrip('ask'))
policy_dict["action"] = "allow"
elif user_choice == UserChoice.ALLOW:
policy_dict["action"] = "allow"
else:
policy_dict["action"] = "deny"
@ -136,4 +163,3 @@ def main():
os.execl(QREXEC_CLIENT, "qrexec_client", "-d", domain, "-l", "/bin/false", "-c", process_ident)
main()

View File

@ -82,6 +82,8 @@ cp qvm-core/qubes.py $RPM_BUILD_ROOT%{python_sitearch}/qubes
cp qvm-core/qubes.py[co] $RPM_BUILD_ROOT%{python_sitearch}/qubes
cp qvm-core/qubesutils.py $RPM_BUILD_ROOT%{python_sitearch}/qubes
cp qvm-core/qubesutils.py[co] $RPM_BUILD_ROOT%{python_sitearch}/qubes
cp qvm-core/guihelpers.py $RPM_BUILD_ROOT%{python_sitearch}/qubes
cp qvm-core/guihelpers.py[co] $RPM_BUILD_ROOT%{python_sitearch}/qubes
cp qvm-core/__init__.py $RPM_BUILD_ROOT%{python_sitearch}/qubes
cp qvm-core/__init__.py[co] $RPM_BUILD_ROOT%{python_sitearch}/qubes
cp qmemman/qmemman*py $RPM_BUILD_ROOT%{python_sitearch}/qubes
@ -303,6 +305,9 @@ fi
%{python_sitearch}/qubes/qubesutils.py
%{python_sitearch}/qubes/qubesutils.pyc
%{python_sitearch}/qubes/qubesutils.pyo
%{python_sitearch}/qubes/guihelpers.py
%{python_sitearch}/qubes/guihelpers.pyc
%{python_sitearch}/qubes/guihelpers.pyo
%{python_sitearch}/qubes/__init__.py
%{python_sitearch}/qubes/__init__.pyc
%{python_sitearch}/qubes/__init__.pyo
@ -358,11 +363,11 @@ fi
/usr/lib/qubes/qubes_rpc_multiplexer
/usr/lib/qubes/qrexec_policy
%dir /etc/qubes_rpc/policy
/etc/qubes_rpc/policy/qubes.Filecopy
/etc/qubes_rpc/policy/qubes.OpenInVM
/etc/qubes_rpc/policy/qubes.SyncAppMenus
/etc/qubes_rpc/policy//qubes.ReceiveUpdates
/etc/qubes_rpc/policy/qubes.VMShell
%attr(0664,root,qubes) /etc/qubes_rpc/policy/qubes.Filecopy
%attr(0664,root,qubes) /etc/qubes_rpc/policy/qubes.OpenInVM
%attr(0664,root,qubes) /etc/qubes_rpc/policy/qubes.SyncAppMenus
%attr(0664,root,qubes) /etc/qubes_rpc/policy/qubes.ReceiveUpdates
%attr(0664,root,qubes) /etc/qubes_rpc/policy/qubes.VMShell
/etc/qubes_rpc/qubes.SyncAppMenus
/etc/qubes_rpc/qubes.ReceiveUpdates
%attr(4750,root,qubes) /usr/lib/qubes/qrexec_daemon