TCP Socket - C Language
|
libreria di comunicazione server client
Continua...
Vai al codice sorgente di questo file.
Strutture dati | |
struct | srvSkSSL |
struct | cli_conn |
Definizioni | |
#define | RSA_SERVER_CERT "server.crt" |
#define | RSA_SERVER_KEY "server.key" |
#define | RSA_SERVER_CA_CERT "server_ca.crt" |
#define | RSA_SERVER_CA_PATH "sys$common:[syshlp.examples.ssl]" |
#define | RSA_CLIENT_CERT "client.crt" |
#define | RSA_CLIENT_KEY "client.key" |
#define | RSA_CLIENT_CA_CERT "client_ca.crt" |
#define | RSA_CLIENT_CA_PATH "sys$common:[syshlp.examples.ssl]" |
#define | ON 1 |
#define | OFF 0 |
Funzioni | |
srvSkSSL * | newSSLServerChannel (const char *service) |
cli_conn * | acceptSSLConnection (srvSkSSL *server) |
int | receiveSSLMessage (cli_conn *client, message_t *msg) |
int | sendSSLMessage (cli_conn *client, message_t *msg) |
int | closeSSLServerSocket (srvSkSSL *server) |
int | closeSSLConnection (cli_conn *client) |
cli_conn * | retrySSLConnection (const char *hostname, const char *service) |
void | unloadSSL () |
libreria di comunicazione server client
This program is free software; you can redistribuite it and/or modify it under the terms of the GNU/General Pubblic License as published the Free software Foundation; either version 2 of the License, or (at your opinion) any later version.
Definizione nel file commSSL.h.
#define RSA_SERVER_CERT "server.crt" |
#define RSA_SERVER_CA_CERT "server_ca.crt" |
#define RSA_SERVER_CA_PATH "sys$common:[syshlp.examples.ssl]" |
#define RSA_CLIENT_CERT "client.crt" |
#define RSA_CLIENT_CA_CERT "client_ca.crt" |
#define RSA_CLIENT_CA_PATH "sys$common:[syshlp.examples.ssl]" |
srvSkSSL* newSSLServerChannel | ( | const char * | service | ) |
Crea le sockets di ascolto. Open passive (server) sockets for the indicated inet service & protocol. Notice in the last sentence that "sockets" is plural. During the interim transition period while everyone is switching over to IPv6, the server application has to open two sockets on which to listen for connections... one for IPv4 traffic and one for IPv6 traffic.
service | Pointer to a character string representing the well-known port on which to listen (can be a service name or a decimal number). |
Definizione alla linea 21 del file commSSL.c.
{ srvSkSSL * server = NULL; if (!service) { errno = EINVAL; sys_err(__FILE__,__LINE__,"Server: Error 'service' nullo."); return NULL; } if (!(server = calloc(1, sizeof(srvSkSSL)))) { sys_err(__FILE__,__LINE__,"Server: Error calloc 'server'"); return NULL; } if (!(server->srvSk = newServerChannel(service))) { free (server); return NULL; } #ifdef _DEBUG_MODE /* Load the error strings for SSL & CRYPTO APIs */ SSL_load_error_strings(); /* ? valgrind ? */ #endif /* Load encryption & hashing algorithms for the SSL program */ SSL_library_init(); /* ? valgrind ? */ /* Create a SSL_CTX structure and * create a SSL_METHOD structure (choose a SSL/TLS protocol version) */ server->ctx = SSL_CTX_new(SSLv3_method()); if (!server->ctx){ sslerr2(__FILE__,__LINE__); free (server); return NULL; } /* Load the server certificate into the SSL_CTX structure */ if (SSL_CTX_use_certificate_file(server->ctx, RSA_SERVER_CERT, SSL_FILETYPE_PEM) <= 0) { sslerr2(__FILE__,__LINE__); closeServerSocket(server->srvSk); free (server); return NULL; } /* Load the private-key corresponding to the server certificate */ if (SSL_CTX_use_PrivateKey_file(server->ctx, RSA_SERVER_KEY, SSL_FILETYPE_PEM) <= 0) { sslerr2(__FILE__,__LINE__); closeServerSocket(server->srvSk); free (server); return NULL; } /* Check if the server certificate and private-key matches */ if (!SSL_CTX_check_private_key(server->ctx)){ sys_err(__FILE__,__LINE__,"Server: Private key does not match the certificate public key"); closeServerSocket(server->srvSk); free (server); return NULL; } if (verify_client == ON){ /* Load the RSA CA certificate into the SSL_CTX structure */ if (!SSL_CTX_load_verify_locations(server->ctx, RSA_SERVER_CA_CERT, NULL)) { sslerr2(__FILE__,__LINE__); closeServerSocket(server->srvSk); free (server); return NULL; } /* Set to require peer (client) certificate verification */ SSL_CTX_set_verify(server->ctx,SSL_VERIFY_PEER,NULL); /* Set the verification depth to 1 */ SSL_CTX_set_verify_depth(server->ctx,1); } return server; }
accetta una connessione da parte di un client
server | struttura dati della socket di ascolto del server |
Definizione alla linea 98 del file commSSL.c.
{ int cli_sk = 0, err = 0; #ifdef _DEBUG_MODE X509 * client_cert = NULL; char * str = NULL; #endif cli_conn * client = NULL; /* In caso di errore la acceptConnection ritorna -1 */ if ((cli_sk = acceptConnection(server->srvSk)) == -1){ sys_err(__FILE__,__LINE__,"Server: acceptSSLConnection"); return NULL; } if (!(client = calloc(1, sizeof(cli_conn)))){ sys_err(__FILE__,__LINE__,"Server: acceptSSLConnection 'calloc'"); return NULL; } client->socket = cli_sk; /* A SSL structure is created */ client->ssl = SSL_new(server->ctx); if (!client->ssl){ sys_err(__FILE__,__LINE__,"Server: Error on create new SSL ctx"); sslerr2(__FILE__,__LINE__); free (client); return NULL; } /* Assign the socket into the SSL structure (SSL and socket without BIO) */ SSL_set_fd(client->ssl, cli_sk); /* Perform SSL Handshake on the SSL server */ if ((err = SSL_accept(client->ssl)) == -1){ sslerr2(__FILE__,__LINE__); free (client); return NULL; } #ifdef _DEBUG_MODE /* Informational output (optional) */ printf("Server: connessione SSL %s\n", SSL_get_cipher (client->ssl)); if (verify_client == ON){ /* Get the client's certificate (optional) */ client_cert = SSL_get_peer_certificate(client->ssl); if (client_cert != NULL){ printf ("Client certificate:\n"); str = X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0); if (str == NULL){ free (client); return NULL; } printf ("\t subject: %s\n", str); free (str); str = X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0); if (str == NULL){ free (client); return NULL; } printf ("\t issuer: %s\n", str); free (str); X509_free(client_cert); } else printf("Server: The SSL client does not have certificate.\n"); } #endif return client; }
legge un messaggio dal channel di trasmissione
client | struttura di comunicazione del cliente |
msg | struttura che conterra' il messagio letto (deve essere allocata all'esterno della funzione, tranne il campo buffer) |
Definizione alla linea 201 del file commSSL.c.
{ int ricevuti=0, tmp_cnt=0, read_cnt=0; char * buffer = NULL; /* Se la struttura del messaggio non e' allocata.. */ if (!msg && !(msg = calloc(1, sizeof(message_t)))){ sys_err(__FILE__,__LINE__,"Error calloc 'msg': "); return -1; } /* Leggo il tipo del messaggio */ if ((ricevuti = SSL_read(client->ssl, &(msg->type), sizeof(char))) < 0){ sys_err(__FILE__,__LINE__,"Error read message 'type': "); sslerr1(client); return -1; } read_cnt = ricevuti; /* Leggo la dimensione del messaggio */ if ((ricevuti = SSL_read(client->ssl, &(msg->length), sizeof(unsigned int))) < 0){ sys_err(__FILE__,__LINE__,"Error read message 'length': "); sslerr1(client); return -1; } read_cnt += ricevuti; /* Leggo il messaggio reale */ if (msg->length!=0){ if (!(buffer = calloc(msg->length+1, sizeof(char)))){ sys_err(__FILE__,__LINE__,"Error calloc 'buffer': "); return -1; } if (!(msg->buffer = calloc(msg->length+1, sizeof(char)))){ sys_err(__FILE__,__LINE__,"Error calloc 'msg->buffer': "); return -1; } while(tmp_cnt < msg->length){ if ((ricevuti = SSL_read(client->ssl, buffer, msg->length-tmp_cnt)) < 0){ sys_err(__FILE__,__LINE__,"Error read message 'buffer': "); sslerr1(client); return -1; } tmp_cnt += ricevuti; if (ricevuti > 0) strncat (msg->buffer, buffer, ricevuti); } free (buffer); read_cnt += tmp_cnt; } return read_cnt; }
scrive un messaggio sul channel di trasmissione
client | struttura di comunicazione del client |
msg | struttura che contiene il messaggio da scrivere |
Definizione alla linea 172 del file commSSL.c.
{ int char_sent = 0, sent = 0; if ((sent = SSL_write(client->ssl, &(msg->type), sizeof(char))) < 0){ sys_err(__FILE__,__LINE__,"Error send message 'type'"); sslerr1(client); return -1; } char_sent = sent; if ((sent = SSL_write(client->ssl, &(msg->length), sizeof(unsigned int))) < 0){ sys_err(__FILE__,__LINE__,"Error send message 'length'"); sslerr1(client); return -1; } char_sent += sent; if (msg->length!=0){ if ((sent = SSL_write(client->ssl, msg->buffer, msg->length)) < 0){ sys_err(__FILE__,__LINE__,"Error send message 'buffer' "); sslerr1(client); return -1; } char_sent += sent; } return char_sent; }
int closeSSLServerSocket | ( | srvSkSSL * | server | ) |
Distrugge un canale di ascolto (server-side)
server | struttura dati della socket di ascolto del server |
Definizione alla linea 253 del file commSSL.c.
{ if (!server) return 0; /* Liberiamo la struttura del contesto SSL */ if (server->ctx) SSL_CTX_free (server->ctx); if (server->srvSk) closeServerSocket(server->srvSk); free (server); server = NULL; return 0; }
int closeSSLConnection | ( | cli_conn * | client | ) |
Chiude un socket
client | struttura di comunicazione del client |
cli_conn* retrySSLConnection | ( | const char * | hostname, |
const char * | service | ||
) |
crea una socket di trasmissione verso il server, tentando la connessione per un massimo di due minuti se MAXSLEEP e' 128
hostname | Indirizzo del server |
service | Nome del servizio (noto) o numero di porta del server |
Definizione alla linea 289 del file commSSL.c.
{ cli_conn * client = NULL; #ifdef _DEBUG_MODE X509 * server_cert; char * str = NULL; #endif if (!hostname){ errno = EINVAL; sys_err(__FILE__,__LINE__,"Server: retrySSLConnection 'hostname' nullo."); return NULL; } if (!portno){ errno = EINVAL; sys_err(__FILE__,__LINE__,"Server: retrySSLConnection 'portno' nullo."); return NULL; } if (!(client = calloc(1, sizeof(cli_conn)))){ sys_err(__FILE__,__LINE__,"Client: Error calloc 'client': "); return NULL; } client->socket = retryConnection(hostname, portno); if (client->socket == -1) return NULL; #ifdef _DEBUG_MODE /* Register the error strings for libcrypto & libssl * Se la memoria e' un problema.. allora e' bene evitare. */ SSL_load_error_strings(); #endif /* Register the available ciphers and digests */ SSL_library_init(); /* ? valgrind ? */ /* New context saying we are a client, and using SSL 2 or 3 */ client->ctx = SSL_CTX_new(SSLv3_method()); if (!client->ctx){ sys_err(__FILE__,__LINE__,"Client: Error on create new SSL ctx"); sslerr2(__FILE__,__LINE__); free (client); return NULL; } if (verify_client == ON){ /* Load the client certificate into the SSL_CTX structure */ if (SSL_CTX_use_certificate_file(client->ctx, RSA_CLIENT_CERT, SSL_FILETYPE_PEM) <= 0) { sslerr2(__FILE__,__LINE__); close(client->socket); free (client); return NULL; } /* Load the private-key corresponding to the client certificate *//* ? valgrind ? */ if (SSL_CTX_use_PrivateKey_file(client->ctx, RSA_CLIENT_KEY, SSL_FILETYPE_PEM) <= 0) { sslerr2(__FILE__,__LINE__); close(client->socket); free (client); return NULL; } /* Check if the client certificate and private-key matches */ if (!SSL_CTX_check_private_key(client->ctx)){ sys_err(__FILE__,__LINE__,"Client: Private key does not match the certificate public key"); close(client->socket); free (client); return NULL; } } /* Load the RSA CA certificate into the SSL_CTX structure * This will allow this client to verify the server's * certificate. */ if (!SSL_CTX_load_verify_locations(client->ctx, RSA_CLIENT_CA_CERT, NULL)){ close(client->socket); sslerr2(__FILE__,__LINE__); free (client); return NULL; } /* Set flag in context to require peer (server) certificate * verification */ SSL_CTX_set_verify(client->ctx,SSL_VERIFY_PEER,NULL); SSL_CTX_set_verify_depth(client->ctx,1); /* Create an SSL struct for the connection */ client->ssl = SSL_new(client->ctx); if (!client->ssl){ sslerr2(__FILE__,__LINE__); close(client->socket); free (client); return NULL; } /* Connect the SSL struct to our connection */ if (!SSL_set_fd(client->ssl, client->socket)){ sslerr2(__FILE__,__LINE__); close(client->socket); free (client); return NULL; } /* Initiate SSL handshake */ if (SSL_connect(client->ssl) != 1){ sslerr2(__FILE__,__LINE__); close(client->socket); free (client); return NULL; } #ifdef _DEBUG_MODE /* Informational output (optional) */ printf ("SSL connection using %s\n", SSL_get_cipher(client->ssl)); /* Get the server's certificate (optional) */ server_cert = SSL_get_peer_certificate(client->ssl); if (server_cert != NULL){ printf ("Server certificate:\n"); if (!(str = X509_NAME_oneline(X509_get_subject_name(server_cert),0,0))){ sys_err(__FILE__,__LINE__,"Client: 'X509_get_subject_name'"); close(client->socket); free (client); return NULL; } printf ("\t subject: %s\n", str); free (str); if (!(str = X509_NAME_oneline(X509_get_issuer_name(server_cert),0,0))){ sys_err(__FILE__,__LINE__,"Client: 'X509_get_iusser_name'"); close(client->socket); free (client); return NULL; } printf ("\t issuer: %s\n", str); free(str); X509_free (server_cert); } else printf("The SSL server does not have certificate.\n"); #endif return client; }
void unloadSSL | ( | ) |
Cerca di scaricare tutta la merda messa in memoria dalle librerie SSL
Definizione alla linea 279 del file commSSL.c.
{ /* Ma quanta merda !!! */ ERR_remove_state(0); EVP_cleanup(); /* Thread unsafe */ CRYPTO_cleanup_all_ex_data(); /* Thread unsafe */ ERR_free_strings(); /*sk_SSL_COMP_free (SSL_COMP_get_compression_methods());*/ }