Пример #1
0
static int vnc_auth_sasl_check_access(VncState *vs)
{
    const void *val;
    int err;
    int allow;

    err = sasl_getprop(vs->sasl.conn, SASL_USERNAME, &val);
    if (err != SASL_OK) {
        VNC_DEBUG("cannot query SASL username on connection %d (%s), denying access\n",
                  err, sasl_errstring(err, NULL, NULL));
        return -1;
    }
    if (val == NULL) {
        VNC_DEBUG("no client username was found, denying access\n");
        return -1;
    }
    VNC_DEBUG("SASL client username %s\n", (const char *)val);

    vs->sasl.username = g_strdup((const char*)val);

    if (vs->vd->sasl.acl == NULL) {
        VNC_DEBUG("no ACL activated, allowing access\n");
        return 0;
    }

    allow = qemu_acl_party_is_allowed(vs->vd->sasl.acl, vs->sasl.username);

    VNC_DEBUG("SASL client %s %s by ACL\n", vs->sasl.username,
              allow ? "allowed" : "denied");
    return allow ? 0 : -1;
}
Пример #2
0
static int
qcrypto_tls_session_check_certificate(QCryptoTLSSession *session,
                                      Error **errp)
{
    int ret;
    unsigned int status;
    const gnutls_datum_t *certs;
    unsigned int nCerts, i;
    time_t now;
    gnutls_x509_crt_t cert = NULL;

    now = time(NULL);
    if (now == ((time_t)-1)) {
        error_setg_errno(errp, errno, "Cannot get current time");
        return -1;
    }

    ret = gnutls_certificate_verify_peers2(session->handle, &status);
    if (ret < 0) {
        error_setg(errp, "Verify failed: %s", gnutls_strerror(ret));
        return -1;
    }

    if (status != 0) {
        const char *reason = "Invalid certificate";

        if (status & GNUTLS_CERT_INVALID) {
            reason = "The certificate is not trusted";
        }

        if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
            reason = "The certificate hasn't got a known issuer";
        }

        if (status & GNUTLS_CERT_REVOKED) {
            reason = "The certificate has been revoked";
        }

        if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
            reason = "The certificate uses an insecure algorithm";
        }

        error_setg(errp, "%s", reason);
        return -1;
    }

    certs = gnutls_certificate_get_peers(session->handle, &nCerts);
    if (!certs) {
        error_setg(errp, "No certificate peers");
        return -1;
    }

    for (i = 0; i < nCerts; i++) {
        ret = gnutls_x509_crt_init(&cert);
        if (ret < 0) {
            error_setg(errp, "Cannot initialize certificate: %s",
                       gnutls_strerror(ret));
            return -1;
        }

        ret = gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER);
        if (ret < 0) {
            error_setg(errp, "Cannot import certificate: %s",
                       gnutls_strerror(ret));
            goto error;
        }

        if (gnutls_x509_crt_get_expiration_time(cert) < now) {
            error_setg(errp, "The certificate has expired");
            goto error;
        }

        if (gnutls_x509_crt_get_activation_time(cert) > now) {
            error_setg(errp, "The certificate is not yet activated");
            goto error;
        }

        if (gnutls_x509_crt_get_activation_time(cert) > now) {
            error_setg(errp, "The certificate is not yet activated");
            goto error;
        }

        if (i == 0) {
            size_t dnameSize = 1024;
            session->peername = g_malloc(dnameSize);
        requery:
            ret = gnutls_x509_crt_get_dn(cert, session->peername, &dnameSize);
            if (ret < 0) {
                if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
                    session->peername = g_realloc(session->peername,
                                                  dnameSize);
                    goto requery;
                }
                error_setg(errp, "Cannot get client distinguished name: %s",
                           gnutls_strerror(ret));
                goto error;
            }
            if (session->aclname) {
                qemu_acl *acl = qemu_acl_find(session->aclname);
                int allow;
                if (!acl) {
                    error_setg(errp, "Cannot find ACL %s",
                               session->aclname);
                    goto error;
                }

                allow = qemu_acl_party_is_allowed(acl, session->peername);

                if (!allow) {
                    error_setg(errp, "TLS x509 ACL check for %s is denied",
                               session->peername);
                    goto error;
                }
            }
            if (session->hostname) {
                if (!gnutls_x509_crt_check_hostname(cert, session->hostname)) {
                    error_setg(errp,
                               "Certificate does not match the hostname %s",
                               session->hostname);
                    goto error;
                }
            }
        }

        gnutls_x509_crt_deinit(cert);
    }

    return 0;

 error:
    gnutls_x509_crt_deinit(cert);
    return -1;
}
Пример #3
0
int vnc_tls_validate_certificate(struct VncState *vs)
{
    int ret;
    unsigned int status;
    const gnutls_datum_t *certs;
    unsigned int nCerts, i;
    time_t now;

    VNC_DEBUG("Validating client certificate\n");
    if ((ret = gnutls_certificate_verify_peers2 (vs->tls.session, &status)) < 0) {
        VNC_DEBUG("Verify failed %s\n", gnutls_strerror(ret));
        return -1;
    }

    if ((now = time(NULL)) == ((time_t)-1)) {
        return -1;
    }

    if (status != 0) {
        if (status & GNUTLS_CERT_INVALID)
            VNC_DEBUG("The certificate is not trusted.\n");

        if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
            VNC_DEBUG("The certificate hasn't got a known issuer.\n");

        if (status & GNUTLS_CERT_REVOKED)
            VNC_DEBUG("The certificate has been revoked.\n");

        if (status & GNUTLS_CERT_INSECURE_ALGORITHM)
            VNC_DEBUG("The certificate uses an insecure algorithm\n");

        return -1;
    } else {
        VNC_DEBUG("Certificate is valid!\n");
    }

    /* Only support x509 for now */
    if (gnutls_certificate_type_get(vs->tls.session) != GNUTLS_CRT_X509)
        return -1;

    if (!(certs = gnutls_certificate_get_peers(vs->tls.session, &nCerts)))
        return -1;

    for (i = 0 ; i < nCerts ; i++) {
        gnutls_x509_crt_t cert;
        VNC_DEBUG ("Checking certificate chain %d\n", i);
        if (gnutls_x509_crt_init (&cert) < 0)
            return -1;

        if (gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER) < 0) {
            gnutls_x509_crt_deinit (cert);
            return -1;
        }

        if (gnutls_x509_crt_get_expiration_time (cert) < now) {
            VNC_DEBUG("The certificate has expired\n");
            gnutls_x509_crt_deinit (cert);
            return -1;
        }

        if (gnutls_x509_crt_get_activation_time (cert) > now) {
            VNC_DEBUG("The certificate is not yet activated\n");
            gnutls_x509_crt_deinit (cert);
            return -1;
        }

        if (gnutls_x509_crt_get_activation_time (cert) > now) {
            VNC_DEBUG("The certificate is not yet activated\n");
            gnutls_x509_crt_deinit (cert);
            return -1;
        }

        if (i == 0) {
            size_t dnameSize = 1024;
            vs->tls.dname = g_malloc(dnameSize);
        requery:
            if ((ret = gnutls_x509_crt_get_dn (cert, vs->tls.dname, &dnameSize)) != 0) {
                if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
                    vs->tls.dname = g_realloc(vs->tls.dname, dnameSize);
                    goto requery;
                }
                gnutls_x509_crt_deinit (cert);
                VNC_DEBUG("Cannot get client distinguished name: %s",
                          gnutls_strerror (ret));
                return -1;
            }

            if (vs->vd->tls.x509verify) {
                int allow;
                if (!vs->vd->tls.acl) {
                    VNC_DEBUG("no ACL activated, allowing access");
                    gnutls_x509_crt_deinit (cert);
                    continue;
                }

                allow = qemu_acl_party_is_allowed(vs->vd->tls.acl,
                                                  vs->tls.dname);

                VNC_DEBUG("TLS x509 ACL check for %s is %s\n",
                          vs->tls.dname, allow ? "allowed" : "denied");
                if (!allow) {
                    gnutls_x509_crt_deinit (cert);
                    return -1;
                }
            }
        }

        gnutls_x509_crt_deinit (cert);
    }

    return 0;
}