Esempio n. 1
1
int openssl_apply_verification_policy(SSL *ssl, X509 *peer, stream *stream) /* {{{ */
{
    zval **val = NULL;
    char *cnmatch = NULL;
    X509_NAME *name;
    char buf[1024];
    int err;

    /* verification is turned off */
    if (!(GET_VER_OPT("verify_peer") && zval_is_true(*val))) {
        return 0;
    }

    if (peer == NULL) {
        error_docref(NULL, E_WARNING, "Could not get peer certificate");
        return -1;
    }

    err = SSL_get_verify_result(ssl);
    switch (err) {
    case X509_V_OK:
        /* fine */
        break;
    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
        if (GET_VER_OPT("allow_self_signed") && zval_is_true(*val)) {
            /* allowed */
            break;
        }
    /* not allowed, so fall through */
    default:
        error_docref(NULL, E_WARNING, "Could not verify peer: code:%d %s", err, X509_verify_cert_error_string(err));
        return -1;
    }

    /* if the cert passed the usual checks, apply our own local policies now */

    name = X509_get_subject_name(peer);

    /* Does the common name match ? (used primarily for https://) */
    GET_VER_OPT_STRING("CN_match", cnmatch);
    if (cnmatch) {
        int match = 0;
        int name_len = X509_NAME_get_text_by_NID(name, NID_commonName, buf, sizeof(buf));

        if (name_len == -1) {
            error_docref(NULL, E_WARNING, "Unable to locate peer certificate CN");
            return -1;
        } else if (name_len != strlen(buf)) {
            error_docref(NULL, E_WARNING, "Peer certificate CN=`%.*s' is malformed", name_len, buf);
            return -1;
        }

        match = strcmp(cnmatch, buf) == 0;
        if (!match && strlen(buf) > 3 && buf[0] == '*' && buf[1] == '.') {
            /* Try wildcard */

            if (strchr(buf+2, '.')) {
                char *tmp = strstr(cnmatch, buf+1);

                match = tmp && strcmp(tmp, buf+2) && tmp == strchr(cnmatch, '.');
            }
        }

        if (!match) {
            /* didn't match */
            error_docref(NULL, E_WARNING, "Peer certificate CN=`%.*s' did not match expected CN=`%s'", name_len, buf, cnmatch);
            return -1;
        }
    }

    return 0;
}
Esempio n. 2
0
int write_dsig_template(opendcp_t *opendcp, xmlTextWriterPtr xml) {
    BIO *bio[3];
    X509 *x[3];
    X509_NAME *issuer_xn[3];
    X509_NAME *subject_xn[3];
    char *cert[3];
    int i;

    dcp_log(LOG_DEBUG, "xml_sign: write_dsig_template");

    if (opendcp->xml_signature.use_external) {
        /* read certificates from file */
        FILE *cp;

        cp = fopen(opendcp->xml_signature.signer,"rb");
        if (cp) {
            x[0] = PEM_read_X509(cp,NULL,NULL,NULL);
            fclose(cp);
        }
        cp = fopen(opendcp->xml_signature.ca,"rb");
        if (cp) {
            x[1] = PEM_read_X509(cp,NULL,NULL,NULL);
            fclose(cp);
        }
        cp = fopen(opendcp->xml_signature.root,"rb");
        if (cp) {
            x[2] = PEM_read_X509(cp,NULL,NULL,NULL);
            fclose(cp);
        }
        cert[0] = strip_cert_file(opendcp->xml_signature.signer);
        cert[1] = strip_cert_file(opendcp->xml_signature.ca);
        cert[2] = strip_cert_file(opendcp->xml_signature.root);
    } else {
        /* read certificate from memory */
        bio[0] = BIO_new_mem_buf((void *)opendcp_signer_cert, -1);
        bio[1] = BIO_new_mem_buf((void *)opendcp_ca_cert, -1);
        bio[2] = BIO_new_mem_buf((void *)opendcp_root_cert, -1);

        /* save a copy with the BEGIN/END stripped */
        cert[0] = strip_cert(opendcp_signer_cert);
        cert[1] = strip_cert(opendcp_ca_cert);
        cert[2] = strip_cert(opendcp_root_cert);

        for (i=0; i<3; i++) {
            if (bio[i] == NULL) {
                dcp_log(LOG_ERROR,"Could allocate certificate from memory");
                return DCP_FATAL;
            }
            x[i] = PEM_read_bio_X509(bio[i], NULL, NULL, NULL);
            BIO_set_close(bio[i], BIO_NOCLOSE);

            if (x[i] == NULL) {
                dcp_log(LOG_ERROR,"Could not read certificate");
                return DCP_FATAL;
            }
        }
    }

    /* get issuer, subject */
    for (i=0; i<3; i++) {
        issuer_xn[i]  =  X509_get_issuer_name(x[i]);
        subject_xn[i] =  X509_get_subject_name(x[i]);
        if (issuer_xn[i] == NULL || subject_xn[i] == NULL) {
            dcp_log(LOG_ERROR,"Could not parse certificate data");
            return DCP_FATAL;
        }
    }

    dcp_log(LOG_DEBUG, "xml_sign: write_dsig_template: start signer");

    /* signer */
    xmlTextWriterStartElement(xml, BAD_CAST "Signer");
    xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "X509Data", NULL);

    xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "X509IssuerSerial", NULL);

    xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig",
                                      BAD_CAST "X509IssuerName", NULL, "%s",
                                      dn_oneline(issuer_xn[0]));

    xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig",
                                      BAD_CAST "X509SerialNumber", NULL, "%ld",
                                      ASN1_INTEGER_get(X509_get_serialNumber(x[0])));
    xmlTextWriterEndElement(xml);

    xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig",
                                      BAD_CAST "X509SubjectName", NULL,
                                      "%s", dn_oneline(subject_xn[0]));

    xmlTextWriterEndElement(xml);
    xmlTextWriterEndElement(xml);

    /* template */
    xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "Signature", NULL);

    xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "SignedInfo", NULL);

    xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "CanonicalizationMethod", NULL);

    xmlTextWriterWriteAttribute(xml, BAD_CAST "Algorithm",
                                BAD_CAST DS_CMA);

    xmlTextWriterEndElement(xml);

    xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "SignatureMethod", NULL);

    xmlTextWriterWriteAttribute(xml, BAD_CAST "Algorithm",
                                BAD_CAST DS_SMA[opendcp->ns]);

    xmlTextWriterEndElement(xml);

    xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "Reference",
                                NULL);

    xmlTextWriterWriteAttribute(xml, BAD_CAST "URI", BAD_CAST NULL);

    xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST"Transforms",
                                NULL);

    xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "Transform",
                                NULL);

    xmlTextWriterWriteAttribute(xml, BAD_CAST "Algorithm",
                                BAD_CAST DS_TMA);

    xmlTextWriterEndElement(xml);
    xmlTextWriterEndElement(xml);

    xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "DigestMethod", NULL);

    xmlTextWriterWriteAttribute(xml, BAD_CAST "Algorithm",
                                BAD_CAST DS_DMA);

    xmlTextWriterEndElement(xml);

    xmlTextWriterWriteElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "DigestValue",
                                NULL, BAD_CAST "");

    xmlTextWriterEndElement(xml);
    xmlTextWriterEndElement(xml);

    xmlTextWriterWriteElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "SignatureValue",
                                NULL, BAD_CAST "");

    xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                BAD_CAST "KeyInfo", NULL);

    for (i=0; i<3; i++) {
        xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                    BAD_CAST "X509Data", NULL);
        xmlTextWriterStartElementNS(xml, BAD_CAST "dsig",
                                    BAD_CAST "X509IssuerSerial", NULL);

        xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig",
                                          BAD_CAST "X509IssuerName", NULL, "%s",
                                          dn_oneline(issuer_xn[i]));

        xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig",
                                          BAD_CAST "X509SerialNumber", NULL, "%ld",
                                          ASN1_INTEGER_get(X509_get_serialNumber(x[i])));
        xmlTextWriterEndElement(xml);

        xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig",
                                          BAD_CAST "X509Certificate", NULL, "%s",
                                          cert[i]);

        xmlTextWriterEndElement(xml);
    }

    xmlTextWriterEndElement(xml); /* KeyInfo */
    xmlTextWriterEndElement(xml); /* Signature */

    if (subject_xn[0]) {
        free(subject_xn[0]);
    }

    for (i=0; i<3; i++) {
        if (issuer_xn[i]) {
            free(issuer_xn[i]);
        }
    }

    return DCP_SUCCESS;
}
Esempio n. 3
0
File: 2cca.c Progetto: randunel/2cca
/*
 * Revoke one certificate at a time
 * No check performed to see if certificate already revoked.
 */
