Exemplo n.º 1
0
/* Return -1 on error, 0 or success. */
int
ssl_connect(struct socket *socket)
{
	int ret;
	unsigned char *server_name;
	struct connection *conn = (struct connection *)socket->conn;

	/* TODO: Recode server_name to UTF-8.  */
	server_name = get_uri_string(conn->proxied_uri, URI_HOST);
	if (!server_name) {
		socket->ops->done(socket, connection_state(S_OUT_OF_MEM));
		return -1;
	}

	/* RFC 3546 says literal IPv4 and IPv6 addresses are not allowed.  */
	if (is_ip_address(server_name, strlen((const char *)server_name)))
		mem_free_set(&server_name, NULL);

	if (init_ssl_connection(socket, server_name) == S_SSL_ERROR) {
		mem_free_if(server_name);
		socket->ops->done(socket, connection_state(S_SSL_ERROR));
		return -1;
	}

	mem_free_if(server_name);

	if (socket->no_tls)
		ssl_set_no_tls(socket);

#ifdef USE_OPENSSL
	SSL_set_fd((SSL *)socket->ssl, socket->fd);

	if (get_opt_bool((const unsigned char *)"connection.ssl.cert_verify", NULL))
		SSL_set_verify((SSL *)socket->ssl, SSL_VERIFY_PEER
					  | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
			       verify_callback);

	if (get_opt_bool((const unsigned char *)"connection.ssl.client_cert.enable", NULL)) {
		unsigned char *client_cert;

#ifdef CONFIG_NSS_COMPAT_OSSL
		client_cert = get_opt_str(
				(const unsigned char *)"connection.ssl.client_cert.nickname", NULL);
#else
		client_cert = get_opt_str(
				(const unsigned char *)"connection.ssl.client_cert.file", NULL);
#endif
		if (!*client_cert) {
			client_cert = (unsigned char *)getenv("X509_CLIENT_CERT");
			if (client_cert && !*client_cert)
				client_cert = NULL;
		}

		if (client_cert) {
#ifdef CONFIG_NSS_COMPAT_OSSL
			SSL_CTX_use_certificate_chain_file(
					(SSL *) socket->ssl,
					(const char *)client_cert);
#else
			SSL_CTX *ctx = ((SSL *) socket->ssl)->ctx;

			SSL_CTX_use_certificate_chain_file(ctx, (const char *)client_cert);
			SSL_CTX_use_PrivateKey_file(ctx, (const char *)client_cert,
						    SSL_FILETYPE_PEM);
#endif
		}
	}

#elif defined(CONFIG_GNUTLS)
	/* GnuTLS uses function pointers for network I/O.  The default
	 * functions take a file descriptor, but it must be passed in
	 * as a pointer.  GnuTLS uses the GNUTLS_INT_TO_POINTER and
	 * GNUTLS_POINTER_TO_INT macros for these conversions, but
	 * those are unfortunately not in any public header.  So
	 * ELinks must just cast the pointer the best it can and hope
	 * that the conversions match.  */
	gnutls_transport_set_ptr(*((ssl_t *) socket->ssl),
				 (gnutls_transport_ptr_t) (longptr_T) socket->fd);

	/* TODO: Some certificates fuss. --pasky */
#endif

	ret = ssl_do_connect(socket);

	switch (ret) {
		case SSL_ERROR_WANT_READ:
		case SSL_ERROR_WANT_READ2:
			socket->ops->set_state(socket, connection_state(S_SSL_NEG));
			set_handlers(socket->fd, (select_handler_T) ssl_want_read,
				     NULL, (select_handler_T) dns_exception, socket);
			return -1;

		case SSL_ERROR_NONE:
#ifdef CONFIG_GNUTLS
			if (!get_opt_bool((const unsigned char *)"connection.ssl.cert_verify", NULL))
				break;

			if (!verify_certificates(socket))
#endif
				break;

		default:
			if (ret != SSL_ERROR_NONE) {
				/* DBG("sslerr %s", gnutls_strerror(ret)); */
				socket->no_tls = !socket->no_tls;
			}

			connect_socket(socket, connection_state(S_SSL_ERROR));
			return -1;
	}

	return 0;
}
Exemplo n.º 2
0
/*
 * Initialize SSL sub module
 *
 * Arguments: None
 * Returns:   None
 */
