Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从未调用Openssl API客户端Hello回调函数_C_Ssl_Openssl - Fatal编程技术网

C 从未调用Openssl API客户端Hello回调函数

C 从未调用Openssl API客户端Hello回调函数,c,ssl,openssl,C,Ssl,Openssl,我试图使用openssl api在个人项目上实现JA3方法(TLS指纹识别方法)。要做到这一点,我需要获得有关客户机Hello数据包的一些信息,我正在尝试使用opensslapi来实现这一点。首先,我下载了一个在我的电脑和一个网站之间建立TLS连接的代码,并检索了证书信息。该程序运行良好,tls连接使用tls 1.3,证书信息正常。然后我尝试检索客户机Hello数据包以开始实现JA3方法。经过几次研究,我发现了许多函数,可以让我获得所需的信息:。所有这些函数只能在客户端hello回调函数上调用。

我试图使用openssl api在个人项目上实现JA3方法(TLS指纹识别方法)。要做到这一点,我需要获得有关客户机Hello数据包的一些信息,我正在尝试使用opensslapi来实现这一点。首先,我下载了一个在我的电脑和一个网站之间建立TLS连接的代码,并检索了证书信息。该程序运行良好,tls连接使用tls 1.3,证书信息正常。然后我尝试检索客户机Hello数据包以开始实现JA3方法。经过几次研究,我发现了许多函数,可以让我获得所需的信息:。所有这些函数只能在客户端hello回调函数上调用。由于SSL\u CTX\u set\u client\u hello\u cb函数,可以调用此函数。但在我的例子中,我的函数从未被调用。我开始绝望了,这就是为什么我需要你的帮助。我真的搜索了很多来调试它,但我没有找到一个允许回调函数或类似的标志。节目如下:

#include <sys/socket.h>
#include <resolv.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>

#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>

int create_socket(char[], BIO *);

int callback(SSL *s, int *al, void *arg)
{
  int * number = arg;
  *number = (*number) + 1;
  printf("\nWe are in the callback function !\n");
  return SSL_CLIENT_HELLO_SUCCESS;
}

int main() {

  char           dest_url[] = "https://www.hp.com";
  BIO              *certbio = NULL;
  BIO               *outbio = NULL;
  X509                *cert = NULL;
  X509_NAME       *certname = NULL;
  const SSL_METHOD *method;
  SSL_CTX *ctx;
  struct ssl_st *ssl;
  int server = 0;

  OpenSSL_add_all_algorithms();
  ERR_load_BIO_strings();
  ERR_load_crypto_strings();
  SSL_load_error_strings();

  certbio = BIO_new(BIO_s_file());
  outbio  = BIO_new_fp(stdout, BIO_NOCLOSE);

  if(SSL_library_init() < 0)
    BIO_printf(outbio, "Could not initialize the OpenSSL library !\n");

  method = TLS_client_method();

  if ( (ctx = SSL_CTX_new(method)) == NULL)
    BIO_printf(outbio, "Unable to create a new SSL context structure.\n");

  int hope = 12;
  SSL_CTX_set_client_hello_cb(ctx, &callback, (void *)&hope);

  ssl = SSL_new(ctx);
  
  server = create_socket(dest_url, outbio);
  if(server != 0)
    BIO_printf(outbio, "Successfully made the TCP connection to: %s.\n", dest_url);

  SSL_set_fd(ssl, server);

  if ( SSL_connect(ssl) != 1 )
    BIO_printf(outbio, "Error: Could not build a SSL session to: %s.\n", dest_url);
  else
    BIO_printf(outbio, "Successfully enabled SSL/TLS session to: %s.\n", dest_url);
    
  cert = SSL_get_peer_certificate(ssl);
  if (cert == NULL)
    BIO_printf(outbio, "Error: Could not get a certificate from: %s.\n", dest_url);
  else
    BIO_printf(outbio, "Retrieved the server's certificate from: %s.\n", dest_url);

  certname = X509_NAME_new();
  certname = X509_get_subject_name(cert);

  BIO_printf(outbio, "Displaying the certificate subject data:\n");
  X509_NAME_print_ex(outbio, certname, 0, 0);
  BIO_printf(outbio, "\n");

  SSL_free(ssl);
  close(server);
  X509_free(cert);
  SSL_CTX_free(ctx);
  BIO_printf(outbio, "Finished SSL/TLS connection with server: %s.\n", dest_url);

  printf("Hope value : %d \n", hope);

  return(0);
}