void revoke_cert(char * ca_name, char * name)
{
    char filename[FIELD_SZ+5];
    FILE * f ;
    X509_CRL * crl ;
    X509 * cert ;
    ASN1_INTEGER * r_serial ;
    ASN1_INTEGER * crlnum ;
    X509_REVOKED * rev ;
    ASN1_TIME * tm ;
    identity ca ;
    BIO * out ;
    BIGNUM * b_crlnum ;

    /* Find requested certificate by name */
    sprintf(filename, "%s.crt", name);
    if ((f=fopen(filename, "r"))==NULL) {
        fprintf(stderr, "Cannot find: %s\n", filename);
        return ; 
    }
    cert = PEM_read_X509(f, NULL, NULL, NULL);
    fclose(f);
    /* Get certificate serial number */
    r_serial = X509_get_serialNumber(cert);

    /* Find out if if was already revoked */

    /* Make a revoked object with that serial */
    rev = X509_REVOKED_new();
    X509_REVOKED_set_serialNumber(rev, r_serial);
    X509_free(cert);
    /* Set reason to unspecified */
    rev->reason = ASN1_ENUMERATED_get(CRL_REASON_UNSPECIFIED);

    /* Load or create new CRL */
    if ((crl = load_crl(ca_name))==NULL) {
        crl = X509_CRL_new();
        X509_CRL_set_version(crl, 1);
        /* Set CRL number */
        crlnum = ASN1_INTEGER_new();
        ASN1_INTEGER_set(crlnum, 1);
        X509_CRL_add1_ext_i2d(crl, NID_crl_number, crlnum, 0, 0);
        ASN1_INTEGER_free(crlnum);
    } else {
        crlnum = X509_CRL_get_ext_d2i(crl, NID_crl_number, 0, 0);
        b_crlnum = ASN1_INTEGER_to_BN(crlnum, NULL);
        BN_add_word(b_crlnum, 1);
        BN_to_ASN1_INTEGER(b_crlnum, crlnum);
        BN_free(b_crlnum);
        X509_CRL_add1_ext_i2d(crl, NID_crl_number, crlnum, 0, X509V3_ADD_REPLACE_EXISTING);
        ASN1_INTEGER_free(crlnum);
    }

    /* What time is it? */
    tm = ASN1_TIME_new();
    X509_gmtime_adj(tm, 0);
    X509_REVOKED_set_revocationDate(rev, tm);
    X509_CRL_set_lastUpdate(crl, tm);

    /* Set CRL next update to a year from now */
    X509_gmtime_adj(tm, 365*24*60*60);
    X509_CRL_set_nextUpdate(crl, tm);
    ASN1_TIME_free(tm);

    /* Add revoked to CRL */
    X509_CRL_add0_revoked(crl, rev);    
    X509_CRL_sort(crl);

    /* Load root key to sign CRL */
    if (load_ca(ca_name, &ca)!=0) {
        fprintf(stderr, "Cannot find CA key/crt\n");
        return ;
    }
    X509_CRL_set_issuer_name(crl, X509_get_subject_name(ca.cert));
    X509_free(ca.cert);

    /* Sign CRL */
    X509_CRL_sign(crl, ca.key, EVP_sha256());
    EVP_PKEY_free(ca.key);

    /* Dump CRL */
    sprintf(filename, "%s.crl", ca_name);
    if ((f = fopen(filename, "wb"))==NULL) {
        fprintf(stderr, "Cannot write %s: aborting\n", filename);
        X509_CRL_free(crl);
        return ;
    }
    out = BIO_new(BIO_s_file());
    BIO_set_fp(out, f, BIO_NOCLOSE);
    PEM_write_bio_X509_CRL(out, crl);
    BIO_free_all(out);
    fclose(f);
    X509_CRL_free(crl);
    return ;
}
Esempio n. 4
0
static gboolean
ssl_verify_certificate (LmSSL *ssl, const gchar *server)
{
    gboolean retval = TRUE;
    LmSSLBase *base;
    long verify_res;
    unsigned int digest_len;
    X509 *srv_crt;
    gchar *cn;
    X509_NAME *crt_subj;

    base = LM_SSL_BASE(ssl);

    g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
           "%s: Cipher: %s/%s/%i\n",
           __FILE__,
           SSL_get_cipher_version(ssl->ssl),
           SSL_get_cipher_name(ssl->ssl),
           SSL_get_cipher_bits(ssl->ssl, NULL));

    verify_res = SSL_get_verify_result(ssl->ssl);
    srv_crt = SSL_get_peer_certificate(ssl->ssl);
    if (base->expected_fingerprint != NULL) {
        X509_digest(srv_crt, EVP_md5(), (guchar *) base->fingerprint,
                    &digest_len);
        if (memcmp(base->expected_fingerprint, base->fingerprint,
                   digest_len) != 0) {
            if (base->func(ssl,
                           LM_SSL_STATUS_CERT_FINGERPRINT_MISMATCH,
                           base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
                return FALSE;
            }
        }
    }
    g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
           "%s: SSL_get_verify_result() = %ld\n",
           __FILE__,
           verify_res);
    switch (verify_res) {
    case X509_V_OK:
        break;
    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
        /* special case for self signed certificates? */
    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
    case X509_V_ERR_UNABLE_TO_GET_CRL:
    case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
        if (base->func(ssl,
                       LM_SSL_STATUS_NO_CERT_FOUND,
                       base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
            retval = FALSE;
        }
        break;
    case X509_V_ERR_INVALID_CA:
    case X509_V_ERR_CERT_UNTRUSTED:
    case X509_V_ERR_CERT_REVOKED:
        if (base->func(ssl,
                       LM_SSL_STATUS_UNTRUSTED_CERT,
                       base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
            retval = FALSE;
        }
        break;
    case X509_V_ERR_CERT_NOT_YET_VALID:
    case X509_V_ERR_CRL_NOT_YET_VALID:
        if (base->func(ssl,
                       LM_SSL_STATUS_CERT_NOT_ACTIVATED,
                       base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
            retval = FALSE;
        }
        break;
    case X509_V_ERR_CERT_HAS_EXPIRED:
    case X509_V_ERR_CRL_HAS_EXPIRED:
        if (base->func(ssl,
                       LM_SSL_STATUS_CERT_EXPIRED,
                       base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
            retval = FALSE;
        }
        break;
    default:
        if (base->func(ssl, LM_SSL_STATUS_GENERIC_ERROR,
                       base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
            retval = FALSE;
        }
    }
    /*if (retval == FALSE) {
      g_set_error (error, LM_ERROR, LM_ERROR_CONNECTION_OPEN,
      ssl_get_x509_err(verify_res), NULL);
      }*/
    crt_subj = X509_get_subject_name(srv_crt);
    cn = (gchar *) g_malloc0(LM_SSL_CN_MAX + 1);

    if (X509_NAME_get_text_by_NID(crt_subj, NID_commonName, cn, LM_SSL_CN_MAX) > 0) {
        gchar *domain = cn;

        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
               "%s: server = '%s', cn = '%s'\n",
               __FILE__, server, cn);

        if ((cn[0] == '*') && (cn[1] == '.')) {
            domain = strstr (cn, server);
        }

        if ((domain == NULL) || (strncasecmp (server, domain, LM_SSL_CN_MAX) != 0)) {
            if (base->func (ssl,
                            LM_SSL_STATUS_CERT_HOSTNAME_MISMATCH,
                            base->func_data) != LM_SSL_RESPONSE_CONTINUE) {
                retval = FALSE;
            }
        }
    } else {
        g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
               "X509_NAME_get_text_by_NID() failed");
    }

    g_log (LM_LOG_DOMAIN, LM_LOG_LEVEL_SSL,
           "%s:\n\tIssuer: %s\n\tSubject: %s\n\tFor: %s\n",
           __FILE__,
           X509_NAME_oneline(X509_get_issuer_name(srv_crt), NULL, 0),
           X509_NAME_oneline(X509_get_subject_name(srv_crt), NULL, 0),
           cn);

    g_free(cn);

    return retval;
}
Esempio n. 5
0
static int ssl_do(struct st_VioSSLFd *ptr, Vio *vio, long timeout,
                  int (*connect_accept_func)(SSL*), unsigned long *errptr)
{
  int r;
  SSL *ssl;
  my_bool unused;
  my_bool was_blocking;

  DBUG_ENTER("ssl_do");
  DBUG_PRINT("enter", ("ptr: 0x%lx, sd: %d  ctx: 0x%lx",
                       (long) ptr, vio->sd, (long) ptr->ssl_context));

  /* Set socket to blocking if not already set */
  vio_blocking(vio, 1, &was_blocking);

  if (!(ssl= SSL_new(ptr->ssl_context)))
  {
    DBUG_PRINT("error", ("SSL_new failure"));
    *errptr= ERR_get_error();
    vio_blocking(vio, was_blocking, &unused);
    DBUG_RETURN(1);
  }
  DBUG_PRINT("info", ("ssl: 0x%lx timeout: %ld", (long) ssl, timeout));
  SSL_clear(ssl);
  SSL_SESSION_set_timeout(SSL_get_session(ssl), timeout);
  SSL_set_fd(ssl, vio->sd);
#if !defined(HAVE_YASSL) && defined(SSL_OP_NO_COMPRESSION)
  SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
#endif

  if ((r= connect_accept_func(ssl)) < 1)
  {
    DBUG_PRINT("error", ("SSL_connect/accept failure"));
    *errptr= SSL_get_error(ssl, r);
    SSL_free(ssl);
    vio_blocking(vio, was_blocking, &unused);
    DBUG_RETURN(1);
  }

  /*
    Connection succeeded. Install new function handlers,
    change type, set sd to the fd used when connecting
    and set pointer to the SSL structure
  */
  vio_reset(vio, VIO_TYPE_SSL, SSL_get_fd(ssl), 0, 0);
  vio->ssl_arg= (void*)ssl;

#ifndef DBUG_OFF
  {
    /* Print some info about the peer */
    X509 *cert;
    char buf[512];

    DBUG_PRINT("info",("SSL connection succeeded"));
    DBUG_PRINT("info",("Using cipher: '%s'" , SSL_get_cipher_name(ssl)));

    if ((cert= SSL_get_peer_certificate (ssl)))
    {
      DBUG_PRINT("info",("Peer certificate:"));
      X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
      DBUG_PRINT("info",("\t subject: '%s'", buf));
      X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
      DBUG_PRINT("info",("\t issuer: '%s'", buf));
      X509_free(cert);
    }
    else
      DBUG_PRINT("info",("Peer does not have certificate."));

    if (SSL_get_shared_ciphers(ssl, buf, sizeof(buf)))
    {
      DBUG_PRINT("info",("shared_ciphers: '%s'", buf));
    }
    else
      DBUG_PRINT("info",("no shared ciphers!"));
  }
#endif

  DBUG_RETURN(0);
}
Esempio n. 6
0
CK_RV
gpkcs11_add_certificate(char *label,
			X509 *cert,
			char *id,
			int anchor)
{
    struct gpkcs11_st_object *o = NULL;
    void *cert_data = NULL;
    size_t cert_length;
    void *subject_data = NULL;
    size_t subject_length;
    void *issuer_data = NULL;
    size_t issuer_length;
    void *serial_data = NULL;
    size_t serial_length;
    EVP_PKEY *public_key;
    unsigned char sha1[SHA_DIGEST_LENGTH];
    CK_TRUST trust_ca = CKT_NSS_TRUSTED_DELEGATOR;
    int ret;
    CK_BBOOL bool_true = CK_TRUE;
    CK_BBOOL bool_false = CK_FALSE;
    CK_OBJECT_CLASS c;
    CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
    CK_KEY_TYPE key_type;
    CK_MECHANISM_TYPE mech_type;
    size_t id_len = strlen(id);

    OPENSSL_ASN1_MALLOC_ENCODE(X509, cert_data, cert_length, cert, ret);
    if (ret)
	goto out;

    OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, issuer_data, issuer_length, 
			       X509_get_issuer_name(cert), ret);
    if (ret)
	goto out;

    OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, subject_data, subject_length, 
			       X509_get_subject_name(cert), ret);
    if (ret)
	goto out;

    OPENSSL_ASN1_MALLOC_ENCODE(ASN1_INTEGER, serial_data, serial_length, 
			       X509_get_serialNumber(cert), ret);
    if (ret)
	goto out;

    gpkcs11_log("done parsing, adding to internal structure\n");

    o = add_st_object();
    if (o == NULL) {
	ret = CKR_DEVICE_MEMORY;
	goto out;
    }
    o->type = STO_T_CERTIFICATE;
    o->u.cert = cert;
    public_key = X509_get_pubkey(o->u.cert);

    switch (EVP_PKEY_type(public_key->type)) {
    case EVP_PKEY_RSA:
	key_type = CKK_RSA;
	break;
    case EVP_PKEY_DSA:
	key_type = CKK_DSA;
	break;
    default:
	/* XXX */
	break;
    }

    c = CKO_CERTIFICATE;
    add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
    add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
    add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));

    add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type));
    add_object_attribute(o, 0, CKA_ID, id, id_len);

    add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);
    add_object_attribute(o, 0, CKA_ISSUER, issuer_data, issuer_length);
    add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data, serial_length);
    add_object_attribute(o, 0, CKA_VALUE, cert_data, cert_length);
    if (anchor)
	add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));
    else
	add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false));

    gpkcs11_log("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o));

    if (anchor) {
	o = add_st_object();
	if (o == NULL) {
	    ret = CKR_DEVICE_MEMORY;
	    goto out;
	}

	o->type = STO_T_NETSCAPE_TRUST;

	c = CKO_NETSCAPE_TRUST;
	add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
	add_object_attribute(o, 0, CKA_LABEL, "IGTF CA Trust", 13);
	add_object_attribute(o, 0, CKA_ID, id, id_len);
	add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_ISSUER, issuer_data, issuer_length);
	add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);
	add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data, serial_length);
	EVP_Digest(cert_data, cert_length, sha1, NULL, EVP_sha1(), NULL);
	add_object_attribute(o, 0, CKA_CERT_SHA1_HASH, sha1, sizeof(sha1));
	add_object_attribute(o, 0, CKA_TRUST_SERVER_AUTH, &trust_ca, sizeof(trust_ca));
	add_object_attribute(o, 0, CKA_TRUST_CLIENT_AUTH, &trust_ca, sizeof(trust_ca));
	add_object_attribute(o, 0, CKA_TRUST_CODE_SIGNING, &trust_ca, sizeof(trust_ca));
	add_object_attribute(o, 0, CKA_TRUST_EMAIL_PROTECTION, &trust_ca, sizeof(trust_ca));
	gpkcs11_log("add Netscape trust object: %lx\n", (unsigned long)OBJECT_ID(o));
    }

    o = add_st_object();
    if (o == NULL) {
	ret = CKR_DEVICE_MEMORY;
	goto out;
    }
    o->type = STO_T_PUBLIC_KEY;
    o->u.public_key = public_key;

    c = CKO_PUBLIC_KEY;
    add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
    add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
    add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));

    add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
    add_object_attribute(o, 0, CKA_ID, id, id_len);
    add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */
    add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */
    add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
    mech_type = CKM_RSA_X_509;
    add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));

    add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);
    add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true));
    add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true));
    add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false));
    add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true));
    add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true));

    add_pubkey_info(o, key_type, public_key);

    gpkcs11_log("add key ok: %lx\n", (unsigned long)OBJECT_ID(o));

    ret = CKR_OK;

out:
    free(cert_data);
    free(serial_data);
    free(issuer_data);
    free(subject_data);

    return ret;
}
Esempio n. 7
0
static void x509v3_cache_extensions(X509 *x)
{
    BASIC_CONSTRAINTS *bs;
    PROXY_CERT_INFO_EXTENSION *pci;
    ASN1_BIT_STRING *usage;
    ASN1_BIT_STRING *ns;
    EXTENDED_KEY_USAGE *extusage;
    X509_EXTENSION *ex;

    int i;
    if (x->ex_flags & EXFLAG_SET)
        return;
#ifndef OPENSSL_NO_SHA
    X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
#endif
    /* V1 should mean no extensions ... */
    if (!X509_get_version(x))
        x->ex_flags |= EXFLAG_V1;
    /* Handle basic constraints */
    if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) {
        if (bs->ca)
            x->ex_flags |= EXFLAG_CA;
        if (bs->pathlen) {
            if ((bs->pathlen->type == V_ASN1_NEG_INTEGER)
                || !bs->ca) {
                x->ex_flags |= EXFLAG_INVALID;
                x->ex_pathlen = 0;
            } else
                x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
        } else
            x->ex_pathlen = -1;
        BASIC_CONSTRAINTS_free(bs);
        x->ex_flags |= EXFLAG_BCONS;
    }
    /* Handle proxy certificates */
    if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
        if (x->ex_flags & EXFLAG_CA
            || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0
            || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
            x->ex_flags |= EXFLAG_INVALID;
        }
        if (pci->pcPathLengthConstraint) {
            x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint);
        } else
            x->ex_pcpathlen = -1;
        PROXY_CERT_INFO_EXTENSION_free(pci);
        x->ex_flags |= EXFLAG_PROXY;
    }
    /* Handle key usage */
    if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
        if (usage->length > 0) {
            x->ex_kusage = usage->data[0];
            if (usage->length > 1)
                x->ex_kusage |= usage->data[1] << 8;
        } else
            x->ex_kusage = 0;
        x->ex_flags |= EXFLAG_KUSAGE;
        ASN1_BIT_STRING_free(usage);
    }
    x->ex_xkusage = 0;
    if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) {
        x->ex_flags |= EXFLAG_XKUSAGE;
        for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
            switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) {
            case NID_server_auth:
                x->ex_xkusage |= XKU_SSL_SERVER;
                break;

            case NID_client_auth:
                x->ex_xkusage |= XKU_SSL_CLIENT;
                break;

            case NID_email_protect:
                x->ex_xkusage |= XKU_SMIME;
                break;

            case NID_code_sign:
                x->ex_xkusage |= XKU_CODE_SIGN;
                break;

            case NID_ms_sgc:
            case NID_ns_sgc:
                x->ex_xkusage |= XKU_SGC;
                break;

            case NID_OCSP_sign:
                x->ex_xkusage |= XKU_OCSP_SIGN;
                break;

            case NID_time_stamp:
                x->ex_xkusage |= XKU_TIMESTAMP;
                break;

            case NID_dvcs:
                x->ex_xkusage |= XKU_DVCS;
                break;

            case NID_anyExtendedKeyUsage:
                x->ex_xkusage |= XKU_ANYEKU;
                break;
            }
        }
        sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
    }

    if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) {
        if (ns->length > 0)
            x->ex_nscert = ns->data[0];
        else
            x->ex_nscert = 0;
        x->ex_flags |= EXFLAG_NSCERT;
        ASN1_BIT_STRING_free(ns);
    }
    x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
    x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
    /* Does subject name match issuer ? */
    if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) {
        x->ex_flags |= EXFLAG_SI;
        /* If SKID matches AKID also indicate self signed */
        if (X509_check_akid(x, x->akid) == X509_V_OK)
            x->ex_flags |= EXFLAG_SS;
    }
    x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
    x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL);
    if (!x->nc && (i != -1))
        x->ex_flags |= EXFLAG_INVALID;
    setup_crldp(x);

#ifndef OPENSSL_NO_RFC3779
    x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL);
    x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum,
                                       NULL, NULL);
#endif
    for (i = 0; i < X509_get_ext_count(x); i++) {
        ex = X509_get_ext(x, i);
        if (OBJ_obj2nid(X509_EXTENSION_get_object(ex))
            == NID_freshest_crl)
            x->ex_flags |= EXFLAG_FRESHEST;
        if (!X509_EXTENSION_get_critical(ex))
            continue;
        if (!X509_supported_extension(ex)) {
            x->ex_flags |= EXFLAG_CRITICAL;
            break;
        }
    }
    x->ex_flags |= EXFLAG_SET;
}
Esempio n. 8
0
/*
 *	Attempt to negotiate SSL connection.
 */
static int
open_server_SSL(Port *port)
{
	int			r;
	int			err;

	Assert(!port->ssl);
	Assert(!port->peer);

	if (!(port->ssl = SSL_new(SSL_context)))
	{
		ereport(COMMERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
				 errmsg("could not initialize SSL connection: %s",
						SSLerrmessage())));
		close_SSL(port);
		return -1;
	}
	if (!my_SSL_set_fd(port->ssl, port->sock))
	{
		ereport(COMMERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
				 errmsg("could not set SSL socket: %s",
						SSLerrmessage())));
		close_SSL(port);
		return -1;
	}

