2014-01-14 481 views
-1

我正在編寫https代理。而我的程序有兩個錯誤。 15883:錯誤:0906D06C:PEM套路:PEM_read_bio:無從下手行:pem_lib.c:644:期待:證書 15883:錯誤:140AD009:SSL例程:SSL_CTX_use_certificate_file:PEM LIB:ssl_rsa.c:491:SSL:錯誤:0906D06C:PEM例程:PEM_read_bio:無起始行:pem_lib.c:644:預計:CERTIFICATE

。這是我的代碼,我不知道哪裏是wrong.please幫我

#include <stdio.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <errno.h> 
#include <string.h> 
#include <netdb.h> 
#include <resolv.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
#include <sys/wait.h> 
#include <arpa/inet.h> 
#include <openssl/err.h> 
#include <openssl/ssl.h> 
#include <pthread.h> 

#define SIZE 1024 

#define PKEY "cacert.pem" 
#define CERTT "privkey.pem" 
pthread_mutex_t mut; 
int counter = 0; 
char url[400] = {0}; 


unsigned long GetIp(char domainname[250]) 
{ 
    struct sockaddr_in sin; 
    struct hostent *phost; 
    if((phost = gethostbyname(domainname)) == NULL) 
    { 
     perror("gethostbyname error\n"); 
     return 0; 
    } 
    sin.sin_addr = *((struct in_addr *)phost->h_addr_list[0]); 
    const char *ip = inet_ntoa(sin.sin_addr); 
    printf("ip is %s\n", ip); 
    return sin.sin_addr.s_addr; 
} 

void ShowCerts(SSL * ssl) 
{ 
    X509 *cert; 
    char *line; 

    cert = SSL_get_peer_certificate(ssl); 
    if (cert != NULL) { 
     printf("數字證書信息:\n"); 
     line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); 
     printf("證書: %s\n", line); 
     free(line); 
     line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); 
     printf("頒發者: %s\n", line); 
     free(line); 
     X509_free(cert); 
    } else 
     printf("無證書信息!\n"); 
} 
char *SendWeb(char buf[]) 
{ 
    char *buffer1 ; 
    int sockfd; 
    int len; 
    struct sockaddr_in web; 
    SSL_CTX *ctx; 
    SSL *ssl; 
    if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) 
    { 
     perror("socket create failed!\n"); 
     exit(errno); 
    } 
    bzero(&web,sizeof(web)); 
    web.sin_family = AF_INET; 
    web.sin_port = htons(443); 
    // web.sin_addr.s_addr = inet_addr("110.75.146.111"); 
    web.sin_addr.s_addr = GetIp(url); 
    if(connect(sockfd,(struct sockaddr *)&web,sizeof(web)) != 0) 
    { 
     perror("connect error!\n"); 
     exit(errno); 
    } 

    ssl = SSL_new(ctx); 
    SSL_set_fd(ssl,sockfd); 
    if(SSL_connect(ssl) == -1) 
    { 
     ERR_print_errors_fp(stderr); 
    } 
    ShowCerts(ssl); 
    bzero(buffer1,SIZE); 
    len = SSL_write(ssl,buf,SIZE); 
    if(len < 0) 
    { 
     printf("SendWeb error!\n"); 
    } 
    else 
    { 
     printf("Send sucess is %s\n", buf); 
    } 
    len = SSL_read(ssl,buffer1,SIZE); 
    if(len > 0) 
    { 
     printf("Recv Web : %s\n", buffer1); 
    } 
    else 
    { 
     printf("Recv Web Error!錯誤代碼:%d,錯誤信息:%s.\n", errno,strerror(errno)); 
    } 
    return buffer1; 
} 
char RecvBro() 
{ 
    //char url[400] = {0}; 
    int i, sockfd , client_fd,new_fd; 
    struct sockaddr_in mim_ser,brow; 
    int len; 
    char *index_start,*index_end,*buf; 
    SSL_CTX *ctx; 
    ctx = SSL_CTX_new(SSLv23_server_method());//以ssl v2 v3 標準敬愛內容方式產生一個SSL_CTX 
    if(ctx == NULL) 
    { 
     ERR_print_errors_fp(stdout); 
     exit(1); 
    } 
//載入用戶數字證書,發給客戶端,包含公鑰 
    if(!SSL_CTX_use_certificate_file(ctx,CERTT,SSL_FILETYPE_PEM)) 
    { 
     ERR_print_errors_fp(stdout); 
     exit(1); 
    } 
//載入用戶私鑰 
    if(SSL_CTX_use_PrivateKey_file(ctx,PKEY,SSL_FILETYPE_PEM)) 
    { 
     ERR_print_errors_fp(stdout); 
     exit(1); 
    } 
    if(!SSL_CTX_check_private_key(ctx)) 
    { 
     ERR_print_errors_fp(stdout); 
     exit(1); 
    } 

    if((sockfd=socket(PF_INET,SOCK_STREAM,0))== -1) 
    { 
     perror("socket create failed"); 
     exit(1); 
    } 
    bzero(&mim_ser,sizeof(mim_ser)); 
    mim_ser.sin_family = PF_INET; 
    mim_ser.sin_port = htons(443); 
    mim_ser.sin_addr.s_addr = INADDR_ANY; 

    if((bind(sockfd,(struct sockaddr *)&mim_ser,sizeof(struct sockaddr))) == -1) 
    { 
     perror("bind failed"); 
     exit(1); 
    } 

    if(listen(sockfd,10) == -1) 
    { 
     perror("listen error"); 
     exit(1); 
    } 


     SSL *ssl; 
     int len2 = sizeof (struct sockaddr); 
     if((new_fd = accept(sockfd,(struct sockaddr *)&brow,&len2)) == -1) 
     { 
     perror("accept error"); 
     exit(1); 
     } 
     //基於ctx產生一個新的ssl 
     ssl = SSL_new(ctx); 
     SSL_set_fd(ssl,new_fd);//將連接用戶的socket加入SSL 
     if(SSL_accept(ssl) == -1) 
     { 
      perror("accept"); 
      close(new_fd); 

     } 
     buf = (char *)malloc(SIZE); 
    // char buf[SIZE]= {0}; 
     bzero(buf,SIZE); 
     len = SSL_read(ssl,buf,SIZE); 
     if(len > 0) 
     { 
     printf("recv from browser is %s\n",buf); 
     } 
     else 
     { 
     printf("RECV ERROR!錯誤代碼:%s,錯誤信息:%s\n",errno,strerror); 

     } 
     index_start = strstr(buf,"Host:"); 
     index_end = strstr(index_end,"\r\n"); 
     if(index_start == NULL ||index_end == NULL) 
     { 
     perror("index_start or index_end is NULL\n"); 
     } 
     if((i = (int)(index_start - index_end)) <= 0) 
     { 
     perror("index_start - index_end <= 0 \n"); 
     } 
     bzero(url,400); 
     strncpy(url,index_start + 6, i-6); 


     buf = SendWeb(buf); 
     len = SSL_write(ssl,buf,SIZE); 
     if(len <= 0) 
     { 
     printf("\nSend sucess!\n"); 
     } 

} 
int main() 
{ 
    ERR_load_BIO_strings(); 
    SSL_library_init();//ssl庫初始化 
    OpenSSL_add_all_algorithms();//載入所有ssl算法 
    SSL_load_error_strings();//載入所有ssl從錯誤消息 
    pthread_mutex_init(&mut,NULL); 

    while(1) 
    { 
     pthread_t work_thread; 
     if(pthread_create(&work_thread,NULL,(void *)&RecvBro,NULL)) 
     { 
     perror("create thread error\n"); 
     } 
     else 
     { 
     pthread_mutex_lock(&mut); 
     counter++; 
     pthread_mutex_unlock(&mut); 
     pthread_detach(work_thread); 
     } 
    } 
    pthread_mutex_destroy(&mut); 
} 

