예제 #1
0
/*
 * This tests sanity checking of our own certificates
 *
 * This code is done when libvirtd starts up, or before
 * a libvirt client connects. The test is ensuring that
 * the creation of virNetTLSContextPtr fails if we
 * give bogus certs, or succeeds for good certs
 */
static int testTLSContextInit(const void *opaque)
{
    struct testTLSContextData *data = (struct testTLSContextData *)opaque;
    virNetTLSContextPtr ctxt = NULL;
    int ret = -1;

    if (data->isServer) {
        ctxt = virNetTLSContextNewServer(data->cacrt,
                                         NULL,
                                         data->crt,
                                         KEYFILE,
                                         NULL,
                                         "NORMAL",
                                         true,
                                         true);
    } else {
        ctxt = virNetTLSContextNewClient(data->cacrt,
                                         NULL,
                                         data->crt,
                                         KEYFILE,
                                         "NORMAL",
                                         true,
                                         true);
    }

    if (ctxt) {
        if (data->expectFail) {
            VIR_WARN("Expected failure %s against %s",
                     data->cacrt, data->crt);
            goto cleanup;
        }
    } else {
        if (!data->expectFail) {
            VIR_WARN("Unexpected failure %s against %s",
                     data->cacrt, data->crt);
            goto cleanup;
        }
        VIR_DEBUG("Got error %s", virGetLastErrorMessage());
    }

    ret = 0;

 cleanup:
    virObjectUnref(ctxt);
    return ret;
}
예제 #2
0
static int daemonSetupNetworking(virNetServerPtr srv,
                                 struct daemonConfig *config,
                                 const char *sock_path,
                                 const char *sock_path_ro,
                                 bool ipsock,
                                 bool privileged)
{
    virNetServerServicePtr svc = NULL;
    virNetServerServicePtr svcRO = NULL;
    virNetServerServicePtr svcTCP = NULL;
    virNetServerServicePtr svcTLS = NULL;
    gid_t unix_sock_gid = 0;
    int unix_sock_ro_mask = 0;
    int unix_sock_rw_mask = 0;

    if (config->unix_sock_group) {
        if (virGetGroupID(config->unix_sock_group, &unix_sock_gid) < 0)
            return -1;
    }

    if (virStrToLong_i(config->unix_sock_ro_perms, NULL, 8, &unix_sock_ro_mask) != 0) {
        VIR_ERROR(_("Failed to parse mode '%s'"), config->unix_sock_ro_perms);
        goto error;
    }

    if (virStrToLong_i(config->unix_sock_rw_perms, NULL, 8, &unix_sock_rw_mask) != 0) {
        VIR_ERROR(_("Failed to parse mode '%s'"), config->unix_sock_rw_perms);
        goto error;
    }

    if (!(svc = virNetServerServiceNewUNIX(sock_path,
                                           unix_sock_rw_mask,
                                           unix_sock_gid,
                                           config->auth_unix_rw,
                                           false,
                                           config->max_client_requests,
                                           NULL)))
        goto error;
    if (sock_path_ro &&
        !(svcRO = virNetServerServiceNewUNIX(sock_path_ro,
                                             unix_sock_ro_mask,
                                             unix_sock_gid,
                                             config->auth_unix_ro,
                                             true,
                                             config->max_client_requests,
                                             NULL)))
        goto error;

    if (virNetServerAddService(srv, svc,
                               config->mdns_adv && !ipsock ?
                               "_libvirt._tcp" :
                               NULL) < 0)
        goto error;

    if (svcRO &&
        virNetServerAddService(srv, svcRO, NULL) < 0)
        goto error;

    if (ipsock) {
        if (config->listen_tcp) {
            if (!(svcTCP = virNetServerServiceNewTCP(config->listen_addr,
                                                     config->tcp_port,
                                                     config->auth_tcp,
                                                     false,
                                                     config->max_client_requests,
                                                     NULL)))
                goto error;

            if (virNetServerAddService(srv, svcTCP,
                                       config->mdns_adv ? "_libvirt._tcp" : NULL) < 0)
                goto error;
        }

        if (config->listen_tls) {
            virNetTLSContextPtr ctxt = NULL;

            if (config->ca_file ||
                config->cert_file ||
                config->key_file) {
                if (!(ctxt = virNetTLSContextNewServer(config->ca_file,
                                                       config->crl_file,
                                                       config->cert_file,
                                                       config->key_file,
                                                       (const char *const*)config->tls_allowed_dn_list,
                                                       config->tls_no_sanity_certificate ? false : true,
                                                       config->tls_no_verify_certificate ? false : true)))
                    goto error;
            } else {
                if (!(ctxt = virNetTLSContextNewServerPath(NULL,
                                                           !privileged,
                                                           (const char *const*)config->tls_allowed_dn_list,
                                                           config->tls_no_sanity_certificate ? false : true,
                                                           config->tls_no_verify_certificate ? false : true)))
                    goto error;
            }

            if (!(svcTLS =
                  virNetServerServiceNewTCP(config->listen_addr,
                                            config->tls_port,
                                            config->auth_tls,
                                            false,
                                            config->max_client_requests,
                                            ctxt))) {
                virNetTLSContextFree(ctxt);
                goto error;
            }
            if (virNetServerAddService(srv, svcTLS,
                                       config->mdns_adv &&
                                       !config->listen_tcp ? "_libvirt._tcp" : NULL) < 0)
                goto error;

            virNetTLSContextFree(ctxt);
        }
    }

#if HAVE_SASL
    if (config->auth_unix_rw == REMOTE_AUTH_SASL ||
        config->auth_unix_ro == REMOTE_AUTH_SASL ||
        config->auth_tcp == REMOTE_AUTH_SASL ||
        config->auth_tls == REMOTE_AUTH_SASL) {
        saslCtxt = virNetSASLContextNewServer(
            (const char *const*)config->sasl_allowed_username_list);
        if (!saslCtxt)
            goto error;
    }
#endif

    return 0;

error:
    virNetServerServiceFree(svcTLS);
    virNetServerServiceFree(svcTCP);
    virNetServerServiceFree(svc);
    virNetServerServiceFree(svcRO);
    return -1;
}
예제 #3
0
파일: libvirtd.c 프로젝트: 6WIND/libvirt
static int daemonSetupNetworking(virNetServerPtr srv,
                                 struct daemonConfig *config,
                                 const char *sock_path,
                                 const char *sock_path_ro,
                                 bool ipsock,
                                 bool privileged)
{
    virNetServerServicePtr svc = NULL;
    virNetServerServicePtr svcRO = NULL;
    virNetServerServicePtr svcTCP = NULL;
#if WITH_GNUTLS
    virNetServerServicePtr svcTLS = NULL;
#endif
    gid_t unix_sock_gid = 0;
    int unix_sock_ro_mask = 0;
    int unix_sock_rw_mask = 0;

    if (config->unix_sock_group) {
        if (virGetGroupID(config->unix_sock_group, &unix_sock_gid) < 0)
            return -1;
    }

    if (virStrToLong_i(config->unix_sock_ro_perms, NULL, 8, &unix_sock_ro_mask) != 0) {
        VIR_ERROR(_("Failed to parse mode '%s'"), config->unix_sock_ro_perms);
        goto error;
    }

    if (virStrToLong_i(config->unix_sock_rw_perms, NULL, 8, &unix_sock_rw_mask) != 0) {
        VIR_ERROR(_("Failed to parse mode '%s'"), config->unix_sock_rw_perms);
        goto error;
    }

    VIR_DEBUG("Registering unix socket %s", sock_path);
    if (!(svc = virNetServerServiceNewUNIX(sock_path,
                                           unix_sock_rw_mask,
                                           unix_sock_gid,
                                           config->auth_unix_rw,
#if WITH_GNUTLS
                                           NULL,
#endif
                                           false,
                                           config->max_queued_clients,
                                           config->max_client_requests)))
        goto error;
    if (sock_path_ro) {
        VIR_DEBUG("Registering unix socket %s", sock_path_ro);
        if (!(svcRO = virNetServerServiceNewUNIX(sock_path_ro,
                                                 unix_sock_ro_mask,
                                                 unix_sock_gid,
                                                 config->auth_unix_ro,
#if WITH_GNUTLS
                                                 NULL,
#endif
                                                 true,
                                                 config->max_queued_clients,
                                                 config->max_client_requests)))
            goto error;
    }

    if (virNetServerAddService(srv, svc,
                               config->mdns_adv && !ipsock ?
                               "_libvirt._tcp" :
                               NULL) < 0)
        goto error;

    if (svcRO &&
        virNetServerAddService(srv, svcRO, NULL) < 0)
        goto error;

    if (ipsock) {
        if (config->listen_tcp) {
            VIR_DEBUG("Registering TCP socket %s:%s",
                      config->listen_addr, config->tcp_port);
            if (!(svcTCP = virNetServerServiceNewTCP(config->listen_addr,
                                                     config->tcp_port,
                                                     config->auth_tcp,
#if WITH_GNUTLS
                                                     NULL,
#endif
                                                     false,
                                                     config->max_queued_clients,
                                                     config->max_client_requests)))
                goto error;

            if (virNetServerAddService(srv, svcTCP,
                                       config->mdns_adv ? "_libvirt._tcp" : NULL) < 0)
                goto error;
        }

#if WITH_GNUTLS
        if (config->listen_tls) {
            virNetTLSContextPtr ctxt = NULL;

            if (config->ca_file ||
                config->cert_file ||
                config->key_file) {
                if (!(ctxt = virNetTLSContextNewServer(config->ca_file,
                                                       config->crl_file,
                                                       config->cert_file,
                                                       config->key_file,
                                                       (const char *const*)config->tls_allowed_dn_list,
                                                       config->tls_no_sanity_certificate ? false : true,
                                                       config->tls_no_verify_certificate ? false : true)))
                    goto error;
            } else {
                if (!(ctxt = virNetTLSContextNewServerPath(NULL,
                                                           !privileged,
                                                           (const char *const*)config->tls_allowed_dn_list,
                                                           config->tls_no_sanity_certificate ? false : true,
                                                           config->tls_no_verify_certificate ? false : true)))
                    goto error;
            }

            VIR_DEBUG("Registering TLS socket %s:%s",
                      config->listen_addr, config->tls_port);
            if (!(svcTLS =
                  virNetServerServiceNewTCP(config->listen_addr,
                                            config->tls_port,
                                            config->auth_tls,
                                            ctxt,
                                            false,
                                            config->max_queued_clients,
                                            config->max_client_requests))) {
                virObjectUnref(ctxt);
                goto error;
            }
            if (virNetServerAddService(srv, svcTLS,
                                       config->mdns_adv &&
                                       !config->listen_tcp ? "_libvirt._tcp" : NULL) < 0)
                goto error;

            virObjectUnref(ctxt);
        }
#else
        (void)privileged;
        if (config->listen_tls) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("This libvirtd build does not support TLS"));
            goto error;
        }
