ssltest.c

来自「一个用于点对点传输加密的工具包源码」· C语言 代码 · 共 1,371 行 · 第 1/3 页

C
1,371
字号
		{		/* fprintf(stderr,"SSL_load_verify_locations\n"); */		ERR_print_errors(bio_err);		/* goto end; */		}	if (client_auth)		{		BIO_printf(bio_err,"client authentication\n");		SSL_CTX_set_verify(s_ctx,			SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,			verify_callback);		}	if (server_auth)		{		BIO_printf(bio_err,"server authentication\n");		SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER,			verify_callback);		}		{		int session_id_context = 0;		SSL_CTX_set_session_id_context(s_ctx, (void *)&session_id_context, sizeof session_id_context);	}	c_ssl=SSL_new(c_ctx);	s_ssl=SSL_new(s_ctx);	for (i=0; i<number; i++)		{		if (!reuse) SSL_set_session(c_ssl,NULL);		if (bio_pair)			ret=doit_biopair(s_ssl,c_ssl,bytes,&s_time,&c_time);		else			ret=doit(s_ssl,c_ssl,bytes);		}	if (!verbose)		{		print_details(c_ssl, "");		}	if ((number > 1) || (bytes > 1L))		BIO_printf(bio_stdout, "%d handshakes of %ld bytes done\n",number,bytes);	if (print_time)		{#ifdef CLOCKS_PER_SEC		/* "To determine the time in seconds, the value returned		 * by the clock function should be divided by the value		 * of the macro CLOCKS_PER_SEC."		 *                                       -- ISO/IEC 9899 */		BIO_printf(bio_stdout, "Approximate total server time: %6.2f s\n"			"Approximate total client time: %6.2f s\n",			(double)s_time/CLOCKS_PER_SEC,			(double)c_time/CLOCKS_PER_SEC);#else		/* "`CLOCKS_PER_SEC' undeclared (first use this function)"		 *                            -- cc on NeXTstep/OpenStep */		BIO_printf(bio_stdout,			"Approximate total server time: %6.2f units\n"			"Approximate total client time: %6.2f units\n",			(double)s_time,			(double)c_time);#endif		}	SSL_free(s_ssl);	SSL_free(c_ssl);end:	if (s_ctx != NULL) SSL_CTX_free(s_ctx);	if (c_ctx != NULL) SSL_CTX_free(c_ctx);	if (bio_stdout != NULL) BIO_free(bio_stdout);#ifndef NO_RSA	free_tmp_rsa();#endif	ERR_free_strings();	ERR_remove_state(0);	EVP_cleanup();	CRYPTO_mem_leaks(bio_err);	if (bio_err != NULL) BIO_free(bio_err);	EXIT(ret);	}int doit_biopair(SSL *s_ssl, SSL *c_ssl, long count,	clock_t *s_time, clock_t *c_time)	{	long cw_num = count, cr_num = count, sw_num = count, sr_num = count;	BIO *s_ssl_bio = NULL, *c_ssl_bio = NULL;	BIO *server = NULL, *server_io = NULL, *client = NULL, *client_io = NULL;	int ret = 1;		size_t bufsiz = 256; /* small buffer for testing */	if (!BIO_new_bio_pair(&server, bufsiz, &server_io, bufsiz))		goto err;	if (!BIO_new_bio_pair(&client, bufsiz, &client_io, bufsiz))		goto err;		s_ssl_bio = BIO_new(BIO_f_ssl());	if (!s_ssl_bio)		goto err;	c_ssl_bio = BIO_new(BIO_f_ssl());	if (!c_ssl_bio)		goto err;	SSL_set_connect_state(c_ssl);	SSL_set_bio(c_ssl, client, client);	(void)BIO_set_ssl(c_ssl_bio, c_ssl, BIO_NOCLOSE);	SSL_set_accept_state(s_ssl);	SSL_set_bio(s_ssl, server, server);	(void)BIO_set_ssl(s_ssl_bio, s_ssl, BIO_NOCLOSE);	do		{		/* c_ssl_bio:          SSL filter BIO		 *		 * client:             pseudo-I/O for SSL library		 *		 * client_io:          client's SSL communication; usually to be		 *                     relayed over some I/O facility, but in this		 *                     test program, we're the server, too:		 *		 * server_io:          server's SSL communication		 *		 * server:             pseudo-I/O for SSL library		 *		 * s_ssl_bio:          SSL filter BIO		 *		 * The client and the server each employ a "BIO pair":		 * client + client_io, server + server_io.		 * BIO pairs are symmetric.  A BIO pair behaves similar		 * to a non-blocking socketpair (but both endpoints must		 * be handled by the same thread).		 * [Here we could connect client and server to the ends		 * of a single BIO pair, but then this code would be less		 * suitable as an example for BIO pairs in general.]		 *		 * Useful functions for querying the state of BIO pair endpoints:		 *		 * BIO_ctrl_pending(bio)              number of bytes we can read now		 * BIO_ctrl_get_read_request(bio)     number of bytes needed to fulfil		 *                                      other side's read attempt		 * BIO_ctrl_get_write_guarantee(bio)   number of bytes we can write now		 *		 * ..._read_request is never more than ..._write_guarantee;		 * it depends on the application which one you should use.		 */		/* We have non-blocking behaviour throughout this test program, but		 * can be sure that there is *some* progress in each iteration; so		 * we don't have to worry about ..._SHOULD_READ or ..._SHOULD_WRITE		 * -- we just try everything in each iteration		 */			{			/* CLIENT */					MS_STATIC char cbuf[1024*8];			int i, r;			clock_t c_clock = clock();			if (debug)				if (SSL_in_init(c_ssl))					printf("client waiting in SSL_connect - %s\n",						SSL_state_string_long(c_ssl));			if (cw_num > 0)				{				/* Write to server. */								if (cw_num > (long)sizeof cbuf)					i = sizeof cbuf;				else					i = (int)cw_num;				r = BIO_write(c_ssl_bio, cbuf, i);				if (r < 0)					{					if (!BIO_should_retry(c_ssl_bio))						{						fprintf(stderr,"ERROR in CLIENT\n");						goto err;						}					/* BIO_should_retry(...) can just be ignored here.					 * The library expects us to call BIO_write with					 * the same arguments again, and that's what we will					 * do in the next iteration. */					}				else if (r == 0)					{					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");					goto err;					}				else					{					if (debug)						printf("client wrote %d\n", r);					cw_num -= r;									}				}			if (cr_num > 0)				{				/* Read from server. */				r = BIO_read(c_ssl_bio, cbuf, sizeof(cbuf));				if (r < 0)					{					if (!BIO_should_retry(c_ssl_bio))						{						fprintf(stderr,"ERROR in CLIENT\n");						goto err;						}					/* Again, "BIO_should_retry" can be ignored. */					}				else if (r == 0)					{					fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");					goto err;					}				else					{					if (debug)						printf("client read %d\n", r);					cr_num -= r;					}				}			/* c_time and s_time increments will typically be very small			 * (depending on machine speed and clock tick intervals),			 * but sampling over a large number of connections should			 * result in fairly accurate figures.  We cannot guarantee			 * a lot, however -- if each connection lasts for exactly			 * one clock tick, it will be counted only for the client			 * or only for the server or even not at all.			 */			*c_time += (clock() - c_clock);			}			{			/* SERVER */					MS_STATIC char sbuf[1024*8];			int i, r;			clock_t s_clock = clock();			if (debug)				if (SSL_in_init(s_ssl))					printf("server waiting in SSL_accept - %s\n",						SSL_state_string_long(s_ssl));			if (sw_num > 0)				{				/* Write to client. */								if (sw_num > (long)sizeof sbuf)					i = sizeof sbuf;				else					i = (int)sw_num;				r = BIO_write(s_ssl_bio, sbuf, i);				if (r < 0)					{					if (!BIO_should_retry(s_ssl_bio))						{						fprintf(stderr,"ERROR in SERVER\n");						goto err;						}					/* Ignore "BIO_should_retry". */					}				else if (r == 0)					{					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");					goto err;					}				else					{					if (debug)						printf("server wrote %d\n", r);					sw_num -= r;									}				}			if (sr_num > 0)				{				/* Read from client. */				r = BIO_read(s_ssl_bio, sbuf, sizeof(sbuf));				if (r < 0)					{					if (!BIO_should_retry(s_ssl_bio))						{						fprintf(stderr,"ERROR in SERVER\n");						goto err;						}					/* blah, blah */					}				else if (r == 0)					{					fprintf(stderr,"SSL SERVER STARTUP FAILED\n");					goto err;					}				else					{					if (debug)						printf("server read %d\n", r);					sr_num -= r;					}				}			*s_time += (clock() - s_clock);			}						{			/* "I/O" BETWEEN CLIENT AND SERVER. */			size_t r1, r2;			BIO *io1 = server_io, *io2 = client_io;			/* we use the non-copying interface for io1			 * and the standard BIO_write/BIO_read interface for io2			 */						static int prev_progress = 1;			int progress = 0;						/* io1 to io2 */			do				{				size_t num;				int r;				r1 = BIO_ctrl_pending(io1);				r2 = BIO_ctrl_get_write_guarantee(io2);				num = r1;				if (r2 < num)					num = r2;				if (num)					{					char *dataptr;					if (INT_MAX < num) /* yeah, right */						num = INT_MAX;										r = BIO_nread(io1, &dataptr, (int)num);					assert(r > 0);					assert(r <= (int)num);					/* possibly r < num (non-contiguous data) */					num = r;					r = BIO_write(io2, dataptr, (int)num);					if (r != (int)num) /* can't happen */						{						fprintf(stderr, "ERROR: BIO_write could not write "							"BIO_ctrl_get_write_guarantee() bytes");						goto err;						}					progress = 1;					if (debug)						printf((io1 == client_io) ?							"C->S relaying: %d bytes\n" :							"S->C relaying: %d bytes\n",							(int)num);					}				}			while (r1 && r2);			/* io2 to io1 */			{				size_t num;				int r;				r1 = BIO_ctrl_pending(io2);				r2 = BIO_ctrl_get_read_request(io1);				/* here we could use ..._get_write_guarantee instead of				 * ..._get_read_request, but by using the latter				 * we test restartability of the SSL implementation				 * more thoroughly */				num = r1;				if (r2 < num)					num = r2;				if (num)					{					char *dataptr;										if (INT_MAX < num)						num = INT_MAX;					if (num > 1)						--num; /* test restartability even more thoroughly */										r = BIO_nwrite(io1, &dataptr, (int)num);					assert(r > 0);					assert(r <= (int)num);					num = r;					r = BIO_read(io2, dataptr, (int)num);					if (r != (int)num) /* can't happen */						{						fprintf(stderr, "ERROR: BIO_read could not read "							"BIO_ctrl_pending() bytes");						goto err;						}					progress = 1;										if (debug)						printf((io2 == client_io) ?							"C->S relaying: %d bytes\n" :							"S->C relaying: %d bytes\n",							(int)num);					}			} /* no loop, BIO_ctrl_get_read_request now returns 0 anyway */			if (!progress && !prev_progress)				if (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0)					{					fprintf(stderr, "ERROR: got stuck\n");					if (strcmp("SSLv2", SSL_get_version(c_ssl)) == 0)						{						fprintf(stderr, "This can happen for SSL2 because "							"CLIENT-FINISHED and SERVER-VERIFY are written \n"							"concurrently ...");						if (strncmp("2SCF", SSL_state_string(c_ssl), 4) == 0							&& strncmp("2SSV", SSL_state_string(s_ssl), 4) == 0)							{							fprintf(stderr, " ok.\n");							goto end;							}						}					fprintf(stderr, " ERROR.\n");					goto err;					}			prev_progress = progress;			}		}	while (cw_num > 0 || cr_num > 0 || sw_num > 0 || sr_num > 0);	if (verbose)		print_details(c_ssl, "DONE via BIO pair: ");end:	ret = 0; err:	ERR_print_errors(bio_err);		if (server)		BIO_free(server);	if (server_io)		BIO_free(server_io);	if (client)		BIO_free(client);	if (client_io)		BIO_free(client_io);	if (s_ssl_bio)		BIO_free(s_ssl_bio);	if (c_ssl_bio)

⌨️ 快捷键说明

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