Initial public commit.

(c) 2010 Invisible Things Lab

Authors:
=========
Joanna Rutkowska <joanna@invisiblethingslab.com>
Rafal Wojtczuk  <rafal@invisiblethingslab.com>
This commit is contained in:
Joanna Rutkowska 2010-04-05 20:58:57 +02:00
commit a17989470a
65 changed files with 4889 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
rpm/
*.pyc

18
Makefile Normal file
View File

@ -0,0 +1,18 @@
RPMS_DIR=rpm/
help:
@echo "make rpms -- generate binary rpm packages"
@echo "make update_repo -- copy newly generated rpms to qubes yum repo"
rpms:
rpmbuild --define "_rpmdir $(RPMS_DIR)" -bb rpm_spec/core-appvm.spec
rpmbuild --define "_rpmdir $(RPMS_DIR)" -bb rpm_spec/core-netvm.spec
rpmbuild --define "_rpmdir $(RPMS_DIR)" -bb rpm_spec/core-dom0.spec
rpmbuild --define "_rpmdir $(RPMS_DIR)" -bb rpm_spec/dom0-cleanup.spec
rpm --addsign $(RPMS_DIR)/x86_64/*.rpm
update_repo:
ln -f $(RPMS_DIR)/x86_64/*.rpm ../yum/rpm/
(if [ -d $(RPMS_DIR)/i686 ] ; then ln -f $(RPMS_DIR)/i686/*.rpm ../yum/rpm/; fi)
clean:
(cd appvm && make clean)

16
TODO Normal file
View File

@ -0,0 +1,16 @@
* file exchange -- handle correctly files that have spaces in name
-- qvm-copy-to-vm* do not copy files in the top directory has spaces in the name
* qvm-update-appmenus
-- let the user install appmenus for (potential) new apps after template update
-- BUT: potential problem of Dom0 needing to mount the template's fs
-- but: perhaps we should trust the template and its update process?
* netvm: prevent inter-VM networking
-- do not allow one AppVM to send any packets to other AppVMs that use the same netvm
* qvm-prefs: allow to grow/shrink AppVM's private.img?
* Dom0 udev scripts: do not load network drivers at all!
* Dom0: detect when running without VT-d enabled and display a warning

9
appvm/Makefile Normal file
View File

@ -0,0 +1,9 @@
CC=gcc
CFLAGS=-Wall
all: qubes_penctl qubes_add_pendrive_script
qubes_penctl: qubes_penctl.o
$(CC) -o qubes_penctl qubes_penctl.o -lxenstore
qubes_add_pendrive_script: qubes_add_pendrive_script.o
$(CC) -o qubes_add_pendrive_script qubes_add_pendrive_script.o
clean:
rm -f qubes_penctl qubes_add_pendrive_script *.o *~

17
appvm/fstab Normal file
View File

@ -0,0 +1,17 @@
#
# /etc/fstab
# Created by anaconda on Thu Dec 3 11:26:49 2009
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/dmroot / ext4 defaults,noatime 1 1
/dev/mapper/dmswap swap swap defaults 0 0
/dev/xvdb /rw ext4 defaults 0 0
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
/dev/xvdg /mnt/outgoing vfat noauto,user,rw 0 0
/dev/xvdh /mnt/incoming vfat noauto,user,rw 0 0

12
appvm/iptables Normal file
View File

@ -0,0 +1,12 @@
# Firewall configuration written by system-config-firewall
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT

1
appvm/qubes.rules Normal file
View File

@ -0,0 +1 @@
SUBSYSTEM=="block", KERNEL=="xvdh", ACTION=="add", RUN+="/usr/bin/qubes_add_pendrive_script"

View File

@ -0,0 +1,87 @@
/*
* The Qubes OS Project, http://www.qubes-os.org
*
* Copyright (C) 2010 Rafal Wojtczuk <rafal@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.
*
*/
#include <stdio.h>
#include <unistd.h>
#include <sys/inotify.h>
#include <fcntl.h>
#include <stdlib.h>
int parse_events(char *buf, int len)
{
int i = 0;
while (i < len) {
struct inotify_event *ev = (struct inotify_event *)(buf + i);
if ((ev->mask & IN_UNMOUNT) || (ev->mask & IN_IGNORED))
return 1;
i += sizeof(struct inotify_event) + ev->len;
}
return 0;
}
#define BUFLEN 1024
void wait_for_umount(char *name)
{
char buf[BUFLEN];
int fd = inotify_init();
int len;
int ret = inotify_add_watch(fd, name, IN_ATTRIB);
if (ret < 0) {
perror("inotify_add_watch");
return;
}
for (;;) {
len = read(fd, buf, BUFLEN - 1);
if (len <= 0) {
perror("read inotify");
return;
}
if (parse_events(buf, len))
return;
}
}
void background()
{
int i, fd;
for (i = 0; i < 256; i++)
close(i);
fd = open("/dev/null", O_RDWR);
for (i = 0; i <= 2; i++)
dup2(fd, i);
switch (fork()) {
case -1:
exit(1);
case 0: break;
default:
exit(0);
}
}
#define MOUNTDIR "/mnt/incoming"
int main()
{
background();
if (!system("su - user -c 'mount " MOUNTDIR "'"))
wait_for_umount(MOUNTDIR "/.");
system("xenstore-write device/qpen umount");
return 0;
}

87
appvm/qubes_core Executable file
View File

@ -0,0 +1,87 @@
#!/bin/sh
#
# chkconfig: 345 90 90
# description: Executes Qubes core scripts at VM boot
#
# Source function library.
. /etc/rc.d/init.d/functions
start()
{
echo -n $"Executing Qubes Core scripts:"
if ! [ -d /rw/home ] ; then
echo
echo "--> Virgin boot of the VM: Linking /home to /rw/home"
mv /home /home.orig
mkdir -p /rw/config
mkdir -p /rw/home
ln -s /rw/home/ /home
# chcon --reference /home.orig /rw/home
cp -a /home.orig/user /home
touch /rw/config/rc.local
rm -fr /home.orig
touch /var/lib/qubes/first_boot_completed
else
mv /home /home.tmpl
ln -s /rw/home/ /home
fi
if ! [ -x /usr/bin/xenstore-read ] ; then
echo "ERROR: /usr/bin/xenstore-read not found!"
exit 1
fi
name=$(/usr/bin/xenstore-read name)
hostname $name
vmtype=$(/usr/bin/xenstore-read qubes_vm_type)
if [ $vmtype == 'NetVM' ] ; then
# Setup gateway for all the VMs this netVM is serviceing...
brctl addbr br0
gateway=$(/usr/bin/xenstore-read qubes_netvm_gateway)
netmask=$(/usr/bin/xenstore-read qubes_netvm_netmask)
network=$(/usr/bin/xenstore-read qubes_netvm_network)
ifconfig br0 $gateway netmask $netmask up
echo "1" > /proc/sys/net/ipv4/ip_forward
dnsmasq
iptables -t nat -A POSTROUTING -s $network/$netmask -j MASQUERADE
else
ip=$(/usr/bin/xenstore-read qubes_ip)
netmask=$(/usr/bin/xenstore-read qubes_netmask)
gateway=$(/usr/bin/xenstore-read qubes_gateway)
if [ x$ip != x ]; then
/sbin/ifconfig eth0 $ip netmask $netmask up
/sbin/route add default gw $gateway
echo "nameserver $gateway" > /etc/resolv.conf
fi
fi
[ -x /rw/config/rc.local ] && /rw/config/rc.local
success
echo ""
return 0
}
stop()
{
return 0
}
case "$1" in
start)
start
;;
stop)
stop
;;
*)
echo $"Usage: $0 {start|stop}"
exit 3
;;
esac
exit $RETVAL

71
appvm/qubes_penctl.c Normal file
View File

