使用openssl的服务器程序在尝试连接Linux中的标准客户端时显示错误

时间:2012-06-08 09:37:01

标签: c linux sockets ssl openssl

以下是服务器程序的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

为什么会这样?有什么方法可以解决它吗?提前谢谢。

1 个答案:

答案 0 :(得分:3)

我没有使用此代码获得连接拒绝错误。

问题是openssl s_client -connect localhost:443默认使用TSL v1。但你有SSLV3。

所以你必须使用

openssl s_client -connect localhost:443 -ssl3