示例#1
0
/* Duplicate a client certificate, which must be in the decrypted state. */
static ne_ssl_client_cert *dup_client_cert(const ne_ssl_client_cert *cc)
{
    int ret;
    ne_ssl_client_cert *newcc = ne_calloc(sizeof *newcc);

    newcc->decrypted = 1;
    
    if (cc->keyless) {
        newcc->keyless = 1;
    }
    else {
        ret = gnutls_x509_privkey_init(&newcc->pkey);
        if (ret != 0) goto dup_error;
        
        ret = gnutls_x509_privkey_cpy(newcc->pkey, cc->pkey);
        if (ret != 0) goto dup_error;
    }    

    newcc->cert.subject = x509_crt_copy(cc->cert.subject);
    if (!newcc->cert.subject) goto dup_error;

    if (cc->friendly_name) newcc->friendly_name = ne_strdup(cc->friendly_name);

    populate_cert(&newcc->cert, newcc->cert.subject);
    return newcc;

dup_error:
    if (newcc->pkey) gnutls_x509_privkey_deinit(newcc->pkey);
    if (newcc->cert.subject) gnutls_x509_crt_deinit(newcc->cert.subject);
    ne_free(newcc);
    return NULL;
}    
示例#2
0
int ne_ssl_clicert_decrypt(ne_ssl_client_cert *cc, const char *password)
{
    int ret;
    gnutls_x509_crt cert = NULL;
    gnutls_x509_privkey pkey = NULL;

    if (gnutls_pkcs12_verify_mac(cc->p12, password) != 0) {
        return -1;
    }        

    ret = pkcs12_parse(cc->p12, &pkey, &cert, NULL, password);
    if (ret < 0)
        return ret;
    
    if (!cert || (!pkey && !cc->keyless)) {
        if (cert) gnutls_x509_crt_deinit(cert);
        if (pkey) gnutls_x509_privkey_deinit(pkey);
        return -1;
    }

    gnutls_pkcs12_deinit(cc->p12);
    populate_cert(&cc->cert, cert);
    cc->pkey = pkey;
    cc->decrypted = 1;
    cc->p12 = NULL;
    return 0;
}
示例#3
0
ne_ssl_certificate *ne_ssl_cert_import(const char *data)
{
    int ret;
    size_t len;
    unsigned char *der;
    gnutls_datum buffer = { NULL, 0 };
    gnutls_x509_crt x5;

    if (gnutls_x509_crt_init(&x5) != 0)
        return NULL;

    /* decode the base64 to get the raw DER representation */
    len = ne_unbase64(data, &der);
    if (len == 0) return NULL;

    buffer.data = der;
    buffer.size = len;

    ret = gnutls_x509_crt_import(x5, &buffer, GNUTLS_X509_FMT_DER);
    ne_free(der);

    if (ret < 0) {
        gnutls_x509_crt_deinit(x5);
        return NULL;
    }

    return populate_cert(ne_calloc(sizeof(struct ne_ssl_certificate_s)), x5);
}
示例#4
0
/* Return the certificate chain sent by the peer, or NULL on error. */
static ne_ssl_certificate *make_peers_chain(gnutls_session sock)
{
    ne_ssl_certificate *current = NULL, *top = NULL;
    const gnutls_datum *certs;
    unsigned int n, count;

    certs = gnutls_certificate_get_peers(sock, &count);
    if (!certs) {
        return NULL;
    }
    
    for (n = 0; n < count; n++) {
        ne_ssl_certificate *cert;
        gnutls_x509_crt x5;

        if (gnutls_x509_crt_init(&x5) ||
            gnutls_x509_crt_import(x5, &certs[n], GNUTLS_X509_FMT_DER)) {
            ne_ssl_cert_free(top);
            return NULL;
        }

        cert = populate_cert(ne_malloc(sizeof *cert), x5);
        
        if (top == NULL) {
            current = top = cert;
        } else {
            current->issuer = cert;
            current = cert;
        }
    }
    
    return top;
}
示例#5
0
ne_ssl_client_cert *ne_ssl_clicert_read(const char *filename)
{
    int ret;
    gnutls_datum data;
    gnutls_pkcs12 p12;
    ne_ssl_client_cert *cc;
    char *friendly_name = NULL;
    gnutls_x509_crt cert = NULL;
    gnutls_x509_privkey pkey = NULL;

    if (read_to_datum(filename, &data))
        return NULL;

    if (gnutls_pkcs12_init(&p12) != 0) {
        return NULL;
    }

    ret = gnutls_pkcs12_import(p12, &data, GNUTLS_X509_FMT_DER, 0);
    ne_free(data.data);
    if (ret < 0) {
        gnutls_pkcs12_deinit(p12);
        return NULL;
    }

    if (gnutls_pkcs12_verify_mac(p12, "") == 0) {
        if (pkcs12_parse(p12, &pkey, &cert, &friendly_name, "") != 0
            || !cert || !pkey) {
            gnutls_pkcs12_deinit(p12);
            return NULL;
        }

        cc = ne_calloc(sizeof *cc);
        cc->pkey = pkey;
        cc->decrypted = 1;
        cc->friendly_name = friendly_name;
        populate_cert(&cc->cert, cert);
        gnutls_pkcs12_deinit(p12);
        cc->p12 = NULL;
        return cc;
    } else {
        /* TODO: calling pkcs12_parse() here to find the friendly_name
         * seems to break horribly.  */
        cc = ne_calloc(sizeof *cc);
        cc->p12 = p12;
        return cc;
    }
}
示例#6
0
ne_ssl_certificate *ne_ssl_cert_read(const char *filename)
{
    int ret;
    gnutls_datum data;
    gnutls_x509_crt x5;

    if (read_to_datum(filename, &data))
        return NULL;

    if (gnutls_x509_crt_init(&x5) != 0)
        return NULL;

    ret = gnutls_x509_crt_import(x5, &data, GNUTLS_X509_FMT_PEM);
    ne_free(data.data);
    if (ret < 0) {
        gnutls_x509_crt_deinit(x5);
        return NULL;
    }
    
    return populate_cert(ne_calloc(sizeof(struct ne_ssl_certificate_s)), x5);
}
示例#7
0
ne_ssl_client_cert *ne__ssl_clicert_exkey_import(const unsigned char *der,
                                                 size_t der_len)
{
    ne_ssl_client_cert *cc;
    gnutls_x509_crt x5;
    gnutls_datum datum;

    datum.data = (unsigned char *)der;
    datum.size = der_len;    

    if (gnutls_x509_crt_init(&x5) 
        || gnutls_x509_crt_import(x5, &datum, GNUTLS_X509_FMT_DER)) {
        NE_DEBUG(NE_DBG_SSL, "ssl: crt_import failed.\n");
        return NULL;
    }
    
    cc = ne_calloc(sizeof *cc);
    cc->keyless = 1;
    cc->decrypted = 1;
    populate_cert(&cc->cert, x5);

    return cc;    
}
示例#8
0
/* Return the certificate chain sent by the peer, or NULL on error. */
static ne_ssl_certificate *make_peers_chain(gnutls_session sock,
                                            gnutls_certificate_credentials crd)
{
    ne_ssl_certificate *current = NULL, *top = NULL;
    const gnutls_datum *certs;
    unsigned int n, count;
    ne_ssl_certificate *cert;

    certs = gnutls_certificate_get_peers(sock, &count);
    if (!certs) {
        return NULL;
    }

    NE_DEBUG(NE_DBG_SSL, "ssl: Got %u certs in peer chain.\n", count);
    
    for (n = 0; n < count; n++) {
        gnutls_x509_crt x5;

        if (gnutls_x509_crt_init(&x5) ||
            gnutls_x509_crt_import(x5, &certs[n], GNUTLS_X509_FMT_DER)) {
            if (top) {
                ne_ssl_cert_free(top);
            }
            return NULL;
        }

        cert = populate_cert(ne_calloc(sizeof *cert), x5);
        
        if (top == NULL) {
            current = top = cert;
        } else {
            current->issuer = cert;
            current = cert;
        }
    }

#ifdef HAVE_GNUTLS_CERTIFICATE_GET_X509_CAS
    /* GnuTLS only returns the peers which were *sent* by the server
     * in the Certificate list during the handshake.  Fill in the
     * complete chain manually against the certs we trust: */
    if (current->issuer == NULL) {
        gnutls_x509_crt issuer;
        gnutls_x509_crt *ca_list;
        unsigned int num_cas;
        
        gnutls_certificate_get_x509_cas(crd, &ca_list, &num_cas);

        do { 
            /* Look up the issuer. */
            issuer = find_issuer(ca_list, num_cas, current->subject);
            if (issuer) {
                issuer = x509_crt_copy(issuer);
                cert = populate_cert(ne_calloc(sizeof *cert), issuer);
                /* Check that the issuer does not match the current
                 * cert. */
                if (ne_ssl_cert_cmp(current, cert)) {
                    current = current->issuer = cert;
                }
                else {
                    ne_ssl_cert_free(cert);
                    issuer = NULL;
                }
            }
        } while (issuer);
    }
#endif
    
    return top;
}
示例#9
0
ne_ssl_client_cert *SSL_X509_Pem_Read(const std::string & pkeyfile_str, const std::string & credfile_str,
                                      const std::string & password_str, DavixError** err){
    FILE *fp;
    BIO* in=NULL;
    X509 *cert,*ca;
    STACK_OF(X509)* chain = NULL;
    EVP_PKEY *pkey;
    ne_ssl_client_cert *cc=NULL;
    int len, errcode;
    const char * pkeyfile = pkeyfile_str.c_str(), *credfile = credfile_str.c_str(), *password = password_str.c_str();
    unsigned char* name;


    if( pkeyfile ==NULL || credfile ==NULL || ((in = BIO_new(BIO_s_file())) == NULL)){
        DavixError::setupError(err, openssl_scope, StatusCode::UnknowError, "init error");
        return NULL;
    }

    // load cred
    if (BIO_read_filename(in, credfile) <= 0){
        std::ostringstream msg;
        msg << "impossible to open " << credfile << ": ";
        opensslErrorMapper(msg.str(), err);
        ERR_clear_error();
        BIO_free(in);
        return NULL;

    }
    if ( (cert = PEM_read_bio_X509(in, NULL, SSL_pem_passwd_cb, (void*) password)) == NULL){
        std::ostringstream msg;
        msg << "parse PEM credential failed " << credfile << ": ";
        opensslErrorMapper(msg.str(), err);
        ERR_clear_error();
        BIO_free(in);
        return NULL;
    }

    // load chain
    chain = sk_X509_new_null();
    while ((ca = PEM_read_bio_X509(in,NULL, SSL_pem_passwd_cb, (void*) password))
                != NULL){
        sk_X509_push(chain, ca);
    }
            /* When the while loop ends, it's usually just EOF. */
    BIO_free(in);
    errcode = ERR_peek_last_error();
    if (ERR_GET_LIB(errcode) == ERR_LIB_PEM && ERR_GET_REASON(errcode) == PEM_R_NO_START_LINE){
        ERR_clear_error();
    }else{
        opensslErrorMapper(" parse PEM credential chain failed ", err);
        ERR_clear_error();
        X509_free(cert);
        return NULL;
    }

    // load pkey
    fp = fopen(pkeyfile, "rb");
    if (fp == NULL){
        std::ostringstream ss;
        ss << "Impossible to open " << pkeyfile << " : " << strerror(errno);
        DavixError::setupError(err, openssl_scope, StatusCode::CredentialNotFound, ss.str());
        errno = 0;
        X509_free(cert);
        return NULL;
    }
    if ( (pkey = PEM_read_PrivateKey(fp, NULL, SSL_pem_passwd_cb,  (void*) password)) == NULL){
        opensslErrorMapper(std::string("parse PEM private key failed ").append(pkeyfile), err);
        ERR_clear_error();
        X509_free(cert);
        return NULL;
    }
    fclose(fp);

    // load ca chain


    name = X509_alias_get0(cert, &len);
    cc = (ne_ssl_client_cert*) calloc(sizeof(ne_ssl_client_cert),1);
    cc->pkey = pkey;
    cc->decrypted = 1;
    if (name && len > 0)
        cc->friendly_name = strndup((char *)name, len);
    populate_cert(&cc->cert, cert);
    cc->cert.chain = chain;
    return cc;

}