aloop:
	r = SSL_accept(port->ssl);
	if (r <= 0)
	{
		err = SSL_get_error(port->ssl, r);
		switch (err)
		{
			case SSL_ERROR_WANT_READ:
			case SSL_ERROR_WANT_WRITE:
#ifdef WIN32
				pgwin32_waitforsinglesocket(SSL_get_fd(port->ssl),
											(err == SSL_ERROR_WANT_READ) ?
						FD_READ | FD_CLOSE | FD_ACCEPT : FD_WRITE | FD_CLOSE,
											INFINITE);
#endif
				goto aloop;
			case SSL_ERROR_SYSCALL:
				if (r < 0)
					ereport(COMMERROR,
							(errcode_for_socket_access(),
							 errmsg("could not accept SSL connection: %m")));
				else
					ereport(COMMERROR,
							(errcode(ERRCODE_PROTOCOL_VIOLATION),
					errmsg("could not accept SSL connection: EOF detected")));
				break;
			case SSL_ERROR_SSL:
				ereport(COMMERROR,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
						 errmsg("could not accept SSL connection: %s",
								SSLerrmessage())));
				break;
			case SSL_ERROR_ZERO_RETURN:
				ereport(COMMERROR,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
				   errmsg("could not accept SSL connection: EOF detected")));
				break;
			default:
				ereport(COMMERROR,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
						 errmsg("unrecognized SSL error code: %d",
								err)));
				break;
		}
		close_SSL(port);
		return -1;
	}

	port->count = 0;

	/* Get client certificate, if available. */
	port->peer = SSL_get_peer_certificate(port->ssl);

	/* and extract the Common Name from it. */
	port->peer_cn = NULL;
	if (port->peer != NULL)
	{
		int			len;

		len = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer),
										NID_commonName, NULL, 0);
		if (len != -1)
		{
			char	   *peer_cn;

			peer_cn = MemoryContextAlloc(TopMemoryContext, len + 1);
			r = X509_NAME_get_text_by_NID(X509_get_subject_name(port->peer),
										  NID_commonName, peer_cn, len + 1);
			peer_cn[len] = '\0';
			if (r != len)
			{
				/* shouldn't happen */
				pfree(peer_cn);
				close_SSL(port);
				return -1;
			}

			/*
			 * Reject embedded NULLs in certificate common name to prevent
			 * attacks like CVE-2009-4034.
			 */
			if (len != strlen(peer_cn))
			{
				ereport(COMMERROR,
						(errcode(ERRCODE_PROTOCOL_VIOLATION),
						 errmsg("SSL certificate's common name contains embedded null")));
				pfree(peer_cn);
				close_SSL(port);
				return -1;
			}

			port->peer_cn = peer_cn;
		}
	}

	ereport(DEBUG2,
			(errmsg("SSL connection from \"%s\"",
					port->peer_cn ? port->peer_cn : "(anonymous)")));

	/* set up debugging/info callback */
	SSL_CTX_set_info_callback(SSL_context, info_cb);

	return 0;
}
Esempio n. 9
0
/* based on BSD-style licensed code of mod_ssl */
static int crl_check(CLI *c, X509_STORE_CTX *callback_ctx) {
    X509_STORE_CTX store_ctx;
    X509_OBJECT obj;
    X509_NAME *subject;
    X509_NAME *issuer;
    X509 *cert;
    X509_CRL *crl;
    X509_REVOKED *revoked;
    EVP_PKEY *pubkey;
    long serial;
    int i, n, rc;
    char *cp;
    ASN1_TIME *last_update=NULL, *next_update=NULL;

    /* determine certificate ingredients in advance */
    cert=X509_STORE_CTX_get_current_cert(callback_ctx);
    subject=X509_get_subject_name(cert);
    issuer=X509_get_issuer_name(cert);

    /* try to retrieve a CRL corresponding to the _subject_ of
     * the current certificate in order to verify it's integrity */
    memset((char *)&obj, 0, sizeof obj);
    X509_STORE_CTX_init(&store_ctx, c->opt->revocation_store, NULL, NULL);
    rc=X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, subject, &obj);
    X509_STORE_CTX_cleanup(&store_ctx);
    crl=obj.data.crl;
    if(rc>0 && crl) {
        cp=X509_NAME_oneline(subject, NULL, 0);
        s_log(LOG_INFO, "CRL: issuer: %s", cp);
        OPENSSL_free(cp);
        last_update=X509_CRL_get_lastUpdate(crl);
        next_update=X509_CRL_get_nextUpdate(crl);
        log_time(LOG_INFO, "CRL: last update", last_update);
        log_time(LOG_INFO, "CRL: next update", next_update);

        /* verify the signature on this CRL */
        pubkey=X509_get_pubkey(cert);
        if(X509_CRL_verify(crl, pubkey)<=0) {
            s_log(LOG_WARNING, "CRL: Invalid signature");
            X509_STORE_CTX_set_error(callback_ctx,
                X509_V_ERR_CRL_SIGNATURE_FAILURE);
            X509_OBJECT_free_contents(&obj);
            if(pubkey)
                EVP_PKEY_free(pubkey);
            return 0; /* reject connection */
        }
        if(pubkey)
            EVP_PKEY_free(pubkey);

        /* check date of CRL to make sure it's not expired */
        if(!next_update) {
            s_log(LOG_WARNING, "CRL: Invalid nextUpdate field");
            X509_STORE_CTX_set_error(callback_ctx,
                X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD);
            X509_OBJECT_free_contents(&obj);
            return 0; /* reject connection */
        }
        if(X509_cmp_current_time(next_update)<0) {
            s_log(LOG_WARNING, "CRL: CRL Expired - revoking all certificates");
            X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CRL_HAS_EXPIRED);
            X509_OBJECT_free_contents(&obj);
            return 0; /* reject connection */
        }
        X509_OBJECT_free_contents(&obj);
    }

    /* try to retrieve a CRL corresponding to the _issuer_ of
     * the current certificate in order to check for revocation */
    memset((char *)&obj, 0, sizeof obj);
    X509_STORE_CTX_init(&store_ctx, c->opt->revocation_store, NULL, NULL);
    rc=X509_STORE_get_by_subject(&store_ctx, X509_LU_CRL, issuer, &obj);
    X509_STORE_CTX_cleanup(&store_ctx);
    crl=obj.data.crl;
    if(rc>0 && crl) {
        /* check if the current certificate is revoked by this CRL */
        n=sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
        for(i=0; i<n; i++) {
            revoked=sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
            if(ASN1_INTEGER_cmp(revoked->serialNumber,
                    X509_get_serialNumber(cert)) == 0) {
                serial=ASN1_INTEGER_get(revoked->serialNumber);
                cp=X509_NAME_oneline(issuer, NULL, 0);
                s_log(LOG_WARNING, "CRL: Certificate with serial %ld (0x%lX) "
                    "revoked per CRL from issuer %s", serial, serial, cp);
                OPENSSL_free(cp);
                X509_STORE_CTX_set_error(callback_ctx, X509_V_ERR_CERT_REVOKED);
                X509_OBJECT_free_contents(&obj);
                return 0; /* reject connection */
            }
        }
        X509_OBJECT_free_contents(&obj);
    }
    return 1; /* accept connection */
}
Esempio n. 10
0
bool
ssl_check_certificate (int fd, const char *host)
{
  X509 *cert;
  GENERAL_NAMES *subjectAltNames;
  char common_name[256];
  long vresult;
  bool success = true;
  bool alt_name_checked = false;

  /* If the user has specified --no-check-cert, we still want to warn
     him about problems with the server's certificate.  */
  const char *severity = opt.check_cert ? _("ERROR") : _("WARNING");

  struct openssl_transport_context *ctx = fd_transport_context (fd);
  SSL *conn = ctx->conn;
  assert (conn != NULL);

  cert = SSL_get_peer_certificate (conn);
  if (!cert)
    {
      logprintf (LOG_NOTQUIET, _("%s: No certificate presented by %s.\n"),
                 severity, quotearg_style (escape_quoting_style, host));
      success = false;
      goto no_cert;             /* must bail out since CERT is NULL */
    }

  IF_DEBUG
    {
      char *subject = X509_NAME_oneline (X509_get_subject_name (cert), 0, 0);
      char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0);
      DEBUGP (("certificate:\n  subject: %s\n  issuer:  %s\n",
               quotearg_n_style (0, escape_quoting_style, subject),
               quotearg_n_style (1, escape_quoting_style, issuer)));
      OPENSSL_free (subject);
      OPENSSL_free (issuer);
    }

  vresult = SSL_get_verify_result (conn);
  if (vresult != X509_V_OK)
    {
      char *issuer = X509_NAME_oneline (X509_get_issuer_name (cert), 0, 0);
      logprintf (LOG_NOTQUIET,
                 _("%s: cannot verify %s's certificate, issued by %s:\n"),
                 severity, quotearg_n_style (0, escape_quoting_style, host),
                 quote_n (1, issuer));
      /* Try to print more user-friendly (and translated) messages for
         the frequent verification errors.  */
      switch (vresult)
        {
        case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
          logprintf (LOG_NOTQUIET,
                     _("  Unable to locally verify the issuer's authority.\n"));
          break;
        case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
        case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
          logprintf (LOG_NOTQUIET,
                     _("  Self-signed certificate encountered.\n"));
          break;
        case X509_V_ERR_CERT_NOT_YET_VALID:
          logprintf (LOG_NOTQUIET, _("  Issued certificate not yet valid.\n"));
          break;
        case X509_V_ERR_CERT_HAS_EXPIRED:
          logprintf (LOG_NOTQUIET, _("  Issued certificate has expired.\n"));
          break;
        default:
          /* For the less frequent error strings, simply provide the
             OpenSSL error message.  */
          logprintf (LOG_NOTQUIET, "  %s\n",
                     X509_verify_cert_error_string (vresult));
        }
      success = false;
      /* Fall through, so that the user is warned about *all* issues
         with the cert (important with --no-check-certificate.)  */
    }

  /* Check that HOST matches the common name in the certificate.
     #### The following remains to be done:

     - When matching against common names, it should loop over all
       common names and choose the most specific one, i.e. the last
       one, not the first one, which the current code picks.

     - Ensure that ASN1 strings from the certificate are encoded as
       UTF-8 which can be meaningfully compared to HOST.  */

  subjectAltNames = X509_get_ext_d2i (cert, NID_subject_alt_name, NULL, NULL);

  if (subjectAltNames)
    {
      /* Test subject alternative names */

      /* Do we want to check for dNSNAmes or ipAddresses (see RFC 2818)?
       * Signal it by host_in_octet_string. */
      ASN1_OCTET_STRING *host_in_octet_string = a2i_IPADDRESS (host);

      int numaltnames = sk_GENERAL_NAME_num (subjectAltNames);
      int i;
      for (i=0; i < numaltnames; i++)
        {
          const GENERAL_NAME *name =
            sk_GENERAL_NAME_value (subjectAltNames, i);
          if (name)
            {
              if (host_in_octet_string)
                {
                  if (name->type == GEN_IPADD)
                    {
                      /* Check for ipAddress */
                      /* TODO: Should we convert between IPv4-mapped IPv6
                       * addresses and IPv4 addresses? */
                      alt_name_checked = true;
                      if (!ASN1_STRING_cmp (host_in_octet_string,
                            name->d.iPAddress))
                        break;
                    }
                }
              else if (name->type == GEN_DNS)
                {
                  /* dNSName should be IA5String (i.e. ASCII), however who
                   * does trust CA? Convert it into UTF-8 for sure. */
                  unsigned char *name_in_utf8 = NULL;

                  /* Check for dNSName */
                  alt_name_checked = true;

                  if (0 <= ASN1_STRING_to_UTF8 (&name_in_utf8, name->d.dNSName))
                    {
                      /* Compare and check for NULL attack in ASN1_STRING */
                      if (pattern_match ((char *)name_in_utf8, host) &&
                            (strlen ((char *)name_in_utf8) ==
                                (size_t) ASN1_STRING_length (name->d.dNSName)))
                        {
                          OPENSSL_free (name_in_utf8);
                          break;
                        }
                      OPENSSL_free (name_in_utf8);
                    }
                }
            }
        }
      sk_GENERAL_NAME_free (subjectAltNames);
      if (host_in_octet_string)
        ASN1_OCTET_STRING_free(host_in_octet_string);

      if (alt_name_checked == true && i >= numaltnames)
        {
          logprintf (LOG_NOTQUIET,
              _("%s: no certificate subject alternative name matches\n"
                "\trequested host name %s.\n"),
                     severity, quote_n (1, host));
          success = false;
        }
    }

  if (alt_name_checked == false)
    {
      /* Test commomName */
      X509_NAME *xname = X509_get_subject_name(cert);
      common_name[0] = '\0';
      X509_NAME_get_text_by_NID (xname, NID_commonName, common_name,
                                 sizeof (common_name));

      if (!pattern_match (common_name, host))
        {
          logprintf (LOG_NOTQUIET, _("\
    %s: certificate common name %s doesn't match requested host name %s.\n"),
                     severity, quote_n (0, common_name), quote_n (1, host));
          success = false;
        }
static int init_ssl_connection(SSL *con)
{
	int i;
#ifdef DEBUG
	const char *str;
	X509 *peer;
	static char buf[BUFSIZ];
#endif
	long verify_error;
	int err = 0;

	if ((i = SSL_accept(con)) <= 0)
	{
		err = SSL_get_error (con, i);
		if ((SSL_ERROR_WANT_READ == err) || (SSL_ERROR_WANT_WRITE == err))
			fprintf (stderr, "%s: %s(): Error [SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE]\n", \
				__FILE__, __func__);

		if (BIO_sock_should_retry (i))
		{
			BIO_printf(bio_s_out, "DELAY\n");
			return 1;
		}

		
		BIO_printf(bio_err, "ERROR\n");
		verify_error = SSL_get_verify_result (con);
		if (verify_error != X509_V_OK)
		{
			BIO_printf(bio_err,"verify error:%s\n",
				X509_verify_cert_error_string(verify_error));
		}
		else
		{
			fprintf (stderr, "%s: %s(): X509_V_OK but error\n", __FILE__, __func__);
			ERR_print_errors (bio_err);
		}
		return 0;
	}

#ifdef DEBUG
	PEM_write_bio_SSL_SESSION (bio_s_out, SSL_get_session (con));

	peer = SSL_get_peer_certificate (con);
	if (NULL != peer)
	{
		BIO_printf (bio_s_out, "Client certificate\n");
		PEM_write_bio_X509 (bio_s_out, peer);
		X509_NAME_oneline (X509_get_subject_name (peer), buf, sizeof buf);
		BIO_printf (bio_s_out, "subject = %s\n", buf);
		X509_NAME_oneline (X509_get_issuer_name (peer), buf, sizeof buf);
		BIO_printf (bio_s_out, "issuer = %s\n", buf);
		X509_free(peer);
	}

	if (SSL_get_shared_ciphers (con, buf, sizeof buf) != NULL)
		BIO_printf (bio_s_out, "Shared ciphers: %s\n", buf);
	str = SSL_CIPHER_get_name (SSL_get_current_cipher (con));
	BIO_printf (bio_s_out, "CIPHER is %s\n", (str != NULL) ? str : "(NONE)");
#endif
	if (con->hit) BIO_printf (bio_s_out, "Reused session-id\n");
	if (SSL_ctrl (con, SSL_CTRL_GET_FLAGS, 0, NULL) & TLS1_FLAGS_TLS_PADDING_BUG)
		BIO_printf (bio_s_out, "Peer has incorrect TLSv1 block padding\n");

	return 1;
}
Esempio n. 12
0
gboolean
z_proxy_ssl_host_iface_check_name_method(ZProxyHostIface *s,
                                         const gchar *host_name,
                                         gchar *reason_buf, gsize reason_len)
{
  ZProxySslHostIface *self = Z_CAST(s, ZProxySslHostIface);
  gint ext_ndx;
  gboolean found = FALSE, result = FALSE;
  gchar pattern_buf[256];

  if (self->hostname_checked)
    return self->hostname_check_result;

  pattern_buf[0] = 0;
  ext_ndx = X509_get_ext_by_NID(self->server_cert, NID_subject_alt_name, -1);
  if (ext_ndx >= 0)
    {
      /* ok, there's a subjectAltName extension, check that */
      X509_EXTENSION *ext;
      STACK_OF(GENERAL_NAME) *alt_names;
      GENERAL_NAME *gen_name;

      ext = X509_get_ext(self->server_cert, ext_ndx);
      alt_names = X509V3_EXT_d2i(ext);
      if (alt_names)
        {
          gint num, i;

          num = sk_GENERAL_NAME_num(alt_names);

          for (i = 0; i < num; i++)
            {
              gen_name = sk_GENERAL_NAME_value(alt_names, i);
              if (gen_name->type == GEN_DNS)
                {
                  guchar *dnsname = ASN1_STRING_data(gen_name->d.dNSName);
                  guint dnsname_len = ASN1_STRING_length(gen_name->d.dNSName);

                  if (dnsname_len > sizeof(pattern_buf) - 1)
                    {
                      found = TRUE;
                      result = FALSE;
                      break;
                    }

                  memcpy(pattern_buf, dnsname, dnsname_len);
                  pattern_buf[dnsname_len] = 0;
                  /* we have found a DNS name as alternative subject name */
                  found = TRUE;
                  result = z_proxy_ssl_host_iface_check_wildcard(s->owner, host_name, pattern_buf);
                  break;
                }
              else if (gen_name->type == GEN_IPADD)
                {
                  z_inet_ntoa(pattern_buf, sizeof(pattern_buf), *(struct in_addr *) gen_name->d.iPAddress->data);

                  found = TRUE;
                  result = strcmp(host_name, pattern_buf) == 0;
                  break;
                }
            }
          sk_GENERAL_NAME_free(alt_names);
        }
    }

  if (!found)
    {
      /* hmm. there was no subjectAltName (this is deprecated, but still
       * widely used), look up the Subject, most specific CN */
      X509_NAME *name;

      name = X509_get_subject_name(self->server_cert);
      if (X509_NAME_get_text_by_NID(name, NID_commonName, pattern_buf, sizeof(pattern_buf)) != -1)
        {
          result = z_proxy_ssl_host_iface_check_wildcard(s->owner, host_name, pattern_buf);
        }
    }

  if (!result && reason_buf)
    {
      g_snprintf(reason_buf, reason_len, "Certificate does not belong to target host (certificate: %s, host %s)",
                 pattern_buf, host_name);
    }
  self->hostname_checked = TRUE;
  self->hostname_check_result = result;
  return result;

}
Esempio n. 13
0
static bool verifyHost(const std::string& host, const X509* cert)
{
    if (host.empty() || cert == nullptr)
    {
        return false;
    }

    bool matched                     = false;
    STACK_OF(GENERAL_NAME)* altnames = (stack_st_GENERAL_NAME*)X509_get_ext_d2i(
        (X509*)cert, NID_subject_alt_name, nullptr, nullptr);
    int             target = GEN_DNS; /// See x509v3.h in openssl project.
    struct in_addr  addr4;
    struct in6_addr addr6;
    uint8_t         ipver   = 4;
    size_t          addrlen = 0;
    bool            result  = true;

    if (inet_pton(AF_INET, host.c_str(), &addr4) == 1)
    {
        addrlen = sizeof(addr4);
        target  = GEN_IPADD; /// See x509v3.h in openssl project.
    }
    else if (inet_pton(AF_INET6, host.c_str(), &addr6) == 1)
    {
        addrlen = sizeof(addr6);
        target  = GEN_IPADD;
        ipver   = 6;
    }

    if (altnames)
    {
        int numalts;
        int i;
        /* get amount of alternatives, RFC2459 claims there MUST be at least
           one, but we don't depend on it... */
        numalts = sk_GENERAL_NAME_num(altnames);

        /* loop through all alternatives while none has matched */
        for (i = 0; (i < numalts) && !matched; i++)
        {
            /* get a handle to alternative name number i */
            const GENERAL_NAME* check = sk_GENERAL_NAME_value(altnames, i);

            /* only check alternatives of the same type the target is */
            if (check->type == target)
            {
                /* get data and length */
                const char* altptr = (char*)ASN1_STRING_data(check->d.ia5);
                size_t      altlen = (size_t)ASN1_STRING_length(check->d.ia5);

                switch (target)
                {
                    case GEN_DNS: /* name/pattern comparison */
                        if ((altlen == strlen(altptr)) &&
                            /* if this isn't true, there was an embedded zero in
                               the name
                                string and we cannot match it. */
                            certHostCheck(altptr, host.c_str()))
                        {
                            matched = true;
                        }
                        break;

                    case GEN_IPADD: /* IP address comparison */
                        /* compare alternative IP address if the data chunk is
                           the same size
                           our server IP address is */
                        if (altlen == addrlen)
                        {
                            if (ipver == 4 &&
                                memcmp(altptr, &addr4, altlen) == 0)
                            {
                                matched = true;
                            }
                            else if (ipver == 6 &&
                                     memcmp(altptr, &addr6, altlen) == 0)
                            {
                                matched = true;
                            }
                        }
                        break;

                    default:
                        break;
                }
            }
        }
        GENERAL_NAMES_free(altnames);
    }

    if (matched)
    {
        // Success.
    }
    else if (altnames)
    {
        result = false;
    }
    else
    {

        /* If here, we have to look to the last occurrence of a commonName
           in the distinguished one to get the most significant one. */

        /* Common name must be domain name. See:
           https://tools.ietf.org/html/rfc2818#section-3.1
        */
        if (target == GEN_IPADD)
        {
            return false;
        }

        int j, i = -1;

        /* The following is done because of a bug in 0.9.6b */

        std::string peerCNStr;

        X509_NAME* name = X509_get_subject_name((X509*)cert);
        if (name)
        {
            while ((j = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >=
                   0)
            {
                i = j;
            }
        }

        /* we have the name entry and we will now convert this to a string
           that we can use for comparison. Doing this we support BMPstring,
           UTF8 etc. */

        if (i >= 0)
        {
            ASN1_STRING* tmp =
                X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
            unsigned char* peer_CN = nullptr;

            if (tmp)
            {
                j = ASN1_STRING_to_UTF8(&peer_CN, tmp);

                int cnLen = (int)strlen((char*)peer_CN);
                if (peer_CN && cnLen != j)
                {
                    result = false;
                }
                else
                {
                    peerCNStr = std::string((const char*)peer_CN, cnLen);
                    OPENSSL_free(peer_CN);
                }
            }
        }

        if (!result)
            /* error already detected, pass through */
            ;
        else if (peerCNStr.empty())
        {
            result = false;
        }
        else if (!certHostCheck(peerCNStr, host))
        {
            result = false;
        }
    }

    return result;
}
Esempio n. 14
0
static EVP_PKEY *pkcs11_load_key(ENGINE_CTX *ctx, const char *s_slot_key_id,
		UI_METHOD *ui_method, void *callback_data, int isPrivate)
{
	PKCS11_SLOT *slot;
	PKCS11_SLOT *found_slot = NULL;
	PKCS11_TOKEN *tok, *match_tok = NULL;
	PKCS11_KEY *keys, *selected_key = NULL;
	PKCS11_CERT *certs;
	EVP_PKEY *pk;
	unsigned int cert_count, key_count, n, m;
	unsigned char key_id[MAX_VALUE_LEN / 2];
	size_t key_id_len = sizeof(key_id);
	char *key_label = NULL;
	int slot_nr = -1;
	char tmp_pin[MAX_PIN_LENGTH+1];
	size_t tmp_pin_len = MAX_PIN_LENGTH;
	char flags[64];
	int already_logged_in = 0;

	if (pkcs11_init_libp11(ctx)) /* Delayed libp11 initialization */
		return NULL;

	if (ctx->verbose)
		fprintf(stderr, "Loading %s key \"%s\"\n",
			(char *)(isPrivate ? "private" : "public"),
			s_slot_key_id);
	if (s_slot_key_id && *s_slot_key_id) {
		if (!strncmp(s_slot_key_id, "pkcs11:", 7)) {
			n = parse_pkcs11_uri(s_slot_key_id, &match_tok,
				key_id, &key_id_len,
				tmp_pin, &tmp_pin_len, &key_label);

			if (n && tmp_pin_len > 0 && tmp_pin[0] != 0) {
				destroy_pin(ctx);
				ctx->pin = OPENSSL_malloc(MAX_PIN_LENGTH+1);
				if (ctx->pin != NULL) {
					memset(ctx->pin, 0, MAX_PIN_LENGTH+1);
					memcpy(ctx->pin, tmp_pin, tmp_pin_len);
					ctx->pin_length = tmp_pin_len;
				}
			}

			if (!n) {
				fprintf(stderr,
					"The certificate ID is not a valid PKCS#11 URI\n"
					"The PKCS#11 URI format is defined by RFC7512\n");
				return NULL;
			}
		} else {
			n = parse_slot_id_string(s_slot_key_id, &slot_nr,
				key_id, &key_id_len, &key_label);

			if (!n) {
				fprintf(stderr,
					"The certificate ID is not a valid PKCS#11 URI\n"
					"The PKCS#11 URI format is defined by RFC7512\n"
					"The legacy ENGINE_pkcs11 ID format is also "
					"still accepted for now\n");
				return NULL;
			}
		}
		if (ctx->verbose) {
			fprintf(stderr, "Looking in slot %d for key: ",
				slot_nr);
			if (key_id_len != 0) {
				fprintf(stderr, "id=");
				dump_hex(stderr, key_id, key_id_len);
			}
			if (key_id_len != 0 && key_label != NULL)
				fprintf(stderr, " ");
			if (key_label != NULL)
				fprintf(stderr, "label=%s", key_label);
			fprintf(stderr, "\n");
		}
	}

	for (n = 0; n < ctx->slot_count; n++) {
		slot = ctx->slot_list + n;
		flags[0] = '\0';
		if (slot->token) {
			if (!slot->token->initialized)
				strcat(flags, "uninitialized, ");
			else if (!slot->token->userPinSet)
				strcat(flags, "no pin, ");
			if (slot->token->loginRequired)
				strcat(flags, "login, ");
			if (slot->token->readOnly)
				strcat(flags, "ro, ");
		} else {
			strcpy(flags, "no token");
		}
		if ((m = strlen(flags)) != 0) {
			flags[m - 2] = '\0';
		}

		if (slot_nr != -1 &&
			slot_nr == (int)PKCS11_get_slotid_from_slot(slot)) {
			found_slot = slot;
		}
		if (match_tok && slot->token &&
				(match_tok->label == NULL ||
					!strcmp(match_tok->label, slot->token->label)) &&
				(match_tok->manufacturer == NULL ||
					!strcmp(match_tok->manufacturer, slot->token->manufacturer)) &&
				(match_tok->serialnr == NULL ||
					!strcmp(match_tok->serialnr, slot->token->serialnr)) &&
				(match_tok->model == NULL ||
					!strcmp(match_tok->model, slot->token->model))) {
			found_slot = slot;
		}
		if (ctx->verbose) {
			fprintf(stderr, "[%lu] %-25.25s  %-16s",
				PKCS11_get_slotid_from_slot(slot),
				slot->description, flags);
			if (slot->token) {
				fprintf(stderr, "  (%s)",
					slot->token->label[0] ?
					slot->token->label : "no label");
			}
			fprintf(stderr, "\n");
		}
	}

	if (match_tok) {
		OPENSSL_free(match_tok->model);
		OPENSSL_free(match_tok->manufacturer);
		OPENSSL_free(match_tok->serialnr);
		OPENSSL_free(match_tok->label);
		OPENSSL_free(match_tok);
	}
	if (found_slot) {
		slot = found_slot;
	} else if (match_tok) {
		fprintf(stderr, "Specified object not found\n");
		return NULL;
	} else if (slot_nr == -1) {
		if (!(slot = PKCS11_find_token(ctx->pkcs11_ctx,
				ctx->slot_list, ctx->slot_count))) {
			fprintf(stderr, "No tokens found\n");
			return NULL;
		}
	} else {
		fprintf(stderr, "Invalid slot number: %d\n", slot_nr);
		return NULL;
	}
	tok = slot->token;

	if (tok == NULL) {
		fprintf(stderr, "Found empty token\n");
		return NULL;
	}
	/* The following check is non-critical to ensure interoperability
	 * with some other (which ones?) PKCS#11 libraries */
	if (!tok->initialized)
		fprintf(stderr, "Found uninitialized token\n");
	if (isPrivate && !tok->userPinSet && !tok->readOnly) {
		fprintf(stderr, "Found slot without user PIN\n");
		return NULL;
	}

	if (ctx->verbose) {
		fprintf(stderr, "Found slot:  %s\n", slot->description);
		fprintf(stderr, "Found token: %s\n", slot->token->label);
	}

	if (PKCS11_enumerate_certs(tok, &certs, &cert_count)) {
		fprintf(stderr, "Unable to enumerate certificates\n");
		return NULL;
	}

	if (ctx->verbose) {
		fprintf(stderr, "Found %u certificate%s:\n", cert_count,
			(cert_count <= 1) ? "" : "s");
		for (n = 0; n < cert_count; n++) {
			PKCS11_CERT *c = certs + n;
			char *dn = NULL;

			fprintf(stderr, "  %2u    id=", n + 1);
			dump_hex(stderr, c->id, c->id_len);
			fprintf(stderr, " label=%s", c->label);
			if (c->x509)
				dn = X509_NAME_oneline(X509_get_subject_name(c->x509), NULL, 0);
			if (dn) {
				fprintf(stderr, " (%s)", dn);
				OPENSSL_free(dn);
			}
			fprintf(stderr, "\n");
		}
	}

	if (isPrivate) {
		/* Check if already logged in to avoid resetting state */
		if (PKCS11_is_logged_in(slot, 0, &already_logged_in) != 0) {
			fprintf(stderr, "Unable to check if already logged in\n");
			return NULL;
		}
		/* Perform login to the token if required */
		if (!already_logged_in && !pkcs11_login(ctx, slot, tok, ui_method, callback_data)) {
			fprintf(stderr, "login to token failed, returning NULL...\n");
			return NULL;
		}
		/* Make sure there is at least one private key on the token */
		if (PKCS11_enumerate_keys(tok, &keys, &key_count)) {
			fprintf(stderr, "Unable to enumerate private keys\n");
			return NULL;
		}
	} else {
		/* Make sure there is at least one public key on the token */
		if (PKCS11_enumerate_public_keys(tok, &keys, &key_count)) {
			fprintf(stderr, "Unable to enumerate public keys\n");
			return NULL;
		}
	}
	if (key_count == 0) {
		fprintf(stderr, "No %s keys found.\n",
			(char *)(isPrivate ? "private" : "public"));
		return NULL;
	}
	if (ctx->verbose)
		fprintf(stderr, "Found %u %s key%s:\n", key_count,
			(char *)(isPrivate ? "private" : "public"),
			(key_count == 1) ? "" : "s");

	if (s_slot_key_id && *s_slot_key_id &&
			(key_id_len != 0 || key_label != NULL)) {
		for (n = 0; n < key_count; n++) {
			PKCS11_KEY *k = keys + n;

			if (ctx->verbose) {
				fprintf(stderr, "  %2u %c%c id=", n + 1,
					k->isPrivate ? 'P' : ' ',
					k->needLogin ? 'L' : ' ');
				dump_hex(stderr, k->id, k->id_len);
				fprintf(stderr, " label=%s\n", k->label);
			}
			if (key_label != NULL && strcmp(k->label, key_label) == 0)
				selected_key = k;
			if (key_id_len != 0 && k->id_len == key_id_len
					&& memcmp(k->id, key_id, key_id_len) == 0)
				selected_key = k;
		}
	} else {
		selected_key = keys; /* Use the first key */
	}

	if (selected_key != NULL) {
		pk = isPrivate ?
			PKCS11_get_private_key(selected_key) :
			PKCS11_get_public_key(selected_key);
	} else {
		fprintf(stderr, "Key not found.\n");
		pk = NULL;
	}
	if (key_label != NULL)
		OPENSSL_free(key_label);
	return pk;
}
Esempio n. 15
0
int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
	{
	long l;
	int ret=0,i;
	char *m=NULL,mlch = ' ';
	int nmindent = 0;
	X509_CINF *ci;
	ASN1_INTEGER *bs;
	EVP_PKEY *pkey=NULL;
	const char *neg;

	if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
			mlch = '\n';
			nmindent = 12;
	}

	if(nmflags == X509_FLAG_COMPAT)
		nmindent = 16;

	ci=x->cert_info;
	if(!(cflag & X509_FLAG_NO_HEADER))
		{
		if (BIO_write(bp,"Certificate:\n",13) <= 0) goto err;
		if (BIO_write(bp,"    Data:\n",10) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_VERSION))
		{
		l=X509_get_version(x);
		if (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_SERIAL))
		{

		if (BIO_write(bp,"        Serial Number:",22) <= 0) goto err;

		bs=X509_get_serialNumber(x);
		if (bs->length <= (int)sizeof(long))
			{
			l=ASN1_INTEGER_get(bs);
			if (bs->type == V_ASN1_NEG_INTEGER)
				{
				l= -l;
				neg="-";
				}
			else
				neg="";
			if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0)
				goto err;
			}
		else
			{
			neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":"";
			if (BIO_printf(bp,"\n%12s%s","",neg) <= 0) goto err;

			for (i=0; i<bs->length; i++)
				{
				if (BIO_printf(bp,"%02x%c",bs->data[i],
					((i+1 == bs->length)?'\n':':')) <= 0)
					goto err;
				}
			}

		}

	if(!(cflag & X509_FLAG_NO_SIGNAME))
		{
		if(X509_signature_print(bp, x->sig_alg, NULL) <= 0)
			goto err;
#if 0
		if (BIO_printf(bp,"%8sSignature Algorithm: ","") <= 0) 
			goto err;
		if (i2a_ASN1_OBJECT(bp, ci->signature->algorithm) <= 0)
			goto err;
		if (BIO_puts(bp, "\n") <= 0)
			goto err;
#endif
		}

	if(!(cflag & X509_FLAG_NO_ISSUER))
		{
		if (BIO_printf(bp,"        Issuer:%c",mlch) <= 0) goto err;
		if (X509_NAME_print_ex(bp,X509_get_issuer_name(x),nmindent, nmflags) < 0) goto err;
		if (BIO_write(bp,"\n",1) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_VALIDITY))
		{
		if (BIO_write(bp,"        Validity\n",17) <= 0) goto err;
		if (BIO_write(bp,"            Not Before: ",24) <= 0) goto err;
		if (!ASN1_TIME_print(bp,X509_get_notBefore(x))) goto err;
		if (BIO_write(bp,"\n            Not After : ",25) <= 0) goto err;
		if (!ASN1_TIME_print(bp,X509_get_notAfter(x))) goto err;
		if (BIO_write(bp,"\n",1) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_SUBJECT))
		{
		if (BIO_printf(bp,"        Subject:%c",mlch) <= 0) goto err;
		if (X509_NAME_print_ex(bp,X509_get_subject_name(x),nmindent, nmflags) < 0) goto err;
		if (BIO_write(bp,"\n",1) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_PUBKEY))
		{
		if (BIO_write(bp,"        Subject Public Key Info:\n",33) <= 0)
			goto err;
		if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0)
			goto err;
		if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
			goto err;
		if (BIO_puts(bp, "\n") <= 0)
			goto err;

		pkey=X509_get_pubkey(x);
		if (pkey == NULL)
			{
			BIO_printf(bp,"%12sUnable to load Public Key\n","");
			ERR_print_errors(bp);
			}
		else
			{
			EVP_PKEY_print_public(bp, pkey, 16, NULL);
			EVP_PKEY_free(pkey);
			}
		}

	if (!(cflag & X509_FLAG_NO_EXTENSIONS))
		X509V3_extensions_print(bp, "X509v3 extensions",
					ci->extensions, cflag, 8);

	if(!(cflag & X509_FLAG_NO_SIGDUMP))
		{
		if(X509_signature_print(bp, x->sig_alg, x->signature) <= 0) goto err;
		}
	if(!(cflag & X509_FLAG_NO_AUX))
		{
		if (!X509_CERT_AUX_print(bp, x->aux, 0)) goto err;
		}
	ret=1;
