Мне нужно запустить GnuTLS с X509 на сервере / клиенте (сомнения и необходимость исправления) - PullRequest
0 голосов
/ 26 декабря 2018

GnuTLS претерпел радикальные изменения, как я вижу в примерах, упомянутых на следующих сайтах, в отношении моей версии кода, которая ранее работала на основе почти тех же примеров, что и раньше:

проблема заключается в том, что прежде чем вам пришлось использовать сертификат авторизациидля клиентской программы теперь вам нужен сертификат и ключ, который использовался только на стороне сервера.Что это за кардинальное изменение?В конце концов, какая сторона принадлежит как частная и публичная среди генерируемых сертификатов?(согласно примеру я должен заменить gnutls_certificate_set_x509_trust_file на gnutls_certificate_set_x509_key_file)

Какие строки с параметрами для команды openssl я должен использовать для генерации всех необходимых сертификатов в этом примереСервер и Клиент?

Это также очень запутывает вопрос об именах файлов для сгенерированных сертификатов, иногда это .pem, а иногда .crt / .key, расскажет вам, как я должен создать эти имена точно (если вы думаете, что некоторые изэто неправильно).

Из-за обновлений GnuTLS он перестал работать, и теперь происходит сбой рукопожатия, в результате чего сервер отказывает в рукопожатии, а клиент продолжает считать, что соединение в порядке.

это код:

Сервер:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <gnutls/gnutls.h>

