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

📄 ssl.c

📁 linux subdivision ying gai ke yi le ba
💻 C
📖 第 1 页 / 共 3 页
字号:
#define RESP_0LENGTH "HTTP/1.1 200 OK\r\n" "Content-Length: 0\r\n" "\r\n"/* a tricky test which requires spawning a second server process in * time for a new connection after a 407. */static int apt_post_send(ne_request *req, void *ud, const ne_status *st){    int *code = ud;    if (st->code == *code) {        struct ssl_server_args args = {SERVER_CERT, NULL};            if (*code == 407) args.numreqs = 2;        args.response = RESP_0LENGTH;        NE_DEBUG(NE_DBG_HTTP, "Got challenge, awaiting server...\n");        CALL(await_server());        NE_DEBUG(NE_DBG_HTTP, "Spawning proper tunnel server...\n");        /* serve *two* 200 OK responses. */        CALL(spawn_server(7777, serve_tunnel, &args));        NE_DEBUG(NE_DBG_HTTP, "Spawned.\n");    }    return OK;}static int apt_creds(void *userdata, const char *realm, int attempt,                     char *username, char *password){    strcpy(username, "foo");    strcpy(password, "bar");    return attempt;}/* Test for using SSL over a CONNECT tunnel via a proxy server which * requires authentication.  Broke briefly between 0.23.x and * 0.24.0. */static int auth_proxy_tunnel(void){    ne_session *sess = ne_session_create("https", "localhost", 443);    int ret, code = 407;        ne_session_proxy(sess, "localhost", 7777);    ne_hook_post_send(sess, apt_post_send, &code);    ne_set_proxy_auth(sess, apt_creds, NULL);    ne_ssl_trust_cert(sess, def_ca_cert);        CALL(spawn_server(7777, single_serve_string,                      "HTTP/1.0 407 I WANT MORE BISCUITS\r\n"                      "Proxy-Authenticate: Basic realm=\"bigbluesea\"\r\n"                      "Connection: close\r\n" "\r\n"));        /* run two requests over the tunnel. */    ret = any_2xx_request(sess, "/foobar");    if (!ret) ret = any_2xx_request(sess, "/foobar2");    CALL(await_server());    CALL(ret);    ne_session_destroy(sess);    return 0;}/* Regression test to check that server credentials aren't sent to the * proxy in a CONNECT request. */static int auth_tunnel_creds(void){    ne_session *sess = ne_session_create("https", "localhost", 443);    int ret, code = 401;    struct ssl_server_args args = {SERVER_CERT, 0};        ne_session_proxy(sess, "localhost", 7777);    ne_hook_post_send(sess, apt_post_send, &code);    ne_set_server_auth(sess, apt_creds, NULL);    ne_ssl_trust_cert(sess, def_ca_cert);        args.response = "HTTP/1.1 401 I want a Shrubbery\r\n"        "WWW-Authenticate: Basic realm=\"bigredocean\"\r\n"        "Server: Python\r\n" "Content-Length: 0\r\n" "\r\n";        CALL(spawn_server(7777, serve_tunnel, &args));    ret = any_2xx_request(sess, "/foobar");    CALL(await_server());    CALL(ret);    ne_session_destroy(sess);    return OK;    }/* compare against known digest of notvalid.pem.  Via: *   $ openssl x509 -fingerprint -sha1 -noout -in notvalid.pem */#define THE_DIGEST "cf:5c:95:93:76:c6:3c:01:8b:62:" \                   "b1:6f:f7:7f:42:32:ac:e6:69:1b"static int cert_fingerprint(void){    char *fn = ne_concat(srcdir, "/notvalid.pem", NULL);    ne_ssl_certificate *cert = ne_ssl_cert_read(fn);    char digest[60];        ne_free(fn);    ONN("could not load notvalid.pem", cert == NULL);    ONN("failed to digest", ne_ssl_cert_digest(cert, digest));    ne_ssl_cert_free(cert);    ONV(strcmp(digest, THE_DIGEST),        ("digest was %s not %s", digest, THE_DIGEST));    return OK;}/* verify that identity of certificate in filename 'fname' is 'identity' */static int check_identity(const char *fname, const char *identity){    ne_ssl_certificate *cert = ne_ssl_cert_read(fname);    const char *id;    ONV(cert == NULL, ("could not read cert `%s'", fname));    id = ne_ssl_cert_identity(cert);    if (identity) {        ONV(id == NULL, ("certificate `%s' had no identity", fname));        ONV(strcmp(id, identity),             ("certificate `%s' had identity `%s' not `%s'", fname,              id, identity));    } else {        ONV(id != NULL, ("certificate `%s' had identity `%s' (expected none)",                         fname, id));    }                    ne_ssl_cert_free(cert);    return OK;}/* check certificate identities. */static int cert_identities(void){    static const struct {        const char *fname, *identity;    } certs[] = {        { "twocn.cert", "localhost" },        { "altname1.cert", "localhost" },        { "altname2.cert", "nohost.example.com" },        { "altname4.cert", "localhost" },        { "ca4.pem", "fourth.example.com" },        { NULL, NULL }    };    int n;    for (n = 0; certs[n].fname != NULL; n++)        CALL(check_identity(certs[n].fname, certs[n].identity));    return OK;}static int check_validity(const char *fname,                          const char *from, const char *until){    char actfrom[NE_SSL_VDATELEN], actuntil[NE_SSL_VDATELEN];    ne_ssl_certificate *cert;    cert = ne_ssl_cert_read(fname);    ONV(cert == NULL, ("could not load cert `%s'", fname));    /* cover all calling combos for nice coverage analysis */    ne_ssl_cert_validity(cert, NULL, NULL);    ne_ssl_cert_validity(cert, actfrom, NULL);    ne_ssl_cert_validity(cert, NULL, actuntil);    ne_ssl_cert_validity(cert, actfrom, actuntil);    ONV(strcmp(actfrom, from),         ("%s: start time was `%s' not `%s'", fname, actfrom, from));    ONV(strcmp(actuntil, until),         ("%s: end time was `%s' not `%s'", fname, actuntil, until));    ne_ssl_cert_free(cert);    return OK;}/* ceritificate validity times. */static int cert_validity(void){    char *cert = ne_concat(srcdir, "/expired.pem", NULL);    CALL(check_validity(cert, "Jan 21 20:39:04 2002 GMT", "Jan 31 20:39:04 2002 GMT"));    ne_free(cert);    cert = ne_concat(srcdir, "/notvalid.pem", NULL);    CALL(check_validity(cert, "Dec 27 20:40:29 2023 GMT", "Dec 28 20:40:29 2023 GMT"));    ne_free(cert);    return OK;}/* dname comparisons. */static int dname_compare(void){    ne_ssl_certificate *ssigned;    const ne_ssl_dname *dn1, *dn2;        dn1 = ne_ssl_cert_subject(def_server_cert);    dn2 = ne_ssl_cert_subject(def_server_cert);    ONN("identical subject names not equal", ne_ssl_dname_cmp(dn1, dn2) != 0);    dn2 = ne_ssl_cert_issuer(def_server_cert);    ONN("issuer and subject names equal for signed cert",        ne_ssl_dname_cmp(dn1, dn2) == 0);        dn1 = ne_ssl_cert_subject(def_ca_cert);    ONN("issuer of signed cert not equal to subject of CA cert",        ne_ssl_dname_cmp(dn1, dn2) != 0);    ssigned = ne_ssl_cert_read("ssigned.pem");    ONN("could not load ssigned.pem", ssigned == NULL);    dn1 = ne_ssl_cert_subject(ssigned);    dn2 = ne_ssl_cert_issuer(ssigned);    ONN("issuer and subject names not equal for self-signed cert",        ne_ssl_dname_cmp(dn1, dn2));    ne_ssl_cert_free(ssigned);    return OK;}/* The dname with the UTF-8 encoding of the Unicode string:  * "H<LATIN SMALL LETTER E WITH GRAVE>llo World". */#define I18N_DNAME "H\xc3\xa8llo World, Neon Hackers Ltd, Cambridge, Cambridgeshire, GB"/* N.B. t61subj.cert encodes an ISO-8859-1 string in a T61String * field, which is strictly wrong but the common usage. *//* tests for ne_ssl_readable_dname */static int dname_readable(void){    struct {        const char *cert;        const char *subjdn, *issuerdn;    } ts[] = {        { "justmail.cert", "blah@example.com", NULL },        { "t61subj.cert", I18N_DNAME, NULL },        { "bmpsubj.cert", I18N_DNAME, NULL },        { "utf8subj.cert", I18N_DNAME, NULL }    };    size_t n;    for (n = 0; n < sizeof(ts)/sizeof(ts[0]); n++) {        ne_ssl_certificate *cert = ne_ssl_cert_read(ts[n].cert);        ONV(cert == NULL, ("could not load cert %s", ts[n].cert));        CALL(check_cert_dnames(cert, ts[n].subjdn, ts[n].issuerdn));        ne_ssl_cert_free(cert);    }    return OK;}/* test cert comparisons */static int cert_compare(void){    ne_ssl_certificate *c1, *c2;    c1 = ne_ssl_cert_read("server.cert");    c2 = ne_ssl_cert_read("server.cert");    ONN("identical certs don't compare equal", ne_ssl_cert_cmp(c1, c2) != 0);    ONN("identical certs don't compare equal", ne_ssl_cert_cmp(c2, c1) != 0);    ne_ssl_cert_free(c2);    c2 = ne_ssl_cert_read("ssigned.pem");    ONN("different certs don't compare different",        ne_ssl_cert_cmp(c1, c2) == 0);    ONN("different certs don't compare different",        ne_ssl_cert_cmp(c2, c1) == 0);    ne_ssl_cert_free(c2);    ne_ssl_cert_free(c1);    return OK;}/* Extract raw base64 string from a PEM file */static int flatten_pem(const char *fname, char **out){    FILE *fp = fopen(fname, "r");    char buf[80];    size_t outlen = 0;    int ignore = 1;    ONV(fp == NULL, ("could not open %s", fname));    *out = NULL;    while (fgets(buf, sizeof buf, fp) != NULL) {        size_t len = strlen(buf) - 1;                if (len < 1) continue;        /* look for the wrapper lines. */        if (strncmp(buf, "-----", 5) == 0) {            ignore = !ignore;            continue;        }        /* ignore until the first wrapper line */        if (ignore) continue;                *out = realloc(*out, outlen + len + 1);        memcpy(*out + outlen, buf, len);        outlen += len;    }    (*out)[outlen] = '\0';    fclose(fp);    return OK;}/* check export cert data 'actual' against expected data 'expected */static int check_exported_data(const char *actual, const char *expected){    ONN("could not export cert", actual == NULL);    ONN("export data contained newline",        strchr(actual, '\r') || strchr(actual, '\n'));            ONV(strcmp(actual, expected), ("exported cert differed from expected:\n"                                   "actual: %s\nexpected: %s",                                    actual, expected));    return OK;}/* Test import and export of certificates.  The export format is PEM * without the line feeds and wrapping; compare against . */static int import_export(void){    char *expected, *actual;    ne_ssl_certificate *cert, *imp;    CALL(flatten_pem("server.cert", &expected));        cert = ne_ssl_cert_read("server.cert");    ONN("could not load server.cert", cert == NULL);    /* export the cert to and compare it with the PEM file */    actual = ne_ssl_cert_export(cert);    CALL(check_exported_data(actual, expected));    /* import the exported cert data, check it looks the same */    imp = ne_ssl_cert_import(actual);    ONN("failed to import exported cert", imp == NULL);    ONN("imported cert was different to original",         ne_ssl_cert_cmp(imp, cert));    /* re-export the imported cert and check that looks the same */    ne_free(actual);    actual = ne_ssl_cert_export(imp);    CALL(check_exported_data(actual, expected));    ne_ssl_cert_free(imp);    /* try importing from bogus data */    imp = ne_ssl_cert_import("!!");    ONN("imported bogus cert from bogus base64", imp != NULL);    imp = ne_ssl_cert_import("aaaa");    ONN("imported bogus cert from valid base64", imp != NULL);    ne_ssl_cert_free(cert);    ne_free(actual);    ne_free(expected);    return OK;}/* Test write/read */static int read_write(void){    ne_ssl_certificate *c1, *c2;    c1 = ne_ssl_cert_read("server.cert");    ONN("could not load server.cert", c1 == NULL);    ONN("could not write output.pem", ne_ssl_cert_write(c1, "output.pem"));        ONN("wrote to nonexistent directory",        ne_ssl_cert_write(c1, "nonesuch/output.pem") == 0);    c2 = ne_ssl_cert_read("output.pem");    ONN("could not read output.pem", c2 == NULL);        ONN("read of output.pem differs from original",        ne_ssl_cert_cmp(c2, c1));    ne_ssl_cert_free(c1);    ne_ssl_cert_free(c2);    return OK;}/* A verification callback which caches the passed cert. */static int verify_cache(void *userdata, int fs,                        const ne_ssl_certificate *cert){    char **cache = userdata;        if (*cache == NULL) {        *cache = ne_ssl_cert_export(cert);        return 0;    } else {        return -1;    }}/* Test a common use of the SSL API; cache the server cert across * sessions. */static int cache_cert(void){    ne_session *sess = DEFSESS;    char *cache = NULL;    ne_ssl_certificate *cert;    struct ssl_server_args args = {0};    args.cert = "ssigned.pem";    args.cache = 1;    ONREQ(any_ssl_request(sess, ssl_server, &args, CA_CERT,                          verify_cache, &cache));    ne_session_destroy(sess);    ONN("no cert was cached", cache == NULL);        /* make a real cert */    cert = ne_ssl_cert_import(cache);    ONN("could not import cached cert", cert == NULL);    ne_free(cache);    /* create a new session */    sess = DEFSESS;    /* trust the cert */    ne_ssl_trust_cert(sess, cert);    ne_ssl_cert_free(cert);    /* now, the request should succeed without manual verification */    ONREQ(any_ssl_request(sess, ssl_server, &args, CA_CERT,                          NULL, NULL));    ne_session_destroy(sess);    return OK;}/* TODO: code paths still to test in cert verification: * - server cert changes between connections: Mozilla gives * a "bad MAC decode" error for this; can do better? * - server presents no certificate (using ADH ciphers)... can * only really happen if they mess with the SSL_CTX and enable * ADH cipher manually; but good to check the failure case is  * safe. * From the SSL book: * - an early FIN should be returned as a possible truncation attack, * NOT just an NE_SOCK_CLOSED. * - unexpected close_notify is an error but not an attack. * - never attempt session resumption after any aborted connection. */ne_test tests[] = {    T_LEAKY(init),    T(load_server_certs),    T(trust_default_ca),    T(cert_fingerprint),    T(cert_identities),    T(cert_validity),    T(cert_compare),    T(dname_compare),    T(dname_readable),    T(import_export),    T(read_write),    T(load_client_cert),    T(simple),    T(simple_sslv2),    T(simple_eof),    T(empty_truncated_eof),    T(fail_not_ssl),    T(cache_cert),    T(client_cert_pkcs12),    T(ccert_unencrypted),    T(client_cert_provided),    T(cc_provided_dnames),    T(parse_cert),    T(parse_chain),    T(no_verify),    T(cache_verify),    T_LEAKY(wildcard_init),    T(wildcard_match),    T(caseless_match),    T(subject_altname),    T(two_subject_altname),    T(two_subject_altname2),    T(notdns_altname),    T(ipaddr_altname),    T(multi_commonName),    T(commonName_first),    T(fail_wrongCN),    T(fail_expired),    T(fail_notvalid),    T(fail_untrusted_ca),    T(fail_self_signed),    T(fail_missing_CN),    T(session_cache),	    T(fail_tunnel),    T(proxy_tunnel),    T(auth_proxy_tunnel),    T(auth_tunnel_creds),    T(NULL) };

⌨️ 快捷键说明

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