/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Gestion du socket du bot ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Auteur: Thaeron
Projet: NewSyndrome
Licence: GPL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
#include "NewSyndrome.h"
#ifndef ENABLE_IPV6
int tcp_connect
(const char *server_host
, int port
, const char *bind_ip
)
{
struct sockaddr_in sindist
, msim
;
int ret
= -1;
struct hostent
*host
;
unsigned long opt
= 1;
int sock
;
sock
= socket
(AF_INET
, SOCK_STREAM
, 0);
if (sock
== -1)
return (NS_NO_SOCKET
);
if (bind_ip
&& *bind_ip
)
{
msim.
sin_addr.
s_addr = inet_addr
(bind_ip
);
msim.
sin_family = AF_INET
;
msim.
sin_port = htons
(0);
setsockopt
(sock
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &opt
, sizeof (opt
));
if (bind
(sock
, (struct sockaddr
*) &msim
, sizeof (msim
)) < 0)
{
closesocket
(sock
);
return (NS_CANNOT_BIND
);
}
}
sindist.
sin_family = AF_INET
;
sindist.
sin_addr.
s_addr = inet_addr
(server_host
);
sindist.
sin_port = htons
(port
);
if (sindist.
sin_addr.
s_addr == -1)
{
host
= gethostbyname
(server_host
);
if (host
== NULL
)
{
closesocket
(sock
);
return (NS_CANNOT_RESOLVE
);
}
memcpy ((char *) &sindist.
sin_addr.
s_addr, host
->h_addr
, host
->h_length
);
}
ret
= connect
(sock
, (struct sockaddr
*) &sindist
, sizeof (struct sockaddr_in
));
if (ret
< 0)
{
closesocket
(sock
);
return (NS_CANNOT_CONNECT
);
}
return (sock
);
}
#endif
#ifdef ENABLE_IPV6
int tcp_connect
(const char *server_host
, int port
, const char *bind_ip
)
{
int sock
;
int ret
;
struct addrinfo
*res
;
char *str_port
;
str_port
= strf
("%d", port
);
ret
= getaddrinfo
(server_host
, str_port
, NULL
, &res
);
free (str_port
);
if (ret
)
return (NS_CANNOT_RESOLVE
);
sock
= socket
(res
->ai_family
, SOCK_STREAM
, 0);
if (sock
== -1)
return (NS_NO_SOCKET
);
ret
= connect
(sock
, res
->ai_addr
, res
->ai_addrlen
);
freeaddrinfo
(res
);
if (ret
< 0)
{
closesocket
(sock
);
return (NS_CANNOT_CONNECT
);
}
return (sock
);
}
#endif
#ifdef ENABLE_SSL_CONNECTION
#ifdef SSL_FROM_OPENSSL
SSL_CTX
*initialize_ctx
(void)
{
static byte init_once
= 0;
SSL_METHOD
*meth
;
SSL_CTX
*ctx
;
if (!init_once
)
{
SSL_library_init
();
SSL_load_error_strings
();
init_once
= 1;
}
meth
= SSLv23_method
();
ctx
= SSL_CTX_new
(meth
);
SSL_CTX_load_verify_locations
(ctx
, "", 0);
#if (OPENSSL_VERSION_NUMBER < 0x00905100L)
SSL_CTX_set_verify_depth
(ctx
, 1);
#endif
return (ctx
);
}
/*int check_cert(SSL *ssl, char *host)
{
X509 *peer;
char peer_CN[256];
if (SSL_get_verify_result (ssl) != X509_V_OK)
log_info ("SSL certificate non signé\n");
peer = SSL_get_peer_certificate (ssl);
if (peer == NULL)
log_infof ("SSL : heu un truc");
else
{
if (X509_NAME_get_text_by_NID (X509_get_subject_name (peer), NID_commonName, peer_CN, 256) == -1)
log_infof ("SSL : getting host name fails");
else if (strcmp (peer_CN, host))
log_infof ("SSL: common name doesn't match host name\nSSL: [%s]<=>[%s]\n", peer_CN, host);
}
return (0);
}*/
int ssl_connect
(void)
{
BIO
*sbio
;
ns_core.
ctx = initialize_ctx
();
ns_core.
ssl = SSL_new
(ns_core.
ctx);
sbio
= BIO_new_socket
(ns_core.
sd, BIO_NOCLOSE
);
SSL_set_bio
(ns_core.
ssl, sbio
, sbio
);
if (SSL_connect
(ns_core.
ssl) <= 0)
return (-1);
/*if (check_cert (ns_core.ssl, ns_conf.server) < 0)
return (-1);*/
return (1);
}
void ssl_free_all
(void)
{
SSL_free
(ns_core.
ssl);
SSL_CTX_free
(ns_core.
ctx);
}
#endif
#ifdef SSL_FROM_GNUTLS
int ssl_connect
(void)
{
const char *err
;
int ret
;
gnutls_global_init
();
gnutls_certificate_allocate_credentials
(&ns_core.
xcred);
gnutls_certificate_set_x509_trust_file
(ns_core.
xcred, "", GNUTLS_X509_FMT_PEM
);
gnutls_init
(&ns_core.
session, GNUTLS_CLIENT
);
ret
= gnutls_priority_set_direct
(ns_core.
session, "PERFORMANCE", &err
);
if (ret
< 0)
{
if (ret
== GNUTLS_E_INVALID_REQUEST
)
log_infof
("SSL : Syntax error at: %s", err
);
return (-1);
}
gnutls_credentials_set
(ns_core.
session, GNUTLS_CRD_CERTIFICATE
, ns_core.
xcred);
gnutls_transport_set_ptr
(ns_core.
session, (gnutls_transport_ptr_t
) ((long int) ns_core.
sd));
ret
= gnutls_handshake
(ns_core.
session);
if (ret
< 0)
{
log_infof
("SSL Error : Handshake failed (%s)", gnutls_strerror
(ret
));
gnutls_deinit
(ns_core.
session);
gnutls_certificate_free_credentials
(ns_core.
xcred);
gnutls_global_deinit
();
return (-1);
}
return (1);
}
void ssl_free_all
(void)
{
gnutls_bye
(ns_core.
session, GNUTLS_SHUT_RDWR
);
gnutls_deinit
(ns_core.
session);
gnutls_certificate_free_credentials
(ns_core.
xcred);
gnutls_global_deinit
();
}
#endif
#endif
ssize_t ns_send
(int s
, const void *buf
, size_t len
, int flags
)
{
#ifdef ENABLE_SSL_CONNECTION
if (ns_conf.
use_ssl)
{
#ifdef SSL_FROM_OPENSSL
return (SSL_write
(ns_core.
ssl, buf
, len
));
#endif
#ifdef SSL_FROM_GNUTLS
return (gnutls_record_send
(ns_core.
session, buf
, len
));
#endif
log_info
("Erreur : SSL activé à la compilation et dans la configuration mais sans support d'openssl ou de gnutls");
}
#endif
return (send
(s
, buf
, len
, flags
));
}
ssize_t ns_recv
(int s
, void *buf
, size_t len
, int flags
)
{
#ifdef ENABLE_SSL_CONNECTION
if (ns_conf.
use_ssl)
{
#ifdef SSL_FROM_OPENSSL
return (SSL_read
(ns_core.
ssl, buf
, len
));
#endif
#ifdef SSL_FROM_GNUTLS
return (gnutls_record_recv
(ns_core.
session, buf
, len
));
#endif
log_info
("Erreur : SSL activé à la compilation et dans la configuration mais sans support d'OpenSSL ou de GnuTLS");
}
#endif
return (recv
(s
, buf
, len
, flags
));
}