#endif
    }

#if WITH_SASL
    if (config->auth_unix_rw == REMOTE_AUTH_SASL ||
        config->auth_unix_ro == REMOTE_AUTH_SASL ||
# if WITH_GNUTLS
        config->auth_tls == REMOTE_AUTH_SASL ||
# endif
        config->auth_tcp == REMOTE_AUTH_SASL) {
        saslCtxt = virNetSASLContextNewServer(
            (const char *const*)config->sasl_allowed_username_list);
        if (!saslCtxt)
            goto error;
    }
#endif

    return 0;

 error:
#if WITH_GNUTLS
    virObjectUnref(svcTLS);
#endif
    virObjectUnref(svcTCP);
    virObjectUnref(svc);
    virObjectUnref(svcRO);
    return -1;
}
예제 #4
0
/*
 * This tests validation checking of peer certificates
 *
 * This is replicating the checks that are done for an
 * active TLS session after handshake completes. To
 * simulate that we create our TLS contexts, skipping
 * sanity checks. When then get a socketpair, and
 * initiate a TLS session across them. Finally do
 * do actual cert validation tests
 */
static int testTLSSessionInit(const void *opaque)
{
    struct testTLSSessionData *data = (struct testTLSSessionData *)opaque;
    virNetTLSContextPtr clientCtxt = NULL;
    virNetTLSContextPtr serverCtxt = NULL;
    virNetTLSSessionPtr clientSess = NULL;
    virNetTLSSessionPtr serverSess = NULL;
    int ret = -1;
    int channel[2];
    bool clientShake = false;
    bool serverShake = false;


    /* We'll use this for our fake client-server connection */
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, channel) < 0)
        abort();

    /*
     * We have an evil loop to do the handshake in a single
     * thread, so we need these non-blocking to avoid deadlock
     * of ourselves
     */
    ignore_value(virSetNonBlock(channel[0]));
    ignore_value(virSetNonBlock(channel[1]));


    /* We skip initial sanity checks here because we
     * want to make sure that problems are being
     * detected at the TLS session validation stage
     */
    serverCtxt = virNetTLSContextNewServer(data->servercacrt,
                                           NULL,
                                           data->servercrt,
                                           KEYFILE,
                                           data->wildcards,
                                           NULL,
                                           false,
                                           true);

    clientCtxt = virNetTLSContextNewClient(data->clientcacrt,
                                           NULL,
                                           data->clientcrt,
                                           KEYFILE,
                                           NULL,
                                           false,
                                           true);

    if (!serverCtxt) {
        VIR_WARN("Unexpected failure loading %s against %s",
                 data->servercacrt, data->servercrt);
        goto cleanup;
    }
    if (!clientCtxt) {
        VIR_WARN("Unexpected failure loading %s against %s",
                 data->clientcacrt, data->clientcrt);
        goto cleanup;
    }


    /* Now the real part of the test, setup the sessions */
    serverSess = virNetTLSSessionNew(serverCtxt, NULL);
    clientSess = virNetTLSSessionNew(clientCtxt, data->hostname);

    if (!serverSess) {
        VIR_WARN("Unexpected failure using %s against %s",
                 data->servercacrt, data->servercrt);
        goto cleanup;
    }
    if (!clientSess) {
        VIR_WARN("Unexpected failure using %s against %s",
                 data->clientcacrt, data->clientcrt);
        goto cleanup;
    }

    /* For handshake to work, we need to set the I/O callbacks
     * to read/write over the socketpair
     */
    virNetTLSSessionSetIOCallbacks(serverSess, testWrite, testRead, &channel[0]);
    virNetTLSSessionSetIOCallbacks(clientSess, testWrite, testRead, &channel[1]);

    /*
     * Finally we loop around & around doing handshake on each
     * session until we get an error, or the handshake completes.
     * This relies on the socketpair being nonblocking to avoid
     * deadlocking ourselves upon handshake
     */
    do {
        int rv;
        if (!serverShake) {
            rv = virNetTLSSessionHandshake(serverSess);
            if (rv < 0)
                goto cleanup;
            if (rv == VIR_NET_TLS_HANDSHAKE_COMPLETE)
                serverShake = true;
        }
        if (!clientShake) {
            rv = virNetTLSSessionHandshake(clientSess);
            if (rv < 0)
                goto cleanup;
            if (rv == VIR_NET_TLS_HANDSHAKE_COMPLETE)
                clientShake = true;
        }
    } while (!clientShake && !serverShake);


    /* Finally make sure the server validation does what
     * we were expecting
     */
    if (virNetTLSContextCheckCertificate(serverCtxt,
                                         serverSess) < 0) {
        if (!data->expectServerFail) {
            VIR_WARN("Unexpected server cert check fail");
            goto cleanup;
        } else {
            VIR_DEBUG("Got expected server cert fail");
        }
    } else {
        if (data->expectServerFail) {
            VIR_WARN("Expected server cert check fail");
            goto cleanup;
        } else {
            VIR_DEBUG("No unexpected server cert fail");
        }
    }

    /*
     * And the same for the client validation check
     */
    if (virNetTLSContextCheckCertificate(clientCtxt,
                                         clientSess) < 0) {
        if (!data->expectClientFail) {
            VIR_WARN("Unexpected client cert check fail");
            goto cleanup;
        } else {
            VIR_DEBUG("Got expected client cert fail");
        }
    } else {
        if (data->expectClientFail) {
            VIR_WARN("Expected client cert check fail");
            goto cleanup;
        } else {
            VIR_DEBUG("No unexpected client cert fail");
        }
    }

    ret = 0;

