我正在写一个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:
这是我的代码,我不知道哪里出错了。请帮助我。
#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);
}
答案 0 :(得分: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);
有关此API的信息,请参阅the documentation。
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
表示您的文件中没有这些破折号页眉/页脚行。