下面是服务器程序的c代码
#define RSA_SERVER_CERT "certificate.pem"
#define RSA_SERVER_KEY "private.pem"
#define RSA_SERVER_CA_CERT "certificate.pem"
#define RSA_SERVER_CA_PATH "sys$common:[syshlp.examples.ssl]"
#define ON 1
#define OFF 0
#define RETURN_NULL(x) if ((x)==NULL) exit(1)
#define RETURN_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define RETURN_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(1); }
int main()
{
int err;
int verify_client = OFF;
int sock, connected, bytes_recieved , true = 1, pid;
char send_data [1024] , recv_data[1024];
struct sockaddr_in server_addr,client_addr;
int sin_size;
size_t client_len;
char *str;
char buf[4096];
SSL_CTX *ctx;
SSL *ssl;
SSL_METHOD *meth;
X509 *client_cert = NULL;
short int s_port = 443;
SSL_library_init();
SSL_load_error_strings();
meth = SSLv3_method();
ctx = SSL_CTX_new(meth);
if (!ctx)
{
ERR_print_errors_fp(stderr);
exit(1);
}
if (SSL_CTX_use_certificate_file(ctx, RSA_SERVER_CERT, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
exit(1);
}
if (SSL_CTX_use_PrivateKey_file(ctx, RSA_SERVER_KEY, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
exit(1);
}
if (!SSL_CTX_check_private_key(ctx))
{
fprintf(stderr,"Private key does not match the certificate public key\n");
exit(1);
}
if(verify_client == ON)
{
if (!SSL_CTX_load_verify_locations(ctx, RSA_SERVER_CA_CERT, NULL))
{
ERR_print_errors_fp(stderr);
exit(1);
}
SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
SSL_CTX_set_verify_depth(ctx,1);
}
sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
RETURN_ERR(sock, "socket");
memset (&server_addr, '\0', sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(s_port);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
err = bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
RETURN_ERR(err, "bind");
err = listen(sock, 5);
RETURN_ERR(err, "listen");
client_len = sizeof(client_addr);
printf("\nSSL Server Waiting for client on port 443");
fflush(stdout);
sin_size = sizeof(struct sockaddr_in);
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);
RETURN_ERR(connected, "accept");
close(sock);
printf("\n I got a connection from (%s , %d)", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
ssl = SSL_new(ctx);
RETURN_NULL(ssl);
SSL_set_fd(ssl, connected);
err = SSL_accept(ssl);
RETURN_SSL(err);
printf("SSL connection using %s\n", SSL_get_cipher (ssl));
if (verify_client == ON)
{
client_cert = SSL_get_peer_certificate(ssl);
}
//necessary code for sending and recieving irrelevant to the issue
err = SSL_shutdown(ssl);
RETURN_SSL(err);
err = close(sock);
RETURN_ERR(err, "close");
SSL_free(ssl);
SSL_CTX_free(ctx);
close(sock);
return 0;
}
客户端程序的代码是:
#define RETURN_NULL(x) if ((x)==NULL) exit (1)
#define RETURN_ERR(err,s) if ((err)==-1) { perror(s); exit(1); }
#define RETURN_SSL(err) if ((err)==-1) { ERR_print_errors_fp(stderr); exit(1); }
static int verify_callback(int ok, X509_STORE_CTX *ctx);
#define RSA_CLIENT_CERT "certificate.pem"
#define RSA_CLIENT_KEY "private.pem"
#define RSA_CLIENT_CA_CERT "certificate.pem"
#define RSA_CLIENT_CA_PATH "sys$common:[syshlp.examples.ssl]"
#define ON 1
#define OFF 0
int main()
{
int sock, err, verify_client = OFF;
char recv_data[1024];
char *str;
struct hostent *host;
struct sockaddr_in server_addr;
SSL_CTX *ctx;
SSL *ssl;
SSL_METHOD *meth;
X509 *server_cert;
EVP_PKEY *pkey;
short int s_port = 443;
const char *s_ipaddr = "127.0.0.1";
SSL_library_init();
SSL_load_error_strings();
meth = SSLv3_method();
ctx = SSL_CTX_new(meth);
RETURN_NULL(ctx);
if(verify_client == ON)
{
if (SSL_CTX_use_certificate_file(ctx, RSA_CLIENT_CERT, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
exit(1);
}
if (SSL_CTX_use_PrivateKey_file(ctx, RSA_CLIENT_KEY, SSL_FILETYPE_PEM) <= 0)
{
ERR_print_errors_fp(stderr);
exit(1);
}
if (!SSL_CTX_check_private_key(ctx))
{
fprintf(stderr,"Private key does not match the certificate public key\n");
exit(1);
}
}
if (!SSL_CTX_load_verify_locations(ctx, RSA_CLIENT_CA_CERT, NULL))
{
ERR_print_errors_fp(stderr);
exit(1);
}
SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL);
SSL_CTX_set_verify_depth(ctx,1);
sock = socket(AF_INET, SOCK_STREAM, 0);
RETURN_ERR(sock, "socket");
memset (&server_addr, '\0', sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(s_port);
server_addr.sin_addr.s_addr = inet_addr(s_ipaddr);
bzero(&(server_addr.sin_zero),8);
err = connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
RETURN_ERR(err, "connect");
ssl = SSL_new (ctx);
RETURN_NULL(ssl);
SSL_set_fd(ssl, sock);
err = SSL_connect(ssl);
RETURN_SSL(err);
printf ("SSL connection using %s\n", SSL_get_cipher (ssl));
server_cert = SSL_get_peer_certificate (ssl);
//necessary code irrelevant to the issue
err = SSL_shutdown(ssl);
RETURN_SSL(err);
err = close(sock);
RETURN_ERR(err, "close");
SSL_free(ssl);
SSL_CTX_free(ctx);
fclose(log);
return 0;
}
当上面的代码在两个 linux 系统中运行时它工作,当我尝试上面的服务器程序使用终端使用命令连接标准客户端时openssl s_client -connect localhost:443
,它显示如下
connect: Connection refused
connect:errno=111
为什么会这样?有什么办法可以解决吗?提前致谢。