void
initSSL(void)
{
    static void *ssl_API[ssl_API_pointers];
    PyObject *ssl_api_object;
    PyObject *module;

    SSL_library_init();
    ERR_load_SSL_strings();

    import_crypto();

    if ((module = Py_InitModule3("SSL", ssl_methods, ssl_doc)) == NULL) {
        return;
    }

    /* Initialize the C API pointer array */
    ssl_API[ssl_Context_New_NUM]    = (void *)ssl_Context_New;
    ssl_API[ssl_Connection_New_NUM] = (void *)ssl_Connection_New;
    ssl_api_object = PyCObject_FromVoidPtr((void *)ssl_API, NULL);
    if (ssl_api_object != NULL)
        PyModule_AddObject(module, "_C_API", ssl_api_object);

    /* Exceptions */
/*
 * ADD_EXCEPTION(dict,name,base) expands to a correct Exception declaration,
 * inserting OpenSSL.SSL.name into dict, derviving the exception from base.
 */
#define ADD_EXCEPTION(_name, _base)                                    \
do {                                                                          \
    ssl_##_name = PyErr_NewException("OpenSSL.SSL."#_name, _base, NULL);\
    if (ssl_##_name == NULL)                                            \
        goto error;                                                           \
    if (PyModule_AddObject(module, #_name, ssl_##_name) != 0)           \
        goto error;                                                           \
} while (0)

    ssl_Error = PyErr_NewException("OpenSSL.SSL.Error", NULL, NULL);
    if (ssl_Error == NULL)
        goto error;
    if (PyModule_AddObject(module, "Error", ssl_Error) != 0)
        goto error;

    ADD_EXCEPTION(ZeroReturnError,     ssl_Error);
    ADD_EXCEPTION(WantReadError,       ssl_Error);
    ADD_EXCEPTION(WantWriteError,      ssl_Error);
    ADD_EXCEPTION(WantX509LookupError, ssl_Error);
    ADD_EXCEPTION(SysCallError,        ssl_Error);
#undef ADD_EXCEPTION

    /* Method constants */
    PyModule_AddIntConstant(module, "SSLv2_METHOD",  ssl_SSLv2_METHOD);
    PyModule_AddIntConstant(module, "SSLv3_METHOD",  ssl_SSLv3_METHOD);
    PyModule_AddIntConstant(module, "SSLv23_METHOD", ssl_SSLv23_METHOD);
    PyModule_AddIntConstant(module, "TLSv1_METHOD",  ssl_TLSv1_METHOD);

    /* Verify constants */
    PyModule_AddIntConstant(module, "VERIFY_NONE", SSL_VERIFY_NONE);
    PyModule_AddIntConstant(module, "VERIFY_PEER", SSL_VERIFY_PEER);
    PyModule_AddIntConstant(module, "VERIFY_FAIL_IF_NO_PEER_CERT",
                            SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
    PyModule_AddIntConstant(module, "VERIFY_CLIENT_ONCE",
                            SSL_VERIFY_CLIENT_ONCE);

    /* File type constants */
    PyModule_AddIntConstant(module, "FILETYPE_PEM",  SSL_FILETYPE_PEM);
    PyModule_AddIntConstant(module, "FILETYPE_ASN1", SSL_FILETYPE_ASN1);

    /* SSL option constants */
    PyModule_AddIntConstant(module, "OP_SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE);
    PyModule_AddIntConstant(module, "OP_EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA);
    PyModule_AddIntConstant(module, "OP_NO_SSLv2", SSL_OP_NO_SSLv2);
    PyModule_AddIntConstant(module, "OP_NO_SSLv3", SSL_OP_NO_SSLv3);
    PyModule_AddIntConstant(module, "OP_NO_TLSv1", SSL_OP_NO_TLSv1);

    /* More SSL option constants */
    PyModule_AddIntConstant(module, "OP_MICROSOFT_SESS_ID_BUG", SSL_OP_MICROSOFT_SESS_ID_BUG);
    PyModule_AddIntConstant(module, "OP_NETSCAPE_CHALLENGE_BUG", SSL_OP_NETSCAPE_CHALLENGE_BUG);
    PyModule_AddIntConstant(module, "OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG);
    PyModule_AddIntConstant(module, "OP_SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG);
    PyModule_AddIntConstant(module, "OP_MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER);
    PyModule_AddIntConstant(module, "OP_MSIE_SSLV2_RSA_PADDING", SSL_OP_MSIE_SSLV2_RSA_PADDING);
    PyModule_AddIntConstant(module, "OP_SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG);
    PyModule_AddIntConstant(module, "OP_TLS_D5_BUG", SSL_OP_TLS_D5_BUG);
    PyModule_AddIntConstant(module, "OP_TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG);
    PyModule_AddIntConstant(module, "OP_DONT_INSERT_EMPTY_FRAGMENTS", SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
    PyModule_AddIntConstant(module, "OP_ALL", SSL_OP_ALL);
    PyModule_AddIntConstant(module, "OP_CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE);
    PyModule_AddIntConstant(module, "OP_TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG);
    PyModule_AddIntConstant(module, "OP_PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1);
    PyModule_AddIntConstant(module, "OP_PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2);
    PyModule_AddIntConstant(module, "OP_NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG);
    PyModule_AddIntConstant(module, "OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);

    /* DTLS related options.  The first two of these were introduced in
     * 2005, the third in 2007.  To accomodate systems which are still using
     * older versions, make them optional. */
#ifdef SSL_OP_NO_QUERY_MTU
    PyModule_AddIntConstant(module, "OP_NO_QUERY_MTU", SSL_OP_NO_QUERY_MTU);
#endif
#ifdef SSL_OP_COOKIE_EXCHANGE
    PyModule_AddIntConstant(module, "OP_COOKIE_EXCHANGE", SSL_OP_COOKIE_EXCHANGE);
#endif
#ifdef SSL_OP_NO_TICKET
    PyModule_AddIntConstant(module, "OP_NO_TICKET", SSL_OP_NO_TICKET);
#endif

    /* For SSL_set_shutdown */
    PyModule_AddIntConstant(module, "SENT_SHUTDOWN", SSL_SENT_SHUTDOWN);
    PyModule_AddIntConstant(module, "RECEIVED_SHUTDOWN", SSL_RECEIVED_SHUTDOWN);

    if (!init_ssl_context(module))
        goto error;
    if (!init_ssl_connection(module))
        goto error;

#ifdef WITH_THREAD
    /*
     * Initialize this module's threading support structures.
     */
    _pyOpenSSL_tstate_key = PyThread_create_key();
#endif

  error:
    ;
}
int dtls_get_data (int s, SSL_CTX *ctx)
{
	char *buf = NULL;
	fd_set readfds;
	int ret = 1, width = 0;
	int i = 0;
	SSL *con = NULL;
	BIO *sbio = NULL;
	int bufsize = BUFSIZ;
	bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);
	bio_s_out = BIO_new_fp (stderr, BIO_NOCLOSE);

	
	if ((buf = OPENSSL_malloc (bufsize)) == NULL)
	{
		BIO_printf (bio_err, "out of memory\n");
		goto ERR;
	}

	if (con == NULL) 
	{
		con = SSL_new(ctx);
	}
	SSL_clear (con);

	if (SSL_version (con) == DTLS1_VERSION)
	{
		struct timeval timeout;

		sbio = BIO_new_dgram (s, BIO_NOCLOSE);

		timeout.tv_sec = 5;
		timeout.tv_usec = 0;
		BIO_ctrl (sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
			
		timeout.tv_sec = 5;
		timeout.tv_usec = 0;
		BIO_ctrl (sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);

		
			/* want to do MTU discovery */
		BIO_ctrl (sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);

	        /* turn on cookie exchange */
        	SSL_set_options (con, SSL_OP_COOKIE_EXCHANGE);
//		fprintf (stderr, "%s: %s(): DTLSv1 Initialization done\n", __FILE__, __func__);
	}

	SSL_set_bio (con, sbio, sbio);
	SSL_set_accept_state (con);
	/* SSL_set_fd(con,s); */

	width = s + 1;
	for (;;)
	{
		int read_from_terminal;
		int read_from_sslcon;

		read_from_terminal = 0;
		read_from_sslcon = SSL_pending (con);

		if (!read_from_sslcon)
		{
			struct timeval tv;
			FD_ZERO(&readfds);
			FD_SET(s, &readfds);
			tv.tv_sec = 1;
			tv.tv_usec = 0;
			i = select(width, (void *)&readfds, NULL, NULL, &tv);
			if (i < 0)
			{
				continue;
			}
			if (FD_ISSET (s, &readfds))
			{
				read_from_sslcon = 1;
			}
			else
			{
				ret = 2;
				goto shut;
			}
		}
		if (read_from_sslcon)
		{
			if (!SSL_is_init_finished(con))
			{
				i = init_ssl_connection(con);
			
				if (i < 0)
				{
					ret = 0;
					goto ERR;
				}
				else if (i == 0)
				{
					ret = 1;
					goto ERR;
				}
			}
			else
			{
AGAIN:	
				i = SSL_read (con, (char *) buf, bufsize);
				switch (SSL_get_error (con, i))
				{
					case SSL_ERROR_NONE:
						write (fileno (stdout), buf, (unsigned int) i);
						if (SSL_pending(con)) 
						{
							fprintf (stderr, "%s: %s(): Some more seems to be coming... "\
								"letz wait for that\n", __FILE__, __func__);
							goto AGAIN;
						}
						else
							fprintf (stderr, "%s(): Hey, itz all over boss... do finishing "\
								"ceremony\n", __func__);
						ret = 0;
						goto ERR;
					case SSL_ERROR_WANT_WRITE:
					case SSL_ERROR_WANT_READ:
					case SSL_ERROR_WANT_X509_LOOKUP:
						BIO_printf(bio_s_out,"Read BLOCK\n");
						break;
					case SSL_ERROR_SYSCALL:
					case SSL_ERROR_SSL:
						BIO_printf(bio_s_out,"ERROR\n");
						ERR_print_errors(bio_err);
						ret = 1;
						goto ERR;
					case SSL_ERROR_ZERO_RETURN:
						BIO_printf(bio_s_out,"\nDONE\n");
						ret = 0;
						goto ERR;
				}
			}
		}
	}
ERR:
	if (0 == ret)
	{
		char temp [] = "ACK from SERVER: READ SUCCESSFULLY DONE\n";
		for (;;)
		{
			i = SSL_write (con, temp, strlen (temp));

			switch (SSL_get_error (con, i))
			{
				case SSL_ERROR_NONE:
					if (SSL_pending (con))
						break;
					else
						goto WRITEDONE;
				case SSL_ERROR_WANT_WRITE:
				case SSL_ERROR_WANT_READ:
				case SSL_ERROR_WANT_X509_LOOKUP:
					BIO_printf (bio_s_out, "Write BLOCK\n");
					break;
				case SSL_ERROR_SYSCALL:
				case SSL_ERROR_SSL:
					BIO_printf (bio_s_out, "ERROR\n");
					ERR_print_errors (bio_err);
					ret = 1;
					goto WRITEDONE;
				case SSL_ERROR_ZERO_RETURN:
					BIO_printf (bio_s_out, "\nDONE\n");
					ret = 1;
					goto WRITEDONE;
			}
		}
	}
WRITEDONE:
#ifdef DEBUG
	BIO_printf (bio_s_out, "shutting down SSL\n");
	print_stats (bio_s_out, ctx);
#endif
#if 1
	SSL_set_shutdown (con, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
#else
	SSL_shutdown(con);
#endif
shut:
	if (con != NULL) SSL_free (con);
	if (2 != ret)
		BIO_printf(bio_s_out,"CONNECTION CLOSED\n");

	if (buf != NULL)
	{
		OPENSSL_cleanse (buf, bufsize);
		OPENSSL_free (buf);
	}

	if ((ret >= 0) && (2 != ret))
		BIO_printf (bio_s_out, "ACCEPT\n");
	return(ret);
}