如我在以下网站中提到的示例中所见,关于我以前使用的代码版本与以前几乎相同的示例,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;
}