23 |
#include <config.h> |
#include <config.h> |
24 |
#include <stdio.h> |
#include <stdio.h> |
25 |
#include <memory.h> |
#include <memory.h> |
26 |
|
#include <time.h> |
27 |
|
|
28 |
#ifdef HAVE_SYS_TYPES_H |
#ifdef HAVE_SYS_TYPES_H |
29 |
#include <sys/types.h> |
#include <sys/types.h> |
70 |
#include <openssl/ssl.h> |
#include <openssl/ssl.h> |
71 |
#include <openssl/err.h> |
#include <openssl/err.h> |
72 |
#include <openssl/rand.h> |
#include <openssl/rand.h> |
73 |
|
#include <openssl/bio.h> |
74 |
#endif |
#endif |
75 |
|
|
76 |
#include "monitor.h" |
#include "monitor.h" |
77 |
#include "net.h" |
#include "net.h" |
78 |
#include "ssl.h" |
#include "ssl.h" |
79 |
|
|
|
/* Private prototypes */ |
|
|
|
|
80 |
#ifdef HAVE_OPENSSL |
#ifdef HAVE_OPENSSL |
81 |
|
|
82 |
|
/* Initialization code */ |
83 |
static int ssl_thread_start(void); |
static int ssl_thread_start(void); |
84 |
static int ssl_thread_stop(void); |
static int ssl_thread_stop(void); |
85 |
static int unsigned long ssl_thread_id(void); |
static int unsigned long ssl_thread_id(void); |
87 |
static int ssl_entropy_start(void); |
static int ssl_entropy_start(void); |
88 |
static int ssl_entropy_stop(void); |
static int ssl_entropy_stop(void); |
89 |
|
|
90 |
|
static pthread_mutex_t ssl_mutex= PTHREAD_MUTEX_INITIALIZER; |
91 |
|
static pthread_mutex_t *ssl_mutex_table; |
92 |
|
static int ssl_initilized= FALSE; |
93 |
|
|
94 |
|
/* Connection verification code */ |
95 |
static int verify_init(ssl_server_connection *); |
static int verify_init(ssl_server_connection *); |
96 |
static int verify_callback(int, X509_STORE_CTX *); |
static int verify_callback(int, X509_STORE_CTX *); |
97 |
static int verify_callback_noclientcert(int, X509_STORE_CTX *); |
static int verify_callback_noclientcert(int, X509_STORE_CTX *); |
98 |
static void verify_info(ssl_server_connection *); |
static void verify_info(ssl_server_connection *); |
99 |
|
static int check_preverify(X509_STORE_CTX *); |
100 |
|
|
|
static pthread_mutex_t ssl_mutex= PTHREAD_MUTEX_INITIALIZER; |
|
|
static pthread_mutex_t *ssl_mutex_table; |
|
|
|
|
|
static int ssl_initilized= FALSE; |
|
101 |
static int allow_self_certfication= FALSE; |
static int allow_self_certfication= FALSE; |
102 |
|
static int allow_any_purpose= FALSE; |
103 |
|
|
104 |
|
/* Error handling */ |
105 |
|
static int handle_connection_error(int, ssl_connection *, char *); |
106 |
|
static void handle_ssl_error(char *); |
107 |
|
#define SSLERROR ERR_error_string(ERR_get_error(),NULL) |
108 |
|
|
109 |
|
#define ALLOW_ANY_PURPOSE |
110 |
|
|
111 |
#endif |
#endif |
112 |
|
|
113 |
/** |
/** |
140 |
*/ |
*/ |
141 |
|
|
142 |
|
|
143 |
|
/* |
144 |
|
* For some of the code I was enlightened by: |
145 |
|
* |
146 |
|
* An Introduction to OpenSSL Programming, Part I of II |
147 |
|
* |
148 |
|
* by Eric Rescorla |
149 |
|
* Linux Journal 9/2001 |
150 |
|
* http://www.linuxjournal.com/article.php?sid=4822 |
151 |
|
*/ |
152 |
|
|
153 |
/* ------------------------------------------------------------------ Public */ |
/* ------------------------------------------------------------------ Public */ |
154 |
|
|
155 |
|
|
161 |
int embed_ssl_socket (ssl_connection *ssl, int socket) { |
int embed_ssl_socket (ssl_connection *ssl, int socket) { |
162 |
|
|
163 |
#ifdef HAVE_OPENSSL |
#ifdef HAVE_OPENSSL |
164 |
|
|
165 |
|
int ssl_error; |
166 |
|
time_t ssl_time; |
167 |
|
|
168 |
if ( ssl == NULL ) { |
if ( ssl == NULL ) { |
169 |
|
|
183 |
|
|
184 |
} else { |
} else { |
185 |
|
|
186 |
error("Socket error!\n"); |
error("%s: Socket error!\n", prog); |
187 |
goto sslerror; |
goto sslerror; |
188 |
} |
} |
189 |
|
|
190 |
if ((ssl->handler= SSL_new (ssl->ctx)) == NULL ) { |
if ((ssl->handler= SSL_new (ssl->ctx)) == NULL ) { |
191 |
|
|
192 |
error("Cannot initialize the SSL handler!\n"); |
handle_ssl_error("embed_ssl_socket()"); |
193 |
|
error("%s: Cannot initialize the SSL handler!\n", prog); |
194 |
goto sslerror; |
goto sslerror; |
195 |
|
|
196 |
} |
} |
197 |
|
|
198 |
SSL_set_fd (ssl->handler, ssl->socket); |
set_noblock(ssl->socket); |
199 |
|
|
200 |
if (SSL_connect (ssl->handler) == -1) { |
if((ssl->socket_bio= BIO_new_socket(ssl->socket, BIO_NOCLOSE)) == NULL) { |
201 |
|
|
202 |
error("Cannot connect with the SSL service!\n"); |
handle_ssl_error("embed_ssl_socket()"); |
203 |
|
error("%s: Cannot generate IO buffer!\n", prog); |
204 |
goto sslerror; |
goto sslerror; |
205 |
|
|
206 |
} |
} |
207 |
|
|
208 |
|
SSL_set_bio(ssl->handler, ssl->socket_bio, ssl->socket_bio); |
209 |
|
|
210 |
|
ssl_time=time(NULL); |
211 |
|
|
212 |
|
while((ssl_error= SSL_connect (ssl->handler)) < 0) { |
213 |
|
|
214 |
|
if((time(NULL)-ssl_time) > SSL_TIMEOUT) { |
215 |
|
|
216 |
|
error("%s: The connection process with the SSL service timed out!\n", |
217 |
|
prog); |
218 |
|
goto sslerror; |
219 |
|
|
220 |
|
} |
221 |
|
|
222 |
|
if (!handle_connection_error(ssl_error, ssl, "embed_ssl_socket()")) { |
223 |
|
|
224 |
|
goto sslerror; |
225 |
|
|
226 |
|
} |
227 |
|
|
228 |
|
} |
229 |
|
|
230 |
ssl->cipher= (char *) SSL_get_cipher(ssl->handler); |
ssl->cipher= (char *) SSL_get_cipher(ssl->handler); |
231 |
|
|
232 |
if (! update_ssl_cert_data(ssl)) { |
if (! update_ssl_cert_data(ssl)) { |
233 |
|
|
234 |
error("Cannot get the SSL server certificate!\n"); |
error("%s: Cannot get the SSL server certificate!\n", |
235 |
|
prog); |
236 |
goto sslerror; |
goto sslerror; |
237 |
|
|
238 |
} |
} |
351 |
|
|
352 |
if ((socket= create_socket(hostname, port, protocol)) == -1) { |
if ((socket= create_socket(hostname, port, protocol)) == -1) { |
353 |
|
|
354 |
error("Cannot connect!\n"); |
error("%s: Cannot connect!\n", prog); |
355 |
goto sslerror; |
goto sslerror; |
356 |
|
|
357 |
} |
} |
358 |
|
|
359 |
if (! embed_ssl_socket(ssl, socket)) { |
if (! embed_ssl_socket(ssl, socket)) { |
360 |
|
|
361 |
error("Cannot embed socket!\n"); |
error("%s: Cannot embed socket!\n", prog); |
362 |
|
|
363 |
goto sslerror; |
goto sslerror; |
364 |
|
|
388 |
|
|
389 |
#ifdef HAVE_OPENSSL |
#ifdef HAVE_OPENSSL |
390 |
|
|
391 |
|
int error; |
392 |
|
|
393 |
if(ssl == NULL) { |
if(ssl == NULL) { |
394 |
|
|
395 |
return FALSE; |
return FALSE; |
396 |
|
|
397 |
} |
} |
398 |
|
|
399 |
SSL_shutdown (ssl->handler); |
if (! (error= SSL_shutdown (ssl->handler))) { |
400 |
|
|
401 |
|
shutdown(ssl->socket,1 ); |
402 |
|
error= SSL_shutdown (ssl->handler); |
403 |
|
|
404 |
|
} |
405 |
|
|
406 |
close(ssl->socket); |
close(ssl->socket); |
407 |
cleanup_ssl_socket(ssl); |
cleanup_ssl_socket(ssl); |
408 |
|
|
409 |
return TRUE; |
if ( error<=0 ) { |
410 |
|
|
411 |
|
return FALSE; |
412 |
|
|
413 |
|
} else { |
414 |
|
|
415 |
|
return TRUE; |
416 |
|
|
417 |
|
} |
418 |
|
|
419 |
#else |
#else |
420 |
|
|
454 |
|
|
455 |
} |
} |
456 |
|
|
457 |
|
if (ssl->socket_bio != NULL) { |
458 |
|
|
459 |
|
/* |
460 |
|
* no BIO_free(ssl->socket_bio); necessary, because BIO is freed |
461 |
|
* by ssl->handler |
462 |
|
*/ |
463 |
|
|
464 |
|
ssl->socket_bio= NULL; |
465 |
|
|
466 |
|
} |
467 |
|
|
468 |
if (ssl->cert_issuer != NULL) { |
if (ssl->cert_issuer != NULL) { |
469 |
|
|
470 |
free(ssl->cert_issuer); |
free(ssl->cert_issuer); |
549 |
|
|
550 |
#ifdef HAVE_OPENSSL |
#ifdef HAVE_OPENSSL |
551 |
|
|
552 |
ssl_server_connection *ssl_server = new_ssl_server_connection(pemfile, clientpemfile); |
ssl_server_connection *ssl_server = new_ssl_server_connection(pemfile, |
553 |
|
clientpemfile); |
554 |
|
|
555 |
ASSERT(pemfile); |
ASSERT(pemfile); |
556 |
|
|
562 |
|
|
563 |
if ((ssl_server->method= SSLv23_server_method()) == NULL ) { |
if ((ssl_server->method= SSLv23_server_method()) == NULL ) { |
564 |
|
|
565 |
error("Cannot initialize the SSL method to use!\n"); |
handle_ssl_error("init_ssl_server()"); |
566 |
|
error("%s: Cannot initialize the SSL method to use!\n", prog); |
567 |
goto sslerror; |
goto sslerror; |
568 |
|
|
569 |
} |
} |
570 |
|
|
571 |
if ((ssl_server->ctx= SSL_CTX_new(ssl_server->method)) == NULL ) { |
if ((ssl_server->ctx= SSL_CTX_new(ssl_server->method)) == NULL ) { |
572 |
|
|
573 |
error("Cannot initialize the SSL server's certificate handler!\n"); |
handle_ssl_error("init_ssl_server()"); |
574 |
|
error("%s: Cannot initialize the SSL server's certificate handler!\n" |
575 |
|
, prog); |
576 |
goto sslerror; |
goto sslerror; |
577 |
|
|
578 |
} |
} |
580 |
if (SSL_CTX_use_certificate_file(ssl_server->ctx, pemfile, |
if (SSL_CTX_use_certificate_file(ssl_server->ctx, pemfile, |
581 |
SSL_FILETYPE_PEM) <= 0) { |
SSL_FILETYPE_PEM) <= 0) { |
582 |
|
|
583 |
error("Cannot initialize the SSL server's certificate!\n"); |
handle_ssl_error("init_ssl_server()"); |
584 |
|
error("%s: Cannot initialize the SSL server's certificate!\n", prog); |
585 |
goto sslerror; |
goto sslerror; |
586 |
|
|
587 |
} |
} |
589 |
if (SSL_CTX_use_PrivateKey_file(ssl_server->ctx, pemfile, |
if (SSL_CTX_use_PrivateKey_file(ssl_server->ctx, pemfile, |
590 |
SSL_FILETYPE_PEM) <= 0) { |
SSL_FILETYPE_PEM) <= 0) { |
591 |
|
|
592 |
error("Cannot initialize the SSL server's private key!\n"); |
handle_ssl_error("init_ssl_server()"); |
593 |
|
error("%s: Cannot initialize the SSL server's private key!\n", prog); |
594 |
goto sslerror; |
goto sslerror; |
595 |
|
|
596 |
} |
} |
597 |
|
|
598 |
if (!SSL_CTX_check_private_key(ssl_server->ctx)) { |
if (!SSL_CTX_check_private_key(ssl_server->ctx)) { |
599 |
|
|
600 |
error("The private key does not match the certificate public key!\n"); |
handle_ssl_error("init_ssl_server()"); |
601 |
|
error("%s: The private key does not match the certificate public key!\n", |
602 |
|
prog); |
603 |
goto sslerror; |
goto sslerror; |
604 |
|
|
605 |
} |
} |
609 |
*/ |
*/ |
610 |
if (!verify_init(ssl_server)) { |
if (!verify_init(ssl_server)) { |
611 |
|
|
612 |
error("Verification engine was not properly initilized!\n"); |
handle_ssl_error("init_ssl_server()"); |
613 |
|
error("%s: Verification engine was not properly initilized!\n", prog); |
614 |
goto sslerror; |
goto sslerror; |
615 |
|
|
616 |
} |
} |
663 |
|
|
664 |
if ((socket= create_server_socket(port, backlog, bindAddr)) == -1) { |
if ((socket= create_server_socket(port, backlog, bindAddr)) == -1) { |
665 |
|
|
666 |
error("Cannot connect!\n"); |
error("%s: Cannot connect!\n", prog); |
667 |
goto sslerror; |
goto sslerror; |
668 |
|
|
669 |
} |
} |
942 |
LOCK(ssl_mutex); |
LOCK(ssl_mutex); |
943 |
|
|
944 |
if ( ssl->prev == NULL ) { |
if ( ssl->prev == NULL ) { |
945 |
|
|
946 |
ssl_server->ssl_conn_list=ssl->next; |
ssl_server->ssl_conn_list=ssl->next; |
947 |
|
|
948 |
} else { |
} else { |
953 |
|
|
954 |
END_LOCK; |
END_LOCK; |
955 |
|
|
956 |
if (! cleanup_ssl_socket(ssl)) { |
if(! cleanup_ssl_socket(ssl)) { |
957 |
|
|
958 |
return_value= FALSE; |
return_value= FALSE; |
959 |
|
|
960 |
} |
} |
961 |
|
|
962 |
if (! delete_ssl_socket(ssl)) { |
if (! delete_ssl_socket(ssl)) { |
963 |
|
|
964 |
return_value= FALSE; |
return_value= FALSE; |
986 |
|
|
987 |
#ifdef HAVE_OPENSSL |
#ifdef HAVE_OPENSSL |
988 |
|
|
989 |
|
int ssl_error; |
990 |
|
time_t ssl_time; |
991 |
|
|
992 |
ASSERT(ssl); |
ASSERT(ssl); |
993 |
|
|
994 |
ssl->socket=socket; |
ssl->socket=socket; |
995 |
|
|
996 |
if (!ssl_initilized) { |
if(!ssl_initilized) { |
997 |
|
|
998 |
start_ssl(); |
start_ssl(); |
999 |
|
|
1000 |
} |
} |
1001 |
|
|
1002 |
if ((ssl->handler= SSL_new(ssl->ctx)) == NULL ) { |
if((ssl->handler= SSL_new(ssl->ctx)) == NULL) { |
|
|
|
|
error("Cannot initialize the SSL handler!\n"); |
|
1003 |
|
|
1004 |
|
handle_ssl_error("embed_accepted_ssl_socket()"); |
1005 |
|
error("%s: Cannot initialize the SSL handler!\n", prog); |
1006 |
|
goto sslerror; |
1007 |
|
|
1008 |
} |
} |
1009 |
|
|
1010 |
if ( socket >= 0 ) { |
if(socket < 0) { |
|
|
|
|
SSL_set_fd(ssl->handler, ssl->socket); |
|
|
|
|
|
} else { |
|
1011 |
|
|
1012 |
error("Socket error!\n"); |
error("Socket error!\n"); |
1013 |
goto sslerror; |
goto sslerror; |
1014 |
|
|
1015 |
} |
} |
1016 |
|
|
1017 |
if (SSL_accept(ssl->handler) == -1) { |
set_noblock(ssl->socket); |
1018 |
|
|
1019 |
|
if((ssl->socket_bio= BIO_new_socket(ssl->socket, BIO_NOCLOSE)) == NULL) { |
1020 |
|
|
1021 |
error("Accept with SSL service has failed!\n"); |
handle_ssl_error("embed_accepted_ssl_socket()"); |
1022 |
|
error("%s: Cannot generate IO buffer!\n", prog); |
1023 |
goto sslerror; |
goto sslerror; |
1024 |
|
|
1025 |
} |
} |
1026 |
|
|
1027 |
|
SSL_set_bio(ssl->handler, ssl->socket_bio, ssl->socket_bio); |
1028 |
|
|
1029 |
|
ssl_time= time(NULL); |
1030 |
|
|
1031 |
|
while((ssl_error= SSL_accept(ssl->handler)) < 0) { |
1032 |
|
|
1033 |
|
if((time(NULL)-ssl_time) > SSL_TIMEOUT) { |
1034 |
|
|
1035 |
|
error("%s: The connection process with the SSL service timed out!\n", |
1036 |
|
prog); |
1037 |
|
goto sslerror; |
1038 |
|
|
1039 |
|
} |
1040 |
|
|
1041 |
|
if (!handle_connection_error(ssl_error, ssl, |
1042 |
|
"embed_accepted_ssl_socket()")) { |
1043 |
|
|
1044 |
|
goto sslerror; |
1045 |
|
|
1046 |
|
} |
1047 |
|
|
1048 |
|
} |
1049 |
|
|
1050 |
ssl->cipher= (char *) SSL_get_cipher(ssl->handler); |
ssl->cipher= (char *) SSL_get_cipher(ssl->handler); |
1051 |
|
|
1052 |
if (! update_ssl_cert_data(ssl) && (ssl->clientpemfile != NULL)) { |
if(!update_ssl_cert_data(ssl) && (ssl->clientpemfile != NULL)) { |
1053 |
|
|
1054 |
error("The client did not supply a required client certificate!\n"); |
error("%s: The client did not supply a required client certificate!\n", |
1055 |
|
prog); |
1056 |
|
goto sslerror; |
1057 |
|
|
1058 |
|
} |
1059 |
|
|
1060 |
|
if (SSL_get_verify_result(ssl->handler)>0) { |
1061 |
|
|
1062 |
|
error("%s: Verification of the certificate has failed!\n", |
1063 |
|
prog); |
1064 |
goto sslerror; |
goto sslerror; |
1065 |
|
|
1066 |
} |
} |
1098 |
no_crypt_socket= accept(ssl_server->server_socket, (struct sockaddr*)&in, |
no_crypt_socket= accept(ssl_server->server_socket, (struct sockaddr*)&in, |
1099 |
&len); |
&len); |
1100 |
|
|
1101 |
if ( no_crypt_socket >= 0 ) { |
if(no_crypt_socket >= 0) { |
1102 |
|
|
1103 |
ssl_connection *ssl = insert_accepted_ssl_socket(ssl_server); |
ssl_connection *ssl = insert_accepted_ssl_socket(ssl_server); |
1104 |
|
|
1105 |
if ( ssl == NULL ) { |
if(ssl == NULL) { |
1106 |
|
|
1107 |
return NULL; |
return NULL; |
1108 |
|
|
1109 |
} |
} |
1110 |
|
|
1111 |
if (embed_accepted_ssl_socket(ssl, no_crypt_socket)) { |
if(embed_accepted_ssl_socket(ssl, no_crypt_socket)) { |
1112 |
|
|
1113 |
return ssl; |
return ssl; |
1114 |
|
|
1144 |
int send_ssl_socket(ssl_connection *ssl, void *buffer, int len) { |
int send_ssl_socket(ssl_connection *ssl, void *buffer, int len) { |
1145 |
|
|
1146 |
#ifdef HAVE_OPENSSL |
#ifdef HAVE_OPENSSL |
1147 |
|
int ssl_error; |
1148 |
|
time_t ssl_time= time(NULL); |
1149 |
|
|
1150 |
ASSERT(ssl); |
ASSERT(ssl); |
1151 |
|
|
1152 |
return SSL_write (ssl->handler, (void *) buffer, len); |
|
1153 |
|
while((ssl_error= SSL_write (ssl->handler, (void *) buffer, len)) < 0) { |
1154 |
|
|
1155 |
|
if((time(NULL)-ssl_time) > SSL_TIMEOUT) { |
1156 |
|
|
1157 |
|
error("%s: The connection process with the SSL service has timed" |
1158 |
|
" out!\n", prog); |
1159 |
|
break; |
1160 |
|
|
1161 |
|
} |
1162 |
|
|
1163 |
|
if (!handle_connection_error(ssl_error, ssl, "send_ssl_socket()")) { |
1164 |
|
|
1165 |
|
break; |
1166 |
|
|
1167 |
|
} |
1168 |
|
|
1169 |
|
} |
1170 |
|
|
1171 |
|
return ssl_error; |
1172 |
|
|
1173 |
#else |
#else |
1174 |
|
|
1189 |
int recv_ssl_socket(ssl_connection *ssl, void *buffer, int len) { |
int recv_ssl_socket(ssl_connection *ssl, void *buffer, int len) { |
1190 |
|
|
1191 |
#ifdef HAVE_OPENSSL |
#ifdef HAVE_OPENSSL |
1192 |
|
int ssl_error; |
1193 |
|
time_t ssl_time= time(NULL); |
1194 |
|
|
1195 |
ASSERT(ssl); |
ASSERT(ssl); |
1196 |
|
|
1197 |
return SSL_read(ssl->handler, (void *) buffer, len); |
while((ssl_error= SSL_read(ssl->handler, (void *) buffer, len)) < 0) { |
1198 |
|
|
1199 |
|
if((time(NULL)-ssl_time) > SSL_TIMEOUT) { |
1200 |
|
|
1201 |
|
error("%s: The connection process with the SSL service has timed" |
1202 |
|
" out!\n", prog); |
1203 |
|
break; |
1204 |
|
|
1205 |
|
} |
1206 |
|
|
1207 |
|
if (!handle_connection_error(ssl_error, ssl, "recv_ssl_socket()")) { |
1208 |
|
|
1209 |
|
break; |
1210 |
|
|
1211 |
|
} |
1212 |
|
} |
1213 |
|
|
1214 |
|
return ssl_error; |
1215 |
|
|
1216 |
#else |
#else |
1217 |
|
|
1328 |
if (! ssl_initilized ) { |
if (! ssl_initilized ) { |
1329 |
|
|
1330 |
ssl_initilized=TRUE; |
ssl_initilized=TRUE; |
1331 |
|
ERR_load_crypto_strings(); |
1332 |
return (ssl_thread_start() && SSL_library_init() && ssl_entropy_start()); |
return (ssl_thread_start() && SSL_library_init() && ssl_entropy_start()); |
1333 |
|
|
1334 |
} else { |
} else { |
1357 |
if ( ssl_initilized ) { |
if ( ssl_initilized ) { |
1358 |
|
|
1359 |
ssl_initilized=FALSE; |
ssl_initilized=FALSE; |
1360 |
|
ERR_free_strings(); |
1361 |
return (ssl_thread_stop() && ssl_entropy_stop()); |
return (ssl_thread_stop() && ssl_entropy_stop()); |
1362 |
|
|
1363 |
} else { |
} else { |
1406 |
|
|
1407 |
} |
} |
1408 |
|
|
1409 |
|
ssl->socket_bio= NULL; |
1410 |
ssl->handler= NULL; |
ssl->handler= NULL; |
1411 |
ssl->cert= NULL; |
ssl->cert= NULL; |
1412 |
ssl->cipher= NULL; |
ssl->cipher= NULL; |
1428 |
|
|
1429 |
if ((ssl->method= SSLv23_client_method()) == NULL ) { |
if ((ssl->method= SSLv23_client_method()) == NULL ) { |
1430 |
|
|
1431 |
error("Cannot initilize SSL method!\n"); |
handle_ssl_error("new_ssl_connection()"); |
1432 |
|
error("%s: Cannot initilize SSL method!\n", prog); |
1433 |
goto sslerror; |
goto sslerror; |
1434 |
|
|
1435 |
} |
} |
1436 |
|
|
1437 |
if ((ssl->ctx= SSL_CTX_new (ssl->method)) == NULL ) { |
if ((ssl->ctx= SSL_CTX_new (ssl->method)) == NULL ) { |
1438 |
|
|
1439 |
error("Cannot initilize SSL server certificate handler!\n"); |
handle_ssl_error("new_ssl_connection()"); |
1440 |
|
error("%s: Cannot initilize SSL server certificate handler!\n", prog); |
1441 |
goto sslerror; |
goto sslerror; |
1442 |
|
|
1443 |
} |
} |
1447 |
if (SSL_CTX_use_certificate_file(ssl->ctx, ssl->clientpemfile, |
if (SSL_CTX_use_certificate_file(ssl->ctx, ssl->clientpemfile, |
1448 |
SSL_FILETYPE_PEM) <= 0) { |
SSL_FILETYPE_PEM) <= 0) { |
1449 |
|
|
1450 |
error("Cannot initilize SSL server certificate!\n"); |
handle_ssl_error("new_ssl_connection()"); |
1451 |
|
error("%s: Cannot initilize SSL server certificate!\n", prog); |
1452 |
goto sslerror; |
goto sslerror; |
1453 |
|
|
1454 |
} |
} |
1456 |
if (SSL_CTX_use_PrivateKey_file(ssl->ctx, ssl->clientpemfile, |
if (SSL_CTX_use_PrivateKey_file(ssl->ctx, ssl->clientpemfile, |
1457 |
SSL_FILETYPE_PEM) <= 0) { |
SSL_FILETYPE_PEM) <= 0) { |
1458 |
|
|
1459 |
error("Cannot initilize SSL server private key!\n"); |
handle_ssl_error("new_ssl_connection()"); |
1460 |
|
error("%s: Cannot initilize SSL server private key!\n", prog); |
1461 |
goto sslerror; |
goto sslerror; |
1462 |
|
|
1463 |
} |
} |
1464 |
|
|
1465 |
if (!SSL_CTX_check_private_key(ssl->ctx)) { |
if (!SSL_CTX_check_private_key(ssl->ctx)) { |
1466 |
|
|
1467 |
error("Private key does not match the certificate public key!\n"); |
handle_ssl_error("new_ssl_connection()"); |
1468 |
|
error("%s: Private key does not match the certificate public key!\n", |
1469 |
|
prog); |
1470 |
goto sslerror; |
goto sslerror; |
1471 |
|
|
1472 |
} |
} |
1495 |
* Generate a new ssl server connection |
* Generate a new ssl server connection |
1496 |
* @return ssl server connection container |
* @return ssl server connection container |
1497 |
*/ |
*/ |
1498 |
ssl_server_connection *new_ssl_server_connection(char * pemfile, char * clientpemfile) { |
ssl_server_connection *new_ssl_server_connection(char * pemfile, |
1499 |
|
char * clientpemfile) { |
1500 |
|
|
1501 |
#ifdef HAVE_OPENSSL |
#ifdef HAVE_OPENSSL |
1502 |
|
|
1503 |
ssl_server_connection *ssl_server = (ssl_server_connection *) NEW(ssl_server); |
ssl_server_connection *ssl_server = |
1504 |
|
(ssl_server_connection *) NEW(ssl_server); |
1505 |
|
|
1506 |
ASSERT(pemfile); |
ASSERT(pemfile); |
1507 |
|
|
1558 |
|
|
1559 |
/* ----------------------------------------------------------------- Private */ |
/* ----------------------------------------------------------------- Private */ |
1560 |
|
|
|
|
|
|
|
|
1561 |
#ifdef HAVE_OPENSSL |
#ifdef HAVE_OPENSSL |
1562 |
|
|
|
|
|
1563 |
/** |
/** |
1564 |
* Init verification of transmitted client certs |
* Init verification of transmitted client certs |
1565 |
*/ |
*/ |
1569 |
|
|
1570 |
if (ssl_server->clientpemfile==NULL) { |
if (ssl_server->clientpemfile==NULL) { |
1571 |
|
|
1572 |
|
allow_any_purpose= TRUE; |
1573 |
SSL_CTX_set_verify(ssl_server->ctx, SSL_VERIFY_PEER , |
SSL_CTX_set_verify(ssl_server->ctx, SSL_VERIFY_PEER , |
1574 |
verify_callback_noclientcert); |
verify_callback_noclientcert); |
1575 |
goto end_success; /* No verification, but we have to call the callback! */ |
goto end_success; /* No verification, but we have to call the callback! */ |
1590 |
if (!SSL_CTX_load_verify_locations(ssl_server->ctx, NULL , |
if (!SSL_CTX_load_verify_locations(ssl_server->ctx, NULL , |
1591 |
ssl_server->clientpemfile)) { |
ssl_server->clientpemfile)) { |
1592 |
|
|
1593 |
|
handle_ssl_error("verify_init()"); |
1594 |
error("%s: Error setting verify directory to %s\n", |
error("%s: Error setting verify directory to %s\n", |
1595 |
Run.httpsslclientpem); |
Run.httpsslclientpem); |
1596 |
|
|
1605 |
if(!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->pemfile, |
if(!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->pemfile, |
1606 |
NULL)) { |
NULL)) { |
1607 |
|
|
1608 |
|
handle_ssl_error("verify_init()"); |
1609 |
error("%s: Error loading verify certificates from %s\n", |
error("%s: Error loading verify certificates from %s\n", |
1610 |
prog, ssl_server->pemfile); |
prog, ssl_server->pemfile); |
1611 |
|
|
1617 |
|
|
1618 |
} else if (S_ISREG(stat_buf.st_mode)) { |
} else if (S_ISREG(stat_buf.st_mode)) { |
1619 |
|
|
1620 |
if(!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->clientpemfile, |
if(!SSL_CTX_load_verify_locations(ssl_server->ctx, |
1621 |
|
ssl_server->clientpemfile, |
1622 |
NULL)) { |
NULL)) { |
1623 |
|
|
1624 |
|
handle_ssl_error("verify_init()"); |
1625 |
error("%s: Error loading verify certificates from %s\n", |
error("%s: Error loading verify certificates from %s\n", |
1626 |
prog, Run.httpsslclientpem); |
prog, Run.httpsslclientpem); |
1627 |
|
|
1636 |
if(!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->pemfile, |
if(!SSL_CTX_load_verify_locations(ssl_server->ctx, ssl_server->pemfile, |
1637 |
NULL)) { |
NULL)) { |
1638 |
|
|
1639 |
|
handle_ssl_error("verify_init()"); |
1640 |
error("%s: Error loading verify certificates from %s\n", |
error("%s: Error loading verify certificates from %s\n", |
1641 |
prog, ssl_server->pemfile); |
prog, ssl_server->pemfile); |
1642 |
|
|
1658 |
|
|
1659 |
} |
} |
1660 |
|
|
1661 |
|
allow_any_purpose= FALSE; |
1662 |
SSL_CTX_set_verify(ssl_server->ctx, SSL_VERIFY_PEER , verify_callback); |
SSL_CTX_set_verify(ssl_server->ctx, SSL_VERIFY_PEER , verify_callback); |
1663 |
|
|
1664 |
end_success: |
end_success: |
1683 |
|
|
1684 |
if(!preverify_ok) { |
if(!preverify_ok) { |
1685 |
|
|
1686 |
if (ctx->error != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) { |
if (!check_preverify(ctx)) { |
1687 |
|
|
1688 |
/* Remote site specified a certificate, but it's not correct */ |
goto reject; |
|
|
|
|
log("SSL VERIFY ERROR: depth=%d, error=[%d] '%s': %s\n", |
|
|
ctx->error_depth, ctx->error, |
|
|
X509_verify_cert_error_string (ctx->error), subject); |
|
|
goto reject; /* Reject connection */ |
|
|
|
|
|
} else { |
|
|
|
|
|
if(allow_self_certfication) { |
|
|
|
|
|
/* Let's accept self signed Certs for the moment! */ |
|
|
|
|
|
log("SSL VERIFY WARNING: depth=%d, error=[%d] '%s': %s\n", |
|
|
ctx->error_depth, ctx->error, |
|
|
X509_verify_cert_error_string (ctx->error), subject); |
|
|
|
|
|
} else { |
|
|
|
|
|
log("SSL VERIFY ERROR: depth=%d, error=[%d] '%s': %s\n", |
|
|
ctx->error_depth, ctx->error, |
|
|
X509_verify_cert_error_string (ctx->error), subject); |
|
|
goto reject; /* Reject connection */ |
|
|
|
|
|
} |
|
1689 |
|
|
1690 |
} |
} |
1691 |
|
|
1696 |
X509_get_subject_name(ctx->current_cert), |
X509_get_subject_name(ctx->current_cert), |
1697 |
&found_cert)!=1) { |
&found_cert)!=1) { |
1698 |
|
|
1699 |
log("SSL VERIFY ERROR: no cert found for %s\n", subject); |
handle_ssl_error("verify_callback()"); |
1700 |
|
error("%s: SSL connection rejected. No matching certificate found.", prog); |
1701 |
|
|
1702 |
goto reject; |
goto reject; |
1703 |
|
|
1706 |
return 1; |
return 1; |
1707 |
|
|
1708 |
reject: |
reject: |
|
log("HTTPD connection denied!\n"); |
|
1709 |
return 0; |
return 0; |
1710 |
|
|
1711 |
} |
} |
1723 |
|
|
1724 |
if(!preverify_ok) { |
if(!preverify_ok) { |
1725 |
|
|
1726 |
if (ctx->error != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) { |
if (!check_preverify(ctx)) { |
1727 |
|
|
1728 |
/* Remote site specified a certificate, but it's not correct */ |
goto reject; |
1729 |
|
|
1730 |
log("SSL VERIFY ERROR: depth=%d, error=[%d] '%s': %s\n", |
} |
|
ctx->error_depth, ctx->error, |
|
|
X509_verify_cert_error_string (ctx->error), subject); |
|
|
goto reject; /* Reject connection */ |
|
1731 |
|
|
1732 |
} else { |
} |
1733 |
|
|
1734 |
if(allow_self_certfication) { |
return 1; |
1735 |
|
|
1736 |
/* Let's accept self signed Certs for the moment! */ |
reject: |
1737 |
|
return 0; |
1738 |
|
|
1739 |
log("SSL VERIFY WARNING: depth=%d, error=[%d] '%s': %s\n", |
} |
|
ctx->error_depth, ctx->error, |
|
|
X509_verify_cert_error_string (ctx->error), subject); |
|
1740 |
|
|
1741 |
} else { |
/** |
1742 |
|
* Analyse errors found before actual verification |
1743 |
|
* @return TRUE if successful |
1744 |
|
*/ |
1745 |
|
static int check_preverify(X509_STORE_CTX *ctx) { |
1746 |
|
|
1747 |
log("SSL VERIFY ERROR: depth=%d, error=[%d] '%s': %s\n", |
if ((ctx->error != X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) && |
1748 |
ctx->error_depth, ctx->error, |
(ctx->error != X509_V_ERR_INVALID_PURPOSE)) { |
|
X509_verify_cert_error_string (ctx->error), subject); |
|
|
goto reject; /* Reject connection */ |
|
1749 |
|
|
1750 |
} |
/* Remote site specified a certificate, but it's not correct */ |
1751 |
|
|
1752 |
|
error("%s: SSL connection rejected because certificate verification" |
1753 |
|
" has failed -- Error %i\n", prog, ctx->error); |
1754 |
|
return FALSE; /* Reject connection */ |
1755 |
|
|
1756 |
} |
} |
1757 |
|
|
|
} |
|
1758 |
|
|
1759 |
return 1; |
if(allow_self_certfication && |
1760 |
|
(ctx->error == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)) { |
1761 |
|
|
1762 |
|
/* Let's accept self signed certs for the moment! */ |
1763 |
|
|
1764 |
|
log("SSL connection accepted with self signed certificate!\n"); |
1765 |
|
|
1766 |
reject: |
ctx->error=0; |
1767 |
log("HTTPD connection denied!\n"); |
return TRUE; |
|
return 0; |
|
1768 |
|
|
1769 |
} |
} |
1770 |
|
|
1771 |
|
if(allow_any_purpose && |
1772 |
|
(ctx->error == X509_V_ERR_INVALID_PURPOSE)) { |
1773 |
|
|
1774 |
|
/* Let's accept any purpose certs for the moment! */ |
1775 |
|
|
1776 |
|
log("SSL connection accepted with invalid purpose!\n"); |
1777 |
|
|
1778 |
|
ctx->error=0; |
1779 |
|
return TRUE; |
1780 |
|
|
1781 |
|
} |
1782 |
|
|
1783 |
|
error("%s: SSL connection rejected because certificate verification" |
1784 |
|
" has failed -- Error %i!\n", prog, ctx->error); |
1785 |
|
return FALSE; /* Reject connection */ |
1786 |
|
|
1787 |
|
|
1788 |
|
} |
1789 |
|
|
1790 |
|
/** |
1791 |
|
* Print info about the verification engine |
1792 |
|
*/ |
1793 |
static void verify_info(ssl_server_connection *ssl_server) { |
static void verify_info(ssl_server_connection *ssl_server) { |
1794 |
|
|
1795 |
STACK_OF(X509_NAME) *stack; |
STACK_OF(X509_NAME) *stack; |
1903 |
|
|
1904 |
} |
} |
1905 |
|
|
1906 |
|
|
1907 |
|
/** |
1908 |
|
* Handle errors during read, write, connect and accept |
1909 |
|
* @return TRUE if non fatal, FALSE if non fatal and retry |
1910 |
|
*/ |
1911 |
|
static int handle_connection_error(int code, ssl_connection *ssl, |
1912 |
|
char *operation) { |
1913 |
|
|
1914 |
|
int ssl_error= 0; |
1915 |
|
|
1916 |
|
switch ((ssl_error= SSL_get_error(ssl->handler, code))) { |
1917 |
|
|
1918 |
|
case SSL_ERROR_WANT_READ: |
1919 |
|
case SSL_ERROR_WANT_WRITE: |
1920 |
|
return TRUE; |
1921 |
|
|
1922 |
|
case SSL_ERROR_SYSCALL: |
1923 |
|
error("%s: Openssl syscall error during %s: %s!\n", prog, operation, |
1924 |
|
STRERROR); |
1925 |
|
return FALSE; |
1926 |
|
|
1927 |
|
case SSL_ERROR_SSL: |
1928 |
|
handle_ssl_error(operation); |
1929 |
|
return FALSE; |
1930 |
|
|
1931 |
|
default: |
1932 |
|
error("%s: Openssl error during %s!\n", prog, operation); |
1933 |
|
return FALSE; |
1934 |
|
|
1935 |
|
} |
1936 |
|
|
1937 |
|
return FALSE; |
1938 |
|
} |
1939 |
|
|
1940 |
|
|
1941 |
|
/** |
1942 |
|
* Handle errors of arbitrary SSL calls |
1943 |
|
*/ |
1944 |
|
static void handle_ssl_error(char *operation) { |
1945 |
|
|
1946 |
|
error("%s: Openssl engine error during %s: %s\n", prog, operation, SSLERROR); |
1947 |
|
|
1948 |
|
} |
1949 |
|
|
1950 |
#endif |
#endif |