@ -0,0 +1,71 @@
/*
* The Qubes OS Project, http://www.qubes-os.org
*
* Copyright (C) 2010 Rafal Wojtczuk <rafal@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.
*
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <xs.h>
int check_name(unsigned char *s)
{
int c;
for (; *s; s++) {
c = *s;
if (c >= 'a' && c <= 'z')
continue;
if (c >= 'A' && c <= 'Z')
continue;
if (c == '_' || c == '-')
continue;
return 0;
}
return 1;
}
int main(int argc, char **argv)
{
char buf[256] = "new";
struct xs_handle *xs;
xs = xs_domain_open();
setuid(getuid());
if (!xs) {
perror("xs_domain_open");
exit(1);
}
if (argc < 2) {
fprintf(stderr, "usage: %s new\n"
"%s send vmname\n", argv[0], argv[0]);
exit(1);
}
if (argc > 2) {
if (!check_name((unsigned char*)argv[2])) {
fprintf(stderr, "invalid vmname %s\n", argv[2]);
exit(1);
}
snprintf(buf, sizeof(buf), "send %s", argv[2]);
}
if (!xs_write(xs, 0, "device/qpen", buf, strlen(buf))) {
perror("xs_write");
exit(1);
}
xs_daemon_close(xs);
return 0;
}

40
appvm/qvm-copy-to-vm Executable file
View File

@ -0,0 +1,40 @@
#!/bin/sh
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Rafal Wojtczuk <rafal@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.
#
#
if [ $# -lt 2 ] ; then
echo usage: $0 'vmname file [file]*'
exit 1
fi
qubes_penctl new || exit 1
echo -n Waiting for the Qubes virtual pendrive
while ! [ -e /dev/xvdg ] ; do
echo -n .
sleep 1
done
echo " received"
mount /mnt/outgoing
VMNAME=$1
shift
cp -v -a $* /mnt/outgoing
#sometimes Dolphin lags a bit
umount /mnt/outgoing || (sleep 1; umount /mnt/outgoing) || exit 1
qubes_penctl send $VMNAME || exit 1

42
appvm/qvm-copy-to-vm.kde Executable file
View File

@ -0,0 +1,42 @@
#!/bin/sh
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Rafal Wojtczuk <rafal@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.
#
#
FILES="$*"
VM=$(kdialog -inputbox "Enter the VM name to send $FILE to:")
if [ X$VM = X ] ; then exit 0 ; fi
DEST=/mnt/outgoing
SIZE=$(du -c $FILES | tail -1 | cut -f 1)
REF=$(kdialog --progressbar "Copy progress")
qdbus $REF org.freedesktop.DBus.Properties.Set "" maximum $SIZE
FLAG=$(mktemp)
(qvm-copy-to-vm $VM $FILES ; rm $FLAG) &
while ! grep -q $DEST /proc/mounts && [ -f $FLAG ] ; do
sleep 0.1
done
while grep -q $DEST /proc/mounts ; do
CURRSIZE=$(du -c $DEST | tail -1 | cut -f 1)
qdbus $REF org.freedesktop.DBus.Properties.Set "" value $CURRSIZE
sleep 1
done
qdbus $REF close

10
appvm/qvm-copy.desktop Normal file
View File

@ -0,0 +1,10 @@
[Desktop Entry]
Actions=QvmCopy;
Type=Service
X-KDE-ServiceTypes=KonqPopupMenu/Plugin,inode/directory,all/allfiles
[Desktop Action QvmCopy]
Exec=/usr/bin/qvm-copy-to-vm.kde %U
Icon=kget
Name=Send To VM

View File

@ -0,0 +1,14 @@
#!/bin/sh
if grep -q X-Qubes-VmName $1 ; then
exit 0
fi
if grep -q "Categories=.*\(System\|Settings\)" $1 ; then
#echo "Leaving file: $1"
exit 0
fi
BACKUP_DIR="/var/lib/qubes/backup/removed-apps/"
mkdir -p $BACKUP_DIR
#echo "Moving file: $1 to $BACKUP_DIR
mv $1 $BACKUP_DIR

View File

@ -0,0 +1,13 @@
#!/bin/sh
SRC=$1
DSTDIR=$2
VMNAME=$3
VMDIR=$4
DST=$DSTDIR/$VMNAME-$(basename $SRC)
sed -e "s/%VMNAME%/$VMNAME/" \
-e "s %VMDIR% $VMDIR " \
<$SRC >$DST

View File

@ -0,0 +1,11 @@
#!/bin/sh
SRC=$1
DST=$2
VMNAME=$3
VMDIR=$4
sed -e "s/%VMNAME%/$VMNAME/" \
-e "s %VMDIR% $VMDIR " \
<$SRC >$DST

View File

@ -0,0 +1,41 @@
#!/bin/sh
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
SRCDIR=$1
VMNAME=$2
VMDIR=/var/lib/qubes/appvms/$VMNAME
APPSDIR=$VMDIR/apps
if [ $# != 2 ]; then
echo "usage: $0 <apps_templates_dir> <vmname>"
exit
fi
mkdir -p $APPSDIR
echo "--> Converting Appmenu Templates..."
find $SRCDIR -name "*.desktop" -exec /usr/lib/qubes/convert_apptemplate2vm.sh {} $APPSDIR $VMNAME $VMDIR \;
/usr/lib/qubes/convert_dirtemplate2vm.sh $SRCDIR/qubes-vm.directory.template $APPSDIR/$VMNAME-vm.directory $VMNAME $VMDIR
echo "--> Adding Apps to the Menu..."
xdg-desktop-menu install $APPSDIR/*.directory $APPSDIR/*.desktop

View File

@ -0,0 +1,82 @@
#!/bin/sh
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
#
# This script can be used to patch the initramfs of the Qubes AppVM
# It inserts an additional script that is responsible for setting up
# COW-based root fs and VM private fs
#
INITRAMFS=$1
INITRAMFS_QUBES=$2
QUBES_COW_SETUP_FILE=$3
TMP_DIR=`mktemp -d /tmp/qubes-initramfs-patching-XXXXXXX`
if [ $# != 3 ] ; then
echo "usage: $0 <original initramfs to patch> <patched initramfs file> <qubes_cow_setup_file>"
exit 0
fi
if [ x$INITRAMFS = x ] ; then
echo "INITRAMFS missing!"
exit 1
fi
if [ x$INITRAMFS_QUBES = x ] ; then
echo "INITRAMFS_QUBES missing!"
exit 1
fi
if [ x$QUBES_COW_SETUP_FILE = x ] ; then
echo "$QUBES_COW_SETUP_FILE missing!"
exit 1
fi
ID=$(id -ur)
if [ $ID != 0 ] ; then
echo "This script should be run as root user. Apparently the initramfs files must have root.root owener..."
exit 1
fi
mkdir $TMP_DIR/initramfs.qubes || exit 1
cp $INITRAMFS $TMP_DIR/initramfs.cpio.gz
pushd $TMP_DIR/initramfs.qubes
gunzip < ../initramfs.cpio.gz | cpio -i --quiet || exit 1
cp $QUBES_COW_SETUP_FILE pre-trigger/90_qubes_cow_setup.sh || exit 1
find ./ | cpio -H newc -o --quiet > $TMP_DIR/initramfs.qubes.cpio || exit 1
popd
gzip $TMP_DIR/initramfs.qubes.cpio || exit 1
mv $TMP_DIR/initramfs.qubes.cpio.gz $INITRAMFS_QUBES || exit 1
rm -fr $TMP_DIR || exit 1

View File

@ -0,0 +1,12 @@
#!/bin/sh
VMNAME=$1
VMDIR=/var/lib/qubes/appvms/$VMNAME
APPSDIR=$VMDIR/apps
if [ $# != 1 ]; then
echo "usage: $0 <vmname>"
exit
fi
xdg-desktop-menu uninstall $APPSDIR/*.directory $APPSDIR/*.desktop

View File

@ -0,0 +1,6 @@
#!/bin/sh
echo "--> Removing unnecessary Dom0 Appmenus..."
find /usr/share/applications -name *.desktop -exec /usr/lib/qubes/check_and_remove_appmenu.sh {} \;
xdg-desktop-menu forceupdate

View File

@ -0,0 +1,74 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from optparse import OptionParser
import subprocess
import shutil
import re
def find_net_devices():
p = subprocess.Popen (["lspci", "-mm", "-n"], stdout=subprocess.PIPE)
result = p.communicate()
retcode = p.returncode
if (retcode != 0):
print "ERROR when executing lspci!"
raise IOError
net_devices = set()
rx_netdev = re.compile (r"^([0-9][0-9]:[0-9][0-9].[0-9]) \"02")
for dev in str(result[0]).splitlines():
match = rx_netdev.match (dev)
if match is not None:
dev_bdf = match.group(1)
assert dev_bdf is not None
net_devices.add (dev_bdf)
return net_devices
def main():
usage = "usage: %prog [options] <netvm-name>"
parser = OptionParser (usage)
parser.add_option ("-v", "--verbose", dest="verbose", action="store_true", default=False)
(options, args) = parser.parse_args ()
if options.verbose:
print "Loading Xen PCI Backend..."
retcode = subprocess.call (["/sbin/modprobe", "xen-pciback"])
if retcode != 0:
print "ERROR: Cannot load xen-pciback module!"
exit(1)
if options.verbose:
print "Unbinding the following net devices:"
net_devices = find_net_devices()
for dev in net_devices:
if options.verbose:
print "--> {0}".format(dev)
retcode = subprocess.call (["/usr/lib/qubes/unbind_pci_device.sh", dev])
if (retcode != 0):
print "WARNING: Could not unbind device {0}".format(dev)
main()

View File

@ -0,0 +1,35 @@
#!/bin/sh
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
BDF=$1
if [ x$BDF = x ] ; then
echo "usage: $0 <BDF>"
exit 0
fi
BDF=0000:$BDF
#echo -n "Binding device $BDF to xen-pciback..."
if [ -e /sys/bus/pci/devices/$BDF/driver/unbind ] ; then
echo -n $BDF > /sys/bus/pci/devices/$BDF/driver/unbind || exit 1
fi
echo -n $BDF > /sys/bus/pci/drivers/pciback/new_slot || exit 1
echo -n $BDF > /sys/bus/pci/drivers/pciback/bind || exit 1
#echo ok

85
dom0/clipboard_notifier/qclipd Executable file
View File

@ -0,0 +1,85 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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 os
import daemon
from pyinotify import WatchManager, Notifier, ThreadedNotifier, EventsCodes, ProcessEvent
import dbus
from qubes.qubes import QubesDaemonPidfile
qubes_clipboard_info_file = "/var/run/qubes/qubes_clipboard.bin.source"
def watch_qubes_clipboard():
def tray_notify(str, timeout = 3000):
notify_object.Notify("Qubes", 0, "dialog-information", "", str, [], [], timeout, dbus_interface="org.freedesktop.Notifications")
notify_object = dbus.SessionBus().get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
wm = WatchManager()
mask = EventsCodes.OP_FLAGS.get('IN_CLOSE_WRITE')
if not os.path.exists (qubes_clipboard_info_file):
file = open (qubes_clipboard_info_file, 'w')
file.close()
class ClipboardWatcher(ProcessEvent):
def process_IN_CLOSE_WRITE (self, event):
src_info_file = open (qubes_clipboard_info_file, 'r')
src_vmname = src_info_file.readline().strip('\n')
if src_vmname == "":
tray_notify ("Qubes Clipboard has been copied to the VM and wiped.\n"\
"<small>Trigger a paste operation (e.g. Ctrl-v) to insert it into an application.</small>" )
else:
print src_vmname
tray_notify ("Qubes Clipboard fetched from VM: <b>'{0}'</b>\n"\
"<small>Press Ctrl-Shift-v to copy this clipboard onto dest VM's clipboard.</small>".format(src_vmname))
src_info_file.close()
notifier = Notifier(wm, ClipboardWatcher())
wdd = wm.add_watch(qubes_clipboard_info_file, mask)
while True:
notifier.process_events()
if notifier.check_events():
notifier.read_events()
def main():
lock = QubesDaemonPidfile ("qclipd")
if lock.pidfile_exists():
if lock.pidfile_is_stale():
lock.remove_pidfile()
print "Removed stale pidfile (has the previous daemon instance crashed?)."
else:
exit (0)
context = daemon.DaemonContext(
working_directory = "/var/run/qubes",
pidfile = lock)
with context:
watch_qubes_clipboard()
main()

BIN
dom0/icons/black.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 169 KiB

BIN
dom0/icons/blue.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

View File

@ -0,0 +1,10 @@
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
This copyright and license notice covers the images in this directory.
************************************************************************
TITLE: Crystal Project Icons
AUTHOR: Everaldo Coelho
SITE: http://www.everaldo.com
CONTACT: everaldo@everaldo.com
Copyright (c) 2006-2007 Everaldo Coelho.

View File

@ -0,0 +1 @@
Color padlock images downloaded from www.openclipart.org

BIN
dom0/icons/gray.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

BIN
dom0/icons/green.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 KiB

BIN
dom0/icons/netvm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
dom0/icons/orange.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

BIN
dom0/icons/purple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

BIN
dom0/icons/red.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

BIN
dom0/icons/template.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
dom0/icons/yellow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

63
dom0/init.d/qubes_core Executable file
View File

@ -0,0 +1,63 @@
#!/bin/sh
#
# chkconfig: 2345 99 00
# description: Executes Qubes core scripts at Dom0 boot
#
### BEGIN INIT INFO
# Provides: qubes-core
# Required-Start: xend
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Default-Enabled: yes
# Short-Description: Start/stop qubes-core services
# Description: Starts and stops the qubes-core serives
### END INIT INFO
# Source function library.
. /etc/rc.d/init.d/functions
start()
{
echo -n $"Executing Qubes Core scripts:"
chgrp qubes /etc/xen
chmod 710 /etc/xen
chgrp qubes /var/run/xend
chmod 710 /var/run/xend
chgrp qubes /var/run/xend/xen-api.sock /var/run/xend/xmlrpc.sock
chmod 660 /var/run/xend/xen-api.sock /var/run/xend/xmlrpc.sock
chgrp qubes /var/run/xenstored/*
chmod 660 /var/run/xenstored/*
xm sched-credit -d 0 -w 65535
cp /var/lib/qubes/qubes.xml /var/lib/qubes/backup/qubes-$(date +%F-%T).xml
touch /var/lock/subsys/qubes_core
success
echo
}
stop()
{
echo -n $"Shutting down all Qubes VMs:"
NETVM=$(qvm-get-default-netvm)
qvm-run -q --shutdown --all --wait --exclude $NETVM
rm -f /var/lock/subsys/qubes_core
success
echo
}
case "$1" in
start)
start
;;
stop)
stop
;;
*)
echo $"Usage: $0 {start|stop}"
exit 3
;;
esac
exit $RETVAL

102
dom0/init.d/qubes_netvm Executable file
View File

@ -0,0 +1,102 @@
#!/bin/sh
#
# chkconfig: 2345 99 00
# description: Starts/stops Qubes default netvm
#
### BEGIN INIT INFO
# Provides: qubes-networking
# Required-Start: qubes-core
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Default-Enabled: yes
# Short-Description: Start/stop qubes networking
# Description: Starts and stops the qubes networking
### END INIT INFO
#
# Source function library.
. /etc/rc.d/init.d/functions
NETVM=$(qvm-get-default-netvm)
start()
{
if [ x$NETVM = x ] ; then
echo WARNING: Qubes NetVM not configured!
echo -n $"Doing nothing:"
elif [ $NETVM = "dom0" ] ; then
echo -n $"Setting up net backend in Dom0:"
/etc/init.d/NetworkManager start
brctl addbr br0 || exit 1
ifconfig br0 10.0.0.1 netmask 255.255.0.0 up || exit 1
echo "1" > /proc/sys/net/ipv4/ip_forward || exit 1
/usr/sbin/dnsmasq --listen-address 10.0.0.1 --bind-interfaces || exit 1
iptables -t nat -A POSTROUTING -s 10.0.0.0/16 '!' -d 10.0.0.0/16 -j MASQUERADE || exit 1
iptables -I INPUT 1 -i br0 -s 10.0.0.0/16 -j ACCEPT || exit 1
iptables -I FORWARD 1 -i br0 -s 10.0.0.0/16 -j ACCEPT || exit 1
iptables -I FORWARD 1 -o br0 -d 10.0.0.0/16 -m state --state ESTABLISHED,RELATED -j ACCEPT || exit 1
else
echo -n $"Starting default NetVM:"
/usr/lib/qubes/unbind_all_network_devices || exit 1
qvm-start -q --no-guid $NETVM || exit 1
fi
touch /var/lock/subsys/qubes_netvm
success
echo
return 0
}
stop()
{
if [ x$NETVM = x ] ; then
echo WARNING: Qubes NetVM not configured!
echo -n $"Doing nothing:"
elif [ $NETVM = "dom0" ] ; then
echo -n $"Stopping Qubes networking in Dom0:"
iptables -t nat -D POSTROUTING -s 10.0.0.0/16 '!' -d 10.0.0.0/16 -j MASQUERADE
iptables -D INPUT -i br0 -s 10.0.0.0/16 -j ACCEPT || exit 1
iptables -D FORWARD -i br0 -s 10.0.0.0/16 -j ACCEPT || exit 1
iptables -D FORWARD -o br0 -d 10.0.0.0/16 -m state --state ESTABLISHED,RELATED -j ACCEPT || exit 1
killall dnsmasq
ifconfig br0 down
brctl delbr br0
else
echo -n $"Stopping default NetVM:"
qvm-run -q --shutdown --wait $NETVM
fi
rm -f /var/lock/subsys/qubes_netvm
success
echo
return 0
}
case "$1" in
start)
start
;;
stop)
stop
;;
*)
echo $"Usage: $0 {start|stop}"
exit 3
;;
esac
exit $RETVAL

223
dom0/pendrive_swapper/qfilexchgd Executable file
View File

@ -0,0 +1,223 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Rafal Wojtczuk <rafal@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 xen.lowlevel.xs
import os
import sys
import subprocess
import daemon
import time
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException
from qubes.qubes import QubesDaemonPidfile
filename_seq = 50
pen_cmd = '/usr/lib/qubes/qubes_pencmd'
def get_next_filename_seq():
global filename_seq
filename_seq = filename_seq + 1
return str(filename_seq)
def logproc(msg):
f = file('/var/log/qubes/qfileexchgd', 'a')
f.write(msg+'\n')
f.close()
def get_req_node(domain_id):
return '/local/domain/'+domain_id+'/device/qpen'
def get_name_node(domain_id):
return '/local/domain/'+domain_id+'/name'
def only_in_first_list(l1, l2):
ret=[]
for i in l1:
if not i in l2:
ret.append(i)
return ret
class WatchType:
def __init__(self, fn, param):
self.fn = fn
self.param = param
class DomainState:
def __init__(self, domain, dict):
self.rcv_state = 'idle'
self.send_state = 'idle'
self.domain_id = domain
self.domdict = dict
self.send_seq = None
self.rcv_seq = None
self.waiting_sender = None
def handle_request(self, request):
req_ok = False
if request is None:
return
tmp = request.split()
rq = tmp[0]
if len(tmp) > 1:
arg = tmp[1]
else:
arg = None
if rq == 'new' and self.send_state == 'idle':
self.send_seq = get_next_filename_seq()
retcode = subprocess.call([pen_cmd, 'new', self.domain_id, self.send_seq])
logproc( 'Give domain ' + self.domain_id + ' a clean pendrive, retcode= ' + str(retcode))
if retcode == 0:
self.send_state = 'has_clean_pendrive'
req_ok = True
if rq == 'send' and self.send_state == 'has_clean_pendrive' and arg is not None:
logproc( 'send from ' + self.domain_id + ' to ' + arg)
if self.handle_transfer(arg):
self.send_state = 'idle'
req_ok = True;
if rq == 'umount' and self.rcv_state == 'has_loaded_pendrive':
retcode = subprocess.call([pen_cmd, 'umount', self.domain_id, self.rcv_seq])
if retcode == 0:
self.rcv_state = 'idle'
self.rcv_seq = None
logproc( 'set state of ' + self.domain_id + ' loaded->idle retcode=' + str(retcode))
req_ok = True
if rq == 'umount' and self.rcv_state == 'waits_to_umount':
req_ok = True
retcode = subprocess.call([pen_cmd, 'umount', self.domain_id, self.rcv_seq])
if retcode != 0:
return
assert(self.waiting_sender != None)
self.rcv_state = 'idle'
self.rcv_seq = None
tmp = self.waiting_sender
self.waiting_sender = None
if tmp.send_state == 'has_clean_pendrive':
if tmp.handle_transfer(self.name):
tmp.send_state = 'idle'
if not req_ok:
logproc( 'request ' + request + ' not served due to nonmatching state')
def ask_to_umount(self, vmname):
q = 'VM ' + vmname + ' has already an incoming pendrive, and thus '
q+= 'cannot accept another one. If you intend to unmount its current '
q+= 'pendrive and retry this transfer, press Yes. '
q+= 'Otherwise press No to fail this transfer.'
retcode = subprocess.call(['/usr/bin/kdialog', '--yesno', q, '--title', 'Some additional action required'])
if retcode == 0:
return True
else:
return False
def handle_transfer(self, vmname):
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None:
logproc( 'Domain ' + vmname + ' does not exist ?')
return False
if not vm.is_running():
logproc( 'Domain ' + vmname + ' is not running ?')
return False
target=self.domdict[str(vm.get_xid())]
if target.rcv_state != 'idle':
if self.ask_to_umount(vmname):
target.rcv_state='waits_to_umount'
target.waiting_sender=self
logproc( 'target domain ' + target.domain_id + ' is not idle, now ' + target.rcv_state)
return False
retcode = subprocess.call(['/usr/bin/kdialog', '--yesno', 'Do you authorize pendrive transfer from ' + self.name + ' to ' + vmname + '?' , '--title', 'Security confirmation'])
logproc('handle_transfer: kdialog retcode=' + str(retcode))
if retcode != 0:
return False
target.rcv_state='has_loaded_pendrive'
retcode = subprocess.call([pen_cmd, 'send', self.domain_id, target.domain_id, self.send_seq])
target.rcv_seq = self.send_seq
self.send_seq = None
logproc( 'set state of ' + target.domain_id + ' to has_loaded_pendrive, retcode=' + str(retcode))
return True
class XS_Watcher:
def __init__(self):
self.handle = xen.lowlevel.xs.xs()
self.handle.watch('/local/domain', WatchType(XS_Watcher.dom_list_change, None))
self.domdict = {}
def dom_list_change(self, param):
curr = self.handle.ls('', '/local/domain')
if curr == None:
return
for i in only_in_first_list(curr, self.domdict.keys()):
newdom = DomainState(i, self.domdict)
newdom.watch_token = WatchType(XS_Watcher.request, newdom)
newdom.watch_name = WatchType(XS_Watcher.namechange, newdom)
self.domdict[i] = newdom
self.handle.watch(get_req_node(i), newdom.watch_token)
self.handle.watch(get_name_node(i), newdom.watch_name)
newdom.name = ''
logproc( 'added domain ' + i)
for i in only_in_first_list(self.domdict.keys(), curr):
self.handle.unwatch(get_req_node(i), self.domdict[i].watch_token)
self.handle.unwatch(get_name_node(i), self.domdict[i].watch_name)
self.domdict.pop(i)
logproc( 'removed domain ' + i)
def request(self, domain_param):
ret = self.handle.read('', get_req_node(domain_param.domain_id))
domain_param.handle_request(ret)
def namechange(self, domain_param):
ret = self.handle.read('', get_name_node(domain_param.domain_id))
if ret!= '' and ret!=None:
domain_param.name = ret
logproc( 'Name for domain xid ' + domain_param.domain_id + ' is ' + ret )
def watch_loop(self):
sys.stderr = file('/var/log/qubes/qfileexchgd.errors', 'a')
while True:
result = self.handle.read_watch()
token = result[1]
token.fn(self, token.param)
def main():
lock = QubesDaemonPidfile ("qfileexchgd")
if lock.pidfile_exists():
if lock.pidfile_is_stale():
lock.remove_pidfile()
print "Removed stale pidfile (has the previous daemon instance crashed?)."
else:
exit (0)
context = daemon.DaemonContext(
working_directory = "/var/run/qubes",
pidfile = lock)
with context:
XS_Watcher().watch_loop()
main()

View File

@ -0,0 +1,74 @@
#!/bin/sh
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Rafal Wojtczuk <rafal@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.
#
#
SHARE_DIR=/var/run/qubes
function do_new()
{
FILE=$SHARE_DIR/pendrive.$2
truncate -s 1G $FILE || exit 1
vmname=$(xenstore-read /local/domain/$1/name)
mkfs.vfat -n "$vmname" $FILE || exit 1
xm block-attach $1 file:/$FILE /dev/xvdg w || exit 1
}
function do_umount()
{
xm block-detach $1 /dev/xvdh || exit 1
rm $SHARE_DIR/pendrive.$2
}
function do_send()
{
FILE=$SHARE_DIR/pendrive.$3
vmname=$(xenstore-read /local/domain/$1/name)
xenstore-write /local/domain/$2/qubes_blocksrc $vmname
xm block-detach $1 /dev/xvdg || exit 1
xm block-attach $2 file:/$FILE /dev/xvdh w || exit 1
}
if [ $# -lt 1 ] ; then
echo args missing ?
exit 1
fi
if [ "$1" = "new" ] ; then
if ! [ $# = 3 ] ; then
echo new requires 2 more args
exit 1
fi
do_new "$2" "$3"
elif [ "$1" = "umount" ] ; then
if ! [ $# = 3 ] ; then
echo umount requires 2 more args
exit 1
fi
do_umount "$2" "$3"
elif [ "$1" = "send" ] ; then
if ! [ $# = 4 ] ; then
echo send requires 3 more args
exit 1
fi
do_send "$2" "$3" "$4"
else
echo bad cmd
exit 1
fi

View File

1515
dom0/qvm-core/qubes.py Executable file

File diff suppressed because it is too large Load Diff

82
dom0/qvm-tools/qvm-add-appvm Executable file
View File

@ -0,0 +1,82 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException
from optparse import OptionParser;
def main():
usage = "usage: %prog [options] <appvm-name> <vm-template-name>\n\n"\
"Adds an already installed appvm to the Qubes DB\n"\
"WARNING: Noramlly you would not need this command,\n"\
"and you would use qvm-create instead!"
parser = OptionParser (usage)
parser.add_option ("-p", "--path", dest="dir_path",
help="Specify path to the template directory")
parser.add_option ("-c", "--conf", dest="conf_file",
help="Specify the Xen VM .conf file to use\
(relative to the template dir path)")
(options, args) = parser.parse_args ()
if (len (args) != 2):
parser.error ("You must specify at least the AppVM and TemplateVM names!")
vmname = args[0]
templatename = args[1]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
if qvm_collection.get_vm_by_name(vmname) is not None:
print "ERROR: A VM with the name '{0}' already exists in the system.".format(vmname)
exit(1)
template_vm = qvm_collection.get_vm_by_name(templatename)
if template_vm is None:
print "ERROR: A Template VM with the name '{0}' does not exist in the system.".format(templatename)
exit(1)
vm = qvm_collection.add_new_appvm(vmname, template_vm,
conf_file=options.conf_file,
dir_path=options.dir_path)
try:
vm.verify_files()
except QubesException as err:
print "ERROR: {0}".format(err)
qvm_collection.pop(vm.qid)
exit (1)
try:
vm.add_to_xen_storage()
except (IOError, OSError) as err:
print "ERROR: {0}".format(err)
qvm_collection.pop(vm.qid)
exit (1)
qvm_collection.save()
qvm_collection.unlock_db()
main()

119
dom0/qvm-tools/qvm-add-netvm Executable file
View File

@ -0,0 +1,119 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from optparse import OptionParser
import subprocess
import shutil
import re
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException
def find_net_devices():
p = subprocess.Popen (["lspci", "-mm", "-n"], stdout=subprocess.PIPE)
result = p.communicate()
retcode = p.returncode
if (retcode != 0):
print "ERROR when executing lspci!"
raise IOError
net_devices = set()
rx_netdev = re.compile (r"^([0-9][0-9]:[0-9][0-9].[0-9]) \"02")
for dev in str(result[0]).splitlines():
match = rx_netdev.match (dev)
if match is not None:
dev_bdf = match.group(1)
assert dev_bdf is not None
net_devices.add (dev_bdf)
return net_devices
def main():
usage = "usage: %prog [options] <netvm-name>"
parser = OptionParser (usage)
parser.add_option ("-p", "--path", dest="dir_path",
help="Specify path to the template directory")
parser.add_option ("-c", "--conf", dest="conf_file",
help="Specify the Xen VM .conf file to use\
(relative to the template dir path)")
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("You must specify a NetVM name!")
netvmname = args[0]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
if qvm_collection.get_vm_by_name(netvmname) is not None:
print "ERROR: A VM with the name '{0}' already exists in the system.".format(netvmname)
exit(1)
vm = qvm_collection.add_new_netvm(netvmname,
conf_file=options.conf_file,
dir_path=options.dir_path)
try:
vm.verify_files()
except QubesException as err:
print "ERROR: {0}".format(err)
qvm_collection.pop(vm.qid)
exit (1)
net_devices = find_net_devices()
print "Found the following net devices in your system:"
dev_str = ''
for dev in net_devices:
print "--> {0}".format(dev)
dev_str += '"{0}", '.format(dev)
print "Assigning them to the netvm '{0}'".format(netvmname)
rx_pcidevs = re.compile (r"%NETVMPCIDEVS%")
conf_template = open (vm.conf_file, "r")
conf_vm = open(vm.conf_file + ".processed", "w")
for line in conf_template:
line = rx_pcidevs.sub(dev_str, line)
conf_vm.write(line)
conf_template.close()
conf_vm.close()
shutil.move (vm.conf_file + ".processed", vm.conf_file)
try:
pass
vm.add_to_xen_storage()
except (IOError, OSError) as err:
print "ERROR: {0}".format(err)
qvm_collection.pop(vm.qid)
exit (1)
qvm_collection.save()
qvm_collection.unlock_db()
main()

78
dom0/qvm-tools/qvm-add-template Executable file
View File

@ -0,0 +1,78 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException
from optparse import OptionParser;
def main():
usage = "usage: %prog [options] <vm-template-name>\n"\
"Adds an already installed template to the Qubes DB"
parser = OptionParser (usage)
parser.add_option ("-p", "--path", dest="dir_path",
help="Specify path to the template directory")
parser.add_option ("-c", "--conf", dest="conf_file",
help="Specify the Xen VM .conf file to use\
(relative to the template dir path)")
parser.add_option ("--rpm", action="store_true", dest="installed_by_rpm",
help="Template files have been installed by RPM", default=False)
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("You must specify at least the TemplateVM name!")
vmname = args[0]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
if qvm_collection.get_vm_by_name(vmname) is not None:
print "ERROR: A VM with the name '{0}' already exists in the system.".format(vmname)
exit(1)
vm = qvm_collection.add_new_templatevm(vmname,
conf_file=options.conf_file,
dir_path=options.dir_path,
installed_by_rpm=options.installed_by_rpm)
try:
vm.verify_files()
except QubesException as err:
print "ERROR: {0}".format(err)
qvm_collection.pop(vm.qid)
exit (1)
try:
vm.add_to_xen_storage()
except (IOError, OSError) as err:
print "ERROR: {0}".format(err)
qvm_collection.pop(vm.qid)
exit (1)
qvm_collection.save()
qvm_collection.unlock_db()
main()

View File

@ -0,0 +1,75 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException
from optparse import OptionParser;
def main():
usage = "usage: %prog [options] <src-template-name> <new-template-name>\n"\
"Clones an existing template by copying all its disk files"
parser = OptionParser (usage)
parser.add_option ("-q", "--quiet", action="store_false", dest="verbose", default=True)
parser.add_option ("-p", "--path", dest="dir_path",
help="Specify path to the template directory")
(options, args) = parser.parse_args ()
if (len (args) != 2):
parser.error ("You must specify at least the src and dst TemplateVM names!")
srcname = args[0]
dstname = args[1]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
src_tvm = qvm_collection.get_vm_by_name(srcname)
if src_tvm is None:
print "ERROR: A VM with the name '{0}' does not exist in the system.".format(srcname)
exit(1)
if qvm_collection.get_vm_by_name(dstname) is not None:
print "ERROR: A VM with the name '{0}' already exists in the system.".format(dstname)
exit(1)
dst_tvm = qvm_collection.clone_templatevm(src_template_vm=src_tvm,
name=dstname,
dir_path=options.dir_path)
try:
dst_tvm.clone_disk_files (src_template_vm=src_tvm, verbose=options.verbose)
if options.verbose:
print "--> Adding to Xen Storage..."
dst_tvm.add_to_xen_storage()
except (IOError, OSError) as err:
print "ERROR: {0}".format(err)
qvm_collection.pop(dst_tvm.qid)
exit (1)
qvm_collection.save()
qvm_collection.unlock_db()
main()

101
dom0/qvm-tools/qvm-create Executable file
View File

@ -0,0 +1,101 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesVmLabels
from optparse import OptionParser;
import subprocess
def main():
usage = "usage: %prog [options] <vm-name>"
parser = OptionParser (usage)
parser.add_option ("-t", "--template", dest="template",
help="Specify the TemplateVM to use")
parser.add_option ("-l", "--label", dest="label",
help="Specify the label to use for the new VM (e.g. red, yellow, green, ...)")
parser.add_option ("-q", "--quiet", action="store_false", dest="verbose", default=True)
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("You must specify VM name!")
vmname = args[0]
if options.label is None:
print "You must choose a label for the new VM by passing the --label option."
print "Possible values are:"
for l in QubesVmLabels.values():
print "* {0}".format(l.name)
exit (1)
if options.label not in QubesVmLabels:
print "Wrong label name, supported values are the following:"
for l in QubesVmLabels.values():
print "* {0}".format(l.name)
exit (1)
label = QubesVmLabels[options.label]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
if qvm_collection.get_vm_by_name(vmname) is not None:
print "A VM with the name '{0}' already exists in the system.".format(vmname)
exit(1)
if options.template is not None:
template_vm = qvm_collection.get_vm_by_name(options.template)
if template_vm is None:
print "There is no (Templete)VM with the name '{0}'".format(options.template)
exit (1)
if not template_vm.is_templete():
print "VM '{0}' is not a TemplateVM".format(options.template)
exit (1)
if (options.verbose):
print "--> Using TemplateVM: {0}".format(template_vm.name)
else:
if qvm_collection.get_default_template_vm() is None:
print "No default TempleteVM defined!"
exit (1)
else:
template_vm = qvm_collection.get_default_template_vm()
if (options.verbose):
print "--> Using default TemplateVM: {0}".format(template_vm.name)
vm = qvm_collection.add_new_appvm(vmname, template_vm, label = label)
try:
vm.create_on_disk(verbose=options.verbose)
vm.add_to_xen_storage()
except (IOError, OSError) as err:
print "ERROR: {0}".format(err)
vm.remove_from_disk()
exit (1)
qvm_collection.save()
qvm_collection.unlock_db()
main()

View File

@ -0,0 +1,39 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from optparse import OptionParser;
def main():
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
netvm = qvm_collection.get_default_netvm_vm()
if netvm is None:
print ""
else:
print netvm.name
main()

32
dom0/qvm-tools/qvm-init-storage Executable file
View File

@ -0,0 +1,32 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
def main():
qvm_collection = QubesVmCollection()
if qvm_collection.check_if_storage_exists():
print "Storage exists, not overwriting."
exit(1)
qvm_collection.create_empty_storage()
main()

54
dom0/qvm-tools/qvm-kill Executable file
View File

@ -0,0 +1,54 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from optparse import OptionParser;
import subprocess
qubes_guid_path = "/usr/bin/qubes_guid"
def main():
usage = "usage: %prog [options] <vm-name>"
parser = OptionParser (usage)
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("You must specify VM name!")
vmname = args[0]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None:
print "A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
try:
vm.force_shutdown()
except (IOError, OSError) as err:
print "ERROR: {0}".format(err)
exit (1)
main()

191
dom0/qvm-tools/qvm-ls Executable file
View File

@ -0,0 +1,191 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException
from optparse import OptionParser
fields = {
"qid": {"func": "vm.qid"},
"name": {"func": "('=>' if qvm_collection.get_default_template_vm() is not None\
and vm.qid == qvm_collection.get_default_template_vm().qid else '')\
+ ('[' if vm.is_templete() else '')\
+ ('{' if vm.is_netvm() else '')\
+ vm.name \
+ (']' if vm.is_templete() else '')\
+ ('}' if vm.is_netvm() else '')"},
"type": {"func": "'Tpl' if vm.is_templete() else \
(' Net' if vm.is_netvm() else '')"},
"updbl" : {"func": "'Yes' if vm.is_updateable() else ''"},
"template": {"func": "'n/a' if vm.is_templete() or vm.is_netvm() else\
qvm_collection[vm.template_vm.qid].name"},
"netvm": {"func": "'n/a' if vm.is_netvm() else\
('*' if vm.uses_default_netvm else '') +\
qvm_collection[vm.netvm_vm.qid].name\
if vm.netvm_vm is not None else '-'"},
"ip" : {"func": "vm.ip"},
"netmask" : {"func": "vm.netmask"},
"gateway" : {"func": "vm.gateway"},
"xid" : {"func" : "vm.get_xid() if vm.is_running() else '-'"},
"mem" : {"func" : "(str(vm.get_mem()/1024/1024) + ' MB') if vm.is_running() else '-'"},
"cpu" : {"func" : "round (vm.get_cpu_total_load(), 1) if vm.is_running() else '-'"},
"disk": {"func" : "str(vm.get_disk_utilization()/(1024*1024)) + ' MB'"},
"state": {"func" : "vm.get_power_state()"},
"priv-curr": {"func" : "str(vm.get_disk_utilization_private_img()/(1024*1024)) + ' MB'"},
"priv-max": {"func" : "str(vm.get_private_img_sz()/(1024*1024)) + ' MB'"},
"priv-util": {"func" : "str(vm.get_disk_utilization_private_img()*100/vm.get_private_img_sz()) + '%' if vm.get_private_img_sz() != 0 else '-'"},
"root-curr": {"func" : "str(vm.get_disk_utilization_root_img()/(1024*1024)) + ' MB'"},
"root-max": {"func" : "str(vm.get_root_img_sz()/(1024*1024)) + ' MB'"},
"root-util": {"func" : "str(vm.get_disk_utilization_root_img()*100/vm.get_root_img_sz()) + '%' if vm.get_root_img_sz() != 0 else '-'"},
"label" : {"func" : "vm.label.name"},
"on" : {"func" : "'*' if vm.is_running() else ''"}
}
def main():
usage = "usage: %prog [options] <vm-name>"
parser = OptionParser (usage)
parser.add_option ("-n", "--network", dest="network",
action="store_true", default=False,
help="Show network addresses assigned to VMs")
parser.add_option ("-c", "--cpu", dest="cpu",
action="store_true", default=False,
help="Show CPU load")
parser.add_option ("-m", "--mem", dest="mem",
action="store_true", default=False,
help="Show memory usage")
parser.add_option ("-d", "--disk", dest="disk",
action="store_true", default=False,
help="Show VM disk utilization statistics")
parser.add_option ("-i", "--ids", dest="ids",
action="store_true", default=False,
help="Show Qubes and Xen id#s")
(options, args) = parser.parse_args ()
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
fields_to_display = ["name", "on", "state", "updbl", "type", "template", "netvm", "label" ]
if (options.ids):
fields_to_display += ["qid", "xid"]
if (options.cpu):
fields_to_display += ["cpu"]
if (options.mem):
fields_to_display += ["mem"]
if (options.network):
fields_to_display.remove ("template")
fields_to_display += ["ip", "netmask", "gateway"]
if (options.disk):
fields_to_display.remove ("template")
fields_to_display.remove ("netvm")
fields_to_display += ["priv-curr", "priv-max", "root-curr", "root-max", "disk" ]
vms_list = [vm for vm in qvm_collection.values()]
no_vms = len (vms_list)
vms_to_display = []
# Frist, the NetVMs...
for netvm in vms_list:
if netvm.is_netvm():
vms_to_display.append (netvm)
# Now, the template, and all its AppVMs...
for tvm in vms_list:
if tvm.is_templete():
vms_to_display.append (tvm)
for appvm in vms_list:
if appvm.is_appvm() and appvm.template_vm.qid == tvm.qid:
vms_to_display.append(appvm)
assert len(vms_to_display) == no_vms
# First calculate the maximum width of each field we want to display
total_width = 0;
for f in fields_to_display:
fields[f]["max_width"] = len(f)
for vm in vms_to_display:
l = len(str(eval(fields[f]["func"])))
if l > fields[f]["max_width"]:
fields[f]["max_width"] = l
total_width += fields[f]["max_width"]
# Display the header
s = ""
for f in fields_to_display:
fmt="{{0:-^{0}}}-+".format(fields[f]["max_width"] + 1)
s += fmt.format('-')
print s
s = ""
for f in fields_to_display:
fmt="{{0:>{0}}} |".format(fields[f]["max_width"] + 1)
s += fmt.format(f)
print s
s = ""
for f in fields_to_display:
fmt="{{0:-^{0}}}-+".format(fields[f]["max_width"] + 1)
s += fmt.format('-')
print s
# ... and the actual data
for vm in vms_to_display:
s = ""
for f in fields_to_display:
fmt="{{0:>{0}}} |".format(fields[f]["max_width"] + 1)
s += fmt.format(eval(fields[f]["func"]))
print s
try:
vm.verify_files()
except QubesException as err:
print "WARNING: VM '{0}' has corrupted files!".format(vm.name)
main()

219
dom0/qvm-tools/qvm-prefs Executable file
View File

@ -0,0 +1,219 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesVmLabels
from optparse import OptionParser
import subprocess
def do_list(vm):
label_width = 18
fmt="{{0:<{0}}}: {{1}}".format(label_width)
print fmt.format ("name", vm.name)
print fmt.format ("label", vm.label.name)
print fmt.format ("type", vm.type)
if vm.is_appvm():
print fmt.format ("template", vm.template_vm.name)
if vm.netvm_vm is not None:
print fmt.format ("netvm", vm.netvm_vm.name)
print fmt.format ("updateable?", vm.is_updateable())
print fmt.format ("installed by RPM?", vm.installed_by_rpm)
print fmt.format ("dir", vm.dir_path)
print fmt.format ("config", vm.conf_file)
if not vm.is_appvm():
print fmt.format ("root img", vm.root_img)
if vm.is_appvm():
print fmt.format ("root img", vm.template_vm.root_img)
print fmt.format ("root COW img", vm.rootcow_img)
print fmt.format ("private img", vm.private_img)
def set_label(vms, vm, args):
if len (args) != 1:
print "Missing label name argument!"
label = args[0]
if label not in QubesVmLabels:
print "Wrong label name, supported values are the following:"
for l in QubesVmLabels.values():
print "* {0}".format(l.name)
exit (1)
vm.label = QubesVmLabels[label]
subprocess.check_call (["ln", "-sf", vm.label.icon_path, vm.icon_path])
def set_netvm(vms, vm, args):
if len (args) != 1:
print "Missing netvm name argument!"
print "Possible values:"
print "1) default"
print "2) none"
print "3) <vmaname>"
return
netvm = args[0]
if netvm == "none":
netvm_vm = None
vm.uses_default_netvm = False
elif netvm == "default":
netvm_vm = vms.get_default_netvm_vm()
vm.uses_default_netvm = True
else:
netvm_vm = vms.get_vm_by_name (netvm)
if netvm_vm is None:
print "A VM with the name '{0}' does not exist in the system.".format(netvm)
exit(1)
if not netvm_vm.is_netvm():
print "VM '{0}' is not a NetVM".format(netvm)
exit (1)
vm.uses_default_netvm = False
vm.netvm_vm = netvm_vm
def set_updateable(vms, vm, args):
if vm.is_updateable():
print "VM '{0}' is already set 'updateable', no action required.".format(vm.name)
return True
if vm.is_running():
print "Cannot change 'updateable' attribute of a running VM. Shut it down first."
return False
if vm.is_appvm():
# Check if the Template is *non* updateable...
if not vm.template_vm.is_updateable():
print "VM '{0}': Setting 'updateable' attribute to True.".format(vm.name)
vm.set_updateable()
else:
print "The Template VM ('{0}') is marked as 'updateable' itself!".format(vm.template_vm.name)
print "Cannot make the AppVM updateable too, as this might cause COW-backed storage incoherency."
print "If you want to make this AppVM updateable, you must first make the Template VM nonupdateable."
return False
if vm.is_templete():
# Make sure that all the AppVMs are non-updateable...
for appvm in vm.appvms.values():
if appvm.is_updateable():
print "At least one of the AppVMs ('{0}') of this Template VM is also marked 'updateable'.".format(appvm.name)
print "Cannot make the Template VM updateable too, as this might cause COW-backed storage incoherency."
print "If you want to make this Template VM updateable, you must first make all its decedent AppVMs nonupdateable."
return False
print "VM '{0}': Setting 'updateable' attribute to True.".format(vm.name)
vm.set_updateable()
return True
def set_nonupdateable(vms, vm, args):
if not vm.is_updateable():
print "VM '{0}' is already set 'nonupdateable', no action required.".format(vm.name)
return True
if vm.is_running():
print "Cannot change 'updateable' attribute of a running VM. Shut it down first."
return False
if vm.is_netvm():
print "Why, on earth, would you want to make a NetVM 'nonupdateable'?"
return False
print "VM '{0}': Setting 'updateable' attribute to False.".format(vm.name)
vm.set_nonupdateable()
return True
properties = {
"updateable": set_updateable,
"nonupdateable": set_nonupdateable,
"label" : set_label,
"netvm" : set_netvm,
}
def do_set(vms, vm, property, args):
if property not in properties.keys():
print "ERROR: Wrong property name: '{0}'".format(property)
return False
return properties[property](vms, vm, args)
def main():
usage = "usage: %prog -l [options] <vm-name>\n"\
"usage: %prog -s [options] <vm-name> <property> [...]\n"\
"List/set various per-VM properties."
parser = OptionParser (usage)
parser.add_option ("-l", "--list", action="store_true", dest="do_list", default=False)
parser.add_option ("-s", "--set", action="store_true", dest="do_set", default=False)
(options, args) = parser.parse_args ()
if (len (args) < 1):
parser.error ("You must provide at least the vmname!")
vmname = args[0]
if options.do_list and options.do_set:
print "You cannot provide -l and -s at the same time!"
exit (1)
if options.do_set:
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
else:
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None or vm.qid not in qvm_collection:
print "A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
if options.do_set:
if len (args) < 2:
print "You must specify the property you wish to set..."
print "Available properties:"
for p in properties.keys():
print "--> '{0}'".format(p)
exit (1)
property = args[1]
do_set(qvm_collection, vm, property, args[2:])
qvm_collection.save()
qvm_collection.unlock_db()
else:
# do_list
do_list(vm)
main()

101
dom0/qvm-tools/qvm-remove Executable file
View File

@ -0,0 +1,101 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from optparse import OptionParser;
def main():
usage = "usage: %prog [options] <vm-name>"
parser = OptionParser (usage)
parser.add_option ("-q", "--quiet", action="store_false", dest="verbose", default=True)
parser.add_option ("--just-db", action="store_true", dest="remove_from_db_only", default=False,
help="Remove only from the Qubes Xen DB, do not remove any files")
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("You must specify VM name!")
vmname = args[0]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None or vm.qid not in qvm_collection:
print "A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
if vm.is_templete():
dependent_vms = qvm_collection.get_vms_based_on(vm.qid)
if len(dependent_vms) > 0:
print "The following AppVMs use '{0}' as a template:".format(vmname)
for vm in dependent_vms:
print "{name:<12} (qid={qid})".format(qid=vm.qid, name=vm.name)
print "Please remove those VMs first, or use the --force option."
exit (1)
if qvm_collection.default_template_qid == vm.qid:
qvm_collection.default_template_qid = None
if vm.is_netvm():
if qvm_collection.default_netvm_qid == vm.qid:
qvm_collection.default_netvm_qid = None
if vm.is_running():
print "Cannot remove a running VM, stop it first"
exit (1)
if vm.installed_by_rpm and not options.remove_from_db_only:
if options.verbose:
print "This VM has been installed by RPM, use rpm -e <pkg name> to remove it!"
exit (1)
try:
if options.verbose:
print "--> Removing from Xen Storage..."
vm.remove_from_xen_storage()
except (IOError, OSError) as err:
print "Warning: {0}".format(err)
# Do not exit, perhaps the VM was not in the Xen store
# so just remove it from Qubes DB
try:
if vm.installed_by_rpm:
if options.verbose:
print "--> VM installed by RPM, leaving all the files on disk"
else:
if options.verbose:
print "--> Removing all the files on disk..."
#TODO: ask for confirmation, perhaps?
vm.remove_from_disk()
except (IOError, OSError) as err:
print "Warning: {0}".format(err)
# Do not exit, perhaps the VM files were somehow removed
# so just remove it from Qubes DB
qvm_collection.pop(vm.qid)
qvm_collection.save()
qvm_collection.unlock_db()
main()

227
dom0/qvm-tools/qvm-run Executable file
View File

@ -0,0 +1,227 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
# Copyright (C) 2010 Rafal Wojtczuk <rafal@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.
#
#
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException
from optparse import OptionParser
import subprocess
import socket
import errno
import dbus
import time
qubes_guid_path = "/usr/bin/qubes_guid"
qubes_clipd_path = "/usr/bin/qclipd"
qubes_qfilexchgd_path= "/usr/bin/qfilexchgd"
notify_object = None
# how long (in sec) to wait for VMs to shutdown
# before killing them (when used with --wait option)
shutdown_counter_max = 30
def tray_notify(str, label, timeout = 3000):
notify_object.Notify("Qubes", 0, label.icon, "Qubes", str, [], [], timeout, dbus_interface="org.freedesktop.Notifications")
def tray_notify_error(str, timeout = 3000):
notify_object.Notify("Qubes", 0, "dialog-error", "Qubes", str, [], [], timeout, dbus_interface="org.freedesktop.Notifications")
def vm_run_cmd(vm, cmd, options):
if options.shutdown:
if options.verbose:
print "Shutting down VM: '{0}'...".format(vm.name)
subprocess.call (["/usr/sbin/xm", "shutdown", vm.name])
return
if options.verbose:
print "Running command on VM: '{0}'...".format(vm.name)
if not vm.is_running():
if not options.auto:
print "VM '{0}' is not running, please start it first, or use the '--auto' switch"
exit (1)
try:
if options.verbose:
print "Starting the VM '{0}'...".format(vm.name)
if options.tray:
tray_notify ("Starting the '{0}' VM...".format(vm.name), label=vm.label)
xid = vm.start(verbose=options.verbose)
except (IOError, OSError, QubesException) as err:
print "ERROR: {0}".format(err)
if options.tray:
tray_notify_error ("Error while starting the '{0}' VM: {1}".format(vm.name, err))
exit (1)
except (MemoryError) as err:
print "ERROR: {0}".format(err)
print "Close one or more running VMs and try again."
if options.tray:
subprocess.call(["kdialog", "--error", "Not enough memory to start '{0}' VM! Close one or more running VMs and try again.".format(vm.name)])
exit (1)
if options.verbose:
print "--> Starting Qubes GUId..."
retcode = subprocess.call ([qubes_guid_path, "-d", str(xid), "-c", vm.label.color, "-e", cmd, "-i", vm.label.icon])
if (retcode != 0) :
print "ERROR: Cannot start qubes_guid!"
if options.tray:
tray_notify_error ("ERROR: Cannot start qubes_guid!")
exit (1)
else: # VM already running...
guid_is_running = True
xid = vm.get_xid()
s = socket.socket (socket.AF_UNIX)
try:
s.connect ("/var/run/qubes/cmd_socket.{0}".format(xid))
except (IOError, OSError) as e:
if e.errno in [errno.ENOENT,errno.ECONNREFUSED]:
guid_is_running = False
else:
print "ERROR: unix-connect: {0}".format(e)
if options.tray:
tray_notify_error ("ERROR: Cannot connect to GUI daemon for this VM!")
exit(1)
if guid_is_running:
s.send (cmd)
s.close()
else:
retcode = subprocess.call ([qubes_guid_path, "-d", str(xid), "-c", vm.label.color, "-e", cmd, "-i", vm.label.icon])
if (retcode != 0) :
print "ERROR: Cannot start qubes_guid!"
if options.tray:
tray_notify_error ("ERROR: Cannot start the GUI daemon for this VM!")
exit (1)
def main():
usage = "usage: %prog [options] [<vm-name>] [<cmd>]"
parser = OptionParser (usage)
parser.add_option ("-q", "--quiet", action="store_false", dest="verbose", default=True)
parser.add_option ("-a", "--auto", action="store_true", dest="auto", default=False,
help="Auto start the VM if not running")
parser.add_option ("-u", "--user", action="store", dest="user", default="user",
help="Run command in a VM as a specified user")
parser.add_option ("--tray", action="store_true", dest="tray", default=False,
help="Use tray notifications instead of stdout" )
parser.add_option ("--all", action="store_true", dest="run_on_all_running", default=False,
help="Run command on all currently running VMs")
parser.add_option ("--exclude", action="append", dest="exclude_list",
help="When --all is used: exclude this VM name (might be repeated)")
parser.add_option ("--wait", action="store_true", dest="wait_for_shutdown", default=False,
help="Wait for the VM(s) to shutdown")
parser.add_option ("--shutdown", action="store_true", dest="shutdown", default=False,
help="Do 'xm shutdown' for the VM(s) (can be combined this with --all and --wait)")
(options, args) = parser.parse_args ()
if options.run_on_all_running:
if len(args) < 1 and not options.shutdown:
parser.error ("You must provide a command to execute on all the VMs.")
if len(args) > 1 or (options.shutdown and len(args) > 0):
parser.error ("To many arguments...")
cmdstr = args[0] if not options.shutdown else None
else:
if len (args) < 1 and options.shutdown:
parser.error ("You must specify the VM name to shutdown.")
if len (args) < 2 and not options.shutdown:
parser.error ("You must specify the VM name and the command to execute in the VM.")
if len (args) > 2 or (options.shutdown and len(args) > 1):
parser.error ("To many arguments...")
vmname = args[0]
cmdstr = args[1] if not options.shutdown else None
if options.tray:
global notify_object
notify_object = dbus.SessionBus().get_object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vms_list = []
if options.run_on_all_running:
all_vms = [vm for vm in qvm_collection.values()]
for vm in all_vms:
if options.exclude_list is not None and vm.name in options.exclude_list:
continue
if vm.qid == 0:
continue
if vm.is_running():
vms_list.append (vm)
else:
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None:
print "A VM with the name '{0}' does not exist in the system!".format(vmname)
exit(1)
vms_list.append(vm)
if options.shutdown:
cmd = None
else:
cmd = "{user}:{cmd}".format(user=options.user, cmd=cmdstr)
for vm in vms_list:
vm_run_cmd(vm, cmd, options)
if options.wait_for_shutdown:
if options.verbose:
print "Waiting for the VM(s) to shutdown..."
shutdown_counter = 0
while len (vms_list):
if options.verbose:
print "Waiting for VMs: ", [vm.name for vm in vms_list]
for vm in vms_list:
if not vm.is_running():
vms_list.remove (vm)
if shutdown_counter > shutdown_counter_max:
# kill the VM
if options.verbose:
print "Killing the (apparently hanging) VM '{0}'...".format(vm.name)
vm.force_shutdown()
#vms_list.remove(vm)
shutdown_counter += 1
time.sleep (1)
exit (0) # there is no point in executing the other daemons in the case of --wait
retcode = subprocess.call([qubes_clipd_path])
if retcode != 0:
print "ERROR: Cannot start qclipd!"
if options.tray:
tray_notify ("ERROR: Cannot start the Qubes Clipboard Notifier!")
retcode = subprocess.call([qubes_qfilexchgd_path])
if retcode != 0:
print "ERROR: Cannot start qfilexchgd!"
if options.tray:
tray_notify ("ERROR: Cannot start the Qubes Inter-VM File Exchange Daemon!")
main()

View File

@ -0,0 +1,50 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from optparse import OptionParser;
def main():
usage = "usage: %prog <netvm-name>"
parser = OptionParser (usage)
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("Missing argument!")
vmname = args[0]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None or vm.qid not in qvm_collection:
print "A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
if not vm.is_netvm():
print "VM '{0}' is not a NetVM".format(vmname)
exit (1)
qvm_collection.set_default_netvm_vm(vm)
qvm_collection.save()
qvm_collection.unlock_db()
main()

View File

@ -0,0 +1,50 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from optparse import OptionParser;
def main():
usage = "usage: %prog <template-vm-name>"
parser = OptionParser (usage)
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("Missing argument!")
vmname = args[0]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_writing()
qvm_collection.load()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None or vm.qid not in qvm_collection:
print "A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
if not vm.is_templete():
print "VM '{0}' is not a TemplateVM".format(vmname)
exit (1)
qvm_collection.set_default_template_vm(vm)
qvm_collection.save()
qvm_collection.unlock_db()
main()

72
dom0/qvm-tools/qvm-start Executable file
View File

@ -0,0 +1,72 @@
#!/usr/bin/python2.6
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
from qubes.qubes import QubesVmCollection
from qubes.qubes import QubesException
from optparse import OptionParser
import subprocess
qubes_guid_path = "/usr/bin/qubes_guid"
def main():
usage = "usage: %prog [options] <vm-name>"
parser = OptionParser (usage)
parser.add_option ("-q", "--quiet", action="store_false", dest="verbose", default=True)
parser.add_option ("--no-guid", action="store_true", dest="noguid", default=False,
help="Do not start the GUId")
parser.add_option ("--console", action="store_true", dest="debug_console", default=False,
help="Attach debugging console to the newly started VM")
(options, args) = parser.parse_args ()
if (len (args) != 1):
parser.error ("You must specify VM name!")
vmname = args[0]
qvm_collection = QubesVmCollection()
qvm_collection.lock_db_for_reading()
qvm_collection.load()
qvm_collection.unlock_db()
vm = qvm_collection.get_vm_by_name(vmname)
if vm is None:
print "A VM with the name '{0}' does not exist in the system.".format(vmname)
exit(1)
try:
vm.verify_files()
xid = vm.start(debug_console=options.debug_console, verbose=options.verbose)
except (IOError, OSError, QubesException) as err:
print "ERROR: {0}".format(err)
exit (1)
if options.noguid:
exit (0)
if options.verbose:
print "--> Starting Qubes GUId..."
retcode = subprocess.call ([qubes_guid_path, "-d", str(xid), "-c", vm.label.color, "-i", vm.label.icon])
if (retcode != 0) :
print "ERROR: Cannot start qubes_guid!"
exit (1)
main()

14
netvm/fstab Normal file
View File

@ -0,0 +1,14 @@
#
# /etc/fstab
# Created by anaconda on Thu Dec 3 11:26:49 2009
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/dmroot / ext4 defaults,noatime 1 1
/dev/mapper/dmswap swap swap defaults 0 0
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0

17
netvm/iptables Normal file
View File

@ -0,0 +1,17 @@
# Generated by iptables-save v1.4.5 on Thu Apr 1 10:55:18 2010
*nat
:PREROUTING ACCEPT [3:696]
:POSTROUTING ACCEPT [1:67]
:OUTPUT ACCEPT [1:67]
-A POSTROUTING -s 10.1.0.0/16 -j MASQUERADE
COMMIT
# Completed on Thu Apr 1 10:55:18 2010
# Generated by iptables-save v1.4.5 on Thu Apr 1 10:55:18 2010
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i br0 -p udp -m udp --dport 68 -j DROP
-A INPUT -i vif+ -p udp -m udp --dport 68 -j DROP
COMMIT
# Completed on Thu Apr 1 10:55:18 2010

55
netvm/qubes_core Executable file
View File

@ -0,0 +1,55 @@
#!/bin/sh
#
# chkconfig: 345 90 90
# description: Executes Qubes core scripts at VM boot
#
# Source function library.
. /etc/rc.d/init.d/functions
start()
{
echo -n $"Executing Qubes Core scripts NetVM:"
if ! [ -x /usr/bin/xenstore-read ] ; then
echo "ERROR: /usr/bin/xenstore-read not found!"
exit 1
fi
name=$(/usr/bin/xenstore-read name)
hostname $name
# Setup gateway for all the VMs this netVM is serviceing...
brctl addbr br0
gateway=$(/usr/bin/xenstore-read qubes_netvm_gateway)
netmask=$(/usr/bin/xenstore-read qubes_netvm_netmask)
network=$(/usr/bin/xenstore-read qubes_netvm_network)
ifconfig br0 $gateway netmask $netmask up
echo "1" > /proc/sys/net/ipv4/ip_forward
dnsmasq --listen-address $gateway --bind-interfaces
#now done by iptables rc script
# iptables -t nat -A POSTROUTING -s $network/$netmask -j MASQUERADE
success
echo ""
return 0
}
stop()
{
return 0
}
case "$1" in
start)
start
;;
stop)
stop
;;
*)
echo $"Usage: $0 {start|stop}"
exit 3
;;
esac
exit $RETVAL

162
rpm_spec/core-appvm.spec Normal file
View File

@ -0,0 +1,162 @@
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
# Copyright (C) 2010 Rafal Wojtczuk <rafal@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.
#
#
%{!?version: %define version %(cat version_vm)}
Name: qubes-core-appvm
Version: %{version}
Release: 1
Summary: The Qubes core files for AppVM
Group: Qubes
Vendor: Invisible Things Lab
License: GPL
URL: http://www.qubes-os.org
Requires: /usr/bin/xenstore-read
Provides: qubes-core-vm
%define _builddir %(pwd)/appvm
%define kde_service_dir /usr/share/kde4/services/ServiceMenus
%description
The Qubes core files for installation inside a Qubes AppVM.
%pre
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes
[ -e $RPM_BUILD_ROOT/etc/fstab ] && mv $RPM_BUILD_ROOT/etc/fstab $RPM_BUILD_ROOT/var/lib/qubes/fstab.orig
%build
make clean all
%install
mkdir -p $RPM_BUILD_ROOT/etc
cp fstab $RPM_BUILD_ROOT/etc/fstab
mkdir -p $RPM_BUILD_ROOT/etc/init.d
cp qubes_core $RPM_BUILD_ROOT/etc/init.d/
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes
mkdir -p $RPM_BUILD_ROOT/usr/bin
cp qubes_add_pendrive_script qubes_penctl qvm-copy-to-vm qvm-copy-to-vm.kde $RPM_BUILD_ROOT/usr/bin
mkdir -p $RPM_BUILD_ROOT/%{kde_service_dir}
cp qvm-copy.desktop $RPM_BUILD_ROOT/%{kde_service_dir}
mkdir -p $RPM_BUILD_ROOT/etc/udev/rules.d
cp qubes.rules $RPM_BUILD_ROOT/etc/udev/rules.d
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
cp iptables $RPM_BUILD_ROOT/etc/sysconfig/
mkdir -p $RPM_BUILD_ROOT/mnt/incoming
mkdir -p $RPM_BUILD_ROOT/mnt/outgoing
%post
if [ "$1" != 1 ] ; then
# do this whole %post thing only when updating for the first time...
exit 0
fi
echo "--> Disabling SELinux..."
sed -e s/^SELINUX=.*$/SELINUX=disabled/ </etc/selinux/config >/etc/selinux/config.processed
mv /etc/selinux/config.processed /etc/selinux/config
setenforce 0
echo "--> Turning off unnecessary services..."
# FIXME: perhaps there is more elegant way to do this?
for f in /etc/init.d/*
do
srv=`basename $f`
[ $srv = 'functions' ] && continue
[ $srv = 'killall' ] && continue
[ $srv = 'halt' ] && continue
chkconfig $srv off
done
echo "--> Enabling essential services..."
chkconfig rsyslog on
chkconfig haldaemon on
chkconfig messagebus on
chkconfig cups on
chkconfig iptables on
chkconfig --add qubes_core || echo "WARNING: Cannot add service qubes_core!"
chkconfig qubes_core on || echo "WARNING: Cannot enable service qubes_core!"
sed -i s/^id:.:initdefault:/id:3:initdefault:/ /etc/inittab
# Remove most of the udev scripts to speed up the VM boot time
# Just leave the xen* scripts, that are needed if this VM was
# ever used as a net backend (e.g. as a VPN domain in the future)
echo "--> Removing unnecessary udev scripts..."
mkdir -p /var/lib/qubes/removed-udev-scripts
for f in /etc/udev/rules.d/*
do
if [ $(basename $f) == "xen-backend.rules" ] ; then
continue
fi
if [ $(basename $f) == "xend.rules" ] ; then
continue
fi
if [ $(basename $f) == "qubes.rules" ] ; then
continue
fi
if [ $(basename $f) == "90-hal.rules" ] ; then
continue
fi
mv $f /var/lib/qubes/removed-udev-scripts/
done
mkdir -p /rw
#rm -f /etc/mtab
echo "--> Removing HWADDR setting from /etc/sysconfig/network-scripts/ifcfg-eth0"
mv /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0.orig
grep -v HWADDR /etc/sysconfig/network-scripts/ifcfg-eth0.orig > /etc/sysconfig/network-scripts/ifcfg-eth0
%preun
if [ "$1" = 0 ] ; then
# no more packages left
chkconfig qubes_core off
mv /var/lib/qubes/fstab.orig /etc/fstab
mv /var/lib/qubes/removed-udev-scripts/* /etc/udev/rules.d/
fi
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
/etc/fstab
/etc/init.d/qubes_core
/usr/bin/qvm-copy-to-vm
/usr/bin/qvm-copy-to-vm.kde
%{kde_service_dir}/qvm-copy.desktop
%attr(4755,root,root) /usr/bin/qubes_penctl
/usr/bin/qubes_add_pendrive_script
/etc/udev/rules.d/qubes.rules
/etc/sysconfig/iptables
%dir /var/lib/qubes
%dir /mnt/incoming
%dir /mnt/outgoing

156
rpm_spec/core-dom0.spec Normal file
View File

@ -0,0 +1,156 @@
#
# This is the SPEC file for creating binary RPMs for the Dom0.
#
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
# Copyright (C) 2010 Rafal Wojtczuk <rafal@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.
#
#
%{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
%{!?version: %define version %(cat version_dom0)}
Name: qubes-core-dom0
Version: %{version}
Release: 1
Summary: The Qubes core files (Dom0-side)
Group: Qubes
Vendor: Invisible Things Lab
License: GPL
URL: http://www.qubes-os.org
Requires: python, xen-runtime, pciutils, python-inotify, python-daemon, kernel-qubes-dom0
%define _builddir %(pwd)/dom0
%description
The Qubes core files for installation on Dom0.
%install
mkdir -p $RPM_BUILD_ROOT/etc/init.d
cp init.d/qubes_core $RPM_BUILD_ROOT/etc/init.d/
cp init.d/qubes_netvm $RPM_BUILD_ROOT/etc/init.d/
mkdir -p $RPM_BUILD_ROOT/usr/bin/
cp qvm-tools/qvm-* $RPM_BUILD_ROOT/usr/bin
cp clipboard_notifier/qclipd $RPM_BUILD_ROOT/usr/bin
cp pendrive_swapper/qfilexchgd $RPM_BUILD_ROOT/usr/bin
mkdir -p $RPM_BUILD_ROOT%{python_sitearch}/qubes
cp qvm-core/qubes.py $RPM_BUILD_ROOT%{python_sitearch}/qubes
cp qvm-core/__init__.py $RPM_BUILD_ROOT%{python_sitearch}/qubes
mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/patch_appvm_initramfs.sh $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/unbind_pci_device.sh $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/unbind_all_network_devices $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/convert_apptemplate2vm.sh $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/convert_dirtemplate2vm.sh $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/create_apps_for_appvm.sh $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/remove_appvm_appmenus.sh $RPM_BUILD_ROOT/usr/lib/qubes
cp pendrive_swapper/qubes_pencmd $RPM_BUILD_ROOT/usr/lib/qubes
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/vm-templates
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/appvms
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes/backup
mkdir -p $RPM_BUILD_ROOT/usr/share/qubes/icons
cp icons/*.png $RPM_BUILD_ROOT/usr/share/qubes/icons
%post
if [ "$1" != 1 ] ; then
# do this whole %post thing only when updating for the first time...
exit 0
fi
#echo "Enabling essential services..."
chkconfig haldaemon on
chkconfig messagebus on
chkconfig xenstored on
chkconfig xend on
chkconfig xenconsoled on
chkconfig --add qubes_core || echo "WARNING: Cannot add service qubes_core!"
chkconfig --add qubes_netvm || echo "WARNING: Cannot add service qubes_netvm!"
chkconfig qubes_core on || echo "WARNING: Cannot enable service qubes_core!"
chkconfig qubes_netvm on || echo "WARNING: Cannot enable service qubes_netvm!"
if ! [ -e /var/lib/qubes/qubes.xml ]; then
# echo "Initializing Qubes DB..."
umask 007; sg qubes -c qvm-init-storage
fi
for i in /usr/share/qubes/icons/*.png ; do
xdg-icon-resource install --novendor --size 48 $i
done
%clean
rm -rf $RPM_BUILD_ROOT
%pre
if ! grep -q ^qubes: /etc/group ; then
groupadd qubes
fi
%preun
if [ "$1" = 0 ] ; then
for i in /usr/share/qubes/icons/*.png ; do
xdg-icon-resource uninstall --novendor --size 48 $i
done
fi
%postun
if [ "$1" = 0 ] ; then
# no more packages left
chgrp root /etc/xen
chmod 700 /etc/xen
groupdel qubes
fi
%files
%defattr(-,root,root,-)
/etc/init.d/qubes_core
/etc/init.d/qubes_netvm
/usr/bin/qvm-*
/usr/bin/qclipd
/usr/bin/qfilexchgd
%{python_sitearch}/qubes/qubes.py
%{python_sitearch}/qubes/qubes.pyc
%{python_sitearch}/qubes/qubes.pyo
%{python_sitearch}/qubes/__init__.py
%{python_sitearch}/qubes/__init__.pyc
%{python_sitearch}/qubes/__init__.pyo
/usr/lib/qubes/patch_appvm_initramfs.sh
/usr/lib/qubes/unbind_pci_device.sh
/usr/lib/qubes/unbind_all_network_devices
/usr/lib/qubes/convert_apptemplate2vm.sh
/usr/lib/qubes/convert_dirtemplate2vm.sh
/usr/lib/qubes/create_apps_for_appvm.sh
/usr/lib/qubes/remove_appvm_appmenus.sh
/usr/lib/qubes/qubes_pencmd
%attr(770,root,qubes) %dir /var/lib/qubes
%attr(770,root,qubes) %dir /var/lib/qubes/vm-templates
%attr(770,root,qubes) %dir /var/lib/qubes/appvms
%attr(770,root,qubes) %dir /var/lib/qubes/backup
%dir /usr/share/qubes/icons/*.png

142
rpm_spec/core-netvm.spec Normal file
View File

@ -0,0 +1,142 @@
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@invisiblethingslab.com>
# Copyright (C) 2010 Rafal Wojtczuk <rafal@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.
#
#
%{!?version: %define version %(cat version_vm)}
Name: qubes-core-netvm
Version: %{version}
Release: 1
Summary: The Qubes core files for NetVM
Group: Qubes
Vendor: Invisible Things Lab
License: GPL
URL: http://www.qubes-os.org
Requires: /usr/bin/xenstore-read
Provides: qubes-core-vm
%define _builddir %(pwd)/netvm
%description
The Qubes core files for installation inside a Qubes NetVM.
%pre
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes
[ -e $RPM_BUILD_ROOT/etc/fstab ] && mv $RPM_BUILD_ROOT/etc/fstab $RPM_BUILD_ROOT/var/lib/qubes/fstab.orig
%build
%install
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
cp iptables $RPM_BUILD_ROOT/etc/sysconfig
mkdir -p $RPM_BUILD_ROOT/etc
cp fstab $RPM_BUILD_ROOT/etc/fstab
mkdir -p $RPM_BUILD_ROOT/etc/init.d
cp qubes_core $RPM_BUILD_ROOT/etc/init.d/
mkdir -p $RPM_BUILD_ROOT/var/lib/qubes
%post
if [ "$1" != 1 ] ; then
# do this whole %post thing only when updating for the first time...
exit 0
fi
echo "--> Disabling SELinux..."
sed -e s/^SELINUX=.*$/SELINUX=disabled/ </etc/selinux/config >/etc/selinux/config.processed
mv /etc/selinux/config.processed /etc/selinux/config
setenforce 0
echo "--> Turning off unnecessary services..."
# FIXME: perhaps there is more elegant way to do this?
for f in /etc/init.d/*
do
srv=`basename $f`
[ $srv = 'functions' ] && continue
[ $srv = 'killall' ] && continue
[ $srv = 'halt' ] && continue
chkconfig $srv off
done
echo "--> Enabling essential services..."
chkconfig iptables on
chkconfig rsyslog on
chkconfig haldaemon on
chkconfig messagebus on
chkconfig NetworkManager on
chkconfig --add qubes_core || echo "WARNING: Cannot add service qubes_core!"
chkconfig qubes_core on || echo "WARNING: Cannot enable service qubes_core!"
sed -i s/^id:.:initdefault:/id:3:initdefault:/ /etc/inittab
# Remove most of the udev scripts to speed up the VM boot time
# Just leave the xen* scripts, that are needed if this VM was
# ever used as a net backend (e.g. as a VPN domain in the future)
echo "--> Removing unnecessary udev scripts..."
mkdir -p /var/lib/qubes/removed-udev-scripts
for f in /etc/udev/rules.d/*
do
if [ $(basename $f) == "xen-backend.rules" ] ; then
continue
fi
if [ $(basename $f) == "xend.rules" ] ; then
continue
fi
if [ $(basename $f) == "qubes.rules" ] ; then
continue
fi
if [ $(basename $f) == "90-hal.rules" ] ; then
continue
fi
mv $f /var/lib/qubes/removed-udev-scripts/
done
#rm -f /etc/mtab
#echo "--> Removing HWADDR setting from /etc/sysconfig/network-scripts/ifcfg-eth0"
#mv /etc/sysconfig/network-scripts/ifcfg-eth0 /etc/sysconfig/network-scripts/ifcfg-eth0.orig
#grep -v HWADDR /etc/sysconfig/network-scripts/ifcfg-eth0.orig > /etc/sysconfig/network-scripts/ifcfg-eth0
%preun
if [ "$1" = 0 ] ; then
# no more packages left
chkconfig qubes_core off
mv /var/lib/qubes/fstab.orig /etc/fstab
mv /var/lib/qubes/removed-udev-scripts/* /etc/udev/rules.d/
fi
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root,-)
/etc/fstab
/etc/sysconfig/iptables
/etc/init.d/qubes_core
%dir /var/lib/qubes

View File

@ -0,0 +1,78 @@
#
# The Qubes OS Project, http://www.qubes-os.org
#
# Copyright (C) 2010 Joanna Rutkowska <joanna@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.
#
#
Name: qubes-dom0-cleanup
Version: 0.2.2
Release: 1
Summary: Additional tools that cleans up some unnecessary stuff in Qubes's Dom0
Group: Qubes
Vendor: Invisible Things Lab
License: GPL
URL: http://www.qubes-os.org
Requires: qubes-core-dom0
%define _builddir %(pwd)/dom0
%description
Additional tools that cleans up some unnecessary stuff in Qubes's Dom0
%install
mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/check_and_remove_appmenu.sh $RPM_BUILD_ROOT/usr/lib/qubes
cp aux-tools/remove_dom0_appmenus.sh $RPM_BUILD_ROOT/usr/lib/qubes
%post
echo "--> Turning off unnecessary services..."
# FIXME: perhaps there is more elegant way to do this?
for f in /etc/init.d/*
do
srv=`basename $f`
[ $srv = 'functions' ] && continue
[ $srv = 'killall' ] && continue
[ $srv = 'halt' ] && continue
chkconfig $srv off
done
#echo "--> Enabling essential services..."
chkconfig abrtd on
chkconfig haldaemon on
chkconfig messagebus on
chkconfig xenstored on
chkconfig xend on
chkconfig xenconsoled on
chkconfig qubes_core on || echo "WARNING: Cannot enable service qubes_core!"
chkconfig qubes_netvm on || echo "WARNING: Cannot enable service qubes_core!"
/usr/lib/qubes/remove_dom0_appmenus.sh
%clean
rm -rf $RPM_BUILD_ROOT
%postun
mv /var/lib/qubes/backup/removed-apps/* /usr/share/applications
xdg-desktop-menu forceupdate
%files
/usr/lib/qubes/check_and_remove_appmenu.sh
/usr/lib/qubes/remove_dom0_appmenus.sh

1
version_dom0 Normal file
View File

@ -0,0 +1 @@
1.0.0

1
version_vm Normal file
View File

@ -0,0 +1 @@
1.0.0