err:
	if (m != NULL) OPENSSL_free(m);
	return(ret);
	}
Esempio n. 16
0
int redisContextConnectSSL(redisContext *c, const char *addr, int port, char* certfile, char* certdir, struct timeval *timeout) {
    struct timeval  start_time;
    int             has_timeout = 0;
    int             is_nonblocking = 0;

    c->ssl.sd = -1;
    c->ssl.ctx = NULL;
    c->ssl.ssl = NULL;
    c->ssl.bio = NULL;

    // Set up a SSL_CTX object, which will tell our BIO object how to do its work
    SSL_CTX* ctx = SSL_CTX_new(TLSv1_1_client_method());
    c->ssl.ctx = ctx;

    // Create a SSL object pointer, which our BIO object will provide.
    SSL* ssl;

    // Create our BIO object for SSL connections.
    BIO* bio = BIO_new_ssl_connect(ctx);
    c->ssl.bio = bio;

    // Failure?
    if (bio == NULL) {
        char errorbuf[1024];
        __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Error creating BIO!\n");

        ERR_error_string(1024,errorbuf);
        __redisSetError(c,REDIS_ERR_OTHER,errorbuf);

        // We need to free up the SSL_CTX before we leave.
        cleanupSSL( &c->ssl );
        return REDIS_ERR;
    }

    // Makes ssl point to bio's SSL object.
    BIO_get_ssl(bio, &ssl);
    c->ssl.ssl = ssl;

    // Set the SSL to automatically retry on failure.
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

    char* connect_str = (char *)calloc( 1, strlen( addr ) + 10 );
    sprintf( connect_str, "%s:%d", addr, port );
    c->ssl.conn_str = connect_str;

    // We're connection to the REDIS server at host:port
    BIO_set_conn_hostname(bio, connect_str);

    SSL_CTX_load_verify_locations(ctx, certfile, certdir);

    // Are we supposed to be blocking or non-blocking?
    if( (c->flags & REDIS_BLOCK) == 0) {
        is_nonblocking = 1;
        BIO_set_nbio(bio,1);
    }

    // What about a timeout?
    // If we're blocking and have a timeout, we need to handle that specially
    if( NULL != timeout ) {
        BIO_set_nbio(bio,1);
        has_timeout = 1;
        gettimeofday(&start_time, NULL);
    }

    while(1) {
        struct timeval	cur_time,
                    elapsed_time;

        if (has_timeout) {
            gettimeofday(&cur_time, NULL);
            elapsed_time = subtractTimeval( cur_time, start_time );

            if (compareTimeval( elapsed_time, *timeout) > 0) {
                char errorbuf[1024];

                __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Connection timed out.");
                ERR_error_string(1024,errorbuf);
                __redisSetError(c,REDIS_ERR_OTHER,errorbuf);
                cleanupSSL( &(c->ssl) );
                return REDIS_ERR;
            }
        }

        // Same as before, try to connect.
        if (BIO_do_connect(bio) <= 0 ) {
            if( BIO_should_retry( bio ) ) {
                // We need to retry.
            } else {
                char errorbuf[1024];
                __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Failed to connect");
                ERR_error_string(1024,errorbuf);
                __redisSetError(c,REDIS_ERR_OTHER,errorbuf);
                cleanupSSL( &(c->ssl) );
                return REDIS_ERR;
            }
        } else {
            // connect is done...
            break;
        }

        if( has_timeout ) {
            // Do select and seelct on it
            int result;
            int fd = BIO_get_fd( bio, NULL );
            struct timeval time_left;

            if (has_timeout) {
                time_left = subtractTimeval( *timeout, elapsed_time );
            }

            fd_set readset, writeset;
            FD_ZERO(&readset);
            FD_SET(fd, &readset);
            FD_ZERO(&writeset);
            FD_SET(fd, &writeset);

            do {
                result = select( fd+1, &readset, &writeset, NULL, &time_left);
            } while( result == -1 && errno == EINTR );
        }

    }

    while(1) {
        struct timeval	cur_time,
                    elapsed_time;

        if (has_timeout) {
            gettimeofday(&cur_time, NULL);
            elapsed_time = subtractTimeval( cur_time, start_time );

            if (compareTimeval( elapsed_time, *timeout) > 0) {
                char errorbuf[1024];

                __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Connection timed out.");
                ERR_error_string(1024,errorbuf);
                __redisSetError(c,REDIS_ERR_OTHER,errorbuf);
                cleanupSSL( &(c->ssl) );
                return REDIS_ERR;
            }
        }

        // Now we need to do the SSL handshake, so we can communicate.
        if (BIO_do_handshake(bio) <= 0) {
            if( BIO_should_retry( bio ) ) {
                // We need to retry.
            } else {
                char errorbuf[1024];
                __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: handshake failure");
                ERR_error_string(1024,errorbuf);
                __redisSetError(c,REDIS_ERR_OTHER,errorbuf);
                cleanupSSL( &(c->ssl) );
                return REDIS_ERR;
            }
        } else {
            // handshake is done...
            break;
        }

        if( has_timeout ) {
            // Do select and seelct on it
            int result;
            int fd = BIO_get_fd( bio, NULL );
            struct timeval time_left;

            if (has_timeout) {
                time_left = subtractTimeval( *timeout, elapsed_time );
            }

            fd_set readset, writeset;
            FD_ZERO(&readset);
            FD_SET(fd, &readset);
            FD_ZERO(&writeset);
            FD_SET(fd, &writeset);

            do {
                result = select( fd+1, &readset, &writeset, NULL, &time_left);
            } while( result == -1 && errno == EINTR );
        }

    }

    long verify_result = SSL_get_verify_result(ssl);
    if( verify_result == X509_V_OK) {
        X509* peerCertificate = SSL_get_peer_certificate(ssl);

        char commonName [512];
        X509_NAME * name = X509_get_subject_name(peerCertificate);
        X509_NAME_get_text_by_NID(name, NID_commonName, commonName, 512);

        // TODO: Add a redis config parameter for the common name to check for.
        //       Since Redis connections are generally done with an IP address directly,
        //       we can't just assume that the name we get on the addr is an actual name.
        //
        //    if(strcasecmp(commonName, "BradBroerman") != 0) {
        //      __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Error validating cert common name.\n\n" );
        //      cleanupSSL( &(c->ssl) );
        //      return REDIS_ERR;

    } else {
        char errorbuf[1024];
        __redisSetError(c,REDIS_ERR_OTHER,"SSL Error: Error retrieving peer certificate.\n" );
        ERR_error_string(1024,errorbuf);
        __redisSetError(c,REDIS_ERR_OTHER,errorbuf);
        cleanupSSL( &(c->ssl) );
        return REDIS_ERR;
    }

    BIO_set_nbio(bio,is_nonblocking);

    return REDIS_OK;
}
/* Helper function to trace the signing cert to a trusted CA root
 * in the OpenSSL Trust Store. */