int main(){
  const char*txterr;
  int lsck;
  gnutls_certificate_credentials_t xcred;
  gnutls_priority_t pcache;
  gnutls_session_t sesion;
  sockaddr_in _cli;

  //INICIO GLOBAL
  //if(!gnutls_check_version("3.6.15"))return -1;
  if(!gnutls_check_version("3.5.10"))return -1;
  if(gnutls_global_init()<0)return -2;
  if(gnutls_certificate_allocate_credentials(&xcred)<0)return -3;
  if(gnutls_certificate_set_x509_trust_file(xcred,"cert/ca.crt",GNUTLS_X509_FMT_PEM)<0)return -4;
  //if(gnutls_certificate_set_x509_crl_file(xcred,"cert/revocar.crl",GNUTLS_X509_FMT_PEM)<0)return -5;
  if(gnutls_certificate_set_x509_key_file(
    xcred,"cert/serv.crt","cert/serv.key",GNUTLS_X509_FMT_PEM)<0)return -6;
  //if(gnutls_certificate_set_ocsp_status_request_file(xcred,"reqocsp.der",0)<0)return -4;
  if(gnutls_priority_init(&pcache,"PERFORMANCE:%SERVER_PRECEDENCE",&txterr)<0){printf("TLS: %s\n",txterr);return -7;}
  if(gnutls_certificate_set_known_dh_params(xcred,GNUTLS_SEC_PARAM_MEDIUM)<0)return -8;

  //ABRE PUERTO SERVIDOR
  lsck=socket(AF_INET,SOCK_STREAM,0);
  if(lsck==-1){lsck=0;printf("Imposible usar Puerto\n");return -1;}
  {int optval=1;setsockopt(lsck,SOL_SOCKET,SO_REUSEADDR,(void*)&optval,sizeof(int));}
  //Convierte el puerto en Escucha
  {
    struct sockaddr_in dsrv;
    dsrv.sin_family=AF_INET;
    dsrv.sin_port=htons(9080);
    dsrv.sin_addr.s_addr=INADDR_ANY;
    if(bind(lsck,(struct sockaddr*)&dsrv,sizeof(dsrv))!=0)
      {printf("Imposible bindear Puerto\n");return -2;}
    if(listen(lsck,10)!=0)
      {printf("Imposible abrir Puerto\n");return -3;}
  }
  printf("Abriendo Puerto\n");

  //ESCUCHA PUERTO
  if(gnutls_init(&sesion,GNUTLS_SERVER)<0)return -6;
  if(gnutls_priority_set(sesion,pcache)<0)return -6;
  if(gnutls_credentials_set(sesion,GNUTLS_CRD_CERTIFICATE,xcred)<0)return -6;
  gnutls_certificate_server_set_request(sesion,GNUTLS_CERT_IGNORE);
  gnutls_handshake_set_timeout(sesion,GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
  int _scli=sizeof(sockaddr_in);
  int nsck=accept(lsck,(sockaddr*)&_cli,(socklen_t*)&_scli);
  if(nsck<0)return -3;
  gnutls_transport_set_int(sesion,nsck);
  int tm;
  do{
    tm=gnutls_handshake(sesion);
  }while(tm<0&&gnutls_error_is_fatal(tm)==0);
  if(tm<0){close(nsck);gnutls_deinit(sesion);return -6;}
  printf("Entrando Usuario: %x:%d\n",_cli.sin_addr,_cli.sin_port);

  //CIFRA PUERTO CLIENTE
  gnutls_datum_t out;
  gnutls_session_t tls_sesion;
  if(gnutls_init(&tls_sesion,GNUTLS_CLIENT)<0)return -6;
  if(gnutls_server_name_set(tls_sesion,GNUTLS_NAME_DNS,"blackrook.ddns.net",strlen("blackrook.ddns.net"))<0)return -7;
  if(gnutls_set_default_priority(tls_sesion)<0)return -8;
  int ret=gnutls_priority_set_direct(tls_sesion,"NORMAL",&txterr);
  if(ret<0){
    switch(ret){
    case GNUTLS_E_INVALID_REQUEST:
      printf("Error tipo %s\n",txterr);
      return -9;
    }
  }
  if(gnutls_credentials_set(tls_sesion,GNUTLS_CRD_CERTIFICATE,xcred)<0)return -10;
  gnutls_session_set_verify_cert(tls_sesion,"blackrook.ddns.net",0);
  //Toma el FD Socket
  gnutls_transport_set_int(tls_sesion,nsck);
  gnutls_handshake_set_timeout(tls_sesion,GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
  do{ret=gnutls_handshake(tls_sesion);
  }while(ret<0&&!gnutls_error_is_fatal(ret));
  if(ret<0){
    gnutls_certificate_type_t type;
    int status;
    switch(ret){
    case GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR:
      type=gnutls_certificate_type_get(tls_sesion);
      status=gnutls_session_get_verify_cert_status(tls_sesion);
      if(gnutls_certificate_verification_status_print(status,type,&out,0)<0)return -255;
      printf("TLS: cert verify output: %s\n",out.data);
      gnutls_free(out.data);
    }
    printf("TLS: Handshake fallado: %s\n",gnutls_strerror(ret));
    return -11;
  }{
    char*desc=gnutls_session_get_desc(tls_sesion);
    printf("TLS: Session info: %s\n",desc);
    gnutls_free(desc);
  }
  //Envia mensaje cifrado
  char*msg="Este es canal abierto.";
  gnutls_record_send(tls_sesion,msg,strlen(msg)+1);

  //CIERRA
  if(gnutls_bye(tls_sesion,GNUTLS_SHUT_WR)<0)printf("TLS: Falla cerrando\n");
  close(nsck);
  gnutls_deinit(tls_sesion);
  close(lsck);
  gnutls_certificate_free_credentials(xcred);
  gnutls_priority_deinit(pcache);
  gnutls_global_deinit();

  return 0;
}

Клиент:

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <gnutls/gnutls.h>

int main(){
  int fd;
  const char*txterr;
  gnutls_certificate_credentials_t xcred;
  gnutls_session_t tls_sesion;

  //INICIA TLS
  if(!gnutls_check_version("3.5.10"))return -1;
  if(gnutls_global_init()<0)return -2;
  if(gnutls_certificate_allocate_credentials(&xcred)<0)return -3;
  if(gnutls_certificate_set_x509_system_trust(xcred)<0)return -4;
  if(gnutls_certificate_set_x509_trust_file(xcred,"cert/ca.crt",GNUTLS_X509_FMT_PEM)<0)return -5;
  //if(gnutls_certificate_set_x509_key_file(xcred,"cert/cert.pem","cert/key.pem",GNUTLS_X509_FMT_PEM)<0)return -5;

  //ABRE SOCKET
  fd=socket(AF_INET,SOCK_STREAM,0);
  if(fd==-1){printf("Imposible abrir nuevo E/S\n");return -1;}
  struct addrinfo hints,*serv,*p;
  char*zip="blackrook.ddns.net",*zprt="9080";
  memset(&hints,0,sizeof(hints));
  hints.ai_family=AF_UNSPEC;
  hints.ai_socktype=SOCK_STREAM;
  int i,ip;
  if(i=getaddrinfo(zip,zprt,&hints,&serv)){
    printf("Conexion no establecida\n");return 0;}
  for(p=serv;p!=0;p=p->ai_next){
    if(p->ai_addr->sa_family==AF_INET){
      ip=((struct sockaddr_in*)p->ai_addr)->sin_addr.s_addr;
      if(connect(fd,p->ai_addr,p->ai_addrlen)==-1)continue;
      freeaddrinfo(serv);
      printf("Conexion establecida\n");goto JmpConti;
    }
  }freeaddrinfo(serv);printf("Conexion no establecida2\n");return 0;
JmpConti:

  //CIFRA PUERTO
  gnutls_datum_t out;
  if(gnutls_init(&tls_sesion,GNUTLS_CLIENT)<0)return -6;
  if(gnutls_server_name_set(tls_sesion,GNUTLS_NAME_DNS,"blackrook.ddns.net",strlen("blackrook.ddns.net"))<0)return -7;
  if(gnutls_set_default_priority(tls_sesion)<0)return -8;
  int ret=gnutls_priority_set_direct(tls_sesion,"NORMAL",&txterr);
  if(ret<0){
    switch(ret){
    case GNUTLS_E_INVALID_REQUEST:
      printf("Error tipo %s\n",txterr);
      return -9;
    }
  }
  if(gnutls_credentials_set(tls_sesion,GNUTLS_CRD_CERTIFICATE,xcred)<0)return -10;
  gnutls_session_set_verify_cert(tls_sesion,"blackrook.ddns.net",0);
  //Toma el FD Socket
  gnutls_transport_set_int(tls_sesion,fd);
  gnutls_handshake_set_timeout(tls_sesion,GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
  do{ret=gnutls_handshake(tls_sesion);
  }while(ret<0&&!gnutls_error_is_fatal(ret));
  if(ret<0){
    printf("RET:%d\n",ret);
    gnutls_certificate_type_t type;
    int status;
    switch(ret){
    case GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR:
      type=gnutls_certificate_type_get(tls_sesion);
      status=gnutls_session_get_verify_cert_status(tls_sesion);
      if(gnutls_certificate_verification_status_print(status,type,&out,0)<0)return -255;
      printf("TLS: cert verify output: %s\n",out.data);
      gnutls_free(out.data);
    }
    printf("TLS: Handshake fallado: %s\n",gnutls_strerror(ret));
    return -11;
  }{
    char*desc=gnutls_session_get_desc(tls_sesion);
    printf("TLS: Session info: %s\n",desc);
    gnutls_free(desc);
  }
  //Recibe mensaje
  char msg[16387];long max=16387,nres;
  sleep(4);
  nres=gnutls_record_recv(tls_sesion,msg,max);
  printf("R:%s\n",msg);

  //CIERRA PUERTO
  if(gnutls_bye(tls_sesion,GNUTLS_SHUT_RDWR)<0)printf("TLS: Falla cerrando\n");
  close(fd);
  gnutls_deinit(tls_sesion);
  gnutls_certificate_free_credentials(xcred);
  gnutls_global_deinit();

  return 0;
}
...