Example #1
0
/* This callback is called for every certificate in a chain. ok is true if
   OpenSSL's internal verification has verified the certificate. We don't change
   anything about the verification, we only need access to the certificates to
   provide diagnostics. */
static int verify_callback(int ok, X509_STORE_CTX *store)
{
    X509 *cert = X509_STORE_CTX_get_current_cert(store);
    int err = X509_STORE_CTX_get_error(store);

    /* Print the subject, issuer, and fingerprint depending on the verbosity
       level. */
    if ((!ok && o.verbose) || o.debug > 1) {
        char digest_buf[SHA1_STRING_LENGTH + 1];

        loguser("Subject: ");
        X509_NAME_print_ex_fp(stderr, X509_get_subject_name(cert), 0, XN_FLAG_COMPAT);
        loguser_noprefix("\n");
        loguser("Issuer: ");
        X509_NAME_print_ex_fp(stderr, X509_get_issuer_name(cert), 0, XN_FLAG_COMPAT);
        loguser_noprefix("\n");

        assert(ssl_cert_fp_str_sha1(cert, digest_buf, sizeof(digest_buf)) != NULL);
        loguser("SHA-1 fingerprint: %s\n", digest_buf);
    }

    if (!ok && o.verbose) {
        loguser("Certificate verification failed (%s).\n",
            X509_verify_cert_error_string(err));
    }

    return ok;
}
Example #2
0
/* Depending on verbosity, print a message that a connection was established. */
static void connect_report(nsock_iod nsi)
{
    union sockaddr_u peer;
    zmem(&peer, sizeof(peer.storage));

    nsi_getlastcommunicationinfo(nsi, NULL, NULL, NULL,
        &peer.sockaddr, sizeof(peer.storage));

    if (o.verbose) {
#ifdef HAVE_OPENSSL
        if (nsi_checkssl(nsi)) {
            X509 *cert;
            X509_NAME *subject;
            char digest_buf[SHA1_STRING_LENGTH + 1];
            char *fp;

            loguser("SSL connection to %s:%hu.", inet_socktop(&peer), nsi_peerport(nsi));

            cert = SSL_get_peer_certificate((SSL *) nsi_getssl(nsi));
            ncat_assert(cert != NULL);

            subject = X509_get_subject_name(cert);
            if (subject != NULL) {
                char buf[256];
                int n;

                n = X509_NAME_get_text_by_NID(subject, NID_organizationName, buf, sizeof(buf));
                if (n >= 0 && n <= sizeof(buf) - 1)
                    loguser_noprefix(" %s", buf);
            }

            loguser_noprefix("\n");

            fp = ssl_cert_fp_str_sha1(cert, digest_buf, sizeof(digest_buf));
            ncat_assert(fp == digest_buf);
            loguser("SHA-1 fingerprint: %s\n", digest_buf);
        } else {
#if HAVE_SYS_UN_H
            if (peer.sockaddr.sa_family == AF_UNIX)
                loguser("Connected to %s.\n", peer.un.sun_path);
            else
#endif
                loguser("Connected to %s:%hu.\n", inet_socktop(&peer), nsi_peerport(nsi));
        }
#else
#if HAVE_SYS_UN_H
        if (peer.sockaddr.sa_family == AF_UNIX)
            loguser("Connected to %s.\n", peer.un.sun_path);
        else
#endif
            loguser("Connected to %s:%hu.\n", inet_socktop(&peer), nsi_peerport(nsi));
#endif
    }
}
SSL_CTX *setup_ssl_listen(void)
{
    const SSL_METHOD *method;

    if (sslctx)
        goto done;

    SSL_library_init();
    OpenSSL_add_all_algorithms();
    ERR_load_crypto_strings();
    SSL_load_error_strings();

    /* RAND_status initializes the random number generator through a variety of
       platform-dependent methods, then returns 1 if there is enough entropy or
       0 otherwise. This seems to be a good platform-independent way of seeding
       the generator, as well as of refusing to continue without enough
       entropy. */
    if (!RAND_status())
        bye("Failed to seed OpenSSL PRNG (RAND_status returned false).");

    if (!(method = SSLv23_server_method()))
        bye("SSLv23_server_method(): %s.", ERR_error_string(ERR_get_error(), NULL));
    if (!(sslctx = SSL_CTX_new(method)))
        bye("SSL_CTX_new(): %s.", ERR_error_string(ERR_get_error(), NULL));

    SSL_CTX_set_options(sslctx, SSL_OP_ALL | SSL_OP_NO_SSLv2);

    /* Secure ciphers list taken from Nsock. */
    if (!SSL_CTX_set_cipher_list(sslctx, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"))
        bye("Unable to set OpenSSL cipher list: %s", ERR_error_string(ERR_get_error(), NULL));

    if (o.sslcert == NULL && o.sslkey == NULL) {
        X509 *cert;
        EVP_PKEY *key;
        char digest_buf[SHA1_STRING_LENGTH + 1];

        if (o.verbose)
            loguser("Generating a temporary %d-bit RSA key. Use --ssl-key and --ssl-cert to use a permanent one.\n", DEFAULT_KEY_BITS);
        if (ssl_gen_cert(&cert, &key) == 0)
            bye("ssl_gen_cert(): %s.", ERR_error_string(ERR_get_error(), NULL));
        if (o.verbose) {
            char *fp;
            fp = ssl_cert_fp_str_sha1(cert, digest_buf, sizeof(digest_buf));
            ncat_assert(fp == digest_buf);
            loguser("SHA-1 fingerprint: %s\n", digest_buf);
        }
        if (SSL_CTX_use_certificate(sslctx, cert) != 1)
            bye("SSL_CTX_use_certificate(): %s.", ERR_error_string(ERR_get_error(), NULL));
        if (SSL_CTX_use_PrivateKey(sslctx, key) != 1)
            bye("SSL_CTX_use_PrivateKey(): %s.", ERR_error_string(ERR_get_error(), NULL));
        X509_free(cert);
        EVP_PKEY_free(key);
    } else {
        if (o.sslcert == NULL || o.sslkey == NULL)
            bye("The --ssl-key and --ssl-cert options must be used together.");
        if (SSL_CTX_use_certificate_chain_file(sslctx, o.sslcert) != 1)
            bye("SSL_CTX_use_certificate_chain_file(): %s.", ERR_error_string(ERR_get_error(), NULL));
        if (SSL_CTX_use_PrivateKey_file(sslctx, o.sslkey, SSL_FILETYPE_PEM) != 1)
            bye("SSL_CTX_use_Privatekey_file(): %s.", ERR_error_string(ERR_get_error(), NULL));
    }

done:
    return sslctx;
}