static int checkCertOpenSSL(const GTPublicationsFile *publications_file)
{
	int res = GT_UNKNOWN_ERROR;
	unsigned char *cert_der = NULL;
	size_t cert_der_len;
	unsigned char *cert_tmp;
	X509 *cert = NULL;
	X509_STORE_CTX *store_ctx = NULL;
	X509_NAME *subj = NULL;
	ASN1_OBJECT *oid = NULL;
	char tmp_name[256];
	int rc;

	res = GTPublicationsFile_getSigningCert(publications_file, &cert_der, &cert_der_len);
	if (res != GT_OK) {
		goto cleanup;
	}

	/* Note that d2i_X509() spoils the pointer to the buffer, use a temporary copy. */
	cert_tmp = cert_der;
	cert = d2i_X509(NULL, (const unsigned char **) &cert_tmp, cert_der_len);
	if (cert == NULL) {
		res = GT_NOT_VALID_PUBLICATION;
		goto cleanup;
	}

#ifdef MAGIC_EMAIL
	subj = X509_get_subject_name(cert);
	if (subj == NULL) {
		res = GT_CRYPTO_FAILURE;
		goto cleanup;
	}
	oid = OBJ_txt2obj("1.2.840.113549.1.9.1", 1);
	if (oid == NULL) {
		res = GT_OUT_OF_MEMORY;
		goto cleanup;
	}
	rc = X509_NAME_get_text_by_OBJ(subj, oid, tmp_name, sizeof(tmp_name));
	if (rc < 0) {
		res = GT_INVALID_SIGNATURE;
		goto cleanup;
	}
	if (strcmp(tmp_name, MAGIC_EMAIL) != 0) {
		res = GT_INVALID_SIGNATURE;
		goto cleanup;
	}
#endif

	store_ctx = X509_STORE_CTX_new();
	if (store_ctx == NULL) {
		res = GT_OUT_OF_MEMORY;
		goto cleanup;
	}

	/* The truststore is not initialized by default. */
	if (GT_truststore == NULL) {
		res = GTTruststore_init(1);
		if (res != GT_OK) goto cleanup;
	}

	if (!X509_STORE_CTX_init(store_ctx, GT_truststore, cert,
			publications_file->signature->d.sign->cert)) {
		res = GT_OUT_OF_MEMORY;
		goto cleanup;
	}

	rc = X509_verify_cert(store_ctx);
	if (rc < 0) {
		res = GT_CRYPTO_FAILURE;
		goto cleanup;
	}
	if (rc != 1) {
		res = GT_CERT_NOT_TRUSTED;
		goto cleanup;
	}

	res = GT_OK;

cleanup:
	GT_free(cert_der);
	/* Do not free subj, it points into cert. */
	ASN1_OBJECT_free(oid);
	if (cert != NULL) {
		X509_free(cert);
	}
	if (store_ctx != NULL) {
		X509_STORE_CTX_free(store_ctx);
	}

	return res;
}
Esempio n. 18
0
static int get_comp(str* res, int local, int issuer, int nid, sip_msg_t* msg)
{
    static char buf[1024];
    X509* cert;
    struct tcp_connection* c;
    X509_NAME* name;
    X509_NAME_ENTRY* e;
    ASN1_STRING* asn1;
    int index, text_len;
    char* elem;
    unsigned char* text_s;

    text_s = 0;

    if (get_cert(&cert, &c, msg, local) < 0) return -1;

    name = issuer ? X509_get_issuer_name(cert) : X509_get_subject_name(cert);
    if (!name) {
        ERR("Cannot extract subject or issuer name from peer certificate\n");
        goto err;
    }

    index = X509_NAME_get_index_by_NID(name, nid, -1);
    if (index == -1) {
        switch(nid) {
        case NID_commonName:
            elem = "CommonName";
            break;
        case NID_organizationName:
            elem = "OrganizationName";
            break;
        case NID_organizationalUnitName:
            elem = "OrganizationalUnitUname";
            break;
        case NID_countryName:
            elem = "CountryName";
            break;
        case NID_stateOrProvinceName:
            elem = "StateOrProvinceName";
            break;
        case NID_localityName:
            elem = "LocalityName";
            break;
        default:
            elem = "Unknown";
            break;
        }
        DBG("Element %s not found in certificate subject/issuer\n", elem);
        goto err;
    }

    e = X509_NAME_get_entry(name, index);
    asn1 = X509_NAME_ENTRY_get_data(e);
    text_len = ASN1_STRING_to_UTF8(&text_s, asn1);
    if (text_len < 0 || text_len >= 1024) {
        ERR("Error converting ASN1 string\n");
        goto err;
    }
    memcpy(buf, text_s, text_len);
    res->s = buf;
    res->len = text_len;

    OPENSSL_free(text_s);
    if (!local) X509_free(cert);
    tcpconn_put(c);
    return 0;

err:
    if (text_s) OPENSSL_free(text_s);
    if (!local) X509_free(cert);
    tcpconn_put(c);
    return -1;
}
Esempio n. 19
0
CK_RV
gpkcs11_add_credentials(char *label,
			const char *cert_file,
			const char *private_key_file,
			char *id,
			int anchor)
{
    struct gpkcs11_st_object *o = NULL;
    CK_BBOOL bool_true = CK_TRUE;
    CK_BBOOL bool_false = CK_FALSE;
    CK_OBJECT_CLASS c;
    CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
    CK_KEY_TYPE key_type;
    CK_MECHANISM_TYPE mech_type;
    CK_RV ret = CKR_GENERAL_ERROR;
    void *subject_data = NULL;
    size_t subject_length;
    X509 *cert, *proxy_cert = NULL;
    EVP_PKEY *public_key;
    FILE *f = NULL;
    size_t id_len = strlen(id);

    f = fopen(cert_file, "r");
    if (f == NULL) {
	gpkcs11_log("failed to open file %s\n", cert_file);
	return CKR_GENERAL_ERROR;
    }

    while (1) {
	cert = PEM_read_X509(f, NULL, NULL, NULL);
	if (cert == NULL) {
	    if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE)
		break;
	    ret = CKR_GENERAL_ERROR;
	    goto out;
	}
	if (proxy_cert == NULL)
	    proxy_cert = cert;
	ret = gpkcs11_add_certificate(label, cert, id, anchor);
	if (ret)
	    goto out;
    }

    public_key = X509_get_pubkey(proxy_cert);
    switch (EVP_PKEY_type(public_key->type)) {
    case EVP_PKEY_RSA:
	key_type = CKK_RSA;
	break;
    case EVP_PKEY_DSA:
	key_type = CKK_DSA;
	break;
    default:
	/* XXX */
	break;
    }

    OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, subject_data, subject_length, 
			       X509_get_subject_name(proxy_cert), ret);
    if (ret)
	goto out;


    if (private_key_file) {
	CK_FLAGS flags;
	FILE *f;

	o = add_st_object();
	if (o == NULL) {
	    ret = CKR_DEVICE_MEMORY;
	    goto out;
	}
	o->type = STO_T_PRIVATE_KEY;
	o->u.private_key.file = strdup(private_key_file);
	o->u.private_key.key = NULL;

	o->u.private_key.cert = proxy_cert;

	c = CKO_PRIVATE_KEY;
	add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c));
	add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_LABEL, label, strlen(label));

	add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type));
	add_object_attribute(o, 0, CKA_ID, id, id_len);
	add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */
	add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */
	add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false));
	mech_type = CKM_RSA_X_509;
	add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type));

	add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length);
	add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true));
	flags = 0;
	add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags));

	add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false));
	add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true));
	add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false));

	add_pubkey_info(o, key_type, public_key);

	f = fopen(private_key_file, "r");
	if (f == NULL) {
	    gpkcs11_log("failed to open private key\n");
	    return CKR_GENERAL_ERROR;
	}

	o->u.private_key.key = PEM_read_PrivateKey(f, NULL, pem_callback, NULL);
	fclose(f);
	if (o->u.private_key.key == NULL) {
	    gpkcs11_log("failed to read private key a startup\n");
	    /* don't bother with this failure for now, 
	       fix it at C_Login time */;
	} else {
	    /* XXX verify keytype */

	    if (key_type == CKK_RSA)
		RSA_set_method(o->u.private_key.key->pkey.rsa, 
			       RSA_PKCS1_SSLeay());

	    if (X509_check_private_key(proxy_cert, o->u.private_key.key) != 1) {
		EVP_PKEY_free(o->u.private_key.key);	    
		o->u.private_key.key = NULL;
		gpkcs11_log("private key doesn't verify\n");
	    } else {
		gpkcs11_log("private key usable\n");
		gpkcs11_soft_token.flags.login_done = 1;
	    }
	}
    }

    ret = CKR_OK;
 out:
    if (ret != CKR_OK) {
	gpkcs11_log("something went wrong when adding cert!\n");

	/* XXX wack o */;
    }

    if (f)
	fclose(f);

    return ret;
}
Esempio n. 20
0
/**
 * Handle a completed fetch (CURLMSG_DONE from curl_multi_info_read()).
 *
 * \param curl_handle curl easy handle of fetch
 * \param result The result code of the completed fetch.
 */
