TCP Socket - C Language
|
00001 00013 #include "commSSL.h" 00014 00015 void sslerr1(cli_conn * client); 00016 void sslerr2(char * file, int line); 00017 00018 int verify_client = ON; 00020 /* Crea una connessione SSL (server-side) sopra una connessione TCP */ 00021 srvSkSSL * newSSLServerChannel(const char *service){ 00022 srvSkSSL * server = NULL; 00023 00024 if (!service) { 00025 errno = EINVAL; 00026 sys_err(__FILE__,__LINE__,"Server: Error 'service' nullo."); 00027 return NULL; 00028 } 00029 00030 if (!(server = calloc(1, sizeof(srvSkSSL)))) { 00031 sys_err(__FILE__,__LINE__,"Server: Error calloc 'server'"); 00032 return NULL; 00033 } 00034 00035 if (!(server->srvSk = newServerChannel(service))) { 00036 free (server); 00037 return NULL; 00038 } 00039 00040 #ifdef _DEBUG_MODE 00041 /* Load the error strings for SSL & CRYPTO APIs */ 00042 SSL_load_error_strings(); /* ? valgrind ? */ 00043 #endif 00044 00045 /* Load encryption & hashing algorithms for the SSL program */ 00046 SSL_library_init(); /* ? valgrind ? */ 00047 00048 /* Create a SSL_CTX structure and 00049 * create a SSL_METHOD structure (choose a SSL/TLS protocol version) */ 00050 server->ctx = SSL_CTX_new(SSLv3_method()); 00051 00052 if (!server->ctx){ 00053 sslerr2(__FILE__,__LINE__); free (server); return NULL; 00054 } 00055 00056 /* Load the server certificate into the SSL_CTX structure */ 00057 if (SSL_CTX_use_certificate_file(server->ctx, RSA_SERVER_CERT, SSL_FILETYPE_PEM) <= 0) { 00058 sslerr2(__FILE__,__LINE__); 00059 closeServerSocket(server->srvSk); 00060 free (server); 00061 return NULL; 00062 } 00063 00064 /* Load the private-key corresponding to the server certificate */ 00065 if (SSL_CTX_use_PrivateKey_file(server->ctx, RSA_SERVER_KEY, SSL_FILETYPE_PEM) <= 0) { 00066 sslerr2(__FILE__,__LINE__); 00067 closeServerSocket(server->srvSk); 00068 free (server); 00069 return NULL; 00070 } 00071 00072 /* Check if the server certificate and private-key matches */ 00073 if (!SSL_CTX_check_private_key(server->ctx)){ 00074 sys_err(__FILE__,__LINE__,"Server: Private key does not match the certificate public key"); 00075 closeServerSocket(server->srvSk); 00076 free (server); 00077 return NULL; 00078 } 00079 00080 if (verify_client == ON){ 00081 /* Load the RSA CA certificate into the SSL_CTX structure */ 00082 if (!SSL_CTX_load_verify_locations(server->ctx, RSA_SERVER_CA_CERT, NULL)) { 00083 sslerr2(__FILE__,__LINE__); 00084 closeServerSocket(server->srvSk); 00085 free (server); 00086 return NULL; 00087 } 00088 /* Set to require peer (client) certificate verification */ 00089 SSL_CTX_set_verify(server->ctx,SSL_VERIFY_PEER,NULL); 00090 /* Set the verification depth to 1 */ 00091 SSL_CTX_set_verify_depth(server->ctx,1); 00092 } 00093 return server; 00094 } 00095 00096 /* Accetta una connessione da parte di un client e ritorna il 00097 * descrittore del canale di trasmissione con il client */ 00098 cli_conn * acceptSSLConnection(srvSkSSL * server){ 00099 int cli_sk = 0, err = 0; 00100 #ifdef _DEBUG_MODE 00101 X509 * client_cert = NULL; 00102 char * str = NULL; 00103 #endif 00104 cli_conn * client = NULL; 00105 00106 /* In caso di errore la acceptConnection ritorna -1 */ 00107 if ((cli_sk = acceptConnection(server->srvSk)) == -1){ 00108 sys_err(__FILE__,__LINE__,"Server: acceptSSLConnection"); 00109 return NULL; 00110 } 00111 00112 if (!(client = calloc(1, sizeof(cli_conn)))){ 00113 sys_err(__FILE__,__LINE__,"Server: acceptSSLConnection 'calloc'"); 00114 return NULL; 00115 } 00116 client->socket = cli_sk; 00117 00118 /* A SSL structure is created */ 00119 client->ssl = SSL_new(server->ctx); 00120 if (!client->ssl){ 00121 sys_err(__FILE__,__LINE__,"Server: Error on create new SSL ctx"); 00122 sslerr2(__FILE__,__LINE__); 00123 free (client); 00124 return NULL; 00125 } 00126 00127 /* Assign the socket into the SSL structure (SSL and socket without BIO) */ 00128 SSL_set_fd(client->ssl, cli_sk); 00129 00130 /* Perform SSL Handshake on the SSL server */ 00131 if ((err = SSL_accept(client->ssl)) == -1){ 00132 sslerr2(__FILE__,__LINE__); 00133 free (client); 00134 return NULL; 00135 } 00136 00137 #ifdef _DEBUG_MODE 00138 /* Informational output (optional) */ 00139 printf("Server: connessione SSL %s\n", SSL_get_cipher (client->ssl)); 00140 00141 if (verify_client == ON){ 00142 /* Get the client's certificate (optional) */ 00143 client_cert = SSL_get_peer_certificate(client->ssl); 00144 if (client_cert != NULL){ 00145 printf ("Client certificate:\n"); 00146 str = X509_NAME_oneline(X509_get_subject_name(client_cert), 0, 0); 00147 if (str == NULL){ 00148 free (client); 00149 return NULL; 00150 } 00151 printf ("\t subject: %s\n", str); 00152 free (str); 00153 str = X509_NAME_oneline(X509_get_issuer_name(client_cert), 0, 0); 00154 if (str == NULL){ 00155 free (client); 00156 return NULL; 00157 } 00158 printf ("\t issuer: %s\n", str); 00159 free (str); 00160 X509_free(client_cert); 00161 } 00162 else 00163 printf("Server: The SSL client does not have certificate.\n"); 00164 } 00165 #endif 00166 00167 return client; 00168 } 00169 00170 /* Scrive un messaggio sul canale di trasmissione rispettando 00171 * la struttura che contiene il messaggio da scrivere */ 00172 int sendSSLMessage(cli_conn * client, message_t *msg){ 00173 int char_sent = 0, sent = 0; 00174 00175 if ((sent = SSL_write(client->ssl, &(msg->type), sizeof(char))) < 0){ 00176 sys_err(__FILE__,__LINE__,"Error send message 'type'"); 00177 sslerr1(client); 00178 return -1; 00179 } 00180 char_sent = sent; 00181 00182 if ((sent = SSL_write(client->ssl, &(msg->length), sizeof(unsigned int))) < 0){ 00183 sys_err(__FILE__,__LINE__,"Error send message 'length'"); 00184 sslerr1(client); 00185 return -1; 00186 } 00187 char_sent += sent; 00188 00189 if (msg->length!=0){ 00190 if ((sent = SSL_write(client->ssl, msg->buffer, msg->length)) < 0){ 00191 sys_err(__FILE__,__LINE__,"Error send message 'buffer' "); 00192 sslerr1(client); 00193 return -1; 00194 } 00195 char_sent += sent; 00196 } 00197 return char_sent; 00198 } 00199 00200 /* Legge un messaggio dal canale di trasmissione */ 00201 int receiveSSLMessage(cli_conn * client, message_t *msg){ 00202 int ricevuti=0, tmp_cnt=0, read_cnt=0; 00203 char * buffer = NULL; 00204 00205 /* Se la struttura del messaggio non e' allocata.. */ 00206 if (!msg && !(msg = calloc(1, sizeof(message_t)))){ 00207 sys_err(__FILE__,__LINE__,"Error calloc 'msg': "); 00208 return -1; 00209 } 00210 00211 /* Leggo il tipo del messaggio */ 00212 if ((ricevuti = SSL_read(client->ssl, &(msg->type), sizeof(char))) < 0){ 00213 sys_err(__FILE__,__LINE__,"Error read message 'type': "); 00214 sslerr1(client); 00215 return -1; 00216 } 00217 read_cnt = ricevuti; 00218 00219 /* Leggo la dimensione del messaggio */ 00220 if ((ricevuti = SSL_read(client->ssl, &(msg->length), sizeof(unsigned int))) < 0){ 00221 sys_err(__FILE__,__LINE__,"Error read message 'length': "); 00222 sslerr1(client); 00223 return -1; 00224 } 00225 read_cnt += ricevuti; 00226 00227 /* Leggo il messaggio reale */ 00228 if (msg->length!=0){ 00229 if (!(buffer = calloc(msg->length+1, sizeof(char)))){ 00230 sys_err(__FILE__,__LINE__,"Error calloc 'buffer': "); 00231 return -1; 00232 } 00233 if (!(msg->buffer = calloc(msg->length+1, sizeof(char)))){ 00234 sys_err(__FILE__,__LINE__,"Error calloc 'msg->buffer': "); 00235 return -1; 00236 } 00237 while(tmp_cnt < msg->length){ 00238 if ((ricevuti = SSL_read(client->ssl, buffer, msg->length-tmp_cnt)) < 0){ 00239 sys_err(__FILE__,__LINE__,"Error read message 'buffer': "); 00240 sslerr1(client); 00241 return -1; 00242 } 00243 tmp_cnt += ricevuti; 00244 if (ricevuti > 0) strncat (msg->buffer, buffer, ricevuti); 00245 } 00246 free (buffer); 00247 read_cnt += tmp_cnt; 00248 } 00249 return read_cnt; 00250 } 00251 00252 /* Chiude e distrugge la socket di ascolto del server */ 00253 int closeSSLServerSocket(srvSkSSL * server){ 00254 if (!server) return 0; 00255 00256 /* Liberiamo la struttura del contesto SSL */ 00257 if (server->ctx) SSL_CTX_free (server->ctx); 00258 if (server->srvSk) closeServerSocket(server->srvSk); 00259 free (server); 00260 server = NULL; 00261 return 0; 00262 } 00263 00264 /* Chiude e distrugge una socket (client) */ 00265 int closeSSLConnection(cli_conn * client){ 00266 if (!client) return 0; /* Puntatore nullo, ritorno */ 00267 00268 if (client->ssl){ 00269 SSL_shutdown (client->ssl); 00270 SSL_free (client->ssl); 00271 } 00272 if (client->ctx) SSL_CTX_free (client->ctx); 00273 if (client->socket) closeConnection(client->socket); 00274 free (client); 00275 client = NULL; 00276 return 0; 00277 } 00278 00279 void unloadSSL(){ 00280 /* Ma quanta merda !!! */ 00281 ERR_remove_state(0); 00282 EVP_cleanup(); /* Thread unsafe */ 00283 CRYPTO_cleanup_all_ex_data(); /* Thread unsafe */ 00284 ERR_free_strings(); 00285 /*sk_SSL_COMP_free (SSL_COMP_get_compression_methods());*/ 00286 } 00287 00288 /* Stabilisce una connessione usando un layer SSL */ 00289 cli_conn * retrySSLConnection(const char * hostname, const char * portno){ 00290 cli_conn * client = NULL; 00291 #ifdef _DEBUG_MODE 00292 X509 * server_cert; 00293 char * str = NULL; 00294 #endif 00295 00296 if (!hostname){ 00297 errno = EINVAL; 00298 sys_err(__FILE__,__LINE__,"Server: retrySSLConnection 'hostname' nullo."); 00299 return NULL; 00300 } 00301 if (!portno){ 00302 errno = EINVAL; 00303 sys_err(__FILE__,__LINE__,"Server: retrySSLConnection 'portno' nullo."); 00304 return NULL; 00305 } 00306 00307 if (!(client = calloc(1, sizeof(cli_conn)))){ 00308 sys_err(__FILE__,__LINE__,"Client: Error calloc 'client': "); 00309 return NULL; 00310 } 00311 00312 client->socket = retryConnection(hostname, portno); 00313 if (client->socket == -1) return NULL; 00314 00315 #ifdef _DEBUG_MODE 00316 /* Register the error strings for libcrypto & libssl 00317 * Se la memoria e' un problema.. allora e' bene evitare. */ 00318 SSL_load_error_strings(); 00319 #endif 00320 00321 /* Register the available ciphers and digests */ 00322 SSL_library_init(); /* ? valgrind ? */ 00323 00324 /* New context saying we are a client, and using SSL 2 or 3 */ 00325 client->ctx = SSL_CTX_new(SSLv3_method()); 00326 if (!client->ctx){ 00327 sys_err(__FILE__,__LINE__,"Client: Error on create new SSL ctx"); 00328 sslerr2(__FILE__,__LINE__); free (client); return NULL; 00329 } 00330 00331 if (verify_client == ON){ 00332 /* Load the client certificate into the SSL_CTX structure */ 00333 if (SSL_CTX_use_certificate_file(client->ctx, RSA_CLIENT_CERT, SSL_FILETYPE_PEM) <= 0) { 00334 sslerr2(__FILE__,__LINE__); 00335 close(client->socket); 00336 free (client); 00337 return NULL; 00338 } 00339 00340 /* Load the private-key corresponding to the client certificate *//* ? valgrind ? */ 00341 if (SSL_CTX_use_PrivateKey_file(client->ctx, RSA_CLIENT_KEY, SSL_FILETYPE_PEM) <= 0) { 00342 sslerr2(__FILE__,__LINE__); 00343 close(client->socket); 00344 free (client); 00345 return NULL; 00346 } 00347 00348 /* Check if the client certificate and private-key matches */ 00349 if (!SSL_CTX_check_private_key(client->ctx)){ 00350 sys_err(__FILE__,__LINE__,"Client: Private key does not match the certificate public key"); 00351 close(client->socket); 00352 free (client); 00353 return NULL; 00354 } 00355 } 00356 00357 /* Load the RSA CA certificate into the SSL_CTX structure 00358 * This will allow this client to verify the server's 00359 * certificate. */ 00360 if (!SSL_CTX_load_verify_locations(client->ctx, RSA_CLIENT_CA_CERT, NULL)){ 00361 close(client->socket); 00362 sslerr2(__FILE__,__LINE__); 00363 free (client); 00364 return NULL; 00365 } 00366 00367 /* Set flag in context to require peer (server) certificate 00368 * verification */ 00369 SSL_CTX_set_verify(client->ctx,SSL_VERIFY_PEER,NULL); 00370 SSL_CTX_set_verify_depth(client->ctx,1); 00371 00372 /* Create an SSL struct for the connection */ 00373 client->ssl = SSL_new(client->ctx); 00374 if (!client->ssl){ 00375 sslerr2(__FILE__,__LINE__); 00376 close(client->socket); 00377 free (client); 00378 return NULL; 00379 } 00380 00381 /* Connect the SSL struct to our connection */ 00382 if (!SSL_set_fd(client->ssl, client->socket)){ 00383 sslerr2(__FILE__,__LINE__); 00384 close(client->socket); 00385 free (client); 00386 return NULL; 00387 } 00388 00389 /* Initiate SSL handshake */ 00390 if (SSL_connect(client->ssl) != 1){ 00391 sslerr2(__FILE__,__LINE__); 00392 close(client->socket); 00393 free (client); 00394 return NULL; 00395 } 00396 00397 #ifdef _DEBUG_MODE 00398 /* Informational output (optional) */ 00399 printf ("SSL connection using %s\n", SSL_get_cipher(client->ssl)); 00400 00401 /* Get the server's certificate (optional) */ 00402 server_cert = SSL_get_peer_certificate(client->ssl); 00403 00404 if (server_cert != NULL){ 00405 printf ("Server certificate:\n"); 00406 00407 if (!(str = X509_NAME_oneline(X509_get_subject_name(server_cert),0,0))){ 00408 sys_err(__FILE__,__LINE__,"Client: 'X509_get_subject_name'"); 00409 close(client->socket); 00410 free (client); 00411 return NULL; 00412 } 00413 printf ("\t subject: %s\n", str); 00414 free (str); 00415 00416 if (!(str = X509_NAME_oneline(X509_get_issuer_name(server_cert),0,0))){ 00417 sys_err(__FILE__,__LINE__,"Client: 'X509_get_iusser_name'"); 00418 close(client->socket); 00419 free (client); 00420 return NULL; 00421 } 00422 printf ("\t issuer: %s\n", str); 00423 free(str); 00424 X509_free (server_cert); 00425 } 00426 else 00427 printf("The SSL server does not have certificate.\n"); 00428 #endif 00429 00430 return client; 00431 } 00432 00433 /*__________________________________________________________________________ */ 00434 00435 #ifdef _DEBUG_MODE 00436 00437 void sslerr1(cli_conn * client){ 00438 int err = 0; 00439 fprintf(stderr,"SSL error number %i\n", SSL_get_error(client->ssl, err)); 00440 ERR_print_errors_fp(stderr); 00441 } 00442 00443 void sslerr2(char * file, int line){ 00444 fprintf(stderr,"Errore file %s, linea %d\n", file, line-1); 00445 ERR_print_errors_fp(stderr); 00446 } 00447 00448 #else 00449 00450 void sslerr1(cli_conn * client){} 00451 00452 void sslerr2(char * file, int line){} 00453 #endif 00454