int create_socket(char url_str[], BIO *out) {
  int sockfd;
  char hostname[256] = "";
  char    portnum[6] = "443";
  char      proto[6] = "";
  char      *tmp_ptr = NULL;
  int           port;
  struct hostent *host;
  struct sockaddr_in dest_addr;

  if(url_str[strlen(url_str)] == '/')
    url_str[strlen(url_str)] = '\0';

  strncpy(proto, url_str, (strchr(url_str, ':')-url_str));
  strncpy(hostname, strstr(url_str, "://")+3, sizeof(hostname));

  if(strchr(hostname, ':')) {
    tmp_ptr = strchr(hostname, ':');
    /* the last : starts the port number, if avail, i.e. 8443 */
    strncpy(portnum, tmp_ptr+1,  sizeof(portnum));
    *tmp_ptr = '\0';
  }

  port = atoi(portnum);

  if ( (host = gethostbyname(hostname)) == NULL ) {
    BIO_printf(out, "Error: Cannot resolve hostname %s.\n",  hostname);
    abort();
  }

  sockfd = socket(AF_INET, SOCK_STREAM, 0);

  dest_addr.sin_family=AF_INET;
  dest_addr.sin_port=htons(port);
  dest_addr.sin_addr.s_addr = *(long*)(host->h_addr);

  memset(&(dest_addr.sin_zero), '\0', 8);

  tmp_ptr = inet_ntoa(dest_addr.sin_addr);

  if ( connect(sockfd, (struct sockaddr *) &dest_addr,
                              sizeof(struct sockaddr)) == -1 ) {
    BIO_printf(out, "Error: Cannot connect to host %s [%s] on port %d.\n",
             hostname, tmp_ptr, port);
  }

  return sockfd;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int create_socket(char[],BIO*);
int回调(SSL*s、int*al、void*arg)
{
int*number=arg;
*数字=(*数字)+1;
printf(“\n我们在回调函数中!\n”);
返回SSL\u CLIENT\u HELLO\u SUCCESS;
}
int main(){
char dest_url[]=”https://www.hp.com";
BIO*certbio=NULL;
BIO*outbio=NULL;
X509*证书=空;
X509_NAME*certname=NULL;
const SSL_方法*方法;
SSL_CTX*CTX;
结构ssl_st*ssl;
int server=0;
OpenSSL_添加_所有算法();
ERR_load_BIO_strings();
错误加载加密字符串();
SSL_加载_错误_字符串();
certbio=BIO_new(BIO_s_file());
outbio=生物新生物fp(stdout、生物NOCLOSE);
if(SSL_library_init()<0)
BIO_printf(outbio,“无法初始化OpenSSL库!\n”);
方法=TLS_客户端_方法();
if((ctx=SSL\u ctx\u new(method))==NULL)
BIO_printf(outbio,“无法创建新的SSL上下文结构。\n”);
int hope=12;
SSL\u CTX\u set\u client\u hello\u cb(CTX和callback,(void*)和hope);
ssl=ssl_新(ctx);
服务器=创建套接字(dest\u url,outbio);
如果(服务器!=0)
BIO_printf(outbio,“已成功建立到%s的TCP连接。\n”,dest_url);
SSL\u set\u fd(SSL,服务器);
如果(SSL_连接(SSL)!=1)
BIO_printf(outbio,“错误:无法建立到:%s的SSL会话。\n”,dest_url);
其他的
BIO_printf(outbio,“成功启用到%s的SSL/TLS会话。\n”,目标url);
证书=SSL\u获取\u对等\u证书(SSL);
如果(证书==NULL)
BIO_printf(outbio,“错误:无法从以下位置获取证书:%s.\n”,dest_url);
其他的
BIO_printf(outbio,“从以下位置检索服务器的证书:%s.\n”,dest_url);
certname=X509_NAME_new();
certname=X509\u获取\u主题\u名称(cert);
BIO_printf(outbio,“显示证书主题数据:\n”);
X509_NAME_print_ex(outbio,certname,0,0);
BIO_printf(outbio,“\n”);
无SSL(SSL);
关闭(服务器);
X509_免费(证书);
SSL_-CTX_-free(CTX);
BIO_printf(outbio,“已完成与服务器的SSL/TLS连接:%s.\n”,目标url);
printf(“希望值:%d\n”,希望);
返回(0);
}
int create_socket(字符url_str[],BIO*out){
int-sockfd;
字符主机名[256]=“”;
char portnum[6]=“443”;
char proto[6]=“”;
char*tmp_ptr=NULL;
国际港口;
结构主机*主机;
dest\u addr中的结构sockaddr\u;
如果(url_str[strlen(url_str)]=='/'))
url_str[strlen(url_str)]='\0';
strncpy(proto,url_str,(strchr(url_str,,:')-url_str));
strncpy(主机名,strstrstr(url_str,“:/”)+3,sizeof(主机名));
if(strchr(主机名“:”)){
tmp_ptr=strchr(主机名“:”);
/*最后:如果可用,则启动端口号,即8443*/
strncpy(portnum,tmp_ptr+1,sizeof(portnum));
*tmp_ptr='\0';
}
port=atoi(portnum);
if((主机=gethostbyname(主机名))==NULL){
BIO_printf(输出,“错误:无法解析主机名%s.\n”,主机名);
中止();
}
sockfd=套接字(AF_INET,SOCK_STREAM,0);
目的地地址sin家庭=AF家庭;
目的地址sin\U端口=htons(端口);
dest_addr.sin_addr.s_addr=*(长*)(主机->h_addr);
memset(&(dest_addr.sinu zero),'\0',8);
tmp_ptr=inet_ntoa(目的地址sin_addr);
如果(连接(sockfd,(结构sockaddr*)和dest_addr,
sizeof(结构sockaddr))=-1){
BIO_printf(输出,“错误:无法连接到端口%d上的主机%s[%s]。\n”,
主机名、tmp_ptr、端口);
}
返回sockfd;
}

我在等待你们的答案,谢谢各位。

关于出错原因的提示来自于您链接到的文档中描述的第一行:

SSL_CTX_set_client_hello_cb()设置回调函数,该函数在服务器上ClientHello处理的早期阶段自动调用

在处理收到的ClientHello时,服务器会调用它。您已经编写了一个客户机,因此从未调用它

作为替代方案,我建议您查看SSL\u CTX\u set\u msg\u callback():

从文档中:

SSL_CTX_set_msg_callback()或SSL_set_msg_callback()可用于定义消息回调函数cb,用于观察接收或发送的所有SSL/TLS协议消息(如握手消息)以及处理过程中发生的其他事件


谢谢你的快速回复。这是我的错,一次粗心的失误花了我两天的时间。。。。谢谢你的帮助,祝你今天愉快。