static void fetch_curl_done(CURL *curl_handle, CURLcode result)
{
	fetch_msg msg;
	bool finished = false;
	bool error = false;
	bool cert = false;
	bool abort_fetch;
	struct curl_fetch_info *f;
	char **_hideous_hack = (char **) (void *) &f;
	CURLcode code;
	struct cert_info certs[MAX_CERTS];
	memset(certs, 0, sizeof(certs));

	/* find the structure associated with this fetch */
	/* For some reason, cURL thinks CURLINFO_PRIVATE should be a string?! */
	code = curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, _hideous_hack);
	assert(code == CURLE_OK);

	abort_fetch = f->abort;
	LOG("done %s", nsurl_access(f->url));

	if (abort_fetch == false && (result == CURLE_OK ||
			(result == CURLE_WRITE_ERROR && f->stopped == false))) {
		/* fetch completed normally or the server fed us a junk gzip
		 * stream (usually in the form of garbage at the end of the
		 * stream). Curl will have fed us all but the last chunk of
		 * decoded data, which is sad as, if we'd received the last
		 * chunk, too, we'd be able to render the whole object.
		 * As is, we'll just have to accept that the end of the
		 * object will be truncated in this case and leave it to
		 * the content handlers to cope.
		 */
		if (f->stopped ||
				(!f->had_headers &&
					fetch_curl_process_headers(f)))
			; /* redirect with no body or similar */
		else
			finished = true;
	} else if (result == CURLE_PARTIAL_FILE) {
		/* CURLE_PARTIAL_FILE occurs if the received body of a
		 * response is smaller than that specified in the
		 * Content-Length header. */
		if (!f->had_headers && fetch_curl_process_headers(f))
			; /* redirect with partial body, or similar */
		else {
			finished = true;
		}
	} else if (result == CURLE_WRITE_ERROR && f->stopped) {
		/* CURLE_WRITE_ERROR occurs when fetch_curl_data
		 * returns 0, which we use to abort intentionally */
		;
	} else if (result == CURLE_SSL_PEER_CERTIFICATE ||
			result == CURLE_SSL_CACERT) {
		memcpy(certs, f->cert_data, sizeof(certs));
		memset(f->cert_data, 0, sizeof(f->cert_data));
		cert = true;
	} else {
		LOG("Unknown cURL response code %d", result);
		error = true;
	}

	fetch_curl_stop(f);

	if (abort_fetch)
		; /* fetch was aborted: no callback */
	else if (finished) {
		msg.type = FETCH_FINISHED;
		fetch_send_callback(&msg, f->fetch_handle);
	} else if (cert) {
		int i;
		BIO *mem;
		BUF_MEM *buf;
		struct ssl_cert_info ssl_certs[MAX_CERTS];

		for (i = 0; i < MAX_CERTS && certs[i].cert; i++) {
			ssl_certs[i].version =
				X509_get_version(certs[i].cert);

			mem = BIO_new(BIO_s_mem());
			ASN1_TIME_print(mem,
					X509_get_notBefore(certs[i].cert));
			BIO_get_mem_ptr(mem, &buf);
			(void) BIO_set_close(mem, BIO_NOCLOSE);
			BIO_free(mem);
			memcpy(ssl_certs[i].not_before,
			       buf->data,
			       min(sizeof(ssl_certs[i].not_before) - 1,
				   (unsigned)buf->length));
			ssl_certs[i].not_before[min(sizeof(ssl_certs[i].not_before) - 1,
						    (unsigned)buf->length)] = 0;
			BUF_MEM_free(buf);

			mem = BIO_new(BIO_s_mem());
			ASN1_TIME_print(mem,
					X509_get_notAfter(certs[i].cert));
			BIO_get_mem_ptr(mem, &buf);
			(void) BIO_set_close(mem, BIO_NOCLOSE);
			BIO_free(mem);
			memcpy(ssl_certs[i].not_after,
			       buf->data,
			       min(sizeof(ssl_certs[i].not_after) - 1,
				   (unsigned)buf->length));
			ssl_certs[i].not_after[min(sizeof(ssl_certs[i].not_after) - 1,
						 (unsigned)buf->length)] = 0;

			BUF_MEM_free(buf);

			ssl_certs[i].sig_type =
				X509_get_signature_type(certs[i].cert);
			ssl_certs[i].serial =
				ASN1_INTEGER_get(
					X509_get_serialNumber(certs[i].cert));
			mem = BIO_new(BIO_s_mem());
			X509_NAME_print_ex(mem,
				X509_get_issuer_name(certs[i].cert),
				0, XN_FLAG_SEP_CPLUS_SPC |
					XN_FLAG_DN_REV | XN_FLAG_FN_NONE);
			BIO_get_mem_ptr(mem, &buf);
			(void) BIO_set_close(mem, BIO_NOCLOSE);
			BIO_free(mem);
			memcpy(ssl_certs[i].issuer,
			       buf->data,
			       min(sizeof(ssl_certs[i].issuer) - 1,
				   (unsigned) buf->length));
			ssl_certs[i].issuer[min(sizeof(ssl_certs[i].issuer) - 1,
						(unsigned) buf->length)] = 0;
			BUF_MEM_free(buf);

			mem = BIO_new(BIO_s_mem());
			X509_NAME_print_ex(mem,
				X509_get_subject_name(certs[i].cert),
					   0,
					   XN_FLAG_SEP_CPLUS_SPC |
					   XN_FLAG_DN_REV |
					   XN_FLAG_FN_NONE);
			BIO_get_mem_ptr(mem, &buf);
			(void) BIO_set_close(mem, BIO_NOCLOSE);
			BIO_free(mem);
			memcpy(ssl_certs[i].subject,
			       buf->data,
			       min(sizeof(ssl_certs[i].subject) - 1,
				   (unsigned)buf->length));
			ssl_certs[i].subject[min(sizeof(ssl_certs[i].subject) - 1,
						 (unsigned) buf->length)] = 0;
			BUF_MEM_free(buf);

			ssl_certs[i].cert_type =
				X509_certificate_type(certs[i].cert,
					X509_get_pubkey(certs[i].cert));

			/* and clean up */
			certs[i].cert->references--;
			if (certs[i].cert->references == 0)
				X509_free(certs[i].cert);
		}

		msg.type = FETCH_CERT_ERR;
		msg.data.cert_err.certs = ssl_certs;
		msg.data.cert_err.num_certs = i;
		fetch_send_callback(&msg, f->fetch_handle);
	} else if (error) {
		switch (result) {
		case CURLE_SSL_CONNECT_ERROR:
			msg.type = FETCH_SSL_ERR;
			break;

		case CURLE_OPERATION_TIMEDOUT:
			msg.type = FETCH_TIMEDOUT;
			msg.data.error = curl_easy_strerror(result);
			break;

		default:
			msg.type = FETCH_ERROR;
			msg.data.error = curl_easy_strerror(result);
		}

		fetch_send_callback(&msg, f->fetch_handle);
	}

	fetch_free(f->fetch_handle);
}
Esempio n. 21
0
static int janus_dtls_generate_keys(X509 **certificate, EVP_PKEY **private_key) {
	static const int num_bits = 2048;
	BIGNUM *bne = NULL;
	RSA *rsa_key = NULL;
	X509_NAME *cert_name = NULL;

	JANUS_LOG(LOG_VERB, "Generating DTLS key / cert\n");

	/* Create a big number object. */
	bne = BN_new();
	if(!bne) {
		JANUS_LOG(LOG_FATAL, "BN_new() failed\n");
		goto error;
	}

	if(!BN_set_word(bne, RSA_F4)) {  /* RSA_F4 == 65537 */
		JANUS_LOG(LOG_FATAL, "BN_set_word() failed\n");
		goto error;
	}

	/* Generate a RSA key. */
	rsa_key = RSA_new();
	if(!rsa_key) {
		JANUS_LOG(LOG_FATAL, "RSA_new() failed\n");
		goto error;
	}

	/* This takes some time. */
	if(!RSA_generate_key_ex(rsa_key, num_bits, bne, NULL)) {
		JANUS_LOG(LOG_FATAL, "RSA_generate_key_ex() failed\n");
		goto error;
	}

	/* Create a private key object (needed to hold the RSA key). */
	*private_key = EVP_PKEY_new();
	if(!*private_key) {
		JANUS_LOG(LOG_FATAL, "EVP_PKEY_new() failed\n");
		goto error;
	}

	if(!EVP_PKEY_assign_RSA(*private_key, rsa_key)) {
		JANUS_LOG(LOG_FATAL, "EVP_PKEY_assign_RSA() failed\n");
		goto error;
	}
	/* The RSA key now belongs to the private key, so don't clean it up separately. */
	rsa_key = NULL;

	/* Create the X509 certificate. */
	*certificate = X509_new();
	if(!*certificate) {
		JANUS_LOG(LOG_FATAL, "X509_new() failed\n");
		goto error;
	}

	/* Set version 3 (note that 0 means version 1). */
	X509_set_version(*certificate, 2);

	/* Set serial number. */
	ASN1_INTEGER_set(X509_get_serialNumber(*certificate), (long)g_random_int());

	/* Set valid period. */
	X509_gmtime_adj(X509_get_notBefore(*certificate), -1 * DTLS_AUTOCERT_DURATION);  /* -1 year */
	X509_gmtime_adj(X509_get_notAfter(*certificate), DTLS_AUTOCERT_DURATION);  /* 1 year */

	/* Set the public key for the certificate using the key. */
	if(!X509_set_pubkey(*certificate, *private_key)) {
		JANUS_LOG(LOG_FATAL, "X509_set_pubkey() failed\n");
		goto error;
	}

	/* Set certificate fields. */
	cert_name = X509_get_subject_name(*certificate);
	if(!cert_name) {
		JANUS_LOG(LOG_FATAL, "X509_get_subject_name() failed\n");
		goto error;
	}
	X509_NAME_add_entry_by_txt(cert_name, "O", MBSTRING_ASC, (const unsigned char*)"Janus", -1, -1, 0);
	X509_NAME_add_entry_by_txt(cert_name, "CN", MBSTRING_ASC, (const unsigned char*)"Janus", -1, -1, 0);

	/* It is self-signed so set the issuer name to be the same as the subject. */
	if(!X509_set_issuer_name(*certificate, cert_name)) {
		JANUS_LOG(LOG_FATAL, "X509_set_issuer_name() failed\n");
		goto error;
	}

	/* Sign the certificate with the private key. */
	if(!X509_sign(*certificate, *private_key, EVP_sha1())) {
		JANUS_LOG(LOG_FATAL, "X509_sign() failed\n");
		goto error;
	}

	/* Free stuff and resurn. */
	BN_free(bne);
	return 0;

error:
	if(bne)
		BN_free(bne);
	if(rsa_key && !*private_key)
		RSA_free(rsa_key);
	if(*private_key)
		EVP_PKEY_free(*private_key);  /* This also frees the RSA key. */
	if(*certificate)
		X509_free(*certificate);
	return -1;
}
Esempio n. 22
0
/*
 * Create a fake X509v3 certificate, signed by the provided CA,
 * based on the original certificate retrieved from the real server.
 * The returned certificate is created using X509_new() and thus must
 * be freed by the caller using X509_free().
 * The optional argument extraname is added to subjectAltNames if provided.
 */
