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

📄 ssl.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
/*    neon test suite   Copyright (C) 2002-2004, Joe Orton <joe@manyfish.co.uk>   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.     This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.     You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "config.h"#include <sys/types.h>#include <sys/stat.h>#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#include "ne_request.h"#include "ne_socket.h"#include "ne_auth.h"#include "tests.h"#include "child.h"#include "utils.h"#ifndef NEON_SSL/* this file shouldn't be built if SSL is not enabled. */#error SSL not supported#endif#include <openssl/ssl.h>#include <openssl/err.h>#include <openssl/evp.h>#define ERROR_SSL_STRING (ERR_reason_error_string(ERR_get_error()))#define SERVER_CERT "server.cert"#define CA_CERT "ca/cert.pem"#define SERVER_DNAME "Neon QA Dept, Neon Hackers Ltd, " \                     "Cambridge, Cambridgeshire, GB"#define CACERT_DNAME "Random Dept, Neosign, Oakland, California, US"static char *srcdir = ".";static char *server_key = NULL; static ne_ssl_certificate *def_ca_cert = NULL, *def_server_cert;static ne_ssl_client_cert *def_cli_cert;static int check_dname(const ne_ssl_dname *dn, const char *expected,                       const char *which);static int s_strwrite(SSL *s, const char *buf){    size_t len = strlen(buf);        ONV(SSL_write(s, buf, len) != (int)len,	("SSL_write failed: %s", ERROR_SSL_STRING));    return OK;}/* Arguments for running the SSL server */struct ssl_server_args {    char *cert; /* the server cert to present. */    const char *response; /* the response to send. */    int unclean; /* use an unclean shutdown if non-NULL */    int numreqs; /* number of request/responses to handle over the SSL connection. */    /* client cert handling: */    int require_cc; /* require a client cert if non-NULL */    const char *ca_list; /* file of CA certs to verify client cert against */    const char *send_ca; /* file of CA certs to send in client cert request */        /* session caching: */    int cache; /* use the session cache if non-zero */    SSL_SESSION *session; /* use to store copy of cached session. */    int count; /* internal use. */    int use_ssl2; /* force use of SSLv2 only */};/* default response string if args->response is NULL */#define DEF_RESP "HTTP/1.0 200 OK\r\nContent-Length: 0\r\n\r\n"/* An SSL server inna bun. */static int ssl_server(ne_socket *sock, void *userdata){    struct ssl_server_args *args = userdata;    int fd = ne_sock_fd(sock), ret;    /* we don't want OpenSSL to close this socket for us. */    BIO *bio = BIO_new_socket(fd, BIO_NOCLOSE);    char buf[BUFSIZ];    SSL *ssl;    static SSL_CTX *ctx = NULL;    if (ctx == NULL) {        ctx = SSL_CTX_new(args->use_ssl2 ? SSLv2_server_method()                          : SSLv23_server_method());    }    ONV(ctx == NULL,	("could not create SSL_CTX: %s", ERROR_SSL_STRING));    ONV(!SSL_CTX_use_PrivateKey_file(ctx, server_key, SSL_FILETYPE_PEM),         ("failed to load private key: %s", ERROR_SSL_STRING));    NE_DEBUG(NE_DBG_HTTP, "using server cert %s\n", args->cert);    ONN("failed to load certificate",	!SSL_CTX_use_certificate_file(ctx, args->cert, SSL_FILETYPE_PEM));    if (args->require_cc) {        /* require a client cert. */        SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER |                            SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL);         if (args->send_ca) {            /* the list of issuer DNs of these CAs is included in the            * certificate request message sent to the client */            SSL_CTX_set_client_CA_list(ctx,                                        SSL_load_client_CA_file(args->send_ca));        }        /* set default ca_list */        if (!args->ca_list) args->ca_list = CA_CERT;    }        if (args->ca_list) {        /* load the CA used to verify the client cert; also sent in the         * certificate exchange message. */        ONN("failed to load CA cert",            SSL_CTX_load_verify_locations(ctx, args->ca_list, NULL) != 1);    }    if (args->cache && args->count == 0) {	/* enable OpenSSL's internal session cache, enabling the	 * negotiation to re-use a session if both sides support it. */	SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);    }    ssl = SSL_new(ctx);    ONN("SSL_new failed", ssl == NULL);    args->count++;    SSL_set_bio(ssl, bio, bio);    ONV(SSL_accept(ssl) != 1,	("SSL_accept failed: %s", ERROR_SSL_STRING));    /* loop handling requests: */    do {        const char *response = args->response ? args->response : DEF_RESP;        ret = SSL_read(ssl, buf, BUFSIZ - 1);        if (ret == 0)            return 0; /* connection closed by parent; give up. */        ONV(ret < 0, ("SSL_read failed (%d): %s", ret, ERROR_SSL_STRING));                buf[ret] = '\0';                NE_DEBUG(NE_DBG_HTTP, "Request over SSL was: [%s]\n", buf);                if (strstr(buf, "Proxy-Authorization:") != NULL) {            NE_DEBUG(NE_DBG_HTTP, "Got Proxy-Auth header over SSL!\n");            response = "HTTP/1.1 500 Client Leaks Credentials\r\n"                "Content-Length: 0\r\n" "\r\n";        }                CALL(s_strwrite(ssl, response));            } while (--args->numreqs > 0);    /* copy out the session if requested. */    if (args->session) {        SSL_SESSION *sess = SSL_get1_session(ssl);#ifdef NE_DEBUGGING        /* dump session to child.log for debugging. */        SSL_SESSION_print_fp(ne_debug_stream, sess);#endif        if (args->count == 0) {            /* save the session */            args->session = sess;        } else {            /* could just to do this with SSL_CTX_sess_hits really,             * but this is a more thorough test. */            ONN("cached SSL session not used",                SSL_SESSION_cmp(args->session, sess));            SSL_SESSION_free(args->session);            SSL_SESSION_free(sess);        }    }	        if (!args->unclean) {	/* Erk, shutdown is messy! See Eric Rescorla's article:	 * http://www.linuxjournal.com/article.php?sid=4822 ; we'll just	 * hide our heads in the sand here. */	SSL_shutdown(ssl);	SSL_free(ssl);    }    return 0;}/* serve_ssl wrapper which ignores server failure and always succeeds */static int fail_serve(ne_socket *sock, void *ud){    struct ssl_server_args args = {0};    args.cert = ud;    ssl_server(sock, &args);    return OK;}#define DEFSESS  (ne_session_create("https", "localhost", 7777))/* Run a request in the given session. */static int any_ssl_request(ne_session *sess, server_fn fn, void *server_ud,			   char *ca_cert,			   ne_ssl_verify_fn verify_fn, void *verify_ud){    int ret;        if (ca_cert) {        ne_ssl_certificate *ca = ne_ssl_cert_read(ca_cert);        ONV(ca == NULL, ("could not load CA cert `%s'", ca_cert));        ne_ssl_trust_cert(sess, ca);        ne_ssl_cert_free(ca);    }    CALL(spawn_server(7777, fn, server_ud));    if (verify_fn)	ne_ssl_set_verify(sess, verify_fn, verify_ud);    ret = any_request(sess, "/foo");    CALL(await_server());        ONREQ(ret);    return OK;}static int init(void){    /* take srcdir as argv[1]. */    if (test_argc > 1) {	srcdir = test_argv[1];	server_key = ne_concat(srcdir, "/server.key", NULL);    } else {	server_key = "server.key";    }        if (ne_sock_init()) {	t_context("could not initialize socket/SSL library.");	return FAILHARD;    }    def_ca_cert = ne_ssl_cert_read(CA_CERT);    if (def_ca_cert == NULL) {        t_context("couldn't load CA cert %s", CA_CERT);        return FAILHARD;    }    def_server_cert = ne_ssl_cert_read(SERVER_CERT);    if (def_server_cert == NULL) {        t_context("couldn't load server cert %s", SERVER_CERT);        return FAILHARD;    }        /* tests for the encrypted client cert, client.p12 */    def_cli_cert = ne_ssl_clicert_read("client.p12");    ONN("could not load client.p12", def_cli_cert == NULL);    ONN("client.p12 is not encrypted!?",         !ne_ssl_clicert_encrypted(def_cli_cert));        ONN("failed to decrypt client.p12",        ne_ssl_clicert_decrypt(def_cli_cert, "foobar"));    return OK;}/* just check the result codes of loading server certs. */static int load_server_certs(void){    ne_ssl_certificate *cert;    cert = ne_ssl_cert_read("Makefile");    ONN("invalid CA cert file loaded successfully", cert != NULL);    cert = ne_ssl_cert_read("nonesuch.pem");    ONN("non-existent 'nonesuch.pem' loaded successfully", cert != NULL);    cert = ne_ssl_cert_read("ssigned.pem");    ONN("could not load ssigned.pem", cert == NULL);    ne_ssl_cert_free(cert);    return OK;}static int trust_default_ca(void){    ne_session *sess = DEFSESS;    ne_ssl_trust_default_ca(sess);    ne_session_destroy(sess);    return OK;}#define CC_NAME "Just A Neon Client Cert"/* Tests for loading client certificates */static int load_client_cert(void){    ne_ssl_client_cert *cc;    const ne_ssl_certificate *cert;    const char *name;    cc = ne_ssl_clicert_read("client.p12");    ONN("could not load client.p12", cc == NULL);    ONN("client.p12 not encrypted!?", !ne_ssl_clicert_encrypted(cc));    name = ne_ssl_clicert_name(cc);    ONN("no friendly name given", name == NULL);    ONV(strcmp(name, CC_NAME), ("friendly name was %s not %s", name, CC_NAME));    ONN("failed to decrypt", ne_ssl_clicert_decrypt(cc, "foobar"));    ne_ssl_clicert_free(cc);    cc = ne_ssl_clicert_read("client.p12");    ONN("decrypted client.p12 with incorrect password!?",        ne_ssl_clicert_decrypt(cc, "barfoo") == 0);    ne_ssl_clicert_free(cc);    /* tests for the unencrypted client cert, client2.p12 */    cc = ne_ssl_clicert_read("unclient.p12");    ONN("could not load unencrypted cert unclient.p12", cc == NULL);    ONN("unencrypted cert marked encrypted?", ne_ssl_clicert_encrypted(cc));    cert = ne_ssl_clicert_owner(cc);    ONN("client cert had no certificate", cert == NULL);    CALL(check_dname(ne_ssl_cert_subject(cert),                     "Neon Client Cert, Neon Hackers Ltd, "                     "Cambridge, Cambridgeshire, GB",                     "client cert subject"));    CALL(check_dname(ne_ssl_cert_issuer(cert), CACERT_DNAME,                      "client cert issuer"));    ne_ssl_clicert_free(cc);    /* test for ccert without a friendly name, noclient.p12 */    cc = ne_ssl_clicert_read("noclient.p12");    ONN("could not load noclient.p12", cc == NULL);    name = ne_ssl_clicert_name(cc);    ONV(name != NULL, ("noclient.p12 had friendly name `%s'", name));    ne_ssl_clicert_free(cc);    /* tests for loading bogus files. */    cc = ne_ssl_clicert_read("Makefile");    ONN("loaded Makefile as client cert!?", cc != NULL);    /* test for loading nonexistent file. */    cc = ne_ssl_clicert_read("nosuch.pem");    ONN("loaded nonexistent file as client cert!?", cc != NULL);    return OK;}/* Test that 'cert', which is signed by CA_CERT, is accepted * unconditionaly. */static int accept_signed_cert_for_hostname(char *cert, const char *hostname){    ne_session *sess = ne_session_create("https", hostname, 7777);    struct ssl_server_args args = {cert, 0};    /* no verify callback needed. */    CALL(any_ssl_request(sess, ssl_server, &args, CA_CERT, NULL, NULL));    ne_session_destroy(sess);    return OK;}static int accept_signed_cert(char *cert){    return accept_signed_cert_for_hostname(cert, "localhost");}static int simple(void){    return accept_signed_cert(SERVER_CERT);}/* Test for SSL operation when server uses SSLv2 */static int simple_sslv2(void){    ne_session *sess = ne_session_create("https", "localhost", 7777);    struct ssl_server_args args = {SERVER_CERT, 0};    args.use_ssl2 = 1;    CALL(any_ssl_request(sess, ssl_server, &args, CA_CERT, NULL, NULL));    ne_session_destroy(sess);    return OK;}/* Serves using HTTP/1.0 get-till-EOF semantics. */static int serve_eof(ne_socket *sock, void *ud){    struct ssl_server_args args = {0};    args.cert = ud;    args.response = "HTTP/1.0 200 OK\r\n"        "Connection: close\r\n"        "\r\n"        "This is a response body, like it or not.";    return ssl_server(sock, &args);}/* Test read-til-EOF behaviour with SSL. */static int simple_eof(void){    ne_session *sess = DEFSESS;    CALL(any_ssl_request(sess, serve_eof, SERVER_CERT, CA_CERT, NULL, NULL));    ne_session_destroy(sess);    return OK;}static int empty_truncated_eof(void){    ne_session *sess = DEFSESS;    struct ssl_server_args args = {0};    args.cert = SERVER_CERT;    args.response = "HTTP/1.0 200 OK\r\n" "\r\n";        CALL(any_ssl_request(sess, ssl_server, &args, CA_CERT, NULL, NULL));    ne_session_destroy(sess);    return OK;}/* Server function which just sends a string then EOF. */static int just_serve_string(ne_socket *sock, void *userdata){    const char *str = userdata;    server_send(sock, str, strlen(str));    return 0;}/* test for the SSL negotiation failing. */static int fail_not_ssl(void){    ne_session *sess = DEFSESS;    int ret;        CALL(spawn_server(7777, just_serve_string, "Hello, world.\n"));    ret = any_request(sess, "/bar");    CALL(await_server());    ONN("request did not fail", ret != NE_ERROR);    ne_session_destroy(sess);    return OK;}static int wildcard_ok = 0;    static int wildcard_init(void){    struct stat stbuf;        t_context("wildcard.cert not found:\n"	      "This test requires a Linux-like hostname command, see makekeys.sh");    PRECOND(stat("wildcard.cert", &stbuf) == 0);    PRECOND(lookup_hostname() == OK);    wildcard_ok = 1;    return OK;}static int wildcard_match(void){    ne_session *sess;    struct ssl_server_args args = {"wildcard.cert", 0};    PRECOND(wildcard_ok);        sess = ne_session_create("https", local_hostname, 7777);    CALL(any_ssl_request(sess, ssl_server, &args, CA_CERT, NULL, NULL));    ne_session_destroy(sess);        return OK;}/* Check that hostname comparisons are not cases-sensitive. */static int caseless_match(void){    return accept_signed_cert("caseless.cert");}/* Test that the subjectAltName extension has precedence over the * commonName attribute */static int subject_altname(void)

⌨️ 快捷键说明

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