回答

1

首先,好像你有一個錯字和這兩條線:

#define PKEY "cacert.pem" 
#define CERTT "privkey.pem" 

可能應改爲

#define CERTT "cacert.pem" 
#define PKEY "privkey.pem" 

即使這還不夠。檢查下面列出的項目

1)SSL_CTX_use_certificate_file()用於加載對應於私鑰的證書,而不是CA證書(如文件名「cacert.pem」的建議)。您可能會發現下面的答案有益於迅速瞭解了這一切:Starting to use OpenSSL

您應該使用SSL_CTX_load_verify_locations()指定與CA證書(或多個)這樣的文件:

SSL_CTX_load_verify_locations(ctx, "cacert.pem", NULL); 

the documentation這個API。

2)證書PEM類型的文件(無論是SSL_CTX_use_certificate_file()與SSL_FILETYPE_PEM和SSL_CTX_load_verify_locations())應該有破折號頁眉和頁腳,就像這樣:

-----BEGIN CERTIFICATE----- 
... (certificate in base64 encoding) ... 
-----END CERTIFICATE----- 

錯誤9478:error:0906D06C:PEM routines:PEM_read_bio:no start line:pem_lib.c:644:Expecting: CERTIFICATE表明你沒有那些破折號在您的文件中的頁眉/頁腳行。

+0

我這樣做就像你說的,但有更多的錯誤。 '9478:錯誤:0906D06C:PEM例程:PEM_read_bio:無起始行:pem_lib.c:644:預計:CERTIFICATE' ........更多..... – user3193163

+0

我更新了我的答案,更多建議,請檢查。 – vond

相關問題