X509 *
ssl_x509_forge(X509 *cacrt, EVP_PKEY *cakey, X509 *origcrt,
               const char *extraname, EVP_PKEY *key)
{
	X509_NAME *subject, *issuer;
	GENERAL_NAMES *names;
	GENERAL_NAME *gn;
	X509 *crt;

	subject = X509_get_subject_name(origcrt);
	issuer = X509_get_subject_name(cacrt);
	if (!subject || !issuer)
		return NULL;

	crt = X509_new();
	if (!crt)
		return NULL;

	if (!X509_set_version(crt, 0x02) ||
	    !X509_set_subject_name(crt, subject) ||
	    !X509_set_issuer_name(crt, issuer) ||
	    ssl_x509_serial_copyrand(crt, origcrt) == -1 ||
	    !X509_gmtime_adj(X509_get_notBefore(crt), (long)-60*60*24) ||
	    !X509_gmtime_adj(X509_get_notAfter(crt), (long)60*60*24*364) ||
	    !X509_set_pubkey(crt, key))
		goto errout;

	/* add standard v3 extensions; cf. RFC 2459 */
	X509V3_CTX ctx;
	X509V3_set_ctx(&ctx, cacrt, crt, NULL, NULL, 0);
	if (ssl_x509_v3ext_add(&ctx, crt, "basicConstraints",
	                                  "CA:FALSE") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "keyUsage",
	                                  "digitalSignature,"
	                                  "keyEncipherment") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "extendedKeyUsage",
	                                  "serverAuth") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "subjectKeyIdentifier",
	                                  "hash") == -1 ||
	    ssl_x509_v3ext_add(&ctx, crt, "authorityKeyIdentifier",
	                                  "keyid,issuer:always") == -1)
		goto errout;

	if (!extraname) {
		/* no extraname provided: copy original subjectAltName ext */
		if (ssl_x509_v3ext_copy_by_nid(crt, origcrt,
		                               NID_subject_alt_name) == -1)
			goto errout;
	} else {
		names = X509_get_ext_d2i(origcrt, NID_subject_alt_name, 0, 0);
		if (!names) {
			/* no subjectAltName present: add new one */
			char *cfval;
			if (asprintf(&cfval, "DNS:%s", extraname) == -1)
				goto errout;
			if (ssl_x509_v3ext_add(&ctx, crt, "subjectAltName",
			                       cfval) == -1) {
				free(cfval);
				goto errout;
			}
			free(cfval);
		} else {
			/* add extraname to original subjectAltName
			 * and add it to the new certificate */
			gn = GENERAL_NAME_new();
			if (!gn)
				goto errout2;
			gn->type = GEN_DNS;
			gn->d.dNSName = M_ASN1_IA5STRING_new();
			if (!gn->d.dNSName)
				goto errout3;
			ASN1_STRING_set(gn->d.dNSName,
			                (unsigned char *)extraname,
			                strlen(extraname));
			sk_GENERAL_NAME_push(names, gn);
			X509_EXTENSION *ext = X509V3_EXT_i2d(
			                      NID_subject_alt_name, 0, names);
			if (!X509_add_ext(crt, ext, -1)) {
				if (ext) {
					X509_EXTENSION_free(ext);
				}
				goto errout3;
			}
			X509_EXTENSION_free(ext);
			sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
		}
	}
#ifdef DEBUG_CERTIFICATE
	ssl_x509_v3ext_add(&ctx, crt, "nsComment", "Generated by " PNAME);
#endif /* DEBUG_CERTIFICATE */

	const EVP_MD *md;
	switch (EVP_PKEY_type(cakey->type)) {
#ifndef OPENSSL_NO_RSA
		case EVP_PKEY_RSA:
			md = EVP_sha1();
			break;
#endif /* !OPENSSL_NO_RSA */
#ifndef OPENSSL_NO_DSA
		case EVP_PKEY_DSA:
			md = EVP_dss1();
			break;
#endif /* !OPENSSL_NO_DSA */
#ifndef OPENSSL_NO_ECDSA
		case EVP_PKEY_EC:
			md = EVP_ecdsa();
			break;
#endif /* !OPENSSL_NO_ECDSA */
		default:
			goto errout;
	}
	if (!X509_sign(crt, cakey, md))
		goto errout;

	return crt;

errout3:
	GENERAL_NAME_free(gn);
errout2:
	sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
errout:
	X509_free(crt);
	return NULL;
}
Esempio n. 23
0
static int
amqp_ssl_socket_verify_hostname(void *base, const char *host)
{
  struct amqp_ssl_socket_t *self = (struct amqp_ssl_socket_t *)base;
  unsigned char *utf8_value = NULL, *cp, ch;
  int pos, utf8_length, status = 0;
  ASN1_STRING *entry_string;
  X509_NAME_ENTRY *entry;
  X509_NAME *name;
  X509 *peer;
  peer = SSL_get_peer_certificate(self->ssl);
  if (!peer) {
    goto error;
  }
  name = X509_get_subject_name(peer);
  if (!name) {
    goto error;
  }
  pos = X509_NAME_get_index_by_NID(name, NID_commonName, -1);
  if (0 > pos) {
    goto error;
  }
  entry = X509_NAME_get_entry(name, pos);
  if (!entry) {
    goto error;
  }
  entry_string = X509_NAME_ENTRY_get_data(entry);
  if (!entry_string) {
    goto error;
  }
  utf8_length = ASN1_STRING_to_UTF8(&utf8_value, entry_string);
  if (0 > utf8_length) {
    goto error;
  }
  while (utf8_length > 0 && utf8_value[utf8_length - 1] == 0) {
    --utf8_length;
  }
  if (utf8_length >= 256) {
    goto error;
  }
  if ((size_t)utf8_length != strlen((char *)utf8_value)) {
    goto error;
  }
  for (cp = utf8_value; (ch = *cp) != '\0'; ++cp) {
    if (isascii(ch) && !isprint(ch)) {
      goto error;
    }
  }
#ifdef _MSC_VER
#define strcasecmp _stricmp
#endif
  if (strcasecmp(host, (char *)utf8_value)) {
    goto error;
  }
#ifdef _MSC_VER
#undef strcasecmp
#endif
exit:
  OPENSSL_free(utf8_value);
  return status;
error:
  status = -1;
  goto exit;
}
Esempio n. 24
0
int verify_callback(int ok, X509_STORE_CTX *ctx)
{
    X509 *err_cert;
    int err, depth;

    err_cert = X509_STORE_CTX_get_current_cert(ctx);
    err = X509_STORE_CTX_get_error(ctx);
    depth = X509_STORE_CTX_get_error_depth(ctx);

    if (!verify_args.quiet || !ok) {
        BIO_printf(bio_err, "depth=%d ", depth);
        if (err_cert != NULL) {
            X509_NAME_print_ex(bio_err,
                               X509_get_subject_name(err_cert),
                               0, get_nameopt());
            BIO_puts(bio_err, "\n");
        } else {
            BIO_puts(bio_err, "<no cert>\n");
        }
    }
    if (!ok) {
        BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
                   X509_verify_cert_error_string(err));
        if (verify_args.depth >= depth) {
            if (!verify_args.return_error)
                ok = 1;
            verify_args.error = err;
        } else {
            ok = 0;
            verify_args.error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
        }
    }
    switch (err) {
    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
        BIO_puts(bio_err, "issuer= ");
        X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert),
                           0, get_nameopt());
        BIO_puts(bio_err, "\n");
        break;
    case X509_V_ERR_CERT_NOT_YET_VALID:
    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
        BIO_printf(bio_err, "notBefore=");
        ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert));
        BIO_printf(bio_err, "\n");
        break;
    case X509_V_ERR_CERT_HAS_EXPIRED:
    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
        BIO_printf(bio_err, "notAfter=");
        ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert));
        BIO_printf(bio_err, "\n");
        break;
    case X509_V_ERR_NO_EXPLICIT_POLICY:
        if (!verify_args.quiet)
            policies_print(ctx);
        break;
    }
    if (err == X509_V_OK && ok == 2 && !verify_args.quiet)
        policies_print(ctx);
    if (ok && !verify_args.quiet)
        BIO_printf(bio_err, "verify return:%d\n", ok);
    return (ok);
}
Esempio n. 25
0
static void set_peer_cert_chain_info(TLS_REC *tls, SSL *ssl)
{
	int nid;
	char *key = NULL;
	char *value = NULL;
	STACK_OF(X509) *chain = NULL;
	int i;
	int j;
	TLS_CERT_REC *cert_rec = NULL;
	X509_NAME *name = NULL;
	X509_NAME_ENTRY *entry = NULL;
	TLS_CERT_ENTRY_REC *tls_cert_entry_rec = NULL;
	ASN1_STRING *data = NULL;

	g_return_if_fail(tls != NULL);
	g_return_if_fail(ssl != NULL);

	chain = SSL_get_peer_cert_chain(ssl);

	if (chain == NULL)
		return;

	for (i = 0; i < sk_X509_num(chain); i++) {
		cert_rec = tls_cert_create_rec();

		/* Subject. */
		name = X509_get_subject_name(sk_X509_value(chain, i));

		for (j = 0; j < X509_NAME_entry_count(name); j++) {
			entry = X509_NAME_get_entry(name, j);

			nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(entry));
			key = (char *)OBJ_nid2sn(nid);

			if (key == NULL)
				key = (char *)OBJ_nid2ln(nid);

			data = X509_NAME_ENTRY_get_data(entry);
			value = (char *)ASN1_STRING_data(data);

			tls_cert_entry_rec = tls_cert_entry_create_rec(key, value);
			tls_cert_rec_append_subject_entry(cert_rec, tls_cert_entry_rec);
		}

		/* Issuer. */
		name = X509_get_issuer_name(sk_X509_value(chain, i));

		for (j = 0; j < X509_NAME_entry_count(name); j++) {
			entry = X509_NAME_get_entry(name, j);

			nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(entry));
			key = (char *)OBJ_nid2sn(nid);

			if (key == NULL)
				key = (char *)OBJ_nid2ln(nid);

			data = X509_NAME_ENTRY_get_data(entry);
			value = (char *)ASN1_STRING_data(data);

			tls_cert_entry_rec = tls_cert_entry_create_rec(key, value);
			tls_cert_rec_append_issuer_entry(cert_rec, tls_cert_entry_rec);
		}

		tls_rec_append_cert(tls, cert_rec);
	}
}
Esempio n. 26
0
static
int
__pkcs11h_crypto_openssl_certificate_is_issuer (
	IN void * const global_data,
	IN const unsigned char * const issuer_blob,
	IN const size_t issuer_blob_size,
	IN const unsigned char * const cert_blob,
	IN const size_t cert_blob_size
) {
	X509 *x509_issuer = NULL;
	X509 *x509_cert = NULL;
	EVP_PKEY *pub_issuer = NULL;
	__pkcs11_openssl_d2i_t d2i;
	PKCS11H_BOOL is_issuer = FALSE;

	(void)global_data;

	/*_PKCS11H_ASSERT (global_data!=NULL); NOT NEEDED*/
	_PKCS11H_ASSERT (issuer_blob!=NULL);
	_PKCS11H_ASSERT (cert_blob!=NULL);

	if (
		(x509_issuer = X509_new ()) == NULL ||
		(x509_cert = X509_new ()) == NULL
	) {
		goto cleanup;
	}

	d2i = (__pkcs11_openssl_d2i_t)issuer_blob;
	if (
		!d2i_X509 (
			&x509_issuer,
			&d2i,
			issuer_blob_size
		)
	) {
		goto cleanup;
	}

	d2i = (__pkcs11_openssl_d2i_t)cert_blob;
	if (
		!d2i_X509 (
			&x509_cert,
			&d2i,
			cert_blob_size
		)
	) {
		goto cleanup;
	}

	if (
		(pub_issuer = X509_get_pubkey (x509_issuer)) == NULL
	) {
		goto cleanup;
	}

	if (
		!X509_NAME_cmp (
			X509_get_subject_name (x509_issuer),
			X509_get_issuer_name (x509_cert)
		) &&
		X509_verify (x509_cert, pub_issuer) == 1
	) {
		is_issuer = TRUE;
	}

cleanup:

	if (pub_issuer != NULL) {
		EVP_PKEY_free (pub_issuer);
		pub_issuer = NULL;
	}
	if (x509_issuer != NULL) {
		X509_free (x509_issuer);
		x509_issuer = NULL;
	}
	if (x509_cert != NULL) {
		X509_free (x509_cert);
		x509_cert = NULL;
	}

	return is_issuer;
}
Esempio n. 27
0
File: 2cca.c Progetto: randunel/2cca
/*
 * Create identity
 */