cleanup:
    virObjectUnref(serverCtxt);
    virObjectUnref(clientCtxt);
    virObjectUnref(serverSess);
    virObjectUnref(clientSess);

    VIR_FORCE_CLOSE(channel[0]);
    VIR_FORCE_CLOSE(channel[1]);
    return ret;
}
예제 #5
0
daemonSetupNetworking(virNetServerPtr srv,
                      virNetServerPtr srvAdm,
                      struct daemonConfig *config,
                      const char *sock_path,
                      const char *sock_path_ro,
                      const char *sock_path_adm,
                      bool ipsock,
                      bool privileged)
{
    virNetServerServicePtr svc = NULL;
    virNetServerServicePtr svcAdm = NULL;
    virNetServerServicePtr svcRO = NULL;
    virNetServerServicePtr svcTCP = NULL;
#if WITH_GNUTLS
    virNetServerServicePtr svcTLS = NULL;
#endif
    gid_t unix_sock_gid = 0;
    int unix_sock_ro_mask = 0;
    int unix_sock_rw_mask = 0;
    int unix_sock_adm_mask = 0;
    int ret = -1;

    unsigned int cur_fd = STDERR_FILENO + 1;
    unsigned int nfds = virGetListenFDs();

    if (config->unix_sock_group) {
        if (virGetGroupID(config->unix_sock_group, &unix_sock_gid) < 0)
            return ret;
    }

    if (nfds > (sock_path_ro ? 2 : 1)) {
        VIR_ERROR(_("Too many (%u) FDs passed from caller"), nfds);
        return ret;
    }

    if (virStrToLong_i(config->unix_sock_ro_perms, NULL, 8, &unix_sock_ro_mask) != 0) {
        VIR_ERROR(_("Failed to parse mode '%s'"), config->unix_sock_ro_perms);
        goto cleanup;
    }

    if (virStrToLong_i(config->unix_sock_admin_perms, NULL, 8, &unix_sock_adm_mask) != 0) {
        VIR_ERROR(_("Failed to parse mode '%s'"), config->unix_sock_admin_perms);
        goto cleanup;
    }

    if (virStrToLong_i(config->unix_sock_rw_perms, NULL, 8, &unix_sock_rw_mask) != 0) {
        VIR_ERROR(_("Failed to parse mode '%s'"), config->unix_sock_rw_perms);
        goto cleanup;
    }

    if (!(svc = virNetServerServiceNewFDOrUNIX(sock_path,
                                               unix_sock_rw_mask,
                                               unix_sock_gid,
                                               config->auth_unix_rw,
#if WITH_GNUTLS
                                               NULL,
#endif
                                               false,
                                               config->max_queued_clients,
                                               config->max_client_requests,
                                               nfds, &cur_fd)))
        goto cleanup;
    if (sock_path_ro) {
        if (!(svcRO = virNetServerServiceNewFDOrUNIX(sock_path_ro,
                                                     unix_sock_ro_mask,
                                                     unix_sock_gid,
                                                     config->auth_unix_ro,
#if WITH_GNUTLS
                                                     NULL,
#endif
                                                     true,
                                                     config->max_queued_clients,
                                                     config->max_client_requests,
                                                     nfds, &cur_fd)))
            goto cleanup;
    }

    if (virNetServerAddService(srv, svc,
                               config->mdns_adv && !ipsock ?
                               "_libvirt._tcp" :
                               NULL) < 0)
        goto cleanup;

    if (svcRO &&
        virNetServerAddService(srv, svcRO, NULL) < 0)
        goto cleanup;

    /* Temporarily disabled */
    if (sock_path_adm && false) {
        VIR_DEBUG("Registering unix socket %s", sock_path_adm);
        if (!(svcAdm = virNetServerServiceNewUNIX(sock_path_adm,
                                                  unix_sock_adm_mask,
                                                  unix_sock_gid,
                                                  REMOTE_AUTH_NONE,
#if WITH_GNUTLS
                                                  NULL,
#endif
                                                  true,
                                                  config->admin_max_queued_clients,
                                                  config->admin_max_client_requests)))
            goto cleanup;

        if (virNetServerAddService(srvAdm, svcAdm, NULL) < 0)
            goto cleanup;
    }

    if (ipsock) {
        if (config->listen_tcp) {
            VIR_DEBUG("Registering TCP socket %s:%s",
                      config->listen_addr, config->tcp_port);
            if (!(svcTCP = virNetServerServiceNewTCP(config->listen_addr,
                                                     config->tcp_port,
                                                     AF_UNSPEC,
                                                     config->auth_tcp,
#if WITH_GNUTLS
                                                     NULL,
#endif
                                                     false,
                                                     config->max_queued_clients,
                                                     config->max_client_requests)))
                goto cleanup;

            if (virNetServerAddService(srv, svcTCP,
                                       config->mdns_adv ? "_libvirt._tcp" : NULL) < 0)
                goto cleanup;
        }

#if WITH_GNUTLS
        if (config->listen_tls) {
            virNetTLSContextPtr ctxt = NULL;

            if (config->ca_file ||
                config->cert_file ||
                config->key_file) {
                if (!(ctxt = virNetTLSContextNewServer(config->ca_file,
                                                       config->crl_file,
                                                       config->cert_file,
                                                       config->key_file,
                                                       (const char *const*)config->tls_allowed_dn_list,
                                                       config->tls_no_sanity_certificate ? false : true,
                                                       config->tls_no_verify_certificate ? false : true)))
                    goto cleanup;
            } else {
                if (!(ctxt = virNetTLSContextNewServerPath(NULL,
                                                           !privileged,
                                                           (const char *const*)config->tls_allowed_dn_list,
                                                           config->tls_no_sanity_certificate ? false : true,
                                                           config->tls_no_verify_certificate ? false : true)))
                    goto cleanup;
            }

            VIR_DEBUG("Registering TLS socket %s:%s",
                      config->listen_addr, config->tls_port);
            if (!(svcTLS =
                  virNetServerServiceNewTCP(config->listen_addr,
                                            config->tls_port,
                                            AF_UNSPEC,
                                            config->auth_tls,
                                            ctxt,
                                            false,
                                            config->max_queued_clients,
                                            config->max_client_requests))) {
                virObjectUnref(ctxt);
                goto cleanup;
            }
            if (virNetServerAddService(srv, svcTLS,
                                       config->mdns_adv &&
                                       !config->listen_tcp ? "_libvirt._tcp" : NULL) < 0)
                goto cleanup;

            virObjectUnref(ctxt);
        }
#else
        (void)privileged;
        if (config->listen_tls) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("This libvirtd build does not support TLS"));
            goto cleanup;
        }
#endif
    }

#if WITH_SASL
    if (config->auth_unix_rw == REMOTE_AUTH_SASL ||
        config->auth_unix_ro == REMOTE_AUTH_SASL ||
# if WITH_GNUTLS
        config->auth_tls == REMOTE_AUTH_SASL ||
# endif
        config->auth_tcp == REMOTE_AUTH_SASL) {
        saslCtxt = virNetSASLContextNewServer(
            (const char *const*)config->sasl_allowed_username_list);
        if (!saslCtxt)
            goto cleanup;
    }
#endif

    ret = 0;

 cleanup:
#if WITH_GNUTLS
    virObjectUnref(svcTLS);
#endif
    virObjectUnref(svcTCP);
    virObjectUnref(svcRO);
    virObjectUnref(svcAdm);
    virObjectUnref(svc);
    return ret;
}