Re: [Qemu-devel] [PATCH] hw/9pfs: Handle Security model parsing
-- Regards, M. Mohan Kumar On Wednesday, October 12, 2011 09:37:23 PM Daniel P. Berrange wrote: > On Wed, Oct 12, 2011 at 09:05:50PM +0530, M. Mohan Kumar wrote: > > > On Wed, Oct 12, 2011 at 01:24:16PM +0530, M. Mohan Kumar wrote: > > > > Security model is needed only for 'local' fs driver. > > > > > > > > Signed-off-by: M. Mohan Kumar > > > > --- > > > > > > > > fsdev/qemu-fsdev.c |6 + > > > > fsdev/qemu-fsdev.h |1 + > > > > hw/9pfs/virtio-9p-device.c | 47 > > > > ++- vl.c > > > > > > > > | 20 +++-- > > > > > > > > 4 files changed, 43 insertions(+), 31 deletions(-) > > > > > > > > --- a/fsdev/qemu-fsdev.h > > > > +++ b/fsdev/qemu-fsdev.h > > > > @@ -40,6 +40,7 @@ typedef struct FsTypeTable { > > > > > > > > typedef struct FsTypeEntry { > > > > > > > > char *fsdev_id; > > > > char *path; > > > > > > > > +char *fsdriver; > > > > > > > > char *security_model; > > > > int cache_flags; > > > > FileOperations *ops; > > > > > > > > diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c > > > > index aac58ad..1846e36 100644 > > > > --- a/hw/9pfs/virtio-9p-device.c > > > > +++ b/hw/9pfs/virtio-9p-device.c > > > > @@ -83,29 +83,30 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, > > > > V9fsConf *conf) > > > > > > > > exit(1); > > > > > > > > } > > > > > > > > -if (!strcmp(fse->security_model, "passthrough")) { > > > > -/* Files on the Fileserver set to client user credentials */ > > > > -s->ctx.fs_sm = SM_PASSTHROUGH; > > > > -s->ctx.xops = passthrough_xattr_ops; > > > > -} else if (!strcmp(fse->security_model, "mapped")) { > > > > -/* Files on the fileserver are set to QEMU credentials. > > > > - * Client user credentials are saved in extended attributes. > > > > - */ > > > > -s->ctx.fs_sm = SM_MAPPED; > > > > -s->ctx.xops = mapped_xattr_ops; > > > > -} else if (!strcmp(fse->security_model, "none")) { > > > > -/* > > > > - * Files on the fileserver are set to QEMU credentials. > > > > - */ > > > > -s->ctx.fs_sm = SM_NONE; > > > > -s->ctx.xops = none_xattr_ops; > > > > -} else { > > > > -fprintf(stderr, "Default to security_model=none. You may > > > > want" -" enable advanced security model using " > > > > -"security option:\n\t security_model=passthrough\n\t > > > > " -"security_model=mapped\n"); > > > > -s->ctx.fs_sm = SM_NONE; > > > > -s->ctx.xops = none_xattr_ops; > > > > +/* security models is needed only for local fs driver */ > > > > +if (!strcmp(fse->fsdriver, "local")) { > > > > +if (!strcmp(fse->security_model, "passthrough")) { > > > > +/* Files on the Fileserver set to client user > > > > credentials */ +s->ctx.fs_sm = SM_PASSTHROUGH; > > > > +s->ctx.xops = passthrough_xattr_ops; > > > > +} else if (!strcmp(fse->security_model, "mapped")) { > > > > +/* Files on the fileserver are set to QEMU credentials. > > > > +* Client user credentials are saved in extended > > > > attributes. +*/ > > > > +s->ctx.fs_sm = SM_MAPPED; > > > > +s->ctx.xops = mapped_xattr_ops; > > > > +} else if (!strcmp(fse->security_model, "none")) { > > > > +/* > > > > +* Files on the fileserver are set to QEMU credentials. > > > > +*/ > > > > +s->ctx.fs_sm = SM_NONE; > > > > +s->ctx.xops = none_xattr_ops; > > > > +} else { > > > > +fprintf(stderr, "Invalid security_model %s specified.\n" > > > > +"Available security models are:\t " > > > > +"passthrough,mapped or none\n", > > > > fse->security_model); +exit(1); > > > > +} > > > > > > Are you sure there aren't use cases where people would like to > > > choose between passthrough & mapped, even when using the 'proxy' > > > or 'handle' security drivers. > > > > Proxy FS driver is added to overcome the limit imposed by local + > > passthrough security model combination that needs qemu to be started by > > root user. Mapped and none secuiry model can be used by non root user > > also. > > > > So Proxy FS driver does not need any security model(its pass-through > > only) > > The Proxy FS driver does not "need" the security model, but if so desired > it would be possible to choose to implement the security models. It just > happens that the driver is hardcoded to only operate in 'passthrough' > mode. > > I think that disabling the parsing of the 'security' parameter for > non-local drivers is dangerous, because an application might think that > the 'mapped' model was supported, but its parameter would get silently > ignored. If the requested value is not supported
Re: [Qemu-devel] [PATCH] hw/9pfs: Handle Security model parsing
On Wed, 12 Oct 2011 09:28:00 +0100, "Daniel P. Berrange" wrote: > On Wed, Oct 12, 2011 at 01:24:16PM +0530, M. Mohan Kumar wrote: > > Security model is needed only for 'local' fs driver. > > > > Signed-off-by: M. Mohan Kumar > > --- > > fsdev/qemu-fsdev.c |6 + > > fsdev/qemu-fsdev.h |1 + > > hw/9pfs/virtio-9p-device.c | 47 > > ++- > > vl.c | 20 +++-- > > 4 files changed, 43 insertions(+), 31 deletions(-) > > > * Files on the fileserver are set to QEMU credentials. > > +*/ > > +s->ctx.fs_sm = SM_NONE; > > +s->ctx.xops = none_xattr_ops; > > +} else { > > +fprintf(stderr, "Invalid security_model %s specified.\n" > > +"Available security models are:\t " > > +"passthrough,mapped or none\n", fse->security_model); > > +exit(1); > > +} > > Are you sure there aren't use cases where people would like to > choose between passthrough & mapped, even when using the 'proxy' > or 'handle' security drivers. Currently handle fs driver requires CAP_DAC_READ_SEARCH and if qemu is not going to run with specific capabilities this implies root privileges. So handle fs driver doesn't do the mapping required by different security model. Proxy fs driver is enabling us to run file system operations as "root". So even for that we don't need mapped security model. Even if we want to store file attributes in xattr with proxy fs driver, that will go as a proxy's argument not as -fsdev argument. Proxy also don't require export path name. But that is another patch. > > Both of the security models seem pretty generally useful to me, > regardless of the driver type. > -aneesh
Re: [Qemu-devel] [PATCH] hw/9pfs: Handle Security model parsing
On Wed, Oct 12, 2011 at 09:05:50PM +0530, M. Mohan Kumar wrote: > -- > Regards, > M. Mohan Kumar > On Wednesday, October 12, 2011 01:58:00 PM Daniel P. Berrange wrote: > > On Wed, Oct 12, 2011 at 01:24:16PM +0530, M. Mohan Kumar wrote: > > > Security model is needed only for 'local' fs driver. > > > > > > Signed-off-by: M. Mohan Kumar > > > --- > > > > > > fsdev/qemu-fsdev.c |6 + > > > fsdev/qemu-fsdev.h |1 + > > > hw/9pfs/virtio-9p-device.c | 47 > > > ++- vl.c > > > | 20 +++-- > > > 4 files changed, 43 insertions(+), 31 deletions(-) > > > > > > --- a/fsdev/qemu-fsdev.h > > > +++ b/fsdev/qemu-fsdev.h > > > @@ -40,6 +40,7 @@ typedef struct FsTypeTable { > > > > > > typedef struct FsTypeEntry { > > > > > > char *fsdev_id; > > > char *path; > > > > > > +char *fsdriver; > > > > > > char *security_model; > > > int cache_flags; > > > FileOperations *ops; > > > > > > diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c > > > index aac58ad..1846e36 100644 > > > --- a/hw/9pfs/virtio-9p-device.c > > > +++ b/hw/9pfs/virtio-9p-device.c > > > @@ -83,29 +83,30 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, > > > V9fsConf *conf) > > > > > > exit(1); > > > > > > } > > > > > > -if (!strcmp(fse->security_model, "passthrough")) { > > > -/* Files on the Fileserver set to client user credentials */ > > > -s->ctx.fs_sm = SM_PASSTHROUGH; > > > -s->ctx.xops = passthrough_xattr_ops; > > > -} else if (!strcmp(fse->security_model, "mapped")) { > > > -/* Files on the fileserver are set to QEMU credentials. > > > - * Client user credentials are saved in extended attributes. > > > - */ > > > -s->ctx.fs_sm = SM_MAPPED; > > > -s->ctx.xops = mapped_xattr_ops; > > > -} else if (!strcmp(fse->security_model, "none")) { > > > -/* > > > - * Files on the fileserver are set to QEMU credentials. > > > - */ > > > -s->ctx.fs_sm = SM_NONE; > > > -s->ctx.xops = none_xattr_ops; > > > -} else { > > > -fprintf(stderr, "Default to security_model=none. You may want" > > > -" enable advanced security model using " > > > -"security option:\n\t security_model=passthrough\n\t " > > > -"security_model=mapped\n"); > > > -s->ctx.fs_sm = SM_NONE; > > > -s->ctx.xops = none_xattr_ops; > > > +/* security models is needed only for local fs driver */ > > > +if (!strcmp(fse->fsdriver, "local")) { > > > +if (!strcmp(fse->security_model, "passthrough")) { > > > +/* Files on the Fileserver set to client user credentials */ > > > +s->ctx.fs_sm = SM_PASSTHROUGH; > > > +s->ctx.xops = passthrough_xattr_ops; > > > +} else if (!strcmp(fse->security_model, "mapped")) { > > > +/* Files on the fileserver are set to QEMU credentials. > > > +* Client user credentials are saved in extended attributes. > > > +*/ > > > +s->ctx.fs_sm = SM_MAPPED; > > > +s->ctx.xops = mapped_xattr_ops; > > > +} else if (!strcmp(fse->security_model, "none")) { > > > +/* > > > +* Files on the fileserver are set to QEMU credentials. > > > +*/ > > > +s->ctx.fs_sm = SM_NONE; > > > +s->ctx.xops = none_xattr_ops; > > > +} else { > > > +fprintf(stderr, "Invalid security_model %s specified.\n" > > > +"Available security models are:\t " > > > +"passthrough,mapped or none\n", > > > fse->security_model); +exit(1); > > > +} > > > > Are you sure there aren't use cases where people would like to > > choose between passthrough & mapped, even when using the 'proxy' > > or 'handle' security drivers. > > > Proxy FS driver is added to overcome the limit imposed by local + passthrough > security model combination that needs qemu to be started by root user. Mapped > and none secuiry model can be used by non root user also. > > So Proxy FS driver does not need any security model(its pass-through only) The Proxy FS driver does not "need" the security model, but if so desired it would be possible to choose to implement the security models. It just happens that the driver is hardcoded to only operate in 'passthrough' mode. I think that disabling the parsing of the 'security' parameter for non-local drivers is dangerous, because an application might think that the 'mapped' model was supported, but its parameter would get silently ignored. If the requested value is not supported, then the application should always be told about that. So, IMHO, it would be better to have logic such as: if (strcmp(security_mode, "passthrough") == 0) { ... } else if (strcmp(security_m
Re: [Qemu-devel] [PATCH] hw/9pfs: Handle Security model parsing
-- Regards, M. Mohan Kumar On Wednesday, October 12, 2011 01:58:00 PM Daniel P. Berrange wrote: > On Wed, Oct 12, 2011 at 01:24:16PM +0530, M. Mohan Kumar wrote: > > Security model is needed only for 'local' fs driver. > > > > Signed-off-by: M. Mohan Kumar > > --- > > > > fsdev/qemu-fsdev.c |6 + > > fsdev/qemu-fsdev.h |1 + > > hw/9pfs/virtio-9p-device.c | 47 > > ++- vl.c > > | 20 +++-- > > 4 files changed, 43 insertions(+), 31 deletions(-) > > > > --- a/fsdev/qemu-fsdev.h > > +++ b/fsdev/qemu-fsdev.h > > @@ -40,6 +40,7 @@ typedef struct FsTypeTable { > > > > typedef struct FsTypeEntry { > > > > char *fsdev_id; > > char *path; > > > > +char *fsdriver; > > > > char *security_model; > > int cache_flags; > > FileOperations *ops; > > > > diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c > > index aac58ad..1846e36 100644 > > --- a/hw/9pfs/virtio-9p-device.c > > +++ b/hw/9pfs/virtio-9p-device.c > > @@ -83,29 +83,30 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, > > V9fsConf *conf) > > > > exit(1); > > > > } > > > > -if (!strcmp(fse->security_model, "passthrough")) { > > -/* Files on the Fileserver set to client user credentials */ > > -s->ctx.fs_sm = SM_PASSTHROUGH; > > -s->ctx.xops = passthrough_xattr_ops; > > -} else if (!strcmp(fse->security_model, "mapped")) { > > -/* Files on the fileserver are set to QEMU credentials. > > - * Client user credentials are saved in extended attributes. > > - */ > > -s->ctx.fs_sm = SM_MAPPED; > > -s->ctx.xops = mapped_xattr_ops; > > -} else if (!strcmp(fse->security_model, "none")) { > > -/* > > - * Files on the fileserver are set to QEMU credentials. > > - */ > > -s->ctx.fs_sm = SM_NONE; > > -s->ctx.xops = none_xattr_ops; > > -} else { > > -fprintf(stderr, "Default to security_model=none. You may want" > > -" enable advanced security model using " > > -"security option:\n\t security_model=passthrough\n\t " > > -"security_model=mapped\n"); > > -s->ctx.fs_sm = SM_NONE; > > -s->ctx.xops = none_xattr_ops; > > +/* security models is needed only for local fs driver */ > > +if (!strcmp(fse->fsdriver, "local")) { > > +if (!strcmp(fse->security_model, "passthrough")) { > > +/* Files on the Fileserver set to client user credentials */ > > +s->ctx.fs_sm = SM_PASSTHROUGH; > > +s->ctx.xops = passthrough_xattr_ops; > > +} else if (!strcmp(fse->security_model, "mapped")) { > > +/* Files on the fileserver are set to QEMU credentials. > > +* Client user credentials are saved in extended attributes. > > +*/ > > +s->ctx.fs_sm = SM_MAPPED; > > +s->ctx.xops = mapped_xattr_ops; > > +} else if (!strcmp(fse->security_model, "none")) { > > +/* > > +* Files on the fileserver are set to QEMU credentials. > > +*/ > > +s->ctx.fs_sm = SM_NONE; > > +s->ctx.xops = none_xattr_ops; > > +} else { > > +fprintf(stderr, "Invalid security_model %s specified.\n" > > +"Available security models are:\t " > > +"passthrough,mapped or none\n", > > fse->security_model); +exit(1); > > +} > > Are you sure there aren't use cases where people would like to > choose between passthrough & mapped, even when using the 'proxy' > or 'handle' security drivers. > Proxy FS driver is added to overcome the limit imposed by local + passthrough security model combination that needs qemu to be started by root user. Mapped and none secuiry model can be used by non root user also. So Proxy FS driver does not need any security model(its pass-through only) > Both of the security models seem pretty generally useful to me, > regardless of the driver type. >
Re: [Qemu-devel] [PATCH] hw/9pfs: Handle Security model parsing
On Wed, 12 Oct 2011 13:24:16 +0530, "M. Mohan Kumar" wrote: > Security model is needed only for 'local' fs driver. Can you also cleanup that fstype -> fsdriver rename ? fsdriver seems more appropriate. > > Signed-off-by: M. Mohan Kumar > --- > fsdev/qemu-fsdev.c |6 + > fsdev/qemu-fsdev.h |1 + > hw/9pfs/virtio-9p-device.c | 47 ++- > vl.c | 20 +++-- > 4 files changed, 43 insertions(+), 31 deletions(-) > > diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c > index 36db127..d08ba9c 100644 > --- a/fsdev/qemu-fsdev.c > +++ b/fsdev/qemu-fsdev.c > @@ -58,11 +58,6 @@ int qemu_fsdev_add(QemuOpts *opts) > return -1; > } > > -if (!sec_model) { > -fprintf(stderr, "fsdev: No security_model specified.\n"); > -return -1; > -} > - > if (!path) { > fprintf(stderr, "fsdev: No path specified.\n"); > return -1; > @@ -72,6 +67,7 @@ int qemu_fsdev_add(QemuOpts *opts) > > fsle->fse.fsdev_id = g_strdup(fsdev_id); > fsle->fse.path = g_strdup(path); > +fsle->fse.fsdriver = g_strdup(fstype); Why use it as a string ? Why can't this again be an export_flag. That would help us to avoid that strdup > fsle->fse.security_model = g_strdup(sec_model); > fsle->fse.ops = FsTypes[i].ops; > fsle->fse.cache_flags = 0; > diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h > index 9c440f2..0f67880 100644 > --- a/fsdev/qemu-fsdev.h > +++ b/fsdev/qemu-fsdev.h > @@ -40,6 +40,7 @@ typedef struct FsTypeTable { > typedef struct FsTypeEntry { > char *fsdev_id; > char *path; > +char *fsdriver; > char *security_model; > int cache_flags; > FileOperations *ops; > diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c > index aac58ad..1846e36 100644 > --- a/hw/9pfs/virtio-9p-device.c > +++ b/hw/9pfs/virtio-9p-device.c > @@ -83,29 +83,30 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf > *conf) > exit(1); > } > > -if (!strcmp(fse->security_model, "passthrough")) { > -/* Files on the Fileserver set to client user credentials */ > -s->ctx.fs_sm = SM_PASSTHROUGH; > -s->ctx.xops = passthrough_xattr_ops; > -} else if (!strcmp(fse->security_model, "mapped")) { > -/* Files on the fileserver are set to QEMU credentials. > - * Client user credentials are saved in extended attributes. > - */ > -s->ctx.fs_sm = SM_MAPPED; > -s->ctx.xops = mapped_xattr_ops; > -} else if (!strcmp(fse->security_model, "none")) { > -/* > - * Files on the fileserver are set to QEMU credentials. > - */ > -s->ctx.fs_sm = SM_NONE; > -s->ctx.xops = none_xattr_ops; > -} else { > -fprintf(stderr, "Default to security_model=none. You may want" > -" enable advanced security model using " > -"security option:\n\t security_model=passthrough\n\t " > -"security_model=mapped\n"); > -s->ctx.fs_sm = SM_NONE; > -s->ctx.xops = none_xattr_ops; > +/* security models is needed only for local fs driver */ > +if (!strcmp(fse->fsdriver, "local")) { > +if (!strcmp(fse->security_model, "passthrough")) { > +/* Files on the Fileserver set to client user credentials */ > +s->ctx.fs_sm = SM_PASSTHROUGH; > +s->ctx.xops = passthrough_xattr_ops; > +} else if (!strcmp(fse->security_model, "mapped")) { > +/* Files on the fileserver are set to QEMU credentials. > +* Client user credentials are saved in extended attributes. > +*/ > +s->ctx.fs_sm = SM_MAPPED; > +s->ctx.xops = mapped_xattr_ops; > +} else if (!strcmp(fse->security_model, "none")) { > +/* > +* Files on the fileserver are set to QEMU credentials. > +*/ > +s->ctx.fs_sm = SM_NONE; > +s->ctx.xops = none_xattr_ops; > +} else { > +fprintf(stderr, "Invalid security_model %s specified.\n" > +"Available security models are:\t " > +"passthrough,mapped or none\n", fse->security_model); > +exit(1); > +} > } > > s->ctx.cache_flags = fse->cache_flags; > diff --git a/vl.c b/vl.c > index 6760e39..a961fa3 100644 > --- a/vl.c > +++ b/vl.c > @@ -2795,6 +2795,7 @@ int main(int argc, char **argv, char **envp) > QemuOpts *fsdev; > QemuOpts *device; > const char *cache; > +const char *fsdriver; > > olist = qemu_find_opts("virtfs"); > if (!olist) { > @@ -2809,13 +2810,26 @@ int main(int argc, char **argv, char **envp) > > if (qemu_opt_get(opts, "fstype") == NULL || > qemu_opt_get(opts, "mount_tag") == NULL
Re: [Qemu-devel] [PATCH] hw/9pfs: Handle Security model parsing
On Wed, Oct 12, 2011 at 01:24:16PM +0530, M. Mohan Kumar wrote: > Security model is needed only for 'local' fs driver. > > Signed-off-by: M. Mohan Kumar > --- > fsdev/qemu-fsdev.c |6 + > fsdev/qemu-fsdev.h |1 + > hw/9pfs/virtio-9p-device.c | 47 ++- > vl.c | 20 +++-- > 4 files changed, 43 insertions(+), 31 deletions(-) > > --- a/fsdev/qemu-fsdev.h > +++ b/fsdev/qemu-fsdev.h > @@ -40,6 +40,7 @@ typedef struct FsTypeTable { > typedef struct FsTypeEntry { > char *fsdev_id; > char *path; > +char *fsdriver; > char *security_model; > int cache_flags; > FileOperations *ops; > diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c > index aac58ad..1846e36 100644 > --- a/hw/9pfs/virtio-9p-device.c > +++ b/hw/9pfs/virtio-9p-device.c > @@ -83,29 +83,30 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf > *conf) > exit(1); > } > > -if (!strcmp(fse->security_model, "passthrough")) { > -/* Files on the Fileserver set to client user credentials */ > -s->ctx.fs_sm = SM_PASSTHROUGH; > -s->ctx.xops = passthrough_xattr_ops; > -} else if (!strcmp(fse->security_model, "mapped")) { > -/* Files on the fileserver are set to QEMU credentials. > - * Client user credentials are saved in extended attributes. > - */ > -s->ctx.fs_sm = SM_MAPPED; > -s->ctx.xops = mapped_xattr_ops; > -} else if (!strcmp(fse->security_model, "none")) { > -/* > - * Files on the fileserver are set to QEMU credentials. > - */ > -s->ctx.fs_sm = SM_NONE; > -s->ctx.xops = none_xattr_ops; > -} else { > -fprintf(stderr, "Default to security_model=none. You may want" > -" enable advanced security model using " > -"security option:\n\t security_model=passthrough\n\t " > -"security_model=mapped\n"); > -s->ctx.fs_sm = SM_NONE; > -s->ctx.xops = none_xattr_ops; > +/* security models is needed only for local fs driver */ > +if (!strcmp(fse->fsdriver, "local")) { > +if (!strcmp(fse->security_model, "passthrough")) { > +/* Files on the Fileserver set to client user credentials */ > +s->ctx.fs_sm = SM_PASSTHROUGH; > +s->ctx.xops = passthrough_xattr_ops; > +} else if (!strcmp(fse->security_model, "mapped")) { > +/* Files on the fileserver are set to QEMU credentials. > +* Client user credentials are saved in extended attributes. > +*/ > +s->ctx.fs_sm = SM_MAPPED; > +s->ctx.xops = mapped_xattr_ops; > +} else if (!strcmp(fse->security_model, "none")) { > +/* > +* Files on the fileserver are set to QEMU credentials. > +*/ > +s->ctx.fs_sm = SM_NONE; > +s->ctx.xops = none_xattr_ops; > +} else { > +fprintf(stderr, "Invalid security_model %s specified.\n" > +"Available security models are:\t " > +"passthrough,mapped or none\n", fse->security_model); > +exit(1); > +} Are you sure there aren't use cases where people would like to choose between passthrough & mapped, even when using the 'proxy' or 'handle' security drivers. Both of the security models seem pretty generally useful to me, regardless of the driver type. Regards, Daniel -- |: http://berrange.com -o-http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|