Fix using /dev/urandom since it wasn't working
[umurmur.git] / src / ssl.c
1 /* Copyright (C) 2009-2012, Martin Johansson <martin@fatbob.nu>
2    Copyright (C) 2005-2012, Thorvald Natvig <thorvald@natvig.com>
3
4    All rights reserved.
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9
10    - Redistributions of source code must retain the above copyright notice,
11      this list of conditions and the following disclaimer.
12    - Redistributions in binary form must reproduce the above copyright notice,
13      this list of conditions and the following disclaimer in the documentation
14      and/or other materials provided with the distribution.
15    - Neither the name of the Developers nor the names of its contributors may
16      be used to endorse or promote products derived from this software without
17      specific prior written permission.
18
19    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
23    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31 #include <string.h>
32 #include <stdlib.h>
33 #include <fcntl.h>
34
35 #include "conf.h"
36 #include "log.h"
37 #include "ssl.h"
38
39 #ifdef USE_POLARSSL
40 /*
41  * PolarSSL interface
42  */
43
44 #include <polarssl/havege.h>
45 #include <polarssl/certs.h>
46 #include <polarssl/x509.h>
47 #include <polarssl/ssl.h>
48 #include <polarssl/net.h>
49
50 #ifdef POLARSSL_API_V1_2
51 int ciphers[] =
52 {
53     TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
54     TLS_RSA_WITH_AES_256_CBC_SHA,
55     TLS_RSA_WITH_AES_128_CBC_SHA,
56     0
57 };
58 #else
59 int ciphers[] =
60 {
61     SSL_EDH_RSA_AES_256_SHA,
62     SSL_RSA_AES_256_SHA,
63     SSL_RSA_AES_128_SHA,
64     0
65 };
66 #endif
67 static x509_cert certificate;
68 static rsa_context key;
69 bool_t builtInTestCertificate;
70
71 #ifdef USE_POLARSSL_HAVEGE
72 havege_state hs;
73 #else
74 int urandom_fd;
75 #endif
76
77 /* DH prime */
78 char *my_dhm_P =
79         "9CE85640903BF123906947FEDE767261" \
80         "D9B4A973EB8F7D984A8C656E2BCC161C" \
81         "183D4CA471BA78225F940F16D1D99CA3" \
82         "E66152CC68EDCE1311A390F307741835" \
83         "44FF6AB553EC7073AD0CB608F2A3B480" \
84         "19E6C02BCED40BD30E91BB2469089670" \
85         "DEF409C08E8AC24D1732A6128D2220DC53";
86 char *my_dhm_G = "4";
87
88 #ifdef USE_POLARSSL_TESTCERT
89 static void initTestCert()
90 {
91         int rc;
92         builtInTestCertificate = true;
93         rc = x509parse_crt(&certificate, (unsigned char *)test_srv_crt,
94                                            strlen(test_srv_crt));       
95         if (rc != 0)
96                 Log_fatal("Could not parse built-in test certificate");
97 }
98
99 static void initTestKey()
100 {
101         int rc;
102         
103         rc = x509parse_key(&key, (unsigned char *)test_srv_key,
104                                            strlen(test_srv_key), NULL, 0);
105         if (rc != 0)
106                 Log_fatal("Could not parse built-in test RSA key");
107 }
108 #endif
109
110 /*
111  * How to generate a self-signed cert with openssl:
112  * openssl genrsa 1024 > host.key
113  * openssl req -new -x509 -nodes -sha1 -days 365 -key host.key > host.cert
114  */
115 static void initCert()
116 {
117         int rc;
118         char *crtfile = (char *)getStrConf(CERTIFICATE);
119         
120         if (crtfile == NULL) {
121 #ifdef USE_POLARSSL_TESTCERT
122                 Log_warn("No certificate file specified. Falling back to test certificate.");
123                 initTestCert();
124 #else
125                 Log_fatal("No certificate file specified");
126 #endif
127                 return;
128         }
129         rc = x509parse_crtfile(&certificate, crtfile);
130         if (rc != 0) {
131 #ifdef USE_POLARSSL_TESTCERT
132                 Log_warn("Could not read certificate file '%s'. Falling back to test certificate.", crtfile);
133                 initTestCert();
134 #else
135                 Log_fatal("Could not read certificate file '%s'", crtfile);
136 #endif
137                 return;
138         }
139 }
140
141 static void initKey()
142 {
143         int rc;
144         char *keyfile = (char *)getStrConf(KEY);
145
146         if (keyfile == NULL)
147                 Log_fatal("No key file specified"); 
148         rc = x509parse_keyfile(&key, keyfile, NULL);
149         if (rc != 0)
150                 Log_fatal("Could not read RSA key file %s", keyfile);
151 }
152
153 #ifndef USE_POLARSSL_HAVEGE
154 int urandom_bytes(void *ctx, unsigned char *dest, size_t len)
155 {
156         int cur;
157         
158         while (len) {
159                 cur = read(urandom_fd, dest, len);
160                 if (cur < 0)
161                         continue;
162                 len -= cur;
163         }
164         return 0;
165 }
166 #endif
167
168 #define DEBUG_LEVEL 0
169 static void pssl_debug(void *ctx, int level, const char *str)
170 {
171     if (level <= DEBUG_LEVEL)
172                 Log_info("PolarSSL [level %d]: %s", level, str);
173 }
174
175 void SSLi_init(void)
176 {
177         char verstring[12];
178         
179         initCert();
180 #ifdef USE_POLARSSL_TESTCERT
181         if (builtInTestCertificate) {
182                 Log_warn("*** Using built-in test certificate and RSA key ***");
183                 Log_warn("*** This is not secure! Please use a CA-signed certificate or create a key and self-signed certificate ***");
184                 initTestKey();
185         }
186         else
187                 initKey();
188 #else
189         initKey();
190 #endif
191
192         /* Initialize random number generator */
193 #ifdef USE_POLARSSL_HAVEGE
194     havege_init(&hs);
195 #else
196     urandom_fd = open("/dev/urandom", O_RDONLY);
197     if (urandom_fd < 0)
198             Log_fatal("Cannot open /dev/urandom");
199 #endif
200     
201     version_get_string(verstring);
202     Log_info("PolarSSL library version %s initialized", verstring);
203 }
204
205 void SSLi_deinit(void)
206 {
207         x509_free(&certificate);
208         rsa_free(&key);
209 }
210
211 /* Create SHA1 of last certificate in the peer's chain. */
212 bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash)
213 {
214         x509_cert const *cert;
215 #ifdef POLARSSL_API_V1_2
216         cert = ssl_get_peer_cert(ssl);
217 #else
218         cert = ssl->peer_cert;
219 #endif
220         if (!cert) {
221                 return false;
222         }       
223         sha1(cert->raw.p, cert->raw.len, hash);
224         return true;
225 }
226         
227 SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
228 {
229         ssl_context *ssl;
230         ssl_session *ssn;
231         int rc;
232         
233         ssl = malloc(sizeof(ssl_context));
234         ssn = malloc(sizeof(ssl_session));
235         if (!ssl || !ssn)
236                 Log_fatal("Out of memory");
237         memset(ssl, 0, sizeof(ssl_context));
238         memset(ssn, 0, sizeof(ssl_session));
239         
240         rc = ssl_init(ssl);
241         if (rc != 0 )
242                 Log_fatal("Failed to initialize: %d", rc);
243         
244         ssl_set_endpoint(ssl, SSL_IS_SERVER);   
245         ssl_set_authmode(ssl, SSL_VERIFY_OPTIONAL);
246         
247 #ifdef USE_POLARSSL_HAVEGE
248         ssl_set_rng(ssl, HAVEGE_RAND, &hs);
249 #else
250         ssl_set_rng(ssl, urandom_bytes, NULL);
251 #endif
252         
253         ssl_set_dbg(ssl, pssl_debug, NULL);
254         ssl_set_bio(ssl, net_recv, fd, net_send, fd);
255
256         ssl_set_ciphersuites(ssl, ciphers);
257
258 #ifdef POLARSSL_API_V1_2
259     ssl_set_session(ssl, ssn);
260 #else
261     ssl_set_session(ssl, 0, 0, ssn);
262 #endif
263     
264     ssl_set_ca_chain(ssl, &certificate, NULL, NULL);
265         ssl_set_own_cert(ssl, &certificate, &key);
266         ssl_set_dh_param(ssl, my_dhm_P, my_dhm_G);
267
268         return ssl;
269 }
270
271 int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready)
272 {
273         int rc;
274         
275         rc = ssl_handshake(ssl);
276         if (rc != 0) {
277                 if (rc == POLARSSL_ERR_NET_WANT_READ || rc == POLARSSL_ERR_NET_WANT_WRITE) {
278                         return 0;
279                 } else if (rc == POLARSSL_ERR_X509_CERT_VERIFY_FAILED) { /* Allow this (selfsigned etc) */
280                         return 0;                       
281                 } else {
282                         Log_warn("SSL handshake failed: %d", rc);
283                         return -1;
284                 }
285         }
286         *SSLready = true;
287         return 0;
288 }
289
290 int SSLi_read(SSL_handle_t *ssl, uint8_t *buf, int len)
291 {
292         int rc;
293
294         rc = ssl_read(ssl, buf, len);
295         if (rc == POLARSSL_ERR_NET_WANT_READ)
296                 return SSLI_ERROR_WANT_READ;
297         return rc;
298 }
299
300 int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len)
301 {
302         int rc;
303         
304         rc = ssl_write(ssl, buf, len);
305         if (rc == POLARSSL_ERR_NET_WANT_WRITE)
306                 return SSLI_ERROR_WANT_WRITE;
307         return rc;
308 }
309
310 int SSLi_get_error(SSL_handle_t *ssl, int code)
311 {
312         return code;
313 }
314
315 bool_t SSLi_data_pending(SSL_handle_t *ssl)
316 {
317         return ssl_get_bytes_avail(ssl) > 0;
318 }
319
320 void SSLi_shutdown(SSL_handle_t *ssl)
321 {
322         ssl_close_notify(ssl);
323 }
324
325 void SSLi_free(SSL_handle_t *ssl)
326 {
327         Log_debug("SSLi_free");
328 #if (POLARSSL_VERSION_MINOR <= 2 && POLARSSL_VERSION_PATCH < 6)
329         free(ssl->session); /* Workaround for memory leak in PolarSSL < 1.2.6 */
330         ssl->session = NULL;
331 #endif
332         ssl_free(ssl);
333         free(ssl);
334 }
335
336 #else
337 /*
338  * OpenSSL interface
339  */
340
341 #include <openssl/x509v3.h>
342 #include <openssl/ssl.h>
343 #include <openssl/err.h>
344 #include <openssl/safestack.h>
345 static X509 *x509;
346 static RSA *rsa;
347 static SSL_CTX *context;
348 static EVP_PKEY *pkey;
349  
350 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx);
351
352 static int SSL_add_ext(X509 * crt, int nid, char *value) {
353         X509_EXTENSION *ex;
354         X509V3_CTX ctx;
355         X509V3_set_ctx_nodb(&ctx);
356         X509V3_set_ctx(&ctx, crt, crt, NULL, NULL, 0);
357         ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
358         if (!ex)
359                 return 0;
360
361         X509_add_ext(crt, ex, -1);
362         X509_EXTENSION_free(ex);
363         return 1;
364 }
365
366 static X509 *SSL_readcert(char *certfile)
367 {
368         FILE *fp;
369         X509 *x509;
370                         
371         /* open the private key file */
372         fp = fopen(certfile, "r");
373         if (fp == NULL) {
374                 Log_warn("Unable to open the X509 file %s for reading.", certfile);
375                 return NULL;
376         }
377         
378         /* allocate memory for the cert structure */    
379         x509 = X509_new();
380         
381         if (PEM_read_X509(fp, &x509, NULL, NULL) == 0) {
382                 /* error reading the x509 information - check the error stack */
383                 Log_warn("Error trying to read X509 info.");
384                 fclose(fp);
385                 X509_free(x509);
386                 return NULL;
387         }
388         fclose(fp);
389         return x509;
390 }
391
392 static RSA *SSL_readprivatekey(char *keyfile)
393 {
394         FILE *fp;
395         RSA *rsa;
396
397 /* open the private key file for reading */
398         fp = fopen(keyfile, "r");
399         if (fp == NULL) {
400                 Log_warn("Unable to open the private key file %s for reading.", keyfile);
401                 return NULL;
402         }
403         
404 /* allocate memory for the RSA structure */
405         rsa = RSA_new();
406         
407         /* assign a callback function for the password */
408         
409         /* read a private key from file */      
410         if (PEM_read_RSAPrivateKey(fp, &rsa, NULL, NULL) <= 0) {
411                 /* error reading the key - check the error stack */
412                 Log_warn("Error trying to read private key.");
413                 RSA_free(rsa);
414                 fclose(fp);
415                 return NULL;
416         }
417         fclose(fp);
418         return rsa;
419 }
420
421 static void SSL_writecert(char *certfile, X509 *x509)
422 {
423         FILE *fp;
424                 
425         /* open the private key file */
426         fp = fopen(certfile, "w");
427         if (fp == NULL) {
428                 Log_warn("Unable to open the X509 file %s for writing", certfile);
429                 return;
430         }               
431         if (PEM_write_X509(fp, x509) == 0) {
432                 Log_warn("Error trying to write X509 info.");
433         }
434         fclose(fp);
435 }
436
437 static void SSL_writekey(char *keyfile, RSA *rsa)
438 {
439         FILE *fp;
440         
441         /* open the private key file for reading */
442         fp = fopen(keyfile, "w");
443         if (fp == NULL) {
444                 Log_warn("Unable to open the private key file %s for writing.", keyfile);
445                 return;
446         }
447         
448         if (PEM_write_RSAPrivateKey(fp, rsa, NULL, NULL, 0, NULL, NULL) == 0) {
449                 Log_warn("Error trying to write private key");
450         }
451         fclose(fp);
452 }
453
454 static void SSL_initializeCert() {
455         char *crt, *key, *pass;
456         
457         crt = (char *)getStrConf(CERTIFICATE);
458         key = (char *)getStrConf(KEY);
459         pass = (char *)getStrConf(PASSPHRASE);
460
461         x509 = SSL_readcert(crt);
462         rsa = SSL_readprivatekey(key);
463         if (rsa != NULL) {
464                 pkey = EVP_PKEY_new();
465                 EVP_PKEY_assign_RSA(pkey, rsa);
466         }               
467         
468 #if 0
469         /* Later ... */
470         if (key && !x509) {             
471                 qscCert = QSslCertificate(key);
472                 if (! qscCert.isNull()) {
473                         logthis("Using certificate from key.");
474                 }
475         }
476
477         if (! qscCert.isNull()) {
478                 QSsl::KeyAlgorithm alg = qscCert.publicKey().algorithm();
479                 /* Fetch algorith from cert */
480                 if (! key.isEmpty()) {
481                         /* get key */
482                         qskKey = QSslKey(key, alg, QSsl::Pem, QSsl::PrivateKey, pass);
483                         if (qskKey.isNull()) {
484                                 logthis("Failed to parse key.");
485                         }
486                 }
487
488                 if (! crt.isEmpty() && qskKey.isNull()) {
489                         /* get key from certificate */
490                         qskKey = QSslKey(crt, alg, QSsl::Pem, QSsl::PrivateKey, pass);
491                         if (! qskKey.isNull()) {
492                                 logthis("Using key from certificate.");
493                         }
494                 }
495
496         }
497 #endif
498         
499         if (!rsa || !x509) {
500                 Log_info("Generating new server certificate.");
501
502                 
503                 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
504                                 
505                 x509 = X509_new();
506                 pkey = EVP_PKEY_new();
507                 rsa = RSA_generate_key(1024,RSA_F4,NULL,NULL);
508                 EVP_PKEY_assign_RSA(pkey, rsa);
509                 
510                 X509_set_version(x509, 2);
511                 ASN1_INTEGER_set(X509_get_serialNumber(x509),1);
512                 X509_gmtime_adj(X509_get_notBefore(x509),0);
513                 X509_gmtime_adj(X509_get_notAfter(x509),60*60*24*365);
514                 X509_set_pubkey(x509, pkey);
515                 
516                 X509_NAME *name=X509_get_subject_name(x509);
517                 
518                 X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const uint8_t *)"Murmur Autogenerated Certificate v2", -1, -1, 0);
519                 X509_set_issuer_name(x509, name);
520                 SSL_add_ext(x509, NID_basic_constraints, "critical,CA:FALSE");
521                 SSL_add_ext(x509, NID_ext_key_usage, "serverAuth,clientAuth");
522                 SSL_add_ext(x509, NID_subject_key_identifier, "hash");
523                 SSL_add_ext(x509, NID_netscape_comment, "Generated from umurmur");
524                 
525                 X509_sign(x509, pkey, EVP_md5());
526                 
527                 SSL_writecert(crt, x509);
528                 SSL_writekey(key, rsa);
529         }
530
531 }
532
533 void SSLi_init(void)
534 {
535         const SSL_METHOD *method;
536         SSL *ssl;
537         int i, offset = 0, cipherstringlen = 0;
538         STACK_OF(SSL_CIPHER) *cipherlist = NULL, *cipherlist_new = NULL;
539         SSL_CIPHER *cipher;
540         char *cipherstring, tempstring[128];
541                 
542         SSL_library_init();
543     OpenSSL_add_all_algorithms();               /* load & register all cryptos, etc. */
544     SSL_load_error_strings();                   /* load all error messages */
545     ERR_load_crypto_strings();                  /* load all error messages */
546     method = SSLv23_server_method();            /* create new server-method instance */
547     context = SSL_CTX_new(method);                      /* create new context from method */
548     if (context == NULL)
549     {
550         ERR_print_errors_fp(stderr);
551         abort();
552     }
553         SSL_initializeCert();
554         if (SSL_CTX_use_certificate(context, x509) <= 0)
555                 Log_fatal("Failed to initialize cert");
556         if (SSL_CTX_use_PrivateKey(context, pkey) <= 0) {
557                 ERR_print_errors_fp(stderr);
558                 Log_fatal("Failed to initialize private key");
559         }
560
561         /* Set cipher list */
562         ssl = SSL_new(context); 
563         cipherlist = (STACK_OF(SSL_CIPHER) *) SSL_get_ciphers(ssl);
564         cipherlist_new = (STACK_OF(SSL_CIPHER) *) sk_SSL_CIPHER_new_null();
565         
566         for ( i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist, i)) != NULL; i++) {
567                 if (SSL_CIPHER_get_bits(cipher, NULL) >= 128) {
568                         sk_SSL_CIPHER_push(cipherlist_new, cipher);
569                 }
570         }
571         Log_debug("List of ciphers:");
572         if (cipherlist_new) {
573                 for (i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist_new, i)) != NULL; i++) {
574                         Log_debug("%s", SSL_CIPHER_get_name(cipher));
575                         cipherstringlen += strlen(SSL_CIPHER_get_name(cipher)) + 1;
576                 }
577                 cipherstring = malloc(cipherstringlen + 1);
578                 if (cipherstring == NULL)
579                         Log_fatal("Out of memory");
580                 for (i = 0; (cipher = sk_SSL_CIPHER_value(cipherlist_new, i)) != NULL; i++) {
581                         offset += sprintf(cipherstring + offset, "%s:", SSL_CIPHER_get_name(cipher));
582                 }
583         }
584         
585         if (cipherlist_new)
586                 sk_SSL_CIPHER_free(cipherlist_new);
587         
588         if (strlen(cipherstring) == 0)
589                 Log_fatal("No suitable ciphers found!");
590         
591         if (SSL_CTX_set_cipher_list(context, cipherstring) == 0)
592                 Log_fatal("Failed to set cipher list!");
593
594         free(cipherstring);
595         
596         SSL_CTX_set_verify(context, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
597                            verify_callback);            
598         
599         SSL_free(ssl);
600         Log_info("OpenSSL library initialized");
601
602 }
603
604 void SSLi_deinit(void)
605 {
606         SSL_CTX_free(context);
607         EVP_cleanup();
608 }
609
610 int SSLi_nonblockaccept(SSL_handle_t *ssl, bool_t *SSLready)
611 {
612         int rc;
613         rc = SSL_accept(ssl);
614         if (rc < 0) {
615                 if (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ ||
616                         SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE) {
617                         Log_debug("SSL not ready");
618                         return 0;
619                 } else {
620                         Log_warn("SSL error: %s", ERR_error_string(SSL_get_error(ssl, rc), NULL));
621                         return -1;
622                 }
623         }
624         *SSLready = true;
625         return 0;
626 }
627
628 SSL_handle_t *SSLi_newconnection(int *fd, bool_t *SSLready)
629 {
630         SSL *ssl;
631         
632         *SSLready = false;
633         ssl = SSL_new(context);
634         SSL_set_fd(ssl, *fd);
635         if (SSLi_nonblockaccept(ssl, SSLready) < 0) {
636                 SSL_free(ssl);
637                 return NULL;
638         }
639         return ssl;
640 }
641
642 /* Create SHA1 of last certificate in the peer's chain. */
643 bool_t SSLi_getSHA1Hash(SSL_handle_t *ssl, uint8_t *hash)
644 {
645         X509 *x509;
646         uint8_t *buf, *p;
647         int len;
648         
649         x509 = SSL_get_peer_certificate(ssl);
650         if (!x509) {
651                 return false;
652         }       
653         
654         len = i2d_X509(x509, NULL);
655         buf = malloc(len);
656         if (buf == NULL) {
657                 Log_fatal("malloc");
658         }
659
660         p = buf;
661         i2d_X509(x509, &p);     
662         
663         SHA1(buf, len, hash);
664         free(buf);
665         return true;
666 }
667  
668 void SSLi_closeconnection(SSL_handle_t *ssl)
669 {
670         SSL_free(ssl);
671 }
672
673 void SSLi_shutdown(SSL_handle_t *ssl)
674 {
675         SSL_shutdown(ssl);
676 }
677
678 int SSLi_read(SSL_handle_t *ssl, uint8_t *buf, int len)
679 {
680         return SSL_read(ssl, buf, len);
681 }
682
683 int SSLi_write(SSL_handle_t *ssl, uint8_t *buf, int len)
684 {
685         return SSL_write(ssl, buf, len);
686 }
687
688 int SSLi_get_error(SSL_handle_t *ssl, int code)
689 {
690         return SSL_get_error(ssl, code);
691 }
692
693 bool_t SSLi_data_pending(SSL_handle_t *ssl)
694 {
695         return SSL_pending(ssl);
696 }
697
698 void SSLi_free(SSL_handle_t *ssl)
699 {
700         SSL_free(ssl);
701 }
702
703 static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
704 {
705         char    buf[256];
706         X509   *err_cert;
707         int     err, depth;
708         SSL    *ssl;
709     
710     err_cert = X509_STORE_CTX_get_current_cert(ctx);
711     err = X509_STORE_CTX_get_error(ctx);
712     depth = X509_STORE_CTX_get_error_depth(ctx);
713     
714     ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
715     X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
716         
717     if (depth > 5) {
718         preverify_ok = 0;
719         err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
720         X509_STORE_CTX_set_error(ctx, err);
721     }
722     if (!preverify_ok) {
723             Log_warn("SSL: verify error:num=%d:%s:depth=%d:%s\n", err,
724                      X509_verify_cert_error_string(err), depth, buf);
725     }
726     /*
727      * At this point, err contains the last verification error. We can use
728      * it for something special
729      */
730     if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
731             X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
732             Log_warn("issuer= %s", buf);
733     }
734     return 1;
735 }
736  
737 #endif