⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne_openssl.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 2 页
字号:
}/* Callback invoked when the SSL server requests a client certificate.  */static int provide_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey){    ne_ssl_context *ctx = SSL_get_app_data(ssl);    ne_session *sess = SSL_CTX_get_app_data(ctx->ctx);    if (!sess->client_cert && sess->ssl_provide_fn) {	ne_ssl_dname **dnames = NULL;        int n, count = 0;	STACK_OF(X509_NAME) *ca_list = SSL_get_client_CA_list(ssl);        count = ca_list ? sk_X509_NAME_num(ca_list) : 0;        if (count > 0) {            dnames = ne_malloc(count * sizeof(ne_ssl_dname *));                        for (n = 0; n < count; n++) {                dnames[n] = ne_malloc(sizeof(ne_ssl_dname));                dnames[n]->dn = sk_X509_NAME_value(ca_list, n);            }        }	NE_DEBUG(NE_DBG_SSL, "Calling client certificate provider...\n");	sess->ssl_provide_fn(sess->ssl_provide_ud, sess,                              (const ne_ssl_dname *const *)dnames, count);        if (count) {            for (n = 0; n < count; n++)                ne_free(dnames[n]);            ne_free(dnames);        }    }    if (sess->client_cert) {        ne_ssl_client_cert *const cc = sess->client_cert;	NE_DEBUG(NE_DBG_SSL, "Supplying client certificate.\n");	cc->pkey->references++;	cc->cert.subject->references++;	*cert = cc->cert.subject;	*pkey = cc->pkey;	return 1;    } else {	NE_DEBUG(NE_DBG_SSL, "No client certificate supplied.\n");	return 0;    }}void ne_ssl_set_clicert(ne_session *sess, const ne_ssl_client_cert *cc){    sess->client_cert = dup_client_cert(cc);}ne_ssl_context *ne_ssl_context_create(void){    ne_ssl_context *ctx = ne_malloc(sizeof *ctx);    ctx->ctx = SSL_CTX_new(SSLv23_client_method());    ctx->sess = NULL;    /* set client cert callback. */    SSL_CTX_set_client_cert_cb(ctx->ctx, provide_client_cert);    /* enable workarounds for buggy SSL server implementations */    SSL_CTX_set_options(ctx->ctx, SSL_OP_ALL);    return ctx;}void ne_ssl_context_destroy(ne_ssl_context *ctx){    SSL_CTX_free(ctx->ctx);    if (ctx->sess)        SSL_SESSION_free(ctx->sess);    ne_free(ctx);}/* For internal use only. */int ne_negotiate_ssl(ne_request *req){    ne_session *sess = ne_get_session(req);    ne_ssl_context *ctx = sess->ssl_context;    ne_ssl_socket *sock;    STACK_OF(X509) *chain;    int freechain = 0; /* non-zero if chain should be free'd. */    NE_DEBUG(NE_DBG_SSL, "Doing SSL negotiation.\n");    /* Rather a hack: link the ssl_context back to the ne_session, so     * provide_client_cert can get to the ne_session. */    SSL_CTX_set_app_data(ctx->ctx, sess);    if (ne_sock_connect_ssl(sess->socket, ctx)) {	if (ctx->sess) {	    /* remove cached session. */	    SSL_SESSION_free(ctx->sess);	    ctx->sess = NULL;	}	ne_set_error(sess, _("SSL negotiation failed: %s"),		     ne_sock_error(sess->socket));	return NE_ERROR;    }	        sock = ne_sock_sslsock(sess->socket);    chain = SSL_get_peer_cert_chain(sock->ssl);    /* For an SSLv2 connection, the cert chain will always be NULL. */    if (chain == NULL) {        X509 *cert = SSL_get_peer_certificate(sock->ssl);        if (cert) {            chain = sk_X509_new_null();            sk_X509_push(chain, cert);        }    }    if (chain == NULL || sk_X509_num(chain) == 0) {	ne_set_error(sess, _("SSL server did not present certificate"));	return NE_ERROR;    }    if (sess->server_cert) {        int diff = X509_cmp(sk_X509_value(chain, 0), sess->server_cert->subject);        if (freechain) sk_X509_free(chain); /* no longer need the chain */	if (diff) {	    /* This could be a MITM attack: fail the request. */	    ne_set_error(sess, _("Server certificate changed: "				 "connection intercepted?"));	    return NE_ERROR;	} 	/* certificate has already passed verification: no need to	 * verify it again. */    } else {	/* new connection: create the chain. */        ne_ssl_certificate *cert = make_chain(chain);        if (freechain) sk_X509_free(chain); /* no longer need the chain */	if (check_certificate(sess, sock->ssl, cert)) {	    NE_DEBUG(NE_DBG_SSL, "SSL certificate checks failed: %s\n",		     sess->error);	    ne_ssl_cert_free(cert);	    return NE_ERROR;	}	/* remember the chain. */        sess->server_cert = cert;    }        if (!ctx->sess) {	/* store the session. */	ctx->sess = SSL_get1_session(sock->ssl);    }    if (sess->notify_cb) {	sess->notify_cb(sess->notify_ud, ne_conn_secure,                        SSL_get_version(sock->ssl));    }    return NE_OK;}const ne_ssl_dname *ne_ssl_cert_issuer(const ne_ssl_certificate *cert){    return &cert->issuer_dn;}const ne_ssl_dname *ne_ssl_cert_subject(const ne_ssl_certificate *cert){    return &cert->subj_dn;}const ne_ssl_certificate *ne_ssl_cert_signedby(const ne_ssl_certificate *cert){    return cert->issuer;}const char *ne_ssl_cert_identity(const ne_ssl_certificate *cert){    return cert->identity;}void ne_ssl_ctx_trustcert(ne_ssl_context *ctx, const ne_ssl_certificate *cert){    X509_STORE *store = SSL_CTX_get_cert_store(ctx->ctx);        X509_STORE_add_cert(store, cert->subject);}void ne_ssl_trust_default_ca(ne_session *sess){    X509_STORE *store = SSL_CTX_get_cert_store(sess->ssl_context->ctx);        X509_STORE_set_default_paths(store);}/* Find a friendly name in a PKCS12 structure the hard way, without * decrypting the parts which are encrypted.. */static char *find_friendly_name(PKCS12 *p12){    STACK_OF(PKCS7) *safes = PKCS12_unpack_authsafes(p12);    int n, m;    char *name = NULL;    if (safes == NULL) return NULL;        /* Iterate over the unpacked authsafes: */    for (n = 0; n < sk_PKCS7_num(safes) && !name; n++) {        PKCS7 *safe = sk_PKCS7_value(safes, n);        STACK_OF(PKCS12_SAFEBAG) *bags;            /* Only looking for unencrypted authsafes. */        if (OBJ_obj2nid(safe->type) != NID_pkcs7_data) continue;        bags = PKCS12_unpack_p7data(safe);        if (!bags) continue;        /* Iterate through the bags, picking out a friendly name */        for (m = 0; m < sk_PKCS12_SAFEBAG_num(bags) && !name; m++) {            PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(bags, m);            name = PKCS12_get_friendlyname(bag);        }            sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free);    }    sk_PKCS7_pop_free(safes, PKCS7_free);    return name;}ne_ssl_client_cert *ne_ssl_clicert_read(const char *filename){    PKCS12 *p12;    FILE *fp;    X509 *cert;    EVP_PKEY *pkey;    ne_ssl_client_cert *cc;    fp = fopen(filename, "rb");    if (fp == NULL)        return NULL;    p12 = d2i_PKCS12_fp(fp, NULL);    fclose(fp);        if (p12 == NULL) {        ERR_clear_error();        return NULL;    }    /* Try parsing with no password. */    if (PKCS12_parse(p12, NULL, &pkey, &cert, NULL) == 1) {        /* Success - no password needed for decryption. */        unsigned int len = 0;        unsigned char *name = X509_alias_get0(cert, &len);                cc = ne_calloc(sizeof *cc);        cc->pkey = pkey;        cc->decrypted = 1;        if (name && len)            cc->friendly_name = ne_strndup((char *)name, len);        populate_cert(&cc->cert, cert);        PKCS12_free(p12);        return cc;    } else {        /* Failed to parse the file */        int err = ERR_get_error();        ERR_clear_error();        if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 &&            ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) {            /* Decryption error due to bad password. */            cc = ne_calloc(sizeof *cc);            cc->friendly_name = find_friendly_name(p12);            cc->p12 = p12;            return cc;        } else {            /* Some parse error, give up. */            PKCS12_free(p12);            return NULL;        }    }}int ne_ssl_clicert_encrypted(const ne_ssl_client_cert *cc){    return !cc->decrypted;}int ne_ssl_clicert_decrypt(ne_ssl_client_cert *cc, const char *password){    X509 *cert;    EVP_PKEY *pkey;    if (PKCS12_parse(cc->p12, password, &pkey, &cert, NULL) != 1) {        ERR_clear_error();        return -1;    }        PKCS12_free(cc->p12);    populate_cert(&cc->cert, cert);    cc->pkey = pkey;    cc->decrypted = 1;    cc->p12 = NULL;    return 0;}const ne_ssl_certificate *ne_ssl_clicert_owner(const ne_ssl_client_cert *cc){    return &cc->cert;}const char *ne_ssl_clicert_name(ne_ssl_client_cert *ccert){    return ccert->friendly_name;}ne_ssl_certificate *ne_ssl_cert_read(const char *filename){    FILE *fp = fopen(filename, "r");    X509 *cert;    if (fp == NULL)        return NULL;    cert = PEM_read_X509(fp, NULL, NULL, NULL);    fclose(fp);    if (cert == NULL) {        NE_DEBUG(NE_DBG_SSL, "d2i_X509_fp failed: %s\n",                  ERR_reason_error_string(ERR_get_error()));        ERR_clear_error();        return NULL;    }    return populate_cert(ne_calloc(sizeof(struct ne_ssl_certificate_s)), cert);}int ne_ssl_cert_write(const ne_ssl_certificate *cert, const char *filename){    FILE *fp = fopen(filename, "w");    if (fp == NULL) return -1;    if (PEM_write_X509(fp, cert->subject) != 1) {        ERR_clear_error();        fclose(fp);        return -1;    }        if (fclose(fp) != 0)        return -1;    return 0;}void ne_ssl_cert_free(ne_ssl_certificate *cert){    X509_free(cert->subject);    if (cert->issuer)        ne_ssl_cert_free(cert->issuer);    if (cert->identity)        ne_free(cert->identity);    ne_free(cert);}int ne_ssl_cert_cmp(const ne_ssl_certificate *c1, const ne_ssl_certificate *c2){    return X509_cmp(c1->subject, c2->subject);}/* The certificate import/export format is the base64 encoding of the * raw DER; PEM without the newlines and wrapping. */ne_ssl_certificate *ne_ssl_cert_import(const char *data){    unsigned char *der, *p;    size_t len;    X509 *x5;        /* decode the base64 to get the raw DER representation */    len = ne_unbase64(data, &der);    if (len == 0) return NULL;    p = der;    x5 = d2i_X509(NULL, &p, len); /* p is incremented */    ne_free(der);    if (x5 == NULL) {        ERR_clear_error();        return NULL;    }    return populate_cert(ne_calloc(sizeof(struct ne_ssl_certificate_s)), x5);}char *ne_ssl_cert_export(const ne_ssl_certificate *cert){    int len;    unsigned char *der, *p;        /* find the length of the DER encoding. */    len = i2d_X509(cert->subject, NULL);    p = der = ne_malloc(len);    i2d_X509(cert->subject, &p); /* p is incremented */    p = ne_base64(der, len);    ne_free(der);    return p;}#if SHA_DIGEST_LENGTH != 20# error SHA digest length is not 20 bytes#endifint ne_ssl_cert_digest(const ne_ssl_certificate *cert, char *digest){    unsigned char sha1[EVP_MAX_MD_SIZE];    unsigned int len, j;    char *p;    if (!X509_digest(cert->subject, EVP_sha1(), sha1, &len) || len != 20) {        ERR_clear_error();        return -1;    }        for (j = 0, p = digest; j < 20; j++) {        *p++ = NE_HEX2ASC((sha1[j] >> 4) & 0x0f);        *p++ = NE_HEX2ASC(sha1[j] & 0x0f);        *p++ = ':';    }    *--p = '\0';    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -