Beispiel #1
0
/**
 * Return information about the connection.
 */
static int meth_info(lua_State *L)
{
  int bits = 0;
  int algbits = 0;
  char buf[256] = {0};
  const SSL_CIPHER *cipher;
  p_ssl ssl = (p_ssl)luaL_checkudata(L, 1, "SSL:Connection");
  cipher = SSL_get_current_cipher(ssl->ssl);
  if (!cipher)
    return 0;
  SSL_CIPHER_description(cipher, buf, sizeof(buf));
  bits = SSL_CIPHER_get_bits(cipher, &algbits);
  lua_pushstring(L, buf);
  lua_pushnumber(L, bits);
  lua_pushnumber(L, algbits);
  lua_pushstring(L, SSL_get_version(ssl->ssl));
  return 4;
}
Beispiel #2
0
static void
log_session_info(as_socket* sock)
{
	if (! sock->ctx->log_session_info)
		return;
	
	SSL_CIPHER const* cipher = SSL_get_current_cipher(sock->ssl);
	if (cipher) {
		char desc[1024];
		SSL_CIPHER_description(cipher, desc, sizeof(desc));
		size_t len = strlen(desc);
		if (len > 0) {
			desc[len-1] = '\0';	// Trim trailing \n
		}
		as_log_info("TLS cipher: %s", desc);
	}
	else {
		as_log_warn("TLS no current cipher");
	}
}
Beispiel #3
0
const char *
ssl_to_text(const SSL *ssl)
{
	static char	buf[256];
	static char	description[128];
	char	       *tls_version = NULL;

	/*
	 * SSL_get_cipher_version() does not know about the exact TLS version...
	 * you have to pick it up from second field of the SSL cipher description !
	 */
	SSL_CIPHER_description(SSL_get_current_cipher(ssl), description, sizeof description);
	tls_version = strchr(description, ' ') + 1;
	tls_version[strcspn(tls_version, " ")] = '\0';
	(void)snprintf(buf, sizeof buf, "version=%s (%s), cipher=%s, bits=%d",
	    SSL_get_cipher_version(ssl),
	    tls_version,
	    SSL_get_cipher_name(ssl),
	    SSL_get_cipher_bits(ssl, NULL));

	return (buf);
}
Beispiel #4
0
static void print_cipher(CLI *c) { /* print negotiated cipher */
    SSL_CIPHER *cipher;
    char *buf, *i, *j;

    cipher=(SSL_CIPHER *)SSL_get_current_cipher(c->ssl);
    buf=SSL_CIPHER_description(cipher, NULL, 0);
    i=j=buf;
    do {
        switch(*i) {
        case ' ':
            *j++=' ';
            while(i[1]==' ')
                ++i;
            break;
        case '\n':
            break;
        default:
            *j++=*i;
        }
    } while(*i++);
    s_log(LOG_INFO, "Negotiated ciphers: %s", buf);
    OPENSSL_free(buf);
}
Beispiel #5
0
/*
Parses the Kx, Enc, and Mac values out of the SSL_CIPHER_description and
maps the values to the corresponding .NET enum value.
*/
static bool GetSslConnectionInfoFromDescription(const SSL_CIPHER* cipher,
                                                CipherAlgorithmType& dataCipherAlg,
                                                ExchangeAlgorithmType& keyExchangeAlg,
                                                HashAlgorithmType& dataHashAlg,
                                                DataHashSize& hashKeySize)
{
    const int descriptionLength = 256;
    char description[descriptionLength] = {};
    SSL_CIPHER_description(cipher, description, descriptionLength - 1); // ensure description is NULL-terminated

    const char* keyExchange;
    size_t keyExchangeLength;
    if (!GetDescriptionValue(description, "Kx=", 3, &keyExchange, keyExchangeLength))
    {
        return false;
    }

    const char* encryption;
    size_t encryptionLength;
    if (!GetDescriptionValue(description, "Enc=", 4, &encryption, encryptionLength))
    {
        return false;
    }

    const char* mac;
    size_t macLength;
    if (!GetDescriptionValue(description, "Mac=", 4, &mac, macLength))
    {
        return false;
    }

    keyExchangeAlg = MapExchangeAlgorithmType(keyExchange, keyExchangeLength);
    dataCipherAlg = MapCipherAlgorithmType(encryption, encryptionLength);
    GetHashAlgorithmTypeAndSize(mac, macLength, dataHashAlg, hashKeySize);
    return true;
}
Beispiel #6
0
/* This equivalent functionality was submitted for OpenSSL 1.1.1+ in
 * https://github.com/openssl/openssl/pull/1666 */
static int dtls_get_data_mtu(struct openconnect_info *vpninfo, int mtu)
{
	int ivlen, maclen, blocksize = 0, pad = 0;
#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
	const SSL_CIPHER *s_ciph = SSL_get_current_cipher(vpninfo->dtls_ssl);
	int cipher_nid;
	const EVP_CIPHER *e_ciph;
	const EVP_MD *e_md;
	char wtf[128];

	cipher_nid = SSL_CIPHER_get_cipher_nid(s_ciph);
	if (cipher_nid == NID_chacha20_poly1305) {
		ivlen = 0; /* Automatically derived from handshake and seqno */
		maclen = 16; /* Poly1305 */
	} else {
		e_ciph = EVP_get_cipherbynid(cipher_nid);
		switch (EVP_CIPHER_mode(e_ciph)) {
		case EVP_CIPH_GCM_MODE:
			ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
			maclen = EVP_GCM_TLS_TAG_LEN;
			break;

		case EVP_CIPH_CCM_MODE:
			ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
			SSL_CIPHER_description(s_ciph, wtf, sizeof(wtf));
			if (strstr(wtf, "CCM8"))
				maclen = 8;
			else
				maclen = 16;
			break;

		case EVP_CIPH_CBC_MODE:
			blocksize = EVP_CIPHER_block_size(e_ciph);
			ivlen = EVP_CIPHER_iv_length(e_ciph);
			pad = 1;

			e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
			maclen = EVP_MD_size(e_md);
			break;

		default:
			vpn_progress(vpninfo, PRG_ERR,
				     _("Unable to calculate DTLS overhead for %s\n"),
				     SSL_CIPHER_get_name(s_ciph));
			ivlen = 0;
			maclen = DTLS_OVERHEAD;
			break;
		}
	}
#else
	/* OpenSSL <= 1.0.2 only supports CBC ciphers with PSK */
	ivlen = EVP_CIPHER_iv_length(EVP_CIPHER_CTX_cipher(vpninfo->dtls_ssl->enc_read_ctx));
	maclen = EVP_MD_CTX_size(vpninfo->dtls_ssl->read_hash);
	blocksize = ivlen;
	pad = 1;
#endif

	/* Even when it pretended to, OpenSSL never did encrypt-then-mac.
	 * So the MAC is *inside* the encryption, unconditionally.
	 * https://github.com/openssl/openssl/pull/1705 */
	if (mtu < DTLS1_RT_HEADER_LENGTH + ivlen)
		return 0;
	mtu -= DTLS1_RT_HEADER_LENGTH + ivlen;

	/* For CBC mode round down to blocksize */
	if (blocksize)
		mtu -= mtu % blocksize;

	/* Finally, CBC modes require at least one byte to indicate
	 * padding length, as well as the MAC. */
	if (mtu < pad + maclen)
		return 0;
	mtu -= pad + maclen;
	return mtu;
}
Beispiel #7
0
int
ciphers_main(int argc, char **argv)
{
	char *cipherlist = NULL;
	STACK_OF(SSL_CIPHER) *ciphers;
	const SSL_CIPHER *cipher;
	SSL_CTX *ssl_ctx = NULL;
	SSL *ssl = NULL;
	uint16_t value;
	int i, rv = 0;
	char *desc;

	if (single_execution) {
		if (pledge("stdio rpath", NULL) == -1) {
			perror("pledge");
			exit(1);
		}
	}

	memset(&ciphers_config, 0, sizeof(ciphers_config));

	if (options_parse(argc, argv, ciphers_options, &cipherlist,
	    NULL) != 0) {
		ciphers_usage();
		return (1);
	}

	if (ciphers_config.usage) {
		ciphers_usage();
		return (1);
	}

	if ((ssl_ctx = SSL_CTX_new(TLSv1_client_method())) == NULL)
		goto err;

	if (cipherlist != NULL) {
		if (SSL_CTX_set_cipher_list(ssl_ctx, cipherlist) == 0)
			goto err;
	}

	if ((ssl = SSL_new(ssl_ctx)) == NULL)
		goto err;

	if ((ciphers = SSL_get_ciphers(ssl)) == NULL)
		goto err;

	for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
		cipher = sk_SSL_CIPHER_value(ciphers, i);
		if (ciphers_config.verbose == 0) {
			fprintf(stdout, "%s%s", (i ? ":" : ""),
			    SSL_CIPHER_get_name(cipher));
			continue;
		}
		if (ciphers_config.verbose > 1) {
			value = SSL_CIPHER_get_value(cipher);
			fprintf(stdout, "%-*s0x%02X,0x%02X - ", 10, "",
				((value >> 8) & 0xff), (value & 0xff));
		}
		desc = SSL_CIPHER_description(cipher, NULL, 0);
		if (strcmp(desc, "OPENSSL_malloc Error") == 0) {
			fprintf(stderr, "out of memory\n");
			goto err;
		}
		fprintf(stdout, "%s", desc);
		free(desc);
	}
Beispiel #8
0
/* Switch on a filedescriptor */
int ggz_tls_enable_fd(int fd, GGZTLSType mode, GGZTLSVerificationType verify)
{
	int ret, ret2;
	STACK_OF(SSL_CIPHER) *stack;
	SSL_CIPHER *cipher;
	int bits;
	char *cipherlist;
	SSL *_tls;
	int _tls_active;
	struct list_entry *entry;

	_state = 1;
	_tls_active = 0;
	if((mode != GGZ_TLS_CLIENT) && (mode != GGZ_TLS_SERVER))
	{
		TLSERROR("Wrong mode.");
		return 0;
	}

	if(!_tlsctx) tls_init(verify);
		
	_tls = SSL_new(_tlsctx);
	if(_tls)
	{
		cipherlist = NULL;
		stack = SSL_get_ciphers(_tls);
		while((cipher = (SSL_CIPHER*)sk_pop(stack)) != NULL)
		{
			printf("* Cipher: %s\n", SSL_CIPHER_get_name(cipher));
			printf("  Bits: %i\n", SSL_CIPHER_get_bits(cipher, &bits));
			printf("  Used bits: %i\n", bits);
			printf("  Version: %s\n", SSL_CIPHER_get_version(cipher));
			printf("  Description: %s\n", SSL_CIPHER_description(cipher, NULL, 0));
			if(cipherlist)
			{
				cipherlist = (char*)realloc(cipherlist, (strlen(cipherlist) + 1) + strlen(SSL_CIPHER_get_name(cipher)) + 1);
				strcat(cipherlist, ":");
				strcat(cipherlist, SSL_CIPHER_get_name(cipher));
			}
			else
			{
				cipherlist = (char*)malloc(strlen(SSL_CIPHER_get_name(cipher)) + 1);
				strcpy(cipherlist, SSL_CIPHER_get_name(cipher));
			}
		}
		printf("Available ciphers: %s\n", cipherlist);
		ret = SSL_set_cipher_list(_tls, cipherlist);
		if(!ret) TLSERROR("Cipher selection failed.");
		ret = SSL_set_fd(_tls, fd);
		if(!ret) TLSERROR("Assignment to connection failed.");
		else
		{
			SSL_set_read_ahead(_tls, 1);
			if(mode == GGZ_TLS_SERVER)
			{
				tls_certkey(_tls);
				if(_state)
				{
					SSL_set_accept_state(_tls);
					ret = SSL_accept(_tls);
				}
			}
			else
			{
				SSL_set_connect_state(_tls);
				ret = SSL_connect(_tls);
			}
			if((ret != 1) || (!_state))
			{
				printf("Ret: %i, State: %i\n", ret, _state);
				TLSERROR("Handshake failed.");
				ret2 = ERR_get_error();
				printf("EXT: %s\n%s\n%s\n%s\n%s\n", tls_exterror(_tls, ret), ERR_error_string(ret2, NULL),
					ERR_lib_error_string(ret2), ERR_func_error_string(ret2), ERR_reason_error_string(ret2));
			}
			else
			{
				printf(">>>>> Handshake successful.\n");
				if((mode == GGZ_TLS_SERVER) || (verify == GGZ_TLS_VERIFY_NONE)) _tls_active = 1;
				else
				{
					printf(">>>>> Client side, thus checking Certificate.\n");
					printf("Negotiated cipher: %s\n", SSL_get_cipher(_tls));
					printf("Shared ciphers: %s\n", SSL_get_shared_ciphers(_tls, NULL, 0));
					if(SSL_get_peer_certificate(_tls))
					{
						if(SSL_get_verify_result(_tls) == X509_V_OK)
						{
							_tls_active = 1;
						}
						else
						{
							printf("Error code: %li\n", SSL_get_verify_result(_tls));
							TLSERROR("Invalid certificate, or certificate is not self-signed.");
						}
					}
					else TLSERROR("Couldn't get certificate.");
				}
			}
			entry = (struct list_entry*)ggz_malloc(sizeof(struct list_entry));
			entry->tls = _tls;
			entry->fd = fd;
			entry->active = _tls_active;
			ggz_list_insert(openssllist, entry);
			return 1;
		}
	}
	return 0;
}
Beispiel #9
0
/** Continue a TLS handshake
 *
 * Advance the TLS handshake by feeding OpenSSL data from dirty_in,
 * and reading data from OpenSSL into dirty_out.
 *
 * @param request The current request.
 * @param session The current TLS session.
 * @return
 *	- 0 on error.
 *	- 1 on success.
 */
int tls_session_handshake(REQUEST *request, tls_session_t *session)
{
	int ret;

	/*
	 *	This is a logic error.  tls_session_handshake
	 *	must not be called if the handshake is
	 *	complete tls_session_recv must be
	 *	called instead.
	 */
	if (SSL_is_init_finished(session->ssl)) {
		REDEBUG("Attempted to continue TLS handshake, but handshake has completed");
		return 0;
	}

	if (session->invalid) {
		REDEBUG("Preventing invalid session from continuing");
		return 0;
	}

	/*
	 *	Feed dirty data into OpenSSL, so that is can either
	 *	process it as Application data (decrypting it)
	 *	or continue the TLS handshake.
	 */
	if (session->dirty_in.used) {
		ret = BIO_write(session->into_ssl, session->dirty_in.data, session->dirty_in.used);
		if (ret != (int)session->dirty_in.used) {
			REDEBUG("Failed writing %zd bytes to TLS BIO: %d", session->dirty_in.used, ret);
			record_init(&session->dirty_in);
			return 0;
		}
		record_init(&session->dirty_in);
	}

	/*
	 *	Magic/More magic? Although SSL_read is normally
	 *	used to read application data, it will also
	 *	continue the TLS handshake.  Removing this call will
	 *	cause the handshake to fail.
	 *
	 *	We don't ever expect to actually *receive* application
	 *	data here.
	 *
	 *	The reason why we call SSL_read instead of SSL_accept,
	 *	or SSL_connect, as it allows this function
	 *	to be used, irrespective or whether we're acting
	 *	as a client or a server.
	 *
	 *	If acting as a client SSL_set_connect_state must have
	 *	been called before this function.
	 *
	 *	If acting as a server SSL_set_accept_state must have
	 *	been called before this function.
	 */
	ret = SSL_read(session->ssl, session->clean_out.data + session->clean_out.used,
		       sizeof(session->clean_out.data) - session->clean_out.used);
	if (ret > 0) {
		session->clean_out.used += ret;
		return 1;
	}
	if (!tls_log_io_error(request, session, ret, "Failed in SSL_read")) return 0;

	/*
	 *	This only occurs once per session, where calling
	 *	SSL_read updates the state of the SSL session, setting
	 *	this flag to true.
	 *
	 *	Callbacks provide enough info so we don't need to
	 *	print debug statements when the handshake is in other
	 *	states.
	 */
	if (SSL_is_init_finished(session->ssl)) {
		SSL_CIPHER const *cipher;
		VALUE_PAIR *vp;
		char const *str_version;

		char cipher_desc[256], cipher_desc_clean[256];
		char *p = cipher_desc, *q = cipher_desc_clean;

		cipher = SSL_get_current_cipher(session->ssl);
		SSL_CIPHER_description(cipher, cipher_desc, sizeof(cipher_desc));

		/*
		 *	Cleanup the output from OpenSSL
		 *	Seems to print info in a tabular format.
		 */
		while (*p != '\0') {
			if (isspace(*p)) {
				*q++ = *p;
				while (isspace(*++p));
				continue;
			}
			*q++ = *p++;
		}
		*q = '\0';

		RDEBUG2("Cipher suite: %s", cipher_desc_clean);

		vp = fr_pair_afrom_num(request->state_ctx, 0, FR_TLS_SESSION_CIPHER_SUITE);
		if (vp) {
			fr_pair_value_strcpy(vp,  SSL_CIPHER_get_name(cipher));
			fr_pair_add(&request->state, vp);
			RDEBUG2("    &session-state:TLS-Session-Cipher-Suite := \"%s\"", vp->vp_strvalue);
		}

		switch (session->info.version) {
		case SSL2_VERSION:
			str_version = "SSL 2.0";
			break;
		case SSL3_VERSION:
			str_version = "SSL 3.0";
			break;
		case TLS1_VERSION:
			str_version = "TLS 1.0";
			break;
#ifdef TLS1_1_VERSION
		case TLS1_1_VERSION:
			str_version = "TLS 1.1";
			break;
#endif
#ifdef TLS1_2_VERSION
		case TLS1_2_VERSION:
			str_version = "TLS 1.2";
			break;
#endif
#ifdef TLS1_3_VERSON
		case TLS1_3_VERSION:
			str_version = "TLS 1.3";
			break;
#endif
		default:
			str_version = "UNKNOWN";
			break;
		}

		vp = fr_pair_afrom_num(request->state_ctx, 0, FR_TLS_SESSION_VERSION);
		if (vp) {
			fr_pair_value_strcpy(vp, str_version);
			fr_pair_add(&request->state, vp);
			RDEBUG2("    &session-state:TLS-Session-Version := \"%s\"", str_version);
		}

#if OPENSSL_VERSION_NUMBER >= 0x10001000L
		/*
		 *	Cache the SSL_SESSION pointer.
		 *
		 *	Which contains all the data we need for session resumption.
		 */
		if (!session->ssl_session) {
			session->ssl_session = SSL_get_session(session->ssl);
			if (!session->ssl_session) {
				REDEBUG("Failed getting TLS session");
				return 0;
			}
		}

		if (RDEBUG_ENABLED3) {
			BIO *ssl_log = BIO_new(BIO_s_mem());

			if (ssl_log) {
				if (SSL_SESSION_print(ssl_log, session->ssl_session) == 1) {
					SSL_DRAIN_ERROR_QUEUE(RDEBUG3, "", ssl_log);
				} else {
					RDEBUG3("Failed retrieving session data");
				}
				BIO_free(ssl_log);
			}
		}
#endif

		/*
		 *	Session was resumed, add attribute to mark it as such.
		 */
		if (SSL_session_reused(session->ssl)) {
			/*
			 *	Mark the request as resumed.
			 */
			MEM(pair_update_request(&vp, attr_eap_session_resumed) >= 0);
			vp->vp_bool = true;
		}
	}

	/*
	 *	Get data to pack and send back to the TLS peer.
	 */
	ret = BIO_ctrl_pending(session->from_ssl);
	if (ret > 0) {
		ret = BIO_read(session->from_ssl, session->dirty_out.data,
			       sizeof(session->dirty_out.data));
		if (ret > 0) {
			session->dirty_out.used = ret;
		} else if (BIO_should_retry(session->from_ssl)) {
			record_init(&session->dirty_in);
			RDEBUG2("Asking for more data in tunnel");
			return 1;

		} else {
			tls_log_error(NULL, NULL);
			record_init(&session->dirty_in);
			return 0;
		}
	} else {
		/* Its clean application data, do whatever we want */
		record_init(&session->clean_out);
	}

	/*
	 *	W would prefer to latch on info.content_type but
	 *	(I think its...) tls_session_msg_cb() updates it
	 *	after the call to tls_session_handshake_alert()
	 */
	if (session->handshake_alert.level) {
		/*
		 * FIXME RFC 4851 section 3.6.1 - peer might ACK alert and include a restarted ClientHello
		 *                                 which eap_tls_session_status() will fail on
		 */
		session->info.content_type = SSL3_RT_ALERT;

		session->dirty_out.data[0] = session->info.content_type;
		session->dirty_out.data[1] = 3;
		session->dirty_out.data[2] = 1;
		session->dirty_out.data[3] = 0;
		session->dirty_out.data[4] = 2;
		session->dirty_out.data[5] = session->handshake_alert.level;
		session->dirty_out.data[6] = session->handshake_alert.description;

		session->dirty_out.used = 7;

		session->handshake_alert.level = 0;
	}

	/* We are done with dirty_in, reinitialize it */
	record_init(&session->dirty_in);
	return 1;
}
Beispiel #10
0
int MAIN(int argc, char **argv)
{
    int ret = 1, i;
    int verbose = 0, Verbose = 0;
    const char **pp;
    const char *p;
    int badops = 0;
    SSL_CTX *ctx = NULL;
    SSL *ssl = NULL;
    char *ciphers = NULL;
    const SSL_METHOD *meth = NULL;
    STACK_OF(SSL_CIPHER) *sk;
    char buf[512];
    BIO *STDout = NULL;

    meth = SSLv23_server_method();

    apps_startup();

    if (bio_err == NULL)
        bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
    STDout = BIO_new_fp(stdout, BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
    {
        BIO *tmpbio = BIO_new(BIO_f_linebuffer());
        STDout = BIO_push(tmpbio, STDout);
    }
#endif
    if (!load_config(bio_err, NULL))
        goto end;

    argc--;
    argv++;
    while (argc >= 1) {
        if (strcmp(*argv, "-v") == 0)
            verbose = 1;
        else if (strcmp(*argv, "-V") == 0)
            verbose = Verbose = 1;
#ifndef OPENSSL_NO_SSL2
        else if (strcmp(*argv, "-ssl2") == 0)
            meth = SSLv2_client_method();
#endif
#ifndef OPENSSL_NO_SSL3
        else if (strcmp(*argv, "-ssl3") == 0)
            meth = SSLv3_client_method();
#endif
#ifndef OPENSSL_NO_TLS1
        else if (strcmp(*argv, "-tls1") == 0)
            meth = TLSv1_client_method();
#endif
        else if ((strncmp(*argv, "-h", 2) == 0) || (strcmp(*argv, "-?") == 0)) {
            badops = 1;
            break;
        } else {
            ciphers = *argv;
        }
        argc--;
        argv++;
    }

    if (badops) {
        for (pp = ciphers_usage; (*pp != NULL); pp++)
            BIO_printf(bio_err, "%s", *pp);
        goto end;
    }

    OpenSSL_add_ssl_algorithms();

    ctx = SSL_CTX_new(meth);
    if (ctx == NULL)
        goto err;
    if (ciphers != NULL) {
        if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
            BIO_printf(bio_err, "Error in cipher list\n");
            goto err;
        }
    }
    ssl = SSL_new(ctx);
    if (ssl == NULL)
        goto err;

    if (!verbose) {
        for (i = 0;; i++) {
            p = SSL_get_cipher_list(ssl, i);
            if (p == NULL)
                break;
            if (i != 0)
                BIO_printf(STDout, ":");
            BIO_printf(STDout, "%s", p);
        }
        BIO_printf(STDout, "\n");
    } else {                    /* verbose */

        sk = SSL_get_ciphers(ssl);

        for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
            SSL_CIPHER *c;

            c = sk_SSL_CIPHER_value(sk, i);

            if (Verbose) {
                unsigned long id = c->id;
                int id0 = (int)(id >> 24);
                int id1 = (int)((id >> 16) & 0xffL);
                int id2 = (int)((id >> 8) & 0xffL);
                int id3 = (int)(id & 0xffL);

                if ((id & 0xff000000L) == 0x02000000L) {
                    /* SSL2 cipher */
                    BIO_printf(STDout, "     0x%02X,0x%02X,0x%02X - ", id1,
                               id2, id3);
                } else if ((id & 0xff000000L) == 0x03000000L) {
                    /* SSL3 cipher */
                    BIO_printf(STDout, "          0x%02X,0x%02X - ", id2,
                               id3);
                } else {
                    /* whatever */
                    BIO_printf(STDout, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0,
                               id1, id2, id3);
                }
            }

            BIO_puts(STDout, SSL_CIPHER_description(c, buf, sizeof buf));
        }
    }

    ret = 0;
    if (0) {
 err:
        SSL_load_error_strings();
        ERR_print_errors(bio_err);
    }
 end:
    if (ctx != NULL)
        SSL_CTX_free(ctx);
    if (ssl != NULL)
        SSL_free(ssl);
    if (STDout != NULL)
        BIO_free_all(STDout);
    apps_shutdown();
    OPENSSL_EXIT(ret);
}
int MAIN(int argc, char **argv)
	{
	int ret=1,i;
	int verbose=0;
	char **pp;
	const char *p;
	int badops=0;
	SSL_CTX *ctx=NULL;
	SSL *ssl=NULL;
	char *ciphers=NULL;
	SSL_METHOD *meth=NULL;
	STACK_OF(SSL_CIPHER) *sk;
	char buf[512];
	BIO *STDout=NULL;

#if !defined(OPENSSL_NO_SSL2) && !defined(OPENSSL_NO_SSL3)
	meth=SSLv23_server_method();
#elif !defined(OPENSSL_NO_SSL3)
	meth=SSLv3_server_method();
#elif !defined(OPENSSL_NO_SSL2)
	meth=SSLv2_server_method();
#endif

	apps_startup();

	if (bio_err == NULL)
		bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
	STDout=BIO_new_fp(stdout,BIO_NOCLOSE);
#ifdef OPENSSL_SYS_VMS
	{
	BIO *tmpbio = BIO_new(BIO_f_linebuffer());
	STDout = BIO_push(tmpbio, STDout);
	}
#endif

	argc--;
	argv++;
	while (argc >= 1)
		{
		if (strcmp(*argv,"-v") == 0)
			verbose=1;
#ifndef OPENSSL_NO_SSL2
		else if (strcmp(*argv,"-ssl2") == 0)
			meth=SSLv2_client_method();
#endif
#ifndef OPENSSL_NO_SSL3
		else if (strcmp(*argv,"-ssl3") == 0)
			meth=SSLv3_client_method();
#endif
#ifndef OPENSSL_NO_TLS1
		else if (strcmp(*argv,"-tls1") == 0)
			meth=TLSv1_client_method();
#endif
		else if ((strncmp(*argv,"-h",2) == 0) ||
			 (strcmp(*argv,"-?") == 0))
			{
			badops=1;
			break;
			}
		else
			{
			ciphers= *argv;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
		for (pp=ciphers_usage; (*pp != NULL); pp++)
			BIO_printf(bio_err,"%s",*pp);
		goto end;
		}

	OpenSSL_add_ssl_algorithms();

	ctx=SSL_CTX_new(meth);
	if (ctx == NULL) goto err;
	if (ciphers != NULL) {
		if(!SSL_CTX_set_cipher_list(ctx,ciphers)) {
			BIO_printf(bio_err, "Error in cipher list\n");
			goto err;
		}
	}
	ssl=SSL_new(ctx);
	if (ssl == NULL) goto err;


	if (!verbose)
		{
		for (i=0; ; i++)
			{
			p=SSL_get_cipher_list(ssl,i);
			if (p == NULL) break;
			if (i != 0) BIO_printf(STDout,":");
			BIO_printf(STDout,"%s",p);
			}
		BIO_printf(STDout,"\n");
		}
	else
		{
		sk=SSL_get_ciphers(ssl);

		for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
			{
			BIO_puts(STDout,SSL_CIPHER_description(
				sk_SSL_CIPHER_value(sk,i),
				buf,sizeof buf));
			}
		}

	ret=0;
	if (0)
		{
err:
		SSL_load_error_strings();
		ERR_print_errors(bio_err);
		}
end:
	if (ctx != NULL) SSL_CTX_free(ctx);
	if (ssl != NULL) SSL_free(ssl);
	if (STDout != NULL) BIO_free_all(STDout);
	apps_shutdown();
	OPENSSL_EXIT(ret);
	}
Beispiel #12
0
int ciphers_main(int argc, char **argv)
{
    SSL_CTX *ctx = NULL;
    SSL *ssl = NULL;
    STACK_OF(SSL_CIPHER) *sk = NULL;
    const SSL_METHOD *meth = TLS_server_method();
    int ret = 1, i, verbose = 0, Verbose = 0, use_supported = 0;
#ifndef OPENSSL_NO_SSL_TRACE
    int stdname = 0;
#endif
#ifndef OPENSSL_NO_PSK
    int psk = 0;
#endif
#ifndef OPENSSL_NO_SRP
    int srp = 0;
#endif
    const char *p;
    char *ciphers = NULL, *prog;
    char buf[512];
    OPTION_CHOICE o;
    int min_version = 0, max_version = 0;

    prog = opt_init(argc, argv, ciphers_options);
    while ((o = opt_next()) != OPT_EOF) {
        switch (o) {
        case OPT_EOF:
        case OPT_ERR:
 opthelp:
            BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
            goto end;
        case OPT_HELP:
            opt_help(ciphers_options);
            ret = 0;
            goto end;
        case OPT_V:
            verbose = 1;
            break;
        case OPT_UPPER_V:
            verbose = Verbose = 1;
            break;
        case OPT_S:
            use_supported = 1;
            break;
        case OPT_STDNAME:
#ifndef OPENSSL_NO_SSL_TRACE
            stdname = verbose = 1;
#endif
            break;
        case OPT_SSL3:
            min_version = SSL3_VERSION;
            max_version = SSL3_VERSION;
            break;
        case OPT_TLS1:
            min_version = TLS1_VERSION;
            max_version = TLS1_VERSION;
            break;
        case OPT_TLS1_1:
            min_version = TLS1_1_VERSION;
            max_version = TLS1_1_VERSION;
            break;
        case OPT_TLS1_2:
            min_version = TLS1_2_VERSION;
            max_version = TLS1_2_VERSION;
            break;
        case OPT_TLS1_3:
            min_version = TLS1_3_VERSION;
            max_version = TLS1_3_VERSION;
            break;
        case OPT_PSK:
#ifndef OPENSSL_NO_PSK
            psk = 1;
#endif
            break;
        case OPT_SRP:
#ifndef OPENSSL_NO_SRP
            srp = 1;
#endif
            break;
        }
    }
    argv = opt_rest();
    argc = opt_num_rest();

    if (argc == 1)
        ciphers = *argv;
    else if (argc != 0)
        goto opthelp;

    ctx = SSL_CTX_new(meth);
    if (ctx == NULL)
        goto err;
    if (SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
        goto err;
    if (SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
        goto err;

#ifndef OPENSSL_NO_PSK
    if (psk)
        SSL_CTX_set_psk_client_callback(ctx, dummy_psk);
#endif
#ifndef OPENSSL_NO_SRP
    if (srp)
        SSL_CTX_set_srp_client_pwd_callback(ctx, dummy_srp);
#endif
    if (ciphers != NULL) {
        if (!SSL_CTX_set_cipher_list(ctx, ciphers)) {
            BIO_printf(bio_err, "Error in cipher list\n");
            goto err;
        }
    }
    ssl = SSL_new(ctx);
    if (ssl == NULL)
        goto err;

    if (use_supported)
        sk = SSL_get1_supported_ciphers(ssl);
    else
        sk = SSL_get_ciphers(ssl);

    if (!verbose) {
        for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
            const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, i);
            p = SSL_CIPHER_get_name(c);
            if (p == NULL)
                break;
            if (i != 0)
                BIO_printf(bio_out, ":");
            BIO_printf(bio_out, "%s", p);
        }
        BIO_printf(bio_out, "\n");
    } else {

        for (i = 0; i < sk_SSL_CIPHER_num(sk); i++) {
            const SSL_CIPHER *c;

            c = sk_SSL_CIPHER_value(sk, i);

            if (Verbose) {
                unsigned long id = SSL_CIPHER_get_id(c);
                int id0 = (int)(id >> 24);
                int id1 = (int)((id >> 16) & 0xffL);
                int id2 = (int)((id >> 8) & 0xffL);
                int id3 = (int)(id & 0xffL);

                if ((id & 0xff000000L) == 0x03000000L)
                    BIO_printf(bio_out, "          0x%02X,0x%02X - ", id2, id3); /* SSL3
                                                                                  * cipher */
                else
                    BIO_printf(bio_out, "0x%02X,0x%02X,0x%02X,0x%02X - ", id0, id1, id2, id3); /* whatever */
            }
#ifndef OPENSSL_NO_SSL_TRACE
            if (stdname) {
                const char *nm = SSL_CIPHER_standard_name(c);
                if (nm == NULL)
                    nm = "UNKNOWN";
                BIO_printf(bio_out, "%s - ", nm);
            }
#endif
            BIO_puts(bio_out, SSL_CIPHER_description(c, buf, sizeof buf));
        }
    }

    ret = 0;
    goto end;
 err:
    ERR_print_errors(bio_err);
 end:
    if (use_supported)
        sk_SSL_CIPHER_free(sk);
    SSL_CTX_free(ctx);
    SSL_free(ssl);
    return (ret);
}
Beispiel #13
0
bool TLS_SOCKET_CLASS::connect()

//  DESCRIPTION     : Set up connection to the remote host.
//  PRECONDITIONS   :
//  POSTCONDITIONS  :
//  EXCEPTIONS      : 
//  NOTES           :
//<<===========================================================================
{
	BIO* bio_ptr;
	long error;
	ostringstream remoteHost;

	// make sure the socket is not already in use
	if (terminatingM)
	{
		if (loggerM_ptr) 
		{
			loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - In process of terminating.  Cannot connect.");
		}

		// return - in process of termintating
		return false;
	}
	if (connectedM)
	{
		if (loggerM_ptr) 
		{
			loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Already connected to \"%s\".  Cannot connect again.", remoteHostnameM.c_str());
		}

		// return - already connected
		return false;
	}
	else if (listeningM)
	{
		if (loggerM_ptr)
		{
			loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Socket is already listening to port %d.  Cannot connect to \"%s\".", 
				localListenPortM, remoteHostnameM.c_str());
		}

		// return - socket is already being used to listen
		return false;
	}
	connectedM = false;
	
	if (remoteHostnameM.length() == 0)
	{
		if (loggerM_ptr) 
		{
			loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - No Remote Hostname defined. Can't make connection.");
		}

		// return - don't know what to connect to
		return false;
	}

	// create the transport object
	remoteHost << remoteHostnameM << ':' << remoteConnectPortM;
	if (loggerM_ptr) 
	{
		loggerM_ptr->text(LOG_DEBUG, 1, "Secure Socket - tls::connect(%s)", remoteHost.str().c_str());
	}
	bio_ptr = BIO_new_connect(const_cast<char *>(remoteHost.str().c_str()));
	if (!bio_ptr)
	{
		openSslError("creating connection");
		return false;
	}

	if (BIO_do_connect(bio_ptr) <= 0)
	{
		openSslError("connecting to remote machine");
		BIO_free(bio_ptr);
		return false;
	}

	// create the secure socket object
	if (sslM_ptr != NULL)
	{
		SSL_free(sslM_ptr);
	}
	sslM_ptr = SSL_new(ctxM_ptr);
	if (sslM_ptr == NULL)
	{
		openSslError("creating secure socket object");
		BIO_free(bio_ptr);
		return false;
	}

	// set the 'this' pointer for the callbacks openSslMsgCallback and openSslVerifyCallback
	SSL_set_msg_callback_arg(sslM_ptr, static_cast<void*>(this));

	// restore the session
	if (cacheTlsSessionsM && (savedClientSessionM_ptr != NULL))
	{
		SSL_set_session(sslM_ptr, savedClientSessionM_ptr);
		SSL_SESSION_free(savedClientSessionM_ptr); // we're done with the saved session now, we'll 
													// get a new one when the session is closed.
		savedClientSessionM_ptr = NULL;
	}

	// make the SSL connection
	SSL_set_bio(sslM_ptr, bio_ptr, bio_ptr); // the ssl takes over the mangement of the bio memory
	if (SSL_connect(sslM_ptr) <= 0)
	{
		openSslError("connecting to %s", remoteHost.str().c_str());
		SSL_free(sslM_ptr);
		sslM_ptr = NULL;
		return false;
	}

	// make sure everything is OK
	error = postConnectionCheck(sslM_ptr);
	if (error != X509_V_OK)
	{
		openSslError("checking connection parameters after connecting to %s", remoteHost.str().c_str());
		SSL_free(sslM_ptr);
		sslM_ptr = NULL;
		return false;
	}

	// socket connected to peer
	connectedM = true;

	if (loggerM_ptr && (loggerM_ptr->getLogMask() & LOG_DEBUG))
	{
		char buffer[128];

		SSL_CIPHER_description(SSL_get_current_cipher(sslM_ptr), buffer, 128);
		loggerM_ptr->text(LOG_DEBUG, 1, "Secure Socket - %s connection opened using cipher %s",
			SSL_get_version(sslM_ptr), buffer);
	}

	// return whether connected or not
	return connectedM;
}
Beispiel #14
0
/*
 * Process the inner tunnel data
 */
FR_CODE eap_fast_process(eap_session_t *eap_session, tls_session_t *tls_session)
{
	FR_CODE			code;
	VALUE_PAIR		*fast_vps = NULL;
	fr_cursor_t		cursor;
	uint8_t const		*data;
	size_t			data_len;
	eap_fast_tunnel_t	*t;
	REQUEST			*request = eap_session->request;

	/*
	 * Just look at the buffer directly, without doing
	 * record_to_buff.
	 */
	data_len = tls_session->clean_out.used;
	tls_session->clean_out.used = 0;
	data = tls_session->clean_out.data;

	t = talloc_get_type_abort(tls_session->opaque, eap_fast_tunnel_t);

	/*
	 * See if the tunneled data is well formed.
	 */
	if (!eap_fast_verify(request, tls_session, data, data_len)) return FR_CODE_ACCESS_REJECT;

	if (t->stage == EAP_FAST_TLS_SESSION_HANDSHAKE) {
		rad_assert(t->mode == EAP_FAST_UNKNOWN);

		char buf[256];
		if (strstr(SSL_CIPHER_description(SSL_get_current_cipher(tls_session->ssl),
						  buf, sizeof(buf)), "Au=None")) {
			/* FIXME enforce MSCHAPv2 - RFC 5422 section 3.2.2 */
			RDEBUG2("Using anonymous provisioning");
			t->mode = EAP_FAST_PROVISIONING_ANON;
			t->pac.send = true;
		} else {
			if (SSL_session_reused(tls_session->ssl)) {
				RDEBUG2("Session Resumed from PAC");
				t->mode = EAP_FAST_NORMAL_AUTH;
			} else {
				RDEBUG2("Using authenticated provisioning");
				t->mode = EAP_FAST_PROVISIONING_AUTH;
			}

			if (!t->pac.expires || t->pac.expired || t->pac.expires - time(NULL) < t->pac_lifetime * 0.6) {
				t->pac.send = true;
			}
		}

		eap_fast_init_keys(request, tls_session);

		eap_fast_send_identity_request(request, tls_session, eap_session);

		t->stage = EAP_FAST_AUTHENTICATION;
		return FR_CODE_ACCESS_CHALLENGE;
	}

	fr_cursor_init(&cursor, &fast_vps);
	if (eap_fast_decode_pair(request, &cursor, attr_eap_fast_tlv,
				 data, data_len, NULL) < 0) return FR_CODE_ACCESS_REJECT;

	RDEBUG2("Got Tunneled FAST TLVs");
	log_request_pair_list(L_DBG_LVL_1, request, fast_vps, NULL);
	code = eap_fast_process_tlvs(request, eap_session, tls_session, fast_vps);
	fr_pair_list_free(&fast_vps);

	if (code == FR_CODE_ACCESS_REJECT) return FR_CODE_ACCESS_REJECT;

	switch (t->stage) {
	case EAP_FAST_AUTHENTICATION:
		code = FR_CODE_ACCESS_CHALLENGE;
		break;

	case EAP_FAST_CRYPTOBIND_CHECK:
	{
		if (t->mode != EAP_FAST_PROVISIONING_ANON && !t->pac.send)
			t->result_final = true;

		eap_fast_append_result(tls_session, code);

		eap_fast_update_icmk(request, tls_session, (uint8_t *)&t->isk);
		eap_fast_append_crypto_binding(request, tls_session);

		code = FR_CODE_ACCESS_CHALLENGE;
		break;
	}
	case EAP_FAST_PROVISIONING:
		t->result_final = true;

		eap_fast_append_result(tls_session, code);

		if (t->pac.send) {
			RDEBUG2("Peer requires new PAC");
			eap_fast_send_pac_tunnel(request, tls_session);
			code = FR_CODE_ACCESS_CHALLENGE;
			break;
		}

		t->stage = EAP_FAST_COMPLETE;
		/* fallthrough */
	case EAP_FAST_COMPLETE:
		/*
		 * RFC 5422 section 3.5 - Network Access after EAP-FAST Provisioning
		 */
		if (t->pac.type && t->pac.expired) {
			REDEBUG("Rejecting expired PAC.");
			code = FR_CODE_ACCESS_REJECT;
			break;
		}

		if (t->mode == EAP_FAST_PROVISIONING_ANON) {
			REDEBUG("Rejecting unauthenticated provisioning");
			code = FR_CODE_ACCESS_REJECT;
			break;
		}

		/*
		 * eap_crypto_mppe_keys() is unsuitable for EAP-FAST as Cisco decided
		 * it would be a great idea to flip the recv/send keys around
		 */
		#define EAPTLS_MPPE_KEY_LEN 32
		eap_add_reply(request, attr_ms_mppe_recv_key, t->msk, EAPTLS_MPPE_KEY_LEN);
		eap_add_reply(request, attr_ms_mppe_send_key, &t->msk[EAPTLS_MPPE_KEY_LEN], EAPTLS_MPPE_KEY_LEN);
		eap_add_reply(request, attr_eap_msk, t->msk, EAP_FAST_KEY_LEN);
		eap_add_reply(request, attr_eap_emsk, t->emsk, EAP_EMSK_LEN);

		break;

	default:
		RERROR("Internal sanity check failed in EAP-FAST at %d", t->stage);
		code = FR_CODE_ACCESS_REJECT;
	}

	return code;
}
Beispiel #15
0
static void tls_list(rpc_t* rpc, void* c)
{
	char buf[128];
	char src_ip[IP_ADDR_MAX_STR_SIZE];
	char dst_ip[IP_ADDR_MAX_STR_SIZE];
	void* handle;
	char* tls_info;
	char* state;
	struct tls_extra_data* tls_d;
	struct tcp_connection* con;
	int i, len, timeout;

	TCPCONN_LOCK;
	for(i = 0; i < TCP_ID_HASH_SIZE; i++) {
		for (con = tcpconn_id_hash[i]; con; con = con->id_next) {
			if (con->rcv.proto != PROTO_TLS) continue;
			tls_d = con->extra_data;
			rpc->add(c, "{", &handle);
			/* tcp data */
			if ((len = ip_addr2sbuf(&con->rcv.src_ip, src_ip, sizeof(src_ip)))
					== 0)
				BUG("failed to convert source ip");
			src_ip[len] = 0;
			if ((len = ip_addr2sbuf(&con->rcv.dst_ip, dst_ip, sizeof(dst_ip)))
					== 0)
				BUG("failed to convert destination ip");
			dst_ip[len] = 0;
			timeout = TICKS_TO_S(con->timeout - get_ticks_raw());
			rpc->struct_add(handle, "ddsdsd",
					"id", con->id,
					"timeout", timeout,
					"src_ip", src_ip,
					"src_port", con->rcv.src_port,
					"dst_ip", dst_ip,
					"dst_port", con->rcv.dst_port);
			if (tls_d) {
				if(SSL_get_current_cipher(tls_d->ssl)) {
					tls_info = SSL_CIPHER_description(
									SSL_get_current_cipher(tls_d->ssl),
									buf, sizeof(buf));
					len = strlen(buf);
					if (len && buf[len - 1] == '\n') buf[len - 1] = '\0';
				} else {
					tls_info = "unknown";
				}
				/* tls data */
				state = "unknown/error";
				lock_get(&con->write_lock);
					switch(tls_d->state) {
						case S_TLS_NONE:
							state = "none/init";
							break;
						case S_TLS_ACCEPTING:
							state = "tls_accept";
							break;
						case S_TLS_CONNECTING:
							state = "tls_connect";
							break;
						case S_TLS_ESTABLISHED:
							state = "established";
							break;
					}
					rpc->struct_add(handle, "sddds",
							"cipher", tls_info,
							"ct_wq_size", tls_d->ct_wq?
											tls_d->ct_wq->queued:0,
							"enc_rd_buf", tls_d->enc_rd_buf?
											tls_d->enc_rd_buf->size:0,
							"flags", tls_d->flags,
							"state", state
							);
				lock_release(&con->write_lock);
			} else {
				rpc->struct_add(handle, "sddds",
						"cipher", "unknown",
						"ct_wq_size", 0,
						"enc_rd_buf", 0,
						"flags", 0,
						"state", "pre-init"
						);
			}
		}
	}
	TCPCONN_UNLOCK;
}
Beispiel #16
0
int main(int argc, char *argv[])
{
    SSL_CTX *ctx;
    SSL *ssl;
    BIO *bio;
    int (*callback)(char *, int, int, void *) = &password_callback;

	SSL_library_init();

    SSL_load_error_strings();
    ERR_load_BIO_strings();
    ERR_load_SSL_strings();

    printf("Attempting to create SSL context...\n");
    ctx = SSL_CTX_new(SSLv3_client_method());
    if(ctx == NULL) {
        printf("Failed. Aborting.\n");
        ERR_print_errors_fp(stdout);
        return 0;
    }

    printf("\nLoading certificates...\n");
    SSL_CTX_set_default_passwd_cb(ctx, callback);
	if (!SSL_CTX_load_verify_locations(ctx, "./CAtest/cacert.pem", NULL)) {
		/* Handle failed load here */
        ERR_print_errors_fp(stdout);
		exit(1);
	}
	if (SSL_CTX_use_certificate_file(ctx, "./CAtest/client_cert.pem", SSL_FILETYPE_PEM) != 1) {
	//if (SSL_CTX_use_certificate_chain_file(ctx, "./CA/client_cert.pem") != 1) {
		/* Handle failed load here */
		ERR_print_errors_fp(stdout);
		exit(1);
	}
	if (SSL_CTX_use_PrivateKey_file(ctx, "./CAtest/private/client_key.pem", SSL_FILETYPE_PEM) != 1) {
		/* Handle failed load here */
		ERR_print_errors_fp(stdout);
		exit(1);
	}

	SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback);
	SSL_CTX_set_verify_depth(ctx, 5);

    //SSL_CTX_set_default_passwd_cb(ctx, callback);
    printf("Attempting to create BIO object...\n");
    bio = BIO_new_ssl_connect(ctx);
    if(bio == NULL) {
        printf("Failed. Aborting.\n");
        ERR_print_errors_fp(stdout);
        SSL_CTX_free(ctx);
        return 0;
    }

    printf("\nAttempting to set up BIO for SSL...\n");
    BIO_get_ssl(bio, &ssl);
    SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY);

	BIO_set_conn_hostname(bio, "127.0.0.1:4422");
	if (BIO_do_connect(bio) <= 0) {
        printf("BIO_do_connect failed\n");
		/* Handle failed connection */
        ERR_print_errors_fp(stdout);
		exit (1);
	}
	if(SSL_get_verify_result(ssl) != X509_V_OK) {
        printf("SSL_get_verify_result failed\n");
		/* Handle the failed verification */
        ERR_print_errors_fp(stdout);
		//exit (1);
	}

	SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
	if (cipher) {
		char buf[1204];
		printf("Cipher Name: %s\n", SSL_CIPHER_get_name(cipher));
		printf("Cipher Desc: %s\n", SSL_CIPHER_description(cipher, buf, 1024));
	}

	int len = 1024;
	char buf[len];
	BIO_puts(bio, "Hello Server, this is just for test!");
	BIO_flush(bio);
	BIO_read(bio, buf, len);
	printf("Received: %s\n", buf);

	SSL_CTX_free(ctx);
	/* To reuse the connection, use this line */
	BIO_reset(bio);
	/* To free it from memory, use this line */
	BIO_free_all(bio);

	return 0;
}
Beispiel #17
0
bool TLS_SOCKET_CLASS::accept(BASE_SOCKET_CLASS** acceptedSocket_ptr_ptr)

//  DESCRIPTION     : Accept connection from listen socket.
//  PRECONDITIONS   :
//  POSTCONDITIONS  :
//  EXCEPTIONS      : 
//  NOTES           : The returned socket was new'ed so it must be deleted by the caller
//<<===========================================================================
{
	*acceptedSocket_ptr_ptr = NULL;
	BIO* acceptedBio_ptr;
	SSL* acceptedSsl_ptr;
	long error;
	int fileDesc;
	struct fd_set fds;
	struct timeval tv = {1, 0}; // always timeout in 1 second
	int sel;

	if (terminatingM)
	{
		if (loggerM_ptr) 
		{
			loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - In process of terminating.  Cannot accept.");
		}

		// return - in process of termintating
		return false;
	}

	// make sure we are listening to the port
	if (!listeningM)
	{
		if (loggerM_ptr)
		{
			loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Socket is not listening to port %d.  Cannot accept a connection.", 
				localListenPortM);
		}
		return false;
	}
	if (acceptBioM_ptr == NULL)
	{
		if (loggerM_ptr)
		{
			loggerM_ptr->text(LOG_ERROR, 1, "Secure Socket - Socket is listening to port %d, but not bound.", 
				localListenPortM);
		}
		listeningM = false;
		return false;
	}

	if (loggerM_ptr) 
	{
		loggerM_ptr->text(LOG_DEBUG, 1, "Secure Socket - tls::accept()");
	}

	// get the file descriptor and set up the file descriptor set for select()
	fileDesc = BIO_get_fd(acceptBioM_ptr, NULL);
	if (fileDesc == -1)
	{
		openSslError("getting listen socket file descriptor");
		return false;
	}

	// wait for a connection
	do
	{
		FD_ZERO(&fds);
		FD_SET(fileDesc, &fds);

		sel = select(fileDesc + 1, &fds, NULL, NULL, &tv);
		if (sel == 0)
		{
			// no data at the end of the timeout - check for terminating
			if (terminatingM)
			{
				return false;
			}
		}
		else if (sel == SOCKET_ERROR)
		{
			// socket error
			if (loggerM_ptr)
			{
				loggerM_ptr->text(LOG_ERROR, 2, "Secure Socket - Error waiting to accept connection (error code %d)", WSAGetLastError());
			}
			return false;
		}
		else if (sel != 1)
		{
			// unknown error
			if (loggerM_ptr)
			{
				loggerM_ptr->text(LOG_ERROR, 2, "Secure Socket - Unknown error while waiting to accept connection (select returned %d)", sel);
			}
			return false;
		}

	} while (sel != 1);

	// accept a connection
	if (BIO_do_accept(acceptBioM_ptr) <= 0)
	{
		openSslError(LOG_DEBUG, "accepting connection on port %d", localListenPortM);
		close();
		return false;
	}

	// get the new connection
	acceptedBio_ptr = BIO_pop(acceptBioM_ptr);

	// setup the socket structure
	acceptedSsl_ptr = SSL_new(ctxM_ptr);
	if (acceptedSsl_ptr == NULL)
	{
		openSslError("creating accepted secure socket object");
		BIO_free(acceptedBio_ptr);
		return false;
	}

	// set the 'this' pointer for the callbacks openSslMsgCallback and openSslVerifyCallback
	SSL_set_msg_callback_arg(acceptedSsl_ptr, static_cast<void*>(this));

	SSL_set_accept_state(acceptedSsl_ptr);
	SSL_set_bio(acceptedSsl_ptr, acceptedBio_ptr, acceptedBio_ptr); // the ssl takes over the BIO memory
	if (SSL_accept(acceptedSsl_ptr) <= 0)
	{
		openSslError("accepting secure connection to port %d", localListenPortM);
		SSL_free(acceptedSsl_ptr);
		return false;
	}

	// make sure everything is OK
	error = postConnectionCheck(acceptedSsl_ptr);
	if (error != X509_V_OK)
	{
		openSslError("checking connection parameters after accepting from port %d", localListenPortM);
		SSL_free(acceptedSsl_ptr);
		return false;
	}

	// create a socket for the new connection
	*acceptedSocket_ptr_ptr = new TLS_SOCKET_CLASS(*this, acceptedSsl_ptr);

	if (loggerM_ptr && (loggerM_ptr->getLogMask() & LOG_DEBUG))
	{
		char buffer[128];

		SSL_CIPHER_description(SSL_get_current_cipher(acceptedSsl_ptr), buffer, 128);
		loggerM_ptr->text(LOG_DEBUG, 1, "Secure Socket - %s connection opened using cipher %s",
			SSL_get_version(acceptedSsl_ptr), buffer);
	}

	return true;
}