Daniel P. Berrange wrote:
On Sat, May 05, 2007 at 12:17:44PM +0100, Richard W.M. Jones wrote:
Richard W.M. Jones wrote:
3 Client-side
-------------

A src/remote_internal.c
A src/remote_internal.h
M src/driver.h
M src/libvirt.c
[...]
What sort of info is currently stored in the  $sysconfdir/libvirtd.conf
file ? It seems to be referred to by both the client & server.

Hopefully only the server is reading this file.

It contains things like:
* What ports the server should listen on?
* Should the server verify TLS certs?
* ACL (list of IP addresses) of clients
* Location of various PKI files

All of these things have sensible defaults, so you can run the server without the file at all.

If you look at qemud/qemud.c:remoteReadConfigFile you'll find the code which reads this file. Yes, this needs to be documented (see step 7 of 8).

On the subject of
 /* GnuTLS functions used by remoteOpen. */
 #define CAFILE "demoCA/cacert.pem" /* XXX */
 #define KEY_FILE "127001key.pem" /* XXX */
 #define CERT_FILE "127001cert.pem" /* XXX */

We've got to think about best way to provide TLS parameters. Bearing in mind
that people may want to port to Mozilla NSS in the future I think it is probably best to not provide formal APIs for these options at this time, and
instead pick them up from the client's config file. As previously discussed
there's no clear standard for location of TLS certs, so I reckon we just default to something like

   tls_ca_cert = "/etc/pks/tls/ca-cert.pem"
   tls_secret = "/etc/pks/tls/libvirt-key.pem"
   tls_cert = "/etc/pks/tls/libvirt-cert.pem"

Yes, agreed. That is a to-do action, as well as documenting how to create these files. One thing I need to do is go back over my notes and work out how _I_ created the files ...

Since we're using client certs for authentication to start with, we ought
to actually make it possible to keep the certs in per-user home dirs rather
than globally readable. eg $HOME/.pki/tls/libvirt-key.pem  and mode 0600

Yes, I'll make a note to talk to the Fedora people about this.

The driver itself (remote_internal.c) consists of the following parts, arranged here in the same order that they appear in the file:

(1) remoteOpen and associated, GnuTLS initialisation

This function and associated functions deals with parsing the remote URI, deciding which transport to use, deciding the URI to forward to the remote end, creating the transport (including initialising GnuTLS, forking ssh, ...), and verifying the server's certificate.

Wrt to this snippet in negotiate_gnutls_on_connection()

   const int cert_type_priority[3] = {
       GNUTLS_CRT_X509,
       GNUTLS_CRT_OPENPGP,
       0
   };

Do we have support in the client/server for doing whatever checks are needed
for the OpenPGP style 'certs'. If not we should probably comment out the
OpenGPG option for now.

Actually looking at the code it's worse than that - at the moment it accepts the certificate and then rejects it later on because it's not an X.509 cert. --> To fix.

(2) The driver functions, remoteClose, remoteType, etc. etc.
(3) The network driver functions, remoteNetworkOpen, etc. etc.

For each function we serialise the parameters as an XDR remote_foo_args object, use the generic "call" function to dispatch the call, then deserialise the XDR remote_foo_ret return value. Most of the heavy lifting for the RPC is done in the "call" function itself ...

This all loooks good to me. Only thought I had was perhaps that

      GET_PRIVATE (conn, -1);

is slightly more readable as

      struct private_data *priv = GET_PRIVATE (conn, -1);

ie, to make it clear to the readable what local variable is being
provided, while still hiding away all the tedious error checking /
assertion logic.

The problem is that GET_PRIVATE has side effects, in particular it can return with an error if the connection object or private pointer is corrupt. Would this require a gcc extension to implement? I'll check.

BTW, although this business of checking if connections are NULL and checking magics and then returning is done a lot in libvirt, I don't agree with it _at all_. I think that the library should abort / assert fail in such cases, because the earlier that memory corruption is detected the better. (Better still would be to use a language where this can't happen).

(4) The RPC implementation (function "call"), error handling, serialisation of virDomainPtr and virNetworkPtr.

In the 'call' method:

   /* Get a unique serial number for this message. */
   /* XXX This is supposed to be atomic over threads, but I don't know
    * if it is.
    */
   static sig_atomic_t counter = 1;
   sig_atomic_t serial = counter++;

Serial numbers only need to be unique within the scope of a single
client <-> server socket connection. So could we just store the
counter in the virConectPtr private data struct to avoid the threading
question here

Yes, good thinking.  I'll fix it.

... which also deals with making error handling transparent.

static void
error (virConnectPtr conn, virErrorNumber code, const char *info)
{
    const char *errmsg;
    /* XXX I don't think this is correct use of virErrorMsg. */
   errmsg = __virErrorMsg (code, info);


This looks consistent with the way other drivers are using __virErrorMsg
at least. Anything in particular you thought was wrong ?

I looked at what precisely happened inside virterror on Friday and came to the conclusion that this was correct, so I'll remove the comment.

Rich.

--
Libvir-list mailing list
Libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to