int build_identity(void)
{
    EVP_PKEY * pkey ;
    RSA * rsa ;
    EC_KEY * ecc ;
    X509 * cert ;
    X509_NAME * name ;
    identity ca ;
    char filename[FIELD_SZ+5];
    FILE * pem ;

    /* Check before overwriting */
    sprintf(filename, "%s.crt", certinfo.cn);
    if (access(filename, F_OK)!=-1) {
        fprintf(stderr, "identity named %s already exists in this directory. Exiting now\n", filename);
        return -1 ;
    }
    sprintf(filename, "%s.key", certinfo.cn);
    if (access(filename, F_OK)!=-1) {
        fprintf(stderr, "identity named %s already exists in this directory. Exiting now\n", filename);
        return -1 ;
    }

    switch (certinfo.profile) {
        case PROFILE_ROOT_CA:
        strcpy(certinfo.ou, "Root");
        break;

        case PROFILE_SUB_CA:
        strcpy(certinfo.ou, "Sub");
        break;

        case PROFILE_SERVER:
        strcpy(certinfo.ou, "Server");
        break;
        
        case PROFILE_CLIENT:
        strcpy(certinfo.ou, "Client");
        break;

        case PROFILE_WWW:
        strcpy(certinfo.ou, "Server");
        break;

        default:
        fprintf(stderr, "Unknown profile: aborting\n");
        return -1 ;
    }

    if (certinfo.ec_name[0] && certinfo.profile!=PROFILE_CLIENT) {
        fprintf(stderr, "ECC keys are only supported for clients\n");
        return -1 ;
    }

    if (certinfo.profile != PROFILE_ROOT_CA) {
        /* Need to load signing CA */
        if (load_ca(certinfo.signing_ca, &ca)!=0) {
            fprintf(stderr, "Cannot find CA key or certificate\n");
            return -1 ;
        }
        /* Organization is the same as root */
        X509_NAME_get_text_by_NID(X509_get_subject_name(ca.cert),
                                  NID_organizationName,
                                  certinfo.o,
                                  FIELD_SZ);
    }

    /* Generate key pair */
    if (certinfo.ec_name[0]) {
        printf("Generating EC key [%s]\n", certinfo.ec_name);
        ecc = EC_KEY_new_by_curve_name(OBJ_txt2nid(certinfo.ec_name));
        if (!ecc) {
            fprintf(stderr, "Unknown curve: [%s]\n", certinfo.ec_name);
            return -1 ;
        }
        EC_KEY_set_asn1_flag(ecc, OPENSSL_EC_NAMED_CURVE);
        EC_KEY_generate_key(ecc);
        pkey = EVP_PKEY_new();
        EVP_PKEY_assign_EC_KEY(pkey, ecc);
    } else {
        printf("Generating RSA-%d key\n", certinfo.rsa_keysz);
        pkey = EVP_PKEY_new();
        rsa = RSA_generate_key(certinfo.rsa_keysz, RSA_F4, progress, 0);
        EVP_PKEY_assign_RSA(pkey, rsa);
    }

    /* Assign all certificate fields */
    cert = X509_new();
    X509_set_version(cert, 2);
    set_serial128(cert);
    X509_gmtime_adj(X509_get_notBefore(cert), 0);
    X509_gmtime_adj(X509_get_notAfter(cert), certinfo.days * 24*60*60);
    X509_set_pubkey(cert, pkey);

    name = X509_get_subject_name(cert);
    if (certinfo.c[0]) {
        X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (unsigned char*)certinfo.c, -1, -1, 0);
    }
    X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (unsigned char*)certinfo.o, -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char*)certinfo.cn, -1, -1, 0);
    X509_NAME_add_entry_by_txt(name, "OU", MBSTRING_ASC, (unsigned char*)certinfo.ou, -1, -1, 0);
    if (certinfo.l[0]) {
        X509_NAME_add_entry_by_txt(name, "L", MBSTRING_ASC, (unsigned char *)certinfo.l, -1, -1, 0);
    }
    if (certinfo.st[0]) {
        X509_NAME_add_entry_by_txt(name, "ST", MBSTRING_ASC, (unsigned char *)certinfo.st, -1, -1, 0);
    }

    /* Set extensions according to profile */
    switch (certinfo.profile) {
        case PROFILE_ROOT_CA:
        /* CA profiles can issue certs and sign CRLS */
        set_extension(cert, cert, NID_basic_constraints, "critical,CA:TRUE");
        set_extension(cert, cert, NID_key_usage, "critical,keyCertSign,cRLSign");
        set_extension(cert, cert, NID_subject_key_identifier, "hash");
        set_extension(cert, cert, NID_authority_key_identifier, "keyid:always");
        break ;

        case PROFILE_SUB_CA:
        /* CA profiles can issue certs and sign CRLS */
        set_extension(ca.cert, cert, NID_basic_constraints, "critical,CA:TRUE");
        set_extension(ca.cert, cert, NID_key_usage, "critical,keyCertSign,cRLSign");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "keyid:always");
        break;

        case PROFILE_CLIENT:
        if (certinfo.san[0]) {
            set_extension(ca.cert, cert, NID_subject_alt_name, certinfo.san);
        }
        set_extension(ca.cert, cert, NID_basic_constraints, "CA:FALSE");
        set_extension(ca.cert, cert, NID_anyExtendedKeyUsage, "clientAuth");
        set_extension(ca.cert, cert, NID_key_usage, "digitalSignature");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "issuer:always,keyid:always");
        break ;

        case PROFILE_SERVER:
        if (certinfo.san[0]) {
            set_extension(ca.cert, cert, NID_subject_alt_name, certinfo.san);
        }
        set_extension(ca.cert, cert, NID_basic_constraints, "CA:FALSE");
        set_extension(ca.cert, cert, NID_netscape_cert_type, "server");
        set_extension(ca.cert, cert, NID_anyExtendedKeyUsage, "serverAuth");
        set_extension(ca.cert, cert, NID_key_usage, "digitalSignature,keyEncipherment");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "issuer:always,keyid:always");
        break ;

        case PROFILE_WWW:
        if (certinfo.san[0]) {
            set_extension(ca.cert, cert, NID_subject_alt_name, certinfo.san);
        }
        set_extension(ca.cert, cert, NID_basic_constraints, "CA:FALSE");
        set_extension(ca.cert, cert, NID_netscape_cert_type, "server");
        set_extension(ca.cert, cert, NID_anyExtendedKeyUsage, "serverAuth,clientAuth");
        set_extension(ca.cert, cert, NID_key_usage, "digitalSignature,keyEncipherment");
        set_extension(ca.cert, cert, NID_subject_key_identifier, "hash");
        set_extension(ca.cert, cert, NID_authority_key_identifier, "issuer:always,keyid:always");
        break;

        case PROFILE_UNKNOWN:
        default:
        break ;
    }
    /* Set issuer */
    if (certinfo.profile==PROFILE_ROOT_CA) {
        /* Self-signed */
        X509_set_issuer_name(cert, name);
        X509_sign(cert, pkey, EVP_sha256());
    } else {
        /* Signed by parent CA */
        X509_set_issuer_name(cert, X509_get_subject_name(ca.cert));
        X509_sign(cert, ca.key, EVP_sha256());
    }

    printf("Saving results to %s.[crt|key]\n", certinfo.cn);
    pem = fopen(filename, "wb");
    PEM_write_PrivateKey(pem, pkey, NULL, NULL, 0, NULL, NULL);
    fclose(pem);
    sprintf(filename, "%s.crt", certinfo.cn);
    pem = fopen(filename, "wb");
    PEM_write_X509(pem, cert);
    fclose(pem);
    X509_free(cert);
    EVP_PKEY_free(pkey);

    if (certinfo.profile!=PROFILE_ROOT_CA) {
        X509_free(ca.cert);
        EVP_PKEY_free(ca.key);
    }
    printf("done\n");

    return 0;
}
Esempio n. 28
0
long
post_connection_check (SSL * ssl, char *host)
{
  X509 *cert;
  X509_NAME *subj;
  char data[256];
  int extcount;
  int ok = 0;

  if (!(cert = SSL_get_peer_certificate (ssl)) || !host) 
	goto err_occured;
  
  if ((extcount = X509_get_ext_count (cert)) > 0)
    {
      int i;

      for (i = 0; i < extcount; i++)
	{
	  char *extstr;
	  X509_EXTENSION *ext;

	  ext = X509_get_ext (cert, i);
	  extstr =
	    (char *)
	    OBJ_nid2sn (OBJ_obj2nid (X509_EXTENSION_get_object (ext)));

	  if (!strcmp (extstr, "subjectAltName"))
	    {
	      int j;
	      unsigned char *data_;
	      STACK_OF (CONF_VALUE) * val;
	      CONF_VALUE *nval;
	      X509V3_EXT_METHOD *meth;
	      void *ext_str = NULL;

	      if (!(meth = X509V3_EXT_get (ext)))
		break;
	      data_ = ext->value->data;

#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
	      if (meth->it)
		ext_str = ASN1_item_d2i (NULL, &data_, ext->value->length,
					 ASN1_ITEM_ptr (meth->it));
	      else
		ext_str = meth->d2i (NULL, &data_, ext->value->length);
#else
	      ext_str = meth->d2i (NULL, &data_, ext->value->length);
#endif
	      val = meth->i2v (meth, ext_str, NULL);
	      for (j = 0; j < sk_CONF_VALUE_num (val); j++)
		{
		  nval = sk_CONF_VALUE_value (val, j);
		  if ((!strcmp (nval->name, "DNS")
		       && !strcmp (nval->value, host)) || (!strcmp (nval->name,
								   "IP Address")
							  && !strcmp (nval->
								      value,
								      host)))
		    {
			  ok = 1;
		      break;
		    }
		}
	    }
	  if (ok)
	    break;
	}
    }

  if (!ok && (subj = X509_get_subject_name (cert)) &&
      X509_NAME_get_text_by_NID (subj, NID_commonName, data, 256) > 0)
    {
      data[255] = 0;
      if (strcasecmp (data, host) != 0)
	goto err_occured;
    }

  X509_free (cert);
  return SSL_get_verify_result (ssl);

err_occured:
  if (cert)
    X509_free (cert);
  return X509_V_ERR_APPLICATION_VERIFICATION;
}
Esempio n. 29
0
char* crypto_cert_subject(X509* xcert)
{
	return crypto_print_name(X509_get_subject_name(xcert));
}
Esempio n. 30
0
int np_net_ssl_check_cert(int days_till_exp_warn, int days_till_exp_crit){
#  ifdef USE_OPENSSL
	X509 *certificate=NULL;
	X509_NAME *subj=NULL;
	char timestamp[50] = "";
	char cn[MAX_CN_LENGTH]= "";
	char *tz;
	
	int cnlen =-1;
	int status=STATE_UNKNOWN;

	ASN1_STRING *tm;
	int offset;
	struct tm stamp;
	float time_left;
	int days_left;
	int time_remaining;
	time_t tm_t;

	certificate=SSL_get_peer_certificate(s);
	if (!certificate) {
		printf("%s\n",_("CRITICAL - Cannot retrieve server certificate."));
		return STATE_CRITICAL;
	}

	/* Extract CN from certificate subject */
	subj=X509_get_subject_name(certificate);

	if (!subj) {
		printf("%s\n",_("CRITICAL - Cannot retrieve certificate subject."));
		return STATE_CRITICAL;
	}
	cnlen = X509_NAME_get_text_by_NID(subj, NID_commonName, cn, sizeof(cn));
	if (cnlen == -1)
		strcpy(cn, _("Unknown CN"));

	/* Retrieve timestamp of certificate */
	tm = X509_get_notAfter(certificate);

	/* Generate tm structure to process timestamp */
	if (tm->type == V_ASN1_UTCTIME) {
		if (tm->length < 10) {
			printf("%s\n", _("CRITICAL - Wrong time format in certificate."));
			return STATE_CRITICAL;
		} else {
			stamp.tm_year = (tm->data[0] - '0') * 10 + (tm->data[1] - '0');
			if (stamp.tm_year < 50)
				stamp.tm_year += 100;
			offset = 0;
		}
	} else {
		if (tm->length < 12) {
			printf("%s\n", _("CRITICAL - Wrong time format in certificate."));
			return STATE_CRITICAL;
		} else {
			stamp.tm_year =
				(tm->data[0] - '0') * 1000 + (tm->data[1] - '0') * 100 +
				(tm->data[2] - '0') * 10 + (tm->data[3] - '0');
			stamp.tm_year -= 1900;
			offset = 2;
		}
	}
	stamp.tm_mon =
		(tm->data[2 + offset] - '0') * 10 + (tm->data[3 + offset] - '0') - 1;
	stamp.tm_mday =
		(tm->data[4 + offset] - '0') * 10 + (tm->data[5 + offset] - '0');
	stamp.tm_hour =
		(tm->data[6 + offset] - '0') * 10 + (tm->data[7 + offset] - '0');
	stamp.tm_min =
		(tm->data[8 + offset] - '0') * 10 + (tm->data[9 + offset] - '0');
	stamp.tm_sec =
		(tm->data[10 + offset] - '0') * 10 + (tm->data[11 + offset] - '0');
	stamp.tm_isdst = -1;

	tm_t = timegm(&stamp);
	time_left = difftime(tm_t, time(NULL));
	days_left = time_left / 86400;
	tz = getenv("TZ");
	setenv("TZ", "GMT", 1);
	tzset();
	strftime(timestamp, 50, "%c %z", localtime(&tm_t));
	if (tz)
		setenv("TZ", tz, 1);
	else
		unsetenv("TZ");
	tzset();

	if (days_left > 0 && days_left <= days_till_exp_warn) {
		printf (_("%s - Certificate '%s' expires in %d day(s) (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", cn, days_left, timestamp);
		if (days_left > days_till_exp_crit)
			status = STATE_WARNING;
		else
			status = STATE_CRITICAL;
	} else if (days_left == 0 && time_left > 0) {
		if (time_left >= 3600)
			time_remaining = (int) time_left / 3600;
		else
			time_remaining = (int) time_left / 60;

		printf (_("%s - Certificate '%s' expires in %u %s (%s)\n"),
			(days_left>days_till_exp_crit) ? "WARNING" : "CRITICAL", cn, time_remaining,
			time_left >= 3600 ? "hours" : "minutes", timestamp);

		if ( days_left > days_till_exp_crit)
			status = STATE_WARNING;
		else
			status = STATE_CRITICAL;
	} else if (time_left < 0) {
		printf(_("CRITICAL - Certificate '%s' expired on %s.\n"), cn, timestamp);
		status=STATE_CRITICAL;
	} else if (days_left == 0) {
		printf (_("%s - Certificate '%s' just expired (%s).\n"), (days_left>days_till_exp_crit)?"WARNING":"CRITICAL", cn, timestamp);
		if (days_left > days_till_exp_crit)
			status = STATE_WARNING;
		else
			status = STATE_CRITICAL;
	} else {
		printf(_("OK - Certificate '%s' will expire on %s.\n"), cn, timestamp);
		status = STATE_OK;
	}
	X509_free(certificate);
	return status;
#  else /* ifndef USE_OPENSSL */
	printf("%s\n", _("WARNING - Plugin does not support checking certificates."));
	return STATE_WARNING;
#  endif /* USE_OPENSSL */
}