s_client.c

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

C
886
字号
	cbuf_len=0;	cbuf_off=0;	sbuf_len=0;	sbuf_off=0;	for (;;)		{		FD_ZERO(&readfds);		FD_ZERO(&writefds);		if (SSL_in_init(con) && !SSL_total_renegotiations(con))			{			in_init=1;			tty_on=0;			}		else			{			tty_on=1;			if (in_init)				{				in_init=0;				print_stuff(bio_c_out,con,full_log);				if (full_log > 0) full_log--;				if (reconnect)					{					reconnect--;					BIO_printf(bio_c_out,"drop connection and then reconnect\n");					SSL_shutdown(con);					SSL_set_connect_state(con);					SHUTDOWN(SSL_get_fd(con));					goto re_start;					}				}			}		ssl_pending = read_ssl && SSL_pending(con);		if (!ssl_pending)			{#ifndef WINDOWS			if (tty_on)				{				if (read_tty)  FD_SET(fileno(stdin),&readfds);				if (write_tty) FD_SET(fileno(stdout),&writefds);				}			if (read_ssl)				FD_SET(SSL_get_fd(con),&readfds);			if (write_ssl)				FD_SET(SSL_get_fd(con),&writefds);#else			if(!tty_on || !write_tty) {				if (read_ssl)					FD_SET(SSL_get_fd(con),&readfds);				if (write_ssl)					FD_SET(SSL_get_fd(con),&writefds);			}#endif/*			printf("mode tty(%d %d%d) ssl(%d%d)\n",				tty_on,read_tty,write_tty,read_ssl,write_ssl);*/			/* Note: under VMS with SOCKETSHR the second parameter			 * is currently of type (int *) whereas under other			 * systems it is (void *) if you don't have a cast it			 * will choke the compiler: if you do have a cast then			 * you can either go for (int *) or (void *).			 */#ifdef WINDOWS			/* Under Windows we make the assumption that we can			 * always write to the tty: therefore if we need to			 * write to the tty we just fall through. Otherwise			 * we timeout the select every second and see if there			 * are any keypresses. Note: this is a hack, in a proper			 * Windows application we wouldn't do this.			 */			i=0;			if(!write_tty) {				if(read_tty) {					tv.tv_sec = 1;					tv.tv_usec = 0;					i=select(width,(void *)&readfds,(void *)&writefds,						 NULL,&tv);					if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue;				} else 	i=select(width,(void *)&readfds,(void *)&writefds,					 NULL,NULL);			}#else			i=select(width,(void *)&readfds,(void *)&writefds,				 NULL,NULL);#endif			if ( i < 0)				{				BIO_printf(bio_err,"bad select %d\n",				get_last_socket_error());				goto shut;				/* goto end; */				}			}		if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds))			{			k=SSL_write(con,&(cbuf[cbuf_off]),				(unsigned int)cbuf_len);			switch (SSL_get_error(con,k))				{			case SSL_ERROR_NONE:				cbuf_off+=k;				cbuf_len-=k;				if (k <= 0) goto end;				/* we have done a  write(con,NULL,0); */				if (cbuf_len <= 0)					{					read_tty=1;					write_ssl=0;					}				else /* if (cbuf_len > 0) */					{					read_tty=0;					write_ssl=1;					}				break;			case SSL_ERROR_WANT_WRITE:				BIO_printf(bio_c_out,"write W BLOCK\n");				write_ssl=1;				read_tty=0;				break;			case SSL_ERROR_WANT_READ:				BIO_printf(bio_c_out,"write R BLOCK\n");				write_tty=0;				read_ssl=1;				write_ssl=0;				break;			case SSL_ERROR_WANT_X509_LOOKUP:				BIO_printf(bio_c_out,"write X BLOCK\n");				break;			case SSL_ERROR_ZERO_RETURN:				if (cbuf_len != 0)					{					BIO_printf(bio_c_out,"shutdown\n");					goto shut;					}				else					{					read_tty=1;					write_ssl=0;					break;					}							case SSL_ERROR_SYSCALL:				if ((k != 0) || (cbuf_len != 0))					{					BIO_printf(bio_err,"write:errno=%d\n",						get_last_socket_error());					goto shut;					}				else					{					read_tty=1;					write_ssl=0;					}				break;			case SSL_ERROR_SSL:				ERR_print_errors(bio_err);				goto shut;				}			}#ifdef WINDOWS		/* Assume Windows can always write */		else if (!ssl_pending && write_tty)#else		else if (!ssl_pending && FD_ISSET(fileno(stdout),&writefds))#endif			{#ifdef CHARSET_EBCDIC			ascii2ebcdic(&(sbuf[sbuf_off]),&(sbuf[sbuf_off]),sbuf_len);#endif			i=write(fileno(stdout),&(sbuf[sbuf_off]),sbuf_len);			if (i <= 0)				{				BIO_printf(bio_c_out,"DONE\n");				goto shut;				/* goto end; */				}			sbuf_len-=i;;			sbuf_off+=i;			if (sbuf_len <= 0)				{				read_ssl=1;				write_tty=0;				}			}		else if (ssl_pending || FD_ISSET(SSL_get_fd(con),&readfds))			{#ifdef RENEG{ static int iiii; if (++iiii == 52) { SSL_renegotiate(con); iiii=0; } }#endif#if 1			k=SSL_read(con,sbuf,1024 /* BUFSIZZ */ );#else/* Demo for pending and peek :-) */			k=SSL_read(con,sbuf,16);{ char zbuf[10240]; printf("read=%d pending=%d peek=%d\n",k,SSL_pending(con),SSL_peek(con,zbuf,10240));}#endif			switch (SSL_get_error(con,k))				{			case SSL_ERROR_NONE:				if (k <= 0)					goto end;				sbuf_off=0;				sbuf_len=k;				read_ssl=0;				write_tty=1;				break;			case SSL_ERROR_WANT_WRITE:				BIO_printf(bio_c_out,"read W BLOCK\n");				write_ssl=1;				read_tty=0;				break;			case SSL_ERROR_WANT_READ:				BIO_printf(bio_c_out,"read R BLOCK\n");				write_tty=0;				read_ssl=1;				if ((read_tty == 0) && (write_ssl == 0))					write_ssl=1;				break;			case SSL_ERROR_WANT_X509_LOOKUP:				BIO_printf(bio_c_out,"read X BLOCK\n");				break;			case SSL_ERROR_SYSCALL:				BIO_printf(bio_err,"read:errno=%d\n",get_last_socket_error());				goto shut;			case SSL_ERROR_ZERO_RETURN:				BIO_printf(bio_c_out,"closed\n");				goto shut;			case SSL_ERROR_SSL:				ERR_print_errors(bio_err);				goto shut;				/* break; */				}			}#ifdef WINDOWS		else if ((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0)))#else		else if (FD_ISSET(fileno(stdin),&readfds))#endif			{			if (crlf)				{				int j, lf_num;				i=read(fileno(stdin),cbuf,BUFSIZZ/2);				lf_num = 0;				/* both loops are skipped when i <= 0 */				for (j = 0; j < i; j++)					if (cbuf[j] == '\n')						lf_num++;				for (j = i-1; j >= 0; j--)					{					cbuf[j+lf_num] = cbuf[j];					if (cbuf[j] == '\n')						{						lf_num--;						i++;						cbuf[j+lf_num] = '\r';						}					}				assert(lf_num == 0);				}			else				i=read(fileno(stdin),cbuf,BUFSIZZ);			if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q')))				{				BIO_printf(bio_err,"DONE\n");				goto shut;				}			if ((!c_ign_eof) && (cbuf[0] == 'R'))				{				BIO_printf(bio_err,"RENEGOTIATING\n");				SSL_renegotiate(con);				cbuf_len=0;				}			else				{				cbuf_len=i;				cbuf_off=0;#ifdef CHARSET_EBCDIC				ebcdic2ascii(cbuf, cbuf, i);#endif				}			write_ssl=1;			read_tty=0;			}		}shut:	SSL_shutdown(con);	SHUTDOWN(SSL_get_fd(con));	ret=0;end:	if(prexit) print_stuff(bio_c_out,con,1);	if (con != NULL) SSL_free(con);	if (con2 != NULL) SSL_free(con2);	if (ctx != NULL) SSL_CTX_free(ctx);	if (cbuf != NULL) { memset(cbuf,0,BUFSIZZ); OPENSSL_free(cbuf); }	if (sbuf != NULL) { memset(sbuf,0,BUFSIZZ); OPENSSL_free(sbuf); }	if (bio_c_out != NULL)		{		BIO_free(bio_c_out);		bio_c_out=NULL;		}	EXIT(ret);	}static void print_stuff(BIO *bio, SSL *s, int full)	{	X509 *peer=NULL;	char *p;	static char *space="                ";	char buf[BUFSIZ];	STACK_OF(X509) *sk;	STACK_OF(X509_NAME) *sk2;	SSL_CIPHER *c;	X509_NAME *xn;	int j,i;	if (full)		{		int got_a_chain = 0;		sk=SSL_get_peer_cert_chain(s);		if (sk != NULL)			{			got_a_chain = 1; /* we don't have it for SSL2 (yet) */			BIO_printf(bio,"---\nCertificate chain\n");			for (i=0; i<sk_X509_num(sk); i++)				{				X509_NAME_oneline(X509_get_subject_name(					sk_X509_value(sk,i)),buf,BUFSIZ);				BIO_printf(bio,"%2d s:%s\n",i,buf);				X509_NAME_oneline(X509_get_issuer_name(					sk_X509_value(sk,i)),buf,BUFSIZ);				BIO_printf(bio,"   i:%s\n",buf);				if (c_showcerts)					PEM_write_bio_X509(bio,sk_X509_value(sk,i));				}			}		BIO_printf(bio,"---\n");		peer=SSL_get_peer_certificate(s);		if (peer != NULL)			{			BIO_printf(bio,"Server certificate\n");			if (!(c_showcerts && got_a_chain)) /* Redundant if we showed the whole chain */				PEM_write_bio_X509(bio,peer);			X509_NAME_oneline(X509_get_subject_name(peer),				buf,BUFSIZ);			BIO_printf(bio,"subject=%s\n",buf);			X509_NAME_oneline(X509_get_issuer_name(peer),				buf,BUFSIZ);			BIO_printf(bio,"issuer=%s\n",buf);			}		else			BIO_printf(bio,"no peer certificate available\n");		sk2=SSL_get_client_CA_list(s);		if ((sk2 != NULL) && (sk_X509_NAME_num(sk2) > 0))			{			BIO_printf(bio,"---\nAcceptable client certificate CA names\n");			for (i=0; i<sk_X509_NAME_num(sk2); i++)				{				xn=sk_X509_NAME_value(sk2,i);				X509_NAME_oneline(xn,buf,sizeof(buf));				BIO_write(bio,buf,strlen(buf));				BIO_write(bio,"\n",1);				}			}		else			{			BIO_printf(bio,"---\nNo client certificate CA names sent\n");			}		p=SSL_get_shared_ciphers(s,buf,BUFSIZ);		if (p != NULL)			{			/* This works only for SSL 2.  In later protocol			 * versions, the client does not know what other			 * ciphers (in addition to the one to be used			 * in the current connection) the server supports. */			BIO_printf(bio,"---\nCiphers common between both SSL endpoints:\n");			j=i=0;			while (*p)				{				if (*p == ':')					{					BIO_write(bio,space,15-j%25);					i++;					j=0;					BIO_write(bio,((i%3)?" ":"\n"),1);					}				else					{					BIO_write(bio,p,1);					j++;					}				p++;				}			BIO_write(bio,"\n",1);			}		BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n",			BIO_number_read(SSL_get_rbio(s)),			BIO_number_written(SSL_get_wbio(s)));		}	BIO_printf(bio,((s->hit)?"---\nReused, ":"---\nNew, "));	c=SSL_get_current_cipher(s);	BIO_printf(bio,"%s, Cipher is %s\n",		SSL_CIPHER_get_version(c),		SSL_CIPHER_get_name(c));	if (peer != NULL) {		EVP_PKEY *pktmp;		pktmp = X509_get_pubkey(peer);		BIO_printf(bio,"Server public key is %d bit\n",							 EVP_PKEY_bits(pktmp));		EVP_PKEY_free(pktmp);	}	SSL_SESSION_print(bio,SSL_get_session(s));	BIO_printf(bio,"---\n");	if (peer != NULL)		X509_free(peer);	}

⌨️ 快捷键说明

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